1 /* $OpenBSD: main.c,v 1.20 2000/12/19 21:48:54 markus 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(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 environment */ 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 /* Check to see if we're /bin/sh. */ 209 if (!strcmp(&kshname[strlen(kshname) - 3], "/sh") 210 || !strcmp(kshname, "sh") || !strcmp(kshname, "-sh")) 211 Flag(FSH) = 1; 212 213 /* Set edit mode to emacs by default, may be overridden 214 * by the environment or the user. Also, we want tab completion 215 * on in vi by default. */ 216 #if defined(EDIT) && defined(EMACS) 217 change_flag(FEMACS, OF_SPECIAL, 1); 218 #endif /* EDIT && EMACS */ 219 #if defined(EDIT) && defined(VI) 220 Flag(FVITABCOMPLETE) = 1; 221 #endif /* EDIT && VI */ 222 223 /* import environment */ 224 if (environ != NULL) 225 for (wp = environ; *wp != NULL; wp++) 226 typeset(*wp, IMPORT|EXPORT, 0, 0, 0); 227 228 kshpid = procpid = getpid(); 229 typeset(initifs, 0, 0, 0, 0); /* for security */ 230 231 /* assign default shell variable values */ 232 substitute(initsubs, 0); 233 234 /* Figure out the current working directory and set $PWD */ 235 { 236 struct stat s_pwd, s_dot; 237 struct tbl *pwd_v = global("PWD"); 238 char *pwd = str_val(pwd_v); 239 char *pwdx = pwd; 240 241 /* Try to use existing $PWD if it is valid */ 242 if (!ISABSPATH(pwd) 243 || stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0 244 || s_pwd.st_dev != s_dot.st_dev 245 || s_pwd.st_ino != s_dot.st_ino) 246 pwdx = (char *) 0; 247 set_current_wd(pwdx); 248 if (current_wd[0]) 249 simplify_path(current_wd); 250 /* Only set pwd if we know where we are or if it had a 251 * bogus value 252 */ 253 if (current_wd[0] || pwd != null) 254 /* setstr can't fail here */ 255 setstr(pwd_v, current_wd, KSH_RETURN_ERROR); 256 } 257 ppid = getppid(); 258 setint(global("PPID"), (long) ppid); 259 #ifdef KSH 260 setint(global("RANDOM"), (long) (time((time_t *)0) * kshpid * ppid)); 261 #endif /* KSH */ 262 /* setstr can't fail here */ 263 setstr(global(version_param), ksh_version, KSH_RETURN_ERROR); 264 265 /* execute initialization statements */ 266 for (wp = (char**) initcoms; *wp != NULL; wp++) { 267 shcomexec(wp); 268 for (; *wp != NULL; wp++) 269 ; 270 } 271 272 273 ksheuid = geteuid(); 274 safe_prompt = ksheuid ? "$ " : "# "; 275 { 276 struct tbl *vp = global("PS1"); 277 278 /* Set PS1 if it isn't set, or we are root and prompt doesn't 279 * contain a #. 280 */ 281 if (!(vp->flag & ISSET) 282 || (!ksheuid && !strchr(str_val(vp), '#'))) 283 /* setstr can't fail here */ 284 setstr(vp, safe_prompt, KSH_RETURN_ERROR); 285 } 286 287 /* Set this before parsing arguments */ 288 Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid(); 289 290 /* this to note if monitor is set on command line (see below) */ 291 Flag(FMONITOR) = 127; 292 argi = parse_args(argv, OF_CMDLINE, (int *) 0); 293 if (argi < 0) 294 exit(1); 295 296 if (Flag(FCOMMAND)) { 297 s = pushs(SSTRING, ATEMP); 298 if (!(s->start = s->str = argv[argi++])) 299 errorf("-c requires an argument"); 300 if (argv[argi]) 301 kshname = argv[argi++]; 302 } else if (argi < argc && !Flag(FSTDIN)) { 303 s = pushs(SFILE, ATEMP); 304 #ifdef OS2 305 /* a bug in os2 extproc shell processing doesn't 306 * pass full pathnames so we have to search for it. 307 * This changes the behavior of 'ksh arg' to search 308 * the users search path but it can't be helped. 309 */ 310 s->file = search(argv[argi++], path, R_OK, (int *) 0); 311 if (!s->file || !*s->file) 312 s->file = argv[argi - 1]; 313 #else 314 s->file = argv[argi++]; 315 #endif /* OS2 */ 316 s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); 317 if (s->u.shf == NULL) { 318 exstat = 127; /* POSIX */ 319 errorf("%s: %s", s->file, strerror(errno)); 320 } 321 kshname = s->file; 322 } else { 323 Flag(FSTDIN) = 1; 324 s = pushs(SSTDIN, ATEMP); 325 s->file = "<stdin>"; 326 s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), 327 (struct shf *) 0); 328 if (isatty(0) && isatty(2)) { 329 Flag(FTALKING) = Flag(FTALKING_I) = 1; 330 /* The following only if isatty(0) */ 331 s->flags |= SF_TTY; 332 s->u.shf->flags |= SHF_INTERRUPT; 333 s->file = (char *) 0; 334 } 335 } 336 337 /* This bizarreness is mandated by POSIX */ 338 { 339 struct stat s_stdin; 340 341 if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && 342 Flag(FTALKING)) 343 reset_nonblock(0); 344 } 345 346 /* initialize job control */ 347 i = Flag(FMONITOR) != 127; 348 Flag(FMONITOR) = 0; 349 j_init(i); 350 #ifdef EDIT 351 /* Do this after j_init(), as tty_fd is not initialized 'til then */ 352 if (Flag(FTALKING)) 353 x_init(); 354 #endif 355 356 l = e->loc; 357 l->argv = &argv[argi - 1]; 358 l->argc = argc - argi; 359 l->argv[0] = (char *) kshname; 360 getopts_reset(1); 361 362 /* Disable during .profile/ENV reading */ 363 restricted = Flag(FRESTRICTED); 364 Flag(FRESTRICTED) = 0; 365 errexit = Flag(FERREXIT); 366 Flag(FERREXIT) = 0; 367 368 /* Do this before profile/$ENV so that if it causes problems in them, 369 * user will know why things broke. 370 */ 371 if (!current_wd[0] && Flag(FTALKING)) 372 warningf(FALSE, "Cannot determine current working directory"); 373 374 if (Flag(FLOGIN)) { 375 #ifdef OS2 376 char *profile; 377 378 /* Try to find a profile - first see if $INIT has a value, 379 * then try /etc/profile.ksh, then c:/usr/etc/profile.ksh. 380 */ 381 if (!Flag(FPRIVILEGED) 382 && strcmp(profile = substitute("$INIT/profile.ksh", 0), 383 "/profile.ksh")) 384 include(profile, 0, (char **) 0, 1); 385 else if (include("/etc/profile.ksh", 0, (char **) 0, 1) < 0) 386 include("c:/usr/etc/profile.ksh", 0, (char **) 0, 1); 387 if (!Flag(FPRIVILEGED)) 388 include(substitute("$HOME/profile.ksh", 0), 0, 389 (char **) 0, 1); 390 #else /* OS2 */ 391 include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1); 392 if (!Flag(FPRIVILEGED)) 393 include(substitute("$HOME/.profile", 0), 0, 394 (char **) 0, 1); 395 #endif /* OS2 */ 396 } 397 398 if (Flag(FPRIVILEGED)) 399 include("/etc/suid_profile", 0, (char **) 0, 1); 400 else { 401 char *env_file; 402 403 #ifndef KSH 404 if (!Flag(FPOSIX)) 405 env_file = null; 406 else 407 #endif /* !KSH */ 408 /* include $ENV */ 409 env_file = str_val(global("ENV")); 410 411 #ifdef DEFAULT_ENV 412 /* If env isn't set, include default environment */ 413 if (env_file == null) 414 env_file = DEFAULT_ENV; 415 #endif /* DEFAULT_ENV */ 416 env_file = substitute(env_file, DOTILDE); 417 if (*env_file != '\0') 418 include(env_file, 0, (char **) 0, 1); 419 #ifdef OS2 420 else if (Flag(FTALKING)) 421 include(substitute("$HOME/kshrc.ksh", 0), 0, 422 (char **) 0, 1); 423 #endif /* OS2 */ 424 } 425 426 if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL")))) 427 restricted = 1; 428 if (restricted) { 429 static const char *const restr_com[] = { 430 "typeset", "-r", "PATH", 431 "ENV", "SHELL", 432 (char *) 0 433 }; 434 shcomexec((char **) restr_com); 435 /* After typeset command... */ 436 Flag(FRESTRICTED) = 1; 437 } 438 if (errexit) 439 Flag(FERREXIT) = 1; 440 441 if (Flag(FTALKING)) { 442 hist_init(s); 443 #ifdef KSH 444 alarm_init(); 445 #endif /* KSH */ 446 } else 447 Flag(FTRACKALL) = 1; /* set after ENV */ 448 449 shell(s, TRUE); /* doesn't return */ 450 return 0; 451 } 452 453 int 454 include(name, argc, argv, intr_ok) 455 const char *name; 456 int argc; 457 char **argv; 458 int intr_ok; 459 { 460 register Source *volatile s = NULL; 461 struct shf *shf; 462 char **volatile old_argv; 463 volatile int old_argc; 464 int i; 465 466 shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); 467 if (shf == NULL) 468 return -1; 469 470 if (argv) { 471 old_argv = e->loc->argv; 472 old_argc = e->loc->argc; 473 } else { 474 old_argv = (char **) 0; 475 old_argc = 0; 476 } 477 newenv(E_INCL); 478 i = ksh_sigsetjmp(e->jbuf, 0); 479 if (i) { 480 if (s) /* Do this before quitenv(), which frees the memory */ 481 shf_close(s->u.shf); 482 quitenv(); 483 if (old_argv) { 484 e->loc->argv = old_argv; 485 e->loc->argc = old_argc; 486 } 487 switch (i) { 488 case LRETURN: 489 case LERROR: 490 return exstat & 0xff; /* see below */ 491 case LINTR: 492 /* intr_ok is set if we are including .profile or $ENV. 493 * If user ^C's out, we don't want to kill the shell... 494 */ 495 if (intr_ok && (exstat - 128) != SIGTERM) 496 return 1; 497 /* fall through... */ 498 case LEXIT: 499 case LLEAVE: 500 case LSHELL: 501 unwind(i); 502 /*NOREACHED*/ 503 default: 504 internal_errorf(1, "include: %d", i); 505 /*NOREACHED*/ 506 } 507 } 508 if (argv) { 509 e->loc->argv = argv; 510 e->loc->argc = argc; 511 } 512 s = pushs(SFILE, ATEMP); 513 s->u.shf = shf; 514 s->file = str_save(name, ATEMP); 515 i = shell(s, FALSE); 516 shf_close(s->u.shf); 517 quitenv(); 518 if (old_argv) { 519 e->loc->argv = old_argv; 520 e->loc->argc = old_argc; 521 } 522 return i & 0xff; /* & 0xff to ensure value not -1 */ 523 } 524 525 int 526 command(comm) 527 const char *comm; 528 { 529 register Source *s; 530 531 s = pushs(SSTRING, ATEMP); 532 s->start = s->str = comm; 533 return shell(s, FALSE); 534 } 535 536 /* 537 * run the commands from the input source, returning status. 538 */ 539 int 540 shell(s, toplevel) 541 Source *volatile s; /* input source */ 542 int volatile toplevel; 543 { 544 struct op *t; 545 volatile int wastty = s->flags & SF_TTY; 546 volatile int attempts = 13; 547 volatile int interactive = Flag(FTALKING) && toplevel; 548 Source *volatile old_source = source; 549 int i; 550 551 newenv(E_PARSE); 552 if (interactive) 553 really_exit = 0; 554 i = ksh_sigsetjmp(e->jbuf, 0); 555 if (i) { 556 switch (i) { 557 case LINTR: /* we get here if SIGINT not caught or ignored */ 558 case LERROR: 559 case LSHELL: 560 if (interactive) { 561 if (i == LINTR) 562 shellf(newline); 563 /* Reset any eof that was read as part of a 564 * multiline command. 565 */ 566 if (Flag(FIGNOREEOF) && s->type == SEOF 567 && wastty) 568 s->type = SSTDIN; 569 /* Used by exit command to get back to 570 * top level shell. Kind of strange since 571 * interactive is set if we are reading from 572 * a tty, but to have stopped jobs, one only 573 * needs FMONITOR set (not FTALKING/SF_TTY)... 574 */ 575 /* toss any input we have so far */ 576 s->start = s->str = null; 577 break; 578 } 579 /* fall through... */ 580 case LEXIT: 581 case LLEAVE: 582 case LRETURN: 583 source = old_source; 584 quitenv(); 585 unwind(i); /* keep on going */ 586 /*NOREACHED*/ 587 default: 588 source = old_source; 589 quitenv(); 590 internal_errorf(1, "shell: %d", i); 591 /*NOREACHED*/ 592 } 593 } 594 595 while (1) { 596 if (trap) 597 runtraps(0); 598 599 if (s->next == NULL) { 600 if (Flag(FVERBOSE)) 601 s->flags |= SF_ECHO; 602 else 603 s->flags &= ~SF_ECHO; 604 } 605 606 if (interactive) { 607 j_notify(); 608 #ifdef KSH 609 mcheck(); 610 #endif /* KSH */ 611 set_prompt(PS1, s); 612 } 613 614 t = compile(s); 615 if (t != NULL && t->type == TEOF) { 616 if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { 617 shellf("Use `exit' to leave ksh\n"); 618 s->type = SSTDIN; 619 } else if (wastty && !really_exit 620 && j_stopped_running()) 621 { 622 really_exit = 1; 623 s->type = SSTDIN; 624 } else { 625 /* this for POSIX, which says EXIT traps 626 * shall be taken in the environment 627 * immediately after the last command 628 * executed. 629 */ 630 if (toplevel) 631 unwind(LEXIT); 632 break; 633 } 634 } 635 636 if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) 637 exstat = execute(t, 0); 638 639 if (t != NULL && t->type != TEOF && interactive && really_exit) 640 really_exit = 0; 641 642 reclaim(); 643 } 644 quitenv(); 645 source = old_source; 646 return exstat; 647 } 648 649 /* return to closest error handler or shell(), exit if none found */ 650 void 651 unwind(i) 652 int i; 653 { 654 /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */ 655 if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) 656 && sigtraps[SIGEXIT_].trap)) 657 { 658 runtrap(&sigtraps[SIGEXIT_]); 659 i = LLEAVE; 660 } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) { 661 runtrap(&sigtraps[SIGERR_]); 662 i = LLEAVE; 663 } 664 while (1) { 665 switch (e->type) { 666 case E_PARSE: 667 case E_FUNC: 668 case E_INCL: 669 case E_LOOP: 670 case E_ERRH: 671 ksh_siglongjmp(e->jbuf, i); 672 /*NOTREACHED*/ 673 674 case E_NONE: 675 if (i == LINTR) 676 e->flags |= EF_FAKE_SIGDIE; 677 /* Fall through... */ 678 679 default: 680 quitenv(); 681 } 682 } 683 } 684 685 void 686 newenv(type) 687 int type; 688 { 689 register struct env *ep; 690 691 ep = (struct env *) alloc(sizeof(*ep), ATEMP); 692 ep->type = type; 693 ep->flags = 0; 694 ainit(&ep->area); 695 ep->loc = e->loc; 696 ep->savefd = NULL; 697 ep->oenv = e; 698 ep->temps = NULL; 699 e = ep; 700 } 701 702 void 703 quitenv() 704 { 705 register struct env *ep = e; 706 register int fd; 707 708 if (ep->oenv && ep->oenv->loc != ep->loc) 709 popblock(); 710 if (ep->savefd != NULL) { 711 for (fd = 0; fd < NUFILE; fd++) 712 /* if ep->savefd[fd] < 0, means fd was closed */ 713 if (ep->savefd[fd]) 714 restfd(fd, ep->savefd[fd]); 715 if (ep->savefd[2]) /* Clear any write errors */ 716 shf_reopen(2, SHF_WR, shl_out); 717 } 718 reclaim(); 719 720 /* Bottom of the stack. 721 * Either main shell is exiting or cleanup_parents_env() was called. 722 */ 723 if (ep->oenv == NULL) { 724 if (ep->type == E_NONE) { /* Main shell exiting? */ 725 if (Flag(FTALKING)) 726 hist_finish(); 727 j_exit(); 728 if (ep->flags & EF_FAKE_SIGDIE) { 729 int sig = exstat - 128; 730 731 /* ham up our death a bit (at&t ksh 732 * only seems to do this for SIGTERM) 733 * Don't do it for SIGQUIT, since we'd 734 * dump a core.. 735 */ 736 if (sig == SIGINT || sig == SIGTERM) { 737 setsig(&sigtraps[sig], SIG_DFL, 738 SS_RESTORE_CURR|SS_FORCE); 739 kill(0, sig); 740 } 741 } 742 #ifdef MEM_DEBUG 743 chmem_allfree(); 744 #endif /* MEM_DEBUG */ 745 } 746 exit(exstat); 747 } 748 749 e = e->oenv; 750 afree(ep, ATEMP); 751 } 752 753 /* Called after a fork to cleanup stuff left over from parents environment */ 754 void 755 cleanup_parents_env() 756 { 757 struct env *ep; 758 int fd; 759 760 /* Don't clean up temporary files - parent will probably need them. 761 * Also, can't easily reclaim memory since variables, etc. could be 762 * anywyere. 763 */ 764 765 /* close all file descriptors hiding in savefd */ 766 for (ep = e; ep; ep = ep->oenv) { 767 if (ep->savefd) { 768 for (fd = 0; fd < NUFILE; fd++) 769 if (ep->savefd[fd] > 0) 770 close(ep->savefd[fd]); 771 afree(ep->savefd, &ep->area); 772 ep->savefd = (short *) 0; 773 } 774 } 775 e->oenv = (struct env *) 0; 776 } 777 778 /* Called just before an execve cleanup stuff temporary files */ 779 void 780 cleanup_proc_env() 781 { 782 struct env *ep; 783 784 for (ep = e; ep; ep = ep->oenv) 785 remove_temps(ep->temps); 786 } 787 788 /* remove temp files and free ATEMP Area */ 789 static void 790 reclaim() 791 { 792 remove_temps(e->temps); 793 e->temps = NULL; 794 afreeall(&e->area); 795 } 796 797 static void 798 remove_temps(tp) 799 struct temp *tp; 800 { 801 #ifdef OS2 802 static struct temp *delayed_remove; 803 struct temp *t, **tprev; 804 805 if (delayed_remove) { 806 for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev) 807 /* No need to check t->pid here... */ 808 if (unlink(t->name) >= 0 || errno == ENOENT) { 809 *tprev = t->next; 810 afree(t, APERM); 811 } else 812 tprev = &t->next; 813 } 814 #endif /* OS2 */ 815 816 for (; tp != NULL; tp = tp->next) 817 if (tp->pid == procpid) { 818 #ifdef OS2 819 /* OS/2 (and dos) do not allow files that are currently 820 * open to be removed, so we cache it away for future 821 * removal. 822 * XXX should only do this if errno 823 * is Efile-still-open-can't-remove 824 * (but I don't know what that is...) 825 */ 826 if (unlink(tp->name) < 0 && errno != ENOENT) { 827 t = (struct temp *) alloc( 828 sizeof(struct temp) + strlen(tp->name) + 1, 829 APERM); 830 memset(t, 0, sizeof(struct temp)); 831 t->name = (char *) &t[1]; 832 strcpy(t->name, tp->name); 833 t->next = delayed_remove; 834 delayed_remove = t; 835 } 836 #else /* OS2 */ 837 unlink(tp->name); 838 #endif /* OS2 */ 839 } 840 } 841 842 /* Returns true if name refers to a restricted shell */ 843 static int 844 is_restricted(name) 845 char *name; 846 { 847 char *p; 848 849 if ((p = ksh_strrchr_dirsep(name))) 850 name = p; 851 /* accepts rsh, rksh, rpdksh, pdrksh, etc. */ 852 return (p = strchr(name, 'r')) && strstr(p, "sh"); 853 } 854 855 void 856 aerror(ap, msg) 857 Area *ap; 858 const char *msg; 859 { 860 internal_errorf(1, "alloc: %s", msg); 861 errorf(null); /* this is never executed - keeps gcc quiet */ 862 /*NOTREACHED*/ 863 } 864