1 /* $OpenBSD: main.c,v 1.47 2011/09/07 11:33:25 otto Exp $ */ 2 3 /* 4 * startup, main loop, environments and error handling 5 */ 6 7 #define EXTERN /* define EXTERNs in sh.h */ 8 9 #include "sh.h" 10 #include <sys/stat.h> 11 #include <pwd.h> 12 13 extern char **environ; 14 15 /* 16 * global data 17 */ 18 19 static void reclaim(void); 20 static void remove_temps(struct temp *tp); 21 static int is_restricted(char *name); 22 static void init_username(void); 23 24 /* 25 * shell initialization 26 */ 27 28 static const char initifs[] = "IFS= \t\n"; 29 30 static const char initsubs[] = "${PS2=> } ${PS3=#? } ${PS4=+ }"; 31 32 static const char *initcoms [] = { 33 "typeset", "-r", "KSH_VERSION", NULL, 34 "typeset", "-x", "SHELL", "PATH", "HOME", NULL, 35 "typeset", "-i", "PPID", NULL, 36 "typeset", "-i", "OPTIND=1", NULL, 37 "eval", "typeset -i RANDOM MAILCHECK=\"${MAILCHECK-600}\" SECONDS=\"${SECONDS-0}\" TMOUT=\"${TMOUT-0}\"", NULL, 38 "alias", 39 /* Standard ksh aliases */ 40 "hash=alias -t", /* not "alias -t --": hash -r needs to work */ 41 "type=whence -v", 42 #ifdef JOBS 43 "stop=kill -STOP", 44 "suspend=kill -STOP $$", 45 #endif 46 "autoload=typeset -fu", 47 "functions=typeset -f", 48 #ifdef HISTORY 49 "history=fc -l", 50 #endif /* HISTORY */ 51 "integer=typeset -i", 52 "nohup=nohup ", 53 "local=typeset", 54 "r=fc -e -", 55 /* Aliases that are builtin commands in at&t */ 56 "login=exec login", 57 NULL, 58 /* this is what at&t ksh seems to track, with the addition of emacs */ 59 "alias", "-tU", 60 "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls", 61 "mail", "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", 62 NULL, 63 NULL 64 }; 65 66 char username[_PW_NAME_LEN + 1]; 67 68 #define version_param (initcoms[2]) 69 70 int 71 main(int argc, char *argv[]) 72 { 73 int i; 74 int argi; 75 Source *s; 76 struct block *l; 77 int restricted, errexit; 78 char **wp; 79 struct env env; 80 pid_t ppid; 81 82 /* make sure argv[] is sane */ 83 if (!*argv) { 84 static const char *empty_argv[] = { 85 "ksh", (char *) 0 86 }; 87 88 argv = (char **) empty_argv; 89 argc = 1; 90 } 91 kshname = *argv; 92 93 ainit(&aperm); /* initialize permanent Area */ 94 95 /* set up base environment */ 96 memset(&env, 0, sizeof(env)); 97 env.type = E_NONE; 98 ainit(&env.area); 99 e = &env; 100 newblock(); /* set up global l->vars and l->funs */ 101 102 /* Do this first so output routines (eg, errorf, shellf) can work */ 103 initio(); 104 105 initvar(); 106 107 initctypes(); 108 109 inittraps(); 110 111 coproc_init(); 112 113 /* set up variable and command dictionaries */ 114 ktinit(&taliases, APERM, 0); 115 ktinit(&aliases, APERM, 0); 116 ktinit(&homedirs, APERM, 0); 117 118 /* define shell keywords */ 119 initkeywords(); 120 121 /* define built-in commands */ 122 ktinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */ 123 for (i = 0; shbuiltins[i].name != NULL; i++) 124 builtin(shbuiltins[i].name, shbuiltins[i].func); 125 for (i = 0; kshbuiltins[i].name != NULL; i++) 126 builtin(kshbuiltins[i].name, kshbuiltins[i].func); 127 128 init_histvec(); 129 130 def_path = _PATH_DEFPATH; 131 { 132 size_t len = confstr(_CS_PATH, (char *) 0, 0); 133 char *new; 134 135 if (len > 0) { 136 confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1); 137 def_path = new; 138 } 139 } 140 141 /* Set PATH to def_path (will set the path global variable). 142 * (import of environment below will probably change this setting). 143 */ 144 { 145 struct tbl *vp = global("PATH"); 146 /* setstr can't fail here */ 147 setstr(vp, def_path, KSH_RETURN_ERROR); 148 } 149 150 151 /* Turn on nohup by default for now - will change to off 152 * by default once people are aware of its existence 153 * (at&t ksh does not have a nohup option - it always sends 154 * the hup). 155 */ 156 Flag(FNOHUP) = 1; 157 158 /* Turn on brace expansion by default. At&t ksh's that have 159 * alternation always have it on. BUT, posix doesn't have 160 * brace expansion, so set this before setting up FPOSIX 161 * (change_flag() clears FBRACEEXPAND when FPOSIX is set). 162 */ 163 #ifdef BRACE_EXPAND 164 Flag(FBRACEEXPAND) = 1; 165 #endif /* BRACE_EXPAND */ 166 167 /* set posix flag just before environment so that it will have 168 * exactly the same effect as the POSIXLY_CORRECT environment 169 * variable. If this needs to be done sooner to ensure correct posix 170 * operation, an initial scan of the environment will also have 171 * done sooner. 172 */ 173 #ifdef POSIXLY_CORRECT 174 change_flag(FPOSIX, OF_SPECIAL, 1); 175 #endif /* POSIXLY_CORRECT */ 176 177 /* Check to see if we're /bin/sh. */ 178 if (!strcmp(kshname, "sh") || !strcmp(kshname, "-sh") || 179 (strlen(kshname) >= 3 && 180 !strcmp(&kshname[strlen(kshname) - 3], "/sh"))) { 181 Flag(FSH) = 1; 182 version_param = "SH_VERSION"; 183 } 184 185 /* Set edit mode to emacs by default, may be overridden 186 * by the environment or the user. Also, we want tab completion 187 * on in vi by default. */ 188 #if defined(EDIT) && defined(EMACS) 189 change_flag(FEMACS, OF_SPECIAL, 1); 190 #endif /* EDIT && EMACS */ 191 #if defined(EDIT) && defined(VI) 192 Flag(FVITABCOMPLETE) = 1; 193 #endif /* EDIT && VI */ 194 195 /* import environment */ 196 if (environ != NULL) 197 for (wp = environ; *wp != NULL; wp++) 198 typeset(*wp, IMPORT|EXPORT, 0, 0, 0); 199 200 kshpid = procpid = getpid(); 201 typeset(initifs, 0, 0, 0, 0); /* for security */ 202 203 /* assign default shell variable values */ 204 substitute(initsubs, 0); 205 206 /* Figure out the current working directory and set $PWD */ 207 { 208 struct stat s_pwd, s_dot; 209 struct tbl *pwd_v = global("PWD"); 210 char *pwd = str_val(pwd_v); 211 char *pwdx = pwd; 212 213 /* Try to use existing $PWD if it is valid */ 214 if (pwd[0] != '/' || 215 stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0 || 216 s_pwd.st_dev != s_dot.st_dev || 217 s_pwd.st_ino != s_dot.st_ino) 218 pwdx = (char *) 0; 219 set_current_wd(pwdx); 220 if (current_wd[0]) 221 simplify_path(current_wd); 222 /* Only set pwd if we know where we are or if it had a 223 * bogus value 224 */ 225 if (current_wd[0] || pwd != null) 226 /* setstr can't fail here */ 227 setstr(pwd_v, current_wd, KSH_RETURN_ERROR); 228 } 229 ppid = getppid(); 230 setint(global("PPID"), (long) ppid); 231 /* setstr can't fail here */ 232 setstr(global(version_param), ksh_version, KSH_RETURN_ERROR); 233 234 /* execute initialization statements */ 235 for (wp = (char**) initcoms; *wp != NULL; wp++) { 236 shcomexec(wp); 237 for (; *wp != NULL; wp++) 238 ; 239 } 240 241 242 ksheuid = geteuid(); 243 init_username(); 244 safe_prompt = ksheuid ? "$ " : "# "; 245 { 246 struct tbl *vp = global("PS1"); 247 248 /* Set PS1 if it isn't set, or we are root and prompt doesn't 249 * contain a # or \$ (only in ksh mode). 250 */ 251 if (!(vp->flag & ISSET) || 252 (!ksheuid && !strchr(str_val(vp), '#') && 253 (Flag(FSH) || !strstr(str_val(vp), "\\$")))) 254 /* setstr can't fail here */ 255 setstr(vp, safe_prompt, KSH_RETURN_ERROR); 256 } 257 258 /* Set this before parsing arguments */ 259 Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid(); 260 261 /* this to note if monitor is set on command line (see below) */ 262 Flag(FMONITOR) = 127; 263 argi = parse_args(argv, OF_CMDLINE, (int *) 0); 264 if (argi < 0) 265 exit(1); 266 267 if (Flag(FCOMMAND)) { 268 s = pushs(SSTRING, ATEMP); 269 if (!(s->start = s->str = argv[argi++])) 270 errorf("-c requires an argument"); 271 if (argv[argi]) 272 kshname = argv[argi++]; 273 } else if (argi < argc && !Flag(FSTDIN)) { 274 s = pushs(SFILE, ATEMP); 275 s->file = argv[argi++]; 276 s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); 277 if (s->u.shf == NULL) { 278 exstat = 127; /* POSIX */ 279 errorf("%s: %s", s->file, strerror(errno)); 280 } 281 kshname = s->file; 282 } else { 283 Flag(FSTDIN) = 1; 284 s = pushs(SSTDIN, ATEMP); 285 s->file = "<stdin>"; 286 s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), 287 (struct shf *) 0); 288 if (isatty(0) && isatty(2)) { 289 Flag(FTALKING) = Flag(FTALKING_I) = 1; 290 /* The following only if isatty(0) */ 291 s->flags |= SF_TTY; 292 s->u.shf->flags |= SHF_INTERRUPT; 293 s->file = (char *) 0; 294 } 295 } 296 297 /* This bizarreness is mandated by POSIX */ 298 { 299 struct stat s_stdin; 300 301 if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && 302 Flag(FTALKING)) 303 reset_nonblock(0); 304 } 305 306 /* initialize job control */ 307 i = Flag(FMONITOR) != 127; 308 Flag(FMONITOR) = 0; 309 j_init(i); 310 #ifdef EDIT 311 /* Do this after j_init(), as tty_fd is not initialized 'til then */ 312 if (Flag(FTALKING)) 313 x_init(); 314 #endif 315 316 l = e->loc; 317 l->argv = &argv[argi - 1]; 318 l->argc = argc - argi; 319 l->argv[0] = (char *) kshname; 320 getopts_reset(1); 321 322 /* Disable during .profile/ENV reading */ 323 restricted = Flag(FRESTRICTED); 324 Flag(FRESTRICTED) = 0; 325 errexit = Flag(FERREXIT); 326 Flag(FERREXIT) = 0; 327 328 /* Do this before profile/$ENV so that if it causes problems in them, 329 * user will know why things broke. 330 */ 331 if (!current_wd[0] && Flag(FTALKING)) 332 warningf(false, "Cannot determine current working directory"); 333 334 if (Flag(FLOGIN)) { 335 include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1); 336 if (!Flag(FPRIVILEGED)) 337 include(substitute("$HOME/.profile", 0), 0, 338 (char **) 0, 1); 339 } 340 341 if (Flag(FPRIVILEGED)) 342 include("/etc/suid_profile", 0, (char **) 0, 1); 343 else if (Flag(FTALKING)) { 344 char *env_file; 345 346 /* include $ENV */ 347 env_file = str_val(global("ENV")); 348 349 #ifdef DEFAULT_ENV 350 /* If env isn't set, include default environment */ 351 if (env_file == null) 352 env_file = DEFAULT_ENV; 353 #endif /* DEFAULT_ENV */ 354 env_file = substitute(env_file, DOTILDE); 355 if (*env_file != '\0') 356 include(env_file, 0, (char **) 0, 1); 357 } 358 359 if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL")))) 360 restricted = 1; 361 if (restricted) { 362 static const char *const restr_com[] = { 363 "typeset", "-r", "PATH", 364 "ENV", "SHELL", 365 (char *) 0 366 }; 367 shcomexec((char **) restr_com); 368 /* After typeset command... */ 369 Flag(FRESTRICTED) = 1; 370 } 371 if (errexit) 372 Flag(FERREXIT) = 1; 373 374 if (Flag(FTALKING)) { 375 hist_init(s); 376 alarm_init(); 377 } else 378 Flag(FTRACKALL) = 1; /* set after ENV */ 379 380 shell(s, true); /* doesn't return */ 381 return 0; 382 } 383 384 static void 385 init_username(void) 386 { 387 char *p; 388 struct tbl *vp = global("USER"); 389 390 if (vp->flag & ISSET) 391 p = ksheuid == 0 ? "root" : str_val(vp); 392 else 393 p = getlogin(); 394 395 strlcpy(username, p != NULL ? p : "?", sizeof username); 396 } 397 398 int 399 include(const char *name, int argc, char **argv, int intr_ok) 400 { 401 Source *volatile s = NULL; 402 struct shf *shf; 403 char **volatile old_argv; 404 volatile int old_argc; 405 int i; 406 407 shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); 408 if (shf == NULL) 409 return -1; 410 411 if (argv) { 412 old_argv = e->loc->argv; 413 old_argc = e->loc->argc; 414 } else { 415 old_argv = (char **) 0; 416 old_argc = 0; 417 } 418 newenv(E_INCL); 419 i = sigsetjmp(e->jbuf, 0); 420 if (i) { 421 quitenv(s ? s->u.shf : NULL); 422 if (old_argv) { 423 e->loc->argv = old_argv; 424 e->loc->argc = old_argc; 425 } 426 switch (i) { 427 case LRETURN: 428 case LERROR: 429 return exstat & 0xff; /* see below */ 430 case LINTR: 431 /* intr_ok is set if we are including .profile or $ENV. 432 * If user ^C's out, we don't want to kill the shell... 433 */ 434 if (intr_ok && (exstat - 128) != SIGTERM) 435 return 1; 436 /* FALLTHROUGH */ 437 case LEXIT: 438 case LLEAVE: 439 case LSHELL: 440 unwind(i); 441 /* NOTREACHED */ 442 default: 443 internal_errorf(1, "include: %d", i); 444 /* NOTREACHED */ 445 } 446 } 447 if (argv) { 448 e->loc->argv = argv; 449 e->loc->argc = argc; 450 } 451 s = pushs(SFILE, ATEMP); 452 s->u.shf = shf; 453 s->file = str_save(name, ATEMP); 454 i = shell(s, false); 455 quitenv(s->u.shf); 456 if (old_argv) { 457 e->loc->argv = old_argv; 458 e->loc->argc = old_argc; 459 } 460 return i & 0xff; /* & 0xff to ensure value not -1 */ 461 } 462 463 /* 464 * spawn a command into a shell optionally keeping track of line 465 * number. 466 */ 467 int 468 command(const char *comm, int line) 469 { 470 Source *s; 471 472 s = pushs(SSTRING, ATEMP); 473 s->start = s->str = comm; 474 s->line = line; 475 return shell(s, false); 476 } 477 478 /* 479 * run the commands from the input source, returning status. 480 */ 481 int 482 shell(Source *volatile s, volatile int toplevel) 483 { 484 struct op *t; 485 volatile int wastty = s->flags & SF_TTY; 486 volatile int attempts = 13; 487 volatile int interactive = Flag(FTALKING) && toplevel; 488 Source *volatile old_source = source; 489 int i; 490 491 newenv(E_PARSE); 492 if (interactive) 493 really_exit = 0; 494 i = sigsetjmp(e->jbuf, 0); 495 if (i) { 496 switch (i) { 497 case LINTR: /* we get here if SIGINT not caught or ignored */ 498 case LERROR: 499 case LSHELL: 500 if (interactive) { 501 if (i == LINTR) 502 shellf(newline); 503 /* Reset any eof that was read as part of a 504 * multiline command. 505 */ 506 if (Flag(FIGNOREEOF) && s->type == SEOF && 507 wastty) 508 s->type = SSTDIN; 509 /* Used by exit command to get back to 510 * top level shell. Kind of strange since 511 * interactive is set if we are reading from 512 * a tty, but to have stopped jobs, one only 513 * needs FMONITOR set (not FTALKING/SF_TTY)... 514 */ 515 /* toss any input we have so far */ 516 s->start = s->str = null; 517 break; 518 } 519 /* FALLTHROUGH */ 520 case LEXIT: 521 case LLEAVE: 522 case LRETURN: 523 source = old_source; 524 quitenv(NULL); 525 unwind(i); /* keep on going */ 526 /* NOTREACHED */ 527 default: 528 source = old_source; 529 quitenv(NULL); 530 internal_errorf(1, "shell: %d", i); 531 /* NOTREACHED */ 532 } 533 } 534 535 while (1) { 536 if (trap) 537 runtraps(0); 538 539 if (s->next == NULL) { 540 if (Flag(FVERBOSE)) 541 s->flags |= SF_ECHO; 542 else 543 s->flags &= ~SF_ECHO; 544 } 545 546 if (interactive) { 547 j_notify(); 548 mcheck(); 549 set_prompt(PS1, s); 550 } 551 552 t = compile(s); 553 if (t != NULL && t->type == TEOF) { 554 if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { 555 shellf("Use `exit' to leave ksh\n"); 556 s->type = SSTDIN; 557 } else if (wastty && !really_exit && 558 j_stopped_running()) { 559 really_exit = 1; 560 s->type = SSTDIN; 561 } else { 562 /* this for POSIX, which says EXIT traps 563 * shall be taken in the environment 564 * immediately after the last command 565 * executed. 566 */ 567 if (toplevel) 568 unwind(LEXIT); 569 break; 570 } 571 } 572 573 if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) 574 exstat = execute(t, 0, NULL); 575 576 if (t != NULL && t->type != TEOF && interactive && really_exit) 577 really_exit = 0; 578 579 reclaim(); 580 } 581 quitenv(NULL); 582 source = old_source; 583 return exstat; 584 } 585 586 /* return to closest error handler or shell(), exit if none found */ 587 void 588 unwind(int i) 589 { 590 /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */ 591 if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) && 592 sigtraps[SIGEXIT_].trap)) { 593 runtrap(&sigtraps[SIGEXIT_]); 594 i = LLEAVE; 595 } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) { 596 runtrap(&sigtraps[SIGERR_]); 597 i = LLEAVE; 598 } 599 while (1) { 600 switch (e->type) { 601 case E_PARSE: 602 case E_FUNC: 603 case E_INCL: 604 case E_LOOP: 605 case E_ERRH: 606 siglongjmp(e->jbuf, i); 607 /* NOTREACHED */ 608 609 case E_NONE: 610 if (i == LINTR) 611 e->flags |= EF_FAKE_SIGDIE; 612 /* FALLTHROUGH */ 613 614 default: 615 quitenv(NULL); 616 } 617 } 618 } 619 620 void 621 newenv(int type) 622 { 623 struct env *ep; 624 625 ep = (struct env *) alloc(sizeof(*ep), ATEMP); 626 ep->type = type; 627 ep->flags = 0; 628 ainit(&ep->area); 629 ep->loc = e->loc; 630 ep->savefd = NULL; 631 ep->oenv = e; 632 ep->temps = NULL; 633 e = ep; 634 } 635 636 void 637 quitenv(struct shf *shf) 638 { 639 struct env *ep = e; 640 int fd; 641 642 if (ep->oenv && ep->oenv->loc != ep->loc) 643 popblock(); 644 if (ep->savefd != NULL) { 645 for (fd = 0; fd < NUFILE; fd++) 646 /* if ep->savefd[fd] < 0, means fd was closed */ 647 if (ep->savefd[fd]) 648 restfd(fd, ep->savefd[fd]); 649 if (ep->savefd[2]) /* Clear any write errors */ 650 shf_reopen(2, SHF_WR, shl_out); 651 } 652 653 /* Bottom of the stack. 654 * Either main shell is exiting or cleanup_parents_env() was called. 655 */ 656 if (ep->oenv == NULL) { 657 if (ep->type == E_NONE) { /* Main shell exiting? */ 658 if (Flag(FTALKING)) 659 hist_finish(); 660 j_exit(); 661 if (ep->flags & EF_FAKE_SIGDIE) { 662 int sig = exstat - 128; 663 664 /* ham up our death a bit (at&t ksh 665 * only seems to do this for SIGTERM) 666 * Don't do it for SIGQUIT, since we'd 667 * dump a core.. 668 */ 669 if ((sig == SIGINT || sig == SIGTERM) && 670 getpgrp() == kshpid) { 671 setsig(&sigtraps[sig], SIG_DFL, 672 SS_RESTORE_CURR|SS_FORCE); 673 kill(0, sig); 674 } 675 } 676 } 677 if (shf) 678 shf_close(shf); 679 reclaim(); 680 exit(exstat); 681 } 682 if (shf) 683 shf_close(shf); 684 reclaim(); 685 686 e = e->oenv; 687 afree(ep, ATEMP); 688 } 689 690 /* Called after a fork to cleanup stuff left over from parents environment */ 691 void 692 cleanup_parents_env(void) 693 { 694 struct env *ep; 695 int fd; 696 697 /* Don't clean up temporary files - parent will probably need them. 698 * Also, can't easily reclaim memory since variables, etc. could be 699 * anywhere. 700 */ 701 702 /* close all file descriptors hiding in savefd */ 703 for (ep = e; ep; ep = ep->oenv) { 704 if (ep->savefd) { 705 for (fd = 0; fd < NUFILE; fd++) 706 if (ep->savefd[fd] > 0) 707 close(ep->savefd[fd]); 708 afree(ep->savefd, &ep->area); 709 ep->savefd = (short *) 0; 710 } 711 } 712 e->oenv = (struct env *) 0; 713 } 714 715 /* Called just before an execve cleanup stuff temporary files */ 716 void 717 cleanup_proc_env(void) 718 { 719 struct env *ep; 720 721 for (ep = e; ep; ep = ep->oenv) 722 remove_temps(ep->temps); 723 } 724 725 /* remove temp files and free ATEMP Area */ 726 static void 727 reclaim(void) 728 { 729 remove_temps(e->temps); 730 e->temps = NULL; 731 afreeall(&e->area); 732 } 733 734 static void 735 remove_temps(struct temp *tp) 736 { 737 738 for (; tp != NULL; tp = tp->next) 739 if (tp->pid == procpid) { 740 unlink(tp->name); 741 } 742 } 743 744 /* Returns true if name refers to a restricted shell */ 745 static int 746 is_restricted(char *name) 747 { 748 char *p; 749 750 if ((p = strrchr(name, '/'))) 751 name = p + 1; 752 /* accepts rsh, rksh, rpdksh, pdrksh */ 753 if (strcmp(name, "rsh") && \ 754 strcmp(name, "rksh") && \ 755 strcmp(name, "rpdksh") && \ 756 strcmp(name, "pdrksh")) 757 return(0); 758 else 759 return(1); 760 761 } 762