1 /* $OpenBSD: main.c,v 1.51 2012/09/10 01:25:30 tedu Exp $ */ 2 /* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */ 3 /* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */ 4 /* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */ 5 6 /*- 7 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 8 * 2011, 2012, 2013 9 * Thorsten Glaser <tg (at) mirbsd.org> 10 * 11 * Provided that these terms and disclaimer and all copyright notices 12 * are retained or reproduced in an accompanying document, permission 13 * is granted to deal in this work without restriction, including un- 14 * limited rights to use, publicly perform, distribute, sell, modify, 15 * merge, give away, or sublicence. 16 * 17 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 18 * the utmost extent permitted by applicable law, neither express nor 19 * implied; without malicious intent or gross negligence. In no event 20 * may a licensor, author or contributor be held liable for indirect, 21 * direct, other damage, loss, or other issues arising in any way out 22 * of dealing in the work, even if advised of the possibility of such 23 * damage or existence of a defect, except proven that it results out 24 * of said person's immediate fault when using the work as intended. 25 */ 26 27 #define EXTERN 28 #include "sh.h" 29 30 #if HAVE_LANGINFO_CODESET 31 #include <langinfo.h> 32 #endif 33 #if HAVE_SETLOCALE_CTYPE 34 #include <locale.h> 35 #endif 36 37 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.260 2013/02/10 21:42:16 tg Exp $"); 38 39 extern char **environ; 40 41 #ifndef MKSHRC_PATH 42 #define MKSHRC_PATH "~/.mkshrc" 43 #endif 44 45 #ifndef MKSH_DEFAULT_TMPDIR 46 #define MKSH_DEFAULT_TMPDIR "/tmp" 47 #endif 48 49 static uint8_t isuc(const char *); 50 static int main_init(int, const char *[], Source **, struct block **); 51 void chvt_reinit(void); 52 static void reclaim(void); 53 static void remove_temps(struct temp *); 54 static mksh_uari_t rndsetup(void); 55 #ifdef SIGWINCH 56 static void x_sigwinch(int); 57 #endif 58 59 static const char initifs[] = "IFS= \t\n"; 60 61 static const char initsubs[] = 62 "${PS2=> } ${PS3=#? } ${PS4=+ } ${SECONDS=0} ${TMOUT=0} ${EPOCHREALTIME=}"; 63 64 static const char *initcoms[] = { 65 Ttypeset, "-r", initvsn, NULL, 66 Ttypeset, "-x", "HOME", "PATH", "RANDOM", "SHELL", NULL, 67 Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL, 68 Talias, 69 "integer=typeset -i", 70 Tlocal_typeset, 71 /* not "alias -t --": hash -r needs to work */ 72 "hash=alias -t", 73 "type=whence -v", 74 #if !defined(ANDROID) && !defined(MKSH_UNEMPLOYED) 75 /* not in Android for political reasons */ 76 /* not in ARGE mksh due to no job control */ 77 "stop=kill -STOP", 78 "suspend=kill -STOP $$", 79 #endif 80 "autoload=typeset -fu", 81 "functions=typeset -f", 82 "history=fc -l", 83 "nameref=typeset -n", 84 "nohup=nohup ", 85 Tr_fc_e_dash, 86 "source=PATH=$PATH:. command .", 87 "login=exec login", 88 NULL, 89 /* this is what AT&T ksh seems to track, with the addition of emacs */ 90 Talias, "-tU", 91 "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls", 92 "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL, 93 NULL 94 }; 95 96 static const char *restr_com[] = { 97 Ttypeset, "-r", "PATH", "ENV", "SHELL", NULL 98 }; 99 100 static bool initio_done; 101 102 /* top-level parsing and execution environment */ 103 static struct env env; 104 struct env *e = &env; 105 106 static mksh_uari_t 107 rndsetup(void) 108 { 109 register uint32_t h; 110 struct { 111 ALLOC_ITEM alloc_INT; 112 void *dataptr, *stkptr, *mallocptr; 113 #if defined(__GLIBC__) && (__GLIBC__ >= 2) 114 sigjmp_buf jbuf; 115 #endif 116 struct timeval tv; 117 } *bufptr; 118 char *cp; 119 120 cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM); 121 #ifdef DEBUG 122 /* clear the allocated space, for valgrind */ 123 memset(cp, 0, sizeof(*bufptr) - ALLOC_SIZE); 124 #endif 125 /* undo what alloc() did to the malloc result address */ 126 bufptr = (void *)(cp - ALLOC_SIZE); 127 /* PIE or something similar provides us with deltas here */ 128 bufptr->dataptr = &rndsetupstate; 129 /* ASLR in at least Windows, Linux, some BSDs */ 130 bufptr->stkptr = &bufptr; 131 /* randomised malloc in BSD (and possibly others) */ 132 bufptr->mallocptr = bufptr; 133 #if defined(__GLIBC__) && (__GLIBC__ >= 2) 134 /* glibc pointer guard */ 135 sigsetjmp(bufptr->jbuf, 1); 136 #endif 137 /* introduce variation (and yes, second arg MBZ for portability) */ 138 mksh_TIME(bufptr->tv); 139 140 NZATInit(h); 141 /* variation through pid, ppid, and the works */ 142 NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate)); 143 /* some variation, some possibly entropy, depending on OE */ 144 NZATUpdateMem(h, bufptr, sizeof(*bufptr)); 145 NZAATFinish(h); 146 147 afree(cp, APERM); 148 return ((mksh_uari_t)h); 149 } 150 151 void 152 chvt_reinit(void) 153 { 154 kshpid = procpid = getpid(); 155 ksheuid = geteuid(); 156 kshpgrp = getpgrp(); 157 kshppid = getppid(); 158 } 159 160 static const char *empty_argv[] = { 161 "mksh", NULL 162 }; 163 164 static uint8_t 165 isuc(const char *cx) { 166 char *cp, *x; 167 uint8_t rv = 0; 168 169 if (!cx || !*cx) 170 return (0); 171 172 /* uppercase a string duplicate */ 173 strdupx(x, cx, ATEMP); 174 cp = x; 175 while ((*cp = ksh_toupper(*cp))) 176 ++cp; 177 178 /* check for UTF-8 */ 179 if (strstr(x, "UTF-8") || strstr(x, "UTF8")) 180 rv = 1; 181 182 /* free copy and out */ 183 afree(x, ATEMP); 184 return (rv); 185 } 186 187 static int 188 main_init(int argc, const char *argv[], Source **sp, struct block **lp) 189 { 190 int argi, i; 191 Source *s = NULL; 192 struct block *l; 193 unsigned char restricted, errexit, utf_flag; 194 char *cp; 195 const char *ccp, **wp; 196 struct tbl *vp; 197 struct stat s_stdin; 198 #if !defined(_PATH_DEFPATH) && defined(_CS_PATH) 199 ssize_t k; 200 #endif 201 202 /* do things like getpgrp() et al. */ 203 chvt_reinit(); 204 205 /* make sure argv[] is sane */ 206 if (!*argv) { 207 argv = empty_argv; 208 argc = 1; 209 } 210 kshname = argv[0]; 211 212 /* initialise permanent Area */ 213 ainit(&aperm); 214 215 /* set up base environment */ 216 env.type = E_NONE; 217 ainit(&env.area); 218 /* set up global l->vars and l->funs */ 219 newblock(); 220 221 /* Do this first so output routines (eg, errorf, shellf) can work */ 222 initio(); 223 224 /* determine the basename (without '-' or path) of the executable */ 225 ccp = kshname; 226 goto begin_parse_kshname; 227 while ((i = ccp[argi++])) { 228 if (i == '/') { 229 ccp += argi; 230 begin_parse_kshname: 231 argi = 0; 232 if (*ccp == '-') 233 ++ccp; 234 } 235 } 236 if (!*ccp) 237 ccp = empty_argv[0]; 238 239 /* define built-in commands and see if we were called as one */ 240 ktinit(APERM, &builtins, 241 /* currently up to 50 builtins: 75% of 128 = 2^7 */ 242 7); 243 for (i = 0; mkshbuiltins[i].name != NULL; i++) 244 if (!strcmp(ccp, builtin(mkshbuiltins[i].name, 245 mkshbuiltins[i].func))) 246 Flag(FAS_BUILTIN) = 1; 247 248 if (!Flag(FAS_BUILTIN)) { 249 /* check for -T option early */ 250 argi = parse_args(argv, OF_FIRSTTIME, NULL); 251 if (argi < 0) 252 return (1); 253 254 #ifdef MKSH_BINSHREDUCED 255 /* set FSH if we're called as -sh or /bin/sh or so */ 256 if (!strcmp(ccp, "sh")) 257 change_flag(FSH, OF_FIRSTTIME, true); 258 #endif 259 } 260 261 initvar(); 262 263 initctypes(); 264 265 inittraps(); 266 267 coproc_init(); 268 269 /* set up variable and command dictionaries */ 270 ktinit(APERM, &taliases, 0); 271 ktinit(APERM, &aliases, 0); 272 #ifndef MKSH_NOPWNAM 273 ktinit(APERM, &homedirs, 0); 274 #endif 275 276 /* define shell keywords */ 277 initkeywords(); 278 279 init_histvec(); 280 281 /* initialise tty size before importing environment */ 282 change_winsz(); 283 284 #ifdef _PATH_DEFPATH 285 def_path = _PATH_DEFPATH; 286 #else 287 #ifdef _CS_PATH 288 if ((k = confstr(_CS_PATH, NULL, 0)) > 0 && 289 confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1) 290 def_path = cp; 291 else 292 #endif 293 /* 294 * this is uniform across all OSes unless it 295 * breaks somewhere; don't try to optimise, 296 * e.g. add stuff for Interix or remove /usr 297 * for HURD, because e.g. Debian GNU/HURD is 298 * "keeping a regular /usr"; this is supposed 299 * to be a sane 'basic' default PATH 300 */ 301 def_path = "/bin:/usr/bin:/sbin:/usr/sbin"; 302 #endif 303 304 /* 305 * Set PATH to def_path (will set the path global variable). 306 * (import of environment below will probably change this setting). 307 */ 308 vp = global("PATH"); 309 /* setstr can't fail here */ 310 setstr(vp, def_path, KSH_RETURN_ERROR); 311 312 /* 313 * Turn on nohup by default for now - will change to off 314 * by default once people are aware of its existence 315 * (AT&T ksh does not have a nohup option - it always sends 316 * the hup). 317 */ 318 Flag(FNOHUP) = 1; 319 320 /* 321 * Turn on brace expansion by default. AT&T kshs that have 322 * alternation always have it on. 323 */ 324 Flag(FBRACEEXPAND) = 1; 325 326 #ifndef MKSH_NO_CMDLINE_EDITING 327 /* 328 * Set edit mode to emacs by default, may be overridden 329 * by the environment or the user. Also, we want tab completion 330 * on in vi by default. 331 */ 332 change_flag(FEMACS, OF_SPECIAL, true); 333 #if !MKSH_S_NOVI 334 Flag(FVITABCOMPLETE) = 1; 335 #endif 336 #endif 337 338 /* import environment */ 339 if (environ != NULL) 340 for (wp = (const char **)environ; *wp != NULL; wp++) 341 typeset(*wp, IMPORT | EXPORT, 0, 0, 0); 342 343 /* for security */ 344 typeset(initifs, 0, 0, 0, 0); 345 346 /* assign default shell variable values */ 347 substitute(initsubs, 0); 348 349 /* Figure out the current working directory and set $PWD */ 350 vp = global("PWD"); 351 cp = str_val(vp); 352 /* Try to use existing $PWD if it is valid */ 353 set_current_wd((cp[0] == '/' && test_eval(NULL, TO_FILEQ, cp, ".", 354 true)) ? cp : NULL); 355 if (current_wd[0]) 356 simplify_path(current_wd); 357 /* Only set pwd if we know where we are or if it had a bogus value */ 358 if (current_wd[0] || *cp) 359 /* setstr can't fail here */ 360 setstr(vp, current_wd, KSH_RETURN_ERROR); 361 362 for (wp = initcoms; *wp != NULL; wp++) { 363 shcomexec(wp); 364 while (*wp != NULL) 365 wp++; 366 } 367 setint_n(global("OPTIND"), 1, 10); 368 369 kshuid = getuid(); 370 kshgid = getgid(); 371 kshegid = getegid(); 372 373 safe_prompt = ksheuid ? "$ " : "# "; 374 vp = global("PS1"); 375 /* Set PS1 if unset or we are root and prompt doesn't contain a # */ 376 if (!(vp->flag & ISSET) || 377 (!ksheuid && !strchr(str_val(vp), '#'))) 378 /* setstr can't fail here */ 379 setstr(vp, safe_prompt, KSH_RETURN_ERROR); 380 setint_n((vp = global("BASHPID")), 0, 10); 381 vp->flag |= INT_U; 382 setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10); 383 vp->flag |= INT_U; 384 setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10); 385 vp->flag |= INT_U; 386 setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10); 387 vp->flag |= INT_U; 388 setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10); 389 vp->flag |= INT_U; 390 setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10); 391 vp->flag |= INT_U; 392 setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10); 393 vp->flag |= INT_U; 394 setint_n((vp = global("RANDOM")), rndsetup(), 10); 395 vp->flag |= INT_U; 396 setint_n((vp_pipest = global("PIPESTATUS")), 0, 10); 397 398 /* Set this before parsing arguments */ 399 Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid; 400 401 /* this to note if monitor is set on command line (see below) */ 402 #ifndef MKSH_UNEMPLOYED 403 Flag(FMONITOR) = 127; 404 #endif 405 /* this to note if utf-8 mode is set on command line (see below) */ 406 UTFMODE = 2; 407 408 if (!Flag(FAS_BUILTIN)) { 409 argi = parse_args(argv, OF_CMDLINE, NULL); 410 if (argi < 0) 411 return (1); 412 } 413 414 #ifdef DEBUG 415 /* test wraparound of arithmetic types */ 416 { 417 volatile long xl; 418 volatile unsigned long xul; 419 volatile int xi; 420 volatile unsigned int xui; 421 volatile mksh_ari_t xa; 422 volatile mksh_uari_t xua, xua2; 423 volatile uint8_t xc; 424 425 xa = 2147483647; 426 xua = 2147483647; 427 ++xa; 428 ++xua; 429 xua2 = xa; 430 xl = xa; 431 xul = xua; 432 xa = 0; 433 xua = 0; 434 --xa; 435 --xua; 436 xi = xa; 437 xui = xua; 438 xa = -1; 439 xua = xa; 440 ++xa; 441 ++xua; 442 xc = 0; 443 --xc; 444 if ((xua2 != 2147483648UL) || 445 (xl != -2147483648L) || (xul != 2147483648UL) || 446 (xi != -1) || (xui != 4294967295U) || 447 (xa != 0) || (xua != 0) || (xc != 255)) 448 errorf("integer wraparound test failed"); 449 } 450 #endif 451 452 /* process this later only, default to off (hysterical raisins) */ 453 utf_flag = UTFMODE; 454 UTFMODE = 0; 455 456 if (Flag(FAS_BUILTIN)) { 457 /* auto-detect from environment variables, always */ 458 utf_flag = 3; 459 } else if (Flag(FCOMMAND)) { 460 s = pushs(SSTRINGCMDLINE, ATEMP); 461 if (!(s->start = s->str = argv[argi++])) 462 errorf("%s %s", "-c", "requires an argument"); 463 #if !defined(MKSH_SMALL) 464 while (*s->str) { 465 if (*s->str != ' ' && ctype(*s->str, C_QUOTE)) 466 break; 467 s->str++; 468 } 469 if (!*s->str) 470 s->flags |= SF_MAYEXEC; 471 s->str = s->start; 472 #endif 473 #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT 474 /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */ 475 if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--")) 476 ++argi; 477 #endif 478 if (argv[argi]) 479 kshname = argv[argi++]; 480 } else if (argi < argc && !Flag(FSTDIN)) { 481 s = pushs(SFILE, ATEMP); 482 s->file = argv[argi++]; 483 s->u.shf = shf_open(s->file, O_RDONLY, 0, 484 SHF_MAPHI | SHF_CLEXEC); 485 if (s->u.shf == NULL) { 486 shl_stdout_ok = false; 487 warningf(true, "%s: %s", s->file, cstrerror(errno)); 488 /* mandated by SUSv4 */ 489 exstat = 127; 490 unwind(LERROR); 491 } 492 kshname = s->file; 493 } else { 494 Flag(FSTDIN) = 1; 495 s = pushs(SSTDIN, ATEMP); 496 s->file = "<stdin>"; 497 s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), 498 NULL); 499 if (isatty(0) && isatty(2)) { 500 Flag(FTALKING) = Flag(FTALKING_I) = 1; 501 /* The following only if isatty(0) */ 502 s->flags |= SF_TTY; 503 s->u.shf->flags |= SHF_INTERRUPT; 504 s->file = NULL; 505 } 506 } 507 508 /* this bizarreness is mandated by POSIX */ 509 if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && 510 Flag(FTALKING)) 511 reset_nonblock(0); 512 513 /* initialise job control */ 514 j_init(); 515 /* do this after j_init() which calls tty_init_state() */ 516 if (Flag(FTALKING)) { 517 if (utf_flag == 2) { 518 #ifndef MKSH_ASSUME_UTF8 519 /* auto-detect from locale or environment */ 520 utf_flag = 4; 521 #elif MKSH_ASSUME_UTF8 522 utf_flag = 1; 523 #else 524 /* always disable UTF-8 (for interactive) */ 525 utf_flag = 0; 526 #endif 527 } 528 #ifndef MKSH_NO_CMDLINE_EDITING 529 x_init(); 530 #endif 531 } 532 533 #ifdef SIGWINCH 534 sigtraps[SIGWINCH].flags |= TF_SHELL_USES; 535 setsig(&sigtraps[SIGWINCH], x_sigwinch, 536 SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 537 #endif 538 539 l = e->loc; 540 if (Flag(FAS_BUILTIN)) { 541 l->argc = argc; 542 l->argv = argv; 543 l->argv[0] = ccp; 544 } else { 545 l->argc = argc - argi; 546 /* 547 * allocate a new array because otherwise, when we modify 548 * it in-place, ps(1) output changes; the meaning of argc 549 * here is slightly different as it excludes kshname, and 550 * we add a trailing NULL sentinel as well 551 */ 552 l->argv = alloc2(l->argc + 2, sizeof(void *), APERM); 553 l->argv[0] = kshname; 554 memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *)); 555 l->argv[l->argc + 1] = NULL; 556 getopts_reset(1); 557 } 558 559 /* divine the initial state of the utf8-mode Flag */ 560 ccp = null; 561 switch (utf_flag) { 562 563 /* auto-detect from locale or environment */ 564 case 4: 565 #if HAVE_SETLOCALE_CTYPE 566 ccp = setlocale(LC_CTYPE, ""); 567 #if HAVE_LANGINFO_CODESET 568 if (!isuc(ccp)) 569 ccp = nl_langinfo(CODESET); 570 #endif 571 if (!isuc(ccp)) 572 ccp = null; 573 /* FALLTHROUGH */ 574 #endif 575 576 /* auto-detect from environment */ 577 case 3: 578 /* these were imported from environ earlier */ 579 if (ccp == null) 580 ccp = str_val(global("LC_ALL")); 581 if (ccp == null) 582 ccp = str_val(global("LC_CTYPE")); 583 if (ccp == null) 584 ccp = str_val(global("LANG")); 585 UTFMODE = isuc(ccp); 586 break; 587 588 /* not set on command line, not FTALKING */ 589 case 2: 590 /* unknown values */ 591 default: 592 utf_flag = 0; 593 /* FALLTHROUGH */ 594 595 /* known values */ 596 case 1: 597 case 0: 598 UTFMODE = utf_flag; 599 break; 600 } 601 602 /* Disable during .profile/ENV reading */ 603 restricted = Flag(FRESTRICTED); 604 Flag(FRESTRICTED) = 0; 605 errexit = Flag(FERREXIT); 606 Flag(FERREXIT) = 0; 607 608 /* 609 * Do this before profile/$ENV so that if it causes problems in them, 610 * user will know why things broke. 611 */ 612 if (!current_wd[0] && Flag(FTALKING)) 613 warningf(false, "can't determine current directory"); 614 615 if (Flag(FLOGIN)) { 616 include(MKSH_SYSTEM_PROFILE, 0, NULL, true); 617 if (!Flag(FPRIVILEGED)) 618 include(substitute("$HOME/.profile", 0), 0, 619 NULL, true); 620 } 621 if (Flag(FPRIVILEGED)) 622 include(MKSH_SUID_PROFILE, 0, NULL, true); 623 else if (Flag(FTALKING)) { 624 char *env_file; 625 626 /* include $ENV */ 627 env_file = substitute(substitute("${ENV:-" MKSHRC_PATH "}", 0), 628 DOTILDE); 629 if (*env_file != '\0') 630 include(env_file, 0, NULL, true); 631 } 632 633 if (restricted) { 634 shcomexec(restr_com); 635 /* After typeset command... */ 636 Flag(FRESTRICTED) = 1; 637 } 638 Flag(FERREXIT) = errexit; 639 640 if (Flag(FTALKING) && s) 641 hist_init(s); 642 else 643 /* set after ENV */ 644 Flag(FTRACKALL) = 1; 645 646 alarm_init(); 647 648 *sp = s; 649 *lp = l; 650 return (0); 651 } 652 653 /* this indirection barrier reduces stack usage during normal operation */ 654 655 int 656 main(int argc, const char *argv[]) 657 { 658 int rv; 659 Source *s; 660 struct block *l; 661 662 if ((rv = main_init(argc, argv, &s, &l)) == 0) { 663 if (Flag(FAS_BUILTIN)) { 664 rv = shcomexec(l->argv); 665 } else { 666 shell(s, true); 667 /* NOTREACHED */ 668 } 669 } 670 return (rv); 671 } 672 673 int 674 include(const char *name, int argc, const char **argv, bool intr_ok) 675 { 676 Source *volatile s = NULL; 677 struct shf *shf; 678 const char **volatile old_argv; 679 volatile int old_argc; 680 int i; 681 682 shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); 683 if (shf == NULL) 684 return (-1); 685 686 if (argv) { 687 old_argv = e->loc->argv; 688 old_argc = e->loc->argc; 689 } else { 690 old_argv = NULL; 691 old_argc = 0; 692 } 693 newenv(E_INCL); 694 if ((i = kshsetjmp(e->jbuf))) { 695 quitenv(s ? s->u.shf : NULL); 696 if (old_argv) { 697 e->loc->argv = old_argv; 698 e->loc->argc = old_argc; 699 } 700 switch (i) { 701 case LRETURN: 702 case LERROR: 703 /* see below */ 704 return (exstat & 0xFF); 705 case LINTR: 706 /* 707 * intr_ok is set if we are including .profile or $ENV. 708 * If user ^Cs out, we don't want to kill the shell... 709 */ 710 if (intr_ok && ((exstat & 0xFF) - 128) != SIGTERM) 711 return (1); 712 /* FALLTHROUGH */ 713 case LEXIT: 714 case LLEAVE: 715 case LSHELL: 716 unwind(i); 717 /* NOTREACHED */ 718 default: 719 internal_errorf("%s %d", "include", i); 720 /* NOTREACHED */ 721 } 722 } 723 if (argv) { 724 e->loc->argv = argv; 725 e->loc->argc = argc; 726 } 727 s = pushs(SFILE, ATEMP); 728 s->u.shf = shf; 729 strdupx(s->file, name, ATEMP); 730 i = shell(s, false); 731 quitenv(s->u.shf); 732 if (old_argv) { 733 e->loc->argv = old_argv; 734 e->loc->argc = old_argc; 735 } 736 /* & 0xff to ensure value not -1 */ 737 return (i & 0xFF); 738 } 739 740 /* spawn a command into a shell optionally keeping track of the line number */ 741 int 742 command(const char *comm, int line) 743 { 744 Source *s; 745 746 s = pushs(SSTRING, ATEMP); 747 s->start = s->str = comm; 748 s->line = line; 749 return (shell(s, false)); 750 } 751 752 /* 753 * run the commands from the input source, returning status. 754 */ 755 int 756 shell(Source * volatile s, volatile bool toplevel) 757 { 758 struct op *t; 759 volatile bool wastty = tobool(s->flags & SF_TTY); 760 volatile uint8_t attempts = 13; 761 volatile bool interactive = Flag(FTALKING) && toplevel; 762 volatile bool sfirst = true; 763 Source *volatile old_source = source; 764 int i; 765 766 newenv(E_PARSE); 767 if (interactive) 768 really_exit = false; 769 switch ((i = kshsetjmp(e->jbuf))) { 770 case 0: 771 break; 772 case LINTR: 773 /* we get here if SIGINT not caught or ignored */ 774 case LERROR: 775 case LSHELL: 776 if (interactive) { 777 if (i == LINTR) 778 shellf("\n"); 779 /* 780 * Reset any eof that was read as part of a 781 * multiline command. 782 */ 783 if (Flag(FIGNOREEOF) && s->type == SEOF && wastty) 784 s->type = SSTDIN; 785 /* 786 * Used by exit command to get back to 787 * top level shell. Kind of strange since 788 * interactive is set if we are reading from 789 * a tty, but to have stopped jobs, one only 790 * needs FMONITOR set (not FTALKING/SF_TTY)... 791 */ 792 /* toss any input we have so far */ 793 yyrecursive_pop(true); 794 s->start = s->str = null; 795 retrace_info = NULL; 796 herep = heres; 797 break; 798 } 799 /* FALLTHROUGH */ 800 case LEXIT: 801 case LLEAVE: 802 case LRETURN: 803 source = old_source; 804 quitenv(NULL); 805 /* keep on going */ 806 unwind(i); 807 /* NOTREACHED */ 808 default: 809 source = old_source; 810 quitenv(NULL); 811 internal_errorf("%s %d", "shell", i); 812 /* NOTREACHED */ 813 } 814 while (/* CONSTCOND */ 1) { 815 if (trap) 816 runtraps(0); 817 818 if (s->next == NULL) { 819 if (Flag(FVERBOSE)) 820 s->flags |= SF_ECHO; 821 else 822 s->flags &= ~SF_ECHO; 823 } 824 if (interactive) { 825 j_notify(); 826 set_prompt(PS1, s); 827 } 828 t = compile(s, sfirst); 829 sfirst = false; 830 if (!t) 831 goto source_no_tree; 832 if (t->type == TEOF) { 833 if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { 834 shellf("Use 'exit' to leave mksh\n"); 835 s->type = SSTDIN; 836 } else if (wastty && !really_exit && 837 j_stopped_running()) { 838 really_exit = true; 839 s->type = SSTDIN; 840 } else { 841 /* 842 * this for POSIX which says EXIT traps 843 * shall be taken in the environment 844 * immediately after the last command 845 * executed. 846 */ 847 if (toplevel) 848 unwind(LEXIT); 849 break; 850 } 851 } 852 #if !defined(MKSH_SMALL) 853 else if ((s->flags & SF_MAYEXEC) && t->type == TCOM) 854 t->u.evalflags |= DOTCOMEXEC; 855 #endif 856 if (!Flag(FNOEXEC) || (s->flags & SF_TTY)) 857 exstat = execute(t, 0, NULL) & 0xFF; 858 859 if (t->type != TEOF && interactive && really_exit) 860 really_exit = false; 861 862 source_no_tree: 863 reclaim(); 864 } 865 quitenv(NULL); 866 source = old_source; 867 return (exstat & 0xFF); 868 } 869 870 /* return to closest error handler or shell(), exit if none found */ 871 /* note: i MUST NOT be 0 */ 872 void 873 unwind(int i) 874 { 875 /* 876 * This is a kludge. We need to restore everything that was 877 * changed in the new environment, see cid 1005090337C7A669439 878 * and 10050903386452ACBF1, but fail to even save things most of 879 * the time. funcs.c:c_eval() changes FERREXIT temporarily to 0, 880 * which needs to be restored thus (related to Debian #696823). 881 * We did not save the shell flags, so we use a special or'd 882 * value here... this is mostly to clean up behind *other* 883 * callers of unwind(LERROR) here; exec.c has the regular case. 884 */ 885 if (Flag(FERREXIT) & 0x80) { 886 /* GNU bash does not run this trapsig */ 887 trapsig(ksh_SIGERR); 888 Flag(FERREXIT) &= ~0x80; 889 } 890 891 /* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */ 892 if (i == LEXIT || 893 ((i == LERROR || i == LINTR) && sigtraps[ksh_SIGEXIT].trap)) { 894 ++trap_nested; 895 runtrap(&sigtraps[ksh_SIGEXIT], trap_nested == 1); 896 --trap_nested; 897 i = LLEAVE; 898 } else if (Flag(FERREXIT) == 1 && (i == LERROR || i == LINTR)) { 899 ++trap_nested; 900 runtrap(&sigtraps[ksh_SIGERR], trap_nested == 1); 901 --trap_nested; 902 i = LLEAVE; 903 } 904 905 while (/* CONSTCOND */ 1) { 906 switch (e->type) { 907 case E_PARSE: 908 case E_FUNC: 909 case E_INCL: 910 case E_LOOP: 911 case E_ERRH: 912 kshlongjmp(e->jbuf, i); 913 /* NOTREACHED */ 914 case E_NONE: 915 if (i == LINTR) 916 e->flags |= EF_FAKE_SIGDIE; 917 /* FALLTHROUGH */ 918 default: 919 quitenv(NULL); 920 } 921 } 922 } 923 924 void 925 newenv(int type) 926 { 927 struct env *ep; 928 char *cp; 929 930 /* 931 * struct env includes ALLOC_ITEM for alignment constraints 932 * so first get the actually used memory, then assign it 933 */ 934 cp = alloc(sizeof(struct env) - ALLOC_SIZE, ATEMP); 935 /* undo what alloc() did to the malloc result address */ 936 ep = (void *)(cp - ALLOC_SIZE); 937 /* initialise public members of struct env (not the ALLOC_ITEM) */ 938 ainit(&ep->area); 939 ep->oenv = e; 940 ep->loc = e->loc; 941 ep->savefd = NULL; 942 ep->temps = NULL; 943 ep->yyrecursive_statep = NULL; 944 ep->type = type; 945 ep->flags = 0; 946 /* jump buffer is invalid because flags == 0 */ 947 e = ep; 948 } 949 950 void 951 quitenv(struct shf *shf) 952 { 953 struct env *ep = e; 954 char *cp; 955 int fd; 956 957 yyrecursive_pop(true); 958 while (ep->oenv && ep->oenv->loc != ep->loc) 959 popblock(); 960 if (ep->savefd != NULL) { 961 for (fd = 0; fd < NUFILE; fd++) 962 /* if ep->savefd[fd] < 0, means fd was closed */ 963 if (ep->savefd[fd]) 964 restfd(fd, ep->savefd[fd]); 965 if (ep->savefd[2]) 966 /* Clear any write errors */ 967 shf_reopen(2, SHF_WR, shl_out); 968 } 969 /* 970 * Bottom of the stack. 971 * Either main shell is exiting or cleanup_parents_env() was called. 972 */ 973 if (ep->oenv == NULL) { 974 #ifdef DEBUG_LEAKS 975 int i; 976 #endif 977 978 if (ep->type == E_NONE) { 979 /* Main shell exiting? */ 980 #if HAVE_PERSISTENT_HISTORY 981 if (Flag(FTALKING)) 982 hist_finish(); 983 #endif 984 j_exit(); 985 if (ep->flags & EF_FAKE_SIGDIE) { 986 int sig = (exstat & 0xFF) - 128; 987 988 /* 989 * ham up our death a bit (AT&T ksh 990 * only seems to do this for SIGTERM) 991 * Don't do it for SIGQUIT, since we'd 992 * dump a core.. 993 */ 994 if ((sig == SIGINT || sig == SIGTERM) && 995 (kshpgrp == kshpid)) { 996 setsig(&sigtraps[sig], SIG_DFL, 997 SS_RESTORE_CURR | SS_FORCE); 998 kill(0, sig); 999 } 1000 } 1001 } 1002 if (shf) 1003 shf_close(shf); 1004 reclaim(); 1005 #ifdef DEBUG_LEAKS 1006 #ifndef MKSH_NO_CMDLINE_EDITING 1007 x_done(); 1008 #endif 1009 afreeall(APERM); 1010 for (fd = 3; fd < NUFILE; fd++) 1011 if ((i = fcntl(fd, F_GETFD, 0)) != -1 && 1012 (i & FD_CLOEXEC)) 1013 close(fd); 1014 close(2); 1015 close(1); 1016 close(0); 1017 #endif 1018 exit(exstat & 0xFF); 1019 } 1020 if (shf) 1021 shf_close(shf); 1022 reclaim(); 1023 1024 e = e->oenv; 1025 1026 /* free the struct env - tricky due to the ALLOC_ITEM inside */ 1027 cp = (void *)ep; 1028 afree(cp + ALLOC_SIZE, ATEMP); 1029 } 1030 1031 /* Called after a fork to cleanup stuff left over from parents environment */ 1032 void 1033 cleanup_parents_env(void) 1034 { 1035 struct env *ep; 1036 int fd; 1037 1038 mkssert(e != NULL); 1039 1040 /* 1041 * Don't clean up temporary files - parent will probably need them. 1042 * Also, can't easily reclaim memory since variables, etc. could be 1043 * anywhere. 1044 */ 1045 1046 /* close all file descriptors hiding in savefd */ 1047 for (ep = e; ep; ep = ep->oenv) { 1048 if (ep->savefd) { 1049 for (fd = 0; fd < NUFILE; fd++) 1050 if (ep->savefd[fd] > 0) 1051 close(ep->savefd[fd]); 1052 afree(ep->savefd, &ep->area); 1053 ep->savefd = NULL; 1054 } 1055 #ifdef DEBUG_LEAKS 1056 if (ep->type != E_NONE) 1057 ep->type = E_GONE; 1058 #endif 1059 } 1060 #ifndef DEBUG_LEAKS 1061 e->oenv = NULL; 1062 #endif 1063 } 1064 1065 /* Called just before an execve cleanup stuff temporary files */ 1066 void 1067 cleanup_proc_env(void) 1068 { 1069 struct env *ep; 1070 1071 for (ep = e; ep; ep = ep->oenv) 1072 remove_temps(ep->temps); 1073 } 1074 1075 /* remove temp files and free ATEMP Area */ 1076 static void 1077 reclaim(void) 1078 { 1079 struct block *l; 1080 1081 while ((l = e->loc) && (!e->oenv || e->oenv->loc != l)) { 1082 e->loc = l->next; 1083 afreeall(&l->area); 1084 } 1085 1086 remove_temps(e->temps); 1087 e->temps = NULL; 1088 afreeall(&e->area); 1089 } 1090 1091 static void 1092 remove_temps(struct temp *tp) 1093 { 1094 for (; tp != NULL; tp = tp->next) 1095 if (tp->pid == procpid) 1096 unlink(tp->tffn); 1097 } 1098 1099 /* 1100 * Initialise tty_fd. Used for tracking the size of the terminal, 1101 * saving/resetting tty modes upon forground job completion, and 1102 * for setting up the tty process group. Return values: 1103 * 0 = got controlling tty 1104 * 1 = got terminal but no controlling tty 1105 * 2 = cannot find a terminal 1106 * 3 = cannot dup fd 1107 * 4 = cannot make fd close-on-exec 1108 * An existing tty_fd is cached if no "better" one could be found, 1109 * i.e. if tty_devtty was already set or the new would not set it. 1110 */ 1111 int 1112 tty_init_fd(void) 1113 { 1114 int fd, rv, eno = 0; 1115 bool do_close = false, is_devtty = true; 1116 1117 if (tty_devtty) { 1118 /* already got a tty which is /dev/tty */ 1119 return (0); 1120 } 1121 1122 #ifdef _UWIN 1123 /*XXX imake style */ 1124 if (isatty(3)) { 1125 /* fd 3 on UWIN _is_ /dev/tty (or our controlling tty) */ 1126 fd = 3; 1127 goto got_fd; 1128 } 1129 #endif 1130 if ((fd = open("/dev/tty", O_RDWR, 0)) >= 0) { 1131 do_close = true; 1132 goto got_fd; 1133 } 1134 eno = errno; 1135 1136 if (tty_fd >= 0) { 1137 /* already got a non-devtty one */ 1138 rv = 1; 1139 goto out; 1140 } 1141 is_devtty = false; 1142 1143 if (isatty((fd = 0)) || isatty((fd = 2))) 1144 goto got_fd; 1145 /* cannot find one */ 1146 rv = 2; 1147 /* assert: do_close == false */ 1148 goto out; 1149 1150 got_fd: 1151 if ((rv = fcntl(fd, F_DUPFD, FDBASE)) < 0) { 1152 eno = errno; 1153 rv = 3; 1154 goto out; 1155 } 1156 if (fcntl(rv, F_SETFD, FD_CLOEXEC) < 0) { 1157 eno = errno; 1158 close(rv); 1159 rv = 4; 1160 goto out; 1161 } 1162 tty_fd = rv; 1163 tty_devtty = is_devtty; 1164 rv = eno = 0; 1165 out: 1166 if (do_close) 1167 close(fd); 1168 errno = eno; 1169 return (rv); 1170 } 1171 1172 /* A shell error occurred (eg, syntax error, etc.) */ 1173 1174 #define VWARNINGF_ERRORPREFIX 1 1175 #define VWARNINGF_FILELINE 2 1176 #define VWARNINGF_BUILTIN 4 1177 #define VWARNINGF_INTERNAL 8 1178 1179 static void vwarningf(unsigned int, const char *, va_list) 1180 MKSH_A_FORMAT(__printf__, 2, 0); 1181 1182 static void 1183 vwarningf(unsigned int flags, const char *fmt, va_list ap) 1184 { 1185 if (fmt) { 1186 if (flags & VWARNINGF_INTERNAL) 1187 shf_fprintf(shl_out, "internal error: "); 1188 if (flags & VWARNINGF_ERRORPREFIX) 1189 error_prefix(tobool(flags & VWARNINGF_FILELINE)); 1190 if ((flags & VWARNINGF_BUILTIN) && 1191 /* not set when main() calls parse_args() */ 1192 builtin_argv0 && builtin_argv0 != kshname) 1193 shf_fprintf(shl_out, "%s: ", builtin_argv0); 1194 shf_vfprintf(shl_out, fmt, ap); 1195 shf_putchar('\n', shl_out); 1196 } 1197 shf_flush(shl_out); 1198 } 1199 1200 void 1201 errorfx(int rc, const char *fmt, ...) 1202 { 1203 va_list va; 1204 1205 exstat = rc; 1206 1207 /* debugging: note that stdout not valid */ 1208 shl_stdout_ok = false; 1209 1210 va_start(va, fmt); 1211 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va); 1212 va_end(va); 1213 unwind(LERROR); 1214 } 1215 1216 void 1217 errorf(const char *fmt, ...) 1218 { 1219 va_list va; 1220 1221 exstat = 1; 1222 1223 /* debugging: note that stdout not valid */ 1224 shl_stdout_ok = false; 1225 1226 va_start(va, fmt); 1227 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va); 1228 va_end(va); 1229 unwind(LERROR); 1230 } 1231 1232 /* like errorf(), but no unwind is done */ 1233 void 1234 warningf(bool fileline, const char *fmt, ...) 1235 { 1236 va_list va; 1237 1238 va_start(va, fmt); 1239 vwarningf(VWARNINGF_ERRORPREFIX | (fileline ? VWARNINGF_FILELINE : 0), 1240 fmt, va); 1241 va_end(va); 1242 } 1243 1244 /* 1245 * Used by built-in utilities to prefix shell and utility name to message 1246 * (also unwinds environments for special builtins). 1247 */ 1248 void 1249 bi_errorf(const char *fmt, ...) 1250 { 1251 va_list va; 1252 1253 /* debugging: note that stdout not valid */ 1254 shl_stdout_ok = false; 1255 1256 exstat = 1; 1257 1258 va_start(va, fmt); 1259 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE | 1260 VWARNINGF_BUILTIN, fmt, va); 1261 va_end(va); 1262 1263 /* 1264 * POSIX special builtins and ksh special builtins cause 1265 * non-interactive shells to exit. 1266 * XXX odd use of KEEPASN; also may not want LERROR here 1267 */ 1268 if (builtin_flag & SPEC_BI) { 1269 builtin_argv0 = NULL; 1270 unwind(LERROR); 1271 } 1272 } 1273 1274 /* Called when something that shouldn't happen does */ 1275 void 1276 internal_errorf(const char *fmt, ...) 1277 { 1278 va_list va; 1279 1280 va_start(va, fmt); 1281 vwarningf(VWARNINGF_INTERNAL, fmt, va); 1282 va_end(va); 1283 unwind(LERROR); 1284 } 1285 1286 void 1287 internal_warningf(const char *fmt, ...) 1288 { 1289 va_list va; 1290 1291 va_start(va, fmt); 1292 vwarningf(VWARNINGF_INTERNAL, fmt, va); 1293 va_end(va); 1294 } 1295 1296 /* used by error reporting functions to print "ksh: .kshrc[25]: " */ 1297 void 1298 error_prefix(bool fileline) 1299 { 1300 /* Avoid foo: foo[2]: ... */ 1301 if (!fileline || !source || !source->file || 1302 strcmp(source->file, kshname) != 0) 1303 shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-')); 1304 if (fileline && source && source->file != NULL) { 1305 shf_fprintf(shl_out, "%s[%d]: ", source->file, 1306 source->errline > 0 ? source->errline : source->line); 1307 source->errline = 0; 1308 } 1309 } 1310 1311 /* printf to shl_out (stderr) with flush */ 1312 void 1313 shellf(const char *fmt, ...) 1314 { 1315 va_list va; 1316 1317 if (!initio_done) 1318 /* shl_out may not be set up yet... */ 1319 return; 1320 va_start(va, fmt); 1321 shf_vfprintf(shl_out, fmt, va); 1322 va_end(va); 1323 shf_flush(shl_out); 1324 } 1325 1326 /* printf to shl_stdout (stdout) */ 1327 void 1328 shprintf(const char *fmt, ...) 1329 { 1330 va_list va; 1331 1332 if (!shl_stdout_ok) 1333 internal_errorf("shl_stdout not valid"); 1334 va_start(va, fmt); 1335 shf_vfprintf(shl_stdout, fmt, va); 1336 va_end(va); 1337 } 1338 1339 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */ 1340 int 1341 can_seek(int fd) 1342 { 1343 struct stat statb; 1344 1345 return (fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ? 1346 SHF_UNBUF : 0); 1347 } 1348 1349 #ifdef DF 1350 int shl_dbg_fd; 1351 #define NSHF_IOB 4 1352 #else 1353 #define NSHF_IOB 3 1354 #endif 1355 struct shf shf_iob[NSHF_IOB]; 1356 1357 void 1358 initio(void) 1359 { 1360 #ifdef DF 1361 const char *lfp; 1362 #endif 1363 1364 /* force buffer allocation */ 1365 shf_fdopen(1, SHF_WR, shl_stdout); 1366 shf_fdopen(2, SHF_WR, shl_out); 1367 shf_fdopen(2, SHF_WR, shl_spare); 1368 #ifdef DF 1369 if ((lfp = getenv("SDMKSH_PATH")) == NULL) { 1370 if ((lfp = getenv("HOME")) == NULL || *lfp != '/') 1371 errorf("cannot get home directory"); 1372 lfp = shf_smprintf("%s/mksh-dbg.txt", lfp); 1373 } 1374 1375 if ((shl_dbg_fd = open(lfp, O_WRONLY | O_APPEND | O_CREAT, 0600)) < 0) 1376 errorf("cannot open debug output file %s", lfp); 1377 if (shl_dbg_fd < FDBASE) { 1378 int nfd; 1379 1380 nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE); 1381 close(shl_dbg_fd); 1382 if ((shl_dbg_fd = nfd) == -1) 1383 errorf("cannot dup debug output file"); 1384 } 1385 fcntl(shl_dbg_fd, F_SETFD, FD_CLOEXEC); 1386 shf_fdopen(shl_dbg_fd, SHF_WR, shl_dbg); 1387 DF("=== open ==="); 1388 #endif 1389 initio_done = true; 1390 } 1391 1392 /* A dup2() with error checking */ 1393 int 1394 ksh_dup2(int ofd, int nfd, bool errok) 1395 { 1396 int rv; 1397 1398 if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF)) 1399 errorf("too many files open in shell"); 1400 1401 #ifdef __ultrix 1402 /*XXX imake style */ 1403 if (rv >= 0) 1404 fcntl(nfd, F_SETFD, 0); 1405 #endif 1406 1407 return (rv); 1408 } 1409 1410 /* 1411 * Move fd from user space (0 <= fd < 10) to shell space (fd >= 10), 1412 * set close-on-exec flag. See FDBASE in sh.h, maybe 24 not 10 here. 1413 */ 1414 short 1415 savefd(int fd) 1416 { 1417 int nfd = fd; 1418 1419 if (fd < FDBASE && (nfd = fcntl(fd, F_DUPFD, FDBASE)) < 0 && 1420 errno == EBADF) 1421 return (-1); 1422 if (nfd < 0 || nfd > SHRT_MAX) 1423 errorf("too many files open in shell"); 1424 fcntl(nfd, F_SETFD, FD_CLOEXEC); 1425 return ((short)nfd); 1426 } 1427 1428 void 1429 restfd(int fd, int ofd) 1430 { 1431 if (fd == 2) 1432 shf_flush(&shf_iob[/* fd */ 2]); 1433 if (ofd < 0) 1434 /* original fd closed */ 1435 close(fd); 1436 else if (fd != ofd) { 1437 /*XXX: what to do if this dup fails? */ 1438 ksh_dup2(ofd, fd, true); 1439 close(ofd); 1440 } 1441 } 1442 1443 void 1444 openpipe(int *pv) 1445 { 1446 int lpv[2]; 1447 1448 if (pipe(lpv) < 0) 1449 errorf("can't create pipe - try again"); 1450 pv[0] = savefd(lpv[0]); 1451 if (pv[0] != lpv[0]) 1452 close(lpv[0]); 1453 pv[1] = savefd(lpv[1]); 1454 if (pv[1] != lpv[1]) 1455 close(lpv[1]); 1456 } 1457 1458 void 1459 closepipe(int *pv) 1460 { 1461 close(pv[0]); 1462 close(pv[1]); 1463 } 1464 1465 /* 1466 * Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn 1467 * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor. 1468 */ 1469 int 1470 check_fd(const char *name, int mode, const char **emsgp) 1471 { 1472 int fd, fl; 1473 1474 if (name[0] == 'p' && !name[1]) 1475 return (coproc_getfd(mode, emsgp)); 1476 for (fd = 0; ksh_isdigit(*name); ++name) 1477 fd = (fd * 10) + *name - '0'; 1478 if (*name || fd >= FDBASE) { 1479 if (emsgp) 1480 *emsgp = "illegal file descriptor name"; 1481 return (-1); 1482 } 1483 if ((fl = fcntl(fd, F_GETFL, 0)) < 0) { 1484 if (emsgp) 1485 *emsgp = "bad file descriptor"; 1486 return (-1); 1487 } 1488 fl &= O_ACCMODE; 1489 /* 1490 * X_OK is a kludge to disable this check for dups (x<&1): 1491 * historical shells never did this check (XXX don't know what 1492 * POSIX has to say). 1493 */ 1494 if (!(mode & X_OK) && fl != O_RDWR && ( 1495 ((mode & R_OK) && fl != O_RDONLY) || 1496 ((mode & W_OK) && fl != O_WRONLY))) { 1497 if (emsgp) 1498 *emsgp = (fl == O_WRONLY) ? 1499 "fd not open for reading" : 1500 "fd not open for writing"; 1501 return (-1); 1502 } 1503 return (fd); 1504 } 1505 1506 /* Called once from main */ 1507 void 1508 coproc_init(void) 1509 { 1510 coproc.read = coproc.readw = coproc.write = -1; 1511 coproc.njobs = 0; 1512 coproc.id = 0; 1513 } 1514 1515 /* Called by c_read() when eof is read - close fd if it is the co-process fd */ 1516 void 1517 coproc_read_close(int fd) 1518 { 1519 if (coproc.read >= 0 && fd == coproc.read) { 1520 coproc_readw_close(fd); 1521 close(coproc.read); 1522 coproc.read = -1; 1523 } 1524 } 1525 1526 /* 1527 * Called by c_read() and by iosetup() to close the other side of the 1528 * read pipe, so reads will actually terminate. 1529 */ 1530 void 1531 coproc_readw_close(int fd) 1532 { 1533 if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) { 1534 close(coproc.readw); 1535 coproc.readw = -1; 1536 } 1537 } 1538 1539 /* 1540 * Called by c_print when a write to a fd fails with EPIPE and by iosetup 1541 * when co-process input is dup'd 1542 */ 1543 void 1544 coproc_write_close(int fd) 1545 { 1546 if (coproc.write >= 0 && fd == coproc.write) { 1547 close(coproc.write); 1548 coproc.write = -1; 1549 } 1550 } 1551 1552 /* 1553 * Called to check for existence of/value of the co-process file descriptor. 1554 * (Used by check_fd() and by c_read/c_print to deal with -p option). 1555 */ 1556 int 1557 coproc_getfd(int mode, const char **emsgp) 1558 { 1559 int fd = (mode & R_OK) ? coproc.read : coproc.write; 1560 1561 if (fd >= 0) 1562 return (fd); 1563 if (emsgp) 1564 *emsgp = "no coprocess"; 1565 return (-1); 1566 } 1567 1568 /* 1569 * called to close file descriptors related to the coprocess (if any) 1570 * Should be called with SIGCHLD blocked. 1571 */ 1572 void 1573 coproc_cleanup(int reuse) 1574 { 1575 /* This to allow co-processes to share output pipe */ 1576 if (!reuse || coproc.readw < 0 || coproc.read < 0) { 1577 if (coproc.read >= 0) { 1578 close(coproc.read); 1579 coproc.read = -1; 1580 } 1581 if (coproc.readw >= 0) { 1582 close(coproc.readw); 1583 coproc.readw = -1; 1584 } 1585 } 1586 if (coproc.write >= 0) { 1587 close(coproc.write); 1588 coproc.write = -1; 1589 } 1590 } 1591 1592 struct temp * 1593 maketemp(Area *ap, Temp_type type, struct temp **tlist) 1594 { 1595 char *cp; 1596 size_t len; 1597 int i; 1598 struct temp *tp; 1599 const char *dir; 1600 struct stat sb; 1601 1602 dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR; 1603 /* add "/shXXXXXX.tmp" plus NUL */ 1604 len = strlen(dir); 1605 checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14); 1606 tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap); 1607 1608 tp->shf = NULL; 1609 tp->pid = procpid; 1610 tp->type = type; 1611 1612 if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) { 1613 tp->tffn[0] = '\0'; 1614 goto maketemp_out; 1615 } 1616 1617 cp = (void *)tp; 1618 cp += offsetof(struct temp, tffn[0]); 1619 memcpy(cp, dir, len); 1620 cp += len; 1621 memcpy(cp, "/shXXXXXX.tmp", 14); 1622 /* point to the first of six Xes */ 1623 cp += 3; 1624 /* generate random part of filename */ 1625 len = -1; 1626 do { 1627 i = rndget() % 36; 1628 cp[++len] = i < 26 ? 'a' + i : '0' + i - 26; 1629 } while (len < 5); 1630 1631 /* cyclically attempt to open a temporary file */ 1632 while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR, 0600)) < 0) { 1633 if (errno != EEXIST) 1634 goto maketemp_out; 1635 /* count down from z to a then from 9 to 0 */ 1636 while (cp[len] == '0') 1637 if (!len--) 1638 goto maketemp_out; 1639 if (cp[len] == 'a') 1640 cp[len] = '9'; 1641 else 1642 --cp[len]; 1643 /* do another cycle */ 1644 } 1645 1646 if (type == TT_FUNSUB) { 1647 int nfd; 1648 1649 /* map us high and mark as close-on-exec */ 1650 if ((nfd = savefd(i)) != i) { 1651 close(i); 1652 i = nfd; 1653 } 1654 } 1655 1656 /* shf_fdopen cannot fail, so no fd leak */ 1657 tp->shf = shf_fdopen(i, SHF_WR, NULL); 1658 1659 maketemp_out: 1660 tp->next = *tlist; 1661 *tlist = tp; 1662 return (tp); 1663 } 1664 1665 /* 1666 * We use a similar collision resolution algorithm as Python 2.5.4 1667 * but with a slightly tweaked implementation written from scratch. 1668 */ 1669 1670 #define INIT_TBLSHIFT 3 /* initial table shift (2^3 = 8) */ 1671 #define PERTURB_SHIFT 5 /* see Python 2.5.4 Objects/dictobject.c */ 1672 1673 static void tgrow(struct table *); 1674 static int tnamecmp(const void *, const void *); 1675 1676 static void 1677 tgrow(struct table *tp) 1678 { 1679 size_t i, j, osize, mask, perturb; 1680 struct tbl *tblp, **pp; 1681 struct tbl **ntblp, **otblp = tp->tbls; 1682 1683 if (tp->tshift > 29) 1684 internal_errorf("hash table size limit reached"); 1685 1686 /* calculate old size, new shift and new size */ 1687 osize = (size_t)1 << (tp->tshift++); 1688 i = osize << 1; 1689 1690 ntblp = alloc2(i, sizeof(struct tbl *), tp->areap); 1691 /* multiplication cannot overflow: alloc2 checked that */ 1692 memset(ntblp, 0, i * sizeof(struct tbl *)); 1693 1694 /* table can get very full when reaching its size limit */ 1695 tp->nfree = (tp->tshift == 30) ? 0x3FFF0000UL : 1696 /* but otherwise, only 75% */ 1697 ((i * 3) / 4); 1698 tp->tbls = ntblp; 1699 if (otblp == NULL) 1700 return; 1701 1702 mask = i - 1; 1703 for (i = 0; i < osize; i++) 1704 if ((tblp = otblp[i]) != NULL) { 1705 if ((tblp->flag & DEFINED)) { 1706 /* search for free hash table slot */ 1707 j = perturb = tblp->ua.hval; 1708 goto find_first_empty_slot; 1709 find_next_empty_slot: 1710 j = (j << 2) + j + perturb + 1; 1711 perturb >>= PERTURB_SHIFT; 1712 find_first_empty_slot: 1713 pp = &ntblp[j & mask]; 1714 if (*pp != NULL) 1715 goto find_next_empty_slot; 1716 /* found an empty hash table slot */ 1717 *pp = tblp; 1718 tp->nfree--; 1719 } else if (!(tblp->flag & FINUSE)) { 1720 afree(tblp, tp->areap); 1721 } 1722 } 1723 afree(otblp, tp->areap); 1724 } 1725 1726 void 1727 ktinit(Area *ap, struct table *tp, uint8_t initshift) 1728 { 1729 tp->areap = ap; 1730 tp->tbls = NULL; 1731 tp->tshift = ((initshift > INIT_TBLSHIFT) ? 1732 initshift : INIT_TBLSHIFT) - 1; 1733 tgrow(tp); 1734 } 1735 1736 /* table, name (key) to search for, hash(name), rv pointer to tbl ptr */ 1737 struct tbl * 1738 ktscan(struct table *tp, const char *name, uint32_t h, struct tbl ***ppp) 1739 { 1740 size_t j, perturb, mask; 1741 struct tbl **pp, *p; 1742 1743 mask = ((size_t)1 << (tp->tshift)) - 1; 1744 /* search for hash table slot matching name */ 1745 j = perturb = h; 1746 goto find_first_slot; 1747 find_next_slot: 1748 j = (j << 2) + j + perturb + 1; 1749 perturb >>= PERTURB_SHIFT; 1750 find_first_slot: 1751 pp = &tp->tbls[j & mask]; 1752 if ((p = *pp) != NULL && (p->ua.hval != h || !(p->flag & DEFINED) || 1753 strcmp(p->name, name))) 1754 goto find_next_slot; 1755 /* p == NULL if not found, correct found entry otherwise */ 1756 if (ppp) 1757 *ppp = pp; 1758 return (p); 1759 } 1760 1761 /* table, name (key) to enter, hash(n) */ 1762 struct tbl * 1763 ktenter(struct table *tp, const char *n, uint32_t h) 1764 { 1765 struct tbl **pp, *p; 1766 size_t len; 1767 1768 Search: 1769 if ((p = ktscan(tp, n, h, &pp))) 1770 return (p); 1771 1772 if (tp->nfree == 0) { 1773 /* too full */ 1774 tgrow(tp); 1775 goto Search; 1776 } 1777 1778 /* create new tbl entry */ 1779 len = strlen(n); 1780 checkoktoadd(len, offsetof(struct tbl, name[0]) + 1); 1781 p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap); 1782 p->flag = 0; 1783 p->type = 0; 1784 p->areap = tp->areap; 1785 p->ua.hval = h; 1786 p->u2.field = 0; 1787 p->u.array = NULL; 1788 memcpy(p->name, n, len); 1789 1790 /* enter in tp->tbls */ 1791 tp->nfree--; 1792 *pp = p; 1793 return (p); 1794 } 1795 1796 void 1797 ktwalk(struct tstate *ts, struct table *tp) 1798 { 1799 ts->left = (size_t)1 << (tp->tshift); 1800 ts->next = tp->tbls; 1801 } 1802 1803 struct tbl * 1804 ktnext(struct tstate *ts) 1805 { 1806 while (--ts->left >= 0) { 1807 struct tbl *p = *ts->next++; 1808 if (p != NULL && (p->flag & DEFINED)) 1809 return (p); 1810 } 1811 return (NULL); 1812 } 1813 1814 static int 1815 tnamecmp(const void *p1, const void *p2) 1816 { 1817 const struct tbl *a = *((const struct tbl * const *)p1); 1818 const struct tbl *b = *((const struct tbl * const *)p2); 1819 1820 return (strcmp(a->name, b->name)); 1821 } 1822 1823 struct tbl ** 1824 ktsort(struct table *tp) 1825 { 1826 size_t i; 1827 struct tbl **p, **sp, **dp; 1828 1829 /* 1830 * since the table is never entirely full, no need to reserve 1831 * additional space for the trailing NULL appended below 1832 */ 1833 i = (size_t)1 << (tp->tshift); 1834 p = alloc2(i, sizeof(struct tbl *), ATEMP); 1835 sp = tp->tbls; /* source */ 1836 dp = p; /* dest */ 1837 while (i--) 1838 if ((*dp = *sp++) != NULL && (((*dp)->flag & DEFINED) || 1839 ((*dp)->flag & ARRAY))) 1840 dp++; 1841 qsort(p, (i = dp - p), sizeof(struct tbl *), tnamecmp); 1842 p[i] = NULL; 1843 return (p); 1844 } 1845 1846 #ifdef SIGWINCH 1847 static void 1848 x_sigwinch(int sig MKSH_A_UNUSED) 1849 { 1850 /* this runs inside interrupt context, with errno saved */ 1851 1852 got_winch = 1; 1853 } 1854 #endif 1855 1856 #ifdef DF 1857 void 1858 DF(const char *fmt, ...) 1859 { 1860 va_list args; 1861 struct timeval tv; 1862 mirtime_mjd mjd; 1863 1864 mksh_lockfd(shl_dbg_fd); 1865 mksh_TIME(tv); 1866 timet2mjd(&mjd, tv.tv_sec); 1867 shf_fprintf(shl_dbg, "[%02u:%02u:%02u (%u) %u.%06u] ", 1868 (unsigned)mjd.sec / 3600, ((unsigned)mjd.sec / 60) % 60, 1869 (unsigned)mjd.sec % 60, (unsigned)getpid(), 1870 (unsigned)tv.tv_sec, (unsigned)tv.tv_usec); 1871 va_start(args, fmt); 1872 shf_vfprintf(shl_dbg, fmt, args); 1873 va_end(args); 1874 shf_putc('\n', shl_dbg); 1875 shf_flush(shl_dbg); 1876 mksh_unlkfd(shl_dbg_fd); 1877 } 1878 #endif 1879 1880 void 1881 x_mkraw(int fd, mksh_ttyst *ocb, bool forread) 1882 { 1883 mksh_ttyst cb; 1884 1885 if (ocb) 1886 mksh_tcget(fd, ocb); 1887 else 1888 ocb = &tty_state; 1889 1890 cb = *ocb; 1891 if (forread) { 1892 cb.c_lflag &= ~(ICANON) | ECHO; 1893 } else { 1894 cb.c_iflag &= ~(INLCR | ICRNL); 1895 cb.c_lflag &= ~(ISIG | ICANON | ECHO); 1896 } 1897 #if defined(VLNEXT) && defined(_POSIX_VDISABLE) 1898 /* OSF/1 processes lnext when ~icanon */ 1899 cb.c_cc[VLNEXT] = _POSIX_VDISABLE; 1900 #endif 1901 /* SunOS 4.1.x & OSF/1 processes discard(flush) when ~icanon */ 1902 #if defined(VDISCARD) && defined(_POSIX_VDISABLE) 1903 cb.c_cc[VDISCARD] = _POSIX_VDISABLE; 1904 #endif 1905 cb.c_cc[VTIME] = 0; 1906 cb.c_cc[VMIN] = 1; 1907 1908 mksh_tcset(fd, &cb); 1909 } 1910