* histfile.c (read_history_range): Remove '\r' character from
[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
9255ee31
EZ
51#if defined (__EMX__) || defined (__CYGWIN__)
52# undef HAVE_MMAP
53#endif
54
55#ifdef HAVE_MMAP
56# include <sys/mman.h>
57
58# ifdef MAP_FILE
59# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
60# define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
61# else
62# define MAP_RFLAGS MAP_PRIVATE
63# define MAP_WFLAGS MAP_SHARED
64# endif
65
66# ifndef MAP_FAILED
67# define MAP_FAILED ((void *)-1)
68# endif
d60d9f65 69
9255ee31 70#endif /* HAVE_MMAP */
1b17e766
EZ
71
72/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
73 on win 95/98/nt), we want to open files with O_BINARY mode so that there
74 is no \n -> \r\n conversion performed. On other systems, we don't want to
75 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
76#if defined (__EMX__) || defined (__CYGWIN__)
d60d9f65
SS
77# ifndef O_BINARY
78# define O_BINARY 0
79# endif
1b17e766 80#else /* !__EMX__ && !__CYGWIN__ */
d60d9f65
SS
81# undef O_BINARY
82# define O_BINARY 0
1b17e766 83#endif /* !__EMX__ && !__CYGWIN__ */
d60d9f65
SS
84
85#include <errno.h>
86#if !defined (errno)
87extern int errno;
88#endif /* !errno */
89
90#include "history.h"
91#include "histlib.h"
92
1b17e766
EZ
93#include "rlshell.h"
94#include "xmalloc.h"
d60d9f65
SS
95
96/* Return the string that should be used in the place of this
97 filename. This only matters when you don't specify the
98 filename to read_history (), or write_history (). */
99static char *
100history_filename (filename)
9255ee31 101 const char *filename;
d60d9f65 102{
9255ee31
EZ
103 char *return_val;
104 const char *home;
d60d9f65
SS
105 int home_len;
106
107 return_val = filename ? savestring (filename) : (char *)NULL;
108
109 if (return_val)
110 return (return_val);
111
9255ee31 112 home = sh_get_env_value ("HOME");
d60d9f65
SS
113
114 if (home == 0)
115 {
116 home = ".";
117 home_len = 1;
118 }
119 else
120 home_len = strlen (home);
121
9255ee31 122 return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
d60d9f65
SS
123 strcpy (return_val, home);
124 return_val[home_len] = '/';
1b17e766
EZ
125#if defined (__MSDOS__)
126 strcpy (return_val + home_len + 1, "_history");
127#else
d60d9f65 128 strcpy (return_val + home_len + 1, ".history");
1b17e766 129#endif
d60d9f65
SS
130
131 return (return_val);
132}
133
134/* Add the contents of FILENAME to the history list, a line at a time.
135 If FILENAME is NULL, then read from ~/.history. Returns 0 if
136 successful, or errno if not. */
137int
138read_history (filename)
9255ee31 139 const char *filename;
d60d9f65
SS
140{
141 return (read_history_range (filename, 0, -1));
142}
143
144/* Read a range of lines from FILENAME, adding them to the history list.
145 Start reading at the FROM'th line and end at the TO'th. If FROM
146 is zero, start at the beginning. If TO is less than FROM, read
147 until the end of the file. If FILENAME is NULL, then read from
148 ~/.history. Returns 0 if successful, or errno if not. */
149int
150read_history_range (filename, from, to)
9255ee31 151 const char *filename;
d60d9f65
SS
152 int from, to;
153{
9255ee31
EZ
154 register char *line_start, *line_end;
155 char *input, *buffer, *bufend;
1b17e766 156 int file, current_line, chars_read;
d60d9f65
SS
157 struct stat finfo;
158 size_t file_size;
159
160 buffer = (char *)NULL;
161 input = history_filename (filename);
162 file = open (input, O_RDONLY|O_BINARY, 0666);
163
164 if ((file < 0) || (fstat (file, &finfo) == -1))
165 goto error_and_exit;
166
167 file_size = (size_t)finfo.st_size;
168
169 /* check for overflow on very large files */
170 if (file_size != finfo.st_size || file_size + 1 < file_size)
171 {
172#if defined (EFBIG)
173 errno = EFBIG;
9255ee31
EZ
174#elif defined (EOVERFLOW)
175 errno = EOVERFLOW;
d60d9f65
SS
176#endif
177 goto error_and_exit;
178 }
179
9255ee31
EZ
180#ifdef HAVE_MMAP
181 /* We map read/write and private so we can change newlines to NULs without
182 affecting the underlying object. */
183 buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
184 if ((void *)buffer == MAP_FAILED)
185 goto error_and_exit;
186 chars_read = file_size;
187#else
188 buffer = (char *)malloc (file_size + 1);
189 if (buffer == 0)
190 goto error_and_exit;
1b17e766
EZ
191
192 chars_read = read (file, buffer, file_size);
9255ee31 193#endif
1b17e766 194 if (chars_read < 0)
d60d9f65
SS
195 {
196 error_and_exit:
9255ee31 197 chars_read = errno;
d60d9f65
SS
198 if (file >= 0)
199 close (file);
200
201 FREE (input);
9255ee31 202#ifndef HAVE_MMAP
d60d9f65 203 FREE (buffer);
9255ee31 204#endif
d60d9f65 205
9255ee31 206 return (chars_read);
d60d9f65
SS
207 }
208
209 close (file);
210
211 /* Set TO to larger than end of file if negative. */
212 if (to < 0)
1b17e766 213 to = chars_read;
d60d9f65
SS
214
215 /* Start at beginning of file, work to end. */
9255ee31
EZ
216 bufend = buffer + chars_read;
217 current_line = 0;
d60d9f65
SS
218
219 /* Skip lines until we are at FROM. */
9255ee31
EZ
220 for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
221 if (*line_end == '\n')
222 {
223 current_line++;
224 line_start = line_end + 1;
225 }
d60d9f65
SS
226
227 /* If there are lines left to gobble, then gobble them now. */
9255ee31
EZ
228 for (line_end = line_start; line_end < bufend; line_end++)
229 if (*line_end == '\n')
d60d9f65 230 {
a75b402a
DJ
231 if (line_end - 1 >= line_start && *(line_end - 1) == '\r')
232 *(line_end - 1) = '\0';
233 else
234 *line_end = '\0';
d60d9f65 235
9255ee31
EZ
236 if (*line_start)
237 add_history (line_start);
d60d9f65
SS
238
239 current_line++;
240
241 if (current_line >= to)
242 break;
243
244 line_start = line_end + 1;
245 }
246
247 FREE (input);
9255ee31 248#ifndef HAVE_MMAP
d60d9f65 249 FREE (buffer);
9255ee31
EZ
250#else
251 munmap (buffer, file_size);
252#endif
d60d9f65
SS
253
254 return (0);
255}
256
257/* Truncate the history file FNAME, leaving only LINES trailing lines.
9255ee31
EZ
258 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
259 on failure. */
d60d9f65
SS
260int
261history_truncate_file (fname, lines)
9255ee31 262 const char *fname;
c862e87b 263 int lines;
d60d9f65 264{
9255ee31
EZ
265 char *buffer, *filename, *bp;
266 int file, chars_read, rv;
d60d9f65
SS
267 struct stat finfo;
268 size_t file_size;
269
270 buffer = (char *)NULL;
271 filename = history_filename (fname);
272 file = open (filename, O_RDONLY|O_BINARY, 0666);
9255ee31 273 rv = 0;
d60d9f65 274
9255ee31 275 /* Don't try to truncate non-regular files. */
d60d9f65 276 if (file == -1 || fstat (file, &finfo) == -1)
9255ee31
EZ
277 {
278 rv = errno;
279 if (file != -1)
280 close (file);
281 goto truncate_exit;
282 }
d60d9f65 283
9255ee31
EZ
284 if (S_ISREG (finfo.st_mode) == 0)
285 {
286 close (file);
287#ifdef EFTYPE
288 rv = EFTYPE;
289#else
290 rv = EINVAL;
291#endif
292 goto truncate_exit;
293 }
1b17e766 294
d60d9f65
SS
295 file_size = (size_t)finfo.st_size;
296
297 /* check for overflow on very large files */
298 if (file_size != finfo.st_size || file_size + 1 < file_size)
299 {
300 close (file);
301#if defined (EFBIG)
9255ee31
EZ
302 rv = errno = EFBIG;
303#elif defined (EOVERFLOW)
304 rv = errno = EOVERFLOW;
305#else
306 rv = errno = EINVAL;
d60d9f65
SS
307#endif
308 goto truncate_exit;
309 }
310
9255ee31
EZ
311 buffer = (char *)malloc (file_size + 1);
312 if (buffer == 0)
313 {
314 close (file);
315 goto truncate_exit;
316 }
317
d60d9f65
SS
318 chars_read = read (file, buffer, file_size);
319 close (file);
320
321 if (chars_read <= 0)
9255ee31
EZ
322 {
323 rv = (chars_read < 0) ? errno : 0;
324 goto truncate_exit;
325 }
d60d9f65
SS
326
327 /* Count backwards from the end of buffer until we have passed
328 LINES lines. */
9255ee31 329 for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
d60d9f65 330 {
9255ee31 331 if (*bp == '\n')
d60d9f65
SS
332 lines--;
333 }
334
335 /* If this is the first line, then the file contains exactly the
336 number of lines we want to truncate to, so we don't need to do
337 anything. It's the first line if we don't find a newline between
338 the current value of i and 0. Otherwise, write from the start of
339 this line until the end of the buffer. */
9255ee31
EZ
340 for ( ; bp > buffer; bp--)
341 if (*bp == '\n')
d60d9f65 342 {
9255ee31 343 bp++;
d60d9f65
SS
344 break;
345 }
346
347 /* Write only if there are more lines in the file than we want to
348 truncate to. */
9255ee31 349 if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
d60d9f65 350 {
9255ee31 351 write (file, bp, chars_read - (bp - buffer));
c862e87b
JM
352
353#if defined (__BEOS__)
354 /* BeOS ignores O_TRUNC. */
9255ee31 355 ftruncate (file, chars_read - (bp - buffer));
c862e87b
JM
356#endif
357
d60d9f65
SS
358 close (file);
359 }
360
361 truncate_exit:
362
363 FREE (buffer);
364
365 free (filename);
9255ee31 366 return rv;
d60d9f65
SS
367}
368
369/* Workhorse function for writing history. Writes NELEMENT entries
370 from the history list to FILENAME. OVERWRITE is non-zero if you
371 wish to replace FILENAME with the entries. */
372static int
373history_do_write (filename, nelements, overwrite)
9255ee31 374 const char *filename;
d60d9f65
SS
375 int nelements, overwrite;
376{
377 register int i;
378 char *output;
9255ee31
EZ
379 int file, mode, rv;
380 size_t cursize;
d60d9f65 381
9255ee31
EZ
382#ifdef HAVE_MMAP
383 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
384#else
d60d9f65 385 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
9255ee31 386#endif
d60d9f65 387 output = history_filename (filename);
9255ee31 388 rv = 0;
d60d9f65
SS
389
390 if ((file = open (output, mode, 0600)) == -1)
391 {
392 FREE (output);
393 return (errno);
394 }
395
9255ee31
EZ
396#ifdef HAVE_MMAP
397 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
398#endif
399
d60d9f65
SS
400 if (nelements > history_length)
401 nelements = history_length;
402
403 /* Build a buffer of all the lines to write, and write them in one syscall.
404 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
405 {
406 HIST_ENTRY **the_history; /* local */
407 register int j;
408 int buffer_size;
409 char *buffer;
410
411 the_history = history_list ();
412 /* Calculate the total number of bytes to write. */
413 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
414 buffer_size += 1 + strlen (the_history[i]->line);
415
416 /* Allocate the buffer, and fill it. */
9255ee31
EZ
417#ifdef HAVE_MMAP
418 if (ftruncate (file, buffer_size+cursize) == -1)
419 goto mmap_error;
420 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
421 if ((void *)buffer == MAP_FAILED)
422 {
423mmap_error:
424 rv = errno;
425 FREE (output);
426 close (file);
427 return rv;
428 }
429#else
430 buffer = (char *)malloc (buffer_size);
431 if (buffer == 0)
432 {
433 rv = errno;
434 FREE (output);
435 close (file);
436 return rv;
437 }
438#endif
d60d9f65
SS
439
440 for (j = 0, i = history_length - nelements; i < history_length; i++)
441 {
442 strcpy (buffer + j, the_history[i]->line);
443 j += strlen (the_history[i]->line);
444 buffer[j++] = '\n';
445 }
446
9255ee31
EZ
447#ifdef HAVE_MMAP
448 if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
449 rv = errno;
450#else
451 if (write (file, buffer, buffer_size) < 0)
452 rv = errno;
d60d9f65 453 free (buffer);
9255ee31 454#endif
d60d9f65
SS
455 }
456
457 close (file);
458
459 FREE (output);
460
9255ee31 461 return (rv);
d60d9f65
SS
462}
463
464/* Append NELEMENT entries to FILENAME. The entries appended are from
465 the end of the list minus NELEMENTs up to the end of the list. */
466int
467append_history (nelements, filename)
468 int nelements;
9255ee31 469 const char *filename;
d60d9f65
SS
470{
471 return (history_do_write (filename, nelements, HISTORY_APPEND));
472}
473
474/* Overwrite FILENAME with the current history. If FILENAME is NULL,
475 then write the history list to ~/.history. Values returned
476 are as in read_history ().*/
477int
478write_history (filename)
9255ee31 479 const char *filename;
d60d9f65
SS
480{
481 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
482}
This page took 0.340222 seconds and 4 git commands to generate.