import gdb-1999-08-02 snapshot
[platform/upstream/binutils.git] / readline / histfile.c
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
10    the Free Software Foundation; either version 1, or (at your option)
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,
21    675 Mass Ave, Cambridge, MA 02139, USA. */
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
38 #include <sys/stat.h>
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
57 #if defined (__EMX__)
58 #  ifndef O_BINARY
59 #    define O_BINARY 0
60 #  endif
61 #else /* !__EMX__ */
62    /* If we're not compiling for __EMX__, we don't want this at all.  Ever. */
63 #  undef O_BINARY
64 #  define O_BINARY 0
65 #endif /* !__EMX__ */
66
67 #include <errno.h>
68 #if !defined (errno)
69 extern int errno;
70 #endif /* !errno */
71
72 #include "history.h"
73 #include "histlib.h"
74
75 /* Functions imported from shell.c */
76 extern char *get_env_value ();
77
78 extern char *xmalloc (), *xrealloc ();
79
80 /* Return the string that should be used in the place of this
81    filename.  This only matters when you don't specify the
82    filename to read_history (), or write_history (). */
83 static char *
84 history_filename (filename)
85      char *filename;
86 {
87   char *return_val, *home;
88   int home_len;
89
90   return_val = filename ? savestring (filename) : (char *)NULL;
91
92   if (return_val)
93     return (return_val);
94   
95   home = get_env_value ("HOME");
96
97   if (home == 0)
98     {
99       home = ".";
100       home_len = 1;
101     }
102   else
103     home_len = strlen (home);
104
105   return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
106   strcpy (return_val, home);
107   return_val[home_len] = '/';
108   strcpy (return_val + home_len + 1, ".history");
109
110   return (return_val);
111 }
112
113 /* Add the contents of FILENAME to the history list, a line at a time.
114    If FILENAME is NULL, then read from ~/.history.  Returns 0 if
115    successful, or errno if not. */
116 int
117 read_history (filename)
118      char *filename;
119 {
120   return (read_history_range (filename, 0, -1));
121 }
122
123 /* Read a range of lines from FILENAME, adding them to the history list.
124    Start reading at the FROM'th line and end at the TO'th.  If FROM
125    is zero, start at the beginning.  If TO is less than FROM, read
126    until the end of the file.  If FILENAME is NULL, then read from
127    ~/.history.  Returns 0 if successful, or errno if not. */
128 int
129 read_history_range (filename, from, to)
130      char *filename;
131      int from, to;
132 {
133   register int line_start, line_end;
134   char *input, *buffer;
135   int file, current_line;
136   struct stat finfo;
137   size_t file_size;
138
139   buffer = (char *)NULL;
140   input = history_filename (filename);
141   file = open (input, O_RDONLY|O_BINARY, 0666);
142
143   if ((file < 0) || (fstat (file, &finfo) == -1))
144     goto error_and_exit;
145
146   file_size = (size_t)finfo.st_size;
147
148   /* check for overflow on very large files */
149   if (file_size != finfo.st_size || file_size + 1 < file_size)
150     {
151 #if defined (EFBIG)
152       errno = EFBIG;
153 #endif
154       goto error_and_exit;
155     }
156
157   buffer = xmalloc (file_size + 1);
158 #if 0
159   if (read (file, buffer, file_size) != file_size)
160 #else
161   if (read (file, buffer, file_size) < 0)
162 #endif
163     {
164   error_and_exit:
165       if (file >= 0)
166         close (file);
167
168       FREE (input);
169       FREE (buffer);
170
171       return (errno);
172     }
173
174   close (file);
175
176   /* Set TO to larger than end of file if negative. */
177   if (to < 0)
178     to = file_size;
179
180   /* Start at beginning of file, work to end. */
181   line_start = line_end = current_line = 0;
182
183   /* Skip lines until we are at FROM. */
184   while (line_start < file_size && current_line < from)
185     {
186       for (line_end = line_start; line_end < file_size; line_end++)
187         if (buffer[line_end] == '\n')
188           {
189             current_line++;
190             line_start = line_end + 1;
191             if (current_line == from)
192               break;
193           }
194     }
195
196   /* If there are lines left to gobble, then gobble them now. */
197   for (line_end = line_start; line_end < file_size; line_end++)
198     if (buffer[line_end] == '\n')
199       {
200         buffer[line_end] = '\0';
201
202         if (buffer[line_start])
203           add_history (buffer + line_start);
204
205         current_line++;
206
207         if (current_line >= to)
208           break;
209
210         line_start = line_end + 1;
211       }
212
213   FREE (input);
214   FREE (buffer);
215
216   return (0);
217 }
218
219 /* Truncate the history file FNAME, leaving only LINES trailing lines.
220    If FNAME is NULL, then use ~/.history. */
221 int
222 history_truncate_file (fname, lines)
223      char *fname;
224      int lines;
225 {
226   register int i;
227   int file, chars_read;
228   char *buffer, *filename;
229   struct stat finfo;
230   size_t file_size;
231
232   buffer = (char *)NULL;
233   filename = history_filename (fname);
234   file = open (filename, O_RDONLY|O_BINARY, 0666);
235
236   if (file == -1 || fstat (file, &finfo) == -1)
237     goto truncate_exit;
238
239   file_size = (size_t)finfo.st_size;
240
241   /* check for overflow on very large files */
242   if (file_size != finfo.st_size || file_size + 1 < file_size)
243     {
244       close (file);
245 #if defined (EFBIG)
246       errno = EFBIG;
247 #endif
248       goto truncate_exit;
249     }
250
251   buffer = xmalloc (file_size + 1);
252   chars_read = read (file, buffer, file_size);
253   close (file);
254
255   if (chars_read <= 0)
256     goto truncate_exit;
257
258   /* Count backwards from the end of buffer until we have passed
259      LINES lines. */
260   for (i = chars_read - 1; lines && i; i--)
261     {
262       if (buffer[i] == '\n')
263         lines--;
264     }
265
266   /* If this is the first line, then the file contains exactly the
267      number of lines we want to truncate to, so we don't need to do
268      anything.  It's the first line if we don't find a newline between
269      the current value of i and 0.  Otherwise, write from the start of
270      this line until the end of the buffer. */
271   for ( ; i; i--)
272     if (buffer[i] == '\n')
273       {
274         i++;
275         break;
276       }
277
278   /* Write only if there are more lines in the file than we want to
279      truncate to. */
280   if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
281     {
282       write (file, buffer + i, file_size - i);
283
284 #if defined (__BEOS__)
285       /* BeOS ignores O_TRUNC. */
286       ftruncate (file, file_size - i);
287 #endif
288
289       close (file);
290     }
291
292  truncate_exit:
293
294   FREE (buffer);
295
296   free (filename);
297   return 0;
298 }
299
300 /* Workhorse function for writing history.  Writes NELEMENT entries
301    from the history list to FILENAME.  OVERWRITE is non-zero if you
302    wish to replace FILENAME with the entries. */
303 static int
304 history_do_write (filename, nelements, overwrite)
305      char *filename;
306      int nelements, overwrite;
307 {
308   register int i;
309   char *output;
310   int file, mode;
311
312   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
313   output = history_filename (filename);
314
315   if ((file = open (output, mode, 0600)) == -1)
316     {
317       FREE (output);
318       return (errno);
319     }
320
321   if (nelements > history_length)
322     nelements = history_length;
323
324   /* Build a buffer of all the lines to write, and write them in one syscall.
325      Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
326   {
327     HIST_ENTRY **the_history;   /* local */
328     register int j;
329     int buffer_size;
330     char *buffer;
331
332     the_history = history_list ();
333     /* Calculate the total number of bytes to write. */
334     for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
335       buffer_size += 1 + strlen (the_history[i]->line);
336
337     /* Allocate the buffer, and fill it. */
338     buffer = xmalloc (buffer_size);
339
340     for (j = 0, i = history_length - nelements; i < history_length; i++)
341       {
342         strcpy (buffer + j, the_history[i]->line);
343         j += strlen (the_history[i]->line);
344         buffer[j++] = '\n';
345       }
346
347     write (file, buffer, buffer_size);
348     free (buffer);
349   }
350
351   close (file);
352
353   FREE (output);
354
355   return (0);
356 }
357
358 /* Append NELEMENT entries to FILENAME.  The entries appended are from
359    the end of the list minus NELEMENTs up to the end of the list. */
360 int
361 append_history (nelements, filename)
362      int nelements;
363      char *filename;
364 {
365   return (history_do_write (filename, nelements, HISTORY_APPEND));
366 }
367
368 /* Overwrite FILENAME with the current history.  If FILENAME is NULL,
369    then write the history list to ~/.history.  Values returned
370    are as in read_history ().*/
371 int
372 write_history (filename)
373      char *filename;
374 {
375   return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
376 }