OSDN Git Service

Upgrade to mksh 51.
[android-x86/external-mksh.git] / src / main.c
1 /*      $OpenBSD: main.c,v 1.55 2015/02/09 09:09:30 jsg Exp $   */
2 /*      $OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $       */
3 /*      $OpenBSD: io.c,v 1.25 2014/08/11 20:28:47 guenther Exp $        */
4 /*      $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */
5
6 /*-
7  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
8  *               2011, 2012, 2013, 2014, 2015
9  *      Thorsten Glaser <tg@mirbsd.org>
10  *
11  * Provided that these terms and disclaimer and all copyright notices
12  * are retained or reproduced in an accompanying document, permission
13  * is granted to deal in this work without restriction, including un-
14  * limited rights to use, publicly perform, distribute, sell, modify,
15  * merge, give away, or sublicence.
16  *
17  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
18  * the utmost extent permitted by applicable law, neither express nor
19  * implied; without malicious intent or gross negligence. In no event
20  * may a licensor, author or contributor be held liable for indirect,
21  * direct, other damage, loss, or other issues arising in any way out
22  * of dealing in the work, even if advised of the possibility of such
23  * damage or existence of a defect, except proven that it results out
24  * of said person's immediate fault when using the work as intended.
25  */
26
27 #define EXTERN
28 #include "sh.h"
29
30 #if HAVE_LANGINFO_CODESET
31 #include <langinfo.h>
32 #endif
33 #if HAVE_SETLOCALE_CTYPE
34 #include <locale.h>
35 #endif
36
37 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.300 2015/07/10 19:36:35 tg Exp $");
38
39 extern char **environ;
40
41 #ifndef MKSHRC_PATH
42 #define MKSHRC_PATH     "~/.mkshrc"
43 #endif
44
45 #ifndef MKSH_DEFAULT_TMPDIR
46 #define MKSH_DEFAULT_TMPDIR     MKSH_UNIXROOT "/tmp"
47 #endif
48
49 static uint8_t isuc(const char *);
50 static int main_init(int, const char *[], Source **, struct block **);
51 void chvt_reinit(void);
52 static void reclaim(void);
53 static void remove_temps(struct temp *);
54 static mksh_uari_t rndsetup(void);
55 #ifdef SIGWINCH
56 static void x_sigwinch(int);
57 #endif
58
59 static const char initifs[] = "IFS= \t\n";
60
61 static const char initsubs[] =
62     "${PS2=> } ${PS3=#? } ${PS4=+ } ${SECONDS=0} ${TMOUT=0} ${EPOCHREALTIME=}";
63
64 static const char *initcoms[] = {
65         Ttypeset, "-r", initvsn, NULL,
66         Ttypeset, "-x", "HOME", "PATH", "SHELL", NULL,
67         Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
68         Talias,
69         "integer=\\typeset -i",
70         "local=\\typeset",
71         /* not "alias -t --": hash -r needs to work */
72         "hash=\\builtin alias -t",
73         "type=\\builtin whence -v",
74 #if !defined(ANDROID) && !defined(MKSH_UNEMPLOYED)
75         /* not in Android for political reasons */
76         /* not in ARGE mksh due to no job control */
77         "stop=\\kill -STOP",
78 #endif
79         "autoload=\\typeset -fu",
80         "functions=\\typeset -f",
81         "history=\\builtin fc -l",
82         "nameref=\\typeset -n",
83         "nohup=nohup ",
84         "r=\\builtin fc -e -",
85         "source=PATH=$PATH" MKSH_PATHSEPS ". \\command .",
86         "login=\\exec login",
87         NULL,
88          /* this is what AT&T ksh seems to track, with the addition of emacs */
89         Talias, "-tU",
90         Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
91         "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL,
92         NULL
93 };
94
95 static const char *restr_com[] = {
96         Ttypeset, "-r", "PATH", "ENV", "SHELL", NULL
97 };
98
99 static bool initio_done;
100
101 /* top-level parsing and execution environment */
102 static struct env env;
103 struct env *e = &env;
104
105 static mksh_uari_t
106 rndsetup(void)
107 {
108         register uint32_t h;
109         struct {
110                 ALLOC_ITEM alloc_INT;
111                 void *dataptr, *stkptr, *mallocptr;
112 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
113                 sigjmp_buf jbuf;
114 #endif
115                 struct timeval tv;
116         } *bufptr;
117         char *cp;
118
119         cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM);
120 #ifdef DEBUG
121         /* clear the allocated space, for valgrind */
122         memset(cp, 0, sizeof(*bufptr) - ALLOC_SIZE);
123 #endif
124         /* undo what alloc() did to the malloc result address */
125         bufptr = (void *)(cp - ALLOC_SIZE);
126         /* PIE or something similar provides us with deltas here */
127         bufptr->dataptr = &rndsetupstate;
128         /* ASLR in at least Windows, Linux, some BSDs */
129         bufptr->stkptr = &bufptr;
130         /* randomised malloc in BSD (and possibly others) */
131         bufptr->mallocptr = bufptr;
132 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
133         /* glibc pointer guard */
134         sigsetjmp(bufptr->jbuf, 1);
135 #endif
136         /* introduce variation (and yes, second arg MBZ for portability) */
137         mksh_TIME(bufptr->tv);
138
139         h = chvt_rndsetup(bufptr, sizeof(*bufptr));
140
141         afree(cp, APERM);
142         return ((mksh_uari_t)h);
143 }
144
145 void
146 chvt_reinit(void)
147 {
148         kshpid = procpid = getpid();
149         ksheuid = geteuid();
150         kshpgrp = getpgrp();
151         kshppid = getppid();
152 }
153
154 static const char *empty_argv[] = {
155         "mksh", NULL
156 };
157
158 static uint8_t
159 isuc(const char *cx) {
160         char *cp, *x;
161         uint8_t rv = 0;
162
163         if (!cx || !*cx)
164                 return (0);
165
166         /* uppercase a string duplicate */
167         strdupx(x, cx, ATEMP);
168         cp = x;
169         while ((*cp = ksh_toupper(*cp)))
170                 ++cp;
171
172         /* check for UTF-8 */
173         if (strstr(x, "UTF-8") || strstr(x, "UTF8"))
174                 rv = 1;
175
176         /* free copy and out */
177         afree(x, ATEMP);
178         return (rv);
179 }
180
181 static int
182 main_init(int argc, const char *argv[], Source **sp, struct block **lp)
183 {
184         int argi, i;
185         Source *s = NULL;
186         struct block *l;
187         unsigned char restricted_shell, errexit, utf_flag;
188         char *cp;
189         const char *ccp, **wp;
190         struct tbl *vp;
191         struct stat s_stdin;
192 #if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
193         ssize_t k;
194 #endif
195
196 #ifdef __OS2__
197         for (i = 0; i < 3; ++i)
198                 if (!isatty(i))
199                         setmode(i, O_BINARY);
200 #endif
201
202         /* do things like getpgrp() et al. */
203         chvt_reinit();
204
205         /* make sure argv[] is sane */
206         if (!*argv) {
207                 argv = empty_argv;
208                 argc = 1;
209         }
210         kshname = argv[0];
211
212         /* initialise permanent Area */
213         ainit(&aperm);
214
215         /* set up base environment */
216         env.type = E_NONE;
217         ainit(&env.area);
218         /* set up global l->vars and l->funs */
219         newblock();
220
221         /* Do this first so output routines (eg, errorf, shellf) can work */
222         initio();
223
224         /* determine the basename (without '-' or path) of the executable */
225         ccp = kshname;
226         goto begin_parse_kshname;
227         while ((i = ccp[argi++])) {
228                 if (i == '/') {
229                         ccp += argi;
230  begin_parse_kshname:
231                         argi = 0;
232                         if (*ccp == '-')
233                                 ++ccp;
234                 }
235         }
236         if (!*ccp)
237                 ccp = empty_argv[0];
238
239         /*
240          * Turn on nohup by default. (AT&T ksh does not have a nohup
241          * option - it always sends the hup).
242          */
243         Flag(FNOHUP) = 1;
244
245         /*
246          * Turn on brace expansion by default. AT&T kshs that have
247          * alternation always have it on.
248          */
249         Flag(FBRACEEXPAND) = 1;
250
251         /*
252          * Turn on "set -x" inheritance by default.
253          */
254         Flag(FXTRACEREC) = 1;
255
256         /* define built-in commands and see if we were called as one */
257         ktinit(APERM, &builtins,
258             /* currently up to 51 builtins: 75% of 128 = 2^7 */
259             7);
260         for (i = 0; mkshbuiltins[i].name != NULL; i++)
261                 if (!strcmp(ccp, builtin(mkshbuiltins[i].name,
262                     mkshbuiltins[i].func)))
263                         Flag(FAS_BUILTIN) = 1;
264
265         if (!Flag(FAS_BUILTIN)) {
266                 /* check for -T option early */
267                 argi = parse_args(argv, OF_FIRSTTIME, NULL);
268                 if (argi < 0)
269                         return (1);
270
271 #if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
272                 /* are we called as -sh or /bin/sh or so? */
273                 if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) {
274                         /* either also turns off braceexpand */
275 #ifdef MKSH_BINSHPOSIX
276                         /* enable better POSIX conformance */
277                         change_flag(FPOSIX, OF_FIRSTTIME, true);
278 #endif
279 #ifdef MKSH_BINSHREDUCED
280                         /* enable kludge/compat mode */
281                         change_flag(FSH, OF_FIRSTTIME, true);
282 #endif
283                 }
284 #endif
285         }
286
287         initvar();
288
289         initctypes();
290
291         inittraps();
292
293         coproc_init();
294
295         /* set up variable and command dictionaries */
296         ktinit(APERM, &taliases, 0);
297         ktinit(APERM, &aliases, 0);
298 #ifndef MKSH_NOPWNAM
299         ktinit(APERM, &homedirs, 0);
300 #endif
301
302         /* define shell keywords */
303         initkeywords();
304
305         init_histvec();
306
307         /* initialise tty size before importing environment */
308         change_winsz();
309
310 #ifdef _PATH_DEFPATH
311         def_path = _PATH_DEFPATH;
312 #else
313 #ifdef _CS_PATH
314         if ((k = confstr(_CS_PATH, NULL, 0)) > 0 &&
315             confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1)
316                 def_path = cp;
317         else
318 #endif
319                 /*
320                  * this is uniform across all OSes unless it
321                  * breaks somewhere; don't try to optimise,
322                  * e.g. add stuff for Interix or remove /usr
323                  * for HURD, because e.g. Debian GNU/HURD is
324                  * "keeping a regular /usr"; this is supposed
325                  * to be a sane 'basic' default PATH
326                  */
327                 def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS
328                     MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS
329                     MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS
330                     MKSH_UNIXROOT "/usr/sbin";
331 #endif
332
333         /*
334          * Set PATH to def_path (will set the path global variable).
335          * (import of environment below will probably change this setting).
336          */
337         vp = global("PATH");
338         /* setstr can't fail here */
339         setstr(vp, def_path, KSH_RETURN_ERROR);
340
341 #ifndef MKSH_NO_CMDLINE_EDITING
342         /*
343          * Set edit mode to emacs by default, may be overridden
344          * by the environment or the user. Also, we want tab completion
345          * on in vi by default.
346          */
347         change_flag(FEMACS, OF_SPECIAL, true);
348 #if !MKSH_S_NOVI
349         Flag(FVITABCOMPLETE) = 1;
350 #endif
351 #endif
352
353         /* import environment */
354         if (environ != NULL) {
355                 wp = (const char **)environ;
356                 while (*wp != NULL) {
357                         rndpush(*wp);
358                         typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
359                         ++wp;
360                 }
361         }
362
363         /* for security */
364         typeset(initifs, 0, 0, 0, 0);
365
366         /* assign default shell variable values */
367         substitute(initsubs, 0);
368
369         /* Figure out the current working directory and set $PWD */
370         vp = global("PWD");
371         cp = str_val(vp);
372         /* Try to use existing $PWD if it is valid */
373         set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp, ".",
374             true)) ? cp : NULL);
375         if (current_wd[0])
376                 simplify_path(current_wd);
377         /* Only set pwd if we know where we are or if it had a bogus value */
378         if (current_wd[0] || *cp)
379                 /* setstr can't fail here */
380                 setstr(vp, current_wd, KSH_RETURN_ERROR);
381
382         for (wp = initcoms; *wp != NULL; wp++) {
383                 shcomexec(wp);
384                 while (*wp != NULL)
385                         wp++;
386         }
387         setint_n(global("OPTIND"), 1, 10);
388
389         kshuid = getuid();
390         kshgid = getgid();
391         kshegid = getegid();
392
393         safe_prompt = ksheuid ? "$ " : "# ";
394         vp = global("PS1");
395         /* Set PS1 if unset or we are root and prompt doesn't contain a # */
396         if (!(vp->flag & ISSET) ||
397             (!ksheuid && !strchr(str_val(vp), '#')))
398                 /* setstr can't fail here */
399                 setstr(vp, safe_prompt, KSH_RETURN_ERROR);
400         setint_n((vp = global("BASHPID")), 0, 10);
401         vp->flag |= INT_U;
402         setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10);
403         vp->flag |= INT_U;
404         setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10);
405         vp->flag |= INT_U;
406         setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10);
407         vp->flag |= INT_U;
408         setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10);
409         vp->flag |= INT_U;
410         setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10);
411         vp->flag |= INT_U;
412         setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10);
413         vp->flag |= INT_U;
414         setint_n((vp = global("RANDOM")), rndsetup(), 10);
415         vp->flag |= INT_U;
416         setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);
417
418         /* Set this before parsing arguments */
419         Flag(FPRIVILEGED) = (
420 #if HAVE_ISSETUGID
421             issetugid() ||
422 #endif
423             kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;
424
425         /* this to note if monitor is set on command line (see below) */
426 #ifndef MKSH_UNEMPLOYED
427         Flag(FMONITOR) = 127;
428 #endif
429         /* this to note if utf-8 mode is set on command line (see below) */
430         UTFMODE = 2;
431
432         if (!Flag(FAS_BUILTIN)) {
433                 argi = parse_args(argv, OF_CMDLINE, NULL);
434                 if (argi < 0)
435                         return (1);
436         }
437
438         /* process this later only, default to off (hysterical raisins) */
439         utf_flag = UTFMODE;
440         UTFMODE = 0;
441
442         if (Flag(FAS_BUILTIN)) {
443                 /* auto-detect from environment variables, always */
444                 utf_flag = 3;
445         } else if (Flag(FCOMMAND)) {
446                 s = pushs(SSTRINGCMDLINE, ATEMP);
447                 if (!(s->start = s->str = argv[argi++]))
448                         errorf("%s %s", "-c", "requires an argument");
449                 while (*s->str) {
450                         if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
451                                 break;
452                         s->str++;
453                 }
454                 if (!*s->str)
455                         s->flags |= SF_MAYEXEC;
456                 s->str = s->start;
457 #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
458                 /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
459                 if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
460                         ++argi;
461 #endif
462                 if (argv[argi])
463                         kshname = argv[argi++];
464         } else if (argi < argc && !Flag(FSTDIN)) {
465                 s = pushs(SFILE, ATEMP);
466 #ifdef __OS2__
467                 /*
468                  * A bug in OS/2 extproc (like shebang) handling makes
469                  * it not pass the full pathname of a script, so we need
470                  * to search for it. This changes the behaviour of a
471                  * simple "mksh foo", but can't be helped.
472                  */
473                 s->file = search_path(argv[argi++], path, X_OK, NULL);
474                 if (!s->file || !*s->file)
475                         s->file = argv[argi - 1];
476 #else
477                 s->file = argv[argi++];
478 #endif
479                 s->u.shf = shf_open(s->file, O_RDONLY, 0,
480                     SHF_MAPHI | SHF_CLEXEC);
481                 if (s->u.shf == NULL) {
482                         shl_stdout_ok = false;
483                         warningf(true, "%s: %s", s->file, cstrerror(errno));
484                         /* mandated by SUSv4 */
485                         exstat = 127;
486                         unwind(LERROR);
487                 }
488                 kshname = s->file;
489         } else {
490                 Flag(FSTDIN) = 1;
491                 s = pushs(SSTDIN, ATEMP);
492                 s->file = "<stdin>";
493                 s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),
494                     NULL);
495                 if (isatty(0) && isatty(2)) {
496                         Flag(FTALKING) = Flag(FTALKING_I) = 1;
497                         /* The following only if isatty(0) */
498                         s->flags |= SF_TTY;
499                         s->u.shf->flags |= SHF_INTERRUPT;
500                         s->file = NULL;
501                 }
502         }
503
504         /* this bizarreness is mandated by POSIX */
505         if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) &&
506             Flag(FTALKING))
507                 reset_nonblock(0);
508
509         /* initialise job control */
510         j_init();
511         /* do this after j_init() which calls tty_init_state() */
512         if (Flag(FTALKING)) {
513                 if (utf_flag == 2) {
514 #ifndef MKSH_ASSUME_UTF8
515                         /* auto-detect from locale or environment */
516                         utf_flag = 4;
517 #else /* this may not be an #elif */
518 #if MKSH_ASSUME_UTF8
519                         utf_flag = 1;
520 #else
521                         /* always disable UTF-8 (for interactive) */
522                         utf_flag = 0;
523 #endif
524 #endif
525                 }
526 #ifndef MKSH_NO_CMDLINE_EDITING
527                 x_init();
528 #endif
529         }
530
531 #ifdef SIGWINCH
532         sigtraps[SIGWINCH].flags |= TF_SHELL_USES;
533         setsig(&sigtraps[SIGWINCH], x_sigwinch,
534             SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
535 #endif
536
537         l = e->loc;
538         if (Flag(FAS_BUILTIN)) {
539                 l->argc = argc;
540                 l->argv = argv;
541                 l->argv[0] = ccp;
542         } else {
543                 l->argc = argc - argi;
544                 /*
545                  * allocate a new array because otherwise, when we modify
546                  * it in-place, ps(1) output changes; the meaning of argc
547                  * here is slightly different as it excludes kshname, and
548                  * we add a trailing NULL sentinel as well
549                  */
550                 l->argv = alloc2(l->argc + 2, sizeof(void *), APERM);
551                 l->argv[0] = kshname;
552                 memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *));
553                 l->argv[l->argc + 1] = NULL;
554                 getopts_reset(1);
555         }
556
557         /* divine the initial state of the utf8-mode Flag */
558         ccp = null;
559         switch (utf_flag) {
560
561         /* auto-detect from locale or environment */
562         case 4:
563 #if HAVE_SETLOCALE_CTYPE
564                 ccp = setlocale(LC_CTYPE, "");
565 #if HAVE_LANGINFO_CODESET
566                 if (!isuc(ccp))
567                         ccp = nl_langinfo(CODESET);
568 #endif
569                 if (!isuc(ccp))
570                         ccp = null;
571                 /* FALLTHROUGH */
572 #endif
573
574         /* auto-detect from environment */
575         case 3:
576                 /* these were imported from environ earlier */
577                 if (ccp == null)
578                         ccp = str_val(global("LC_ALL"));
579                 if (ccp == null)
580                         ccp = str_val(global("LC_CTYPE"));
581                 if (ccp == null)
582                         ccp = str_val(global("LANG"));
583                 UTFMODE = isuc(ccp);
584                 break;
585
586         /* not set on command line, not FTALKING */
587         case 2:
588         /* unknown values */
589         default:
590                 utf_flag = 0;
591                 /* FALLTHROUGH */
592
593         /* known values */
594         case 1:
595         case 0:
596                 UTFMODE = utf_flag;
597                 break;
598         }
599
600         /* Disable during .profile/ENV reading */
601         restricted_shell = Flag(FRESTRICTED);
602         Flag(FRESTRICTED) = 0;
603         errexit = Flag(FERREXIT);
604         Flag(FERREXIT) = 0;
605
606         /*
607          * Do this before profile/$ENV so that if it causes problems in them,
608          * user will know why things broke.
609          */
610         if (!current_wd[0] && Flag(FTALKING))
611                 warningf(false, "can't determine current directory");
612
613         if (Flag(FLOGIN))
614                 include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
615         if (!Flag(FPRIVILEGED)) {
616                 if (Flag(FLOGIN))
617                         include(substitute("$HOME/.profile", 0), 0, NULL, true);
618                 if (Flag(FTALKING)) {
619                         cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
620                             0), DOTILDE);
621                         if (cp[0] != '\0')
622                                 include(cp, 0, NULL, true);
623                 }
624         } else {
625                 include(MKSH_SUID_PROFILE, 0, NULL, true);
626                 /* turn off -p if not set explicitly */
627                 if (Flag(FPRIVILEGED) != 1)
628                         change_flag(FPRIVILEGED, OF_INTERNAL, false);
629         }
630
631         if (restricted_shell) {
632                 shcomexec(restr_com);
633                 /* After typeset command... */
634                 Flag(FRESTRICTED) = 1;
635         }
636         Flag(FERREXIT) = errexit;
637
638         if (Flag(FTALKING) && s)
639                 hist_init(s);
640         else
641                 /* set after ENV */
642                 Flag(FTRACKALL) = 1;
643
644         alarm_init();
645
646         *sp = s;
647         *lp = l;
648         return (0);
649 }
650
651 /* this indirection barrier reduces stack usage during normal operation */
652
653 int
654 main(int argc, const char *argv[])
655 {
656         int rv;
657         Source *s;
658         struct block *l;
659
660         if ((rv = main_init(argc, argv, &s, &l)) == 0) {
661                 if (Flag(FAS_BUILTIN)) {
662                         rv = shcomexec(l->argv);
663                 } else {
664                         shell(s, true);
665                         /* NOTREACHED */
666                 }
667         }
668         return (rv);
669 }
670
671 int
672 include(const char *name, int argc, const char **argv, bool intr_ok)
673 {
674         Source *volatile s = NULL;
675         struct shf *shf;
676         const char **volatile old_argv;
677         volatile int old_argc;
678         int i;
679
680         shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC);
681         if (shf == NULL)
682                 return (-1);
683
684         if (argv) {
685                 old_argv = e->loc->argv;
686                 old_argc = e->loc->argc;
687         } else {
688                 old_argv = NULL;
689                 old_argc = 0;
690         }
691         newenv(E_INCL);
692         if ((i = kshsetjmp(e->jbuf))) {
693                 quitenv(s ? s->u.shf : NULL);
694                 if (old_argv) {
695                         e->loc->argv = old_argv;
696                         e->loc->argc = old_argc;
697                 }
698                 switch (i) {
699                 case LRETURN:
700                 case LERROR:
701                         /* see below */
702                         return (exstat & 0xFF);
703                 case LINTR:
704                         /*
705                          * intr_ok is set if we are including .profile or $ENV.
706                          * If user ^Cs out, we don't want to kill the shell...
707                          */
708                         if (intr_ok && ((exstat & 0xFF) - 128) != SIGTERM)
709                                 return (1);
710                         /* FALLTHROUGH */
711                 case LEXIT:
712                 case LLEAVE:
713                 case LSHELL:
714                         unwind(i);
715                         /* NOTREACHED */
716                 default:
717                         internal_errorf("%s %d", "include", i);
718                         /* NOTREACHED */
719                 }
720         }
721         if (argv) {
722                 e->loc->argv = argv;
723                 e->loc->argc = argc;
724         }
725         s = pushs(SFILE, ATEMP);
726         s->u.shf = shf;
727         strdupx(s->file, name, ATEMP);
728         i = shell(s, false);
729         quitenv(s->u.shf);
730         if (old_argv) {
731                 e->loc->argv = old_argv;
732                 e->loc->argc = old_argc;
733         }
734         /* & 0xff to ensure value not -1 */
735         return (i & 0xFF);
736 }
737
738 /* spawn a command into a shell optionally keeping track of the line number */
739 int
740 command(const char *comm, int line)
741 {
742         Source *s;
743
744         s = pushs(SSTRING, ATEMP);
745         s->start = s->str = comm;
746         s->line = line;
747         return (shell(s, false));
748 }
749
750 /*
751  * run the commands from the input source, returning status.
752  */
753 int
754 shell(Source * volatile s, volatile bool toplevel)
755 {
756         struct op *t;
757         volatile bool wastty = tobool(s->flags & SF_TTY);
758         volatile uint8_t attempts = 13;
759         volatile bool interactive = Flag(FTALKING) && toplevel;
760         volatile bool sfirst = true;
761         Source *volatile old_source = source;
762         int i;
763
764         newenv(E_PARSE);
765         if (interactive)
766                 really_exit = false;
767         switch ((i = kshsetjmp(e->jbuf))) {
768         case 0:
769                 break;
770         case LINTR:
771                 /* we get here if SIGINT not caught or ignored */
772         case LERROR:
773         case LSHELL:
774                 if (interactive) {
775                         if (i == LINTR)
776                                 shellf("\n");
777                         /*
778                          * Reset any eof that was read as part of a
779                          * multiline command.
780                          */
781                         if (Flag(FIGNOREEOF) && s->type == SEOF && wastty)
782                                 s->type = SSTDIN;
783                         /*
784                          * Used by exit command to get back to
785                          * top level shell. Kind of strange since
786                          * interactive is set if we are reading from
787                          * a tty, but to have stopped jobs, one only
788                          * needs FMONITOR set (not FTALKING/SF_TTY)...
789                          */
790                         /* toss any input we have so far */
791                         yyrecursive_pop(true);
792                         s->start = s->str = null;
793                         retrace_info = NULL;
794                         herep = heres;
795                         break;
796                 }
797                 /* FALLTHROUGH */
798         case LEXIT:
799         case LLEAVE:
800         case LRETURN:
801                 source = old_source;
802                 quitenv(NULL);
803                 /* keep on going */
804                 unwind(i);
805                 /* NOTREACHED */
806         default:
807                 source = old_source;
808                 quitenv(NULL);
809                 internal_errorf("%s %d", "shell", i);
810                 /* NOTREACHED */
811         }
812         while (/* CONSTCOND */ 1) {
813                 if (trap)
814                         runtraps(0);
815
816                 if (s->next == NULL) {
817                         if (Flag(FVERBOSE))
818                                 s->flags |= SF_ECHO;
819                         else
820                                 s->flags &= ~SF_ECHO;
821                 }
822                 if (interactive) {
823                         j_notify();
824                         set_prompt(PS1, s);
825                 }
826                 t = compile(s, sfirst);
827                 if (interactive)
828                         histsave(&s->line, NULL, HIST_FLUSH, true);
829                 sfirst = false;
830                 if (!t)
831                         goto source_no_tree;
832                 if (t->type == TEOF) {
833                         if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {
834                                 shellf("Use 'exit' to leave mksh\n");
835                                 s->type = SSTDIN;
836                         } else if (wastty && !really_exit &&
837                             j_stopped_running()) {
838                                 really_exit = true;
839                                 s->type = SSTDIN;
840                         } else {
841                                 /*
842                                  * this for POSIX which says EXIT traps
843                                  * shall be taken in the environment
844                                  * immediately after the last command
845                                  * executed.
846                                  */
847                                 if (toplevel)
848                                         unwind(LEXIT);
849                                 break;
850                         }
851                 } else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
852                         t->u.evalflags |= DOTCOMEXEC;
853                 if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
854                         exstat = execute(t, 0, NULL) & 0xFF;
855
856                 if (t->type != TEOF && interactive && really_exit)
857                         really_exit = false;
858
859  source_no_tree:
860                 reclaim();
861         }
862         quitenv(NULL);
863         source = old_source;
864         return (exstat & 0xFF);
865 }
866
867 /* return to closest error handler or shell(), exit if none found */
868 /* note: i MUST NOT be 0 */
869 void
870 unwind(int i)
871 {
872         /*
873          * This is a kludge. We need to restore everything that was
874          * changed in the new environment, see cid 1005090337C7A669439
875          * and 10050903386452ACBF1, but fail to even save things most of
876          * the time. funcs.c:c_eval() changes FERREXIT temporarily to 0,
877          * which needs to be restored thus (related to Debian #696823).
878          * We did not save the shell flags, so we use a special or'd
879          * value here... this is mostly to clean up behind *other*
880          * callers of unwind(LERROR) here; exec.c has the regular case.
881          */
882         if (Flag(FERREXIT) & 0x80) {
883                 /* GNU bash does not run this trapsig */
884                 trapsig(ksh_SIGERR);
885                 Flag(FERREXIT) &= ~0x80;
886         }
887
888         /* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */
889         if (i == LEXIT || ((i == LERROR || i == LINTR) &&
890             sigtraps[ksh_SIGEXIT].trap &&
891             (!Flag(FTALKING) || Flag(FERREXIT)))) {
892                 ++trap_nested;
893                 runtrap(&sigtraps[ksh_SIGEXIT], trap_nested == 1);
894                 --trap_nested;
895                 i = LLEAVE;
896         } else if (Flag(FERREXIT) == 1 && (i == LERROR || i == LINTR)) {
897                 ++trap_nested;
898                 runtrap(&sigtraps[ksh_SIGERR], trap_nested == 1);
899                 --trap_nested;
900                 i = LLEAVE;
901         }
902
903         while (/* CONSTCOND */ 1) {
904                 switch (e->type) {
905                 case E_PARSE:
906                 case E_FUNC:
907                 case E_INCL:
908                 case E_LOOP:
909                 case E_ERRH:
910                         kshlongjmp(e->jbuf, i);
911                         /* NOTREACHED */
912                 case E_NONE:
913                         if (i == LINTR)
914                                 e->flags |= EF_FAKE_SIGDIE;
915                         /* FALLTHROUGH */
916                 default:
917                         quitenv(NULL);
918                         /*
919                          * quitenv() may have reclaimed the memory
920                          * used by source which will end badly when
921                          * we jump to a function that expects it to
922                          * be valid
923                          */
924                         source = NULL;
925                 }
926         }
927 }
928
929 void
930 newenv(int type)
931 {
932         struct env *ep;
933         char *cp;
934
935         /*
936          * struct env includes ALLOC_ITEM for alignment constraints
937          * so first get the actually used memory, then assign it
938          */
939         cp = alloc(sizeof(struct env) - ALLOC_SIZE, ATEMP);
940         /* undo what alloc() did to the malloc result address */
941         ep = (void *)(cp - ALLOC_SIZE);
942         /* initialise public members of struct env (not the ALLOC_ITEM) */
943         ainit(&ep->area);
944         ep->oenv = e;
945         ep->loc = e->loc;
946         ep->savefd = NULL;
947         ep->temps = NULL;
948         ep->yyrecursive_statep = NULL;
949         ep->type = type;
950         ep->flags = 0;
951         /* jump buffer is invalid because flags == 0 */
952         e = ep;
953 }
954
955 void
956 quitenv(struct shf *shf)
957 {
958         struct env *ep = e;
959         char *cp;
960         int fd;
961
962         yyrecursive_pop(true);
963         while (ep->oenv && ep->oenv->loc != ep->loc)
964                 popblock();
965         if (ep->savefd != NULL) {
966                 for (fd = 0; fd < NUFILE; fd++)
967                         /* if ep->savefd[fd] < 0, means fd was closed */
968                         if (ep->savefd[fd])
969                                 restfd(fd, ep->savefd[fd]);
970                 if (ep->savefd[2])
971                         /* Clear any write errors */
972                         shf_reopen(2, SHF_WR, shl_out);
973         }
974         /*
975          * Bottom of the stack.
976          * Either main shell is exiting or cleanup_parents_env() was called.
977          */
978         if (ep->oenv == NULL) {
979 #ifdef DEBUG_LEAKS
980                 int i;
981 #endif
982
983                 if (ep->type == E_NONE) {
984                         /* Main shell exiting? */
985 #if HAVE_PERSISTENT_HISTORY
986                         if (Flag(FTALKING))
987                                 hist_finish();
988 #endif
989                         j_exit();
990                         if (ep->flags & EF_FAKE_SIGDIE) {
991                                 int sig = (exstat & 0xFF) - 128;
992
993                                 /*
994                                  * ham up our death a bit (AT&T ksh
995                                  * only seems to do this for SIGTERM)
996                                  * Don't do it for SIGQUIT, since we'd
997                                  * dump a core..
998                                  */
999                                 if ((sig == SIGINT || sig == SIGTERM) &&
1000                                     (kshpgrp == kshpid)) {
1001                                         setsig(&sigtraps[sig], SIG_DFL,
1002                                             SS_RESTORE_CURR | SS_FORCE);
1003                                         kill(0, sig);
1004                                 }
1005                         }
1006                 }
1007                 if (shf)
1008                         shf_close(shf);
1009                 reclaim();
1010 #ifdef DEBUG_LEAKS
1011 #ifndef MKSH_NO_CMDLINE_EDITING
1012                 x_done();
1013 #endif
1014 #ifndef MKSH_NOPROSPECTOFWORK
1015                 /* block at least SIGCHLD during/after afreeall */
1016                 sigprocmask(SIG_BLOCK, &sm_sigchld, NULL);
1017 #endif
1018                 afreeall(APERM);
1019                 for (fd = 3; fd < NUFILE; fd++)
1020                         if ((i = fcntl(fd, F_GETFD, 0)) != -1 &&
1021                             (i & FD_CLOEXEC))
1022                                 close(fd);
1023                 close(2);
1024                 close(1);
1025                 close(0);
1026 #endif
1027                 exit(exstat & 0xFF);
1028         }
1029         if (shf)
1030                 shf_close(shf);
1031         reclaim();
1032
1033         e = e->oenv;
1034
1035         /* free the struct env - tricky due to the ALLOC_ITEM inside */
1036         cp = (void *)ep;
1037         afree(cp + ALLOC_SIZE, ATEMP);
1038 }
1039
1040 /* Called after a fork to cleanup stuff left over from parents environment */
1041 void
1042 cleanup_parents_env(void)
1043 {
1044         struct env *ep;
1045         int fd;
1046
1047         /*
1048          * Don't clean up temporary files - parent will probably need them.
1049          * Also, can't easily reclaim memory since variables, etc. could be
1050          * anywhere.
1051          */
1052
1053         /* close all file descriptors hiding in savefd */
1054         for (ep = e; ep; ep = ep->oenv) {
1055                 if (ep->savefd) {
1056                         for (fd = 0; fd < NUFILE; fd++)
1057                                 if (ep->savefd[fd] > 0)
1058                                         close(ep->savefd[fd]);
1059                         afree(ep->savefd, &ep->area);
1060                         ep->savefd = NULL;
1061                 }
1062 #ifdef DEBUG_LEAKS
1063                 if (ep->type != E_NONE)
1064                         ep->type = E_GONE;
1065 #endif
1066         }
1067 #ifndef DEBUG_LEAKS
1068         e->oenv = NULL;
1069 #endif
1070 }
1071
1072 /* Called just before an execve cleanup stuff temporary files */
1073 void
1074 cleanup_proc_env(void)
1075 {
1076         struct env *ep;
1077
1078         for (ep = e; ep; ep = ep->oenv)
1079                 remove_temps(ep->temps);
1080 }
1081
1082 /* remove temp files and free ATEMP Area */
1083 static void
1084 reclaim(void)
1085 {
1086         struct block *l;
1087
1088         while ((l = e->loc) && (!e->oenv || e->oenv->loc != l)) {
1089                 e->loc = l->next;
1090                 afreeall(&l->area);
1091         }
1092
1093         remove_temps(e->temps);
1094         e->temps = NULL;
1095         afreeall(&e->area);
1096 }
1097
1098 static void
1099 remove_temps(struct temp *tp)
1100 {
1101         for (; tp != NULL; tp = tp->next)
1102                 if (tp->pid == procpid)
1103                         unlink(tp->tffn);
1104 }
1105
1106 /*
1107  * Initialise tty_fd. Used for tracking the size of the terminal,
1108  * saving/resetting tty modes upon forground job completion, and
1109  * for setting up the tty process group. Return values:
1110  *      0 = got controlling tty
1111  *      1 = got terminal but no controlling tty
1112  *      2 = cannot find a terminal
1113  *      3 = cannot dup fd
1114  *      4 = cannot make fd close-on-exec
1115  * An existing tty_fd is cached if no "better" one could be found,
1116  * i.e. if tty_devtty was already set or the new would not set it.
1117  */
1118 int
1119 tty_init_fd(void)
1120 {
1121         int fd, rv, eno = 0;
1122         bool do_close = false, is_devtty = true;
1123
1124         if (tty_devtty) {
1125                 /* already got a tty which is /dev/tty */
1126                 return (0);
1127         }
1128
1129 #ifdef _UWIN
1130         /*XXX imake style */
1131         if (isatty(3)) {
1132                 /* fd 3 on UWIN _is_ /dev/tty (or our controlling tty) */
1133                 fd = 3;
1134                 goto got_fd;
1135         }
1136 #endif
1137         if ((fd = open("/dev/tty", O_RDWR, 0)) >= 0) {
1138                 do_close = true;
1139                 goto got_fd;
1140         }
1141         eno = errno;
1142
1143         if (tty_fd >= 0) {
1144                 /* already got a non-devtty one */
1145                 rv = 1;
1146                 goto out;
1147         }
1148         is_devtty = false;
1149
1150         if (isatty((fd = 0)) || isatty((fd = 2)))
1151                 goto got_fd;
1152         /* cannot find one */
1153         rv = 2;
1154         /* assert: do_close == false */
1155         goto out;
1156
1157  got_fd:
1158         if ((rv = fcntl(fd, F_DUPFD, FDBASE)) < 0) {
1159                 eno = errno;
1160                 rv = 3;
1161                 goto out;
1162         }
1163         if (fcntl(rv, F_SETFD, FD_CLOEXEC) < 0) {
1164                 eno = errno;
1165                 close(rv);
1166                 rv = 4;
1167                 goto out;
1168         }
1169         tty_fd = rv;
1170         tty_devtty = is_devtty;
1171         rv = eno = 0;
1172  out:
1173         if (do_close)
1174                 close(fd);
1175         errno = eno;
1176         return (rv);
1177 }
1178
1179 /* A shell error occurred (eg, syntax error, etc.) */
1180
1181 #define VWARNINGF_ERRORPREFIX   1
1182 #define VWARNINGF_FILELINE      2
1183 #define VWARNINGF_BUILTIN       4
1184 #define VWARNINGF_INTERNAL      8
1185
1186 static void vwarningf(unsigned int, const char *, va_list)
1187     MKSH_A_FORMAT(__printf__, 2, 0);
1188
1189 static void
1190 vwarningf(unsigned int flags, const char *fmt, va_list ap)
1191 {
1192         if (fmt) {
1193                 if (flags & VWARNINGF_INTERNAL)
1194                         shf_fprintf(shl_out, "internal error: ");
1195                 if (flags & VWARNINGF_ERRORPREFIX)
1196                         error_prefix(tobool(flags & VWARNINGF_FILELINE));
1197                 if ((flags & VWARNINGF_BUILTIN) &&
1198                     /* not set when main() calls parse_args() */
1199                     builtin_argv0 && builtin_argv0 != kshname)
1200                         shf_fprintf(shl_out, "%s: ", builtin_argv0);
1201                 shf_vfprintf(shl_out, fmt, ap);
1202                 shf_putchar('\n', shl_out);
1203         }
1204         shf_flush(shl_out);
1205 }
1206
1207 void
1208 errorfx(int rc, const char *fmt, ...)
1209 {
1210         va_list va;
1211
1212         exstat = rc;
1213
1214         /* debugging: note that stdout not valid */
1215         shl_stdout_ok = false;
1216
1217         va_start(va, fmt);
1218         vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
1219         va_end(va);
1220         unwind(LERROR);
1221 }
1222
1223 void
1224 errorf(const char *fmt, ...)
1225 {
1226         va_list va;
1227
1228         exstat = 1;
1229
1230         /* debugging: note that stdout not valid */
1231         shl_stdout_ok = false;
1232
1233         va_start(va, fmt);
1234         vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
1235         va_end(va);
1236         unwind(LERROR);
1237 }
1238
1239 /* like errorf(), but no unwind is done */
1240 void
1241 warningf(bool fileline, const char *fmt, ...)
1242 {
1243         va_list va;
1244
1245         va_start(va, fmt);
1246         vwarningf(VWARNINGF_ERRORPREFIX | (fileline ? VWARNINGF_FILELINE : 0),
1247             fmt, va);
1248         va_end(va);
1249 }
1250
1251 /*
1252  * Used by built-in utilities to prefix shell and utility name to message
1253  * (also unwinds environments for special builtins).
1254  */
1255 void
1256 bi_errorf(const char *fmt, ...)
1257 {
1258         va_list va;
1259
1260         /* debugging: note that stdout not valid */
1261         shl_stdout_ok = false;
1262
1263         exstat = 1;
1264
1265         va_start(va, fmt);
1266         vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE |
1267             VWARNINGF_BUILTIN, fmt, va);
1268         va_end(va);
1269
1270         /*
1271          * POSIX special builtins and ksh special builtins cause
1272          * non-interactive shells to exit.
1273          * XXX odd use of KEEPASN; also may not want LERROR here
1274          */
1275         if (builtin_spec) {
1276                 builtin_argv0 = NULL;
1277                 unwind(LERROR);
1278         }
1279 }
1280
1281 /* Called when something that shouldn't happen does */
1282 void
1283 internal_errorf(const char *fmt, ...)
1284 {
1285         va_list va;
1286
1287         va_start(va, fmt);
1288         vwarningf(VWARNINGF_INTERNAL, fmt, va);
1289         va_end(va);
1290         unwind(LERROR);
1291 }
1292
1293 void
1294 internal_warningf(const char *fmt, ...)
1295 {
1296         va_list va;
1297
1298         va_start(va, fmt);
1299         vwarningf(VWARNINGF_INTERNAL, fmt, va);
1300         va_end(va);
1301 }
1302
1303 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
1304 void
1305 error_prefix(bool fileline)
1306 {
1307         /* Avoid foo: foo[2]: ... */
1308         if (!fileline || !source || !source->file ||
1309             strcmp(source->file, kshname) != 0)
1310                 shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-'));
1311         if (fileline && source && source->file != NULL) {
1312                 shf_fprintf(shl_out, "%s[%lu]: ", source->file,
1313                     (unsigned long)(source->errline ?
1314                     source->errline : source->line));
1315                 source->errline = 0;
1316         }
1317 }
1318
1319 /* printf to shl_out (stderr) with flush */
1320 void
1321 shellf(const char *fmt, ...)
1322 {
1323         va_list va;
1324
1325         if (!initio_done)
1326                 /* shl_out may not be set up yet... */
1327                 return;
1328         va_start(va, fmt);
1329         shf_vfprintf(shl_out, fmt, va);
1330         va_end(va);
1331         shf_flush(shl_out);
1332 }
1333
1334 /* printf to shl_stdout (stdout) */
1335 void
1336 shprintf(const char *fmt, ...)
1337 {
1338         va_list va;
1339
1340         if (!shl_stdout_ok)
1341                 internal_errorf("shl_stdout not valid");
1342         va_start(va, fmt);
1343         shf_vfprintf(shl_stdout, fmt, va);
1344         va_end(va);
1345 }
1346
1347 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
1348 int
1349 can_seek(int fd)
1350 {
1351         struct stat statb;
1352
1353         return (fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ?
1354             SHF_UNBUF : 0);
1355 }
1356
1357 #ifdef DF
1358 int shl_dbg_fd;
1359 #define NSHF_IOB 4
1360 #else
1361 #define NSHF_IOB 3
1362 #endif
1363 struct shf shf_iob[NSHF_IOB];
1364
1365 void
1366 initio(void)
1367 {
1368 #ifdef DF
1369         const char *lfp;
1370 #endif
1371
1372         /* force buffer allocation */
1373         shf_fdopen(1, SHF_WR, shl_stdout);
1374         shf_fdopen(2, SHF_WR, shl_out);
1375         shf_fdopen(2, SHF_WR, shl_xtrace);
1376 #ifdef DF
1377         if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
1378                 if ((lfp = getenv("HOME")) == NULL || !mksh_abspath(lfp))
1379                         errorf("cannot get home directory");
1380                 lfp = shf_smprintf("%s/mksh-dbg.txt", lfp);
1381         }
1382
1383         if ((shl_dbg_fd = open(lfp, O_WRONLY | O_APPEND | O_CREAT, 0600)) < 0)
1384                 errorf("cannot open debug output file %s", lfp);
1385         if (shl_dbg_fd < FDBASE) {
1386                 int nfd;
1387
1388                 nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE);
1389                 close(shl_dbg_fd);
1390                 if ((shl_dbg_fd = nfd) == -1)
1391                         errorf("cannot dup debug output file");
1392         }
1393         fcntl(shl_dbg_fd, F_SETFD, FD_CLOEXEC);
1394         shf_fdopen(shl_dbg_fd, SHF_WR, shl_dbg);
1395         DF("=== open ===");
1396 #endif
1397         initio_done = true;
1398 }
1399
1400 /* A dup2() with error checking */
1401 int
1402 ksh_dup2(int ofd, int nfd, bool errok)
1403 {
1404         int rv;
1405
1406         if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF))
1407                 errorf("too many files open in shell");
1408
1409 #ifdef __ultrix
1410         /*XXX imake style */
1411         if (rv >= 0)
1412                 fcntl(nfd, F_SETFD, 0);
1413 #endif
1414
1415         return (rv);
1416 }
1417
1418 /*
1419  * Move fd from user space (0 <= fd < 10) to shell space (fd >= 10),
1420  * set close-on-exec flag. See FDBASE in sh.h, maybe 24 not 10 here.
1421  */
1422 short
1423 savefd(int fd)
1424 {
1425         int nfd = fd;
1426
1427         if (fd < FDBASE && (nfd = fcntl(fd, F_DUPFD, FDBASE)) < 0 &&
1428             (errno == EBADF || errno == EPERM))
1429                 return (-1);
1430         if (nfd < 0 || nfd > SHRT_MAX)
1431                 errorf("too many files open in shell");
1432         fcntl(nfd, F_SETFD, FD_CLOEXEC);
1433         return ((short)nfd);
1434 }
1435
1436 void
1437 restfd(int fd, int ofd)
1438 {
1439         if (fd == 2)
1440                 shf_flush(&shf_iob[/* fd */ 2]);
1441         if (ofd < 0)
1442                 /* original fd closed */
1443                 close(fd);
1444         else if (fd != ofd) {
1445                 /*XXX: what to do if this dup fails? */
1446                 ksh_dup2(ofd, fd, true);
1447                 close(ofd);
1448         }
1449 }
1450
1451 void
1452 openpipe(int *pv)
1453 {
1454         int lpv[2];
1455
1456         if (pipe(lpv) < 0)
1457                 errorf("can't create pipe - try again");
1458         pv[0] = savefd(lpv[0]);
1459         if (pv[0] != lpv[0])
1460                 close(lpv[0]);
1461         pv[1] = savefd(lpv[1]);
1462         if (pv[1] != lpv[1])
1463                 close(lpv[1]);
1464 }
1465
1466 void
1467 closepipe(int *pv)
1468 {
1469         close(pv[0]);
1470         close(pv[1]);
1471 }
1472
1473 /*
1474  * Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
1475  * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
1476  */
1477 int
1478 check_fd(const char *name, int mode, const char **emsgp)
1479 {
1480         int fd = 0, fl;
1481
1482         if (name[0] == 'p' && !name[1])
1483                 return (coproc_getfd(mode, emsgp));
1484         while (ksh_isdigit(*name)) {
1485                 fd = fd * 10 + ksh_numdig(*name);
1486                 if (fd >= FDBASE) {
1487                         if (emsgp)
1488                                 *emsgp = "file descriptor too large";
1489                         return (-1);
1490                 }
1491                 ++name;
1492         }
1493         if (*name) {
1494                 if (emsgp)
1495                         *emsgp = "illegal file descriptor name";
1496                 return (-1);
1497         }
1498         if ((fl = fcntl(fd, F_GETFL, 0)) < 0) {
1499                 if (emsgp)
1500                         *emsgp = "bad file descriptor";
1501                 return (-1);
1502         }
1503         fl &= O_ACCMODE;
1504         /*
1505          * X_OK is a kludge to disable this check for dups (x<&1):
1506          * historical shells never did this check (XXX don't know what
1507          * POSIX has to say).
1508          */
1509         if (!(mode & X_OK) && fl != O_RDWR && (
1510             ((mode & R_OK) && fl != O_RDONLY) ||
1511             ((mode & W_OK) && fl != O_WRONLY))) {
1512                 if (emsgp)
1513                         *emsgp = (fl == O_WRONLY) ?
1514                             "fd not open for reading" :
1515                             "fd not open for writing";
1516                 return (-1);
1517         }
1518         return (fd);
1519 }
1520
1521 /* Called once from main */
1522 void
1523 coproc_init(void)
1524 {
1525         coproc.read = coproc.readw = coproc.write = -1;
1526         coproc.njobs = 0;
1527         coproc.id = 0;
1528 }
1529
1530 /* Called by c_read() when eof is read - close fd if it is the co-process fd */
1531 void
1532 coproc_read_close(int fd)
1533 {
1534         if (coproc.read >= 0 && fd == coproc.read) {
1535                 coproc_readw_close(fd);
1536                 close(coproc.read);
1537                 coproc.read = -1;
1538         }
1539 }
1540
1541 /*
1542  * Called by c_read() and by iosetup() to close the other side of the
1543  * read pipe, so reads will actually terminate.
1544  */
1545 void
1546 coproc_readw_close(int fd)
1547 {
1548         if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) {
1549                 close(coproc.readw);
1550                 coproc.readw = -1;
1551         }
1552 }
1553
1554 /*
1555  * Called by c_print when a write to a fd fails with EPIPE and by iosetup
1556  * when co-process input is dup'd
1557  */
1558 void
1559 coproc_write_close(int fd)
1560 {
1561         if (coproc.write >= 0 && fd == coproc.write) {
1562                 close(coproc.write);
1563                 coproc.write = -1;
1564         }
1565 }
1566
1567 /*
1568  * Called to check for existence of/value of the co-process file descriptor.
1569  * (Used by check_fd() and by c_read/c_print to deal with -p option).
1570  */
1571 int
1572 coproc_getfd(int mode, const char **emsgp)
1573 {
1574         int fd = (mode & R_OK) ? coproc.read : coproc.write;
1575
1576         if (fd >= 0)
1577                 return (fd);
1578         if (emsgp)
1579                 *emsgp = "no coprocess";
1580         return (-1);
1581 }
1582
1583 /*
1584  * called to close file descriptors related to the coprocess (if any)
1585  * Should be called with SIGCHLD blocked.
1586  */
1587 void
1588 coproc_cleanup(int reuse)
1589 {
1590         /* This to allow co-processes to share output pipe */
1591         if (!reuse || coproc.readw < 0 || coproc.read < 0) {
1592                 if (coproc.read >= 0) {
1593                         close(coproc.read);
1594                         coproc.read = -1;
1595                 }
1596                 if (coproc.readw >= 0) {
1597                         close(coproc.readw);
1598                         coproc.readw = -1;
1599                 }
1600         }
1601         if (coproc.write >= 0) {
1602                 close(coproc.write);
1603                 coproc.write = -1;
1604         }
1605 }
1606
1607 struct temp *
1608 maketemp(Area *ap, Temp_type type, struct temp **tlist)
1609 {
1610         char *cp;
1611         size_t len;
1612         int i, j;
1613         struct temp *tp;
1614         const char *dir;
1615         struct stat sb;
1616
1617         dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR;
1618         /* add "/shXXXXXX.tmp" plus NUL */
1619         len = strlen(dir);
1620         checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14);
1621         tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap);
1622
1623         tp->shf = NULL;
1624         tp->pid = procpid;
1625         tp->type = type;
1626
1627         if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) {
1628                 tp->tffn[0] = '\0';
1629                 goto maketemp_out;
1630         }
1631
1632         cp = (void *)tp;
1633         cp += offsetof(struct temp, tffn[0]);
1634         memcpy(cp, dir, len);
1635         cp += len;
1636         memcpy(cp, "/shXXXXXX.tmp", 14);
1637         /* point to the first of six Xes */
1638         cp += 3;
1639
1640         /* cyclically attempt to open a temporary file */
1641         do {
1642                 /* generate random part of filename */
1643                 len = 0;
1644                 do {
1645                         cp[len++] = digits_lc[rndget() % 36];
1646                 } while (len < 6);
1647
1648                 /* check if this one works */
1649                 if ((i = binopen3(tp->tffn, O_CREAT | O_EXCL | O_RDWR,
1650                     0600)) < 0 && errno != EEXIST)
1651                         goto maketemp_out;
1652         } while (i < 0);
1653
1654         if (type == TT_FUNSUB) {
1655                 /* map us high and mark as close-on-exec */
1656                 if ((j = savefd(i)) != i) {
1657                         close(i);
1658                         i = j;
1659                 }
1660
1661                 /* operation mode for the shf */
1662                 j = SHF_RD;
1663         } else
1664                 j = SHF_WR;
1665
1666         /* shf_fdopen cannot fail, so no fd leak */
1667         tp->shf = shf_fdopen(i, j, NULL);
1668
1669  maketemp_out:
1670         tp->next = *tlist;
1671         *tlist = tp;
1672         return (tp);
1673 }
1674
1675 /*
1676  * We use a similar collision resolution algorithm as Python 2.5.4
1677  * but with a slightly tweaked implementation written from scratch.
1678  */
1679
1680 #define INIT_TBLSHIFT   3       /* initial table shift (2^3 = 8) */
1681 #define PERTURB_SHIFT   5       /* see Python 2.5.4 Objects/dictobject.c */
1682
1683 static void tgrow(struct table *);
1684 static int tnamecmp(const void *, const void *);
1685
1686 static void
1687 tgrow(struct table *tp)
1688 {
1689         size_t i, j, osize, mask, perturb;
1690         struct tbl *tblp, **pp;
1691         struct tbl **ntblp, **otblp = tp->tbls;
1692
1693         if (tp->tshift > 29)
1694                 internal_errorf("hash table size limit reached");
1695
1696         /* calculate old size, new shift and new size */
1697         osize = (size_t)1 << (tp->tshift++);
1698         i = osize << 1;
1699
1700         ntblp = alloc2(i, sizeof(struct tbl *), tp->areap);
1701         /* multiplication cannot overflow: alloc2 checked that */
1702         memset(ntblp, 0, i * sizeof(struct tbl *));
1703
1704         /* table can get very full when reaching its size limit */
1705         tp->nfree = (tp->tshift == 30) ? 0x3FFF0000UL :
1706             /* but otherwise, only 75% */
1707             ((i * 3) / 4);
1708         tp->tbls = ntblp;
1709         if (otblp == NULL)
1710                 return;
1711
1712         mask = i - 1;
1713         for (i = 0; i < osize; i++)
1714                 if ((tblp = otblp[i]) != NULL) {
1715                         if ((tblp->flag & DEFINED)) {
1716                                 /* search for free hash table slot */
1717                                 j = perturb = tblp->ua.hval;
1718                                 goto find_first_empty_slot;
1719  find_next_empty_slot:
1720                                 j = (j << 2) + j + perturb + 1;
1721                                 perturb >>= PERTURB_SHIFT;
1722  find_first_empty_slot:
1723                                 pp = &ntblp[j & mask];
1724                                 if (*pp != NULL)
1725                                         goto find_next_empty_slot;
1726                                 /* found an empty hash table slot */
1727                                 *pp = tblp;
1728                                 tp->nfree--;
1729                         } else if (!(tblp->flag & FINUSE)) {
1730                                 afree(tblp, tp->areap);
1731                         }
1732                 }
1733         afree(otblp, tp->areap);
1734 }
1735
1736 void
1737 ktinit(Area *ap, struct table *tp, uint8_t initshift)
1738 {
1739         tp->areap = ap;
1740         tp->tbls = NULL;
1741         tp->tshift = ((initshift > INIT_TBLSHIFT) ?
1742             initshift : INIT_TBLSHIFT) - 1;
1743         tgrow(tp);
1744 }
1745
1746 /* table, name (key) to search for, hash(name), rv pointer to tbl ptr */
1747 struct tbl *
1748 ktscan(struct table *tp, const char *name, uint32_t h, struct tbl ***ppp)
1749 {
1750         size_t j, perturb, mask;
1751         struct tbl **pp, *p;
1752
1753         mask = ((size_t)1 << (tp->tshift)) - 1;
1754         /* search for hash table slot matching name */
1755         j = perturb = h;
1756         goto find_first_slot;
1757  find_next_slot:
1758         j = (j << 2) + j + perturb + 1;
1759         perturb >>= PERTURB_SHIFT;
1760  find_first_slot:
1761         pp = &tp->tbls[j & mask];
1762         if ((p = *pp) != NULL && (p->ua.hval != h || !(p->flag & DEFINED) ||
1763             strcmp(p->name, name)))
1764                 goto find_next_slot;
1765         /* p == NULL if not found, correct found entry otherwise */
1766         if (ppp)
1767                 *ppp = pp;
1768         return (p);
1769 }
1770
1771 /* table, name (key) to enter, hash(n) */
1772 struct tbl *
1773 ktenter(struct table *tp, const char *n, uint32_t h)
1774 {
1775         struct tbl **pp, *p;
1776         size_t len;
1777
1778  Search:
1779         if ((p = ktscan(tp, n, h, &pp)))
1780                 return (p);
1781
1782         if (tp->nfree == 0) {
1783                 /* too full */
1784                 tgrow(tp);
1785                 goto Search;
1786         }
1787
1788         /* create new tbl entry */
1789         len = strlen(n);
1790         checkoktoadd(len, offsetof(struct tbl, name[0]) + 1);
1791         p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap);
1792         p->flag = 0;
1793         p->type = 0;
1794         p->areap = tp->areap;
1795         p->ua.hval = h;
1796         p->u2.field = 0;
1797         p->u.array = NULL;
1798         memcpy(p->name, n, len);
1799
1800         /* enter in tp->tbls */
1801         tp->nfree--;
1802         *pp = p;
1803         return (p);
1804 }
1805
1806 void
1807 ktwalk(struct tstate *ts, struct table *tp)
1808 {
1809         ts->left = (size_t)1 << (tp->tshift);
1810         ts->next = tp->tbls;
1811 }
1812
1813 struct tbl *
1814 ktnext(struct tstate *ts)
1815 {
1816         while (--ts->left >= 0) {
1817                 struct tbl *p = *ts->next++;
1818                 if (p != NULL && (p->flag & DEFINED))
1819                         return (p);
1820         }
1821         return (NULL);
1822 }
1823
1824 static int
1825 tnamecmp(const void *p1, const void *p2)
1826 {
1827         const struct tbl *a = *((const struct tbl * const *)p1);
1828         const struct tbl *b = *((const struct tbl * const *)p2);
1829
1830         return (strcmp(a->name, b->name));
1831 }
1832
1833 struct tbl **
1834 ktsort(struct table *tp)
1835 {
1836         size_t i;
1837         struct tbl **p, **sp, **dp;
1838
1839         /*
1840          * since the table is never entirely full, no need to reserve
1841          * additional space for the trailing NULL appended below
1842          */
1843         i = (size_t)1 << (tp->tshift);
1844         p = alloc2(i, sizeof(struct tbl *), ATEMP);
1845         sp = tp->tbls;          /* source */
1846         dp = p;                 /* dest */
1847         while (i--)
1848                 if ((*dp = *sp++) != NULL && (((*dp)->flag & DEFINED) ||
1849                     ((*dp)->flag & ARRAY)))
1850                         dp++;
1851         qsort(p, (i = dp - p), sizeof(struct tbl *), tnamecmp);
1852         p[i] = NULL;
1853         return (p);
1854 }
1855
1856 #ifdef SIGWINCH
1857 static void
1858 x_sigwinch(int sig MKSH_A_UNUSED)
1859 {
1860         /* this runs inside interrupt context, with errno saved */
1861
1862         got_winch = 1;
1863 }
1864 #endif
1865
1866 #ifdef DF
1867 void
1868 DF(const char *fmt, ...)
1869 {
1870         va_list args;
1871         struct timeval tv;
1872         mirtime_mjd mjd;
1873
1874         mksh_lockfd(shl_dbg_fd);
1875         mksh_TIME(tv);
1876         timet2mjd(&mjd, tv.tv_sec);
1877         shf_fprintf(shl_dbg, "[%02u:%02u:%02u (%u) %u.%06u] ",
1878             (unsigned)mjd.sec / 3600, ((unsigned)mjd.sec / 60) % 60,
1879             (unsigned)mjd.sec % 60, (unsigned)getpid(),
1880             (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
1881         va_start(args, fmt);
1882         shf_vfprintf(shl_dbg, fmt, args);
1883         va_end(args);
1884         shf_putc('\n', shl_dbg);
1885         shf_flush(shl_dbg);
1886         mksh_unlkfd(shl_dbg_fd);
1887 }
1888 #endif
1889
1890 void
1891 x_mkraw(int fd, mksh_ttyst *ocb, bool forread)
1892 {
1893         mksh_ttyst cb;
1894
1895         if (ocb)
1896                 mksh_tcget(fd, ocb);
1897         else
1898                 ocb = &tty_state;
1899
1900         cb = *ocb;
1901         if (forread) {
1902                 cb.c_iflag &= ~(ISTRIP);
1903                 cb.c_lflag &= ~(ICANON) | ECHO;
1904         } else {
1905                 cb.c_iflag &= ~(INLCR | ICRNL | ISTRIP);
1906                 cb.c_lflag &= ~(ISIG | ICANON | ECHO);
1907         }
1908 #if defined(VLNEXT) && defined(_POSIX_VDISABLE)
1909         /* OSF/1 processes lnext when ~icanon */
1910         cb.c_cc[VLNEXT] = _POSIX_VDISABLE;
1911 #endif
1912         /* SunOS 4.1.x & OSF/1 processes discard(flush) when ~icanon */
1913 #if defined(VDISCARD) && defined(_POSIX_VDISABLE)
1914         cb.c_cc[VDISCARD] = _POSIX_VDISABLE;
1915 #endif
1916         cb.c_cc[VTIME] = 0;
1917         cb.c_cc[VMIN] = 1;
1918
1919         mksh_tcset(fd, &cb);
1920 }