[__GO32__]: Don't undef HANDLE_SIGNALS for DJGPP v2.x.
[deliverable/binutils-gdb.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
144 #ifdef __MSDOS__
145 /* MSDOS doesn't allow leading dots in file names. Try again
146 with the dot replaced by an underscore. */
147 if (file < 0 && !filename)
148 {
149 input[strlen (input) - 8] = '_';
150 file = open (input, O_RDONLY|O_BINARY, 0666);
151 }
152 #endif
153 if ((file < 0) || (fstat (file, &finfo) == -1))
154 goto error_and_exit;
155
156 file_size = (size_t)finfo.st_size;
157
158 /* check for overflow on very large files */
159 if (file_size != finfo.st_size || file_size + 1 < file_size)
160 {
161 #if defined (EFBIG)
162 errno = EFBIG;
163 #endif
164 goto error_and_exit;
165 }
166
167 buffer = xmalloc (file_size + 1);
168 #if 0
169 if (read (file, buffer, file_size) != file_size)
170 #else
171 if (read (file, buffer, file_size) < 0)
172 #endif
173 {
174 error_and_exit:
175 if (file >= 0)
176 close (file);
177
178 FREE (input);
179 FREE (buffer);
180
181 return (errno);
182 }
183
184 close (file);
185
186 /* Set TO to larger than end of file if negative. */
187 if (to < 0)
188 to = file_size;
189
190 /* Start at beginning of file, work to end. */
191 line_start = line_end = current_line = 0;
192
193 /* Skip lines until we are at FROM. */
194 while (line_start < file_size && current_line < from)
195 {
196 for (line_end = line_start; line_end < file_size; line_end++)
197 if (buffer[line_end] == '\n')
198 {
199 current_line++;
200 line_start = line_end + 1;
201 if (current_line == from)
202 break;
203 }
204 }
205
206 /* If there are lines left to gobble, then gobble them now. */
207 for (line_end = line_start; line_end < file_size; line_end++)
208 if (buffer[line_end] == '\n')
209 {
210 buffer[line_end] = '\0';
211
212 if (buffer[line_start])
213 add_history (buffer + line_start);
214
215 current_line++;
216
217 if (current_line >= to)
218 break;
219
220 line_start = line_end + 1;
221 }
222
223 FREE (input);
224 FREE (buffer);
225
226 return (0);
227 }
228
229 /* Truncate the history file FNAME, leaving only LINES trailing lines.
230 If FNAME is NULL, then use ~/.history. */
231 int
232 history_truncate_file (fname, lines)
233 char *fname;
234 int lines;
235 {
236 register int i;
237 int file, chars_read;
238 char *buffer, *filename;
239 struct stat finfo;
240 size_t file_size;
241
242 buffer = (char *)NULL;
243 filename = history_filename (fname);
244 file = open (filename, O_RDONLY|O_BINARY, 0666);
245
246 #ifdef __MSDOS__
247 /* MSDOS doesn't allow leading dots in file names. Try again
248 with the dot replaced by an underscore. */
249 if (file < 0 && !fname)
250 {
251 filename[strlen (filename) - 8] = '_';
252 file = open (filename, O_RDONLY|O_BINARY, 0666);
253 }
254 #endif
255
256 if (file == -1 || fstat (file, &finfo) == -1)
257 goto truncate_exit;
258
259 file_size = (size_t)finfo.st_size;
260
261 /* check for overflow on very large files */
262 if (file_size != finfo.st_size || file_size + 1 < file_size)
263 {
264 close (file);
265 #if defined (EFBIG)
266 errno = EFBIG;
267 #endif
268 goto truncate_exit;
269 }
270
271 buffer = xmalloc (file_size + 1);
272 chars_read = read (file, buffer, file_size);
273 close (file);
274
275 if (chars_read <= 0)
276 goto truncate_exit;
277
278 /* Count backwards from the end of buffer until we have passed
279 LINES lines. */
280 for (i = chars_read - 1; lines && i; i--)
281 {
282 if (buffer[i] == '\n')
283 lines--;
284 }
285
286 /* If this is the first line, then the file contains exactly the
287 number of lines we want to truncate to, so we don't need to do
288 anything. It's the first line if we don't find a newline between
289 the current value of i and 0. Otherwise, write from the start of
290 this line until the end of the buffer. */
291 for ( ; i; i--)
292 if (buffer[i] == '\n')
293 {
294 i++;
295 break;
296 }
297
298 /* Write only if there are more lines in the file than we want to
299 truncate to. */
300 if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
301 {
302 write (file, buffer + i, file_size - i);
303
304 #if defined (__BEOS__)
305 /* BeOS ignores O_TRUNC. */
306 ftruncate (file, file_size - i);
307 #endif
308
309 close (file);
310 }
311
312 truncate_exit:
313
314 FREE (buffer);
315
316 free (filename);
317 return 0;
318 }
319
320 /* Workhorse function for writing history. Writes NELEMENT entries
321 from the history list to FILENAME. OVERWRITE is non-zero if you
322 wish to replace FILENAME with the entries. */
323 static int
324 history_do_write (filename, nelements, overwrite)
325 char *filename;
326 int nelements, overwrite;
327 {
328 register int i;
329 char *output;
330 int file, mode;
331
332 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
333 output = history_filename (filename);
334
335 if ((file = open (output, mode, 0600)) == -1)
336 {
337 #ifdef __MSDOS__
338 /* MSDOS doesn't allow leading dots in file names. If this is
339 the default file name, try again with the dot replaced by an
340 underscore. */
341 if (!filename)
342 {
343 output[strlen (output) - 8] = '_';
344 if ((file = open (output, mode, 0600)) == -1)
345 {
346 FREE (output);
347 return (errno);
348 }
349 }
350 #else
351 FREE (output);
352 return (errno);
353 #endif
354 }
355
356 if (nelements > history_length)
357 nelements = history_length;
358
359 /* Build a buffer of all the lines to write, and write them in one syscall.
360 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
361 {
362 HIST_ENTRY **the_history; /* local */
363 register int j;
364 int buffer_size;
365 char *buffer;
366
367 the_history = history_list ();
368 /* Calculate the total number of bytes to write. */
369 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
370 buffer_size += 1 + strlen (the_history[i]->line);
371
372 /* Allocate the buffer, and fill it. */
373 buffer = xmalloc (buffer_size);
374
375 for (j = 0, i = history_length - nelements; i < history_length; i++)
376 {
377 strcpy (buffer + j, the_history[i]->line);
378 j += strlen (the_history[i]->line);
379 buffer[j++] = '\n';
380 }
381
382 write (file, buffer, buffer_size);
383 free (buffer);
384 }
385
386 close (file);
387
388 FREE (output);
389
390 return (0);
391 }
392
393 /* Append NELEMENT entries to FILENAME. The entries appended are from
394 the end of the list minus NELEMENTs up to the end of the list. */
395 int
396 append_history (nelements, filename)
397 int nelements;
398 char *filename;
399 {
400 return (history_do_write (filename, nelements, HISTORY_APPEND));
401 }
402
403 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
404 then write the history list to ~/.history. Values returned
405 are as in read_history ().*/
406 int
407 write_history (filename)
408 char *filename;
409 {
410 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
411 }
This page took 0.041663 seconds and 4 git commands to generate.