1 /* $NetBSD: main.c,v 1.11 2004/07/07 19:20:09 mycroft 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.11 2004/07/07 19:20:09 mycroft 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 **) 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**) 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 *) 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 = 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 **) 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 532 s = pushs(SSTRING, ATEMP); 533 s->start = s->str = comm; 534 return shell(s, FALSE); 535 } 536 537 /* 538 * run the commands from the input source, returning status. 539 */ 540 int 541 shell(s, toplevel) 542 Source *volatile s; /* input source */ 543 int volatile toplevel; 544 { 545 struct op *t; 546 volatile int wastty = s->flags & SF_TTY; 547 volatile int attempts = 13; 548 volatile int interactive = Flag(FTALKING) && toplevel; 549 Source *volatile old_source = source; 550 int i; 551 552 newenv(E_PARSE); 553 if (interactive) 554 really_exit = 0; 555 i = ksh_sigsetjmp(e->jbuf, 0); 556 if (i) { 557 switch (i) { 558 case LINTR: /* we get here if SIGINT not caught or ignored */ 559 case LERROR: 560 case LSHELL: 561 if (interactive) { 562 if (i == LINTR) 563 shellf(newline); 564 /* Reset any eof that was read as part of a 565 * multiline command. 566 */ 567 if (Flag(FIGNOREEOF) && s->type == SEOF 568 && wastty) 569 s->type = SSTDIN; 570 /* Used by exit command to get back to 571 * top level shell. Kind of strange since 572 * interactive is set if we are reading from 573 * a tty, but to have stopped jobs, one only 574 * needs FMONITOR set (not FTALKING/SF_TTY)... 575 */ 576 /* toss any input we have so far */ 577 s->start = s->str = null; 578 break; 579 } 580 /* fall through... */ 581 case LEXIT: 582 case LLEAVE: 583 case LRETURN: 584 source = old_source; 585 quitenv(); 586 unwind(i); /* keep on going */ 587 /*NOREACHED*/ 588 default: 589 source = old_source; 590 quitenv(); 591 internal_errorf(1, "shell: %d", i); 592 /*NOREACHED*/ 593 } 594 } 595 596 while (1) { 597 if (trap) 598 runtraps(0); 599 600 if (s->next == NULL) { 601 if (Flag(FVERBOSE)) 602 s->flags |= SF_ECHO; 603 else 604 s->flags &= ~SF_ECHO; 605 } 606 607 if (interactive) { 608 j_notify(); 609 #ifdef KSH 610 mcheck(); 611 #endif /* KSH */ 612 set_prompt(PS1, s); 613 } 614 615 t = compile(s); 616 if (t != NULL && t->type == TEOF) { 617 if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { 618 shellf("Use `exit' to leave ksh\n"); 619 s->type = SSTDIN; 620 } else if (wastty && !really_exit 621 && j_stopped_running()) 622 { 623 really_exit = 1; 624 s->type = SSTDIN; 625 } else { 626 /* this for POSIX, which says EXIT traps 627 * shall be taken in the environment 628 * immediately after the last command 629 * executed. 630 */ 631 if (toplevel) 632 unwind(LEXIT); 633 break; 634 } 635 } 636 637 if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) 638 exstat = execute(t, 0); 639 640 if (t != NULL && t->type != TEOF && interactive && really_exit) 641 really_exit = 0; 642 643 reclaim(); 644 } 645 quitenv(); 646 source = old_source; 647 return exstat; 648 } 649 650 /* return to closest error handler or shell(), exit if none found */ 651 void 652 unwind(i) 653 int i; 654 { 655 /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */ 656 if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) 657 && sigtraps[SIGEXIT_].trap)) 658 { 659 runtrap(&sigtraps[SIGEXIT_]); 660 i = LLEAVE; 661 } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) { 662 runtrap(&sigtraps[SIGERR_]); 663 i = LLEAVE; 664 } 665 while (1) { 666 switch (e->type) { 667 case E_PARSE: 668 case E_FUNC: 669 case E_INCL: 670 case E_LOOP: 671 case E_ERRH: 672 ksh_siglongjmp(e->jbuf, i); 673 /*NOTREACHED*/ 674 675 case E_NONE: 676 if (i == LINTR) 677 e->flags |= EF_FAKE_SIGDIE; 678 /* Fall through... */ 679 680 default: 681 quitenv(); 682 } 683 } 684 } 685 686 void 687 newenv(type) 688 int type; 689 { 690 register struct env *ep; 691 692 ep = (struct env *) alloc(sizeof(*ep), ATEMP); 693 ep->type = type; 694 ep->flags = 0; 695 ainit(&ep->area); 696 ep->loc = e->loc; 697 ep->savefd = NULL; 698 ep->oenv = e; 699 ep->temps = NULL; 700 e = ep; 701 } 702 703 void 704 quitenv() 705 { 706 register struct env *ep = e; 707 register int fd; 708 709 if (ep->oenv && ep->oenv->loc != ep->loc) 710 popblock(); 711 if (ep->savefd != NULL) { 712 for (fd = 0; fd < NUFILE; fd++) 713 /* if ep->savefd[fd] < 0, means fd was closed */ 714 if (ep->savefd[fd]) 715 restfd(fd, ep->savefd[fd]); 716 if (ep->savefd[2]) /* Clear any write errors */ 717 shf_reopen(2, SHF_WR, shl_out); 718 } 719 reclaim(); 720 721 /* Bottom of the stack. 722 * Either main shell is exiting or cleanup_parents_env() was called. 723 */ 724 if (ep->oenv == NULL) { 725 if (ep->type == E_NONE) { /* Main shell exiting? */ 726 if (Flag(FTALKING)) 727 hist_finish(); 728 j_exit(); 729 if (ep->flags & EF_FAKE_SIGDIE) { 730 int sig = exstat - 128; 731 732 /* ham up our death a bit (at&t ksh 733 * only seems to do this for SIGTERM) 734 * Don't do it for SIGQUIT, since we'd 735 * dump a core.. 736 */ 737 if (sig == SIGINT || sig == SIGTERM) { 738 setsig(&sigtraps[sig], SIG_DFL, 739 SS_RESTORE_CURR|SS_FORCE); 740 kill(0, sig); 741 } 742 } 743 #ifdef MEM_DEBUG 744 chmem_allfree(); 745 #endif /* MEM_DEBUG */ 746 } 747 exit(exstat); 748 } 749 750 e = e->oenv; 751 afree(ep, ATEMP); 752 } 753 754 /* Called after a fork to cleanup stuff left over from parents environment */ 755 void 756 cleanup_parents_env() 757 { 758 struct env *ep; 759 int fd; 760 761 /* Don't clean up temporary files - parent will probably need them. 762 * Also, can't easily reclaim memory since variables, etc. could be 763 * anywhere. 764 */ 765 766 /* close all file descriptors hiding in savefd */ 767 for (ep = e; ep; ep = ep->oenv) { 768 if (ep->savefd) { 769 for (fd = 0; fd < NUFILE; fd++) 770 if (ep->savefd[fd] > 0) 771 close(ep->savefd[fd]); 772 afree(ep->savefd, &ep->area); 773 ep->savefd = (short *) 0; 774 } 775 } 776 e->oenv = (struct env *) 0; 777 } 778 779 /* Called just before an execve cleanup stuff temporary files */ 780 void 781 cleanup_proc_env() 782 { 783 struct env *ep; 784 785 for (ep = e; ep; ep = ep->oenv) 786 remove_temps(ep->temps); 787 } 788 789 /* remove temp files and free ATEMP Area */ 790 static void 791 reclaim() 792 { 793 remove_temps(e->temps); 794 e->temps = NULL; 795 afreeall(&e->area); 796 } 797 798 static void 799 remove_temps(tp) 800 struct temp *tp; 801 { 802 #ifdef OS2 803 static struct temp *delayed_remove; 804 struct temp *t, **tprev; 805 806 if (delayed_remove) { 807 for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev) 808 /* No need to check t->pid here... */ 809 if (unlink(t->name) >= 0 || errno == ENOENT) { 810 *tprev = t->next; 811 afree(t, APERM); 812 } else 813 tprev = &t->next; 814 } 815 #endif /* OS2 */ 816 817 for (; tp != NULL; tp = tp->next) 818 if (tp->pid == procpid) { 819 #ifdef OS2 820 /* OS/2 (and dos) do not allow files that are currently 821 * open to be removed, so we cache it away for future 822 * removal. 823 * XXX should only do this if errno 824 * is Efile-still-open-can't-remove 825 * (but I don't know what that is...) 826 */ 827 if (unlink(tp->name) < 0 && errno != ENOENT) { 828 t = (struct temp *) alloc( 829 sizeof(struct temp) + strlen(tp->name) + 1, 830 APERM); 831 memset(t, 0, sizeof(struct temp)); 832 t->name = (char *) &t[1]; 833 strlcpy(t->name, tp->name, strlen(tp->name) + 1); 834 t->next = delayed_remove; 835 delayed_remove = t; 836 } 837 #else /* OS2 */ 838 unlink(tp->name); 839 #endif /* OS2 */ 840 } 841 } 842 843 /* Returns true if name refers to a restricted shell */ 844 static int 845 is_restricted(name) 846 char *name; 847 { 848 char *p; 849 850 if ((p = ksh_strrchr_dirsep(name))) 851 name = p; 852 /* accepts rsh, rksh, rpdksh, pdrksh, etc. */ 853 return (p = strchr(name, 'r')) && strstr(p, "sh"); 854 } 855 856 void 857 aerror(ap, msg) 858 Area *ap; 859 const char *msg; 860 { 861 internal_errorf(1, "alloc: %s", msg); 862 errorf(null); /* this is never executed - keeps gcc quiet */ 863 /*NOTREACHED*/ 864 } 865