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