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 2, 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 59 Temple Place, Suite 330, Boston, MA 02111 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 "posixstat.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 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__) 63 # ifndef O_BINARY 64 # define O_BINARY 0 65 # endif 66 #else /* !__EMX__ && !__CYGWIN__ */ 67 # undef O_BINARY 68 # define O_BINARY 0 69 #endif /* !__EMX__ && !__CYGWIN__ */ 70 71 #include <errno.h> 72 #if !defined (errno) 73 extern int errno; 74 #endif /* !errno */ 75 76 #include "history.h" 77 #include "histlib.h" 78 79 #include "rlshell.h" 80 #include "xmalloc.h" 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 (). */ 85 static char * 86 history_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 || *home == '\0') { 100 errno = ENOENT; 101 return (NULL); 102 } 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 #if defined (__MSDOS__) 109 strcpy (return_val + home_len + 1, "_history"); 110 #else 111 strcpy (return_val + home_len + 1, ".history"); 112 #endif 113 114 return (return_val); 115 } 116 117 /* Add the contents of FILENAME to the history list, a line at a time. 118 If FILENAME is NULL, then read from ~/.history. Returns 0 if 119 successful, or errno if not. */ 120 int 121 read_history (filename) 122 char *filename; 123 { 124 return (read_history_range (filename, 0, -1)); 125 } 126 127 /* Read a range of lines from FILENAME, adding them to the history list. 128 Start reading at the FROM'th line and end at the TO'th. If FROM 129 is zero, start at the beginning. If TO is less than FROM, read 130 until the end of the file. If FILENAME is NULL, then read from 131 ~/.history. Returns 0 if successful, or errno if not. */ 132 int 133 read_history_range (filename, from, to) 134 char *filename; 135 int from, to; 136 { 137 register int line_start, line_end; 138 char *input, *buffer; 139 int file, current_line, chars_read; 140 struct stat finfo; 141 size_t file_size; 142 143 buffer = (char *)NULL; 144 if ((input = history_filename (filename))) 145 file = open (input, O_RDONLY|O_BINARY, 0666); 146 else 147 file = -1; 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); 164 165 chars_read = read (file, buffer, file_size); 166 if (chars_read < 0) 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) 182 to = chars_read; 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. */ 188 while (line_start < chars_read && current_line < from) 189 { 190 for (line_end = line_start; line_end < chars_read; line_end++) 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. */ 201 for (line_end = line_start; line_end < chars_read; line_end++) 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. */ 225 int 226 history_truncate_file (fname, lines) 227 char *fname; 228 int lines; 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 if ((filename = history_filename (fname))) 238 file = open (filename, O_RDONLY|O_BINARY, 0666); 239 else 240 file = -1; 241 242 if (file == -1 || fstat (file, &finfo) == -1) 243 goto truncate_exit; 244 245 /* Don't try to truncate non-regular files. */ 246 if (S_ISREG(finfo.st_mode) == 0) 247 goto truncate_exit; 248 249 file_size = (size_t)finfo.st_size; 250 251 /* check for overflow on very large files */ 252 if (file_size != finfo.st_size || file_size + 1 < file_size) 253 { 254 close (file); 255 #if defined (EFBIG) 256 errno = EFBIG; 257 #endif 258 goto truncate_exit; 259 } 260 261 buffer = xmalloc (file_size + 1); 262 chars_read = read (file, buffer, file_size); 263 close (file); 264 265 if (chars_read <= 0) 266 goto truncate_exit; 267 268 /* Count backwards from the end of buffer until we have passed 269 LINES lines. */ 270 for (i = chars_read - 1; lines && i; i--) 271 { 272 if (buffer[i] == '\n') 273 lines--; 274 } 275 276 /* If this is the first line, then the file contains exactly the 277 number of lines we want to truncate to, so we don't need to do 278 anything. It's the first line if we don't find a newline between 279 the current value of i and 0. Otherwise, write from the start of 280 this line until the end of the buffer. */ 281 for ( ; i; i--) 282 if (buffer[i] == '\n') 283 { 284 i++; 285 break; 286 } 287 288 /* Write only if there are more lines in the file than we want to 289 truncate to. */ 290 if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) 291 { 292 write (file, buffer + i, chars_read - i); 293 294 #if defined (__BEOS__) 295 /* BeOS ignores O_TRUNC. */ 296 ftruncate (file, chars_read - i); 297 #endif 298 299 close (file); 300 } 301 302 truncate_exit: 303 304 FREE (buffer); 305 306 free (filename); 307 return 0; 308 } 309 310 /* Workhorse function for writing history. Writes NELEMENT entries 311 from the history list to FILENAME. OVERWRITE is non-zero if you 312 wish to replace FILENAME with the entries. */ 313 static int 314 history_do_write (filename, nelements, overwrite) 315 char *filename; 316 int nelements, overwrite; 317 { 318 register int i; 319 char *output; 320 int file, mode; 321 322 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY; 323 output = history_filename (filename); 324 325 if (!output || (file = open (output, mode, 0600)) == -1) 326 { 327 FREE (output); 328 return (errno); 329 } 330 331 if (nelements > history_length) 332 nelements = history_length; 333 334 /* Build a buffer of all the lines to write, and write them in one syscall. 335 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */ 336 { 337 HIST_ENTRY **the_history; /* local */ 338 register int j; 339 int buffer_size; 340 char *buffer; 341 342 the_history = history_list (); 343 /* Calculate the total number of bytes to write. */ 344 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) 345 buffer_size += 1 + strlen (the_history[i]->line); 346 347 /* Allocate the buffer, and fill it. */ 348 buffer = xmalloc (buffer_size); 349 350 for (j = 0, i = history_length - nelements; i < history_length; i++) 351 { 352 strcpy (buffer + j, the_history[i]->line); 353 j += strlen (the_history[i]->line); 354 buffer[j++] = '\n'; 355 } 356 357 write (file, buffer, buffer_size); 358 free (buffer); 359 } 360 361 close (file); 362 363 FREE (output); 364 365 return (0); 366 } 367 368 /* Append NELEMENT entries to FILENAME. The entries appended are from 369 the end of the list minus NELEMENTs up to the end of the list. */ 370 int 371 append_history (nelements, filename) 372 int nelements; 373 char *filename; 374 { 375 return (history_do_write (filename, nelements, HISTORY_APPEND)); 376 } 377 378 /* Overwrite FILENAME with the current history. If FILENAME is NULL, 379 then write the history list to ~/.history. Values returned 380 are as in read_history ().*/ 381 int 382 write_history (filename) 383 char *filename; 384 { 385 return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); 386 } 387