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