gdb: Make use of gdb::option framework for some info commands
[deliverable/binutils-gdb.git] / readline / histfile.c
1 /* histfile.c - functions to manipulate the history file. */
2
3 /* Copyright (C) 1989-2010 Free Software Foundation, Inc.
4
5 This file contains the GNU History Library (History), a set of
6 routines for managing the text of previously typed lines.
7
8 History 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 3 of the License, or
11 (at your option) any later version.
12
13 History is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with History. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* The goal is to make the implementation transparent, so that you
23 don't have to know what data types are used, just what functions
24 you can call. I think I have done that. */
25
26 #define READLINE_LIBRARY
27
28 #if defined (__TANDEM)
29 # include <floss.h>
30 #endif
31
32 #if defined (HAVE_CONFIG_H)
33 # include <config.h>
34 #endif
35
36 #include <stdio.h>
37
38 #include <sys/types.h>
39 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
40 # include <sys/file.h>
41 #endif
42 #include "posixstat.h"
43 #include <fcntl.h>
44
45 #if defined (HAVE_STDLIB_H)
46 # include <stdlib.h>
47 #else
48 # include "ansi_stdlib.h"
49 #endif /* HAVE_STDLIB_H */
50
51 #if defined (HAVE_UNISTD_H)
52 # include <unistd.h>
53 #endif
54
55 #include <ctype.h>
56
57 #if defined (__EMX__)
58 # undef HAVE_MMAP
59 #endif
60
61 #ifdef HISTORY_USE_MMAP
62 # include <sys/mman.h>
63
64 # ifdef MAP_FILE
65 # define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
66 # define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
67 # else
68 # define MAP_RFLAGS MAP_PRIVATE
69 # define MAP_WFLAGS MAP_SHARED
70 # endif
71
72 # ifndef MAP_FAILED
73 # define MAP_FAILED ((void *)-1)
74 # endif
75
76 #endif /* HISTORY_USE_MMAP */
77
78 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
79 on win 95/98/nt), we want to open files with O_BINARY mode so that there
80 is no \n -> \r\n conversion performed. On other systems, we don't want to
81 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
82 #if defined (__EMX__) || defined (__CYGWIN__)
83 # ifndef O_BINARY
84 # define O_BINARY 0
85 # endif
86 #else /* !__EMX__ && !__CYGWIN__ */
87 # undef O_BINARY
88 # define O_BINARY 0
89 #endif /* !__EMX__ && !__CYGWIN__ */
90
91 #include <errno.h>
92 #if !defined (errno)
93 extern int errno;
94 #endif /* !errno */
95
96 #include "history.h"
97 #include "histlib.h"
98
99 #include "rlshell.h"
100 #include "xmalloc.h"
101
102 /* If non-zero, we write timestamps to the history file in history_do_write() */
103 int history_write_timestamps = 0;
104
105 /* Does S look like the beginning of a history timestamp entry? Placeholder
106 for more extensive tests. */
107 #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((s)[1]) )
108
109 /* Return the string that should be used in the place of this
110 filename. This only matters when you don't specify the
111 filename to read_history (), or write_history (). */
112 static char *
113 history_filename (filename)
114 const char *filename;
115 {
116 char *return_val;
117 const char *home;
118 int home_len;
119
120 return_val = filename ? savestring (filename) : (char *)NULL;
121
122 if (return_val)
123 return (return_val);
124
125 home = sh_get_env_value ("HOME");
126 #ifdef _WIN32
127 if (!home)
128 home = sh_get_env_value ("APPDATA");
129 #endif
130
131 if (home == 0)
132 {
133 #if 0
134 home = ".";
135 home_len = 1;
136 #else
137 return (NULL);
138 #endif
139 }
140 else
141 home_len = strlen (home);
142
143 return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
144 strcpy (return_val, home);
145 return_val[home_len] = '/';
146 #if defined (__MSDOS__)
147 strcpy (return_val + home_len + 1, "_history");
148 #else
149 strcpy (return_val + home_len + 1, ".history");
150 #endif
151
152 return (return_val);
153 }
154
155 /* Add the contents of FILENAME to the history list, a line at a time.
156 If FILENAME is NULL, then read from ~/.history. Returns 0 if
157 successful, or errno if not. */
158 int
159 read_history (filename)
160 const char *filename;
161 {
162 return (read_history_range (filename, 0, -1));
163 }
164
165 /* Read a range of lines from FILENAME, adding them to the history list.
166 Start reading at the FROM'th line and end at the TO'th. If FROM
167 is zero, start at the beginning. If TO is less than FROM, read
168 until the end of the file. If FILENAME is NULL, then read from
169 ~/.history. Returns 0 if successful, or errno if not. */
170 int
171 read_history_range (filename, from, to)
172 const char *filename;
173 int from, to;
174 {
175 register char *line_start, *line_end, *p;
176 char *input, *buffer, *bufend, *last_ts;
177 int file, current_line, chars_read;
178 struct stat finfo;
179 size_t file_size;
180 #if defined (EFBIG)
181 int overflow_errno = EFBIG;
182 #elif defined (EOVERFLOW)
183 int overflow_errno = EOVERFLOW;
184 #else
185 int overflow_errno = EIO;
186 #endif
187
188 buffer = last_ts = (char *)NULL;
189 input = history_filename (filename);
190 file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
191
192 if ((file < 0) || (fstat (file, &finfo) == -1))
193 goto error_and_exit;
194
195 file_size = (size_t)finfo.st_size;
196
197 /* check for overflow on very large files */
198 if (file_size != finfo.st_size || file_size + 1 < file_size)
199 {
200 errno = overflow_errno;
201 goto error_and_exit;
202 }
203
204 #ifdef HISTORY_USE_MMAP
205 /* We map read/write and private so we can change newlines to NULs without
206 affecting the underlying object. */
207 buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
208 if ((void *)buffer == MAP_FAILED)
209 {
210 errno = overflow_errno;
211 goto error_and_exit;
212 }
213 chars_read = file_size;
214 #else
215 buffer = (char *)malloc (file_size + 1);
216 if (buffer == 0)
217 {
218 errno = overflow_errno;
219 goto error_and_exit;
220 }
221
222 chars_read = read (file, buffer, file_size);
223 #endif
224 if (chars_read < 0)
225 {
226 error_and_exit:
227 if (errno != 0)
228 chars_read = errno;
229 else
230 chars_read = EIO;
231 if (file >= 0)
232 close (file);
233
234 FREE (input);
235 #ifndef HISTORY_USE_MMAP
236 FREE (buffer);
237 #endif
238
239 return (chars_read);
240 }
241
242 close (file);
243
244 /* Set TO to larger than end of file if negative. */
245 if (to < 0)
246 to = chars_read;
247
248 /* Start at beginning of file, work to end. */
249 bufend = buffer + chars_read;
250 current_line = 0;
251
252 /* Skip lines until we are at FROM. */
253 for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
254 if (*line_end == '\n')
255 {
256 p = line_end + 1;
257 /* If we see something we think is a timestamp, continue with this
258 line. We should check more extensively here... */
259 if (HIST_TIMESTAMP_START(p) == 0)
260 current_line++;
261 line_start = p;
262 }
263
264 /* If there are lines left to gobble, then gobble them now. */
265 for (line_end = line_start; line_end < bufend; line_end++)
266 if (*line_end == '\n')
267 {
268 /* Change to allow Windows-like \r\n end of line delimiter. */
269 if (line_end > line_start && line_end[-1] == '\r')
270 line_end[-1] = '\0';
271 else
272 *line_end = '\0';
273
274 if (*line_start)
275 {
276 if (HIST_TIMESTAMP_START(line_start) == 0)
277 {
278 add_history (line_start);
279 if (last_ts)
280 {
281 add_history_time (last_ts);
282 last_ts = NULL;
283 }
284 }
285 else
286 {
287 last_ts = line_start;
288 current_line--;
289 }
290 }
291
292 current_line++;
293
294 if (current_line >= to)
295 break;
296
297 line_start = line_end + 1;
298 }
299
300 FREE (input);
301 #ifndef HISTORY_USE_MMAP
302 FREE (buffer);
303 #else
304 munmap (buffer, file_size);
305 #endif
306
307 return (0);
308 }
309
310 /* Truncate the history file FNAME, leaving only LINES trailing lines.
311 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
312 on failure. */
313 int
314 history_truncate_file (fname, lines)
315 const char *fname;
316 int lines;
317 {
318 char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
319 int file, chars_read, rv;
320 struct stat finfo;
321 size_t file_size;
322
323 buffer = (char *)NULL;
324 filename = history_filename (fname);
325 file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
326 rv = 0;
327
328 /* Don't try to truncate non-regular files. */
329 if (file == -1 || fstat (file, &finfo) == -1)
330 {
331 rv = errno;
332 if (file != -1)
333 close (file);
334 goto truncate_exit;
335 }
336
337 if (S_ISREG (finfo.st_mode) == 0)
338 {
339 close (file);
340 #ifdef EFTYPE
341 rv = EFTYPE;
342 #else
343 rv = EINVAL;
344 #endif
345 goto truncate_exit;
346 }
347
348 file_size = (size_t)finfo.st_size;
349
350 /* check for overflow on very large files */
351 if (file_size != finfo.st_size || file_size + 1 < file_size)
352 {
353 close (file);
354 #if defined (EFBIG)
355 rv = errno = EFBIG;
356 #elif defined (EOVERFLOW)
357 rv = errno = EOVERFLOW;
358 #else
359 rv = errno = EINVAL;
360 #endif
361 goto truncate_exit;
362 }
363
364 buffer = (char *)malloc (file_size + 1);
365 if (buffer == 0)
366 {
367 close (file);
368 goto truncate_exit;
369 }
370
371 chars_read = read (file, buffer, file_size);
372 close (file);
373
374 if (chars_read <= 0)
375 {
376 rv = (chars_read < 0) ? errno : 0;
377 goto truncate_exit;
378 }
379
380 /* Count backwards from the end of buffer until we have passed
381 LINES lines. bp1 is set funny initially. But since bp[1] can't
382 be a comment character (since it's off the end) and *bp can't be
383 both a newline and the history comment character, it should be OK. */
384 for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
385 {
386 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
387 lines--;
388 bp1 = bp;
389 }
390
391 /* If this is the first line, then the file contains exactly the
392 number of lines we want to truncate to, so we don't need to do
393 anything. It's the first line if we don't find a newline between
394 the current value of i and 0. Otherwise, write from the start of
395 this line until the end of the buffer. */
396 for ( ; bp > buffer; bp--)
397 {
398 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
399 {
400 bp++;
401 break;
402 }
403 bp1 = bp;
404 }
405
406 /* Write only if there are more lines in the file than we want to
407 truncate to. */
408 if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
409 {
410 if (write (file, bp, chars_read - (bp - buffer)) < 0)
411 rv = errno;
412
413 #if defined (__BEOS__)
414 /* BeOS ignores O_TRUNC. */
415 ftruncate (file, chars_read - (bp - buffer));
416 #endif
417
418 close (file);
419 }
420
421 truncate_exit:
422
423 FREE (buffer);
424
425 xfree (filename);
426 return rv;
427 }
428
429 /* Workhorse function for writing history. Writes NELEMENT entries
430 from the history list to FILENAME. OVERWRITE is non-zero if you
431 wish to replace FILENAME with the entries. */
432 static int
433 history_do_write (filename, nelements, overwrite)
434 const char *filename;
435 int nelements, overwrite;
436 {
437 register int i;
438 char *output;
439 int file, mode, rv;
440 #ifdef HISTORY_USE_MMAP
441 size_t cursize;
442
443 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
444 #else
445 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
446 #endif
447 output = history_filename (filename);
448 file = output ? open (output, mode, 0600) : -1;
449 rv = 0;
450
451 if (file == -1)
452 {
453 FREE (output);
454 return (errno);
455 }
456
457 #ifdef HISTORY_USE_MMAP
458 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
459 #endif
460
461 if (nelements > history_length)
462 nelements = history_length;
463
464 /* Build a buffer of all the lines to write, and write them in one syscall.
465 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
466 {
467 HIST_ENTRY **the_history; /* local */
468 register int j;
469 int buffer_size;
470 char *buffer;
471
472 the_history = history_list ();
473 /* Calculate the total number of bytes to write. */
474 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
475 #if 0
476 buffer_size += 2 + HISTENT_BYTES (the_history[i]);
477 #else
478 {
479 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
480 buffer_size += strlen (the_history[i]->timestamp) + 1;
481 buffer_size += strlen (the_history[i]->line) + 1;
482 }
483 #endif
484
485 /* Allocate the buffer, and fill it. */
486 #ifdef HISTORY_USE_MMAP
487 if (ftruncate (file, buffer_size+cursize) == -1)
488 goto mmap_error;
489 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
490 if ((void *)buffer == MAP_FAILED)
491 {
492 mmap_error:
493 rv = errno;
494 FREE (output);
495 close (file);
496 return rv;
497 }
498 #else
499 buffer = (char *)malloc (buffer_size);
500 if (buffer == 0)
501 {
502 rv = errno;
503 FREE (output);
504 close (file);
505 return rv;
506 }
507 #endif
508
509 for (j = 0, i = history_length - nelements; i < history_length; i++)
510 {
511 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
512 {
513 strcpy (buffer + j, the_history[i]->timestamp);
514 j += strlen (the_history[i]->timestamp);
515 buffer[j++] = '\n';
516 }
517 strcpy (buffer + j, the_history[i]->line);
518 j += strlen (the_history[i]->line);
519 buffer[j++] = '\n';
520 }
521
522 #ifdef HISTORY_USE_MMAP
523 if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
524 rv = errno;
525 #else
526 if (write (file, buffer, buffer_size) < 0)
527 rv = errno;
528 xfree (buffer);
529 #endif
530 }
531
532 close (file);
533
534 FREE (output);
535
536 return (rv);
537 }
538
539 /* Append NELEMENT entries to FILENAME. The entries appended are from
540 the end of the list minus NELEMENTs up to the end of the list. */
541 int
542 append_history (nelements, filename)
543 int nelements;
544 const char *filename;
545 {
546 return (history_do_write (filename, nelements, HISTORY_APPEND));
547 }
548
549 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
550 then write the history list to ~/.history. Values returned
551 are as in read_history ().*/
552 int
553 write_history (filename)
554 const char *filename;
555 {
556 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
557 }
This page took 0.042037 seconds and 4 git commands to generate.