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