s/ui_out_list/ui_out_tupple/
[deliverable/binutils-gdb.git] / readline / histfile.c
CommitLineData
d60d9f65
SS
1/* histfile.c - functions to manipulate the history file. */
2
3/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
5 This file contains the GNU History Library (the Library), a set of
6 routines for managing the text of previously typed lines.
7
8 The Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
1b17e766 10 the Free Software Foundation; either version 2, or (at your option)
d60d9f65
SS
11 any later version.
12
13 The Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 The GNU General Public License is often shipped with GNU software, and
19 is generally kept in a file called COPYING or LICENSE. If you do not
20 have a copy of the license, write to the Free Software Foundation,
1b17e766 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
d60d9f65
SS
22
23/* The goal is to make the implementation transparent, so that you
24 don't have to know what data types are used, just what functions
25 you can call. I think I have done that. */
26#define READLINE_LIBRARY
27
28#if defined (HAVE_CONFIG_H)
29# include <config.h>
30#endif
31
32#include <stdio.h>
33
34#include <sys/types.h>
35#ifndef _MINIX
36# include <sys/file.h>
37#endif
1b17e766 38#include "posixstat.h"
d60d9f65
SS
39#include <fcntl.h>
40
41#if defined (HAVE_STDLIB_H)
42# include <stdlib.h>
43#else
44# include "ansi_stdlib.h"
45#endif /* HAVE_STDLIB_H */
46
47#if defined (HAVE_UNISTD_H)
48# include <unistd.h>
49#endif
50
51#if defined (HAVE_STRING_H)
52# include <string.h>
53#else
54# include <strings.h>
55#endif /* !HAVE_STRING_H */
56
1b17e766
EZ
57
58/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
59 on win 95/98/nt), we want to open files with O_BINARY mode so that there
60 is no \n -> \r\n conversion performed. On other systems, we don't want to
61 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
62#if defined (__EMX__) || defined (__CYGWIN__)
d60d9f65
SS
63# ifndef O_BINARY
64# define O_BINARY 0
65# endif
1b17e766 66#else /* !__EMX__ && !__CYGWIN__ */
d60d9f65
SS
67# undef O_BINARY
68# define O_BINARY 0
1b17e766 69#endif /* !__EMX__ && !__CYGWIN__ */
d60d9f65
SS
70
71#include <errno.h>
72#if !defined (errno)
73extern int errno;
74#endif /* !errno */
75
76#include "history.h"
77#include "histlib.h"
78
1b17e766
EZ
79#include "rlshell.h"
80#include "xmalloc.h"
d60d9f65
SS
81
82/* Return the string that should be used in the place of this
83 filename. This only matters when you don't specify the
84 filename to read_history (), or write_history (). */
85static char *
86history_filename (filename)
87 char *filename;
88{
89 char *return_val, *home;
90 int home_len;
91
92 return_val = filename ? savestring (filename) : (char *)NULL;
93
94 if (return_val)
95 return (return_val);
96
97 home = get_env_value ("HOME");
98
99 if (home == 0)
100 {
101 home = ".";
102 home_len = 1;
103 }
104 else
105 home_len = strlen (home);
106
107 return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
108 strcpy (return_val, home);
109 return_val[home_len] = '/';
1b17e766
EZ
110#if defined (__MSDOS__)
111 strcpy (return_val + home_len + 1, "_history");
112#else
d60d9f65 113 strcpy (return_val + home_len + 1, ".history");
1b17e766 114#endif
d60d9f65
SS
115
116 return (return_val);
117}
118
119/* Add the contents of FILENAME to the history list, a line at a time.
120 If FILENAME is NULL, then read from ~/.history. Returns 0 if
121 successful, or errno if not. */
122int
123read_history (filename)
124 char *filename;
125{
126 return (read_history_range (filename, 0, -1));
127}
128
129/* Read a range of lines from FILENAME, adding them to the history list.
130 Start reading at the FROM'th line and end at the TO'th. If FROM
131 is zero, start at the beginning. If TO is less than FROM, read
132 until the end of the file. If FILENAME is NULL, then read from
133 ~/.history. Returns 0 if successful, or errno if not. */
134int
135read_history_range (filename, from, to)
136 char *filename;
137 int from, to;
138{
139 register int line_start, line_end;
140 char *input, *buffer;
1b17e766 141 int file, current_line, chars_read;
d60d9f65
SS
142 struct stat finfo;
143 size_t file_size;
144
145 buffer = (char *)NULL;
146 input = history_filename (filename);
147 file = open (input, O_RDONLY|O_BINARY, 0666);
148
149 if ((file < 0) || (fstat (file, &finfo) == -1))
150 goto error_and_exit;
151
152 file_size = (size_t)finfo.st_size;
153
154 /* check for overflow on very large files */
155 if (file_size != finfo.st_size || file_size + 1 < file_size)
156 {
157#if defined (EFBIG)
158 errno = EFBIG;
159#endif
160 goto error_and_exit;
161 }
162
163 buffer = xmalloc (file_size + 1);
1b17e766
EZ
164
165 chars_read = read (file, buffer, file_size);
166 if (chars_read < 0)
d60d9f65
SS
167 {
168 error_and_exit:
169 if (file >= 0)
170 close (file);
171
172 FREE (input);
173 FREE (buffer);
174
175 return (errno);
176 }
177
178 close (file);
179
180 /* Set TO to larger than end of file if negative. */
181 if (to < 0)
1b17e766 182 to = chars_read;
d60d9f65
SS
183
184 /* Start at beginning of file, work to end. */
185 line_start = line_end = current_line = 0;
186
187 /* Skip lines until we are at FROM. */
1b17e766 188 while (line_start < chars_read && current_line < from)
d60d9f65 189 {
1b17e766 190 for (line_end = line_start; line_end < chars_read; line_end++)
d60d9f65
SS
191 if (buffer[line_end] == '\n')
192 {
193 current_line++;
194 line_start = line_end + 1;
195 if (current_line == from)
196 break;
197 }
198 }
199
200 /* If there are lines left to gobble, then gobble them now. */
1b17e766 201 for (line_end = line_start; line_end < chars_read; line_end++)
d60d9f65
SS
202 if (buffer[line_end] == '\n')
203 {
204 buffer[line_end] = '\0';
205
206 if (buffer[line_start])
207 add_history (buffer + line_start);
208
209 current_line++;
210
211 if (current_line >= to)
212 break;
213
214 line_start = line_end + 1;
215 }
216
217 FREE (input);
218 FREE (buffer);
219
220 return (0);
221}
222
223/* Truncate the history file FNAME, leaving only LINES trailing lines.
224 If FNAME is NULL, then use ~/.history. */
225int
226history_truncate_file (fname, lines)
227 char *fname;
c862e87b 228 int lines;
d60d9f65
SS
229{
230 register int i;
231 int file, chars_read;
232 char *buffer, *filename;
233 struct stat finfo;
234 size_t file_size;
235
236 buffer = (char *)NULL;
237 filename = history_filename (fname);
238 file = open (filename, O_RDONLY|O_BINARY, 0666);
239
240 if (file == -1 || fstat (file, &finfo) == -1)
241 goto truncate_exit;
242
1b17e766
EZ
243 /* Don't try to truncate non-regular files. */
244 if (S_ISREG(finfo.st_mode) == 0)
245 goto truncate_exit;
246
d60d9f65
SS
247 file_size = (size_t)finfo.st_size;
248
249 /* check for overflow on very large files */
250 if (file_size != finfo.st_size || file_size + 1 < file_size)
251 {
252 close (file);
253#if defined (EFBIG)
254 errno = EFBIG;
255#endif
256 goto truncate_exit;
257 }
258
259 buffer = xmalloc (file_size + 1);
260 chars_read = read (file, buffer, file_size);
261 close (file);
262
263 if (chars_read <= 0)
264 goto truncate_exit;
265
266 /* Count backwards from the end of buffer until we have passed
267 LINES lines. */
268 for (i = chars_read - 1; lines && i; i--)
269 {
270 if (buffer[i] == '\n')
271 lines--;
272 }
273
274 /* If this is the first line, then the file contains exactly the
275 number of lines we want to truncate to, so we don't need to do
276 anything. It's the first line if we don't find a newline between
277 the current value of i and 0. Otherwise, write from the start of
278 this line until the end of the buffer. */
279 for ( ; i; i--)
280 if (buffer[i] == '\n')
281 {
282 i++;
283 break;
284 }
285
286 /* Write only if there are more lines in the file than we want to
287 truncate to. */
288 if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
289 {
1b17e766 290 write (file, buffer + i, chars_read - i);
c862e87b
JM
291
292#if defined (__BEOS__)
293 /* BeOS ignores O_TRUNC. */
1b17e766 294 ftruncate (file, chars_read - i);
c862e87b
JM
295#endif
296
d60d9f65
SS
297 close (file);
298 }
299
300 truncate_exit:
301
302 FREE (buffer);
303
304 free (filename);
305 return 0;
306}
307
308/* Workhorse function for writing history. Writes NELEMENT entries
309 from the history list to FILENAME. OVERWRITE is non-zero if you
310 wish to replace FILENAME with the entries. */
311static int
312history_do_write (filename, nelements, overwrite)
313 char *filename;
314 int nelements, overwrite;
315{
316 register int i;
317 char *output;
318 int file, mode;
319
320 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
321 output = history_filename (filename);
322
323 if ((file = open (output, mode, 0600)) == -1)
324 {
325 FREE (output);
326 return (errno);
327 }
328
329 if (nelements > history_length)
330 nelements = history_length;
331
332 /* Build a buffer of all the lines to write, and write them in one syscall.
333 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
334 {
335 HIST_ENTRY **the_history; /* local */
336 register int j;
337 int buffer_size;
338 char *buffer;
339
340 the_history = history_list ();
341 /* Calculate the total number of bytes to write. */
342 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
343 buffer_size += 1 + strlen (the_history[i]->line);
344
345 /* Allocate the buffer, and fill it. */
346 buffer = xmalloc (buffer_size);
347
348 for (j = 0, i = history_length - nelements; i < history_length; i++)
349 {
350 strcpy (buffer + j, the_history[i]->line);
351 j += strlen (the_history[i]->line);
352 buffer[j++] = '\n';
353 }
354
355 write (file, buffer, buffer_size);
356 free (buffer);
357 }
358
359 close (file);
360
361 FREE (output);
362
363 return (0);
364}
365
366/* Append NELEMENT entries to FILENAME. The entries appended are from
367 the end of the list minus NELEMENTs up to the end of the list. */
368int
369append_history (nelements, filename)
370 int nelements;
371 char *filename;
372{
373 return (history_do_write (filename, nelements, HISTORY_APPEND));
374}
375
376/* Overwrite FILENAME with the current history. If FILENAME is NULL,
377 then write the history list to ~/.history. Values returned
378 are as in read_history ().*/
379int
380write_history (filename)
381 char *filename;
382{
383 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
384}
This page took 0.085869 seconds and 4 git commands to generate.