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