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