1 /* $OpenBSD: history.c,v 1.39 2010/05/19 17:36:08 jasper Exp $ */ 2 /* $OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $ */ 3 4 /*- 5 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 6 * 2011, 2012 7 * Thorsten Glaser <tg (at) mirbsd.org> 8 * 9 * Provided that these terms and disclaimer and all copyright notices 10 * are retained or reproduced in an accompanying document, permission 11 * is granted to deal in this work without restriction, including un- 12 * limited rights to use, publicly perform, distribute, sell, modify, 13 * merge, give away, or sublicence. 14 * 15 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 16 * the utmost extent permitted by applicable law, neither express nor 17 * implied; without malicious intent or gross negligence. In no event 18 * may a licensor, author or contributor be held liable for indirect, 19 * direct, other damage, loss, or other issues arising in any way out 20 * of dealing in the work, even if advised of the possibility of such 21 * damage or existence of a defect, except proven that it results out 22 * of said person's immediate fault when using the work as intended. 23 */ 24 25 #include "sh.h" 26 #if HAVE_SYS_FILE_H 27 #include <sys/file.h> 28 #endif 29 30 __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.131 2012/12/28 02:28:35 tg Exp $"); 31 32 Trap sigtraps[NSIG + 1]; 33 static struct sigaction Sigact_ign; 34 35 #if HAVE_PERSISTENT_HISTORY 36 static int histload(Source *, unsigned char *, size_t); 37 static int writehistline(int, int, const char *); 38 static void writehistfile(int, const char *); 39 #endif 40 41 static int hist_execute(char *); 42 static char **hist_get(const char *, bool, bool); 43 static char **hist_get_oldest(void); 44 45 static bool hstarted; /* set after hist_init() called */ 46 static Source *hist_source; 47 48 #if HAVE_PERSISTENT_HISTORY 49 /*XXX imake style */ 50 #if defined(__linux) 51 #define caddr_cast(x) ((void *)(x)) 52 #else 53 #define caddr_cast(x) ((caddr_t)(x)) 54 #endif 55 56 /* several OEs do not have these constants */ 57 #ifndef MAP_FAILED 58 #define MAP_FAILED caddr_cast(-1) 59 #endif 60 61 /* some OEs need the default mapping type specified */ 62 #ifndef MAP_FILE 63 #define MAP_FILE 0 64 #endif 65 66 /* current history file: name, fd, size */ 67 static char *hname; 68 static int histfd = -1; 69 static off_t histfsize; 70 #endif 71 72 static const char Tnot_in_history[] = "not in history"; 73 #define Thistory (Tnot_in_history + 7) 74 75 static const char TFCEDIT_dollaru[] = "${FCEDIT:-/bin/ed} $_"; 76 #define Tspdollaru (TFCEDIT_dollaru + 18) 77 78 /* HISTSIZE default: size of saved history, persistent or standard */ 79 #ifdef MKSH_SMALL 80 #define MKSH_DEFHISTSIZE 255 81 #else 82 #define MKSH_DEFHISTSIZE 2047 83 #endif 84 /* maximum considered size of persistent history file */ 85 #define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96) 86 87 int 88 c_fc(const char **wp) 89 { 90 struct shf *shf; 91 struct temp *tf; 92 bool gflag = false, lflag = false, nflag = false, rflag = false, 93 sflag = false; 94 int optc; 95 const char *p, *first = NULL, *last = NULL; 96 char **hfirst, **hlast, **hp, *editor = NULL; 97 98 if (!Flag(FTALKING_I)) { 99 bi_errorf("history %ss not available", Tfunction); 100 return (1); 101 } 102 103 while ((optc = ksh_getopt(wp, &builtin_opt, 104 "e:glnrs0,1,2,3,4,5,6,7,8,9,")) != -1) 105 switch (optc) { 106 107 case 'e': 108 p = builtin_opt.optarg; 109 if (ksh_isdash(p)) 110 sflag = true; 111 else { 112 size_t len = strlen(p); 113 114 /* almost certainly not overflowing */ 115 editor = alloc(len + 4, ATEMP); 116 memcpy(editor, p, len); 117 memcpy(editor + len, Tspdollaru, 4); 118 } 119 break; 120 121 /* non-AT&T ksh */ 122 case 'g': 123 gflag = true; 124 break; 125 126 case 'l': 127 lflag = true; 128 break; 129 130 case 'n': 131 nflag = true; 132 break; 133 134 case 'r': 135 rflag = true; 136 break; 137 138 /* POSIX version of -e - */ 139 case 's': 140 sflag = true; 141 break; 142 143 /* kludge city - accept -num as -- -num (kind of) */ 144 case '0': case '1': case '2': case '3': case '4': 145 case '5': case '6': case '7': case '8': case '9': 146 p = shf_smprintf("-%c%s", 147 optc, builtin_opt.optarg); 148 if (!first) 149 first = p; 150 else if (!last) 151 last = p; 152 else { 153 bi_errorf("too many arguments"); 154 return (1); 155 } 156 break; 157 158 case '?': 159 return (1); 160 } 161 wp += builtin_opt.optind; 162 163 /* Substitute and execute command */ 164 if (sflag) { 165 char *pat = NULL, *rep = NULL, *line; 166 167 if (editor || lflag || nflag || rflag) { 168 bi_errorf("can't use -e, -l, -n, -r with -s (-e -)"); 169 return (1); 170 } 171 172 /* Check for pattern replacement argument */ 173 if (*wp && **wp && (p = cstrchr(*wp + 1, '='))) { 174 strdupx(pat, *wp, ATEMP); 175 rep = pat + (p - *wp); 176 *rep++ = '\0'; 177 wp++; 178 } 179 /* Check for search prefix */ 180 if (!first && (first = *wp)) 181 wp++; 182 if (last || *wp) { 183 bi_errorf("too many arguments"); 184 return (1); 185 } 186 187 hp = first ? hist_get(first, false, false) : 188 hist_get_newest(false); 189 if (!hp) 190 return (1); 191 /* hist_replace */ 192 if (!pat) 193 strdupx(line, *hp, ATEMP); 194 else { 195 char *s, *s1; 196 size_t len, pat_len, rep_len; 197 XString xs; 198 char *xp; 199 bool any_subst = false; 200 201 pat_len = strlen(pat); 202 rep_len = strlen(rep); 203 Xinit(xs, xp, 128, ATEMP); 204 for (s = *hp; (s1 = strstr(s, pat)) && 205 (!any_subst || gflag); s = s1 + pat_len) { 206 any_subst = true; 207 len = s1 - s; 208 XcheckN(xs, xp, len + rep_len); 209 /*; first part */ 210 memcpy(xp, s, len); 211 xp += len; 212 /* replacement */ 213 memcpy(xp, rep, rep_len); 214 xp += rep_len; 215 } 216 if (!any_subst) { 217 bi_errorf("bad substitution"); 218 return (1); 219 } 220 len = strlen(s) + 1; 221 XcheckN(xs, xp, len); 222 memcpy(xp, s, len); 223 xp += len; 224 line = Xclose(xs, xp); 225 } 226 return (hist_execute(line)); 227 } 228 229 if (editor && (lflag || nflag)) { 230 bi_errorf("can't use -l, -n with -e"); 231 return (1); 232 } 233 234 if (!first && (first = *wp)) 235 wp++; 236 if (!last && (last = *wp)) 237 wp++; 238 if (*wp) { 239 bi_errorf("too many arguments"); 240 return (1); 241 } 242 if (!first) { 243 hfirst = lflag ? hist_get("-16", true, true) : 244 hist_get_newest(false); 245 if (!hfirst) 246 return (1); 247 /* can't fail if hfirst didn't fail */ 248 hlast = hist_get_newest(false); 249 } else { 250 /* 251 * POSIX says not an error if first/last out of bounds 252 * when range is specified; AT&T ksh and pdksh allow out 253 * of bounds for -l as well. 254 */ 255 hfirst = hist_get(first, tobool(lflag || last), lflag); 256 if (!hfirst) 257 return (1); 258 hlast = last ? hist_get(last, true, lflag) : 259 (lflag ? hist_get_newest(false) : hfirst); 260 if (!hlast) 261 return (1); 262 } 263 if (hfirst > hlast) { 264 char **temp; 265 266 temp = hfirst; hfirst = hlast; hlast = temp; 267 /* POSIX */ 268 rflag = !rflag; 269 } 270 271 /* List history */ 272 if (lflag) { 273 char *s, *t; 274 275 for (hp = rflag ? hlast : hfirst; 276 hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) { 277 if (!nflag) 278 shf_fprintf(shl_stdout, "%d", 279 hist_source->line - (int)(histptr - hp)); 280 shf_putc('\t', shl_stdout); 281 /* print multi-line commands correctly */ 282 s = *hp; 283 while ((t = strchr(s, '\n'))) { 284 *t = '\0'; 285 shf_fprintf(shl_stdout, "%s\n\t", s); 286 *t++ = '\n'; 287 s = t; 288 } 289 shf_fprintf(shl_stdout, "%s\n", s); 290 } 291 shf_flush(shl_stdout); 292 return (0); 293 } 294 295 /* Run editor on selected lines, then run resulting commands */ 296 297 tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps); 298 if (!(shf = tf->shf)) { 299 bi_errorf("can't %s temporary file %s: %s", 300 "create", tf->tffn, cstrerror(errno)); 301 return (1); 302 } 303 for (hp = rflag ? hlast : hfirst; 304 hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) 305 shf_fprintf(shf, "%s\n", *hp); 306 if (shf_close(shf) == EOF) { 307 bi_errorf("can't %s temporary file %s: %s", 308 "write", tf->tffn, cstrerror(errno)); 309 return (1); 310 } 311 312 /* Ignore setstr errors here (arbitrary) */ 313 setstr(local("_", false), tf->tffn, KSH_RETURN_ERROR); 314 315 /* XXX: source should not get trashed by this.. */ 316 { 317 Source *sold = source; 318 int ret; 319 320 ret = command(editor ? editor : TFCEDIT_dollaru, 0); 321 source = sold; 322 if (ret) 323 return (ret); 324 } 325 326 { 327 struct stat statb; 328 XString xs; 329 char *xp; 330 ssize_t n; 331 332 if (!(shf = shf_open(tf->tffn, O_RDONLY, 0, 0))) { 333 bi_errorf("can't %s temporary file %s: %s", 334 "open", tf->tffn, cstrerror(errno)); 335 return (1); 336 } 337 338 if (stat(tf->tffn, &statb) < 0) 339 n = 128; 340 else if ((off_t)statb.st_size > MKSH_MAXHISTFSIZE) { 341 bi_errorf("%s %s too large: %lu", Thistory, 342 "file", (unsigned long)statb.st_size); 343 goto errout; 344 } else 345 n = (size_t)statb.st_size + 1; 346 Xinit(xs, xp, n, hist_source->areap); 347 while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) { 348 xp += n; 349 if (Xnleft(xs, xp) <= 0) 350 XcheckN(xs, xp, Xlength(xs, xp)); 351 } 352 if (n < 0) { 353 bi_errorf("can't %s temporary file %s: %s", 354 "read", tf->tffn, cstrerror(shf_errno(shf))); 355 errout: 356 shf_close(shf); 357 return (1); 358 } 359 shf_close(shf); 360 *xp = '\0'; 361 strip_nuls(Xstring(xs, xp), Xlength(xs, xp)); 362 return (hist_execute(Xstring(xs, xp))); 363 } 364 } 365 366 /* Save cmd in history, execute cmd (cmd gets trashed) */ 367 static int 368 hist_execute(char *cmd) 369 { 370 static int last_line = -1; 371 Source *sold; 372 int ret; 373 char *p, *q; 374 375 /* Back up over last histsave */ 376 if (histptr >= history && last_line != hist_source->line) { 377 hist_source->line--; 378 afree(*histptr, APERM); 379 histptr--; 380 last_line = hist_source->line; 381 } 382 383 for (p = cmd; p; p = q) { 384 if ((q = strchr(p, '\n'))) { 385 /* kill the newline */ 386 *q++ = '\0'; 387 if (!*q) 388 /* ignore trailing newline */ 389 q = NULL; 390 } 391 histsave(&hist_source->line, p, true, true); 392 393 /* POSIX doesn't say this is done... */ 394 shellf("%s\n", p); 395 if (q) 396 /* restore \n (trailing \n not restored) */ 397 q[-1] = '\n'; 398 } 399 400 /*- 401 * Commands are executed here instead of pushing them onto the 402 * input 'cause POSIX says the redirection and variable assignments 403 * in 404 * X=y fc -e - 42 2> /dev/null 405 * are to effect the repeated commands environment. 406 */ 407 /* XXX: source should not get trashed by this.. */ 408 sold = source; 409 ret = command(cmd, 0); 410 source = sold; 411 return (ret); 412 } 413 414 /* 415 * get pointer to history given pattern 416 * pattern is a number or string 417 */ 418 static char ** 419 hist_get(const char *str, bool approx, bool allow_cur) 420 { 421 char **hp = NULL; 422 int n; 423 424 if (getn(str, &n)) { 425 hp = histptr + (n < 0 ? n : (n - hist_source->line)); 426 if ((ptrdiff_t)hp < (ptrdiff_t)history) { 427 if (approx) 428 hp = hist_get_oldest(); 429 else { 430 bi_errorf("%s: %s", str, Tnot_in_history); 431 hp = NULL; 432 } 433 } else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) { 434 if (approx) 435 hp = hist_get_newest(allow_cur); 436 else { 437 bi_errorf("%s: %s", str, Tnot_in_history); 438 hp = NULL; 439 } 440 } else if (!allow_cur && hp == histptr) { 441 bi_errorf("%s: %s", str, "invalid range"); 442 hp = NULL; 443 } 444 } else { 445 int anchored = *str == '?' ? (++str, 0) : 1; 446 447 /* the -1 is to avoid the current fc command */ 448 if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0) 449 bi_errorf("%s: %s", str, Tnot_in_history); 450 else 451 hp = &history[n]; 452 } 453 return (hp); 454 } 455 456 /* Return a pointer to the newest command in the history */ 457 char ** 458 hist_get_newest(bool allow_cur) 459 { 460 if (histptr < history || (!allow_cur && histptr == history)) { 461 bi_errorf("no history (yet)"); 462 return (NULL); 463 } 464 return (allow_cur ? histptr : histptr - 1); 465 } 466 467 /* Return a pointer to the oldest command in the history */ 468 static char ** 469 hist_get_oldest(void) 470 { 471 if (histptr <= history) { 472 bi_errorf("no history (yet)"); 473 return (NULL); 474 } 475 return (history); 476 } 477 478 #if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI 479 /* current position in history[] */ 480 static char **current; 481 482 /* 483 * Return the current position. 484 */ 485 char ** 486 histpos(void) 487 { 488 return (current); 489 } 490 491 int 492 histnum(int n) 493 { 494 int last = histptr - history; 495 496 if (n < 0 || n >= last) { 497 current = histptr; 498 return (last); 499 } else { 500 current = &history[n]; 501 return (n); 502 } 503 } 504 #endif 505 506 /* 507 * This will become unnecessary if hist_get is modified to allow 508 * searching from positions other than the end, and in either 509 * direction. 510 */ 511 int 512 findhist(int start, int fwd, const char *str, int anchored) 513 { 514 char **hp; 515 int maxhist = histptr - history; 516 int incr = fwd ? 1 : -1; 517 size_t len = strlen(str); 518 519 if (start < 0 || start >= maxhist) 520 start = maxhist; 521 522 hp = &history[start]; 523 for (; hp >= history && hp <= histptr; hp += incr) 524 if ((anchored && strncmp(*hp, str, len) == 0) || 525 (!anchored && strstr(*hp, str))) 526 return (hp - history); 527 528 return (-1); 529 } 530 531 /* 532 * set history; this means reallocating the dataspace 533 */ 534 void 535 sethistsize(mksh_ari_t n) 536 { 537 if (n > 0 && n != histsize) { 538 int cursize = histptr - history; 539 540 /* save most recent history */ 541 if (n < cursize) { 542 memmove(history, histptr - n + 1, n * sizeof(char *)); 543 cursize = n - 1; 544 } 545 546 history = aresize2(history, n, sizeof(char *), APERM); 547 548 histsize = n; 549 histptr = history + cursize; 550 } 551 } 552 553 #if HAVE_PERSISTENT_HISTORY 554 /* 555 * set history file; this can mean reloading/resetting/starting 556 * history file maintenance 557 */ 558 void 559 sethistfile(const char *name) 560 { 561 /* if not started then nothing to do */ 562 if (hstarted == false) 563 return; 564 565 /* if the name is the same as the name we have */ 566 if (hname && strcmp(hname, name) == 0) 567 return; 568 569 /* 570 * it's a new name - possibly 571 */ 572 if (histfd != -1) { 573 /* yes the file is open */ 574 (void)close(histfd); 575 histfd = -1; 576 histfsize = 0; 577 afree(hname, APERM); 578 hname = NULL; 579 /* let's reset the history */ 580 histptr = history - 1; 581 hist_source->line = 0; 582 } 583 584 hist_init(hist_source); 585 } 586 #endif 587 588 /* 589 * initialise the history vector 590 */ 591 void 592 init_histvec(void) 593 { 594 if (history == (char **)NULL) { 595 histsize = MKSH_DEFHISTSIZE; 596 history = alloc2(histsize, sizeof(char *), APERM); 597 histptr = history - 1; 598 } 599 } 600 601 602 /* 603 * It turns out that there is a lot of ghastly hackery here 604 */ 605 606 #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY 607 /* do not save command in history but possibly sync */ 608 bool 609 histsync(void) 610 { 611 bool changed = false; 612 613 if (histfd != -1) { 614 int lno = hist_source->line; 615 616 hist_source->line++; 617 writehistfile(0, NULL); 618 hist_source->line--; 619 620 if (lno != hist_source->line) 621 changed = true; 622 } 623 624 return (changed); 625 } 626 #endif 627 628 /* 629 * save command in history 630 */ 631 void 632 histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups) 633 { 634 char **hp; 635 char *c, *cp; 636 637 mkssert(cmd != NULL); 638 strdupx(c, cmd, APERM); 639 if ((cp = strchr(c, '\n')) != NULL) 640 *cp = '\0'; 641 642 if (ignoredups && !strcmp(c, *histptr) 643 #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY 644 && !histsync() 645 #endif 646 ) { 647 afree(c, APERM); 648 return; 649 } 650 ++*lnp; 651 652 #if HAVE_PERSISTENT_HISTORY 653 if (dowrite && histfd != -1) 654 writehistfile(*lnp, c); 655 #endif 656 657 hp = histptr; 658 659 if (++hp >= history + histsize) { 660 /* remove oldest command */ 661 afree(*history, APERM); 662 for (hp = history; hp < history + histsize - 1; hp++) 663 hp[0] = hp[1]; 664 } 665 *hp = c; 666 histptr = hp; 667 } 668 669 /* 670 * Write history data to a file nominated by HISTFILE; 671 * if HISTFILE is unset then history still happens, but 672 * the data is not written to a file. All copies of ksh 673 * looking at the file will maintain the same history. 674 * This is ksh behaviour. 675 * 676 * This stuff uses mmap() 677 * 678 * This stuff is so totally broken it must eventually be 679 * redesigned, without mmap, better checks, support for 680 * larger files, etc. and handle partially corrupted files 681 */ 682 683 /*- 684 * Open a history file 685 * Format is: 686 * Bytes 1, 2: 687 * HMAGIC - just to check that we are dealing with the correct object 688 * Then follows a number of stored commands 689 * Each command is 690 * <command byte><command number(4 octets, big endian)><bytes><NUL> 691 */ 692 #define HMAGIC1 0xAB 693 #define HMAGIC2 0xCD 694 #define COMMAND 0xFF 695 696 #if HAVE_PERSISTENT_HISTORY 697 static const unsigned char sprinkle[2] = { HMAGIC1, HMAGIC2 }; 698 #endif 699 700 void 701 hist_init(Source *s) 702 { 703 #if HAVE_PERSISTENT_HISTORY 704 unsigned char *base; 705 int lines, fd; 706 enum { hist_init_first, hist_init_retry, hist_init_restore } hs; 707 #endif 708 709 if (Flag(FTALKING) == 0) 710 return; 711 712 hstarted = true; 713 hist_source = s; 714 715 #if HAVE_PERSISTENT_HISTORY 716 if ((hname = str_val(global("HISTFILE"))) == NULL) 717 return; 718 strdupx(hname, hname, APERM); 719 hs = hist_init_first; 720 721 retry: 722 /* we have a file and are interactive */ 723 if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND, 0600)) < 0) 724 return; 725 726 histfd = savefd(fd); 727 if (histfd != fd) 728 close(fd); 729 730 mksh_lockfd(histfd); 731 732 histfsize = lseek(histfd, (off_t)0, SEEK_END); 733 if (histfsize > MKSH_MAXHISTFSIZE || hs == hist_init_restore) { 734 /* we ignore too large files but still append to them */ 735 /* we also don't need to re-read after truncation */ 736 goto hist_init_tail; 737 } else if (histfsize > 2) { 738 /* we have some data, check its validity */ 739 base = (void *)mmap(NULL, (size_t)histfsize, PROT_READ, 740 MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 741 if (base == (unsigned char *)MAP_FAILED) 742 goto hist_init_fail; 743 if (base[0] != HMAGIC1 || base[1] != HMAGIC2) { 744 munmap(caddr_cast(base), (size_t)histfsize); 745 goto hist_init_fail; 746 } 747 /* load _all_ data */ 748 lines = histload(hist_source, base + 2, (size_t)histfsize - 2); 749 munmap(caddr_cast(base), (size_t)histfsize); 750 /* check if the file needs to be truncated */ 751 if (lines > histsize && histptr >= history) { 752 /* you're fucked up with the current code, trust me */ 753 char *nhname, **hp; 754 struct stat sb; 755 756 /* create temporary file */ 757 nhname = shf_smprintf("%s.%d", hname, (int)procpid); 758 if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC | 759 O_EXCL, 0600)) < 0) { 760 /* just don't truncate then, meh. */ 761 goto hist_trunc_dont; 762 } 763 if (fstat(histfd, &sb) >= 0 && 764 chown(nhname, sb.st_uid, sb.st_gid)) { 765 /* abort the truncation then, meh. */ 766 goto hist_trunc_abort; 767 } 768 /* we definitively want some magic in that file */ 769 if (write(fd, sprinkle, 2) != 2) 770 goto hist_trunc_abort; 771 /* and of course the entries */ 772 hp = history; 773 while (hp < histptr) { 774 if (!writehistline(fd, 775 s->line - (histptr - hp), *hp)) 776 goto hist_trunc_abort; 777 ++hp; 778 } 779 /* now unlock, close both, rename, rinse, repeat */ 780 close(fd); 781 fd = -1; 782 hist_finish(); 783 if (rename(nhname, hname) < 0) { 784 hist_trunc_abort: 785 if (fd != -1) 786 close(fd); 787 unlink(nhname); 788 if (fd != -1) 789 goto hist_trunc_dont; 790 /* darn! restore histfd and pray */ 791 } 792 hs = hist_init_restore; 793 hist_trunc_dont: 794 afree(nhname, ATEMP); 795 if (hs == hist_init_restore) 796 goto retry; 797 } 798 } else if (histfsize != 0) { 799 /* negative or too small... */ 800 hist_init_fail: 801 /* ... or mmap failed or illegal */ 802 hist_finish(); 803 /* nuke the bogus file then retry, at most once */ 804 if (!unlink(hname) && hs != hist_init_retry) { 805 hs = hist_init_retry; 806 goto retry; 807 } 808 if (hs != hist_init_retry) 809 bi_errorf("can't %s %s: %s", 810 "unlink HISTFILE", hname, cstrerror(errno)); 811 histfsize = 0; 812 return; 813 } else { 814 /* size 0, add magic to the history file */ 815 if (write(histfd, sprinkle, 2) != 2) { 816 hist_finish(); 817 return; 818 } 819 } 820 histfsize = lseek(histfd, (off_t)0, SEEK_END); 821 hist_init_tail: 822 mksh_unlkfd(histfd); 823 #endif 824 } 825 826 #if HAVE_PERSISTENT_HISTORY 827 /* 828 * load the history structure from the stored data 829 */ 830 static int 831 histload(Source *s, unsigned char *base, size_t bytes) 832 { 833 int lno = 0, lines = 0; 834 unsigned char *cp; 835 836 histload_loop: 837 /* !bytes check as some systems (older FreeBSDs) have buggy memchr */ 838 if (!bytes || (cp = memchr(base, COMMAND, bytes)) == NULL) 839 return (lines); 840 /* advance base pointer past COMMAND byte */ 841 bytes -= ++cp - base; 842 base = cp; 843 /* if there is no full string left, don't bother with the rest */ 844 if (bytes < 5 || (cp = memchr(base + 4, '\0', bytes - 4)) == NULL) 845 return (lines); 846 /* load the stored line number */ 847 lno = ((base[0] & 0xFF) << 24) | ((base[1] & 0xFF) << 16) | 848 ((base[2] & 0xFF) << 8) | (base[3] & 0xFF); 849 /* store away the found line (@base[4]) */ 850 ++lines; 851 if (histptr >= history && lno - 1 != s->line) { 852 /* a replacement? */ 853 char **hp; 854 855 if (lno >= s->line - (histptr - history) && lno <= s->line) { 856 hp = &histptr[lno - s->line]; 857 if (*hp) 858 afree(*hp, APERM); 859 strdupx(*hp, (char *)(base + 4), APERM); 860 } 861 } else { 862 s->line = lno--; 863 histsave(&lno, (char *)(base + 4), false, false); 864 } 865 /* advance base pointer past NUL */ 866 bytes -= ++cp - base; 867 base = cp; 868 /* repeat until no more */ 869 goto histload_loop; 870 } 871 872 /* 873 * write a command to the end of the history file 874 * 875 * This *MAY* seem easy but it's also necessary to check 876 * that the history file has not changed in size. 877 * If it has - then some other shell has written to it and 878 * we should (re)read those commands to update our history 879 */ 880 static void 881 writehistfile(int lno, const char *cmd) 882 { 883 off_t sizenow; 884 size_t bytes; 885 unsigned char *base, *news; 886 887 mksh_lockfd(histfd); 888 sizenow = lseek(histfd, (off_t)0, SEEK_END); 889 if (sizenow < histfsize) { 890 /* the file has shrunk; give up */ 891 goto bad; 892 } 893 if ( 894 /* ignore changes when the file is too large */ 895 sizenow <= MKSH_MAXHISTFSIZE 896 && 897 /* the size has changed, we need to do read updates */ 898 sizenow > histfsize 899 ) { 900 /* both sizenow and histfsize are <= MKSH_MAXHISTFSIZE */ 901 bytes = (size_t)(sizenow - histfsize); 902 base = (void *)mmap(NULL, (size_t)sizenow, PROT_READ, 903 MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 904 if (base == (unsigned char *)MAP_FAILED) 905 goto bad; 906 news = base + (size_t)histfsize; 907 if (*news == COMMAND) { 908 hist_source->line--; 909 histload(hist_source, news, bytes); 910 hist_source->line++; 911 lno = hist_source->line; 912 } else 913 bytes = 0; 914 munmap(caddr_cast(base), (size_t)sizenow); 915 if (!bytes) 916 goto bad; 917 } 918 if (cmd && !writehistline(histfd, lno, cmd)) { 919 bad: 920 hist_finish(); 921 return; 922 } 923 histfsize = lseek(histfd, (off_t)0, SEEK_END); 924 mksh_unlkfd(histfd); 925 } 926 927 static int 928 writehistline(int fd, int lno, const char *cmd) 929 { 930 ssize_t n; 931 unsigned char hdr[5]; 932 933 hdr[0] = COMMAND; 934 hdr[1] = (lno >> 24) & 0xFF; 935 hdr[2] = (lno >> 16) & 0xFF; 936 hdr[3] = (lno >> 8) & 0xFF; 937 hdr[4] = lno & 0xFF; 938 n = strlen(cmd) + 1; 939 return (write(fd, hdr, 5) == 5 && write(fd, cmd, n) == n); 940 } 941 942 void 943 hist_finish(void) 944 { 945 if (histfd >= 0) { 946 mksh_unlkfd(histfd); 947 (void)close(histfd); 948 } 949 histfd = -1; 950 } 951 #endif 952 953 954 #if !HAVE_SYS_SIGNAME 955 static const struct mksh_sigpair { 956 const char * const name; 957 int nr; 958 } mksh_sigpairs[] = { 959 #include "signames.inc" 960 { NULL, 0 } 961 }; 962 #endif 963 964 #if HAVE_SYS_SIGLIST 965 #if !HAVE_SYS_SIGLIST_DECL 966 extern const char * const sys_siglist[]; 967 #endif 968 #endif 969 970 void 971 inittraps(void) 972 { 973 int i; 974 const char *cs; 975 976 trap_exstat = -1; 977 978 /* Populate sigtraps based on sys_signame and sys_siglist. */ 979 for (i = 0; i <= NSIG; i++) { 980 sigtraps[i].signal = i; 981 if (i == ksh_SIGERR) { 982 sigtraps[i].name = "ERR"; 983 sigtraps[i].mess = "Error handler"; 984 } else { 985 #if HAVE_SYS_SIGNAME 986 cs = sys_signame[i]; 987 #else 988 const struct mksh_sigpair *pair = mksh_sigpairs; 989 while ((pair->nr != i) && (pair->name != NULL)) 990 ++pair; 991 cs = pair->name; 992 #endif 993 if ((cs == NULL) || 994 (cs[0] == '\0')) 995 sigtraps[i].name = shf_smprintf("%d", i); 996 else { 997 char *s; 998 999 /* this is not optimal, what about SIGSIG1? */ 1000 if ((cs[0] & 0xDF) == 'S' && 1001 (cs[1] & 0xDF) == 'I' && 1002 (cs[2] & 0xDF) == 'G' && 1003 cs[3] != '\0') { 1004 /* skip leading "SIG" */ 1005 cs += 3; 1006 } 1007 strdupx(s, cs, APERM); 1008 sigtraps[i].name = s; 1009 while ((*s = ksh_toupper(*s))) 1010 ++s; 1011 } 1012 #if HAVE_SYS_SIGLIST 1013 sigtraps[i].mess = sys_siglist[i]; 1014 #elif HAVE_STRSIGNAL 1015 sigtraps[i].mess = strsignal(i); 1016 #else 1017 sigtraps[i].mess = NULL; 1018 #endif 1019 if ((sigtraps[i].mess == NULL) || 1020 (sigtraps[i].mess[0] == '\0')) 1021 sigtraps[i].mess = shf_smprintf("%s %d", 1022 "Signal", i); 1023 } 1024 } 1025 /* our name for signal 0 */ 1026 sigtraps[ksh_SIGEXIT].name = "EXIT"; 1027 1028 (void)sigemptyset(&Sigact_ign.sa_mask); 1029 Sigact_ign.sa_flags = 0; /* interruptible */ 1030 Sigact_ign.sa_handler = SIG_IGN; 1031 1032 sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR; 1033 sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR; 1034 /* SIGTERM is not fatal for interactive */ 1035 sigtraps[SIGTERM].flags |= TF_DFL_INTR; 1036 sigtraps[SIGHUP].flags |= TF_FATAL; 1037 sigtraps[SIGCHLD].flags |= TF_SHELL_USES; 1038 1039 /* these are always caught so we can clean up any temporary files. */ 1040 setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG); 1041 setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG); 1042 setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG); 1043 setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG); 1044 } 1045 1046 static void alarm_catcher(int sig); 1047 1048 void 1049 alarm_init(void) 1050 { 1051 sigtraps[SIGALRM].flags |= TF_SHELL_USES; 1052 setsig(&sigtraps[SIGALRM], alarm_catcher, 1053 SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 1054 } 1055 1056 /* ARGSUSED */ 1057 static void 1058 alarm_catcher(int sig MKSH_A_UNUSED) 1059 { 1060 /* this runs inside interrupt context, with errno saved */ 1061 1062 if (ksh_tmout_state == TMOUT_READING) { 1063 int left = alarm(0); 1064 1065 if (left == 0) { 1066 ksh_tmout_state = TMOUT_LEAVING; 1067 intrsig = 1; 1068 } else 1069 alarm(left); 1070 } 1071 } 1072 1073 Trap * 1074 gettrap(const char *cs, bool igncase) 1075 { 1076 int i; 1077 Trap *p; 1078 char *as; 1079 1080 if (ksh_isdigit(*cs)) { 1081 return ((getn(cs, &i) && 0 <= i && i < NSIG) ? 1082 (&sigtraps[i]) : NULL); 1083 } 1084 1085 /* this breaks SIGSIG1, but we do that above anyway */ 1086 if ((cs[0] & 0xDF) == 'S' && 1087 (cs[1] & 0xDF) == 'I' && 1088 (cs[2] & 0xDF) == 'G' && 1089 cs[3] != '\0') { 1090 /* skip leading "SIG" */ 1091 cs += 3; 1092 } 1093 if (igncase) { 1094 char *s; 1095 1096 strdupx(as, cs, ATEMP); 1097 cs = s = as; 1098 while ((*s = ksh_toupper(*s))) 1099 ++s; 1100 } else 1101 as = NULL; 1102 1103 p = sigtraps; 1104 for (i = 0; i <= NSIG; i++) { 1105 if (!strcmp(p->name, cs)) 1106 goto found; 1107 ++p; 1108 } 1109 p = NULL; 1110 found: 1111 afree(as, ATEMP); 1112 return (p); 1113 } 1114 1115 /* 1116 * trap signal handler 1117 */ 1118 void 1119 trapsig(int i) 1120 { 1121 Trap *p = &sigtraps[i]; 1122 int eno = errno; 1123 1124 trap = p->set = 1; 1125 if (p->flags & TF_DFL_INTR) 1126 intrsig = 1; 1127 if ((p->flags & TF_FATAL) && !p->trap) { 1128 fatal_trap = 1; 1129 intrsig = 1; 1130 } 1131 if (p->shtrap) 1132 (*p->shtrap)(i); 1133 errno = eno; 1134 } 1135 1136 /* 1137 * called when we want to allow the user to ^C out of something - won't 1138 * work if user has trapped SIGINT. 1139 */ 1140 void 1141 intrcheck(void) 1142 { 1143 if (intrsig) 1144 runtraps(TF_DFL_INTR|TF_FATAL); 1145 } 1146 1147 /* 1148 * called after EINTR to check if a signal with normally causes process 1149 * termination has been received. 1150 */ 1151 int 1152 fatal_trap_check(void) 1153 { 1154 int i; 1155 Trap *p; 1156 1157 /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */ 1158 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 1159 if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL))) 1160 /* return value is used as an exit code */ 1161 return (128 + p->signal); 1162 return (0); 1163 } 1164 1165 /* 1166 * Returns the signal number of any pending traps: ie, a signal which has 1167 * occurred for which a trap has been set or for which the TF_DFL_INTR flag 1168 * is set. 1169 */ 1170 int 1171 trap_pending(void) 1172 { 1173 int i; 1174 Trap *p; 1175 1176 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 1177 if (p->set && ((p->trap && p->trap[0]) || 1178 ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap))) 1179 return (p->signal); 1180 return (0); 1181 } 1182 1183 /* 1184 * run any pending traps. If intr is set, only run traps that 1185 * can interrupt commands. 1186 */ 1187 void 1188 runtraps(int flag) 1189 { 1190 int i; 1191 Trap *p; 1192 1193 if (ksh_tmout_state == TMOUT_LEAVING) { 1194 ksh_tmout_state = TMOUT_EXECUTING; 1195 warningf(false, "timed out waiting for input"); 1196 unwind(LEXIT); 1197 } else 1198 /* 1199 * XXX: this means the alarm will have no effect if a trap 1200 * is caught after the alarm() was started...not good. 1201 */ 1202 ksh_tmout_state = TMOUT_EXECUTING; 1203 if (!flag) 1204 trap = 0; 1205 if (flag & TF_DFL_INTR) 1206 intrsig = 0; 1207 if (flag & TF_FATAL) 1208 fatal_trap = 0; 1209 ++trap_nested; 1210 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 1211 if (p->set && (!flag || 1212 ((p->flags & flag) && p->trap == NULL))) 1213 runtrap(p, false); 1214 if (!--trap_nested) 1215 runtrap(NULL, true); 1216 } 1217 1218 void 1219 runtrap(Trap *p, bool is_last) 1220 { 1221 int old_changed = 0, i; 1222 char *trapstr; 1223 1224 if (p == NULL) 1225 /* just clean up, see runtraps() above */ 1226 goto donetrap; 1227 i = p->signal; 1228 trapstr = p->trap; 1229 p->set = 0; 1230 if (trapstr == NULL) { 1231 /* SIG_DFL */ 1232 if (p->flags & TF_FATAL) { 1233 /* eg, SIGHUP */ 1234 exstat = (int)ksh_min(128U + (unsigned)i, 255U); 1235 unwind(LLEAVE); 1236 } 1237 if (p->flags & TF_DFL_INTR) { 1238 /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */ 1239 exstat = (int)ksh_min(128U + (unsigned)i, 255U); 1240 unwind(LINTR); 1241 } 1242 goto donetrap; 1243 } 1244 if (trapstr[0] == '\0') 1245 /* SIG_IGN */ 1246 goto donetrap; 1247 if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 1248 /* avoid recursion on these */ 1249 old_changed = p->flags & TF_CHANGED; 1250 p->flags &= ~TF_CHANGED; 1251 p->trap = NULL; 1252 } 1253 if (trap_exstat == -1) 1254 trap_exstat = exstat & 0xFF; 1255 /* 1256 * Note: trapstr is fully parsed before anything is executed, thus 1257 * no problem with afree(p->trap) in settrap() while still in use. 1258 */ 1259 command(trapstr, current_lineno); 1260 if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 1261 if (p->flags & TF_CHANGED) 1262 /* don't clear TF_CHANGED */ 1263 afree(trapstr, APERM); 1264 else 1265 p->trap = trapstr; 1266 p->flags |= old_changed; 1267 } 1268 1269 donetrap: 1270 /* we're the last trap of a sequence executed */ 1271 if (is_last && trap_exstat != -1) { 1272 exstat = trap_exstat; 1273 trap_exstat = -1; 1274 } 1275 } 1276 1277 /* clear pending traps and reset user's trap handlers; used after fork(2) */ 1278 void 1279 cleartraps(void) 1280 { 1281 int i; 1282 Trap *p; 1283 1284 trap = 0; 1285 intrsig = 0; 1286 fatal_trap = 0; 1287 for (i = NSIG+1, p = sigtraps; --i >= 0; p++) { 1288 p->set = 0; 1289 if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) 1290 settrap(p, NULL); 1291 } 1292 } 1293 1294 /* restore signals just before an exec(2) */ 1295 void 1296 restoresigs(void) 1297 { 1298 int i; 1299 Trap *p; 1300 1301 for (i = NSIG+1, p = sigtraps; --i >= 0; p++) 1302 if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL)) 1303 setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL, 1304 SS_RESTORE_CURR|SS_FORCE); 1305 } 1306 1307 void 1308 settrap(Trap *p, const char *s) 1309 { 1310 sig_t f; 1311 1312 if (p->trap) 1313 afree(p->trap, APERM); 1314 /* handles s == NULL */ 1315 strdupx(p->trap, s, APERM); 1316 p->flags |= TF_CHANGED; 1317 f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN; 1318 1319 p->flags |= TF_USER_SET; 1320 if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL) 1321 f = trapsig; 1322 else if (p->flags & TF_SHELL_USES) { 1323 if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) { 1324 /* do what user wants at exec time */ 1325 p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 1326 if (f == SIG_IGN) 1327 p->flags |= TF_EXEC_IGN; 1328 else 1329 p->flags |= TF_EXEC_DFL; 1330 } 1331 1332 /* 1333 * assumes handler already set to what shell wants it 1334 * (normally trapsig, but could be j_sigchld() or SIG_IGN) 1335 */ 1336 return; 1337 } 1338 1339 /* todo: should we let user know signal is ignored? how? */ 1340 setsig(p, f, SS_RESTORE_CURR|SS_USER); 1341 } 1342 1343 /* 1344 * Called by c_print() when writing to a co-process to ensure SIGPIPE won't 1345 * kill shell (unless user catches it and exits) 1346 */ 1347 int 1348 block_pipe(void) 1349 { 1350 int restore_dfl = 0; 1351 Trap *p = &sigtraps[SIGPIPE]; 1352 1353 if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 1354 setsig(p, SIG_IGN, SS_RESTORE_CURR); 1355 if (p->flags & TF_ORIG_DFL) 1356 restore_dfl = 1; 1357 } else if (p->cursig == SIG_DFL) { 1358 setsig(p, SIG_IGN, SS_RESTORE_CURR); 1359 /* restore to SIG_DFL */ 1360 restore_dfl = 1; 1361 } 1362 return (restore_dfl); 1363 } 1364 1365 /* Called by c_print() to undo whatever block_pipe() did */ 1366 void 1367 restore_pipe(int restore_dfl) 1368 { 1369 if (restore_dfl) 1370 setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR); 1371 } 1372 1373 /* 1374 * Set action for a signal. Action may not be set if original 1375 * action was SIG_IGN, depending on the value of flags and FTALKING. 1376 */ 1377 int 1378 setsig(Trap *p, sig_t f, int flags) 1379 { 1380 struct sigaction sigact; 1381 1382 if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) 1383 return (1); 1384 1385 memset(&sigact, 0, sizeof(sigact)); 1386 1387 /* 1388 * First time setting this signal? If so, get and note the current 1389 * setting. 1390 */ 1391 if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 1392 sigaction(p->signal, &Sigact_ign, &sigact); 1393 p->flags |= sigact.sa_handler == SIG_IGN ? 1394 TF_ORIG_IGN : TF_ORIG_DFL; 1395 p->cursig = SIG_IGN; 1396 } 1397 1398 /*- 1399 * Generally, an ignored signal stays ignored, except if 1400 * - the user of an interactive shell wants to change it 1401 * - the shell wants for force a change 1402 */ 1403 if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE) && 1404 (!(flags & SS_USER) || !Flag(FTALKING))) 1405 return (0); 1406 1407 setexecsig(p, flags & SS_RESTORE_MASK); 1408 1409 /* 1410 * This is here 'cause there should be a way of clearing 1411 * shtraps, but don't know if this is a sane way of doing 1412 * it. At the moment, all users of shtrap are lifetime 1413 * users (SIGALRM, SIGCHLD, SIGWINCH). 1414 */ 1415 if (!(flags & SS_USER)) 1416 p->shtrap = (sig_t)NULL; 1417 if (flags & SS_SHTRAP) { 1418 p->shtrap = f; 1419 f = trapsig; 1420 } 1421 1422 if (p->cursig != f) { 1423 p->cursig = f; 1424 (void)sigemptyset(&sigact.sa_mask); 1425 /* interruptible */ 1426 sigact.sa_flags = 0; 1427 sigact.sa_handler = f; 1428 sigaction(p->signal, &sigact, NULL); 1429 } 1430 1431 return (1); 1432 } 1433 1434 /* control what signal is set to before an exec() */ 1435 void 1436 setexecsig(Trap *p, int restore) 1437 { 1438 /* XXX debugging */ 1439 if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) 1440 internal_errorf("setexecsig: unset signal %d(%s)", 1441 p->signal, p->name); 1442 1443 /* restore original value for exec'd kids */ 1444 p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 1445 switch (restore & SS_RESTORE_MASK) { 1446 case SS_RESTORE_CURR: 1447 /* leave things as they currently are */ 1448 break; 1449 case SS_RESTORE_ORIG: 1450 p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL; 1451 break; 1452 case SS_RESTORE_DFL: 1453 p->flags |= TF_EXEC_DFL; 1454 break; 1455 case SS_RESTORE_IGN: 1456 p->flags |= TF_EXEC_IGN; 1457 break; 1458 } 1459 } 1460 1461 #if HAVE_PERSISTENT_HISTORY || defined(DF) 1462 /* 1463 * File descriptor locking and unlocking functions. 1464 * Could use some error handling, but hey, this is only 1465 * advisory locking anyway, will often not work over NFS, 1466 * and you are SOL if this fails... 1467 */ 1468 1469 void 1470 mksh_lockfd(int fd) 1471 { 1472 #if defined(__OpenBSD__) 1473 /* flock is not interrupted by signals */ 1474 (void)flock(fd, LOCK_EX); 1475 #elif HAVE_FLOCK 1476 int rv; 1477 1478 /* e.g. on Linux */ 1479 do { 1480 rv = flock(fd, LOCK_EX); 1481 } while (rv == 1 && errno == EINTR); 1482 #elif HAVE_LOCK_FCNTL 1483 int rv; 1484 struct flock lks; 1485 1486 memset(&lks, 0, sizeof(lks)); 1487 lks.l_type = F_WRLCK; 1488 do { 1489 rv = fcntl(fd, F_SETLKW, &lks); 1490 } while (rv == 1 && errno == EINTR); 1491 #endif 1492 } 1493 1494 /* designed to not define mksh_unlkfd if none triggered */ 1495 #if HAVE_FLOCK 1496 void 1497 mksh_unlkfd(int fd) 1498 { 1499 (void)flock(fd, LOCK_UN); 1500 } 1501 #elif HAVE_LOCK_FCNTL 1502 void 1503 mksh_unlkfd(int fd) 1504 { 1505 struct flock lks; 1506 1507 memset(&lks, 0, sizeof(lks)); 1508 lks.l_type = F_UNLCK; 1509 (void)fcntl(fd, F_SETLKW, &lks); 1510 } 1511 #endif 1512 #endif 1513