17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier * startup, main loop, enviroments and error handling
37dd7cddfSDavid du Colombier */
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier #define EXTERN /* define EXTERNs in sh.h */
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier #include "sh.h"
87dd7cddfSDavid du Colombier #include "ksh_stat.h"
97dd7cddfSDavid du Colombier #include "ksh_time.h"
107dd7cddfSDavid du Colombier
117dd7cddfSDavid du Colombier extern char **environ;
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier /*
147dd7cddfSDavid du Colombier * global data
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier static void reclaim ARGS((void));
187dd7cddfSDavid du Colombier static void remove_temps ARGS((struct temp *tp));
197dd7cddfSDavid du Colombier static int is_restricted ARGS((char *name));
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier /*
227dd7cddfSDavid du Colombier * shell initialization
237dd7cddfSDavid du Colombier */
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier static const char initifs[] = "IFS= \t\n";
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier static const char initsubs[] = "${PS2=> } ${PS3=#? } ${PS4=+ }";
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier static const char version_param[] =
307dd7cddfSDavid du Colombier #ifdef KSH
317dd7cddfSDavid du Colombier "KSH_VERSION"
327dd7cddfSDavid du Colombier #else /* KSH */
337dd7cddfSDavid du Colombier "SH_VERSION"
347dd7cddfSDavid du Colombier #endif /* KSH */
357dd7cddfSDavid du Colombier ;
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static const char *const initcoms [] = {
387dd7cddfSDavid du Colombier "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
397dd7cddfSDavid du Colombier "typeset", "-r", version_param, NULL,
407dd7cddfSDavid du Colombier "typeset", "-i", "PPID", NULL,
417dd7cddfSDavid du Colombier "typeset", "-i", "OPTIND=1", NULL,
427dd7cddfSDavid du Colombier #ifdef KSH
437dd7cddfSDavid du Colombier "eval", "typeset -i RANDOM MAILCHECK=\"${MAILCHECK-600}\" SECONDS=\"${SECONDS-0}\" TMOUT=\"${TMOUT-0}\"", NULL,
447dd7cddfSDavid du Colombier #endif /* KSH */
457dd7cddfSDavid du Colombier "alias",
467dd7cddfSDavid du Colombier /* Standard ksh aliases */
477dd7cddfSDavid du Colombier "hash=alias -t", /* not "alias -t --": hash -r needs to work */
487dd7cddfSDavid du Colombier "type=whence -v",
497dd7cddfSDavid du Colombier #ifdef JOBS
507dd7cddfSDavid du Colombier "stop=kill -STOP",
517dd7cddfSDavid du Colombier "suspend=kill -STOP $$",
527dd7cddfSDavid du Colombier #endif
537dd7cddfSDavid du Colombier #ifdef KSH
547dd7cddfSDavid du Colombier "autoload=typeset -fu",
557dd7cddfSDavid du Colombier "functions=typeset -f",
567dd7cddfSDavid du Colombier # ifdef HISTORY
577dd7cddfSDavid du Colombier "history=fc -l",
587dd7cddfSDavid du Colombier # endif /* HISTORY */
597dd7cddfSDavid du Colombier "integer=typeset -i",
607dd7cddfSDavid du Colombier "nohup=nohup ",
617dd7cddfSDavid du Colombier "local=typeset",
627dd7cddfSDavid du Colombier "r=fc -e -",
637dd7cddfSDavid du Colombier #endif /* KSH */
647dd7cddfSDavid du Colombier #ifdef KSH
657dd7cddfSDavid du Colombier /* Aliases that are builtin commands in at&t */
667dd7cddfSDavid du Colombier "login=exec login",
677dd7cddfSDavid du Colombier "newgrp=exec newgrp",
687dd7cddfSDavid du Colombier #endif /* KSH */
697dd7cddfSDavid du Colombier NULL,
707dd7cddfSDavid du Colombier /* this is what at&t ksh seems to track, with the addition of emacs */
717dd7cddfSDavid du Colombier "alias", "-tU",
727dd7cddfSDavid du Colombier "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
737dd7cddfSDavid du Colombier "mail", "make", "mv", "pr", "rm", "sed", "sh", "vi", "who",
747dd7cddfSDavid du Colombier NULL,
757dd7cddfSDavid du Colombier #ifdef EXTRA_INITCOMS
767dd7cddfSDavid du Colombier EXTRA_INITCOMS, NULL,
777dd7cddfSDavid du Colombier #endif /* EXTRA_INITCOMS */
787dd7cddfSDavid du Colombier NULL
797dd7cddfSDavid du Colombier };
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier int
main(argc,argv)827dd7cddfSDavid du Colombier main(argc, argv)
837dd7cddfSDavid du Colombier int argc;
847dd7cddfSDavid du Colombier register char **argv;
857dd7cddfSDavid du Colombier {
867dd7cddfSDavid du Colombier register int i;
877dd7cddfSDavid du Colombier int argi;
887dd7cddfSDavid du Colombier Source *s;
897dd7cddfSDavid du Colombier struct block *l;
907dd7cddfSDavid du Colombier int restricted, errexit;
917dd7cddfSDavid du Colombier char **wp;
927dd7cddfSDavid du Colombier struct env env;
937dd7cddfSDavid du Colombier pid_t ppid;
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier #ifdef MEM_DEBUG
967dd7cddfSDavid du Colombier chmem_set_defaults("ct", 1);
977dd7cddfSDavid du Colombier /* chmem_push("+c", 1); */
987dd7cddfSDavid du Colombier #endif /* MEM_DEBUG */
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier #ifdef OS2
1017dd7cddfSDavid du Colombier setmode (0, O_BINARY);
1027dd7cddfSDavid du Colombier setmode (1, O_TEXT);
1037dd7cddfSDavid du Colombier #endif
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier /* make sure argv[] is sane */
1067dd7cddfSDavid du Colombier if (!*argv) {
1077dd7cddfSDavid du Colombier static const char *empty_argv[] = {
1087dd7cddfSDavid du Colombier "pdksh", (char *) 0
1097dd7cddfSDavid du Colombier };
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier argv = (char **) empty_argv;
1127dd7cddfSDavid du Colombier argc = 1;
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier kshname = *argv;
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier ainit(&aperm); /* initialize permanent Area */
1177dd7cddfSDavid du Colombier
1187dd7cddfSDavid du Colombier /* set up base enviroment */
1197dd7cddfSDavid du Colombier memset(&env, 0, sizeof(env));
1207dd7cddfSDavid du Colombier env.type = E_NONE;
1217dd7cddfSDavid du Colombier ainit(&env.area);
1227dd7cddfSDavid du Colombier e = &env;
1237dd7cddfSDavid du Colombier newblock(); /* set up global l->vars and l->funs */
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier /* Do this first so output routines (eg, errorf, shellf) can work */
1267dd7cddfSDavid du Colombier initio();
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier initvar();
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier initctypes();
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier inittraps();
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier #ifdef KSH
1357dd7cddfSDavid du Colombier coproc_init();
1367dd7cddfSDavid du Colombier #endif /* KSH */
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier /* set up variable and command dictionaries */
1397dd7cddfSDavid du Colombier tinit(&taliases, APERM, 0);
1407dd7cddfSDavid du Colombier tinit(&aliases, APERM, 0);
1417dd7cddfSDavid du Colombier tinit(&homedirs, APERM, 0);
1427dd7cddfSDavid du Colombier
1437dd7cddfSDavid du Colombier /* define shell keywords */
1447dd7cddfSDavid du Colombier initkeywords();
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier /* define built-in commands */
1477dd7cddfSDavid du Colombier tinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */
1487dd7cddfSDavid du Colombier for (i = 0; shbuiltins[i].name != NULL; i++)
1497dd7cddfSDavid du Colombier builtin(shbuiltins[i].name, shbuiltins[i].func);
1507dd7cddfSDavid du Colombier for (i = 0; kshbuiltins[i].name != NULL; i++)
1517dd7cddfSDavid du Colombier builtin(kshbuiltins[i].name, kshbuiltins[i].func);
1527dd7cddfSDavid du Colombier
1537dd7cddfSDavid du Colombier init_histvec();
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier def_path = DEFAULT__PATH;
1567dd7cddfSDavid du Colombier #if defined(HAVE_CONFSTR) && defined(_CS_PATH)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier size_t len = confstr(_CS_PATH, (char *) 0, 0);
1597dd7cddfSDavid du Colombier char *new;
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier if (len > 0) {
1627dd7cddfSDavid du Colombier confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1);
1637dd7cddfSDavid du Colombier def_path = new;
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier #endif /* HAVE_CONFSTR && _CS_PATH */
1677dd7cddfSDavid du Colombier
1687dd7cddfSDavid du Colombier /* Set PATH to def_path (will set the path global variable).
1697dd7cddfSDavid du Colombier * (import of environment below will probably change this setting).
1707dd7cddfSDavid du Colombier */
1717dd7cddfSDavid du Colombier {
1727dd7cddfSDavid du Colombier struct tbl *vp = global("PATH");
1737dd7cddfSDavid du Colombier /* setstr can't fail here */
1747dd7cddfSDavid du Colombier setstr(vp, def_path, KSH_RETURN_ERROR);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier /* Turn on nohup by default for how - will change to off
1797dd7cddfSDavid du Colombier * by default once people are aware of its existance
1807dd7cddfSDavid du Colombier * (at&t ksh does not have a nohup option - it always sends
1817dd7cddfSDavid du Colombier * the hup).
1827dd7cddfSDavid du Colombier */
1837dd7cddfSDavid du Colombier Flag(FNOHUP) = 1;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier /* Turn on brace expansion by default. At&t ksh's that have
1867dd7cddfSDavid du Colombier * alternation always have it on. BUT, posix doesn't have
1877dd7cddfSDavid du Colombier * brace expansion, so set this before setting up FPOSIX
1887dd7cddfSDavid du Colombier * (change_flag() clears FBRACEEXPAND when FPOSIX is set).
1897dd7cddfSDavid du Colombier */
1907dd7cddfSDavid du Colombier #ifdef BRACE_EXPAND
1917dd7cddfSDavid du Colombier Flag(FBRACEEXPAND) = 1;
1927dd7cddfSDavid du Colombier #endif /* BRACE_EXPAND */
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier /* set posix flag just before environment so that it will have
1957dd7cddfSDavid du Colombier * exactly the same effect as the POSIXLY_CORRECT environment
1967dd7cddfSDavid du Colombier * variable. If this needs to be done sooner to ensure correct posix
1977dd7cddfSDavid du Colombier * operation, an initial scan of the environment will also have
1987dd7cddfSDavid du Colombier * done sooner.
1997dd7cddfSDavid du Colombier */
2007dd7cddfSDavid du Colombier #ifdef POSIXLY_CORRECT
2017dd7cddfSDavid du Colombier change_flag(FPOSIX, OF_SPECIAL, 1);
2027dd7cddfSDavid du Colombier #endif /* POSIXLY_CORRECT */
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier /* import enviroment */
2057dd7cddfSDavid du Colombier if (environ != NULL)
2067dd7cddfSDavid du Colombier for (wp = environ; *wp != NULL; wp++)
2077dd7cddfSDavid du Colombier typeset(*wp, IMPORT|EXPORT, 0, 0, 0);
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier kshpid = procpid = getpid();
2107dd7cddfSDavid du Colombier typeset(initifs, 0, 0, 0, 0); /* for security */
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier /* assign default shell variable values */
2137dd7cddfSDavid du Colombier substitute(initsubs, 0);
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier /* Figure out the current working directory and set $PWD */
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier struct stat s_pwd, s_dot;
2187dd7cddfSDavid du Colombier struct tbl *pwd_v = global("PWD");
2197dd7cddfSDavid du Colombier char *pwd = str_val(pwd_v);
2207dd7cddfSDavid du Colombier char *pwdx = pwd;
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier /* Try to use existing $PWD if it is valid */
2237dd7cddfSDavid du Colombier if (!ISABSPATH(pwd)
2247dd7cddfSDavid du Colombier || stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0
2257dd7cddfSDavid du Colombier || s_pwd.st_dev != s_dot.st_dev
2267dd7cddfSDavid du Colombier || s_pwd.st_ino != s_dot.st_ino)
2277dd7cddfSDavid du Colombier pwdx = (char *) 0;
2287dd7cddfSDavid du Colombier set_current_wd(pwdx);
2297dd7cddfSDavid du Colombier if (current_wd[0])
2307dd7cddfSDavid du Colombier simplify_path(current_wd);
2317dd7cddfSDavid du Colombier /* Only set pwd if we know where we are or if it had a
2327dd7cddfSDavid du Colombier * bogus value
2337dd7cddfSDavid du Colombier */
2347dd7cddfSDavid du Colombier if (current_wd[0] || pwd != null)
2357dd7cddfSDavid du Colombier /* setstr can't fail here */
2367dd7cddfSDavid du Colombier setstr(pwd_v, current_wd, KSH_RETURN_ERROR);
2377dd7cddfSDavid du Colombier }
2387dd7cddfSDavid du Colombier ppid = getppid();
2397dd7cddfSDavid du Colombier setint(global("PPID"), (long) ppid);
2407dd7cddfSDavid du Colombier #ifdef KSH
2417dd7cddfSDavid du Colombier setint(global("RANDOM"), (long) (time((time_t *)0) * kshpid * ppid));
2427dd7cddfSDavid du Colombier #endif /* KSH */
2437dd7cddfSDavid du Colombier /* setstr can't fail here */
2447dd7cddfSDavid du Colombier setstr(global(version_param), ksh_version, KSH_RETURN_ERROR);
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier /* execute initialization statements */
2477dd7cddfSDavid du Colombier for (wp = (char**) initcoms; *wp != NULL; wp++) {
2487dd7cddfSDavid du Colombier shcomexec(wp);
2497dd7cddfSDavid du Colombier for (; *wp != NULL; wp++)
2507dd7cddfSDavid du Colombier ;
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier
2547dd7cddfSDavid du Colombier ksheuid = geteuid();
2557dd7cddfSDavid du Colombier safe_prompt = ksheuid ? "$ " : "# ";
2567dd7cddfSDavid du Colombier {
2577dd7cddfSDavid du Colombier struct tbl *vp = global("PS1");
2587dd7cddfSDavid du Colombier
2597dd7cddfSDavid du Colombier /* Set PS1 if it isn't set, or we are root and prompt doesn't
2607dd7cddfSDavid du Colombier * contain a #.
2617dd7cddfSDavid du Colombier */
2627dd7cddfSDavid du Colombier if (!(vp->flag & ISSET)
2637dd7cddfSDavid du Colombier || (!ksheuid && !strchr(str_val(vp), '#')))
2647dd7cddfSDavid du Colombier /* setstr can't fail here */
2657dd7cddfSDavid du Colombier setstr(vp, safe_prompt, KSH_RETURN_ERROR);
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier /* Set this before parsing arguments */
2697dd7cddfSDavid du Colombier Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid();
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier /* this to note if monitor is set on command line (see below) */
2727dd7cddfSDavid du Colombier Flag(FMONITOR) = 127;
2737dd7cddfSDavid du Colombier argi = parse_args(argv, OF_CMDLINE, (int *) 0);
2747dd7cddfSDavid du Colombier if (argi < 0)
2757dd7cddfSDavid du Colombier exit(1);
2767dd7cddfSDavid du Colombier
2777dd7cddfSDavid du Colombier if (Flag(FCOMMAND)) {
2787dd7cddfSDavid du Colombier s = pushs(SSTRING, ATEMP);
2797dd7cddfSDavid du Colombier if (!(s->start = s->str = argv[argi++]))
2807dd7cddfSDavid du Colombier errorf("-c requires an argument");
2817dd7cddfSDavid du Colombier if (argv[argi])
2827dd7cddfSDavid du Colombier kshname = argv[argi++];
2837dd7cddfSDavid du Colombier } else if (argi < argc && !Flag(FSTDIN)) {
2847dd7cddfSDavid du Colombier s = pushs(SFILE, ATEMP);
2857dd7cddfSDavid du Colombier #ifdef OS2
2867dd7cddfSDavid du Colombier /* a bug in os2 extproc shell processing doesn't
2877dd7cddfSDavid du Colombier * pass full pathnames so we have to search for it.
2887dd7cddfSDavid du Colombier * This changes the behavior of 'ksh arg' to search
2897dd7cddfSDavid du Colombier * the users search path but it can't be helped.
2907dd7cddfSDavid du Colombier */
2917dd7cddfSDavid du Colombier s->file = search(argv[argi++], path, R_OK, (int *) 0);
2927dd7cddfSDavid du Colombier if (!s->file || !*s->file)
2937dd7cddfSDavid du Colombier s->file = argv[argi - 1];
2947dd7cddfSDavid du Colombier #else
2957dd7cddfSDavid du Colombier s->file = argv[argi++];
2967dd7cddfSDavid du Colombier #endif /* OS2 */
2977dd7cddfSDavid du Colombier s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
2987dd7cddfSDavid du Colombier if (s->u.shf == NULL) {
2997dd7cddfSDavid du Colombier exstat = 127; /* POSIX */
3007dd7cddfSDavid du Colombier errorf("%s: %s", s->file, strerror(errno));
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier kshname = s->file;
3037dd7cddfSDavid du Colombier } else {
3047dd7cddfSDavid du Colombier Flag(FSTDIN) = 1;
3057dd7cddfSDavid du Colombier s = pushs(SSTDIN, ATEMP);
3067dd7cddfSDavid du Colombier s->file = "<stdin>";
3077dd7cddfSDavid du Colombier s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),
3087dd7cddfSDavid du Colombier (struct shf *) 0);
309223a736eSDavid du Colombier if (!Flag(FNOTTALKING) && isatty(0) && isatty(2)) {
3107dd7cddfSDavid du Colombier Flag(FTALKING) = Flag(FTALKING_I) = 1;
3117dd7cddfSDavid du Colombier /* The following only if isatty(0) */
3127dd7cddfSDavid du Colombier s->flags |= SF_TTY;
3137dd7cddfSDavid du Colombier s->u.shf->flags |= SHF_INTERRUPT;
3147dd7cddfSDavid du Colombier s->file = (char *) 0;
3157dd7cddfSDavid du Colombier }
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier
3187dd7cddfSDavid du Colombier /* This bizarreness is mandated by POSIX */
3197dd7cddfSDavid du Colombier {
3207dd7cddfSDavid du Colombier struct stat s_stdin;
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode))
3237dd7cddfSDavid du Colombier reset_nonblock(0);
3247dd7cddfSDavid du Colombier }
3257dd7cddfSDavid du Colombier
3267dd7cddfSDavid du Colombier /* initialize job control */
3277dd7cddfSDavid du Colombier i = Flag(FMONITOR) != 127;
3287dd7cddfSDavid du Colombier Flag(FMONITOR) = 0;
3297dd7cddfSDavid du Colombier j_init(i);
3307dd7cddfSDavid du Colombier #ifdef EDIT
3317dd7cddfSDavid du Colombier /* Do this after j_init(), as tty_fd is not initialized 'til then */
3327dd7cddfSDavid du Colombier if (Flag(FTALKING))
3337dd7cddfSDavid du Colombier x_init();
3347dd7cddfSDavid du Colombier #endif
3357dd7cddfSDavid du Colombier
3367dd7cddfSDavid du Colombier l = e->loc;
3377dd7cddfSDavid du Colombier l->argv = &argv[argi - 1];
3387dd7cddfSDavid du Colombier l->argc = argc - argi;
3397dd7cddfSDavid du Colombier l->argv[0] = (char *) kshname;
3407dd7cddfSDavid du Colombier getopts_reset(1);
3417dd7cddfSDavid du Colombier
3427dd7cddfSDavid du Colombier /* Disable during .profile/ENV reading */
3437dd7cddfSDavid du Colombier restricted = Flag(FRESTRICTED);
3447dd7cddfSDavid du Colombier Flag(FRESTRICTED) = 0;
3457dd7cddfSDavid du Colombier errexit = Flag(FERREXIT);
3467dd7cddfSDavid du Colombier Flag(FERREXIT) = 0;
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier /* Do this before profile/$ENV so that if it causes problems in them,
3497dd7cddfSDavid du Colombier * user will know why things broke.
3507dd7cddfSDavid du Colombier */
3517dd7cddfSDavid du Colombier if (!current_wd[0] && Flag(FTALKING))
3527dd7cddfSDavid du Colombier warningf(FALSE, "Cannot determine current working directory");
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier if (Flag(FLOGIN)) {
3557dd7cddfSDavid du Colombier #ifdef OS2
3567dd7cddfSDavid du Colombier char *profile;
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier /* Try to find a profile - first see if $INIT has a value,
3597dd7cddfSDavid du Colombier * then try /etc/profile.ksh, then c:/usr/etc/profile.ksh.
3607dd7cddfSDavid du Colombier */
3617dd7cddfSDavid du Colombier if (!Flag(FPRIVILEGED)
3627dd7cddfSDavid du Colombier && strcmp(profile = substitute("$INIT/profile.ksh", 0),
3637dd7cddfSDavid du Colombier "/profile.ksh"))
3647dd7cddfSDavid du Colombier include(profile, 0, (char **) 0, 1);
3657dd7cddfSDavid du Colombier else if (include("/etc/profile.ksh", 0, (char **) 0, 1) < 0)
3667dd7cddfSDavid du Colombier include("c:/usr/etc/profile.ksh", 0, (char **) 0, 1);
3677dd7cddfSDavid du Colombier if (!Flag(FPRIVILEGED))
3687dd7cddfSDavid du Colombier include(substitute("$HOME/profile.ksh", 0), 0,
3697dd7cddfSDavid du Colombier (char **) 0, 1);
3707dd7cddfSDavid du Colombier #else /* OS2 */
3717dd7cddfSDavid du Colombier include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1);
3727dd7cddfSDavid du Colombier if (!Flag(FPRIVILEGED))
3737dd7cddfSDavid du Colombier include(substitute("$HOME/.profile", 0), 0,
3747dd7cddfSDavid du Colombier (char **) 0, 1);
3757dd7cddfSDavid du Colombier #endif /* OS2 */
3767dd7cddfSDavid du Colombier }
3777dd7cddfSDavid du Colombier
3787dd7cddfSDavid du Colombier if (Flag(FPRIVILEGED))
3797dd7cddfSDavid du Colombier include("/etc/suid_profile", 0, (char **) 0, 1);
3807dd7cddfSDavid du Colombier else {
3817dd7cddfSDavid du Colombier char *env_file;
3827dd7cddfSDavid du Colombier
3837dd7cddfSDavid du Colombier #ifndef KSH
3847dd7cddfSDavid du Colombier if (!Flag(FPOSIX))
3857dd7cddfSDavid du Colombier env_file = null;
3867dd7cddfSDavid du Colombier else
3877dd7cddfSDavid du Colombier #endif /* !KSH */
3887dd7cddfSDavid du Colombier /* include $ENV */
3897dd7cddfSDavid du Colombier env_file = str_val(global("ENV"));
3907dd7cddfSDavid du Colombier
3917dd7cddfSDavid du Colombier #ifdef DEFAULT_ENV
3927dd7cddfSDavid du Colombier /* If env isn't set, include default environment */
3937dd7cddfSDavid du Colombier if (env_file == null)
3947dd7cddfSDavid du Colombier env_file = DEFAULT_ENV;
3957dd7cddfSDavid du Colombier #endif /* DEFAULT_ENV */
3967dd7cddfSDavid du Colombier env_file = substitute(env_file, DOTILDE);
3977dd7cddfSDavid du Colombier if (*env_file != '\0')
3987dd7cddfSDavid du Colombier include(env_file, 0, (char **) 0, 1);
3997dd7cddfSDavid du Colombier #ifdef OS2
4007dd7cddfSDavid du Colombier else if (Flag(FTALKING))
4017dd7cddfSDavid du Colombier include(substitute("$HOME/kshrc.ksh", 0), 0,
4027dd7cddfSDavid du Colombier (char **) 0, 1);
4037dd7cddfSDavid du Colombier #endif /* OS2 */
4047dd7cddfSDavid du Colombier }
4057dd7cddfSDavid du Colombier
4067dd7cddfSDavid du Colombier if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL"))))
4077dd7cddfSDavid du Colombier restricted = 1;
4087dd7cddfSDavid du Colombier if (restricted) {
4097dd7cddfSDavid du Colombier static const char *const restr_com[] = {
4107dd7cddfSDavid du Colombier "typeset", "-r", "PATH",
4117dd7cddfSDavid du Colombier "ENV", "SHELL",
4127dd7cddfSDavid du Colombier (char *) 0
4137dd7cddfSDavid du Colombier };
4147dd7cddfSDavid du Colombier shcomexec((char **) restr_com);
4157dd7cddfSDavid du Colombier /* After typeset command... */
4167dd7cddfSDavid du Colombier Flag(FRESTRICTED) = 1;
4177dd7cddfSDavid du Colombier }
4187dd7cddfSDavid du Colombier if (errexit)
4197dd7cddfSDavid du Colombier Flag(FERREXIT) = 1;
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier if (Flag(FTALKING)) {
4227dd7cddfSDavid du Colombier hist_init(s);
4237dd7cddfSDavid du Colombier #ifdef KSH
4247dd7cddfSDavid du Colombier alarm_init();
4257dd7cddfSDavid du Colombier #endif /* KSH */
4267dd7cddfSDavid du Colombier } else
4277dd7cddfSDavid du Colombier Flag(FTRACKALL) = 1; /* set after ENV */
4287dd7cddfSDavid du Colombier
4297dd7cddfSDavid du Colombier shell(s, TRUE); /* doesn't return */
4307dd7cddfSDavid du Colombier return 0;
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier
4337dd7cddfSDavid du Colombier int
include(name,argc,argv,intr_ok)4347dd7cddfSDavid du Colombier include(name, argc, argv, intr_ok)
4357dd7cddfSDavid du Colombier const char *name;
4367dd7cddfSDavid du Colombier int argc;
4377dd7cddfSDavid du Colombier char **argv;
4387dd7cddfSDavid du Colombier int intr_ok;
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier register Source *volatile s = NULL;
4417dd7cddfSDavid du Colombier Source *volatile sold;
4427dd7cddfSDavid du Colombier struct shf *shf;
4437dd7cddfSDavid du Colombier char **volatile old_argv;
4447dd7cddfSDavid du Colombier volatile int old_argc;
4457dd7cddfSDavid du Colombier int i;
4467dd7cddfSDavid du Colombier
4477dd7cddfSDavid du Colombier shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
4487dd7cddfSDavid du Colombier if (shf == NULL)
4497dd7cddfSDavid du Colombier return -1;
4507dd7cddfSDavid du Colombier
4517dd7cddfSDavid du Colombier if (argv) {
4527dd7cddfSDavid du Colombier old_argv = e->loc->argv;
4537dd7cddfSDavid du Colombier old_argc = e->loc->argc;
4547dd7cddfSDavid du Colombier } else {
4557dd7cddfSDavid du Colombier old_argv = (char **) 0;
4567dd7cddfSDavid du Colombier old_argc = 0;
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier sold = source;
4597dd7cddfSDavid du Colombier newenv(E_INCL);
4607dd7cddfSDavid du Colombier i = ksh_sigsetjmp(e->jbuf, 0);
4617dd7cddfSDavid du Colombier if (i) {
4627dd7cddfSDavid du Colombier source = sold;
4637dd7cddfSDavid du Colombier if (s) /* Do this before quitenv(), which frees the memory */
4647dd7cddfSDavid du Colombier shf_close(s->u.shf);
4657dd7cddfSDavid du Colombier quitenv();
4667dd7cddfSDavid du Colombier if (old_argv) {
4677dd7cddfSDavid du Colombier e->loc->argv = old_argv;
4687dd7cddfSDavid du Colombier e->loc->argc = old_argc;
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier switch (i) {
4717dd7cddfSDavid du Colombier case LRETURN:
4727dd7cddfSDavid du Colombier case LERROR:
4737dd7cddfSDavid du Colombier return exstat & 0xff; /* see below */
4747dd7cddfSDavid du Colombier case LINTR:
4757dd7cddfSDavid du Colombier /* intr_ok is set if we are including .profile or $ENV.
4767dd7cddfSDavid du Colombier * If user ^C's out, we don't want to kill the shell...
4777dd7cddfSDavid du Colombier */
4787dd7cddfSDavid du Colombier if (intr_ok && (exstat - 128) != SIGTERM)
4797dd7cddfSDavid du Colombier return 1;
4807dd7cddfSDavid du Colombier /* fall through... */
4817dd7cddfSDavid du Colombier case LEXIT:
4827dd7cddfSDavid du Colombier case LLEAVE:
4837dd7cddfSDavid du Colombier case LSHELL:
4847dd7cddfSDavid du Colombier unwind(i);
4857dd7cddfSDavid du Colombier /*NOREACHED*/
4867dd7cddfSDavid du Colombier default:
4877dd7cddfSDavid du Colombier internal_errorf(1, "include: %d", i);
4887dd7cddfSDavid du Colombier /*NOREACHED*/
4897dd7cddfSDavid du Colombier }
4907dd7cddfSDavid du Colombier }
4917dd7cddfSDavid du Colombier if (argv) {
4927dd7cddfSDavid du Colombier e->loc->argv = argv;
4937dd7cddfSDavid du Colombier e->loc->argc = argc;
4947dd7cddfSDavid du Colombier }
4957dd7cddfSDavid du Colombier s = pushs(SFILE, ATEMP);
4967dd7cddfSDavid du Colombier s->u.shf = shf;
4977dd7cddfSDavid du Colombier s->file = str_save(name, ATEMP);
4987dd7cddfSDavid du Colombier i = shell(s, FALSE);
4997dd7cddfSDavid du Colombier source = sold;
5007dd7cddfSDavid du Colombier shf_close(s->u.shf);
5017dd7cddfSDavid du Colombier quitenv();
5027dd7cddfSDavid du Colombier if (old_argv) {
5037dd7cddfSDavid du Colombier e->loc->argv = old_argv;
5047dd7cddfSDavid du Colombier e->loc->argc = old_argc;
5057dd7cddfSDavid du Colombier }
5067dd7cddfSDavid du Colombier return i & 0xff; /* & 0xff to ensure value not -1 */
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier int
command(comm)5107dd7cddfSDavid du Colombier command(comm)
5117dd7cddfSDavid du Colombier const char *comm;
5127dd7cddfSDavid du Colombier {
5137dd7cddfSDavid du Colombier register Source *s;
5147dd7cddfSDavid du Colombier
5157dd7cddfSDavid du Colombier s = pushs(SSTRING, ATEMP);
5167dd7cddfSDavid du Colombier s->start = s->str = comm;
5177dd7cddfSDavid du Colombier return shell(s, FALSE);
5187dd7cddfSDavid du Colombier }
5197dd7cddfSDavid du Colombier
5207dd7cddfSDavid du Colombier /*
5217dd7cddfSDavid du Colombier * run the commands from the input source, returning status.
5227dd7cddfSDavid du Colombier */
5237dd7cddfSDavid du Colombier int
shell(s,toplevel)5247dd7cddfSDavid du Colombier shell(s, toplevel)
5257dd7cddfSDavid du Colombier Source *volatile s; /* input source */
5267dd7cddfSDavid du Colombier int volatile toplevel;
5277dd7cddfSDavid du Colombier {
5287dd7cddfSDavid du Colombier struct op *t;
5297dd7cddfSDavid du Colombier volatile int wastty = s->flags & SF_TTY;
5307dd7cddfSDavid du Colombier volatile int attempts = 13;
5317dd7cddfSDavid du Colombier volatile int interactive = Flag(FTALKING) && toplevel;
5327dd7cddfSDavid du Colombier int i;
5337dd7cddfSDavid du Colombier
5347dd7cddfSDavid du Colombier newenv(E_PARSE);
5357dd7cddfSDavid du Colombier if (interactive)
5367dd7cddfSDavid du Colombier really_exit = 0;
5377dd7cddfSDavid du Colombier i = ksh_sigsetjmp(e->jbuf, 0);
5387dd7cddfSDavid du Colombier if (i) {
5397dd7cddfSDavid du Colombier s->start = s->str = null;
5407dd7cddfSDavid du Colombier switch (i) {
5417dd7cddfSDavid du Colombier case LINTR: /* we get here if SIGINT not caught or ignored */
5427dd7cddfSDavid du Colombier case LERROR:
5437dd7cddfSDavid du Colombier case LSHELL:
5447dd7cddfSDavid du Colombier if (interactive) {
5457dd7cddfSDavid du Colombier if (i == LINTR)
5467dd7cddfSDavid du Colombier shellf(newline);
5477dd7cddfSDavid du Colombier /* Reset any eof that was read as part of a
5487dd7cddfSDavid du Colombier * multiline command.
5497dd7cddfSDavid du Colombier */
5507dd7cddfSDavid du Colombier if (Flag(FIGNOREEOF) && s->type == SEOF
5517dd7cddfSDavid du Colombier && wastty)
5527dd7cddfSDavid du Colombier s->type = SSTDIN;
5537dd7cddfSDavid du Colombier /* Used by exit command to get back to
5547dd7cddfSDavid du Colombier * top level shell. Kind of strange since
5557dd7cddfSDavid du Colombier * interactive is set if we are reading from
5567dd7cddfSDavid du Colombier * a tty, but to have stopped jobs, one only
5577dd7cddfSDavid du Colombier * needs FMONITOR set (not FTALKING/SF_TTY)...
5587dd7cddfSDavid du Colombier */
5597dd7cddfSDavid du Colombier break;
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier /* fall through... */
5627dd7cddfSDavid du Colombier case LEXIT:
5637dd7cddfSDavid du Colombier case LLEAVE:
5647dd7cddfSDavid du Colombier case LRETURN:
5657dd7cddfSDavid du Colombier quitenv();
5667dd7cddfSDavid du Colombier unwind(i); /* keep on going */
5677dd7cddfSDavid du Colombier /*NOREACHED*/
5687dd7cddfSDavid du Colombier default:
5697dd7cddfSDavid du Colombier quitenv();
5707dd7cddfSDavid du Colombier internal_errorf(1, "shell: %d", i);
5717dd7cddfSDavid du Colombier /*NOREACHED*/
5727dd7cddfSDavid du Colombier }
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier
5757dd7cddfSDavid du Colombier while (1) {
5767dd7cddfSDavid du Colombier if (trap)
5777dd7cddfSDavid du Colombier runtraps(0);
5787dd7cddfSDavid du Colombier
5797dd7cddfSDavid du Colombier if (s->next == NULL)
5807dd7cddfSDavid du Colombier if (Flag(FVERBOSE))
5817dd7cddfSDavid du Colombier s->flags |= SF_ECHO;
5827dd7cddfSDavid du Colombier else
5837dd7cddfSDavid du Colombier s->flags &= ~SF_ECHO;
5847dd7cddfSDavid du Colombier
5857dd7cddfSDavid du Colombier if (interactive) {
5867dd7cddfSDavid du Colombier j_notify();
5877dd7cddfSDavid du Colombier #ifdef KSH
5887dd7cddfSDavid du Colombier mcheck();
5897dd7cddfSDavid du Colombier #endif /* KSH */
5907dd7cddfSDavid du Colombier set_prompt(PS1, s);
5917dd7cddfSDavid du Colombier }
5927dd7cddfSDavid du Colombier
5937dd7cddfSDavid du Colombier t = compile(s);
5947dd7cddfSDavid du Colombier if (t != NULL && t->type == TEOF) {
5957dd7cddfSDavid du Colombier if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {
5967dd7cddfSDavid du Colombier shellf("Use `exit' to leave ksh\n");
5977dd7cddfSDavid du Colombier s->type = SSTDIN;
5987dd7cddfSDavid du Colombier } else if (wastty && !really_exit
5997dd7cddfSDavid du Colombier && j_stopped_running())
6007dd7cddfSDavid du Colombier {
6017dd7cddfSDavid du Colombier really_exit = 1;
6027dd7cddfSDavid du Colombier s->type = SSTDIN;
6037dd7cddfSDavid du Colombier } else {
6047dd7cddfSDavid du Colombier /* this for POSIX, which says EXIT traps
6057dd7cddfSDavid du Colombier * shall be taken in the environment
6067dd7cddfSDavid du Colombier * immediately after the last command
6077dd7cddfSDavid du Colombier * executed.
6087dd7cddfSDavid du Colombier */
6097dd7cddfSDavid du Colombier if (toplevel)
6107dd7cddfSDavid du Colombier unwind(LEXIT);
6117dd7cddfSDavid du Colombier break;
6127dd7cddfSDavid du Colombier }
6137dd7cddfSDavid du Colombier }
6147dd7cddfSDavid du Colombier
6157dd7cddfSDavid du Colombier if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY)))
6167dd7cddfSDavid du Colombier exstat = execute(t, 0);
6177dd7cddfSDavid du Colombier
6187dd7cddfSDavid du Colombier if (t != NULL && t->type != TEOF && interactive && really_exit)
6197dd7cddfSDavid du Colombier really_exit = 0;
6207dd7cddfSDavid du Colombier
6217dd7cddfSDavid du Colombier reclaim();
6227dd7cddfSDavid du Colombier }
6237dd7cddfSDavid du Colombier quitenv();
6247dd7cddfSDavid du Colombier return exstat;
6257dd7cddfSDavid du Colombier }
6267dd7cddfSDavid du Colombier
6277dd7cddfSDavid du Colombier /* return to closest error handler or shell(), exit if none found */
6287dd7cddfSDavid du Colombier void
unwind(i)6297dd7cddfSDavid du Colombier unwind(i)
6307dd7cddfSDavid du Colombier int i;
6317dd7cddfSDavid du Colombier {
6327dd7cddfSDavid du Colombier /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
6337dd7cddfSDavid du Colombier if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR)
6347dd7cddfSDavid du Colombier && sigtraps[SIGEXIT_].trap))
6357dd7cddfSDavid du Colombier {
6367dd7cddfSDavid du Colombier runtrap(&sigtraps[SIGEXIT_]);
6377dd7cddfSDavid du Colombier i = LLEAVE;
6387dd7cddfSDavid du Colombier } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) {
6397dd7cddfSDavid du Colombier runtrap(&sigtraps[SIGERR_]);
6407dd7cddfSDavid du Colombier i = LLEAVE;
6417dd7cddfSDavid du Colombier }
6427dd7cddfSDavid du Colombier while (1) {
6437dd7cddfSDavid du Colombier switch (e->type) {
6447dd7cddfSDavid du Colombier case E_PARSE:
6457dd7cddfSDavid du Colombier case E_FUNC:
6467dd7cddfSDavid du Colombier case E_INCL:
6477dd7cddfSDavid du Colombier case E_LOOP:
6487dd7cddfSDavid du Colombier case E_ERRH:
6497dd7cddfSDavid du Colombier ksh_siglongjmp(e->jbuf, i);
6507dd7cddfSDavid du Colombier /*NOTREACHED*/
6517dd7cddfSDavid du Colombier
6527dd7cddfSDavid du Colombier case E_NONE:
6537dd7cddfSDavid du Colombier if (i == LINTR)
6547dd7cddfSDavid du Colombier e->flags |= EF_FAKE_SIGDIE;
6557dd7cddfSDavid du Colombier /* Fall through... */
6567dd7cddfSDavid du Colombier
6577dd7cddfSDavid du Colombier default:
6587dd7cddfSDavid du Colombier quitenv();
6597dd7cddfSDavid du Colombier }
6607dd7cddfSDavid du Colombier }
6617dd7cddfSDavid du Colombier }
6627dd7cddfSDavid du Colombier
6637dd7cddfSDavid du Colombier void
newenv(type)6647dd7cddfSDavid du Colombier newenv(type)
6657dd7cddfSDavid du Colombier int type;
6667dd7cddfSDavid du Colombier {
6677dd7cddfSDavid du Colombier register struct env *ep;
6687dd7cddfSDavid du Colombier
6697dd7cddfSDavid du Colombier ep = (struct env *) alloc(sizeof(*ep), ATEMP);
6707dd7cddfSDavid du Colombier ep->type = type;
6717dd7cddfSDavid du Colombier ep->flags = 0;
6727dd7cddfSDavid du Colombier ainit(&ep->area);
6737dd7cddfSDavid du Colombier ep->loc = e->loc;
6747dd7cddfSDavid du Colombier ep->savefd = NULL;
6757dd7cddfSDavid du Colombier ep->oenv = e;
6767dd7cddfSDavid du Colombier ep->temps = NULL;
6777dd7cddfSDavid du Colombier e = ep;
6787dd7cddfSDavid du Colombier }
6797dd7cddfSDavid du Colombier
6807dd7cddfSDavid du Colombier void
quitenv()6817dd7cddfSDavid du Colombier quitenv()
6827dd7cddfSDavid du Colombier {
6837dd7cddfSDavid du Colombier register struct env *ep = e;
6847dd7cddfSDavid du Colombier register int fd;
6857dd7cddfSDavid du Colombier
6867dd7cddfSDavid du Colombier if (ep->oenv && ep->oenv->loc != ep->loc)
6877dd7cddfSDavid du Colombier popblock();
6887dd7cddfSDavid du Colombier if (ep->savefd != NULL) {
6897dd7cddfSDavid du Colombier for (fd = 0; fd < NUFILE; fd++)
6907dd7cddfSDavid du Colombier /* if ep->savefd[fd] < 0, means fd was closed */
6917dd7cddfSDavid du Colombier if (ep->savefd[fd])
6927dd7cddfSDavid du Colombier restfd(fd, ep->savefd[fd]);
6937dd7cddfSDavid du Colombier if (ep->savefd[2]) /* Clear any write errors */
6947dd7cddfSDavid du Colombier shf_reopen(2, SHF_WR, shl_out);
6957dd7cddfSDavid du Colombier }
6967dd7cddfSDavid du Colombier reclaim();
6977dd7cddfSDavid du Colombier
6987dd7cddfSDavid du Colombier /* Bottom of the stack.
6997dd7cddfSDavid du Colombier * Either main shell is exiting or cleanup_parents_env() was called.
7007dd7cddfSDavid du Colombier */
7017dd7cddfSDavid du Colombier if (ep->oenv == NULL) {
7027dd7cddfSDavid du Colombier if (ep->type == E_NONE) { /* Main shell exiting? */
7037dd7cddfSDavid du Colombier if (Flag(FTALKING))
7047dd7cddfSDavid du Colombier hist_finish();
7057dd7cddfSDavid du Colombier j_exit();
7067dd7cddfSDavid du Colombier if (ep->flags & EF_FAKE_SIGDIE) {
7077dd7cddfSDavid du Colombier int sig = exstat - 128;
7087dd7cddfSDavid du Colombier
7097dd7cddfSDavid du Colombier /* ham up our death a bit (at&t ksh
7107dd7cddfSDavid du Colombier * only seems to do this for SIGTERM)
7117dd7cddfSDavid du Colombier * Don't do it for SIGQUIT, since we'd
7127dd7cddfSDavid du Colombier * dump a core..
7137dd7cddfSDavid du Colombier */
7147dd7cddfSDavid du Colombier if (sig == SIGINT || sig == SIGTERM) {
7157dd7cddfSDavid du Colombier setsig(&sigtraps[sig], SIG_DFL,
7167dd7cddfSDavid du Colombier SS_RESTORE_CURR|SS_FORCE);
7177dd7cddfSDavid du Colombier kill(0, sig);
7187dd7cddfSDavid du Colombier }
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier #ifdef MEM_DEBUG
7217dd7cddfSDavid du Colombier chmem_allfree();
7227dd7cddfSDavid du Colombier #endif /* MEM_DEBUG */
7237dd7cddfSDavid du Colombier }
7247dd7cddfSDavid du Colombier exit(exstat);
7257dd7cddfSDavid du Colombier }
7267dd7cddfSDavid du Colombier
7277dd7cddfSDavid du Colombier e = e->oenv;
7287dd7cddfSDavid du Colombier afree(ep, ATEMP);
7297dd7cddfSDavid du Colombier }
7307dd7cddfSDavid du Colombier
7317dd7cddfSDavid du Colombier /* Called after a fork to cleanup stuff left over from parents environment */
7327dd7cddfSDavid du Colombier void
cleanup_parents_env()7337dd7cddfSDavid du Colombier cleanup_parents_env()
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier struct env *ep;
7367dd7cddfSDavid du Colombier int fd;
7377dd7cddfSDavid du Colombier
7387dd7cddfSDavid du Colombier /* Don't clean up temporary files - parent will probably need them.
7397dd7cddfSDavid du Colombier * Also, can't easily reclaim memory since variables, etc. could be
7407dd7cddfSDavid du Colombier * anywyere.
7417dd7cddfSDavid du Colombier */
7427dd7cddfSDavid du Colombier
7437dd7cddfSDavid du Colombier /* close all file descriptors hiding in savefd */
7447dd7cddfSDavid du Colombier for (ep = e; ep; ep = ep->oenv) {
7457dd7cddfSDavid du Colombier if (ep->savefd) {
7467dd7cddfSDavid du Colombier for (fd = 0; fd < NUFILE; fd++)
7477dd7cddfSDavid du Colombier if (ep->savefd[fd] > 0)
7487dd7cddfSDavid du Colombier close(ep->savefd[fd]);
7497dd7cddfSDavid du Colombier afree(ep->savefd, &ep->area);
7507dd7cddfSDavid du Colombier ep->savefd = (short *) 0;
7517dd7cddfSDavid du Colombier }
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier e->oenv = (struct env *) 0;
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier
7567dd7cddfSDavid du Colombier /* Called just before an execve cleanup stuff temporary files */
7577dd7cddfSDavid du Colombier void
cleanup_proc_env()7587dd7cddfSDavid du Colombier cleanup_proc_env()
7597dd7cddfSDavid du Colombier {
7607dd7cddfSDavid du Colombier struct env *ep;
7617dd7cddfSDavid du Colombier
7627dd7cddfSDavid du Colombier for (ep = e; ep; ep = ep->oenv)
7637dd7cddfSDavid du Colombier remove_temps(ep->temps);
7647dd7cddfSDavid du Colombier }
7657dd7cddfSDavid du Colombier
7667dd7cddfSDavid du Colombier /* remove temp files and free ATEMP Area */
7677dd7cddfSDavid du Colombier static void
reclaim()7687dd7cddfSDavid du Colombier reclaim()
7697dd7cddfSDavid du Colombier {
7707dd7cddfSDavid du Colombier remove_temps(e->temps);
7717dd7cddfSDavid du Colombier e->temps = NULL;
7727dd7cddfSDavid du Colombier afreeall(&e->area);
7737dd7cddfSDavid du Colombier }
7747dd7cddfSDavid du Colombier
7757dd7cddfSDavid du Colombier static void
remove_temps(tp)7767dd7cddfSDavid du Colombier remove_temps(tp)
7777dd7cddfSDavid du Colombier struct temp *tp;
7787dd7cddfSDavid du Colombier {
7797dd7cddfSDavid du Colombier #ifdef OS2
7807dd7cddfSDavid du Colombier static struct temp *delayed_remove;
7817dd7cddfSDavid du Colombier struct temp *t, **tprev;
7827dd7cddfSDavid du Colombier
7837dd7cddfSDavid du Colombier if (delayed_remove) {
7847dd7cddfSDavid du Colombier for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev)
7857dd7cddfSDavid du Colombier /* No need to check t->pid here... */
7867dd7cddfSDavid du Colombier if (unlink(t->name) >= 0 || errno == ENOENT) {
7877dd7cddfSDavid du Colombier *tprev = t->next;
7887dd7cddfSDavid du Colombier afree(t, APERM);
7897dd7cddfSDavid du Colombier } else
7907dd7cddfSDavid du Colombier tprev = &t->next;
7917dd7cddfSDavid du Colombier }
7927dd7cddfSDavid du Colombier #endif /* OS2 */
7937dd7cddfSDavid du Colombier
7947dd7cddfSDavid du Colombier for (; tp != NULL; tp = tp->next)
7957dd7cddfSDavid du Colombier if (tp->pid == procpid) {
7967dd7cddfSDavid du Colombier #ifdef OS2
7977dd7cddfSDavid du Colombier /* OS/2 (and dos) do not allow files that are currently
7987dd7cddfSDavid du Colombier * open to be removed, so we cache it away for future
7997dd7cddfSDavid du Colombier * removal.
8007dd7cddfSDavid du Colombier * XXX should only do this if errno
8017dd7cddfSDavid du Colombier * is Efile-still-open-can't-remove
8027dd7cddfSDavid du Colombier * (but I don't know what that is...)
8037dd7cddfSDavid du Colombier */
8047dd7cddfSDavid du Colombier if (unlink(tp->name) < 0 && errno != ENOENT) {
8057dd7cddfSDavid du Colombier t = (struct temp *) alloc(
8067dd7cddfSDavid du Colombier sizeof(struct temp) + strlen(tp->name) + 1,
8077dd7cddfSDavid du Colombier APERM);
8087dd7cddfSDavid du Colombier memset(t, 0, sizeof(struct temp));
8097dd7cddfSDavid du Colombier t->name = (char *) &t[1];
8107dd7cddfSDavid du Colombier strcpy(t->name, tp->name);
8117dd7cddfSDavid du Colombier t->next = delayed_remove;
8127dd7cddfSDavid du Colombier delayed_remove = t;
8137dd7cddfSDavid du Colombier }
8147dd7cddfSDavid du Colombier #else /* OS2 */
8157dd7cddfSDavid du Colombier unlink(tp->name);
8167dd7cddfSDavid du Colombier #endif /* OS2 */
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier }
8197dd7cddfSDavid du Colombier
8207dd7cddfSDavid du Colombier /* Returns true if name refers to a restricted shell */
8217dd7cddfSDavid du Colombier static int
is_restricted(name)8227dd7cddfSDavid du Colombier is_restricted(name)
8237dd7cddfSDavid du Colombier char *name;
8247dd7cddfSDavid du Colombier {
8257dd7cddfSDavid du Colombier char *p;
8267dd7cddfSDavid du Colombier
827*59cc4ca5SDavid du Colombier /* this silly function prevents you running a command called runconf.sh. */
828*59cc4ca5SDavid du Colombier /* we don't care about restricted shells, which aren't very restricted anyway */
829*59cc4ca5SDavid du Colombier /* and introduce a false sense of security */
830*59cc4ca5SDavid du Colombier return 0;
831*59cc4ca5SDavid du Colombier #ifdef dumbidea
8327dd7cddfSDavid du Colombier if ((p = ksh_strrchr_dirsep(name)))
8337dd7cddfSDavid du Colombier name = p;
8347dd7cddfSDavid du Colombier /* accepts rsh, rksh, rpdksh, pdrksh, etc. */
8357dd7cddfSDavid du Colombier return (p = strchr(name, 'r')) && strstr(p, "sh");
836*59cc4ca5SDavid du Colombier #endif
8377dd7cddfSDavid du Colombier }
8387dd7cddfSDavid du Colombier
8397dd7cddfSDavid du Colombier void
aerror(ap,msg)8407dd7cddfSDavid du Colombier aerror(ap, msg)
8417dd7cddfSDavid du Colombier Area *ap;
8427dd7cddfSDavid du Colombier const char *msg;
8437dd7cddfSDavid du Colombier {
8447dd7cddfSDavid du Colombier internal_errorf(1, "alloc: %s", msg);
8457dd7cddfSDavid du Colombier errorf(null); /* this is never executed - keeps gcc quiet */
8467dd7cddfSDavid du Colombier /*NOTREACHED*/
8477dd7cddfSDavid du Colombier }
848