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