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