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