Error Buddy
Do you have an error message from your application? Then find the answer with Error Buddy. You can search over 40000 source code files and troubleshooting documents using our beta lucene/nutch search interface or if you prefer, search as normal using google. With LXR technology you can drill right down into the line of source code where it came from with full cross-referencing.
If after searching you didn't get your ideal answer, or you are still unclear what the error means, you can choose to post that question to the community forums following the link included in the search results.
[1.6]001 /* histfile.c - functions to manipulate the history file. */ 002 003 /* Copyright (C) 1989-2003 Free Software Foundation, Inc. 004 005 This file contains the GNU History Library (the Library), a set of 006 routines for managing the text of previously typed lines. 007 008 The Library is free software; you can redistribute it and/or modify 009 it under the terms of the GNU General Public License as published by 010 the Free Software Foundation; either version 2, or (at your option) 011 any later version. 012 013 The Library is distributed in the hope that it will be useful, but 014 WITHOUT ANY WARRANTY; without even the implied warranty of 015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 016 General Public License for more details. 017 018 The GNU General Public License is often shipped with GNU software, and 019 is generally kept in a file called COPYING or LICENSE. If you do not 020 have a copy of the license, write to the Free Software Foundation, 021 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 022 023 /* The goal is to make the implementation transparent, so that you 024 don't have to know what data types are used, just what functions 025 you can call. I think I have done that. */ 026 027 #define READLINE_LIBRARY 028 029 #if defined (__TANDEM) 030 # include <floss.h> 031 #endif 032 033 #if defined (HAVE_CONFIG_H) 034 # include <config.h> 035 #endif 036 037 #include <stdio.h> 038 039 #include <sys/types.h> 040 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H) 041 # include <sys/file.h> 042 #endif 043 #include "posixstat.h" 044 #include <fcntl.h> 045 046 #if defined (HAVE_STDLIB_H) 047 # include <stdlib.h> 048 #else 049 # include "ansi_stdlib.h" 050 #endif /* HAVE_STDLIB_H */ 051 052 #if defined (HAVE_UNISTD_H) 053 # include <unistd.h> 054 #endif 055 056 #if defined (__EMX__) || defined (__CYGWIN__) 057 # undef HAVE_MMAP 058 #endif 059 060 #ifdef HISTORY_USE_MMAP 061 # include <sys/mman.h> 062 063 # ifdef MAP_FILE 064 # define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE) 065 # define MAP_WFLAGS (MAP_FILE|MAP_SHARED) 066 # else 067 # define MAP_RFLAGS MAP_PRIVATE 068 # define MAP_WFLAGS MAP_SHARED 069 # endif 070 071 # ifndef MAP_FAILED 072 # define MAP_FAILED ((void *)-1) 073 # endif 074 075 #endif /* HISTORY_USE_MMAP */ 076 077 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment 078 on win 95/98/nt), we want to open files with O_BINARY mode so that there 079 is no \n -> \r\n conversion performed. On other systems, we don't want to 080 mess around with O_BINARY at all, so we ensure that it's defined to 0. */ 081 #if defined (__EMX__) || defined (__CYGWIN__) 082 # ifndef O_BINARY 083 # define O_BINARY 0 084 # endif 085 #else /* !__EMX__ && !__CYGWIN__ */ 086 # undef O_BINARY 087 # define O_BINARY 0 088 #endif /* !__EMX__ && !__CYGWIN__ */ 089 090 #include <errno.h> 091 #if !defined (errno) 092 extern int errno; 093 #endif /* !errno */ 094 095 #include "history.h" 096 #include "histlib.h" 097 098 #include "rlshell.h" 099 #include "xmalloc.h" 100 101 /* If non-zero, we write timestamps to the history file in history_do_write() */ 102 int history_write_timestamps = 0; 103 104 /* Does S look like the beginning of a history timestamp entry? Placeholder 105 for more extensive tests. */ 106 #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char) 107 108 /* Return the string that should be used in the place of this 109 filename. This only matters when you don't specify the 110 filename to read_history (), or write_history (). */ 111 static char * 112 history_filename (filename) 113 const char *filename; 114 { 115 char *return_val; 116 const char *home; 117 int home_len; 118 119 return_val = filename ? savestring (filename) : (char *)NULL; 120 121 if (return_val) 122 return (return_val); 123 124 home = sh_get_env_value ("HOME"); 125 126 if (home == 0) 127 { 128 home = "."; 129 home_len = 1; 130 } 131 else 132 home_len = strlen (home); 133 134 return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ 135 strcpy (return_val, home); 136 return_val[home_len] = '/'; 137 #if defined (__MSDOS__) 138 strcpy (return_val + home_len + 1, "_history"); 139 #else 140 strcpy (return_val + home_len + 1, ".history"); 141 #endif 142 143 return (return_val); 144 } 145 146 /* Add the contents of FILENAME to the history list, a line at a time. 147 If FILENAME is NULL, then read from ~/.history. Returns 0 if 148 successful, or errno if not. */ 149 int 150 read_history (filename) 151 const char *filename; 152 { 153 return (read_history_range (filename, 0, -1)); 154 } 155 156 /* Read a range of lines from FILENAME, adding them to the history list. 157 Start reading at the FROM'th line and end at the TO'th. If FROM 158 is zero, start at the beginning. If TO is less than FROM, read 159 until the end of the file. If FILENAME is NULL, then read from 160 ~/.history. Returns 0 if successful, or errno if not. */ 161 int 162 read_history_range (filename, from, to) 163 const char *filename; 164 int from, to; 165 { 166 register char *line_start, *line_end, *p; 167 char *input, *buffer, *bufend, *last_ts; 168 int file, current_line, chars_read; 169 struct stat finfo; 170 size_t file_size; 171 #if defined (EFBIG) 172 int overflow_errno = EFBIG; 173 #elif defined (EOVERFLOW) 174 int overflow_errno = EOVERFLOW; 175 #else 176 int overflow_errno = EIO; 177 #endif 178 179 buffer = last_ts = (char *)NULL; 180 input = history_filename (filename); 181 file = open (input, O_RDONLY|O_BINARY, 0666); 182 183 if ((file < 0) || (fstat (file, &finfo) == -1)) 184 goto error_and_exit; 185 186 file_size = (size_t)finfo.st_size; 187 188 /* check for overflow on very large files */ 189 if (file_size != finfo.st_size || file_size + 1 < file_size) 190 { 191 errno = overflow_errno; 192 goto error_and_exit; 193 } 194 195 #ifdef HISTORY_USE_MMAP 196 /* We map read/write and private so we can change newlines to NULs without 197 affecting the underlying object. */ 198 buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0); 199 if ((void *)buffer == MAP_FAILED) 200 { 201 errno = overflow_errno; 202 goto error_and_exit; 203 } 204 chars_read = file_size; 205 #else 206 buffer = (char *)malloc (file_size + 1); 207 if (buffer == 0) 208 { 209 errno = overflow_errno; 210 goto error_and_exit; 211 } 212 213 chars_read = read (file, buffer, file_size); 214 #endif 215 if (chars_read < 0) 216 { 217 error_and_exit: 218 if (errno != 0) 219 chars_read = errno; 220 else 221 chars_read = EIO; 222 if (file >= 0) 223 close (file); 224 225 FREE (input); 226 #ifndef HISTORY_USE_MMAP 227 FREE (buffer); 228 #endif 229 230 return (chars_read); 231 } 232 233 close (file); 234 235 /* Set TO to larger than end of file if negative. */ 236 if (to < 0) 237 to = chars_read; 238 239 /* Start at beginning of file, work to end. */ 240 bufend = buffer + chars_read; 241 current_line = 0; 242 243 /* Skip lines until we are at FROM. */ 244 for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) 245 if (*line_end == '\n') 246 { 247 p = line_end + 1; 248 /* If we see something we think is a timestamp, continue with this 249 line. We should check more extensively here... */ 250 if (HIST_TIMESTAMP_START(p) == 0) 251 current_line++; 252 line_start = p; 253 } 254 255 /* If there are lines left to gobble, then gobble them now. */ 256 for (line_end = line_start; line_end < bufend; line_end++) 257 if (*line_end == '\n') 258 { 259 *line_end = '\0'; 260 261 if (*line_start) 262 { 263 if (HIST_TIMESTAMP_START(line_start) == 0) 264 { 265 add_history (line_start); 266 if (last_ts) 267 { 268 add_history_time (last_ts); 269 last_ts = NULL; 270 } 271 } 272 else 273 { 274 last_ts = line_start; 275 current_line--; 276 } 277 } 278 279 current_line++; 280 281 if (current_line >= to) 282 break; 283 284 line_start = line_end + 1; 285 } 286 287 FREE (input); 288 #ifndef HISTORY_USE_MMAP 289 FREE (buffer); 290 #else 291 munmap (buffer, file_size); 292 #endif 293 294 return (0); 295 } 296 297 /* Truncate the history file FNAME, leaving only LINES trailing lines. 298 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno 299 on failure. */ 300 int 301 history_truncate_file (fname, lines) 302 const char *fname; 303 int lines; 304 { 305 char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */ 306 int file, chars_read, rv; 307 struct stat finfo; 308 size_t file_size; 309 310 buffer = (char *)NULL; 311 filename = history_filename (fname); 312 file = open (filename, O_RDONLY|O_BINARY, 0666); 313 rv = 0; 314 315 /* Don't try to truncate non-regular files. */ 316 if (file == -1 || fstat (file, &finfo) == -1) 317 { 318 rv = errno; 319 if (file != -1) 320 close (file); 321 goto truncate_exit; 322 } 323 324 if (S_ISREG (finfo.st_mode) == 0) 325 { 326 close (file); 327 #ifdef EFTYPE 328 rv = EFTYPE; 329 #else 330 rv = EINVAL; 331 #endif 332 goto truncate_exit; 333 } 334 335 file_size = (size_t)finfo.st_size; 336 337 /* check for overflow on very large files */ 338 if (file_size != finfo.st_size || file_size + 1 < file_size) 339 { 340 close (file); 341 #if defined (EFBIG) 342 rv = errno = EFBIG; 343 #elif defined (EOVERFLOW) 344 rv = errno = EOVERFLOW; 345 #else 346 rv = errno = EINVAL; 347 #endif 348 goto truncate_exit; 349 } 350 351 buffer = (char *)malloc (file_size + 1); 352 if (buffer == 0) 353 { 354 close (file); 355 goto truncate_exit; 356 } 357 358 chars_read = read (file, buffer, file_size); 359 close (file); 360 361 if (chars_read <= 0) 362 { 363 rv = (chars_read < 0) ? errno : 0; 364 goto truncate_exit; 365 } 366 367 /* Count backwards from the end of buffer until we have passed 368 LINES lines. bp1 is set funny initially. But since bp[1] can't 369 be a comment character (since it's off the end) and *bp can't be 370 both a newline and the history comment character, it should be OK. */ 371 for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--) 372 { 373 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0) 374 lines--; 375 bp1 = bp; 376 } 377 378 /* If this is the first line, then the file contains exactly the 379 number of lines we want to truncate to, so we don't need to do 380 anything. It's the first line if we don't find a newline between 381 the current value of i and 0. Otherwise, write from the start of 382 this line until the end of the buffer. */ 383 for ( ; bp > buffer; bp--) 384 { 385 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0) 386 { 387 bp++; 388 break; 389 } 390 bp1 = bp; 391 } 392 393 /* Write only if there are more lines in the file than we want to 394 truncate to. */ 395 if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) 396 { 397 write (file, bp, chars_read - (bp - buffer)); 398 399 #if defined (__BEOS__) 400 /* BeOS ignores O_TRUNC. */ 401 ftruncate (file, chars_read - (bp - buffer)); 402 #endif 403 404 close (file); 405 } 406 407 truncate_exit: 408 409 FREE (buffer); 410 411 free (filename); 412 return rv; 413 } 414 415 /* Workhorse function for writing history. Writes NELEMENT entries 416 from the history list to FILENAME. OVERWRITE is non-zero if you 417 wish to replace FILENAME with the entries. */ 418 static int 419 history_do_write (filename, nelements, overwrite) 420 const char *filename; 421 int nelements, overwrite; 422 { 423 register int i; 424 char *output; 425 int file, mode, rv; 426 #ifdef HISTORY_USE_MMAP 427 size_t cursize; 428 429 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY; 430 #else 431 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY; 432 #endif 433 output = history_filename (filename); 434 rv = 0; 435 436 if ((file = open (output, mode, 0600)) == -1) 437 { 438 FREE (output); 439 return (errno); 440 } 441 442 #ifdef HISTORY_USE_MMAP 443 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END); 444 #endif 445 446 if (nelements > history_length) 447 nelements = history_length; 448 449 /* Build a buffer of all the lines to write, and write them in one syscall. 450 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */ 451 { 452 HIST_ENTRY **the_history; /* local */ 453 register int j; 454 int buffer_size; 455 char *buffer; 456 457 the_history = history_list (); 458 /* Calculate the total number of bytes to write. */ 459 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) 460 #if 0 461 buffer_size += 2 + HISTENT_BYTES (the_history[i]); 462 #else 463 { 464 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) 465 buffer_size += strlen (the_history[i]->timestamp) + 1; 466 buffer_size += strlen (the_history[i]->line) + 1; 467 } 468 #endif 469 470 /* Allocate the buffer, and fill it. */ 471 #ifdef HISTORY_USE_MMAP 472 if (ftruncate (file, buffer_size+cursize) == -1) 473 goto mmap_error; 474 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize); 475 if ((void *)buffer == MAP_FAILED) 476 { 477 mmap_error: 478 rv = errno; 479 FREE (output); 480 close (file); 481 return rv; 482 } 483 #else 484 buffer = (char *)malloc (buffer_size); 485 if (buffer == 0) 486 { 487 rv = errno; 488 FREE (output); 489 close (file); 490 return rv; 491 } 492 #endif 493 494 for (j = 0, i = history_length - nelements; i < history_length; i++) 495 { 496 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) 497 { 498 strcpy (buffer + j, the_history[i]->timestamp); 499 j += strlen (the_history[i]->timestamp); 500 buffer[j++] = '\n'; 501 } 502 strcpy (buffer + j, the_history[i]->line); 503 j += strlen (the_history[i]->line); 504 buffer[j++] = '\n'; 505 } 506 507 #ifdef HISTORY_USE_MMAP 508 if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0) 509 rv = errno; 510 #else 511 if (write (file, buffer, buffer_size) < 0) 512 rv = errno; 513 free (buffer); 514 #endif 515 } 516 517 close (file); 518 519 FREE (output); 520 521 return (rv); 522 } 523 524 /* Append NELEMENT entries to FILENAME. The entries appended are from 525 the end of the list minus NELEMENTs up to the end of the list. */ 526 int 527 append_history (nelements, filename) 528 int nelements; 529 const char *filename; 530 { 531 return (history_do_write (filename, nelements, HISTORY_APPEND)); 532 } 533 534 /* Overwrite FILENAME with the current history. If FILENAME is NULL, 535 then write the history list to ~/.history. Values returned 536 are as in read_history ().*/ 537 int 538 write_history (filename) 539 const char *filename; 540 { 541 return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); 542 }
Testing
