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