Update web page...
[oweals/busybox.git] / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Kenneth Almquist.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26  * package.
27  *
28  * Modified by Erik Andersen <andersee@debian.org> and
29  * Vladimir Oleynik <vodz@usa.net> to be used in busybox
30  *
31  *
32  * Original copyright notice is retained at the end of this file.
33  */
34
35
36 /* These defines allow you to adjust the feature set to be compiled
37  * into the ash shell.   As a rule, enabling these options will make
38  * ash get bigger...   With all of these options off, ash adds about
39  * 62k to busybox on an x86 system.*/
40
41
42
43 /* Enable job control.  This allows you to run jobs in the background,
44  * which is great when ash is being  used as an interactive shell, but
45  * it completely useless for is all you are doing is running scripts.
46  * This adds about 2.5k on an x86 system. */
47 #define JOBS
48
49 /* This enables alias support in ash.  If you want to support things
50  * like "alias ls='ls -l'" with ash, enable this.  This is only useful
51  * when ash is used as an intractive shell.   This adds about 1.5k */
52 #define ASH_ALIAS
53
54 /* If you need ash to act as a full Posix shell, with full math
55  * support, enable this.   This option needs some work, since it
56  * doesn't compile right now... */
57 #undef ASH_MATH_SUPPORT
58
59 /* This shell builtin is used to indicate how the shell would interpret
60  * what you give it.  This command is only useful when debugging, and
61  * is obsolete anyways.  Adds about 670 bytes... You probably want to
62  * leave this disabled. */
63 #undef ASH_TYPE
64
65 /* Getopts is used by shell procedures to parse positional parameters.
66  * You probably want to leave this disabled, and use the busybox getopt
67  * applet if you want to do this sort of thing.  There are some scripts
68  * out there that use it, so it you need it, enable.  Most people will
69  * leave this disabled.  This adds 1k on an x86 system. */
70 #undef ASH_GETOPTS
71
72 /* This allows you to override shell builtins and use whatever is on
73  * the filesystem.  This is most useful when ash is acting as a
74  * standalone shell.   Adds about 320 bytes. */
75 #undef ASH_CMDCMD
76
77 /* This makes a few common apps that are usually part of busybox
78  * anyways to be used as builtins.  This may cause these builtins to be
79  * a little bit faster, but leaving this disabled will save you 2k. */
80 #undef ASH_BBAPPS_AS_BUILTINS
81
82 /* Optimize size vs speed as size */
83 #define ASH_OPTIMIZE_FOR_SIZE
84
85 /* Enable this to compile in extra debugging noise.  When debugging is
86  * on, debugging info will be written to $HOME/trace and a quit signal
87  * will generate a core dump. */
88 #undef DEBUG
89
90
91
92 /* These are here to work with glibc -- Don't change these... */
93 #undef FNMATCH_BROKEN
94 #undef GLOB_BROKEN
95 #undef _GNU_SOURCE
96
97 #include <assert.h>
98 #include <ctype.h>
99 #include <dirent.h>
100 #include <errno.h>
101 #include <fcntl.h>
102 #include <limits.h>
103 #include <paths.h>
104 #include <pwd.h>
105 #include <setjmp.h>
106 #include <signal.h>
107 #include <stdarg.h>
108 #include <stdbool.h>
109 #include <stdio.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <sysexits.h>
113 #include <unistd.h>
114 #include <sys/stat.h>
115 #include <sys/cdefs.h>
116 #include <sys/ioctl.h>
117 #include <sys/param.h>
118 #include <sys/resource.h>
119 #include <sys/time.h>
120 #include <sys/times.h>
121 #include <sys/types.h>
122 #include <sys/wait.h>
123
124
125 #if !defined(FNMATCH_BROKEN)
126 #include <fnmatch.h>
127 #endif
128 #if !defined(GLOB_BROKEN)
129 #include <glob.h>
130 #endif
131
132 #ifdef JOBS
133 #include <termios.h>
134 #endif
135
136 #include "busybox.h"
137 #include "cmdedit.h"
138
139 /*
140  * This file was generated by the mksyntax program.
141  */
142
143 /* Syntax classes */
144 #define CWORD 0                 /* character is nothing special */
145 #define CNL 1                   /* newline character */
146 #define CBACK 2                 /* a backslash character */
147 #define CSQUOTE 3               /* single quote */
148 #define CDQUOTE 4               /* double quote */
149 #define CENDQUOTE 5             /* a terminating quote */
150 #define CBQUOTE 6               /* backwards single quote */
151 #define CVAR 7                  /* a dollar sign */
152 #define CENDVAR 8               /* a '}' character */
153 #define CLP 9                   /* a left paren in arithmetic */
154 #define CRP 10                  /* a right paren in arithmetic */
155 #define CENDFILE 11             /* end of file */
156 #define CCTL 12                 /* like CWORD, except it must be escaped */
157 #define CSPCL 13                /* these terminate a word */
158 #define CIGN 14                 /* character should be ignored */
159
160 /* Syntax classes for is_ functions */
161 #define ISDIGIT 01              /* a digit */
162 #define ISUPPER 02              /* an upper case letter */
163 #define ISLOWER 04              /* a lower case letter */
164 #define ISUNDER 010             /* an underscore */
165 #define ISSPECL 020             /* the name of a special parameter */
166
167 #define SYNBASE 130
168 #define PEOF -130
169
170 #define PEOA -129
171
172 #define TEOF 0
173 #define TNL 1
174 #define TSEMI 2
175 #define TBACKGND 3
176 #define TAND 4
177 #define TOR 5
178 #define TPIPE 6
179 #define TLP 7
180 #define TRP 8
181 #define TENDCASE 9
182 #define TENDBQUOTE 10
183 #define TREDIR 11
184 #define TWORD 12
185 #define TASSIGN 13
186 #define TNOT 14
187 #define TCASE 15
188 #define TDO 16
189 #define TDONE 17
190 #define TELIF 18
191 #define TELSE 19
192 #define TESAC 20
193 #define TFI 21
194 #define TFOR 22
195 #define TIF 23
196 #define TIN 24
197 #define TTHEN 25
198 #define TUNTIL 26
199 #define TWHILE 27
200 #define TBEGIN 28
201 #define TEND 29
202
203
204 #define BASESYNTAX (basesyntax + SYNBASE)
205 #define DQSYNTAX (dqsyntax + SYNBASE)
206 #define SQSYNTAX (sqsyntax + SYNBASE)
207 #define ARISYNTAX (arisyntax + SYNBASE)
208
209 /* control characters in argument strings */
210 #define CTLESC '\201'
211 #define CTLVAR '\202'
212 #define CTLENDVAR '\203'
213 #define CTLBACKQ '\204'
214 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
215 /*      CTLBACKQ | CTLQUOTE == '\205' */
216 #define CTLARI  '\206'
217 #define CTLENDARI '\207'
218 #define CTLQUOTEMARK '\210'
219
220 #define is_digit(c)     ((((unsigned char)(c)) - '0') <= 9)
221 #define is_alpha(c)     (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
222 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
223 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
224 #define is_special(c)   ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
225 #define digit_val(c)    ((c) - '0')
226
227
228 #define _DIAGASSERT(x)
229
230
231
232 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
233 #define S_CATCH 2               /* signal is caught */
234 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
235 #define S_HARD_IGN 4            /* signal is ignored permenantly */
236 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
237
238
239 /* variable substitution byte (follows CTLVAR) */
240 #define VSTYPE  0x0f            /* type of variable substitution */
241 #define VSNUL   0x10            /* colon--treat the empty string as unset */
242 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
243
244 /* values of VSTYPE field */
245 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
246 #define VSMINUS         0x2             /* ${var-text} */
247 #define VSPLUS          0x3             /* ${var+text} */
248 #define VSQUESTION      0x4             /* ${var?message} */
249 #define VSASSIGN        0x5             /* ${var=text} */
250 #define VSTRIMLEFT      0x6             /* ${var#pattern} */
251 #define VSTRIMLEFTMAX   0x7             /* ${var##pattern} */
252 #define VSTRIMRIGHT     0x8             /* ${var%pattern} */
253 #define VSTRIMRIGHTMAX  0x9             /* ${var%%pattern} */
254 #define VSLENGTH        0xa             /* ${#var} */
255
256 /* flags passed to redirect */
257 #define REDIR_PUSH 01           /* save previous values of file descriptors */
258 #define REDIR_BACKQ 02          /* save the command output to pipe */
259
260 /*
261  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
262  * so we use _setjmp instead.
263  */
264
265 #if !defined(__GLIBC__)
266 #define setjmp(jmploc)  _setjmp(jmploc)
267 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
268 #endif
269
270 /*
271  * Most machines require the value returned from malloc to be aligned
272  * in some way.  The following macro will get this right on many machines.
273  */
274
275 #ifndef ALIGN
276 union align {
277         int i;
278         char *cp;
279 };
280
281 #define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
282 #endif
283
284 #ifdef BB_LOCALE_SUPPORT
285 #include <locale.h>
286 static void change_lc_all(const char *value);
287 static void change_lc_ctype(const char *value);
288 #endif
289
290 /*
291  * These macros allow the user to suspend the handling of interrupt signals
292  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
293  * much more efficient and portable.  (But hacking the kernel is so much
294  * more fun than worrying about efficiency and portability. :-))
295  */
296
297 static void onint (void);
298 static volatile int suppressint;
299 static volatile int intpending;
300
301 #define INTOFF suppressint++
302 #ifndef ASH_OPTIMIZE_FOR_SIZE
303 #define INTON { if (--suppressint == 0 && intpending) onint(); }
304 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
305 #else
306 static void __inton (void);
307 static void forceinton (void);
308 #define INTON __inton()
309 #define FORCEINTON forceinton()
310 #endif
311
312 #define CLEAR_PENDING_INT intpending = 0
313 #define int_pending() intpending
314
315
316 typedef void *pointer;
317 #ifndef NULL
318 #define NULL (void *)0
319 #endif
320
321 static inline pointer  ckmalloc (int sz)          { return xmalloc(sz);     }
322 static inline pointer  ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
323 static inline char *   savestr  (const char *s)   { return xstrdup(s);      }
324
325 static pointer stalloc (int);
326 static void stunalloc (pointer);
327 static void ungrabstackstr (char *, char *);
328 static char * growstackstr(void);
329 static char * makestrspace(size_t newlen);
330 static char *sstrdup (const char *);
331
332 /*
333  * Parse trees for commands are allocated in lifo order, so we use a stack
334  * to make this more efficient, and also to avoid all sorts of exception
335  * handling code to handle interrupts in the middle of a parse.
336  *
337  * The size 504 was chosen because the Ultrix malloc handles that size
338  * well.
339  */
340
341 #define MINSIZE 504             /* minimum size of a block */
342
343
344 struct stack_block {
345         struct stack_block *prev;
346         char space[MINSIZE];
347 };
348
349 static struct stack_block stackbase;
350 static struct stack_block *stackp = &stackbase;
351 static struct stackmark *markp;
352 static char *stacknxt = stackbase.space;
353 static int stacknleft = MINSIZE;
354
355
356 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
357
358 #define stackblock() stacknxt
359 #define stackblocksize() stacknleft
360 #define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
361
362 #define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
363 #define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
364 #define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
365
366
367 #define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
368 #define STUNPUTC(p)     (++sstrnleft, --p)
369 #define STTOPC(p)       p[-1]
370 #define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
371 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
372
373 #define ckfree(p)       free((pointer)(p))
374
375
376 #ifdef DEBUG
377 #define TRACE(param)    trace param
378 static void trace (const char *, ...);
379 static void trargs (char **);
380 static void showtree (union node *);
381 static void trputc (int);
382 static void trputs (const char *);
383 static void opentrace (void);
384 #else
385 #define TRACE(param)
386 #endif
387
388 #define NSEMI 0
389 #define NCMD 1
390 #define NPIPE 2
391 #define NREDIR 3
392 #define NBACKGND 4
393 #define NSUBSHELL 5
394 #define NAND 6
395 #define NOR 7
396 #define NIF 8
397 #define NWHILE 9
398 #define NUNTIL 10
399 #define NFOR 11
400 #define NCASE 12
401 #define NCLIST 13
402 #define NDEFUN 14
403 #define NARG 15
404 #define NTO 16
405 #define NFROM 17
406 #define NFROMTO 18
407 #define NAPPEND 19
408 #define NTOOV 20
409 #define NTOFD 21
410 #define NFROMFD 22
411 #define NHERE 23
412 #define NXHERE 24
413 #define NNOT 25
414
415 /*
416  * expandarg() flags
417  */
418 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
419 #define EXP_TILDE       0x2     /* do normal tilde expansion */
420 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
421 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
422 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
423 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
424
425
426 #define NOPTS   16
427
428 static char optet_vals[NOPTS];
429
430 static const char * const optlist[NOPTS] = {
431         "e" "errexit",
432         "f" "noglob",
433         "I" "ignoreeof",
434         "i" "interactive",
435         "m" "monitor",
436         "n" "noexec",
437         "s" "stdin",
438         "x" "xtrace",
439         "v" "verbose",
440         "V" "vi",
441         "E" "emacs",
442         "C" "noclobber",
443         "a" "allexport",
444         "b" "notify",
445         "u" "nounset",
446         "q" "quietprofile"
447 };
448
449 #define optent_name(optent) (optent+1)
450 #define optent_letter(optent) optent[0]
451 #define optent_val(optent) optet_vals[optent]
452
453 #define eflag optent_val(0)
454 #define fflag optent_val(1)
455 #define Iflag optent_val(2)
456 #define iflag optent_val(3)
457 #define mflag optent_val(4)
458 #define nflag optent_val(5)
459 #define sflag optent_val(6)
460 #define xflag optent_val(7)
461 #define vflag optent_val(8)
462 #define Vflag optent_val(9)
463 #define Eflag optent_val(10)
464 #define Cflag optent_val(11)
465 #define aflag optent_val(12)
466 #define bflag optent_val(13)
467 #define uflag optent_val(14)
468 #define qflag optent_val(15)
469
470
471 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
472 #define FORK_FG 0
473 #define FORK_BG 1
474 #define FORK_NOJOB 2
475
476
477 struct nbinary {
478       int type;
479       union node *ch1;
480       union node *ch2;
481 };
482
483
484 struct ncmd {
485       int type;
486       int backgnd;
487       union node *assign;
488       union node *args;
489       union node *redirect;
490 };
491
492
493 struct npipe {
494       int type;
495       int backgnd;
496       struct nodelist *cmdlist;
497 };
498
499
500 struct nredir {
501       int type;
502       union node *n;
503       union node *redirect;
504 };
505
506
507 struct nif {
508       int type;
509       union node *test;
510       union node *ifpart;
511       union node *elsepart;
512 };
513
514
515 struct nfor {
516       int type;
517       union node *args;
518       union node *body;
519       char *var;
520 };
521
522
523 struct ncase {
524       int type;
525       union node *expr;
526       union node *cases;
527 };
528
529
530 struct nclist {
531       int type;
532       union node *next;
533       union node *pattern;
534       union node *body;
535 };
536
537
538 struct narg {
539       int type;
540       union node *next;
541       char *text;
542       struct nodelist *backquote;
543 };
544
545
546 struct nfile {
547       int type;
548       union node *next;
549       int fd;
550       union node *fname;
551       char *expfname;
552 };
553
554
555 struct ndup {
556       int type;
557       union node *next;
558       int fd;
559       int dupfd;
560       union node *vname;
561 };
562
563
564 struct nhere {
565       int type;
566       union node *next;
567       int fd;
568       union node *doc;
569 };
570
571
572 struct nnot {
573       int type;
574       union node *com;
575 };
576
577
578 union node {
579       int type;
580       struct nbinary nbinary;
581       struct ncmd ncmd;
582       struct npipe npipe;
583       struct nredir nredir;
584       struct nif nif;
585       struct nfor nfor;
586       struct ncase ncase;
587       struct nclist nclist;
588       struct narg narg;
589       struct nfile nfile;
590       struct ndup ndup;
591       struct nhere nhere;
592       struct nnot nnot;
593 };
594
595
596 struct nodelist {
597         struct nodelist *next;
598         union node *n;
599 };
600
601 struct backcmd {                /* result of evalbackcmd */
602         int fd;                 /* file descriptor to read from */
603         char *buf;              /* buffer */
604         int nleft;              /* number of chars in buffer */
605         struct job *jp;         /* job structure for command */
606 };
607
608 struct cmdentry {
609         int cmdtype;
610         union param {
611                 int index;
612                 union node *func;
613                 const struct builtincmd *cmd;
614         } u;
615 };
616
617 struct strlist {
618         struct strlist *next;
619         char *text;
620 };
621
622
623 struct arglist {
624         struct strlist *list;
625         struct strlist **lastp;
626 };
627
628 struct strpush {
629         struct strpush *prev;   /* preceding string on stack */
630         char *prevstring;
631         int prevnleft;
632 #ifdef ASH_ALIAS
633         struct alias *ap;       /* if push was associated with an alias */
634 #endif
635         char *string;           /* remember the string since it may change */
636 };
637
638 struct parsefile {
639         struct parsefile *prev; /* preceding file on stack */
640         int linno;              /* current line */
641         int fd;                 /* file descriptor (or -1 if string) */
642         int nleft;              /* number of chars left in this line */
643         int lleft;              /* number of chars left in this buffer */
644         char *nextc;            /* next char in buffer */
645         char *buf;              /* input buffer */
646         struct strpush *strpush; /* for pushing strings at this level */
647         struct strpush basestrpush; /* so pushing one is fast */
648 };
649
650 struct stackmark {
651         struct stack_block *stackp;
652         char *stacknxt;
653         int stacknleft;
654         struct stackmark *marknext;
655 };
656
657 struct shparam {
658         int nparam;             /* # of positional parameters (without $0) */
659         unsigned char malloc;   /* if parameter list dynamically allocated */
660         char **p;               /* parameter list */
661         int optind;             /* next parameter to be processed by getopts */
662         int optoff;             /* used by getopts */
663 };
664
665 static void flushall (void);
666 static void out2fmt (const char *, ...)
667     __attribute__((__format__(__printf__,1,2)));
668 static void out1fmt (const char *, ...)
669     __attribute__((__format__(__printf__,1,2)));
670 static int xwrite (int, const char *, int);
671
672 static void outstr (const char *p, FILE *file) { fputs(p, file); }
673 static void out1str(const char *p) { outstr(p, stdout); }
674 static void out2str(const char *p) { outstr(p, stderr); }
675
676 #define out2c(c)        putc((c), stderr)
677
678 /* syntax table used when not in quotes */
679 static const char basesyntax[257] = {
680       CENDFILE,   CSPCL,   CWORD,   CCTL,
681       CCTL,    CCTL,    CCTL,    CCTL,
682       CCTL,    CCTL,    CCTL,    CWORD,
683       CWORD,   CWORD,   CWORD,   CWORD,
684       CWORD,   CWORD,   CWORD,   CWORD,
685       CWORD,   CWORD,   CWORD,   CWORD,
686       CWORD,   CWORD,   CWORD,   CWORD,
687       CWORD,   CWORD,   CWORD,   CWORD,
688       CWORD,   CWORD,   CWORD,   CWORD,
689       CWORD,   CWORD,   CWORD,   CWORD,
690       CWORD,   CWORD,   CWORD,   CWORD,
691       CWORD,   CWORD,   CWORD,   CWORD,
692       CWORD,   CWORD,   CWORD,   CWORD,
693       CWORD,   CWORD,   CWORD,   CWORD,
694       CWORD,   CWORD,   CWORD,   CWORD,
695       CWORD,   CWORD,   CWORD,   CWORD,
696       CWORD,   CWORD,   CWORD,   CWORD,
697       CWORD,   CWORD,   CWORD,   CWORD,
698       CWORD,   CWORD,   CWORD,   CWORD,
699       CWORD,   CWORD,   CWORD,   CWORD,
700       CWORD,   CWORD,   CWORD,   CWORD,
701       CWORD,   CWORD,   CWORD,   CWORD,
702       CWORD,   CWORD,   CWORD,   CWORD,
703       CWORD,   CWORD,   CWORD,   CWORD,
704       CWORD,   CWORD,   CWORD,   CWORD,
705       CWORD,   CWORD,   CWORD,   CWORD,
706       CWORD,   CWORD,   CWORD,   CWORD,
707       CWORD,   CWORD,   CWORD,   CWORD,
708       CWORD,   CWORD,   CWORD,   CWORD,
709       CWORD,   CWORD,   CWORD,   CWORD,
710       CWORD,   CWORD,   CWORD,   CWORD,
711       CWORD,   CWORD,   CWORD,   CWORD,
712       CWORD,   CWORD,   CWORD,   CWORD,
713       CWORD,   CWORD,   CWORD,   CWORD,
714       CWORD,   CWORD,   CWORD,   CSPCL,
715       CNL,     CWORD,   CWORD,   CWORD,
716       CWORD,   CWORD,   CWORD,   CWORD,
717       CWORD,   CWORD,   CWORD,   CWORD,
718       CWORD,   CWORD,   CWORD,   CWORD,
719       CWORD,   CWORD,   CWORD,   CWORD,
720       CWORD,   CWORD,   CSPCL,   CWORD,
721       CDQUOTE, CWORD,   CVAR,    CWORD,
722       CSPCL,   CSQUOTE, CSPCL,   CSPCL,
723       CWORD,   CWORD,   CWORD,   CWORD,
724       CWORD,   CWORD,   CWORD,   CWORD,
725       CWORD,   CWORD,   CWORD,   CWORD,
726       CWORD,   CWORD,   CWORD,   CWORD,
727       CWORD,   CSPCL,   CSPCL,   CWORD,
728       CSPCL,   CWORD,   CWORD,   CWORD,
729       CWORD,   CWORD,   CWORD,   CWORD,
730       CWORD,   CWORD,   CWORD,   CWORD,
731       CWORD,   CWORD,   CWORD,   CWORD,
732       CWORD,   CWORD,   CWORD,   CWORD,
733       CWORD,   CWORD,   CWORD,   CWORD,
734       CWORD,   CWORD,   CWORD,   CWORD,
735       CWORD,   CWORD,   CBACK,   CWORD,
736       CWORD,   CWORD,   CBQUOTE, CWORD,
737       CWORD,   CWORD,   CWORD,   CWORD,
738       CWORD,   CWORD,   CWORD,   CWORD,
739       CWORD,   CWORD,   CWORD,   CWORD,
740       CWORD,   CWORD,   CWORD,   CWORD,
741       CWORD,   CWORD,   CWORD,   CWORD,
742       CWORD,   CWORD,   CWORD,   CWORD,
743       CWORD,   CWORD,   CSPCL,   CENDVAR,
744       CWORD
745 };
746
747 /* syntax table used when in double quotes */
748 static const char dqsyntax[257] = {
749       CENDFILE,   CIGN,    CWORD,   CCTL,
750       CCTL,    CCTL,    CCTL,    CCTL,
751       CCTL,    CCTL,    CCTL,    CWORD,
752       CWORD,   CWORD,   CWORD,   CWORD,
753       CWORD,   CWORD,   CWORD,   CWORD,
754       CWORD,   CWORD,   CWORD,   CWORD,
755       CWORD,   CWORD,   CWORD,   CWORD,
756       CWORD,   CWORD,   CWORD,   CWORD,
757       CWORD,   CWORD,   CWORD,   CWORD,
758       CWORD,   CWORD,   CWORD,   CWORD,
759       CWORD,   CWORD,   CWORD,   CWORD,
760       CWORD,   CWORD,   CWORD,   CWORD,
761       CWORD,   CWORD,   CWORD,   CWORD,
762       CWORD,   CWORD,   CWORD,   CWORD,
763       CWORD,   CWORD,   CWORD,   CWORD,
764       CWORD,   CWORD,   CWORD,   CWORD,
765       CWORD,   CWORD,   CWORD,   CWORD,
766       CWORD,   CWORD,   CWORD,   CWORD,
767       CWORD,   CWORD,   CWORD,   CWORD,
768       CWORD,   CWORD,   CWORD,   CWORD,
769       CWORD,   CWORD,   CWORD,   CWORD,
770       CWORD,   CWORD,   CWORD,   CWORD,
771       CWORD,   CWORD,   CWORD,   CWORD,
772       CWORD,   CWORD,   CWORD,   CWORD,
773       CWORD,   CWORD,   CWORD,   CWORD,
774       CWORD,   CWORD,   CWORD,   CWORD,
775       CWORD,   CWORD,   CWORD,   CWORD,
776       CWORD,   CWORD,   CWORD,   CWORD,
777       CWORD,   CWORD,   CWORD,   CWORD,
778       CWORD,   CWORD,   CWORD,   CWORD,
779       CWORD,   CWORD,   CWORD,   CWORD,
780       CWORD,   CWORD,   CWORD,   CWORD,
781       CWORD,   CWORD,   CWORD,   CWORD,
782       CWORD,   CWORD,   CWORD,   CWORD,
783       CWORD,   CWORD,   CWORD,   CWORD,
784       CNL,     CWORD,   CWORD,   CWORD,
785       CWORD,   CWORD,   CWORD,   CWORD,
786       CWORD,   CWORD,   CWORD,   CWORD,
787       CWORD,   CWORD,   CWORD,   CWORD,
788       CWORD,   CWORD,   CWORD,   CWORD,
789       CWORD,   CWORD,   CWORD,   CCTL,
790       CENDQUOTE,CWORD,  CVAR,    CWORD,
791       CWORD,   CWORD,   CWORD,   CWORD,
792       CCTL,    CWORD,   CWORD,   CCTL,
793       CWORD,   CCTL,    CWORD,   CWORD,
794       CWORD,   CWORD,   CWORD,   CWORD,
795       CWORD,   CWORD,   CWORD,   CWORD,
796       CCTL,    CWORD,   CWORD,   CCTL,
797       CWORD,   CCTL,    CWORD,   CWORD,
798       CWORD,   CWORD,   CWORD,   CWORD,
799       CWORD,   CWORD,   CWORD,   CWORD,
800       CWORD,   CWORD,   CWORD,   CWORD,
801       CWORD,   CWORD,   CWORD,   CWORD,
802       CWORD,   CWORD,   CWORD,   CWORD,
803       CWORD,   CWORD,   CWORD,   CWORD,
804       CWORD,   CCTL,    CBACK,   CCTL,
805       CWORD,   CWORD,   CBQUOTE, CWORD,
806       CWORD,   CWORD,   CWORD,   CWORD,
807       CWORD,   CWORD,   CWORD,   CWORD,
808       CWORD,   CWORD,   CWORD,   CWORD,
809       CWORD,   CWORD,   CWORD,   CWORD,
810       CWORD,   CWORD,   CWORD,   CWORD,
811       CWORD,   CWORD,   CWORD,   CWORD,
812       CWORD,   CWORD,   CWORD,   CENDVAR,
813       CCTL
814 };
815
816 /* syntax table used when in single quotes */
817 static const char sqsyntax[257] = {
818       CENDFILE,   CIGN,    CWORD,   CCTL,
819       CCTL,    CCTL,    CCTL,    CCTL,
820       CCTL,    CCTL,    CCTL,    CWORD,
821       CWORD,   CWORD,   CWORD,   CWORD,
822       CWORD,   CWORD,   CWORD,   CWORD,
823       CWORD,   CWORD,   CWORD,   CWORD,
824       CWORD,   CWORD,   CWORD,   CWORD,
825       CWORD,   CWORD,   CWORD,   CWORD,
826       CWORD,   CWORD,   CWORD,   CWORD,
827       CWORD,   CWORD,   CWORD,   CWORD,
828       CWORD,   CWORD,   CWORD,   CWORD,
829       CWORD,   CWORD,   CWORD,   CWORD,
830       CWORD,   CWORD,   CWORD,   CWORD,
831       CWORD,   CWORD,   CWORD,   CWORD,
832       CWORD,   CWORD,   CWORD,   CWORD,
833       CWORD,   CWORD,   CWORD,   CWORD,
834       CWORD,   CWORD,   CWORD,   CWORD,
835       CWORD,   CWORD,   CWORD,   CWORD,
836       CWORD,   CWORD,   CWORD,   CWORD,
837       CWORD,   CWORD,   CWORD,   CWORD,
838       CWORD,   CWORD,   CWORD,   CWORD,
839       CWORD,   CWORD,   CWORD,   CWORD,
840       CWORD,   CWORD,   CWORD,   CWORD,
841       CWORD,   CWORD,   CWORD,   CWORD,
842       CWORD,   CWORD,   CWORD,   CWORD,
843       CWORD,   CWORD,   CWORD,   CWORD,
844       CWORD,   CWORD,   CWORD,   CWORD,
845       CWORD,   CWORD,   CWORD,   CWORD,
846       CWORD,   CWORD,   CWORD,   CWORD,
847       CWORD,   CWORD,   CWORD,   CWORD,
848       CWORD,   CWORD,   CWORD,   CWORD,
849       CWORD,   CWORD,   CWORD,   CWORD,
850       CWORD,   CWORD,   CWORD,   CWORD,
851       CWORD,   CWORD,   CWORD,   CWORD,
852       CWORD,   CWORD,   CWORD,   CWORD,
853       CNL,     CWORD,   CWORD,   CWORD,
854       CWORD,   CWORD,   CWORD,   CWORD,
855       CWORD,   CWORD,   CWORD,   CWORD,
856       CWORD,   CWORD,   CWORD,   CWORD,
857       CWORD,   CWORD,   CWORD,   CWORD,
858       CWORD,   CWORD,   CWORD,   CCTL,
859       CWORD,   CWORD,   CWORD,   CWORD,
860       CWORD,   CENDQUOTE,CWORD,  CWORD,
861       CCTL,    CWORD,   CWORD,   CCTL,
862       CWORD,   CCTL,    CWORD,   CWORD,
863       CWORD,   CWORD,   CWORD,   CWORD,
864       CWORD,   CWORD,   CWORD,   CWORD,
865       CCTL,    CWORD,   CWORD,   CCTL,
866       CWORD,   CCTL,    CWORD,   CWORD,
867       CWORD,   CWORD,   CWORD,   CWORD,
868       CWORD,   CWORD,   CWORD,   CWORD,
869       CWORD,   CWORD,   CWORD,   CWORD,
870       CWORD,   CWORD,   CWORD,   CWORD,
871       CWORD,   CWORD,   CWORD,   CWORD,
872       CWORD,   CWORD,   CWORD,   CWORD,
873       CWORD,   CCTL,    CCTL,    CCTL,
874       CWORD,   CWORD,   CWORD,   CWORD,
875       CWORD,   CWORD,   CWORD,   CWORD,
876       CWORD,   CWORD,   CWORD,   CWORD,
877       CWORD,   CWORD,   CWORD,   CWORD,
878       CWORD,   CWORD,   CWORD,   CWORD,
879       CWORD,   CWORD,   CWORD,   CWORD,
880       CWORD,   CWORD,   CWORD,   CWORD,
881       CWORD,   CWORD,   CWORD,   CWORD,
882       CCTL
883 };
884
885 /* syntax table used when in arithmetic */
886 static const char arisyntax[257] = {
887       CENDFILE,   CIGN,    CWORD,   CCTL,
888       CCTL,    CCTL,    CCTL,    CCTL,
889       CCTL,    CCTL,    CCTL,    CWORD,
890       CWORD,   CWORD,   CWORD,   CWORD,
891       CWORD,   CWORD,   CWORD,   CWORD,
892       CWORD,   CWORD,   CWORD,   CWORD,
893       CWORD,   CWORD,   CWORD,   CWORD,
894       CWORD,   CWORD,   CWORD,   CWORD,
895       CWORD,   CWORD,   CWORD,   CWORD,
896       CWORD,   CWORD,   CWORD,   CWORD,
897       CWORD,   CWORD,   CWORD,   CWORD,
898       CWORD,   CWORD,   CWORD,   CWORD,
899       CWORD,   CWORD,   CWORD,   CWORD,
900       CWORD,   CWORD,   CWORD,   CWORD,
901       CWORD,   CWORD,   CWORD,   CWORD,
902       CWORD,   CWORD,   CWORD,   CWORD,
903       CWORD,   CWORD,   CWORD,   CWORD,
904       CWORD,   CWORD,   CWORD,   CWORD,
905       CWORD,   CWORD,   CWORD,   CWORD,
906       CWORD,   CWORD,   CWORD,   CWORD,
907       CWORD,   CWORD,   CWORD,   CWORD,
908       CWORD,   CWORD,   CWORD,   CWORD,
909       CWORD,   CWORD,   CWORD,   CWORD,
910       CWORD,   CWORD,   CWORD,   CWORD,
911       CWORD,   CWORD,   CWORD,   CWORD,
912       CWORD,   CWORD,   CWORD,   CWORD,
913       CWORD,   CWORD,   CWORD,   CWORD,
914       CWORD,   CWORD,   CWORD,   CWORD,
915       CWORD,   CWORD,   CWORD,   CWORD,
916       CWORD,   CWORD,   CWORD,   CWORD,
917       CWORD,   CWORD,   CWORD,   CWORD,
918       CWORD,   CWORD,   CWORD,   CWORD,
919       CWORD,   CWORD,   CWORD,   CWORD,
920       CWORD,   CWORD,   CWORD,   CWORD,
921       CWORD,   CWORD,   CWORD,   CWORD,
922       CNL,     CWORD,   CWORD,   CWORD,
923       CWORD,   CWORD,   CWORD,   CWORD,
924       CWORD,   CWORD,   CWORD,   CWORD,
925       CWORD,   CWORD,   CWORD,   CWORD,
926       CWORD,   CWORD,   CWORD,   CWORD,
927       CWORD,   CWORD,   CWORD,   CWORD,
928       CDQUOTE, CWORD,   CVAR,    CWORD,
929       CWORD,   CSQUOTE, CLP,     CRP,
930       CWORD,   CWORD,   CWORD,   CWORD,
931       CWORD,   CWORD,   CWORD,   CWORD,
932       CWORD,   CWORD,   CWORD,   CWORD,
933       CWORD,   CWORD,   CWORD,   CWORD,
934       CWORD,   CWORD,   CWORD,   CWORD,
935       CWORD,   CWORD,   CWORD,   CWORD,
936       CWORD,   CWORD,   CWORD,   CWORD,
937       CWORD,   CWORD,   CWORD,   CWORD,
938       CWORD,   CWORD,   CWORD,   CWORD,
939       CWORD,   CWORD,   CWORD,   CWORD,
940       CWORD,   CWORD,   CWORD,   CWORD,
941       CWORD,   CWORD,   CWORD,   CWORD,
942       CWORD,   CWORD,   CBACK,   CWORD,
943       CWORD,   CWORD,   CBQUOTE, CWORD,
944       CWORD,   CWORD,   CWORD,   CWORD,
945       CWORD,   CWORD,   CWORD,   CWORD,
946       CWORD,   CWORD,   CWORD,   CWORD,
947       CWORD,   CWORD,   CWORD,   CWORD,
948       CWORD,   CWORD,   CWORD,   CWORD,
949       CWORD,   CWORD,   CWORD,   CWORD,
950       CWORD,   CWORD,   CWORD,   CENDVAR,
951       CWORD
952 };
953
954 /* character classification table */
955 static const char is_type[257] = {
956       0,       0,       0,       0,
957       0,       0,       0,       0,
958       0,       0,       0,       0,
959       0,       0,       0,       0,
960       0,       0,       0,       0,
961       0,       0,       0,       0,
962       0,       0,       0,       0,
963       0,       0,       0,       0,
964       0,       0,       0,       0,
965       0,       0,       0,       0,
966       0,       0,       0,       0,
967       0,       0,       0,       0,
968       0,       0,       0,       0,
969       0,       0,       0,       0,
970       0,       0,       0,       0,
971       0,       0,       0,       0,
972       0,       0,       0,       0,
973       0,       0,       0,       0,
974       0,       0,       0,       0,
975       0,       0,       0,       0,
976       0,       0,       0,       0,
977       0,       0,       0,       0,
978       0,       0,       0,       0,
979       0,       0,       0,       0,
980       0,       0,       0,       0,
981       0,       0,       0,       0,
982       0,       0,       0,       0,
983       0,       0,       0,       0,
984       0,       0,       0,       0,
985       0,       0,       0,       0,
986       0,       0,       0,       0,
987       0,       0,       0,       0,
988       0,       0,       0,       0,
989       0,       0,       0,       0,
990       0,       0,       0,       0,
991       0,       0,       0,       0,
992       0,       0,       0,       0,
993       0,       0,       0,       0,
994       0,       0,       0,       0,
995       0,       0,       0,       0,
996       0,       0,       0,       ISSPECL,
997       0,       ISSPECL, ISSPECL, 0,
998       0,       0,       0,       0,
999       ISSPECL, 0,       0,       ISSPECL,
1000       0,       0,       ISDIGIT, ISDIGIT,
1001       ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1002       ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1003       0,       0,       0,       0,
1004       0,       ISSPECL, ISSPECL, ISUPPER,
1005       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1006       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1007       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1008       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1009       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1010       ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1011       ISUPPER, 0,       0,       0,
1012       0,       ISUNDER, 0,       ISLOWER,
1013       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1014       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1015       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1016       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1017       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1018       ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1019       ISLOWER, 0,       0,       0,
1020       0
1021 };
1022
1023 /* Array indicating which tokens mark the end of a list */
1024 static const char tokendlist[] = {
1025         1,
1026         0,
1027         0,
1028         0,
1029         0,
1030         0,
1031         0,
1032         0,
1033         1,
1034         1,
1035         1,
1036         0,
1037         0,
1038         0,
1039         0,
1040         0,
1041         1,
1042         1,
1043         1,
1044         1,
1045         1,
1046         1,
1047         0,
1048         0,
1049         0,
1050         1,
1051         0,
1052         0,
1053         0,
1054         1,
1055 };
1056
1057 static const char *const tokname[] = {
1058         "end of file",
1059         "newline",
1060         "\";\"",
1061         "\"&\"",
1062         "\"&&\"",
1063         "\"||\"",
1064         "\"|\"",
1065         "\"(\"",
1066         "\")\"",
1067         "\";;\"",
1068         "\"`\"",
1069         "redirection",
1070         "word",
1071         "assignment",
1072         "\"!\"",
1073         "\"case\"",
1074         "\"do\"",
1075         "\"done\"",
1076         "\"elif\"",
1077         "\"else\"",
1078         "\"esac\"",
1079         "\"fi\"",
1080         "\"for\"",
1081         "\"if\"",
1082         "\"in\"",
1083         "\"then\"",
1084         "\"until\"",
1085         "\"while\"",
1086         "\"{\"",
1087         "\"}\"",
1088 };
1089
1090 #define KWDOFFSET 14
1091
1092 static const char *const parsekwd[] = {
1093         "!",
1094         "case",
1095         "do",
1096         "done",
1097         "elif",
1098         "else",
1099         "esac",
1100         "fi",
1101         "for",
1102         "if",
1103         "in",
1104         "then",
1105         "until",
1106         "while",
1107         "{",
1108         "}"
1109 };
1110
1111
1112 static int plinno = 1;          /* input line number */
1113
1114 static int parselleft;          /* copy of parsefile->lleft */
1115
1116 static struct parsefile basepf; /* top level input file */
1117 static char basebuf[BUFSIZ];    /* buffer for top level input file */
1118 static struct parsefile *parsefile = &basepf;  /* current input file */
1119
1120 /*
1121  * NEOF is returned by parsecmd when it encounters an end of file.  It
1122  * must be distinct from NULL, so we use the address of a variable that
1123  * happens to be handy.
1124  */
1125
1126 static int tokpushback;         /* last token pushed back */
1127 #define NEOF ((union node *)&tokpushback)
1128 static int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
1129
1130
1131 static void error (const char *, ...) __attribute__((__noreturn__));
1132 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1133 static void shellexec (char **, char **, const char *, int)
1134     __attribute__((noreturn));
1135 static void exitshell (int) __attribute__((noreturn));
1136
1137 static int  goodname(const char *);
1138 static void ignoresig (int);
1139 static void onsig (int);
1140 static void dotrap (void);
1141 static int  decode_signal (const char *, int);
1142
1143 static void shprocvar(void);
1144 static void deletefuncs(void);
1145 static void setparam (char **);
1146 static void freeparam (volatile struct shparam *);
1147
1148 /* reasons for skipping commands (see comment on breakcmd routine) */
1149 #define SKIPBREAK       1
1150 #define SKIPCONT        2
1151 #define SKIPFUNC        3
1152 #define SKIPFILE        4
1153
1154 /* values of cmdtype */
1155 #define CMDUNKNOWN -1           /* no entry in table for command */
1156 #define CMDNORMAL 0             /* command is an executable program */
1157 #define CMDBUILTIN 1            /* command is a shell builtin */
1158 #define CMDFUNCTION 2           /* command is a shell function */
1159
1160 #define DO_ERR  1               /* find_command prints errors */
1161 #define DO_ABS  2               /* find_command checks absolute paths */
1162 #define DO_NOFUN        4       /* find_command ignores functions */
1163 #define DO_BRUTE        8       /* find_command ignores hash table */
1164
1165 /*
1166  * Shell variables.
1167  */
1168
1169 /* flags */
1170 #define VEXPORT         0x01    /* variable is exported */
1171 #define VREADONLY       0x02    /* variable cannot be modified */
1172 #define VSTRFIXED       0x04    /* variable struct is staticly allocated */
1173 #define VTEXTFIXED      0x08    /* text is staticly allocated */
1174 #define VSTACK          0x10    /* text is allocated on the stack */
1175 #define VUNSET          0x20    /* the variable is not set */
1176 #define VNOFUNC         0x40    /* don't call the callback function */
1177
1178
1179 struct var {
1180         struct var *next;               /* next entry in hash list */
1181         int flags;                      /* flags are defined above */
1182         char *text;                     /* name=value */
1183         void (*func) (const char *);
1184                                         /* function to be called when  */
1185                                         /* the variable gets set/unset */
1186 };
1187
1188 struct localvar {
1189         struct localvar *next;          /* next local variable in list */
1190         struct var *vp;                 /* the variable that was made local */
1191         int flags;                      /* saved flags */
1192         char *text;                     /* saved text */
1193 };
1194
1195
1196 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
1197 #define rmescapes(p) _rmescapes((p), 0)
1198 static char *_rmescapes (char *, int);
1199 #else
1200 static void rmescapes (char *);
1201 #endif
1202
1203 static int  casematch (union node *, const char *);
1204 static void clearredir(void);
1205 static void popstring(void);
1206 static void readcmdfile (const char *);
1207
1208 static int number (const char *);
1209 static int is_number (const char *, int *num);
1210 static char *single_quote (const char *);
1211 static int nextopt (const char *);
1212
1213 static void redirect (union node *, int);
1214 static void popredir (void);
1215 static int dup_as_newfd (int, int);
1216
1217 static void changepath(const char *newval);
1218 static void getoptsreset(const char *value);
1219
1220
1221 static int parsenleft;                  /* copy of parsefile->nleft */
1222 static char *parsenextc;                /* copy of parsefile->nextc */
1223 static int rootpid;     /* pid of main shell */
1224 static int rootshell;   /* true if we aren't a child of the main shell */
1225
1226 static const char spcstr[] = " ";
1227 static const char snlfmt[] = "%s\n";
1228
1229 static int sstrnleft;
1230 static int herefd = -1;
1231
1232 static struct localvar *localvars;
1233
1234 static struct var vifs;
1235 static struct var vmail;
1236 static struct var vmpath;
1237 static struct var vpath;
1238 static struct var vps1;
1239 static struct var vps2;
1240 static struct var voptind;
1241 #ifdef BB_LOCALE_SUPPORT
1242 static struct var vlc_all;
1243 static struct var vlc_ctype;
1244 #endif
1245
1246 struct varinit {
1247         struct var *var;
1248         int flags;
1249         const char *text;
1250         void (*func) (const char *);
1251 };
1252
1253 static const char defpathvar[] =
1254         "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1255 #define defpath (defpathvar + 5)
1256
1257 #ifdef IFS_BROKEN
1258 static const char defifsvar[] = "IFS= \t\n";
1259 #define defifs (defifsvar + 4)
1260 #else
1261 static const char defifs[] = " \t\n";
1262 #endif
1263
1264 static const struct varinit varinit[] = {
1265 #ifdef IFS_BROKEN
1266         { &vifs,        VSTRFIXED|VTEXTFIXED,           defifsvar,
1267 #else
1268         { &vifs,        VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS=",
1269 #endif
1270           NULL },
1271         { &vmail,       VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL=",
1272           NULL },
1273         { &vmpath,      VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH=",
1274           NULL },
1275         { &vpath,       VSTRFIXED|VTEXTFIXED,           defpathvar,
1276           changepath },
1277         /*
1278          * vps1 depends on uid
1279          */
1280         { &vps2,        VSTRFIXED|VTEXTFIXED,           "PS2=> ",
1281           NULL },
1282         { &voptind,     VSTRFIXED|VTEXTFIXED,           "OPTIND=1",
1283           getoptsreset },
1284 #ifdef BB_LOCALE_SUPPORT
1285         { &vlc_all,     VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_ALL=",
1286           change_lc_all },
1287         { &vlc_ctype,   VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_CTYPE=",
1288           change_lc_ctype },
1289 #endif
1290         { NULL, 0,                              NULL,
1291           NULL }
1292 };
1293
1294 #define VTABSIZE 39
1295
1296 static struct var *vartab[VTABSIZE];
1297
1298 /*
1299  * The following macros access the values of the above variables.
1300  * They have to skip over the name.  They return the null string
1301  * for unset variables.
1302  */
1303
1304 #define ifsval()        (vifs.text + 4)
1305 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1306 #define mailval()       (vmail.text + 5)
1307 #define mpathval()      (vmpath.text + 9)
1308 #define pathval()       (vpath.text + 5)
1309 #define ps1val()        (vps1.text + 4)
1310 #define ps2val()        (vps2.text + 4)
1311 #define optindval()     (voptind.text + 7)
1312
1313 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1314
1315 static void initvar (void);
1316 static void setvar (const char *, const char *, int);
1317 static void setvareq (char *, int);
1318 static void listsetvar (struct strlist *);
1319 static char *lookupvar (const char *);
1320 static char *bltinlookup (const char *);
1321 static char **environment (void);
1322 static int showvarscmd (int, char **);
1323 static void mklocal (char *);
1324 static void poplocalvars (void);
1325 static int unsetvar (const char *);
1326 static int varequal (const char *, const char *);
1327
1328
1329 static char *arg0;                      /* value of $0 */
1330 static struct shparam shellparam;       /* current positional parameters */
1331 static char **argptr;                   /* argument list for builtin commands */
1332 static char *optionarg;                 /* set by nextopt (like getopt) */
1333 static char *optptr;                    /* used by nextopt */
1334 static char *minusc;                    /* argument to -c option */
1335
1336
1337 #ifdef ASH_ALIAS
1338
1339 #define ALIASINUSE      1
1340 #define ALIASDEAD       2
1341
1342 #define ATABSIZE 39
1343
1344 struct alias {
1345         struct alias *next;
1346         char *name;
1347         char *val;
1348         int flag;
1349 };
1350
1351 static struct alias *atab[ATABSIZE];
1352
1353 static void setalias (char *, char *);
1354 static struct alias **hashalias (const char *);
1355 static struct alias *freealias (struct alias *);
1356 static struct alias **__lookupalias (const char *);
1357
1358 static void
1359 setalias(name, val)
1360         char *name, *val;
1361 {
1362         struct alias *ap, **app;
1363
1364         app = __lookupalias(name);
1365         ap = *app;
1366         INTOFF;
1367         if (ap) {
1368                 if (!(ap->flag & ALIASINUSE)) {
1369                         ckfree(ap->val);
1370                 }
1371                 ap->val = savestr(val);
1372                 ap->flag &= ~ALIASDEAD;
1373         } else {
1374                 /* not found */
1375                 ap = ckmalloc(sizeof (struct alias));
1376                 ap->name = savestr(name);
1377                 ap->val = savestr(val);
1378                 ap->flag = 0;
1379                 ap->next = 0;
1380                 *app = ap;
1381         }
1382         INTON;
1383 }
1384
1385 static int
1386 unalias(char *name)
1387 {
1388         struct alias **app;
1389
1390         app = __lookupalias(name);
1391
1392         if (*app) {
1393                 INTOFF;
1394                 *app = freealias(*app);
1395                 INTON;
1396                 return (0);
1397         }
1398
1399         return (1);
1400 }
1401
1402 static void
1403 rmaliases(void)
1404 {
1405         struct alias *ap, **app;
1406         int i;
1407
1408         INTOFF;
1409         for (i = 0; i < ATABSIZE; i++) {
1410                 app = &atab[i];
1411                 for (ap = *app; ap; ap = *app) {
1412                         *app = freealias(*app);
1413                         if (ap == *app) {
1414                                 app = &ap->next;
1415                         }
1416                 }
1417         }
1418         INTON;
1419 }
1420
1421 static struct alias *
1422 lookupalias(const char *name, int check)
1423 {
1424         struct alias *ap = *__lookupalias(name);
1425
1426         if (check && ap && (ap->flag & ALIASINUSE))
1427                 return (NULL);
1428         return (ap);
1429 }
1430
1431 static void
1432 printalias(const struct alias *ap) {
1433         char *p;
1434
1435         p = single_quote(ap->val);
1436         out1fmt("alias %s=%s\n", ap->name, p);
1437         stunalloc(p);
1438 }
1439
1440
1441 /*
1442  * TODO - sort output
1443  */
1444 static int
1445 aliascmd(int argc, char **argv)
1446 {
1447         char *n, *v;
1448         int ret = 0;
1449         struct alias *ap;
1450
1451         if (argc == 1) {
1452                 int i;
1453
1454                 for (i = 0; i < ATABSIZE; i++)
1455                         for (ap = atab[i]; ap; ap = ap->next) {
1456                                 printalias(ap);
1457                         }
1458                 return (0);
1459         }
1460         while ((n = *++argv) != NULL) {
1461                 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1462                         if ((ap = *__lookupalias(n)) == NULL) {
1463                                 out2fmt("%s: %s not found\n", "alias", n);
1464                                 ret = 1;
1465                         } else
1466                                 printalias(ap);
1467                 }
1468                 else {
1469                         *v++ = '\0';
1470                         setalias(n, v);
1471                 }
1472         }
1473
1474         return (ret);
1475 }
1476
1477 static int
1478 unaliascmd(int argc, char **argv)
1479 {
1480         int i;
1481
1482         while ((i = nextopt("a")) != '\0') {
1483                 if (i == 'a') {
1484                         rmaliases();
1485                         return (0);
1486                 }
1487         }
1488         for (i = 0; *argptr; argptr++) {
1489                 if (unalias(*argptr)) {
1490                         out2fmt("%s: %s not found\n", "unalias", *argptr);
1491                         i = 1;
1492                 }
1493         }
1494
1495         return (i);
1496 }
1497
1498 static struct alias **
1499 hashalias(p)
1500         const char *p;
1501         {
1502         unsigned int hashval;
1503
1504         hashval = *p << 4;
1505         while (*p)
1506                 hashval+= *p++;
1507         return &atab[hashval % ATABSIZE];
1508 }
1509
1510 static struct alias *
1511 freealias(struct alias *ap) {
1512         struct alias *next;
1513
1514         if (ap->flag & ALIASINUSE) {
1515                 ap->flag |= ALIASDEAD;
1516                 return ap;
1517         }
1518
1519         next = ap->next;
1520         ckfree(ap->name);
1521         ckfree(ap->val);
1522         ckfree(ap);
1523         return next;
1524 }
1525
1526
1527 static struct alias **
1528 __lookupalias(const char *name) {
1529         struct alias **app = hashalias(name);
1530
1531         for (; *app; app = &(*app)->next) {
1532                 if (equal(name, (*app)->name)) {
1533                         break;
1534                 }
1535         }
1536
1537         return app;
1538 }
1539 #endif
1540
1541 #ifdef ASH_MATH_SUPPORT
1542 /* The generated file arith.c has been snipped.  If you want this
1543  * stuff back in, feel free to add it to your own copy.  */
1544 #define ARITH_NUM 257
1545 #define ARITH_LPAREN 258
1546 #define ARITH_RPAREN 259
1547 #define ARITH_OR 260
1548 #define ARITH_AND 261
1549 #define ARITH_BOR 262
1550 #define ARITH_BXOR 263
1551 #define ARITH_BAND 264
1552 #define ARITH_EQ 265
1553 #define ARITH_NE 266
1554 #define ARITH_LT 267
1555 #define ARITH_GT 268
1556 #define ARITH_GE 269
1557 #define ARITH_LE 270
1558 #define ARITH_LSHIFT 271
1559 #define ARITH_RSHIFT 272
1560 #define ARITH_ADD 273
1561 #define ARITH_SUB 274
1562 #define ARITH_MUL 275
1563 #define ARITH_DIV 276
1564 #define ARITH_REM 277
1565 #define ARITH_UNARYMINUS 278
1566 #define ARITH_UNARYPLUS 279
1567 #define ARITH_NOT 280
1568 #define ARITH_BNOT 281
1569
1570 static void expari (int);
1571 /* From arith.y */
1572 static int arith (const char *);
1573 static int expcmd (int , char **);
1574 static void arith_lex_reset (void);
1575 static int yylex (void);
1576
1577 #endif
1578
1579 static char *trap[NSIG];                /* trap handler commands */
1580 static char sigmode[NSIG - 1];  /* current value of signal */
1581 static char gotsig[NSIG - 1];           /* indicates specified signal received */
1582 static int pendingsigs;                 /* indicates some signal received */
1583
1584 /*
1585  * This file was generated by the mkbuiltins program.
1586  */
1587
1588 #ifdef JOBS
1589 static int bgcmd (int, char **);
1590 static int fgcmd (int, char **);
1591 static int killcmd (int, char **);
1592 #endif
1593 static int bltincmd (int, char **);
1594 static int cdcmd (int, char **);
1595 static int breakcmd (int, char **);
1596 #ifdef ASH_CMDCMD
1597 static int commandcmd (int, char **);
1598 #endif
1599 static int dotcmd (int, char **);
1600 static int evalcmd (int, char **);
1601 static int execcmd (int, char **);
1602 static int exitcmd (int, char **);
1603 static int exportcmd (int, char **);
1604 static int histcmd (int, char **);
1605 static int hashcmd (int, char **);
1606 static int helpcmd (int, char **);
1607 static int jobscmd (int, char **);
1608 static int localcmd (int, char **);
1609 #ifndef BB_PWD
1610 static int pwdcmd (int, char **);
1611 #endif
1612 static int readcmd (int, char **);
1613 static int returncmd (int, char **);
1614 static int setcmd (int, char **);
1615 static int setvarcmd (int, char **);
1616 static int shiftcmd (int, char **);
1617 static int trapcmd (int, char **);
1618 static int umaskcmd (int, char **);
1619 #ifdef ASH_ALIAS
1620 static int aliascmd (int, char **);
1621 static int unaliascmd (int, char **);
1622 #endif
1623 static int unsetcmd (int, char **);
1624 static int waitcmd (int, char **);
1625 static int ulimitcmd (int, char **);
1626 static int timescmd (int, char **);
1627 #ifdef ASH_MATH_SUPPORT
1628 static int expcmd (int, char **);
1629 #endif
1630 #ifdef ASH_TYPE
1631 static int typecmd (int, char **);
1632 #endif
1633 #ifdef ASH_GETOPTS
1634 static int getoptscmd (int, char **);
1635 #endif
1636
1637 #ifndef BB_TRUE_FALSE
1638 # ifdef ASH_BBAPPS_AS_BUILTINS
1639 static int true_main (int, char **);
1640 static int false_main (int, char **);
1641 # endif
1642 #endif
1643
1644 static void     setpwd (const char *, int);
1645
1646
1647 #define BUILTIN_NOSPEC  "0"
1648 #define BUILTIN_SPECIAL "1"
1649 #define BUILTIN_REGULAR "2"
1650 #define BUILTIN_ASSIGN  "4"
1651 #define BUILTIN_SPEC_ASSG  "5"
1652 #define BUILTIN_REG_ASSG   "6"
1653
1654 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1655 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1656 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1657
1658 struct builtincmd {
1659         const char *name;
1660         int (*const builtinfunc) (int, char **);
1661         //unsigned flags;
1662 };
1663
1664
1665 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1666  * the binary search in find_builtin() will stop working. If you value
1667  * your kneecaps, you'll be sure to *make sure* that any changes made
1668  * to this array result in the listing remaining in ascii order. You
1669  * have been warned.
1670  */
1671 static const struct builtincmd builtincmds[] = {
1672         { BUILTIN_SPECIAL   ".", dotcmd },
1673         { BUILTIN_SPECIAL   ":", true_main },
1674 #ifdef ASH_ALIAS
1675         { BUILTIN_REG_ASSG  "alias", aliascmd },
1676 #endif
1677 #ifdef JOBS
1678         { BUILTIN_REGULAR   "bg", bgcmd },
1679 #endif
1680         { BUILTIN_SPECIAL   "break", breakcmd },
1681         { BUILTIN_SPECIAL   "builtin", bltincmd },
1682         { BUILTIN_REGULAR   "cd", cdcmd },
1683 #ifdef ASH_BBAPPS_AS_BUILTINS
1684         { BUILTIN_NOSPEC    "chdir", cdcmd },
1685 #endif
1686 #ifdef ASH_CMDCMD
1687         { BUILTIN_REGULAR   "command", commandcmd },
1688 #endif
1689         { BUILTIN_SPECIAL   "continue", breakcmd },
1690         { BUILTIN_SPECIAL   "eval", evalcmd },
1691         { BUILTIN_SPECIAL   "exec", execcmd },
1692         { BUILTIN_SPECIAL   "exit", exitcmd },
1693 #ifdef ASH_MATH_SUPPORT
1694         { BUILTIN_NOSPEC    "exp", expcmd },
1695 #endif
1696         { BUILTIN_SPEC_ASSG "export", exportcmd },
1697 #ifdef ASH_BBAPPS_AS_BUILTINS
1698         { BUILTIN_REGULAR   "false", false_main },
1699 #endif
1700         { BUILTIN_REGULAR   "fc", histcmd },
1701 #ifdef JOBS
1702         { BUILTIN_REGULAR   "fg", fgcmd },
1703 #endif
1704 #ifdef ASH_GETOPTS
1705         { BUILTIN_REGULAR   "getopts", getoptscmd },
1706 #endif
1707         { BUILTIN_NOSPEC    "hash", hashcmd },
1708         { BUILTIN_NOSPEC    "help", helpcmd },
1709         { BUILTIN_REGULAR   "jobs", jobscmd },
1710 #ifdef JOBS
1711         { BUILTIN_REGULAR   "kill", killcmd },
1712 #endif
1713 #ifdef ASH_MATH_SUPPORT
1714         { BUILTIN_NOSPEC    "let", expcmd },
1715 #endif
1716         { BUILTIN_ASSIGN    "local", localcmd },
1717 #ifndef BB_PWD
1718         { BUILTIN_NOSPEC    "pwd", pwdcmd },
1719 #endif
1720         { BUILTIN_REGULAR   "read", readcmd },
1721         { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1722         { BUILTIN_SPECIAL   "return", returncmd },
1723         { BUILTIN_SPECIAL   "set", setcmd },
1724         { BUILTIN_NOSPEC    "setvar", setvarcmd },
1725         { BUILTIN_SPECIAL   "shift", shiftcmd },
1726         { BUILTIN_SPECIAL   "times", timescmd },
1727         { BUILTIN_SPECIAL   "trap", trapcmd },
1728 #ifdef ASH_BBAPPS_AS_BUILTINS
1729         { BUILTIN_REGULAR   "true", true_main },
1730 #endif
1731 #ifdef ASH_TYPE
1732         { BUILTIN_NOSPEC    "type", typecmd },
1733 #endif
1734         { BUILTIN_NOSPEC    "ulimit", ulimitcmd },
1735         { BUILTIN_REGULAR   "umask", umaskcmd },
1736 #ifdef ASH_ALIAS
1737         { BUILTIN_REGULAR   "unalias", unaliascmd },
1738 #endif
1739         { BUILTIN_SPECIAL   "unset", unsetcmd },
1740         { BUILTIN_REGULAR   "wait", waitcmd },
1741 };
1742 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
1743
1744 static const struct builtincmd *DOTCMD = &builtincmds[0];
1745 static struct builtincmd *BLTINCMD;
1746 static struct builtincmd *EXECCMD;
1747 static struct builtincmd *EVALCMD;
1748
1749 /* states */
1750 #define JOBSTOPPED 1            /* all procs are stopped */
1751 #define JOBDONE 2               /* all procs are completed */
1752
1753 /*
1754  * A job structure contains information about a job.  A job is either a
1755  * single process or a set of processes contained in a pipeline.  In the
1756  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1757  * array of pids.
1758  */
1759
1760 struct procstat {
1761         pid_t pid;              /* process id */
1762         int status;             /* status flags (defined above) */
1763         char *cmd;              /* text of command being run */
1764 };
1765
1766
1767 static int job_warning;         /* user was warned about stopped jobs */
1768
1769 #ifdef JOBS
1770 static void setjobctl(int enable);
1771 #else
1772 #define setjobctl(on)   /* do nothing */
1773 #endif
1774
1775
1776 struct job {
1777         struct procstat ps0;    /* status of process */
1778         struct procstat *ps;    /* status or processes when more than one */
1779         short nprocs;           /* number of processes */
1780         short pgrp;             /* process group of this job */
1781         char state;             /* true if job is finished */
1782         char used;              /* true if this entry is in used */
1783         char changed;           /* true if status has changed */
1784 #ifdef JOBS
1785         char jobctl;            /* job running under job control */
1786 #endif
1787 };
1788
1789 static struct job *jobtab;      /* array of jobs */
1790 static int njobs;               /* size of array */
1791 static int backgndpid = -1;     /* pid of last background process */
1792 #ifdef JOBS
1793 static int initialpgrp;         /* pgrp of shell on invocation */
1794 static int curjob;              /* current job */
1795 static int jobctl;
1796 #endif
1797 static int intreceived;
1798
1799 static struct job *makejob (union node *, int);
1800 static int forkshell (struct job *, union node *, int);
1801 static int waitforjob (struct job *);
1802
1803 static int docd (char *, int);
1804 static char *getcomponent (void);
1805 static void updatepwd (const char *);
1806 static void getpwd (void);
1807
1808 static char *padvance (const char **, const char *);
1809
1810 static char nullstr[1];         /* zero length string */
1811 static char *curdir = nullstr;          /* current working directory */
1812 static char *cdcomppath;
1813
1814 static int
1815 cdcmd(argc, argv)
1816         int argc;
1817         char **argv;
1818 {
1819         const char *dest;
1820         const char *path;
1821         char *p;
1822         struct stat statb;
1823         int print = 0;
1824
1825         nextopt(nullstr);
1826         if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1827                 error("HOME not set");
1828         if (*dest == '\0')
1829                 dest = ".";
1830         if (dest[0] == '-' && dest[1] == '\0') {
1831                 dest = bltinlookup("OLDPWD");
1832                 if (!dest || !*dest) {
1833                         dest = curdir;
1834                 }
1835                 print = 1;
1836                 if (dest)
1837                         print = 1;
1838                 else
1839                         dest = ".";
1840         }
1841         if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1842                 path = nullstr;
1843         while ((p = padvance(&path, dest)) != NULL) {
1844                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1845                         if (!print) {
1846                                 /*
1847                                  * XXX - rethink
1848                                  */
1849                                 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1850                                         p += 2;
1851                                 print = strcmp(p, dest);
1852                         }
1853                         if (docd(p, print) >= 0)
1854                                 return 0;
1855
1856                 }
1857         }
1858         error("can't cd to %s", dest);
1859         /* NOTREACHED */
1860 }
1861
1862
1863 /*
1864  * Actually do the chdir.  In an interactive shell, print the
1865  * directory name if "print" is nonzero.
1866  */
1867
1868 static int
1869 docd(dest, print)
1870         char *dest;
1871         int print;
1872 {
1873         char *p;
1874         char *q;
1875         char *component;
1876         struct stat statb;
1877         int first;
1878         int badstat;
1879
1880         TRACE(("docd(\"%s\", %d) called\n", dest, print));
1881
1882         /*
1883          *  Check each component of the path. If we find a symlink or
1884          *  something we can't stat, clear curdir to force a getcwd()
1885          *  next time we get the value of the current directory.
1886          */
1887         badstat = 0;
1888         cdcomppath = sstrdup(dest);
1889         STARTSTACKSTR(p);
1890         if (*dest == '/') {
1891                 STPUTC('/', p);
1892                 cdcomppath++;
1893         }
1894         first = 1;
1895         while ((q = getcomponent()) != NULL) {
1896                 if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
1897                         continue;
1898                 if (! first)
1899                         STPUTC('/', p);
1900                 first = 0;
1901                 component = q;
1902                 while (*q)
1903                         STPUTC(*q++, p);
1904                 if (equal(component, ".."))
1905                         continue;
1906                 STACKSTRNUL(p);
1907                 if ((lstat(stackblock(), &statb) < 0)
1908                     || (S_ISLNK(statb.st_mode)))  {
1909                         /* print = 1; */
1910                         badstat = 1;
1911                         break;
1912                 }
1913         }
1914
1915         INTOFF;
1916         if (chdir(dest) < 0) {
1917                 INTON;
1918                 return -1;
1919         }
1920         updatepwd(badstat ? NULL : dest);
1921         INTON;
1922         if (print && iflag)
1923                 out1fmt(snlfmt, curdir);
1924         return 0;
1925 }
1926
1927
1928 /*
1929  * Get the next component of the path name pointed to by cdcomppath.
1930  * This routine overwrites the string pointed to by cdcomppath.
1931  */
1932
1933 static char *
1934 getcomponent() {
1935         char *p;
1936         char *start;
1937
1938         if ((p = cdcomppath) == NULL)
1939                 return NULL;
1940         start = cdcomppath;
1941         while (*p != '/' && *p != '\0')
1942                 p++;
1943         if (*p == '\0') {
1944                 cdcomppath = NULL;
1945         } else {
1946                 *p++ = '\0';
1947                 cdcomppath = p;
1948         }
1949         return start;
1950 }
1951
1952
1953
1954 /*
1955  * Update curdir (the name of the current directory) in response to a
1956  * cd command.  We also call hashcd to let the routines in exec.c know
1957  * that the current directory has changed.
1958  */
1959
1960 static void hashcd (void);
1961
1962 static void
1963 updatepwd(const char *dir)
1964 {
1965         char *new;
1966         char *p;
1967         size_t len;
1968
1969         hashcd();                               /* update command hash table */
1970
1971         /*
1972          * If our argument is NULL, we don't know the current directory
1973          * any more because we traversed a symbolic link or something
1974          * we couldn't stat().
1975          */
1976         if (dir == NULL || curdir == nullstr)  {
1977                 setpwd(0, 1);
1978                 return;
1979         }
1980         len = strlen(dir);
1981         cdcomppath = sstrdup(dir);
1982         STARTSTACKSTR(new);
1983         if (*dir != '/') {
1984                 p = curdir;
1985                 while (*p)
1986                         STPUTC(*p++, new);
1987                 if (p[-1] == '/')
1988                         STUNPUTC(new);
1989         }
1990         while ((p = getcomponent()) != NULL) {
1991                 if (equal(p, "..")) {
1992                         while (new > stackblock() && (STUNPUTC(new), *new) != '/');
1993                 } else if (*p != '\0' && ! equal(p, ".")) {
1994                         STPUTC('/', new);
1995                         while (*p)
1996                                 STPUTC(*p++, new);
1997                 }
1998         }
1999         if (new == stackblock())
2000                 STPUTC('/', new);
2001         STACKSTRNUL(new);
2002         setpwd(stackblock(), 1);
2003 }
2004
2005
2006 #ifndef BB_PWD
2007 static int
2008 pwdcmd(argc, argv)
2009         int argc;
2010         char **argv;
2011 {
2012         out1fmt(snlfmt, curdir);
2013         return 0;
2014 }
2015 #endif
2016
2017 /*
2018  * Find out what the current directory is. If we already know the current
2019  * directory, this routine returns immediately.
2020  */
2021 static void
2022 getpwd(void)
2023 {
2024         curdir = xgetcwd(0);
2025         if(curdir==0)
2026                 curdir = nullstr;
2027 }
2028
2029 static void
2030 setpwd(const char *val, int setold)
2031 {
2032         if (setold) {
2033                 setvar("OLDPWD", curdir, VEXPORT);
2034         }
2035         INTOFF;
2036         if (curdir != nullstr) {
2037                 free(curdir);
2038                 curdir = nullstr;
2039         }
2040         if (!val) {
2041                 getpwd();
2042         } else {
2043                 curdir = savestr(val);
2044         }
2045         INTON;
2046         setvar("PWD", curdir, VEXPORT);
2047 }
2048
2049 /*
2050  * Errors and exceptions.
2051  */
2052
2053 /*
2054  * Code to handle exceptions in C.
2055  */
2056
2057 /*
2058  * We enclose jmp_buf in a structure so that we can declare pointers to
2059  * jump locations.  The global variable handler contains the location to
2060  * jump to when an exception occurs, and the global variable exception
2061  * contains a code identifying the exeception.  To implement nested
2062  * exception handlers, the user should save the value of handler on entry
2063  * to an inner scope, set handler to point to a jmploc structure for the
2064  * inner scope, and restore handler on exit from the scope.
2065  */
2066
2067 struct jmploc {
2068         jmp_buf loc;
2069 };
2070
2071 /* exceptions */
2072 #define EXINT 0         /* SIGINT received */
2073 #define EXERROR 1       /* a generic error */
2074 #define EXSHELLPROC 2   /* execute a shell procedure */
2075 #define EXEXEC 3        /* command execution failed */
2076
2077 static struct jmploc *handler;
2078 static int exception;
2079
2080 static void exverror (int, const char *, va_list)
2081     __attribute__((__noreturn__));
2082
2083 /*
2084  * Called to raise an exception.  Since C doesn't include exceptions, we
2085  * just do a longjmp to the exception handler.  The type of exception is
2086  * stored in the global variable "exception".
2087  */
2088
2089 static void exraise (int) __attribute__((__noreturn__));
2090
2091 static void
2092 exraise(int e)
2093 {
2094 #ifdef DEBUG
2095         if (handler == NULL)
2096                 abort();
2097 #endif
2098         exception = e;
2099         longjmp(handler->loc, 1);
2100 }
2101
2102
2103 /*
2104  * Called from trap.c when a SIGINT is received.  (If the user specifies
2105  * that SIGINT is to be trapped or ignored using the trap builtin, then
2106  * this routine is not called.)  Suppressint is nonzero when interrupts
2107  * are held using the INTOFF macro.  The call to _exit is necessary because
2108  * there is a short period after a fork before the signal handlers are
2109  * set to the appropriate value for the child.  (The test for iflag is
2110  * just defensive programming.)
2111  */
2112
2113 static void
2114 onint(void) {
2115         sigset_t mysigset;
2116
2117         if (suppressint) {
2118                 intpending++;
2119                 return;
2120         }
2121         intpending = 0;
2122         sigemptyset(&mysigset);
2123         sigprocmask(SIG_SETMASK, &mysigset, NULL);
2124         if (rootshell && iflag)
2125                 exraise(EXINT);
2126         else {
2127                 signal(SIGINT, SIG_DFL);
2128                 raise(SIGINT);
2129         }
2130         /* NOTREACHED */
2131 }
2132
2133
2134 static char *commandname;       /* currently executing command */
2135
2136 /*
2137  * Exverror is called to raise the error exception.  If the first argument
2138  * is not NULL then error prints an error message using printf style
2139  * formatting.  It then raises the error exception.
2140  */
2141 static void
2142 exverror(int cond, const char *msg, va_list ap)
2143 {
2144         CLEAR_PENDING_INT;
2145         INTOFF;
2146
2147 #ifdef DEBUG
2148         if (msg)
2149                 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
2150         else
2151                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2152 #endif
2153         if (msg) {
2154                 if (commandname)
2155                         out2fmt("%s: ", commandname);
2156                 vfprintf(stderr, msg, ap);
2157                 out2c('\n');
2158         }
2159         flushall();
2160         exraise(cond);
2161         /* NOTREACHED */
2162 }
2163
2164
2165 #ifdef __STDC__
2166 static void
2167 error(const char *msg, ...)
2168 #else
2169 static void
2170 error(va_alist)
2171         va_dcl
2172 #endif
2173 {
2174 #ifndef __STDC__
2175         const char *msg;
2176 #endif
2177         va_list ap;
2178 #ifdef __STDC__
2179         va_start(ap, msg);
2180 #else
2181         va_start(ap);
2182         msg = va_arg(ap, const char *);
2183 #endif
2184         exverror(EXERROR, msg, ap);
2185         /* NOTREACHED */
2186         va_end(ap);
2187 }
2188
2189
2190 #ifdef __STDC__
2191 static void
2192 exerror(int cond, const char *msg, ...)
2193 #else
2194 static void
2195 exerror(va_alist)
2196         va_dcl
2197 #endif
2198 {
2199 #ifndef __STDC__
2200         int cond;
2201         const char *msg;
2202 #endif
2203         va_list ap;
2204 #ifdef __STDC__
2205         va_start(ap, msg);
2206 #else
2207         va_start(ap);
2208         cond = va_arg(ap, int);
2209         msg = va_arg(ap, const char *);
2210 #endif
2211         exverror(cond, msg, ap);
2212         /* NOTREACHED */
2213         va_end(ap);
2214 }
2215
2216
2217
2218 /*
2219  * Table of error messages.
2220  */
2221
2222 struct errname {
2223         short errcode;          /* error number */
2224         short action;           /* operation which encountered the error */
2225 };
2226
2227 /*
2228  * Types of operations (passed to the errmsg routine).
2229  */
2230
2231 #define E_OPEN 01       /* opening a file */
2232 #define E_CREAT 02      /* creating a file */
2233 #define E_EXEC 04       /* executing a program */
2234
2235 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2236
2237 static const struct errname errormsg[] = {
2238         { EINTR,        ALL     },
2239         { EACCES,       ALL     },
2240         { EIO,          ALL     },
2241         { ENOENT,       E_OPEN  },
2242         { ENOENT,       E_CREAT },
2243         { ENOENT,       E_EXEC  },
2244         { ENOTDIR,      E_OPEN  },
2245         { ENOTDIR,      E_CREAT },
2246         { ENOTDIR,      E_EXEC  },
2247         { EISDIR,       ALL     },
2248         { EEXIST,       E_CREAT },
2249 #ifdef EMFILE
2250         { EMFILE,       ALL     },
2251 #endif
2252         { ENFILE,       ALL     },
2253         { ENOSPC,       ALL     },
2254 #ifdef EDQUOT
2255         { EDQUOT,       ALL     },
2256 #endif
2257 #ifdef ENOSR
2258         { ENOSR,        ALL     },
2259 #endif
2260         { ENXIO,        ALL     },
2261         { EROFS,        ALL     },
2262         { ETXTBSY,      ALL     },
2263 #ifdef EAGAIN
2264         { EAGAIN,       E_EXEC  },
2265 #endif
2266         { ENOMEM,       ALL     },
2267 #ifdef ENOLINK
2268         { ENOLINK,      ALL     },
2269 #endif
2270 #ifdef EMULTIHOP
2271         { EMULTIHOP,    ALL     },
2272 #endif
2273 #ifdef ECOMM
2274         { ECOMM,        ALL     },
2275 #endif
2276 #ifdef ESTALE
2277         { ESTALE,       ALL     },
2278 #endif
2279 #ifdef ETIMEDOUT
2280         { ETIMEDOUT,    ALL     },
2281 #endif
2282 #ifdef ELOOP
2283         { ELOOP,        ALL     },
2284 #endif
2285         { E2BIG,        E_EXEC  },
2286 #ifdef ELIBACC
2287         { ELIBACC,      E_EXEC  },
2288 #endif
2289 };
2290
2291 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2292
2293 /*
2294  * Return a string describing an error.  The returned string may be a
2295  * pointer to a static buffer that will be overwritten on the next call.
2296  * Action describes the operation that got the error.
2297  */
2298
2299 static const char *
2300 errmsg(int e, int action)
2301 {
2302         struct errname const *ep;
2303         static char buf[12];
2304
2305         for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2306                 if (ep->errcode == e && (ep->action & action) != 0)
2307                         return strerror(e);
2308         }
2309
2310         snprintf(buf, sizeof buf, "error %d", e);
2311         return buf;
2312 }
2313
2314
2315 #ifdef ASH_OPTIMIZE_FOR_SIZE
2316 static void
2317 __inton() {
2318         if (--suppressint == 0 && intpending) {
2319                 onint();
2320         }
2321 }
2322 static void forceinton (void) {
2323         suppressint = 0;
2324         if (intpending)
2325                 onint();
2326 }
2327 #endif
2328
2329 /* flags in argument to evaltree */
2330 #define EV_EXIT 01              /* exit after evaluating tree */
2331 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
2332 #define EV_BACKCMD 04           /* command executing within back quotes */
2333
2334 static int evalskip;                    /* set if we are skipping commands */
2335 static int skipcount;           /* number of levels to skip */
2336 static int loopnest;            /* current loop nesting level */
2337 static int funcnest;                    /* depth of function calls */
2338
2339
2340
2341 static struct strlist *cmdenviron;      /* environment for builtin command */
2342 static int exitstatus;                  /* exit status of last command */
2343 static int oexitstatus;         /* saved exit status */
2344
2345
2346 static void evalloop (union node *, int);
2347 static void evalfor (union node *, int);
2348 static void evalcase (union node *, int);
2349 static void evalsubshell (union node *, int);
2350 static void expredir (union node *);
2351 static void evalpipe (union node *);
2352 static void evalcommand (union node *, int);
2353 static void prehash (union node *);
2354 static void eprintlist (struct strlist *);
2355
2356 static union node *parsecmd(int);
2357 /*
2358  * Called to reset things after an exception.
2359  */
2360
2361 /*
2362  * The eval commmand.
2363  */
2364 static void evalstring (char *, int);
2365
2366 static int
2367 evalcmd(argc, argv)
2368         int argc;
2369         char **argv;
2370 {
2371         char *p;
2372         char *concat;
2373         char **ap;
2374
2375         if (argc > 1) {
2376                 p = argv[1];
2377                 if (argc > 2) {
2378                         STARTSTACKSTR(concat);
2379                         ap = argv + 2;
2380                         for (;;) {
2381                                 while (*p)
2382                                         STPUTC(*p++, concat);
2383                                 if ((p = *ap++) == NULL)
2384                                         break;
2385                                 STPUTC(' ', concat);
2386                         }
2387                         STPUTC('\0', concat);
2388                         p = grabstackstr(concat);
2389                 }
2390                 evalstring(p, EV_TESTED);
2391         }
2392         return exitstatus;
2393 }
2394
2395 /*
2396  * Execute a command or commands contained in a string.
2397  */
2398
2399 static void evaltree (union node *, int);
2400 static void setinputstring (char *);
2401 static void popfile (void);
2402 static void setstackmark(struct stackmark *mark);
2403 static void popstackmark(struct stackmark *mark);
2404
2405
2406 static void
2407 evalstring(char *s, int flag)
2408 {
2409         union node *n;
2410         struct stackmark smark;
2411
2412         setstackmark(&smark);
2413         setinputstring(s);
2414         while ((n = parsecmd(0)) != NEOF) {
2415                 evaltree(n, flag);
2416                 popstackmark(&smark);
2417         }
2418         popfile();
2419         popstackmark(&smark);
2420 }
2421
2422 /*
2423  * Evaluate a parse tree.  The value is left in the global variable
2424  * exitstatus.
2425  */
2426 static struct builtincmd *find_builtin (const char *);
2427 static void defun (char *, union node *);
2428
2429 static void
2430 evaltree(n, flags)
2431         union node *n;
2432         int flags;
2433 {
2434         int checkexit = 0;
2435         if (n == NULL) {
2436                 TRACE(("evaltree(NULL) called\n"));
2437                 goto out;
2438         }
2439         TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2440         switch (n->type) {
2441         case NSEMI:
2442                 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2443                 if (evalskip)
2444                         goto out;
2445                 evaltree(n->nbinary.ch2, flags);
2446                 break;
2447         case NAND:
2448                 evaltree(n->nbinary.ch1, EV_TESTED);
2449                 if (evalskip || exitstatus != 0)
2450                         goto out;
2451                 evaltree(n->nbinary.ch2, flags);
2452                 break;
2453         case NOR:
2454                 evaltree(n->nbinary.ch1, EV_TESTED);
2455                 if (evalskip || exitstatus == 0)
2456                         goto out;
2457                 evaltree(n->nbinary.ch2, flags);
2458                 break;
2459         case NREDIR:
2460                 expredir(n->nredir.redirect);
2461                 redirect(n->nredir.redirect, REDIR_PUSH);
2462                 evaltree(n->nredir.n, flags);
2463                 popredir();
2464                 break;
2465         case NSUBSHELL:
2466                 evalsubshell(n, flags);
2467                 break;
2468         case NBACKGND:
2469                 evalsubshell(n, flags);
2470                 break;
2471         case NIF: {
2472                 evaltree(n->nif.test, EV_TESTED);
2473                 if (evalskip)
2474                         goto out;
2475                 if (exitstatus == 0)
2476                         evaltree(n->nif.ifpart, flags);
2477                 else if (n->nif.elsepart)
2478                         evaltree(n->nif.elsepart, flags);
2479                 else
2480                         exitstatus = 0;
2481                 break;
2482         }
2483         case NWHILE:
2484         case NUNTIL:
2485                 evalloop(n, flags);
2486                 break;
2487         case NFOR:
2488                 evalfor(n, flags);
2489                 break;
2490         case NCASE:
2491                 evalcase(n, flags);
2492                 break;
2493         case NDEFUN: {
2494                 struct builtincmd *bcmd;
2495                 if (
2496                         (bcmd = find_builtin(n->narg.text)) &&
2497                         IS_BUILTIN_SPECIAL(bcmd)
2498                 ) {
2499                         out2fmt("%s is a special built-in\n", n->narg.text);
2500                         exitstatus = 1;
2501                         break;
2502                 }
2503                 defun(n->narg.text, n->narg.next);
2504                 exitstatus = 0;
2505                 break;
2506         }
2507         case NNOT:
2508                 evaltree(n->nnot.com, EV_TESTED);
2509                 exitstatus = !exitstatus;
2510                 break;
2511
2512         case NPIPE:
2513                 evalpipe(n);
2514                 checkexit = 1;
2515                 break;
2516         case NCMD:
2517                 evalcommand(n, flags);
2518                 checkexit = 1;
2519                 break;
2520 #ifdef DEBUG
2521         default:
2522                 out1fmt("Node type = %d\n", n->type);
2523                 break;
2524 #endif
2525         }
2526 out:
2527         if (pendingsigs)
2528                 dotrap();
2529         if (
2530                 flags & EV_EXIT ||
2531                 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2532         )
2533                 exitshell(exitstatus);
2534 }
2535
2536
2537 static void
2538 evalloop(n, flags)
2539         union node *n;
2540         int flags;
2541 {
2542         int status;
2543
2544         loopnest++;
2545         status = 0;
2546         for (;;) {
2547                 evaltree(n->nbinary.ch1, EV_TESTED);
2548                 if (evalskip) {
2549 skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
2550                                 evalskip = 0;
2551                                 continue;
2552                         }
2553                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2554                                 evalskip = 0;
2555                         break;
2556                 }
2557                 if (n->type == NWHILE) {
2558                         if (exitstatus != 0)
2559                                 break;
2560                 } else {
2561                         if (exitstatus == 0)
2562                                 break;
2563                 }
2564                 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2565                 status = exitstatus;
2566                 if (evalskip)
2567                         goto skipping;
2568         }
2569         loopnest--;
2570         exitstatus = status;
2571 }
2572
2573 static void expandarg (union node *, struct arglist *, int);
2574 static void fixredir(union node *n, const char *text, int err);
2575
2576 static void
2577 evalfor(n, flags)
2578     union node *n;
2579     int flags;
2580 {
2581         struct arglist arglist;
2582         union node *argp;
2583         struct strlist *sp;
2584         struct stackmark smark;
2585
2586         setstackmark(&smark);
2587         arglist.lastp = &arglist.list;
2588         for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2589                 oexitstatus = exitstatus;
2590                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2591                 if (evalskip)
2592                         goto out;
2593         }
2594         *arglist.lastp = NULL;
2595
2596         exitstatus = 0;
2597         loopnest++;
2598         for (sp = arglist.list ; sp ; sp = sp->next) {
2599                 setvar(n->nfor.var, sp->text, 0);
2600                 evaltree(n->nfor.body, flags & EV_TESTED);
2601                 if (evalskip) {
2602                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2603                                 evalskip = 0;
2604                                 continue;
2605                         }
2606                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2607                                 evalskip = 0;
2608                         break;
2609                 }
2610         }
2611         loopnest--;
2612 out:
2613         popstackmark(&smark);
2614 }
2615
2616
2617 static void
2618 evalcase(n, flags)
2619         union node *n;
2620         int flags;
2621 {
2622         union node *cp;
2623         union node *patp;
2624         struct arglist arglist;
2625         struct stackmark smark;
2626
2627         setstackmark(&smark);
2628         arglist.lastp = &arglist.list;
2629         oexitstatus = exitstatus;
2630         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2631         for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2632                 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2633                         if (casematch(patp, arglist.list->text)) {
2634                                 if (evalskip == 0) {
2635                                         evaltree(cp->nclist.body, flags);
2636                                 }
2637                                 goto out;
2638                         }
2639                 }
2640         }
2641 out:
2642         popstackmark(&smark);
2643 }
2644
2645 /*
2646  * Kick off a subshell to evaluate a tree.
2647  */
2648
2649 static void
2650 evalsubshell(n, flags)
2651         union node *n;
2652         int flags;
2653 {
2654         struct job *jp;
2655         int backgnd = (n->type == NBACKGND);
2656
2657         expredir(n->nredir.redirect);
2658         jp = makejob(n, 1);
2659         if (forkshell(jp, n, backgnd) == 0) {
2660                 if (backgnd)
2661                         flags &=~ EV_TESTED;
2662                 redirect(n->nredir.redirect, 0);
2663                 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2664         }
2665         if (! backgnd) {
2666                 INTOFF;
2667                 exitstatus = waitforjob(jp);
2668                 INTON;
2669         }
2670 }
2671
2672
2673 /*
2674  * Compute the names of the files in a redirection list.
2675  */
2676
2677 static void
2678 expredir(n)
2679         union node *n;
2680 {
2681         union node *redir;
2682
2683         for (redir = n ; redir ; redir = redir->nfile.next) {
2684                 struct arglist fn;
2685                 fn.lastp = &fn.list;
2686                 oexitstatus = exitstatus;
2687                 switch (redir->type) {
2688                 case NFROMTO:
2689                 case NFROM:
2690                 case NTO:
2691                 case NAPPEND:
2692                 case NTOOV:
2693                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2694                         redir->nfile.expfname = fn.list->text;
2695                         break;
2696                 case NFROMFD:
2697                 case NTOFD:
2698                         if (redir->ndup.vname) {
2699                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2700                                 fixredir(redir, fn.list->text, 1);
2701                         }
2702                         break;
2703                 }
2704         }
2705 }
2706
2707 /*
2708  * Evaluate a pipeline.  All the processes in the pipeline are children
2709  * of the process creating the pipeline.  (This differs from some versions
2710  * of the shell, which make the last process in a pipeline the parent
2711  * of all the rest.)
2712  */
2713
2714 static void
2715 evalpipe(n)
2716         union node *n;
2717 {
2718         struct job *jp;
2719         struct nodelist *lp;
2720         int pipelen;
2721         int prevfd;
2722         int pip[2];
2723
2724         TRACE(("evalpipe(0x%lx) called\n", (long)n));
2725         pipelen = 0;
2726         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2727                 pipelen++;
2728         INTOFF;
2729         jp = makejob(n, pipelen);
2730         prevfd = -1;
2731         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2732                 prehash(lp->n);
2733                 pip[1] = -1;
2734                 if (lp->next) {
2735                         if (pipe(pip) < 0) {
2736                                 close(prevfd);
2737                                 error("Pipe call failed");
2738                         }
2739                 }
2740                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2741                         INTON;
2742                         if (prevfd > 0) {
2743                                 close(0);
2744                                 dup_as_newfd(prevfd, 0);
2745                                 close(prevfd);
2746                                 if (pip[0] == 0) {
2747                                         pip[0] = -1;
2748                                 }
2749                         }
2750                         if (pip[1] >= 0) {
2751                                 if (pip[0] >= 0) {
2752                                         close(pip[0]);
2753                                 }
2754                                 if (pip[1] != 1) {
2755                                         close(1);
2756                                         dup_as_newfd(pip[1], 1);
2757                                         close(pip[1]);
2758                                 }
2759                         }
2760                         evaltree(lp->n, EV_EXIT);
2761                 }
2762                 if (prevfd >= 0)
2763                         close(prevfd);
2764                 prevfd = pip[0];
2765                 close(pip[1]);
2766         }
2767         INTON;
2768         if (n->npipe.backgnd == 0) {
2769                 INTOFF;
2770                 exitstatus = waitforjob(jp);
2771                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
2772                 INTON;
2773         }
2774 }
2775
2776
2777
2778 /*
2779  * Execute a command inside back quotes.  If it's a builtin command, we
2780  * want to save its output in a block obtained from malloc.  Otherwise
2781  * we fork off a subprocess and get the output of the command via a pipe.
2782  * Should be called with interrupts off.
2783  */
2784
2785 static void
2786 evalbackcmd(union node *n, struct backcmd *result)
2787 {
2788         int pip[2];
2789         struct job *jp;
2790         struct stackmark smark;         /* unnecessary */
2791
2792         setstackmark(&smark);
2793         result->fd = -1;
2794         result->buf = NULL;
2795         result->nleft = 0;
2796         result->jp = NULL;
2797         if (n == NULL) {
2798                 exitstatus = 0;
2799                 goto out;
2800         }
2801         exitstatus = 0;
2802         if (pipe(pip) < 0)
2803                 error("Pipe call failed");
2804         jp = makejob(n, 1);
2805         if (forkshell(jp, n, FORK_NOJOB) == 0) {
2806                 FORCEINTON;
2807                 close(pip[0]);
2808                 if (pip[1] != 1) {
2809                         close(1);
2810                         dup_as_newfd(pip[1], 1);
2811                         close(pip[1]);
2812                 }
2813                 eflag = 0;
2814                 evaltree(n, EV_EXIT);
2815         }
2816         close(pip[1]);
2817         result->fd = pip[0];
2818         result->jp = jp;
2819 out:
2820         popstackmark(&smark);
2821         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2822                 result->fd, result->buf, result->nleft, result->jp));
2823 }
2824
2825
2826
2827 /*
2828  * Execute a simple command.
2829  */
2830
2831 static void find_command (const char *, struct cmdentry *, int, const char *);
2832
2833 static int
2834 isassignment(const char *word) {
2835         if (!is_name(*word)) {
2836                 return 0;
2837         }
2838         do {
2839                 word++;
2840         } while (is_in_name(*word));
2841         return *word == '=';
2842 }
2843
2844 static void
2845 evalcommand(union node *cmd, int flags)
2846 {
2847         struct stackmark smark;
2848         union node *argp;
2849         struct arglist arglist;
2850         struct arglist varlist;
2851         char **argv;
2852         int argc;
2853         char **envp;
2854         struct strlist *sp;
2855         int mode;
2856         struct cmdentry cmdentry;
2857         struct job *jp;
2858         char *volatile savecmdname;
2859         volatile struct shparam saveparam;
2860         struct localvar *volatile savelocalvars;
2861         volatile int e;
2862         char *lastarg;
2863         const char *path;
2864         const struct builtincmd *firstbltin;
2865         struct jmploc *volatile savehandler;
2866         struct jmploc jmploc;
2867 #if __GNUC__
2868         /* Avoid longjmp clobbering */
2869         (void) &argv;
2870         (void) &argc;
2871         (void) &lastarg;
2872         (void) &flags;
2873 #endif
2874
2875         /* First expand the arguments. */
2876         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2877         setstackmark(&smark);
2878         arglist.lastp = &arglist.list;
2879         varlist.lastp = &varlist.list;
2880         arglist.list = 0;
2881         oexitstatus = exitstatus;
2882         exitstatus = 0;
2883         path = pathval();
2884         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2885                 expandarg(argp, &varlist, EXP_VARTILDE);
2886         }
2887         for (
2888                 argp = cmd->ncmd.args; argp && !arglist.list;
2889                 argp = argp->narg.next
2890         ) {
2891                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2892         }
2893         if (argp) {
2894                 struct builtincmd *bcmd;
2895                 bool pseudovarflag;
2896                 bcmd = find_builtin(arglist.list->text);
2897                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2898                 for (; argp; argp = argp->narg.next) {
2899                         if (pseudovarflag && isassignment(argp->narg.text)) {
2900                                 expandarg(argp, &arglist, EXP_VARTILDE);
2901                                 continue;
2902                         }
2903                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2904                 }
2905         }
2906         *arglist.lastp = NULL;
2907         *varlist.lastp = NULL;
2908         expredir(cmd->ncmd.redirect);
2909         argc = 0;
2910         for (sp = arglist.list ; sp ; sp = sp->next)
2911                 argc++;
2912         argv = stalloc(sizeof (char *) * (argc + 1));
2913
2914         for (sp = arglist.list ; sp ; sp = sp->next) {
2915                 TRACE(("evalcommand arg: %s\n", sp->text));
2916                 *argv++ = sp->text;
2917         }
2918         *argv = NULL;
2919         lastarg = NULL;
2920         if (iflag && funcnest == 0 && argc > 0)
2921                 lastarg = argv[-1];
2922         argv -= argc;
2923
2924         /* Print the command if xflag is set. */
2925         if (xflag) {
2926                 out2c('+');
2927                 eprintlist(varlist.list);
2928                 eprintlist(arglist.list);
2929                 out2c('\n');
2930         }
2931
2932         /* Now locate the command. */
2933         if (argc == 0) {
2934                 cmdentry.cmdtype = CMDBUILTIN;
2935                 firstbltin = cmdentry.u.cmd = BLTINCMD;
2936         } else {
2937                 const char *oldpath;
2938                 int findflag = DO_ERR;
2939                 int oldfindflag;
2940
2941                 /*
2942                  * Modify the command lookup path, if a PATH= assignment
2943                  * is present
2944                  */
2945                 for (sp = varlist.list ; sp ; sp = sp->next)
2946                         if (varequal(sp->text, defpathvar)) {
2947                                 path = sp->text + 5;
2948                                 findflag |= DO_BRUTE;
2949                         }
2950                 oldpath = path;
2951                 oldfindflag = findflag;
2952                 firstbltin = 0;
2953                 for(;;) {
2954                         find_command(argv[0], &cmdentry, findflag, path);
2955                         if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
2956                                 exitstatus = 127;
2957                                 goto out;
2958                         }
2959                         /* implement bltin and command here */
2960                         if (cmdentry.cmdtype != CMDBUILTIN) {
2961                                 break;
2962                         }
2963                         if (!firstbltin) {
2964                                 firstbltin = cmdentry.u.cmd;
2965                         }
2966                         if (cmdentry.u.cmd == BLTINCMD) {
2967                                 for(;;) {
2968                                         struct builtincmd *bcmd;
2969
2970                                         argv++;
2971                                         if (--argc == 0)
2972                                                 goto found;
2973                                         if (!(bcmd = find_builtin(*argv))) {
2974                                                 out2fmt("%s: not found\n", *argv);
2975                                                 exitstatus = 127;
2976                                                 goto out;
2977                                         }
2978                                         cmdentry.u.cmd = bcmd;
2979                                         if (bcmd != BLTINCMD)
2980                                                 break;
2981                                 }
2982                         }
2983                         if (cmdentry.u.cmd == find_builtin("command")) {
2984                                 argv++;
2985                                 if (--argc == 0) {
2986                                         goto found;
2987                                 }
2988                                 if (*argv[0] == '-') {
2989                                         if (!equal(argv[0], "-p")) {
2990                                                 argv--;
2991                                                 argc++;
2992                                                 break;
2993                                         }
2994                                         argv++;
2995                                         if (--argc == 0) {
2996                                                 goto found;
2997                                         }
2998                                         path = defpath;
2999                                         findflag |= DO_BRUTE;
3000                                 } else {
3001                                         path = oldpath;
3002                                         findflag = oldfindflag;
3003                                 }
3004                                 findflag |= DO_NOFUN;
3005                                 continue;
3006                         }
3007 found:
3008                         break;
3009                 }
3010         }
3011
3012         /* Fork off a child process if necessary. */
3013         if (cmd->ncmd.backgnd
3014          || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
3015         ) {
3016                 jp = makejob(cmd, 1);
3017                 mode = cmd->ncmd.backgnd;
3018                 if (forkshell(jp, cmd, mode) != 0)
3019                         goto parent;    /* at end of routine */
3020                 flags |= EV_EXIT;
3021         }
3022
3023         /* This is the child process if a fork occurred. */
3024         /* Execute the command. */
3025         if (cmdentry.cmdtype == CMDFUNCTION) {
3026 #ifdef DEBUG
3027                 trputs("Shell function:  ");  trargs(argv);
3028 #endif
3029                 exitstatus = oexitstatus;
3030                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
3031                 saveparam = shellparam;
3032                 shellparam.malloc = 0;
3033                 shellparam.nparam = argc - 1;
3034                 shellparam.p = argv + 1;
3035                 INTOFF;
3036                 savelocalvars = localvars;
3037                 localvars = NULL;
3038                 INTON;
3039                 if (setjmp(jmploc.loc)) {
3040                         if (exception == EXSHELLPROC) {
3041                                 freeparam((volatile struct shparam *)
3042                                     &saveparam);
3043                         } else {
3044                                 saveparam.optind = shellparam.optind;
3045                                 saveparam.optoff = shellparam.optoff;
3046                                 freeparam(&shellparam);
3047                                 shellparam = saveparam;
3048                         }
3049                         poplocalvars();
3050                         localvars = savelocalvars;
3051                         handler = savehandler;
3052                         longjmp(handler->loc, 1);
3053                 }
3054                 savehandler = handler;
3055                 handler = &jmploc;
3056                 for (sp = varlist.list ; sp ; sp = sp->next)
3057                         mklocal(sp->text);
3058                 funcnest++;
3059                 evaltree(cmdentry.u.func, flags & EV_TESTED);
3060                 funcnest--;
3061                 INTOFF;
3062                 poplocalvars();
3063                 localvars = savelocalvars;
3064                 saveparam.optind = shellparam.optind;
3065                 saveparam.optoff = shellparam.optoff;
3066                 freeparam(&shellparam);
3067                 shellparam = saveparam;
3068                 handler = savehandler;
3069                 popredir();
3070                 INTON;
3071                 if (evalskip == SKIPFUNC) {
3072                         evalskip = 0;
3073                         skipcount = 0;
3074                 }
3075                 if (flags & EV_EXIT)
3076                         exitshell(exitstatus);
3077         } else if (cmdentry.cmdtype == CMDBUILTIN) {
3078 #ifdef DEBUG
3079                 trputs("builtin command:  ");  trargs(argv);
3080 #endif
3081                 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
3082                 redirect(cmd->ncmd.redirect, mode);
3083                 savecmdname = commandname;
3084                 if (IS_BUILTIN_SPECIAL(firstbltin)) {
3085                         listsetvar(varlist.list);
3086                 } else {
3087                         cmdenviron = varlist.list;
3088                 }
3089                 e = -1;
3090                 if (setjmp(jmploc.loc)) {
3091                         e = exception;
3092                         exitstatus = (e == EXINT)? SIGINT+128 : 2;
3093                         goto cmddone;
3094                 }
3095                 savehandler = handler;
3096                 handler = &jmploc;
3097                 commandname = argv[0];
3098                 argptr = argv + 1;
3099                 optptr = NULL;                  /* initialize nextopt */
3100                 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
3101                 flushall();
3102 cmddone:
3103                 cmdenviron = NULL;
3104                 if (e != EXSHELLPROC) {
3105                         commandname = savecmdname;
3106                         if (flags & EV_EXIT)
3107                                 exitshell(exitstatus);
3108                 }
3109                 handler = savehandler;
3110                 if (e != -1) {
3111                         if ((e != EXERROR && e != EXEXEC)
3112                            || cmdentry.u.cmd == BLTINCMD
3113                            || cmdentry.u.cmd == DOTCMD
3114                            || cmdentry.u.cmd == EVALCMD
3115                            || cmdentry.u.cmd == EXECCMD)
3116                                 exraise(e);
3117                         FORCEINTON;
3118                 }
3119                 if (cmdentry.u.cmd != EXECCMD)
3120                         popredir();
3121         } else {
3122 #ifdef DEBUG
3123                 trputs("normal command:  ");  trargs(argv);
3124 #endif
3125                 redirect(cmd->ncmd.redirect, 0);
3126                 clearredir();
3127                 for (sp = varlist.list ; sp ; sp = sp->next)
3128                         setvareq(sp->text, VEXPORT|VSTACK);
3129                 envp = environment();
3130                 shellexec(argv, envp, path, cmdentry.u.index);
3131         }
3132         goto out;
3133
3134 parent: /* parent process gets here (if we forked) */
3135         if (mode == 0) {        /* argument to fork */
3136                 INTOFF;
3137                 exitstatus = waitforjob(jp);
3138                 INTON;
3139         }
3140
3141 out:
3142         if (lastarg)
3143                 setvar("_", lastarg, 0);
3144         popstackmark(&smark);
3145 }
3146
3147
3148
3149 /*
3150  * Search for a command.  This is called before we fork so that the
3151  * location of the command will be available in the parent as well as
3152  * the child.  The check for "goodname" is an overly conservative
3153  * check that the name will not be subject to expansion.
3154  */
3155
3156 static void
3157 prehash(n)
3158         union node *n;
3159 {
3160         struct cmdentry entry;
3161
3162         if (n->type == NCMD && n->ncmd.args)
3163                 if (goodname(n->ncmd.args->narg.text))
3164                         find_command(n->ncmd.args->narg.text, &entry, 0,
3165                                      pathval());
3166 }
3167
3168
3169
3170 /*
3171  * Builtin commands.  Builtin commands whose functions are closely
3172  * tied to evaluation are implemented here.
3173  */
3174
3175 /*
3176  * No command given, or a bltin command with no arguments.  Set the
3177  * specified variables.
3178  */
3179
3180 int
3181 bltincmd(argc, argv)
3182         int argc;
3183         char **argv;
3184 {
3185         /*
3186          * Preserve exitstatus of a previous possible redirection
3187          * as POSIX mandates
3188          */
3189         return exitstatus;
3190 }
3191
3192
3193 /*
3194  * Handle break and continue commands.  Break, continue, and return are
3195  * all handled by setting the evalskip flag.  The evaluation routines
3196  * above all check this flag, and if it is set they start skipping
3197  * commands rather than executing them.  The variable skipcount is
3198  * the number of loops to break/continue, or the number of function
3199  * levels to return.  (The latter is always 1.)  It should probably
3200  * be an error to break out of more loops than exist, but it isn't
3201  * in the standard shell so we don't make it one here.
3202  */
3203
3204 static int
3205 breakcmd(argc, argv)
3206         int argc;
3207         char **argv;
3208 {
3209         int n = argc > 1 ? number(argv[1]) : 1;
3210
3211         if (n > loopnest)
3212                 n = loopnest;
3213         if (n > 0) {
3214                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3215                 skipcount = n;
3216         }
3217         return 0;
3218 }
3219
3220
3221 /*
3222  * The return command.
3223  */
3224
3225 static int
3226 returncmd(argc, argv)
3227         int argc;
3228         char **argv;
3229 {
3230         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3231
3232         if (funcnest) {
3233                 evalskip = SKIPFUNC;
3234                 skipcount = 1;
3235                 return ret;
3236         }
3237         else {
3238                 /* Do what ksh does; skip the rest of the file */
3239                 evalskip = SKIPFILE;
3240                 skipcount = 1;
3241                 return ret;
3242         }
3243 }
3244
3245
3246 #ifndef BB_TRUE_FALSE
3247 #ifdef ASH_BBAPPS_AS_BUILTINS
3248 static int
3249 false_main(argc, argv)
3250         int argc;
3251         char **argv;
3252 {
3253         return 1;
3254 }
3255
3256
3257 static int
3258 true_main(argc, argv)
3259         int argc;
3260         char **argv;
3261 {
3262         return 0;
3263 }
3264 #endif
3265 #endif
3266
3267 /*
3268  * Controls whether the shell is interactive or not.
3269  */
3270
3271 static void setsignal(int signo);
3272 static void chkmail(int silent);
3273
3274
3275 static void
3276 setinteractive(int on)
3277 {
3278         static int is_interactive;
3279         static int do_banner=0;
3280
3281         if (on == is_interactive)
3282                 return;
3283         setsignal(SIGINT);
3284         setsignal(SIGQUIT);
3285         setsignal(SIGTERM);
3286         chkmail(1);
3287         is_interactive = on;
3288         if (do_banner==0 && is_interactive) {
3289                 /* Looks like they want an interactive shell */
3290                 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3291                 printf( "Enter 'help' for a list of built-in commands.\n\n");
3292                 do_banner=1;
3293         }
3294 }
3295
3296 static void
3297 optschanged(void)
3298 {
3299         setinteractive(iflag);
3300         setjobctl(mflag);
3301 }
3302
3303
3304 static int
3305 execcmd(argc, argv)
3306         int argc;
3307         char **argv;
3308 {
3309         if (argc > 1) {
3310                 struct strlist *sp;
3311
3312                 iflag = 0;              /* exit on error */
3313                 mflag = 0;
3314                 optschanged();
3315                 for (sp = cmdenviron; sp ; sp = sp->next)
3316                         setvareq(sp->text, VEXPORT|VSTACK);
3317                 shellexec(argv + 1, environment(), pathval(), 0);
3318         }
3319         return 0;
3320 }
3321
3322 static void
3323 eprintlist(struct strlist *sp)
3324 {
3325         for (; sp; sp = sp->next) {
3326                 out2fmt(" %s",sp->text);
3327         }
3328 }
3329 /*
3330  * When commands are first encountered, they are entered in a hash table.
3331  * This ensures that a full path search will not have to be done for them
3332  * on each invocation.
3333  *
3334  * We should investigate converting to a linear search, even though that
3335  * would make the command name "hash" a misnomer.
3336  */
3337 #define CMDTABLESIZE 31         /* should be prime */
3338 #define ARB 1                   /* actual size determined at run time */
3339
3340
3341
3342 struct tblentry {
3343         struct tblentry *next;  /* next entry in hash chain */
3344         union param param;      /* definition of builtin function */
3345         short cmdtype;          /* index identifying command */
3346         char rehash;            /* if set, cd done since entry created */
3347         char cmdname[ARB];      /* name of command */
3348 };
3349
3350
3351 static struct tblentry *cmdtable[CMDTABLESIZE];
3352 static int builtinloc = -1;             /* index in path of %builtin, or -1 */
3353 static int exerrno = 0;                 /* Last exec error */
3354
3355
3356 static void tryexec (char *, char **, char **);
3357 static void printentry (struct tblentry *, int);
3358 static void clearcmdentry (int);
3359 static struct tblentry *cmdlookup (const char *, int);
3360 static void delete_cmd_entry (void);
3361 #ifdef ASH_TYPE
3362 static int describe_command (char *, int);
3363 #endif
3364 static int path_change (const char *, int *);
3365
3366
3367 /*
3368  * Exec a program.  Never returns.  If you change this routine, you may
3369  * have to change the find_command routine as well.
3370  */
3371
3372 static const char *pathopt;     /* set by padvance */
3373
3374 static void
3375 shellexec(argv, envp, path, idx)
3376         char **argv, **envp;
3377         const char *path;
3378         int idx;
3379 {
3380         char *cmdname;
3381         int e;
3382
3383         if (strchr(argv[0], '/') != NULL) {
3384                 tryexec(argv[0], argv, envp);
3385                 e = errno;
3386         } else {
3387                 e = ENOENT;
3388                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3389                         if (--idx < 0 && pathopt == NULL) {
3390                                 tryexec(cmdname, argv, envp);
3391                                 if (errno != ENOENT && errno != ENOTDIR)
3392                                         e = errno;
3393                         }
3394                         stunalloc(cmdname);
3395                 }
3396         }
3397
3398         /* Map to POSIX errors */
3399         switch (e) {
3400         case EACCES:
3401                 exerrno = 126;
3402                 break;
3403         case ENOENT:
3404                 exerrno = 127;
3405                 break;
3406         default:
3407                 exerrno = 2;
3408                 break;
3409         }
3410         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3411         /* NOTREACHED */
3412 }
3413
3414 /*
3415  * Clear traps on a fork.
3416  */
3417 static void
3418 clear_traps(void) {
3419         char **tp;
3420
3421         for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3422                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
3423                         INTOFF;
3424                         ckfree(*tp);
3425                         *tp = NULL;
3426                         if (tp != &trap[0])
3427                                 setsignal(tp - trap);
3428                         INTON;
3429                 }
3430         }
3431 }
3432
3433
3434 static void
3435 initshellproc(void) {
3436
3437 #ifdef ASH_ALIAS
3438       /* from alias.c: */
3439       {
3440               rmaliases();
3441       }
3442 #endif
3443       /* from eval.c: */
3444       {
3445               exitstatus = 0;
3446       }
3447
3448       /* from exec.c: */
3449       {
3450               deletefuncs();
3451       }
3452
3453       /* from jobs.c: */
3454       {
3455               backgndpid = -1;
3456 #ifdef JOBS
3457               jobctl = 0;
3458 #endif
3459       }
3460
3461       /* from options.c: */
3462       {
3463               int i;
3464
3465               for (i = 0; i < NOPTS; i++)
3466                       optent_val(i) = 0;
3467               optschanged();
3468
3469       }
3470
3471       /* from redir.c: */
3472       {
3473               clearredir();
3474       }
3475
3476       /* from trap.c: */
3477       {
3478               char *sm;
3479
3480               clear_traps();
3481               for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3482                       if (*sm == S_IGN)
3483                               *sm = S_HARD_IGN;
3484               }
3485       }
3486
3487       /* from var.c: */
3488       {
3489               shprocvar();
3490       }
3491 }
3492
3493 static int preadbuffer(void);
3494 static void pushfile (void);
3495 static int preadfd (void);
3496
3497 /*
3498  * Read a character from the script, returning PEOF on end of file.
3499  * Nul characters in the input are silently discarded.
3500  */
3501
3502 #ifndef ASH_OPTIMIZE_FOR_SIZE
3503 #define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3504 static int
3505 pgetc(void)
3506 {
3507         return pgetc_macro();
3508 }
3509 #else
3510 static int
3511 pgetc_macro(void)
3512 {
3513         return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3514 }
3515
3516 static inline int
3517 pgetc(void)
3518 {
3519         return pgetc_macro();
3520 }
3521 #endif
3522
3523
3524 /*
3525  * Undo the last call to pgetc.  Only one character may be pushed back.
3526  * PEOF may be pushed back.
3527  */
3528
3529 static void
3530 pungetc() {
3531         parsenleft++;
3532         parsenextc--;
3533 }
3534
3535
3536 static void
3537 popfile(void) {
3538         struct parsefile *pf = parsefile;
3539
3540         INTOFF;
3541         if (pf->fd >= 0)
3542                 close(pf->fd);
3543         if (pf->buf)
3544                 ckfree(pf->buf);
3545         while (pf->strpush)
3546                 popstring();
3547         parsefile = pf->prev;
3548         ckfree(pf);
3549         parsenleft = parsefile->nleft;
3550         parselleft = parsefile->lleft;
3551         parsenextc = parsefile->nextc;
3552         plinno = parsefile->linno;
3553         INTON;
3554 }
3555
3556
3557 /*
3558  * Return to top level.
3559  */
3560
3561 static void
3562 popallfiles(void) {
3563         while (parsefile != &basepf)
3564                 popfile();
3565 }
3566
3567 /*
3568  * Close the file(s) that the shell is reading commands from.  Called
3569  * after a fork is done.
3570  */
3571
3572 static void
3573 closescript() {
3574         popallfiles();
3575         if (parsefile->fd > 0) {
3576                 close(parsefile->fd);
3577                 parsefile->fd = 0;
3578         }
3579 }
3580
3581
3582 /*
3583  * Like setinputfile, but takes an open file descriptor.  Call this with
3584  * interrupts off.
3585  */
3586
3587 static void
3588 setinputfd(fd, push)
3589         int fd, push;
3590 {
3591         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3592         if (push) {
3593                 pushfile();
3594                 parsefile->buf = 0;
3595         } else {
3596                 closescript();
3597                 while (parsefile->strpush)
3598                         popstring();
3599         }
3600         parsefile->fd = fd;
3601         if (parsefile->buf == NULL)
3602                 parsefile->buf = ckmalloc(BUFSIZ);
3603         parselleft = parsenleft = 0;
3604         plinno = 1;
3605 }
3606
3607
3608 /*
3609  * Set the input to take input from a file.  If push is set, push the
3610  * old input onto the stack first.
3611  */
3612
3613 static void
3614 setinputfile(const char *fname, int push)
3615 {
3616         int fd;
3617         int myfileno2;
3618
3619         INTOFF;
3620         if ((fd = open(fname, O_RDONLY)) < 0)
3621                 error("Can't open %s", fname);
3622         if (fd < 10) {
3623                 myfileno2 = dup_as_newfd(fd, 10);
3624                 close(fd);
3625                 if (myfileno2 < 0)
3626                         error("Out of file descriptors");
3627                 fd = myfileno2;
3628         }
3629         setinputfd(fd, push);
3630         INTON;
3631 }
3632
3633
3634 static void
3635 tryexec(cmd, argv, envp)
3636         char *cmd;
3637         char **argv;
3638         char **envp;
3639         {
3640         int e;
3641
3642 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3643         char *name = cmd;
3644         char** argv_l=argv;
3645         int argc_l;
3646 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
3647         name = get_last_path_component(name);
3648 #endif
3649         argv_l=envp;
3650         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3651                 putenv(*argv_l);
3652         argv_l=argv;
3653         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
3654         optind = 1;
3655         run_applet_by_name(name, argc_l, argv);
3656 #endif
3657         execve(cmd, argv, envp);
3658         e = errno;
3659         if (e == ENOEXEC) {
3660                 INTOFF;
3661                 initshellproc();
3662                 setinputfile(cmd, 0);
3663                 commandname = arg0 = savestr(argv[0]);
3664                 setparam(argv + 1);
3665                 exraise(EXSHELLPROC);
3666         }
3667         errno = e;
3668 }
3669
3670 static char *commandtext (const union node *);
3671
3672 /*
3673  * Do a path search.  The variable path (passed by reference) should be
3674  * set to the start of the path before the first call; padvance will update
3675  * this value as it proceeds.  Successive calls to padvance will return
3676  * the possible path expansions in sequence.  If an option (indicated by
3677  * a percent sign) appears in the path entry then the global variable
3678  * pathopt will be set to point to it; otherwise pathopt will be set to
3679  * NULL.
3680  */
3681
3682 static const char *pathopt;
3683
3684 static void growstackblock(void);
3685
3686
3687 static char *
3688 padvance(const char **path, const char *name)
3689 {
3690         const char *p;
3691         char *q;
3692         const char *start;
3693         int len;
3694
3695         if (*path == NULL)
3696                 return NULL;
3697         start = *path;
3698         for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3699         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3700         while (stackblocksize() < len)
3701                 growstackblock();
3702         q = stackblock();
3703         if (p != start) {
3704                 memcpy(q, start, p - start);
3705                 q += p - start;
3706                 *q++ = '/';
3707         }
3708         strcpy(q, name);
3709         pathopt = NULL;
3710         if (*p == '%') {
3711                 pathopt = ++p;
3712                 while (*p && *p != ':')  p++;
3713         }
3714         if (*p == ':')
3715                 *path = p + 1;
3716         else
3717                 *path = NULL;
3718         return stalloc(len);
3719 }
3720
3721
3722
3723 /*** Command hashing code ***/
3724
3725
3726 static int
3727 hashcmd(argc, argv)
3728         int argc;
3729         char **argv;
3730 {
3731         struct tblentry **pp;
3732         struct tblentry *cmdp;
3733         int c;
3734         int verbose;
3735         struct cmdentry entry;
3736         char *name;
3737
3738         verbose = 0;
3739         while ((c = nextopt("rv")) != '\0') {
3740                 if (c == 'r') {
3741                         clearcmdentry(0);
3742                         return 0;
3743                 } else if (c == 'v') {
3744                         verbose++;
3745                 }
3746         }
3747         if (*argptr == NULL) {
3748                 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3749                         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3750                                 if (cmdp->cmdtype != CMDBUILTIN) {
3751                                         printentry(cmdp, verbose);
3752                                 }
3753                         }
3754                 }
3755                 return 0;
3756         }
3757         c = 0;
3758         while ((name = *argptr) != NULL) {
3759                 if ((cmdp = cmdlookup(name, 0)) != NULL
3760                  && (cmdp->cmdtype == CMDNORMAL
3761                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3762                         delete_cmd_entry();
3763                 find_command(name, &entry, DO_ERR, pathval());
3764                 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3765                 else if (verbose) {
3766                         cmdp = cmdlookup(name, 0);
3767                         if (cmdp) printentry(cmdp, verbose);
3768                         flushall();
3769                 }
3770                 argptr++;
3771         }
3772         return c;
3773 }
3774
3775
3776 static void
3777 printentry(cmdp, verbose)
3778         struct tblentry *cmdp;
3779         int verbose;
3780         {
3781         int idx;
3782         const char *path;
3783         char *name;
3784
3785         if (cmdp->cmdtype == CMDNORMAL) {
3786                 idx = cmdp->param.index;
3787                 path = pathval();
3788                 do {
3789                         name = padvance(&path, cmdp->cmdname);
3790                         stunalloc(name);
3791                 } while (--idx >= 0);
3792                 out1str(name);
3793         } else if (cmdp->cmdtype == CMDBUILTIN) {
3794                 out1fmt("builtin %s", cmdp->cmdname);
3795         } else if (cmdp->cmdtype == CMDFUNCTION) {
3796                 out1fmt("function %s", cmdp->cmdname);
3797                 if (verbose) {
3798                         INTOFF;
3799                         name = commandtext(cmdp->param.func);
3800                         out1fmt(" %s", name);
3801                         ckfree(name);
3802                         INTON;
3803                 }
3804 #ifdef DEBUG
3805         } else {
3806                 error("internal error: cmdtype %d", cmdp->cmdtype);
3807 #endif
3808         }
3809         out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr);
3810 }
3811
3812
3813
3814 /*** List the available builtins ***/
3815
3816
3817 static int helpcmd(int argc, char** argv)
3818 {
3819         int col, i;
3820         const struct builtincmd *x;
3821
3822         printf("\nBuilt-in commands:\n");
3823         printf("-------------------\n");
3824         for (col=0, i=0, x = builtincmds; i < NUMBUILTINS; x++, i++) {
3825                 if (!x->name || ! (x->name+1))
3826                         continue;
3827                 col += printf("%s%s", ((col == 0) ? "\t" : " "), 
3828                                 (x->name+1));
3829                 if (col > 60) {
3830                         printf("\n");
3831                         col = 0;
3832                 }
3833         }
3834 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3835         {
3836                 const struct BB_applet *applet;
3837                 extern const struct BB_applet applets[];
3838                 extern const size_t NUM_APPLETS;
3839
3840                 for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
3841                         if (!applet->name)
3842                                 continue;
3843                 
3844                         col += printf("%s%s", ((col == 0) ? "\t" : " "), 
3845                                         applet->name);
3846                         if (col > 60) {
3847                                 printf("\n");
3848                                 col = 0;
3849                         }
3850                 }
3851         }
3852 #endif
3853         printf("\n\n");
3854         return EXIT_SUCCESS;
3855 }
3856
3857
3858
3859 /*
3860  * Resolve a command name.  If you change this routine, you may have to
3861  * change the shellexec routine as well.
3862  */
3863
3864 static int prefix (const char *, const char *);
3865
3866 static void
3867 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3868 {
3869         struct tblentry *cmdp;
3870         int idx;
3871         int prev;
3872         char *fullname;
3873         struct stat statb;
3874         int e;
3875         int bltin;
3876         int firstchange;
3877         int updatetbl;
3878         bool regular;
3879         struct builtincmd *bcmd;
3880
3881         /* If name contains a slash, don't use the hash table */
3882         if (strchr(name, '/') != NULL) {
3883                 if (act & DO_ABS) {
3884                         while (stat(name, &statb) < 0) {
3885                                 if (errno != ENOENT && errno != ENOTDIR)
3886                                         e = errno;
3887                                 entry->cmdtype = CMDUNKNOWN;
3888                                 entry->u.index = -1;
3889                                 return;
3890                         }
3891                         entry->cmdtype = CMDNORMAL;
3892                         entry->u.index = -1;
3893                         return;
3894                 }
3895                 entry->cmdtype = CMDNORMAL;
3896                 entry->u.index = 0;
3897                 return;
3898         }
3899
3900         updatetbl = 1;
3901         if (act & DO_BRUTE) {
3902                 firstchange = path_change(path, &bltin);
3903         } else {
3904                 bltin = builtinloc;
3905                 firstchange = 9999;
3906         }
3907
3908         /* If name is in the table, and not invalidated by cd, we're done */
3909         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3910                 if (cmdp->cmdtype == CMDFUNCTION) {
3911                         if (act & DO_NOFUN) {
3912                                 updatetbl = 0;
3913                         } else {
3914                                 goto success;
3915                         }
3916                 } else if (act & DO_BRUTE) {
3917                         if ((cmdp->cmdtype == CMDNORMAL &&
3918                              cmdp->param.index >= firstchange) ||
3919                             (cmdp->cmdtype == CMDBUILTIN &&
3920                              ((builtinloc < 0 && bltin >= 0) ?
3921                               bltin : builtinloc) >= firstchange)) {
3922                                 /* need to recompute the entry */
3923                         } else {
3924                                 goto success;
3925                         }
3926                 } else {
3927                         goto success;
3928                 }
3929         }
3930
3931         bcmd = find_builtin(name);
3932         regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3933
3934         if (regular) {
3935                 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3936                         goto success;
3937                 }
3938         } else if (act & DO_BRUTE) {
3939                 if (firstchange == 0) {
3940                         updatetbl = 0;
3941                 }
3942         }
3943
3944         /* If %builtin not in path, check for builtin next */
3945         if (regular || (bltin < 0 && bcmd)) {
3946 builtin:
3947                 if (!updatetbl) {
3948                         entry->cmdtype = CMDBUILTIN;
3949                         entry->u.cmd = bcmd;
3950                         return;
3951                 }
3952                 INTOFF;
3953                 cmdp = cmdlookup(name, 1);
3954                 cmdp->cmdtype = CMDBUILTIN;
3955                 cmdp->param.cmd = bcmd;
3956                 INTON;
3957                 goto success;
3958         }
3959
3960         /* We have to search path. */
3961         prev = -1;              /* where to start */
3962         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3963                 if (cmdp->cmdtype == CMDBUILTIN)
3964                         prev = builtinloc;
3965                 else
3966                         prev = cmdp->param.index;
3967         }
3968
3969         e = ENOENT;
3970         idx = -1;
3971 loop:
3972         while ((fullname = padvance(&path, name)) != NULL) {
3973                 stunalloc(fullname);
3974                 idx++;
3975                 if (idx >= firstchange) {
3976                         updatetbl = 0;
3977                 }
3978                 if (pathopt) {
3979                         if (prefix("builtin", pathopt)) {
3980                                 if ((bcmd = find_builtin(name))) {
3981                                         goto builtin;
3982                                 }
3983                                 continue;
3984                         } else if (!(act & DO_NOFUN) &&
3985                                    prefix("func", pathopt)) {
3986                                 /* handled below */
3987                         } else {
3988                                 continue;       /* ignore unimplemented options */
3989                         }
3990                 }
3991                 /* if rehash, don't redo absolute path names */
3992                 if (fullname[0] == '/' && idx <= prev &&
3993                     idx < firstchange) {
3994                         if (idx < prev)
3995                                 continue;
3996                         TRACE(("searchexec \"%s\": no change\n", name));
3997                         goto success;
3998                 }
3999                 while (stat(fullname, &statb) < 0) {
4000                         if (errno != ENOENT && errno != ENOTDIR)
4001                                 e = errno;
4002                         goto loop;
4003                 }
4004                 e = EACCES;     /* if we fail, this will be the error */
4005                 if (!S_ISREG(statb.st_mode))
4006                         continue;
4007                 if (pathopt) {          /* this is a %func directory */
4008                         stalloc(strlen(fullname) + 1);
4009                         readcmdfile(fullname);
4010                         if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
4011                                 error("%s not defined in %s", name, fullname);
4012                         stunalloc(fullname);
4013                         goto success;
4014                 }
4015                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4016                 /* If we aren't called with DO_BRUTE and cmdp is set, it must
4017                    be a function and we're being called with DO_NOFUN */
4018                 if (!updatetbl) {
4019                         entry->cmdtype = CMDNORMAL;
4020                         entry->u.index = idx;
4021                         return;
4022                 }
4023                 INTOFF;
4024                 cmdp = cmdlookup(name, 1);
4025                 cmdp->cmdtype = CMDNORMAL;
4026                 cmdp->param.index = idx;
4027                 INTON;
4028                 goto success;
4029         }
4030
4031         /* We failed.  If there was an entry for this command, delete it */
4032         if (cmdp && updatetbl)
4033                 delete_cmd_entry();
4034         if (act & DO_ERR)
4035                 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
4036         entry->cmdtype = CMDUNKNOWN;
4037         return;
4038
4039 success:
4040         cmdp->rehash = 0;
4041         entry->cmdtype = cmdp->cmdtype;
4042         entry->u = cmdp->param;
4043 }
4044
4045
4046
4047 /*
4048  * Search the table of builtin commands.
4049  */
4050
4051 static int
4052 bstrcmp(const void *name, const void *b)
4053 {
4054         return strcmp((const char *)name, (*(const char *const *) b)+1);
4055 }
4056
4057 static struct builtincmd *
4058 find_builtin(const char *name)
4059 {
4060         struct builtincmd *bp;
4061
4062         bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
4063                 bstrcmp
4064         );
4065         return bp;
4066 }
4067
4068
4069 /*
4070  * Called when a cd is done.  Marks all commands so the next time they
4071  * are executed they will be rehashed.
4072  */
4073
4074 static void
4075 hashcd(void) {
4076         struct tblentry **pp;
4077         struct tblentry *cmdp;
4078
4079         for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4080                 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4081                         if (cmdp->cmdtype == CMDNORMAL
4082                          || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
4083                                 cmdp->rehash = 1;
4084                 }
4085         }
4086 }
4087
4088
4089
4090 /*
4091  * Called before PATH is changed.  The argument is the new value of PATH;
4092  * pathval() still returns the old value at this point.  Called with
4093  * interrupts off.
4094  */
4095
4096 static void
4097 changepath(const char *newval)
4098 {
4099         int firstchange;
4100         int bltin;
4101
4102         firstchange = path_change(newval, &bltin);
4103         if (builtinloc < 0 && bltin >= 0)
4104                 builtinloc = bltin;             /* zap builtins */
4105         clearcmdentry(firstchange);
4106         builtinloc = bltin;
4107 }
4108
4109
4110 /*
4111  * Clear out command entries.  The argument specifies the first entry in
4112  * PATH which has changed.
4113  */
4114
4115 static void
4116 clearcmdentry(firstchange)
4117         int firstchange;
4118 {
4119         struct tblentry **tblp;
4120         struct tblentry **pp;
4121         struct tblentry *cmdp;
4122
4123         INTOFF;
4124         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4125                 pp = tblp;
4126                 while ((cmdp = *pp) != NULL) {
4127                         if ((cmdp->cmdtype == CMDNORMAL &&
4128                              cmdp->param.index >= firstchange)
4129                          || (cmdp->cmdtype == CMDBUILTIN &&
4130                              builtinloc >= firstchange)) {
4131                                 *pp = cmdp->next;
4132                                 ckfree(cmdp);
4133                         } else {
4134                                 pp = &cmdp->next;
4135                         }
4136                 }
4137         }
4138         INTON;
4139 }
4140
4141 /*
4142  * Free a parse tree.
4143  */
4144
4145 static void
4146 freefunc(union node *n)
4147 {
4148         if (n)
4149                 ckfree(n);
4150 }
4151
4152
4153 /*
4154  * Delete all functions.
4155  */
4156
4157 static void
4158 deletefuncs(void) {
4159         struct tblentry **tblp;
4160         struct tblentry **pp;
4161         struct tblentry *cmdp;
4162
4163         INTOFF;
4164         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4165                 pp = tblp;
4166                 while ((cmdp = *pp) != NULL) {
4167                         if (cmdp->cmdtype == CMDFUNCTION) {
4168                                 *pp = cmdp->next;
4169                                 freefunc(cmdp->param.func);
4170                                 ckfree(cmdp);
4171                         } else {
4172                                 pp = &cmdp->next;
4173                         }
4174                 }
4175         }
4176         INTON;
4177 }
4178
4179
4180
4181 /*
4182  * Locate a command in the command hash table.  If "add" is nonzero,
4183  * add the command to the table if it is not already present.  The
4184  * variable "lastcmdentry" is set to point to the address of the link
4185  * pointing to the entry, so that delete_cmd_entry can delete the
4186  * entry.
4187  */
4188
4189 static struct tblentry **lastcmdentry;
4190
4191 static struct tblentry *
4192 cmdlookup(const char *name, int add)
4193 {
4194         int hashval;
4195         const char *p;
4196         struct tblentry *cmdp;
4197         struct tblentry **pp;
4198
4199         p = name;
4200         hashval = *p << 4;
4201         while (*p)
4202                 hashval += *p++;
4203         hashval &= 0x7FFF;
4204         pp = &cmdtable[hashval % CMDTABLESIZE];
4205         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4206                 if (equal(cmdp->cmdname, name))
4207                         break;
4208                 pp = &cmdp->next;
4209         }
4210         if (add && cmdp == NULL) {
4211                 INTOFF;
4212                 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4213                                         + strlen(name) + 1);
4214                 cmdp->next = NULL;
4215                 cmdp->cmdtype = CMDUNKNOWN;
4216                 cmdp->rehash = 0;
4217                 strcpy(cmdp->cmdname, name);
4218                 INTON;
4219         }
4220         lastcmdentry = pp;
4221         return cmdp;
4222 }
4223
4224 /*
4225  * Delete the command entry returned on the last lookup.
4226  */
4227
4228 static void
4229 delete_cmd_entry() {
4230         struct tblentry *cmdp;
4231
4232         INTOFF;
4233         cmdp = *lastcmdentry;
4234         *lastcmdentry = cmdp->next;
4235         ckfree(cmdp);
4236         INTON;
4237 }
4238
4239
4240
4241 /*
4242  * Add a new command entry, replacing any existing command entry for
4243  * the same name.
4244  */
4245
4246 static void
4247 addcmdentry(char *name, struct cmdentry *entry)
4248 {
4249         struct tblentry *cmdp;
4250
4251         INTOFF;
4252         cmdp = cmdlookup(name, 1);
4253         if (cmdp->cmdtype == CMDFUNCTION) {
4254                 freefunc(cmdp->param.func);
4255         }
4256         cmdp->cmdtype = entry->cmdtype;
4257         cmdp->param = entry->u;
4258         INTON;
4259 }
4260
4261
4262 /*
4263  * Define a shell function.
4264  */
4265
4266 static union node *copyfunc(union node *);
4267
4268 static void
4269 defun(char *name, union node *func)
4270 {
4271         struct cmdentry entry;
4272
4273         entry.cmdtype = CMDFUNCTION;
4274         entry.u.func = copyfunc(func);
4275         addcmdentry(name, &entry);
4276 }
4277
4278
4279 /*
4280  * Delete a function if it exists.
4281  */
4282
4283 static void
4284 unsetfunc(char *name)
4285 {
4286         struct tblentry *cmdp;
4287
4288         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4289                 freefunc(cmdp->param.func);
4290                 delete_cmd_entry();
4291         }
4292 }
4293
4294 /*
4295  * Wrapper around strcmp for qsort/bsearch/...
4296  */
4297 static int
4298 pstrcmp(const void *a, const void *b)
4299 {
4300         return strcmp((const char *) a, *(const char *const *) b);
4301 }
4302
4303 /*
4304  * Find a keyword is in a sorted array.
4305  */
4306
4307 static const char *const *
4308 findkwd(const char *s)
4309 {
4310         return  bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
4311                         sizeof(const char *), pstrcmp);
4312 }
4313
4314 #ifdef ASH_TYPE
4315 /*
4316  * Locate and print what a word is...
4317  */
4318
4319 static int
4320 typecmd(argc, argv)
4321         int argc;
4322         char **argv;
4323 {
4324         int i;
4325         int err = 0;
4326
4327         for (i = 1; i < argc; i++) {
4328                 err |= describe_command(argv[i], 1);
4329         }
4330         return err;
4331 }
4332
4333 static int
4334 describe_command(char *command, int verbose)
4335 {
4336         struct cmdentry entry;
4337         struct tblentry *cmdp;
4338 #ifdef ASH_ALIAS
4339         const struct alias *ap;
4340 #endif
4341         const char *path = pathval();
4342
4343         if (verbose) {
4344                 out1str(command);
4345         }
4346
4347         /* First look at the keywords */
4348         if (findkwd(command)) {
4349                 out1str(verbose ? " is a shell keyword" : command);
4350                 goto out;
4351         }
4352
4353 #ifdef ASH_ALIAS
4354         /* Then look at the aliases */
4355         if ((ap = lookupalias(command, 0)) != NULL) {
4356                 if (verbose) {
4357                         out1fmt(" is an alias for %s", ap->val);
4358                 } else {
4359                         printalias(ap);
4360                 }
4361                 goto out;
4362         }
4363 #endif
4364         /* Then check if it is a tracked alias */
4365         if ((cmdp = cmdlookup(command, 0)) != NULL) {
4366                 entry.cmdtype = cmdp->cmdtype;
4367                 entry.u = cmdp->param;
4368         } else {
4369                 /* Finally use brute force */
4370                 find_command(command, &entry, DO_ABS, path);
4371         }
4372
4373         switch (entry.cmdtype) {
4374         case CMDNORMAL: {
4375                 int j = entry.u.index;
4376                 char *p;
4377                 if (j == -1) {
4378                         p = command;
4379                 } else {
4380                         do {
4381                                 p = padvance(&path, command);
4382                                 stunalloc(p);
4383                         } while (--j >= 0);
4384                 }
4385                 if (verbose) {
4386                         out1fmt(
4387                                 " is%s %s",
4388                                 cmdp ? " a tracked alias for" : nullstr, p
4389                         );
4390                 } else {
4391                         out1str(p);
4392                 }
4393                 break;
4394         }
4395
4396         case CMDFUNCTION:
4397                 if (verbose) {
4398                         out1str(" is a shell function");
4399                 } else {
4400                         out1str(command);
4401                 }
4402                 break;
4403
4404         case CMDBUILTIN:
4405                 if (verbose) {
4406                         out1fmt(
4407                                 " is a %sshell builtin",
4408                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4409                                         "special " : nullstr
4410                         );
4411                 } else {
4412                         out1str(command);
4413                 }
4414                 break;
4415
4416         default:
4417                 if (verbose) {
4418                         out1str(": not found\n");
4419                 }
4420                 return 127;
4421         }
4422
4423 out:
4424         putchar('\n');
4425         return 0;
4426 }
4427 #endif
4428
4429 #ifdef ASH_CMDCMD
4430 static int
4431 commandcmd(argc, argv)
4432         int argc;
4433         char **argv;
4434 {
4435         int c;
4436         int default_path = 0;
4437         int verify_only = 0;
4438         int verbose_verify_only = 0;
4439
4440         while ((c = nextopt("pvV")) != '\0')
4441                 switch (c) {
4442                 case 'p':
4443                         default_path = 1;
4444                         break;
4445                 case 'v':
4446                         verify_only = 1;
4447                         break;
4448                 case 'V':
4449                         verbose_verify_only = 1;
4450                         break;
4451                 default:
4452                         out2fmt(
4453 "command: nextopt returned character code 0%o\n", c);
4454                         return EX_SOFTWARE;
4455                 }
4456
4457         if (default_path + verify_only + verbose_verify_only > 1 ||
4458             !*argptr) {
4459                         out2fmt(
4460 "command [-p] command [arg ...]\n");
4461                         out2fmt(
4462 "command {-v|-V} command\n");
4463                         return EX_USAGE;
4464         }
4465
4466 #ifdef ASH_TYPE
4467         if (verify_only || verbose_verify_only) {
4468                 return describe_command(*argptr, verbose_verify_only);
4469         }
4470 #endif
4471
4472         return 0;
4473 }
4474 #endif
4475
4476 static int
4477 path_change(newval, bltin)
4478         const char *newval;
4479         int *bltin;
4480 {
4481         const char *old, *new;
4482         int idx;
4483         int firstchange;
4484
4485         old = pathval();
4486         new = newval;
4487         firstchange = 9999;     /* assume no change */
4488         idx = 0;
4489         *bltin = -1;
4490         for (;;) {
4491                 if (*old != *new) {
4492                         firstchange = idx;
4493                         if ((*old == '\0' && *new == ':')
4494                          || (*old == ':' && *new == '\0'))
4495                                 firstchange++;
4496                         old = new;      /* ignore subsequent differences */
4497                 }
4498                 if (*new == '\0')
4499                         break;
4500                 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4501                         *bltin = idx;
4502                 if (*new == ':') {
4503                         idx++;
4504                 }
4505                 new++, old++;
4506         }
4507         if (builtinloc >= 0 && *bltin < 0)
4508                 firstchange = 0;
4509         return firstchange;
4510 }
4511 /*
4512  * Routines to expand arguments to commands.  We have to deal with
4513  * backquotes, shell variables, and file metacharacters.
4514  */
4515 /*
4516  * _rmescape() flags
4517  */
4518 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4519 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4520
4521 /*
4522  * Structure specifying which parts of the string should be searched
4523  * for IFS characters.
4524  */
4525
4526 struct ifsregion {
4527         struct ifsregion *next; /* next region in list */
4528         int begoff;             /* offset of start of region */
4529         int endoff;             /* offset of end of region */
4530         int nulonly;            /* search for nul bytes only */
4531 };
4532
4533
4534 static char *expdest;                   /* output of current string */
4535 static struct nodelist *argbackq;      /* list of back quote expressions */
4536 static struct ifsregion ifsfirst;      /* first struct in list of ifs regions */
4537 static struct ifsregion *ifslastp;     /* last struct in list */
4538 static struct arglist exparg;          /* holds expanded arg list */
4539
4540 static void argstr (char *, int);
4541 static char *exptilde (char *, int);
4542 static void expbackq (union node *, int, int);
4543 static int subevalvar (char *, char *, int, int, int, int, int);
4544 static char *evalvar (char *, int);
4545 static int varisset (char *, int);
4546 static void strtodest (const char *, const char *, int);
4547 static void varvalue (char *, int, int);
4548 static void recordregion (int, int, int);
4549 static void removerecordregions (int);
4550 static void ifsbreakup (char *, struct arglist *);
4551 static void ifsfree (void);
4552 static void expandmeta (struct strlist *, int);
4553 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4554 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4555 #if !defined(GLOB_BROKEN)
4556 static void addglob (const glob_t *);
4557 #endif
4558 #endif
4559 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4560 static void expmeta (char *, char *);
4561 #endif
4562 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4563 static struct strlist *expsort (struct strlist *);
4564 static struct strlist *msort (struct strlist *, int);
4565 #endif
4566 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4567 static int patmatch (char *, char *, int);
4568 static int patmatch2 (char *, char *, int);
4569 #else
4570 static int pmatch (char *, char *, int);
4571 #define patmatch2 patmatch
4572 #endif
4573 static char *cvtnum (int, char *);
4574
4575 /*
4576  * Expand shell variables and backquotes inside a here document.
4577  */
4578
4579 /* arg: the document, fd: where to write the expanded version */
4580 static void
4581 expandhere(union node *arg, int fd)
4582 {
4583         herefd = fd;
4584         expandarg(arg, (struct arglist *)NULL, 0);
4585         xwrite(fd, stackblock(), expdest - stackblock());
4586 }
4587
4588
4589 /*
4590  * Perform variable substitution and command substitution on an argument,
4591  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
4592  * perform splitting and file name expansion.  When arglist is NULL, perform
4593  * here document expansion.
4594  */
4595
4596 static void
4597 expandarg(arg, arglist, flag)
4598         union node *arg;
4599         struct arglist *arglist;
4600         int flag;
4601 {
4602         struct strlist *sp;
4603         char *p;
4604
4605         argbackq = arg->narg.backquote;
4606         STARTSTACKSTR(expdest);
4607         ifsfirst.next = NULL;
4608         ifslastp = NULL;
4609         argstr(arg->narg.text, flag);
4610         if (arglist == NULL) {
4611                 return;                 /* here document expanded */
4612         }
4613         STPUTC('\0', expdest);
4614         p = grabstackstr(expdest);
4615         exparg.lastp = &exparg.list;
4616         /*
4617          * TODO - EXP_REDIR
4618          */
4619         if (flag & EXP_FULL) {
4620                 ifsbreakup(p, &exparg);
4621                 *exparg.lastp = NULL;
4622                 exparg.lastp = &exparg.list;
4623                 expandmeta(exparg.list, flag);
4624         } else {
4625                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4626                         rmescapes(p);
4627                 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4628                 sp->text = p;
4629                 *exparg.lastp = sp;
4630                 exparg.lastp = &sp->next;
4631         }
4632         ifsfree();
4633         *exparg.lastp = NULL;
4634         if (exparg.list) {
4635                 *arglist->lastp = exparg.list;
4636                 arglist->lastp = exparg.lastp;
4637         }
4638 }
4639
4640
4641
4642 /*
4643  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
4644  * characters to allow for further processing.  Otherwise treat
4645  * $@ like $* since no splitting will be performed.
4646  */
4647
4648 static void
4649 argstr(p, flag)
4650         char *p;
4651         int flag;
4652 {
4653         char c;
4654         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
4655         int firsteq = 1;
4656
4657         if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4658                 p = exptilde(p, flag);
4659         for (;;) {
4660                 switch (c = *p++) {
4661                 case '\0':
4662                 case CTLENDVAR: /* ??? */
4663                         goto breakloop;
4664                 case CTLQUOTEMARK:
4665                         /* "$@" syntax adherence hack */
4666                         if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4667                                 break;
4668                         if ((flag & EXP_FULL) != 0)
4669                                 STPUTC(c, expdest);
4670                         break;
4671                 case CTLESC:
4672                         if (quotes)
4673                                 STPUTC(c, expdest);
4674                         c = *p++;
4675                         STPUTC(c, expdest);
4676                         break;
4677                 case CTLVAR:
4678                         p = evalvar(p, flag);
4679                         break;
4680                 case CTLBACKQ:
4681                 case CTLBACKQ|CTLQUOTE:
4682                         expbackq(argbackq->n, c & CTLQUOTE, flag);
4683                         argbackq = argbackq->next;
4684                         break;
4685 #ifdef ASH_MATH_SUPPORT
4686                 case CTLENDARI:
4687                         expari(flag);
4688                         break;
4689 #endif
4690                 case ':':
4691                 case '=':
4692                         /*
4693                          * sort of a hack - expand tildes in variable
4694                          * assignments (after the first '=' and after ':'s).
4695                          */
4696                         STPUTC(c, expdest);
4697                         if (flag & EXP_VARTILDE && *p == '~') {
4698                                 if (c == '=') {
4699                                         if (firsteq)
4700                                                 firsteq = 0;
4701                                         else
4702                                                 break;
4703                                 }
4704                                 p = exptilde(p, flag);
4705                         }
4706                         break;
4707                 default:
4708                         STPUTC(c, expdest);
4709                 }
4710         }
4711 breakloop:;
4712         return;
4713 }
4714
4715 static char *
4716 exptilde(p, flag)
4717         char *p;
4718         int flag;
4719 {
4720         char c, *startp = p;
4721         struct passwd *pw;
4722         const char *home;
4723         int quotes = flag & (EXP_FULL | EXP_CASE);
4724
4725         while ((c = *p) != '\0') {
4726                 switch(c) {
4727                 case CTLESC:
4728                         return (startp);
4729                 case CTLQUOTEMARK:
4730                         return (startp);
4731                 case ':':
4732                         if (flag & EXP_VARTILDE)
4733                                 goto done;
4734                         break;
4735                 case '/':
4736                         goto done;
4737                 }
4738                 p++;
4739         }
4740 done:
4741         *p = '\0';
4742         if (*(startp+1) == '\0') {
4743                 if ((home = lookupvar("HOME")) == NULL)
4744                         goto lose;
4745         } else {
4746                 if ((pw = getpwnam(startp+1)) == NULL)
4747                         goto lose;
4748                 home = pw->pw_dir;
4749         }
4750         if (*home == '\0')
4751                 goto lose;
4752         *p = c;
4753         strtodest(home, SQSYNTAX, quotes);
4754         return (p);
4755 lose:
4756         *p = c;
4757         return (startp);
4758 }
4759
4760
4761 static void
4762 removerecordregions(int endoff)
4763 {
4764         if (ifslastp == NULL)
4765                 return;
4766
4767         if (ifsfirst.endoff > endoff) {
4768                 while (ifsfirst.next != NULL) {
4769                         struct ifsregion *ifsp;
4770                         INTOFF;
4771                         ifsp = ifsfirst.next->next;
4772                         ckfree(ifsfirst.next);
4773                         ifsfirst.next = ifsp;
4774                         INTON;
4775                 }
4776                 if (ifsfirst.begoff > endoff)
4777                         ifslastp = NULL;
4778                 else {
4779                         ifslastp = &ifsfirst;
4780                         ifsfirst.endoff = endoff;
4781                 }
4782                 return;
4783         }
4784
4785         ifslastp = &ifsfirst;
4786         while (ifslastp->next && ifslastp->next->begoff < endoff)
4787                 ifslastp=ifslastp->next;
4788         while (ifslastp->next != NULL) {
4789                 struct ifsregion *ifsp;
4790                 INTOFF;
4791                 ifsp = ifslastp->next->next;
4792                 ckfree(ifslastp->next);
4793                 ifslastp->next = ifsp;
4794                 INTON;
4795         }
4796         if (ifslastp->endoff > endoff)
4797                 ifslastp->endoff = endoff;
4798 }
4799
4800
4801 #ifdef ASH_MATH_SUPPORT
4802 /*
4803  * Expand arithmetic expression.  Backup to start of expression,
4804  * evaluate, place result in (backed up) result, adjust string position.
4805  */
4806 static void
4807 expari(int flag)
4808 {
4809         char *p, *start;
4810         int result;
4811         int begoff;
4812         int quotes = flag & (EXP_FULL | EXP_CASE);
4813         int quoted;
4814
4815         /*      ifsfree(); */
4816
4817         /*
4818          * This routine is slightly over-complicated for
4819          * efficiency.  First we make sure there is
4820          * enough space for the result, which may be bigger
4821          * than the expression if we add exponentation.  Next we
4822          * scan backwards looking for the start of arithmetic.  If the
4823          * next previous character is a CTLESC character, then we
4824          * have to rescan starting from the beginning since CTLESC
4825          * characters have to be processed left to right.
4826          */
4827         CHECKSTRSPACE(10, expdest);
4828         USTPUTC('\0', expdest);
4829         start = stackblock();
4830         p = expdest - 1;
4831         while (*p != CTLARI && p >= start)
4832                 --p;
4833         if (*p != CTLARI)
4834                 error("missing CTLARI (shouldn't happen)");
4835         if (p > start && *(p-1) == CTLESC)
4836                 for (p = start; *p != CTLARI; p++)
4837                         if (*p == CTLESC)
4838                                 p++;
4839
4840         if (p[1] == '"')
4841                 quoted=1;
4842         else
4843                 quoted=0;
4844         begoff = p - start;
4845         removerecordregions(begoff);
4846         if (quotes)
4847                 rmescapes(p+2);
4848         result = arith(p+2);
4849         snprintf(p, 12, "%d", result);
4850
4851         while (*p++)
4852                 ;
4853
4854         if (quoted == 0)
4855                 recordregion(begoff, p - 1 - start, 0);
4856         result = expdest - p + 1;
4857         STADJUST(-result, expdest);
4858 }
4859 #endif
4860
4861 /*
4862  * Expand stuff in backwards quotes.
4863  */
4864
4865 static void
4866 expbackq(cmd, quoted, flag)
4867         union node *cmd;
4868         int quoted;
4869         int flag;
4870 {
4871         volatile struct backcmd in;
4872         int i;
4873         char buf[128];
4874         char *p;
4875         char *dest = expdest;
4876         volatile struct ifsregion saveifs;
4877         struct ifsregion *volatile savelastp;
4878         struct nodelist *volatile saveargbackq;
4879         char lastc;
4880         int startloc = dest - stackblock();
4881         char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
4882         volatile int saveherefd;
4883         int quotes = flag & (EXP_FULL | EXP_CASE);
4884         struct jmploc jmploc;
4885         struct jmploc *volatile savehandler;
4886         int ex;
4887
4888 #if __GNUC__
4889         /* Avoid longjmp clobbering */
4890         (void) &dest;
4891         (void) &syntax;
4892 #endif
4893
4894         in.fd = -1;
4895         in.buf = 0;
4896         in.jp = 0;
4897
4898         INTOFF;
4899         saveifs = ifsfirst;
4900         savelastp = ifslastp;
4901         saveargbackq = argbackq;
4902         saveherefd = herefd;
4903         herefd = -1;
4904         if ((ex = setjmp(jmploc.loc))) {
4905                 goto err1;
4906         }
4907         savehandler = handler;
4908         handler = &jmploc;
4909         INTON;
4910         p = grabstackstr(dest);
4911         evalbackcmd(cmd, (struct backcmd *) &in);
4912         ungrabstackstr(p, dest);
4913 err1:
4914         INTOFF;
4915         ifsfirst = saveifs;
4916         ifslastp = savelastp;
4917         argbackq = saveargbackq;
4918         herefd = saveherefd;
4919         if (ex) {
4920                 goto err2;
4921         }
4922
4923         p = in.buf;
4924         lastc = '\0';
4925         for (;;) {
4926                 if (--in.nleft < 0) {
4927                         if (in.fd < 0)
4928                                 break;
4929                         while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
4930                         TRACE(("expbackq: read returns %d\n", i));
4931                         if (i <= 0)
4932                                 break;
4933                         p = buf;
4934                         in.nleft = i - 1;
4935                 }
4936                 lastc = *p++;
4937                 if (lastc != '\0') {
4938                         if (quotes && syntax[(int)lastc] == CCTL)
4939                                 STPUTC(CTLESC, dest);
4940                         STPUTC(lastc, dest);
4941                 }
4942         }
4943
4944         /* Eat all trailing newlines */
4945         for (; dest > stackblock() && dest[-1] == '\n';)
4946                 STUNPUTC(dest);
4947
4948 err2:
4949         if (in.fd >= 0)
4950                 close(in.fd);
4951         if (in.buf)
4952                 ckfree(in.buf);
4953         if (in.jp)
4954                 exitstatus = waitforjob(in.jp);
4955         handler = savehandler;
4956         if (ex) {
4957                 longjmp(handler->loc, 1);
4958         }
4959         if (quoted == 0)
4960                 recordregion(startloc, dest - stackblock(), 0);
4961         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4962                 (dest - stackblock()) - startloc,
4963                 (dest - stackblock()) - startloc,
4964                 stackblock() + startloc));
4965         expdest = dest;
4966         INTON;
4967 }
4968
4969 static int
4970 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
4971         char *p;
4972         char *str;
4973         int strloc;
4974         int subtype;
4975         int startloc;
4976         int varflags;
4977         int quotes;
4978 {
4979         char *startp;
4980         char *loc = NULL;
4981         char *q;
4982         int c = 0;
4983         int saveherefd = herefd;
4984         struct nodelist *saveargbackq = argbackq;
4985         int amount;
4986
4987         herefd = -1;
4988         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4989         STACKSTRNUL(expdest);
4990         herefd = saveherefd;
4991         argbackq = saveargbackq;
4992         startp = stackblock() + startloc;
4993         if (str == NULL)
4994             str = stackblock() + strloc;
4995
4996         switch (subtype) {
4997         case VSASSIGN:
4998                 setvar(str, startp, 0);
4999                 amount = startp - expdest;
5000                 STADJUST(amount, expdest);
5001                 varflags &= ~VSNUL;
5002                 if (c != 0)
5003                         *loc = c;
5004                 return 1;
5005
5006         case VSQUESTION:
5007                 if (*p != CTLENDVAR) {
5008                         out2fmt(snlfmt, startp);
5009                         error((char *)NULL);
5010                 }
5011                 error("%.*s: parameter %snot set", p - str - 1,
5012                       str, (varflags & VSNUL) ? "null or "
5013                                               : nullstr);
5014                 /* NOTREACHED */
5015
5016         case VSTRIMLEFT:
5017                 for (loc = startp; loc < str; loc++) {
5018                         c = *loc;
5019                         *loc = '\0';
5020                         if (patmatch2(str, startp, quotes))
5021                                 goto recordleft;
5022                         *loc = c;
5023                         if (quotes && *loc == CTLESC)
5024                                 loc++;
5025                 }
5026                 return 0;
5027
5028         case VSTRIMLEFTMAX:
5029                 for (loc = str - 1; loc >= startp;) {
5030                         c = *loc;
5031                         *loc = '\0';
5032                         if (patmatch2(str, startp, quotes))
5033                                 goto recordleft;
5034                         *loc = c;
5035                         loc--;
5036                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5037                                 for (q = startp; q < loc; q++)
5038                                         if (*q == CTLESC)
5039                                                 q++;
5040                                 if (q > loc)
5041                                         loc--;
5042                         }
5043                 }
5044                 return 0;
5045
5046         case VSTRIMRIGHT:
5047                 for (loc = str - 1; loc >= startp;) {
5048                         if (patmatch2(str, loc, quotes))
5049                                 goto recordright;
5050                         loc--;
5051                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5052                                 for (q = startp; q < loc; q++)
5053                                         if (*q == CTLESC)
5054                                                 q++;
5055                                 if (q > loc)
5056                                         loc--;
5057                         }
5058                 }
5059                 return 0;
5060
5061         case VSTRIMRIGHTMAX:
5062                 for (loc = startp; loc < str - 1; loc++) {
5063                         if (patmatch2(str, loc, quotes))
5064                                 goto recordright;
5065                         if (quotes && *loc == CTLESC)
5066                                 loc++;
5067                 }
5068                 return 0;
5069
5070 #ifdef DEBUG
5071         default:
5072                 abort();
5073 #endif
5074         }
5075
5076 recordleft:
5077         *loc = c;
5078         amount = ((str - 1) - (loc - startp)) - expdest;
5079         STADJUST(amount, expdest);
5080         while (loc != str - 1)
5081                 *startp++ = *loc++;
5082         return 1;
5083
5084 recordright:
5085         amount = loc - expdest;
5086         STADJUST(amount, expdest);
5087         STPUTC('\0', expdest);
5088         STADJUST(-1, expdest);
5089         return 1;
5090 }
5091
5092
5093 /*
5094  * Expand a variable, and return a pointer to the next character in the
5095  * input string.
5096  */
5097
5098 static char *
5099 evalvar(p, flag)
5100         char *p;
5101         int flag;
5102 {
5103         int subtype;
5104         int varflags;
5105         char *var;
5106         char *val;
5107         int patloc;
5108         int c;
5109         int set;
5110         int special;
5111         int startloc;
5112         int varlen;
5113         int easy;
5114         int quotes = flag & (EXP_FULL | EXP_CASE);
5115
5116         varflags = *p++;
5117         subtype = varflags & VSTYPE;
5118         var = p;
5119         special = 0;
5120         if (! is_name(*p))
5121                 special = 1;
5122         p = strchr(p, '=') + 1;
5123 again: /* jump here after setting a variable with ${var=text} */
5124         if (special) {
5125                 set = varisset(var, varflags & VSNUL);
5126                 val = NULL;
5127         } else {
5128                 val = lookupvar(var);
5129                 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
5130                         val = NULL;
5131                         set = 0;
5132                 } else
5133                         set = 1;
5134         }
5135         varlen = 0;
5136         startloc = expdest - stackblock();
5137         if (set && subtype != VSPLUS) {
5138                 /* insert the value of the variable */
5139                 if (special) {
5140                         varvalue(var, varflags & VSQUOTE, flag);
5141                         if (subtype == VSLENGTH) {
5142                                 varlen = expdest - stackblock() - startloc;
5143                                 STADJUST(-varlen, expdest);
5144                         }
5145                 } else {
5146                         if (subtype == VSLENGTH) {
5147                                 varlen = strlen(val);
5148                         } else {
5149                                 strtodest(
5150                                         val,
5151                                         varflags & VSQUOTE ?
5152                                                 DQSYNTAX : BASESYNTAX,
5153                                         quotes
5154                                 );
5155                         }
5156                 }
5157         }
5158
5159         if (subtype == VSPLUS)
5160                 set = ! set;
5161
5162         easy = ((varflags & VSQUOTE) == 0 ||
5163                 (*var == '@' && shellparam.nparam != 1));
5164
5165
5166         switch (subtype) {
5167         case VSLENGTH:
5168                 expdest = cvtnum(varlen, expdest);
5169                 goto record;
5170
5171         case VSNORMAL:
5172                 if (!easy)
5173                         break;
5174 record:
5175                 recordregion(startloc, expdest - stackblock(),
5176                              varflags & VSQUOTE);
5177                 break;
5178
5179         case VSPLUS:
5180         case VSMINUS:
5181                 if (!set) {
5182                         argstr(p, flag);
5183                         break;
5184                 }
5185                 if (easy)
5186                         goto record;
5187                 break;
5188
5189         case VSTRIMLEFT:
5190         case VSTRIMLEFTMAX:
5191         case VSTRIMRIGHT:
5192         case VSTRIMRIGHTMAX:
5193                 if (!set)
5194                         break;
5195                 /*
5196                  * Terminate the string and start recording the pattern
5197                  * right after it
5198                  */
5199                 STPUTC('\0', expdest);
5200                 patloc = expdest - stackblock();
5201                 if (subevalvar(p, NULL, patloc, subtype,
5202                                startloc, varflags, quotes) == 0) {
5203                         int amount = (expdest - stackblock() - patloc) + 1;
5204                         STADJUST(-amount, expdest);
5205                 }
5206                 /* Remove any recorded regions beyond start of variable */
5207                 removerecordregions(startloc);
5208                 goto record;
5209
5210         case VSASSIGN:
5211         case VSQUESTION:
5212                 if (!set) {
5213                         if (subevalvar(p, var, 0, subtype, startloc,
5214                                        varflags, quotes)) {
5215                                 varflags &= ~VSNUL;
5216                                 /*
5217                                  * Remove any recorded regions beyond
5218                                  * start of variable
5219                                  */
5220                                 removerecordregions(startloc);
5221                                 goto again;
5222                         }
5223                         break;
5224                 }
5225                 if (easy)
5226                         goto record;
5227                 break;
5228
5229 #ifdef DEBUG
5230         default:
5231                 abort();
5232 #endif
5233         }
5234
5235         if (subtype != VSNORMAL) {      /* skip to end of alternative */
5236                 int nesting = 1;
5237                 for (;;) {
5238                         if ((c = *p++) == CTLESC)
5239                                 p++;
5240                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5241                                 if (set)
5242                                         argbackq = argbackq->next;
5243                         } else if (c == CTLVAR) {
5244                                 if ((*p++ & VSTYPE) != VSNORMAL)
5245                                         nesting++;
5246                         } else if (c == CTLENDVAR) {
5247                                 if (--nesting == 0)
5248                                         break;
5249                         }
5250                 }
5251         }
5252         return p;
5253 }
5254
5255 /*
5256  * Test whether a specialized variable is set.
5257  */
5258
5259 static int
5260 varisset(name, nulok)
5261         char *name;
5262         int nulok;
5263 {
5264         if (*name == '!')
5265                 return backgndpid != -1;
5266         else if (*name == '@' || *name == '*') {
5267                 if (*shellparam.p == NULL)
5268                         return 0;
5269
5270                 if (nulok) {
5271                         char **av;
5272
5273                         for (av = shellparam.p; *av; av++)
5274                                 if (**av != '\0')
5275                                         return 1;
5276                         return 0;
5277                 }
5278         } else if (is_digit(*name)) {
5279                 char *ap;
5280                 int num = atoi(name);
5281
5282                 if (num > shellparam.nparam)
5283                         return 0;
5284
5285                 if (num == 0)
5286                         ap = arg0;
5287                 else
5288                         ap = shellparam.p[num - 1];
5289
5290                 if (nulok && (ap == NULL || *ap == '\0'))
5291                         return 0;
5292         }
5293         return 1;
5294 }
5295
5296 /*
5297  * Put a string on the stack.
5298  */
5299
5300 static void
5301 strtodest(p, syntax, quotes)
5302         const char *p;
5303         const char *syntax;
5304         int quotes;
5305 {
5306         while (*p) {
5307                 if (quotes && syntax[(int) *p] == CCTL)
5308                         STPUTC(CTLESC, expdest);
5309                 STPUTC(*p++, expdest);
5310         }
5311 }
5312
5313 /*
5314  * Add the value of a specialized variable to the stack string.
5315  */
5316
5317 static void
5318 varvalue(name, quoted, flags)
5319         char *name;
5320         int quoted;
5321         int flags;
5322 {
5323         int num;
5324         char *p;
5325         int i;
5326         int sep;
5327         int sepq = 0;
5328         char **ap;
5329         char const *syntax;
5330         int allow_split = flags & EXP_FULL;
5331         int quotes = flags & (EXP_FULL | EXP_CASE);
5332
5333         syntax = quoted ? DQSYNTAX : BASESYNTAX;
5334         switch (*name) {
5335         case '$':
5336                 num = rootpid;
5337                 goto numvar;
5338         case '?':
5339                 num = oexitstatus;
5340                 goto numvar;
5341         case '#':
5342                 num = shellparam.nparam;
5343                 goto numvar;
5344         case '!':
5345                 num = backgndpid;
5346 numvar:
5347                 expdest = cvtnum(num, expdest);
5348                 break;
5349         case '-':
5350                 for (i = 0 ; i < NOPTS ; i++) {
5351                         if (optent_val(i))
5352                                 STPUTC(optent_letter(optlist[i]), expdest);
5353                 }
5354                 break;
5355         case '@':
5356                 if (allow_split && quoted) {
5357                         sep = 1 << CHAR_BIT;
5358                         goto param;
5359                 }
5360                 /* fall through */
5361         case '*':
5362                 sep = ifsset() ? ifsval()[0] : ' ';
5363                 if (quotes) {
5364                         sepq = syntax[(int) sep] == CCTL;
5365                 }
5366 param:
5367                 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5368                         strtodest(p, syntax, quotes);
5369                         if (*ap && sep) {
5370                                 if (sepq)
5371                                         STPUTC(CTLESC, expdest);
5372                                 STPUTC(sep, expdest);
5373                         }
5374                 }
5375                 break;
5376         case '0':
5377                 strtodest(arg0, syntax, quotes);
5378                 break;
5379         default:
5380                 num = atoi(name);
5381                 if (num > 0 && num <= shellparam.nparam) {
5382                         strtodest(shellparam.p[num - 1], syntax, quotes);
5383                 }
5384                 break;
5385         }
5386 }
5387
5388
5389 /*
5390  * Record the fact that we have to scan this region of the
5391  * string for IFS characters.
5392  */
5393
5394 static void
5395 recordregion(start, end, nulonly)
5396         int start;
5397         int end;
5398         int nulonly;
5399 {
5400         struct ifsregion *ifsp;
5401
5402         if (ifslastp == NULL) {
5403                 ifsp = &ifsfirst;
5404         } else {
5405                 INTOFF;
5406                 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5407                 ifsp->next = NULL;
5408                 ifslastp->next = ifsp;
5409                 INTON;
5410         }
5411         ifslastp = ifsp;
5412         ifslastp->begoff = start;
5413         ifslastp->endoff = end;
5414         ifslastp->nulonly = nulonly;
5415 }
5416
5417
5418
5419 /*
5420  * Break the argument string into pieces based upon IFS and add the
5421  * strings to the argument list.  The regions of the string to be
5422  * searched for IFS characters have been stored by recordregion.
5423  */
5424 static void
5425 ifsbreakup(string, arglist)
5426         char *string;
5427         struct arglist *arglist;
5428         {
5429         struct ifsregion *ifsp;
5430         struct strlist *sp;
5431         char *start;
5432         char *p;
5433         char *q;
5434         const char *ifs, *realifs;
5435         int ifsspc;
5436         int nulonly;
5437
5438
5439         start = string;
5440         ifsspc = 0;
5441         nulonly = 0;
5442         realifs = ifsset() ? ifsval() : defifs;
5443         if (ifslastp != NULL) {
5444                 ifsp = &ifsfirst;
5445                 do {
5446                         p = string + ifsp->begoff;
5447                         nulonly = ifsp->nulonly;
5448                         ifs = nulonly ? nullstr : realifs;
5449                         ifsspc = 0;
5450                         while (p < string + ifsp->endoff) {
5451                                 q = p;
5452                                 if (*p == CTLESC)
5453                                         p++;
5454                                 if (strchr(ifs, *p)) {
5455                                         if (!nulonly)
5456                                                 ifsspc = (strchr(defifs, *p) != NULL);
5457                                         /* Ignore IFS whitespace at start */
5458                                         if (q == start && ifsspc) {
5459                                                 p++;
5460                                                 start = p;
5461                                                 continue;
5462                                         }
5463                                         *q = '\0';
5464                                         sp = (struct strlist *)stalloc(sizeof *sp);
5465                                         sp->text = start;
5466                                         *arglist->lastp = sp;
5467                                         arglist->lastp = &sp->next;
5468                                         p++;
5469                                         if (!nulonly) {
5470                                                 for (;;) {
5471                                                         if (p >= string + ifsp->endoff) {
5472                                                                 break;
5473                                                         }
5474                                                         q = p;
5475                                                         if (*p == CTLESC)
5476                                                                 p++;
5477                                                         if (strchr(ifs, *p) == NULL ) {
5478                                                                 p = q;
5479                                                                 break;
5480                                                         } else if (strchr(defifs, *p) == NULL) {
5481                                                                 if (ifsspc) {
5482                                                                         p++;
5483                                                                         ifsspc = 0;
5484                                                                 } else {
5485                                                                         p = q;
5486                                                                         break;
5487                                                                 }
5488                                                         } else
5489                                                                 p++;
5490                                                 }
5491                                         }
5492                                         start = p;
5493                                 } else
5494                                         p++;
5495                         }
5496                 } while ((ifsp = ifsp->next) != NULL);
5497                 if (!(*start || (!ifsspc && start > string && nulonly))) {
5498                         return;
5499                 }
5500         }
5501
5502         sp = (struct strlist *)stalloc(sizeof *sp);
5503         sp->text = start;
5504         *arglist->lastp = sp;
5505         arglist->lastp = &sp->next;
5506 }
5507
5508 static void
5509 ifsfree()
5510 {
5511         while (ifsfirst.next != NULL) {
5512                 struct ifsregion *ifsp;
5513                 INTOFF;
5514                 ifsp = ifsfirst.next->next;
5515                 ckfree(ifsfirst.next);
5516                 ifsfirst.next = ifsp;
5517                 INTON;
5518         }
5519         ifslastp = NULL;
5520         ifsfirst.next = NULL;
5521 }
5522
5523 /*
5524  * Add a file name to the list.
5525  */
5526
5527 static void
5528 addfname(const char *name)
5529 {
5530         char *p;
5531         struct strlist *sp;
5532
5533         p = sstrdup(name);
5534         sp = (struct strlist *)stalloc(sizeof *sp);
5535         sp->text = p;
5536         *exparg.lastp = sp;
5537         exparg.lastp = &sp->next;
5538 }
5539
5540 /*
5541  * Expand shell metacharacters.  At this point, the only control characters
5542  * should be escapes.  The results are stored in the list exparg.
5543  */
5544
5545 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5546 static void
5547 expandmeta(str, flag)
5548         struct strlist *str;
5549         int flag;
5550 {
5551         const char *p;
5552         glob_t pglob;
5553         /* TODO - EXP_REDIR */
5554
5555         while (str) {
5556                 if (fflag)
5557                         goto nometa;
5558                 p = preglob(str->text);
5559                 INTOFF;
5560                 switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) {
5561                 case 0:
5562                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
5563                                 goto nometa2;
5564                         addglob(&pglob);
5565                         globfree(&pglob);
5566                         INTON;
5567                         break;
5568                 case GLOB_NOMATCH:
5569 nometa2:
5570                         globfree(&pglob);
5571                         INTON;
5572 nometa:
5573                         *exparg.lastp = str;
5574                         rmescapes(str->text);
5575                         exparg.lastp = &str->next;
5576                         break;
5577                 default:        /* GLOB_NOSPACE */
5578                         error("Out of space");
5579                 }
5580                 str = str->next;
5581         }
5582 }
5583
5584
5585 /*
5586  * Add the result of glob(3) to the list.
5587  */
5588
5589 static void
5590 addglob(pglob)
5591         const glob_t *pglob;
5592 {
5593         char **p = pglob->gl_pathv;
5594
5595         do {
5596                 addfname(*p);
5597         } while (*++p);
5598 }
5599
5600
5601 #else   /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5602 static char *expdir;
5603
5604
5605 static void
5606 expandmeta(str, flag)
5607         struct strlist *str;
5608         int flag;
5609 {
5610         char *p;
5611         struct strlist **savelastp;
5612         struct strlist *sp;
5613         char c;
5614         /* TODO - EXP_REDIR */
5615
5616         while (str) {
5617                 if (fflag)
5618                         goto nometa;
5619                 p = str->text;
5620                 for (;;) {                      /* fast check for meta chars */
5621                         if ((c = *p++) == '\0')
5622                                 goto nometa;
5623                         if (c == '*' || c == '?' || c == '[' || c == '!')
5624                                 break;
5625                 }
5626                 savelastp = exparg.lastp;
5627                 INTOFF;
5628                 if (expdir == NULL) {
5629                         int i = strlen(str->text);
5630                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5631                 }
5632
5633                 expmeta(expdir, str->text);
5634                 ckfree(expdir);
5635                 expdir = NULL;
5636                 INTON;
5637                 if (exparg.lastp == savelastp) {
5638                         /*
5639                          * no matches
5640                          */
5641 nometa:
5642                         *exparg.lastp = str;
5643                         rmescapes(str->text);
5644                         exparg.lastp = &str->next;
5645                 } else {
5646                         *exparg.lastp = NULL;
5647                         *savelastp = sp = expsort(*savelastp);
5648                         while (sp->next != NULL)
5649                                 sp = sp->next;
5650                         exparg.lastp = &sp->next;
5651                 }
5652                 str = str->next;
5653         }
5654 }
5655
5656
5657 /*
5658  * Do metacharacter (i.e. *, ?, [...]) expansion.
5659  */
5660
5661 static void
5662 expmeta(enddir, name)
5663         char *enddir;
5664         char *name;
5665         {
5666         char *p;
5667         const char *cp;
5668         char *q;
5669         char *start;
5670         char *endname;
5671         int metaflag;
5672         struct stat statb;
5673         DIR *dirp;
5674         struct dirent *dp;
5675         int atend;
5676         int matchdot;
5677
5678         metaflag = 0;
5679         start = name;
5680         for (p = name ; ; p++) {
5681                 if (*p == '*' || *p == '?')
5682                         metaflag = 1;
5683                 else if (*p == '[') {
5684                         q = p + 1;
5685                         if (*q == '!')
5686                                 q++;
5687                         for (;;) {
5688                                 while (*q == CTLQUOTEMARK)
5689                                         q++;
5690                                 if (*q == CTLESC)
5691                                         q++;
5692                                 if (*q == '/' || *q == '\0')
5693                                         break;
5694                                 if (*++q == ']') {
5695                                         metaflag = 1;
5696                                         break;
5697                                 }
5698                         }
5699                 } else if (*p == '!' && p[1] == '!'     && (p == name || p[-1] == '/')) {
5700                         metaflag = 1;
5701                 } else if (*p == '\0')
5702                         break;
5703                 else if (*p == CTLQUOTEMARK)
5704                         continue;
5705                 else if (*p == CTLESC)
5706                         p++;
5707                 if (*p == '/') {
5708                         if (metaflag)
5709                                 break;
5710                         start = p + 1;
5711                 }
5712         }
5713         if (metaflag == 0) {    /* we've reached the end of the file name */
5714                 if (enddir != expdir)
5715                         metaflag++;
5716                 for (p = name ; ; p++) {
5717                         if (*p == CTLQUOTEMARK)
5718                                 continue;
5719                         if (*p == CTLESC)
5720                                 p++;
5721                         *enddir++ = *p;
5722                         if (*p == '\0')
5723                                 break;
5724                 }
5725                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5726                         addfname(expdir);
5727                 return;
5728         }
5729         endname = p;
5730         if (start != name) {
5731                 p = name;
5732                 while (p < start) {
5733                         while (*p == CTLQUOTEMARK)
5734                                 p++;
5735                         if (*p == CTLESC)
5736                                 p++;
5737                         *enddir++ = *p++;
5738                 }
5739         }
5740         if (enddir == expdir) {
5741                 cp = ".";
5742         } else if (enddir == expdir + 1 && *expdir == '/') {
5743                 cp = "/";
5744         } else {
5745                 cp = expdir;
5746                 enddir[-1] = '\0';
5747         }
5748         if ((dirp = opendir(cp)) == NULL)
5749                 return;
5750         if (enddir != expdir)
5751                 enddir[-1] = '/';
5752         if (*endname == 0) {
5753                 atend = 1;
5754         } else {
5755                 atend = 0;
5756                 *endname++ = '\0';
5757         }
5758         matchdot = 0;
5759         p = start;
5760         while (*p == CTLQUOTEMARK)
5761                 p++;
5762         if (*p == CTLESC)
5763                 p++;
5764         if (*p == '.')
5765                 matchdot++;
5766         while (! int_pending() && (dp = readdir(dirp)) != NULL) {
5767                 if (dp->d_name[0] == '.' && ! matchdot)
5768                         continue;
5769                 if (patmatch(start, dp->d_name, 0)) {
5770                         if (atend) {
5771                                 strcpy(enddir, dp->d_name);
5772                                 addfname(expdir);
5773                         } else {
5774                                 for (p = enddir, cp = dp->d_name;
5775                                      (*p++ = *cp++) != '\0';)
5776                                         continue;
5777                                 p[-1] = '/';
5778                                 expmeta(p, endname);
5779                         }
5780                 }
5781         }
5782         closedir(dirp);
5783         if (! atend)
5784                 endname[-1] = '/';
5785 }
5786 #endif  /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5787
5788
5789
5790 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5791 /*
5792  * Sort the results of file name expansion.  It calculates the number of
5793  * strings to sort and then calls msort (short for merge sort) to do the
5794  * work.
5795  */
5796
5797 static struct strlist *
5798 expsort(str)
5799         struct strlist *str;
5800         {
5801         int len;
5802         struct strlist *sp;
5803
5804         len = 0;
5805         for (sp = str ; sp ; sp = sp->next)
5806                 len++;
5807         return msort(str, len);
5808 }
5809
5810
5811 static struct strlist *
5812 msort(list, len)
5813         struct strlist *list;
5814         int len;
5815 {
5816         struct strlist *p, *q = NULL;
5817         struct strlist **lpp;
5818         int half;
5819         int n;
5820
5821         if (len <= 1)
5822                 return list;
5823         half = len >> 1;
5824         p = list;
5825         for (n = half ; --n >= 0 ; ) {
5826                 q = p;
5827                 p = p->next;
5828         }
5829         q->next = NULL;                 /* terminate first half of list */
5830         q = msort(list, half);          /* sort first half of list */
5831         p = msort(p, len - half);               /* sort second half */
5832         lpp = &list;
5833         for (;;) {
5834                 if (strcmp(p->text, q->text) < 0) {
5835                         *lpp = p;
5836                         lpp = &p->next;
5837                         if ((p = *lpp) == NULL) {
5838                                 *lpp = q;
5839                                 break;
5840                         }
5841                 } else {
5842                         *lpp = q;
5843                         lpp = &q->next;
5844                         if ((q = *lpp) == NULL) {
5845                                 *lpp = p;
5846                                 break;
5847                         }
5848                 }
5849         }
5850         return list;
5851 }
5852 #endif
5853
5854
5855
5856 /*
5857  * Returns true if the pattern matches the string.
5858  */
5859
5860 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
5861 /* squoted: string might have quote chars */
5862 static int
5863 patmatch(char *pattern, char *string, int squoted)
5864 {
5865         const char *p;
5866         char *q;
5867
5868         p = preglob(pattern);
5869         q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5870
5871         return !fnmatch(p, q, 0);
5872 }
5873
5874
5875 static int
5876 patmatch2(char *pattern, char *string, int squoted)
5877 {
5878         char *p;
5879         int res;
5880
5881         sstrnleft--;
5882         p = grabstackstr(expdest);
5883         res = patmatch(pattern, string, squoted);
5884         ungrabstackstr(p, expdest);
5885         return res;
5886 }
5887 #else
5888 static int
5889 patmatch(char *pattern, char *string, int squoted) {
5890         return pmatch(pattern, string, squoted);
5891 }
5892
5893
5894 static int
5895 pmatch(char *pattern, char *string, int squoted)
5896 {
5897         char *p, *q;
5898         char c;
5899
5900         p = pattern;
5901         q = string;
5902         for (;;) {
5903                 switch (c = *p++) {
5904                 case '\0':
5905                         goto breakloop;
5906                 case CTLESC:
5907                         if (squoted && *q == CTLESC)
5908                                 q++;
5909                         if (*q++ != *p++)
5910                                 return 0;
5911                         break;
5912                 case CTLQUOTEMARK:
5913                         continue;
5914                 case '?':
5915                         if (squoted && *q == CTLESC)
5916                                 q++;
5917                         if (*q++ == '\0')
5918                                 return 0;
5919                         break;
5920                 case '*':
5921                         c = *p;
5922                         while (c == CTLQUOTEMARK || c == '*')
5923                                 c = *++p;
5924                         if (c != CTLESC &&  c != CTLQUOTEMARK &&
5925                             c != '?' && c != '*' && c != '[') {
5926                                 while (*q != c) {
5927                                         if (squoted && *q == CTLESC &&
5928                                             q[1] == c)
5929                                                 break;
5930                                         if (*q == '\0')
5931                                                 return 0;
5932                                         if (squoted && *q == CTLESC)
5933                                                 q++;
5934                                         q++;
5935                                 }
5936                         }
5937                         do {
5938                                 if (pmatch(p, q, squoted))
5939                                         return 1;
5940                                 if (squoted && *q == CTLESC)
5941                                         q++;
5942                         } while (*q++ != '\0');
5943                         return 0;
5944                 case '[': {
5945                         char *endp;
5946                         int invert, found;
5947                         char chr;
5948
5949                         endp = p;
5950                         if (*endp == '!')
5951                                 endp++;
5952                         for (;;) {
5953                                 while (*endp == CTLQUOTEMARK)
5954                                         endp++;
5955                                 if (*endp == '\0')
5956                                         goto dft;               /* no matching ] */
5957                                 if (*endp == CTLESC)
5958                                         endp++;
5959                                 if (*++endp == ']')
5960                                         break;
5961                         }
5962                         invert = 0;
5963                         if (*p == '!') {
5964                                 invert++;
5965                                 p++;
5966                         }
5967                         found = 0;
5968                         chr = *q++;
5969                         if (squoted && chr == CTLESC)
5970                                 chr = *q++;
5971                         if (chr == '\0')
5972                                 return 0;
5973                         c = *p++;
5974                         do {
5975                                 if (c == CTLQUOTEMARK)
5976                                         continue;
5977                                 if (c == CTLESC)
5978                                         c = *p++;
5979                                 if (*p == '-' && p[1] != ']') {
5980                                         p++;
5981                                         while (*p == CTLQUOTEMARK)
5982                                                 p++;
5983                                         if (*p == CTLESC)
5984                                                 p++;
5985                                         if (chr >= c && chr <= *p)
5986                                                 found = 1;
5987                                         p++;
5988                                 } else {
5989                                         if (chr == c)
5990                                                 found = 1;
5991                                 }
5992                         } while ((c = *p++) != ']');
5993                         if (found == invert)
5994                                 return 0;
5995                         break;
5996                 }
5997 dft:            default:
5998                         if (squoted && *q == CTLESC)
5999                                 q++;
6000                         if (*q++ != c)
6001                                 return 0;
6002                         break;
6003                 }
6004         }
6005 breakloop:
6006         if (*q != '\0')
6007                 return 0;
6008         return 1;
6009 }
6010 #endif
6011
6012
6013
6014 /*
6015  * Remove any CTLESC characters from a string.
6016  */
6017
6018 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
6019 static char *
6020 _rmescapes(char *str, int flag)
6021 {
6022         char *p, *q, *r;
6023         static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
6024
6025         p = strpbrk(str, qchars);
6026         if (!p) {
6027                 return str;
6028         }
6029         q = p;
6030         r = str;
6031         if (flag & RMESCAPE_ALLOC) {
6032                 size_t len = p - str;
6033                 q = r = stalloc(strlen(p) + len + 1);
6034                 if (len > 0) {
6035 #ifdef _GNU_SOURCE
6036                         q = mempcpy(q, str, len);
6037 #else
6038                         memcpy(q, str, len);
6039                         q += len;
6040 #endif
6041                 }
6042         }
6043         while (*p) {
6044                 if (*p == CTLQUOTEMARK) {
6045                         p++;
6046                         continue;
6047                 }
6048                 if (*p == CTLESC) {
6049                         p++;
6050                         if (flag & RMESCAPE_GLOB && *p != '/') {
6051                                 *q++ = '\\';
6052                         }
6053                 }
6054                 *q++ = *p++;
6055         }
6056         *q = '\0';
6057         return r;
6058 }
6059 #else
6060 static void
6061 rmescapes(str)
6062         char *str;
6063 {
6064         char *p, *q;
6065
6066         p = str;
6067         while (*p != CTLESC && *p != CTLQUOTEMARK) {
6068                 if (*p++ == '\0')
6069                         return;
6070         }
6071         q = p;
6072         while (*p) {
6073                 if (*p == CTLQUOTEMARK) {
6074                         p++;
6075                         continue;
6076                 }
6077                 if (*p == CTLESC)
6078                         p++;
6079                 *q++ = *p++;
6080         }
6081         *q = '\0';
6082 }
6083 #endif
6084
6085
6086
6087 /*
6088  * See if a pattern matches in a case statement.
6089  */
6090
6091 static int
6092 casematch(union node *pattern, const char *val)
6093 {
6094         struct stackmark smark;
6095         int result;
6096         char *p;
6097
6098         setstackmark(&smark);
6099         argbackq = pattern->narg.backquote;
6100         STARTSTACKSTR(expdest);
6101         ifslastp = NULL;
6102         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6103         STPUTC('\0', expdest);
6104         p = grabstackstr(expdest);
6105         result = patmatch(p, (char *)val, 0);
6106         popstackmark(&smark);
6107         return result;
6108 }
6109
6110 /*
6111  * Our own itoa().
6112  */
6113
6114 static char *
6115 cvtnum(num, buf)
6116         int num;
6117         char *buf;
6118         {
6119         int len;
6120
6121         CHECKSTRSPACE(32, buf);
6122         len = sprintf(buf, "%d", num);
6123         STADJUST(len, buf);
6124         return buf;
6125 }
6126 /*
6127  * Editline and history functions (and glue).
6128  */
6129 static int histcmd(argc, argv)
6130         int argc;
6131         char **argv;
6132 {
6133         error("not compiled with history support");
6134         /* NOTREACHED */
6135 }
6136
6137
6138 static int whichprompt;         /* 1 == PS1, 2 == PS2 */
6139
6140
6141 struct redirtab {
6142         struct redirtab *next;
6143         short renamed[10];
6144 };
6145
6146 static struct redirtab *redirlist;
6147
6148 extern char **environ;
6149
6150
6151
6152 /*
6153  * Initialization code.
6154  */
6155
6156 static void
6157 init(void) {
6158
6159       /* from cd.c: */
6160       {
6161               setpwd(0, 0);
6162       }
6163
6164       /* from input.c: */
6165       {
6166               basepf.nextc = basepf.buf = basebuf;
6167       }
6168
6169       /* from var.c: */
6170       {
6171               char **envp;
6172               char ppid[32];
6173
6174               initvar();
6175               for (envp = environ ; *envp ; envp++) {
6176                       if (strchr(*envp, '=')) {
6177                               setvareq(*envp, VEXPORT|VTEXTFIXED);
6178                       }
6179               }
6180
6181               snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
6182               setvar("PPID", ppid, 0);
6183       }
6184 }
6185
6186
6187
6188 /*
6189  * This routine is called when an error or an interrupt occurs in an
6190  * interactive shell and control is returned to the main command loop.
6191  */
6192
6193 #ifdef ASH_ALIAS
6194 /* 1 == check for aliases, 2 == also check for assignments */
6195 static int checkalias;
6196 #endif
6197
6198 static void
6199 reset(void) {
6200
6201       /* from eval.c: */
6202       {
6203               evalskip = 0;
6204               loopnest = 0;
6205               funcnest = 0;
6206       }
6207
6208       /* from input.c: */
6209       {
6210               if (exception != EXSHELLPROC)
6211                       parselleft = parsenleft = 0;      /* clear input buffer */
6212               popallfiles();
6213       }
6214
6215       /* from parser.c: */
6216       {
6217               tokpushback = 0;
6218               checkkwd = 0;
6219 #ifdef ASH_ALIAS
6220               checkalias = 0;
6221 #endif
6222       }
6223
6224       /* from redir.c: */
6225       {
6226               while (redirlist)
6227                       popredir();
6228       }
6229
6230 }
6231
6232
6233
6234 /*
6235  * This file implements the input routines used by the parser.
6236  */
6237
6238 #ifdef BB_FEATURE_COMMAND_EDITING
6239 unsigned int shell_context;
6240 static const char * cmdedit_prompt;
6241 static inline void putprompt(const char *s) {
6242     cmdedit_prompt = s;
6243 }
6244 #else
6245 static inline void putprompt(const char *s) {
6246     out2str(s);
6247 }
6248 #endif
6249
6250 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
6251
6252
6253
6254 /*
6255  * Same as pgetc(), but ignores PEOA.
6256  */
6257
6258 #ifdef ASH_ALIAS
6259 static int
6260 pgetc2()
6261 {
6262         int c;
6263         do {
6264                 c = pgetc_macro();
6265         } while (c == PEOA);
6266         return c;
6267 }
6268 #else
6269 static inline int pgetc2() { return pgetc_macro(); }
6270 #endif
6271
6272 /*
6273  * Read a line from the script.
6274  */
6275
6276 static char *
6277 pfgets(char *line, int len)
6278 {
6279         char *p = line;
6280         int nleft = len;
6281         int c;
6282
6283         while (--nleft > 0) {
6284                 c = pgetc2();
6285                 if (c == PEOF) {
6286                         if (p == line)
6287                                 return NULL;
6288                         break;
6289                 }
6290                 *p++ = c;
6291                 if (c == '\n')
6292                         break;
6293         }
6294         *p = '\0';
6295         return line;
6296 }
6297
6298 static int
6299 preadfd(void)
6300 {
6301     int nr;
6302     char *buf =  parsefile->buf;
6303     parsenextc = buf;
6304
6305 retry:
6306 #ifdef BB_FEATURE_COMMAND_EDITING
6307         {
6308             if (parsefile->fd)
6309                 nr = read(parsefile->fd, buf, BUFSIZ - 1);
6310             else {
6311                 do {
6312                     cmdedit_read_input((char*)cmdedit_prompt, buf);
6313                     nr = strlen(buf);
6314                 } while (nr <=0 || shell_context);
6315                 cmdedit_terminate();
6316             }
6317         }
6318 #else
6319         nr = read(parsefile->fd, buf, BUFSIZ - 1);
6320 #endif
6321
6322         if (nr < 0) {
6323                 if (errno == EINTR)
6324                         goto retry;
6325                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6326                         int flags = fcntl(0, F_GETFL, 0);
6327                         if (flags >= 0 && flags & O_NONBLOCK) {
6328                                 flags &=~ O_NONBLOCK;
6329                                 if (fcntl(0, F_SETFL, flags) >= 0) {
6330                                         out2str("sh: turning off NDELAY mode\n");
6331                                         goto retry;
6332                                 }
6333                         }
6334                 }
6335         }
6336         return nr;
6337 }
6338
6339 static void
6340 popstring(void)
6341 {
6342         struct strpush *sp = parsefile->strpush;
6343
6344         INTOFF;
6345 #ifdef ASH_ALIAS
6346         if (sp->ap) {
6347                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6348                         if (!checkalias) {
6349                                 checkalias = 1;
6350                         }
6351                 }
6352                 if (sp->string != sp->ap->val) {
6353                         ckfree(sp->string);
6354                 }
6355
6356                 sp->ap->flag &= ~ALIASINUSE;
6357                 if (sp->ap->flag & ALIASDEAD) {
6358                         unalias(sp->ap->name);
6359                 }
6360         }
6361 #endif
6362         parsenextc = sp->prevstring;
6363         parsenleft = sp->prevnleft;
6364 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6365         parsefile->strpush = sp->prev;
6366         if (sp != &(parsefile->basestrpush))
6367                 ckfree(sp);
6368         INTON;
6369 }
6370
6371
6372 /*
6373  * Refill the input buffer and return the next input character:
6374  *
6375  * 1) If a string was pushed back on the input, pop it;
6376  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6377  *    from a string so we can't refill the buffer, return EOF.
6378  * 3) If the is more stuff in this buffer, use it else call read to fill it.
6379  * 4) Process input up to the next newline, deleting nul characters.
6380  */
6381
6382 static int
6383 preadbuffer(void)
6384 {
6385         char *p, *q;
6386         int more;
6387         char savec;
6388
6389         while (parsefile->strpush) {
6390 #ifdef ASH_ALIAS
6391                 if (parsenleft == -1 && parsefile->strpush->ap &&
6392                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6393                         return PEOA;
6394                 }
6395 #endif
6396                 popstring();
6397                 if (--parsenleft >= 0)
6398                         return (*parsenextc++);
6399         }
6400         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6401                 return PEOF;
6402         flushall();
6403
6404 again:
6405         if (parselleft <= 0) {
6406                 if ((parselleft = preadfd()) <= 0) {
6407                         parselleft = parsenleft = EOF_NLEFT;
6408                         return PEOF;
6409                 }
6410         }
6411
6412         q = p = parsenextc;
6413
6414         /* delete nul characters */
6415         for (more = 1; more;) {
6416                 switch (*p) {
6417                 case '\0':
6418                         p++;    /* Skip nul */
6419                         goto check;
6420
6421
6422                 case '\n':
6423                         parsenleft = q - parsenextc;
6424                         more = 0; /* Stop processing here */
6425                         break;
6426                 }
6427
6428                 *q++ = *p++;
6429 check:
6430                 if (--parselleft <= 0 && more) {
6431                         parsenleft = q - parsenextc - 1;
6432                         if (parsenleft < 0)
6433                                 goto again;
6434                         more = 0;
6435                 }
6436         }
6437
6438         savec = *q;
6439         *q = '\0';
6440
6441         if (vflag) {
6442                 out2str(parsenextc);
6443         }
6444
6445         *q = savec;
6446
6447         return *parsenextc++;
6448 }
6449
6450
6451 /*
6452  * Push a string back onto the input at this current parsefile level.
6453  * We handle aliases this way.
6454  */
6455 static void
6456 pushstring(char *s, int len, void *ap)
6457 {
6458         struct strpush *sp;
6459
6460         INTOFF;
6461 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6462         if (parsefile->strpush) {
6463                 sp = ckmalloc(sizeof (struct strpush));
6464                 sp->prev = parsefile->strpush;
6465                 parsefile->strpush = sp;
6466         } else
6467                 sp = parsefile->strpush = &(parsefile->basestrpush);
6468         sp->prevstring = parsenextc;
6469         sp->prevnleft = parsenleft;
6470 #ifdef ASH_ALIAS
6471         sp->ap = (struct alias *)ap;
6472         if (ap) {
6473                 ((struct alias *)ap)->flag |= ALIASINUSE;
6474                 sp->string = s;
6475         }
6476 #endif
6477         parsenextc = s;
6478         parsenleft = len;
6479         INTON;
6480 }
6481
6482
6483
6484
6485 /*
6486  * Like setinputfile, but takes input from a string.
6487  */
6488
6489 static void
6490 setinputstring(string)
6491         char *string;
6492         {
6493         INTOFF;
6494         pushfile();
6495         parsenextc = string;
6496         parsenleft = strlen(string);
6497         parsefile->buf = NULL;
6498         plinno = 1;
6499         INTON;
6500 }
6501
6502
6503
6504 /*
6505  * To handle the "." command, a stack of input files is used.  Pushfile
6506  * adds a new entry to the stack and popfile restores the previous level.
6507  */
6508
6509 static void
6510 pushfile(void) {
6511         struct parsefile *pf;
6512
6513         parsefile->nleft = parsenleft;
6514         parsefile->lleft = parselleft;
6515         parsefile->nextc = parsenextc;
6516         parsefile->linno = plinno;
6517         pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6518         pf->prev = parsefile;
6519         pf->fd = -1;
6520         pf->strpush = NULL;
6521         pf->basestrpush.prev = NULL;
6522         parsefile = pf;
6523 }
6524
6525 #ifdef JOBS
6526 static void restartjob (struct job *);
6527 #endif
6528 static void freejob (struct job *);
6529 static struct job *getjob (const char *);
6530 static int dowait (int, struct job *);
6531 static int waitproc (int, int *);
6532 static void waitonint(int);
6533
6534
6535 /*
6536  * We keep track of whether or not fd0 has been redirected.  This is for
6537  * background commands, where we want to redirect fd0 to /dev/null only
6538  * if it hasn't already been redirected.
6539 */
6540 static int fd0_redirected = 0;
6541
6542 /* Return true if fd 0 has already been redirected at least once.  */
6543 static inline int
6544 fd0_redirected_p () {
6545         return fd0_redirected != 0;
6546 }
6547
6548 static int openredirect (union node *);
6549 static void dupredirect (union node *, int, char[10 ]);
6550 static int openhere (union node *);
6551 static int noclobberopen (const char *);
6552
6553
6554
6555 #ifdef JOBS
6556 /*
6557  * Turn job control on and off.
6558  *
6559  * Note:  This code assumes that the third arg to ioctl is a character
6560  * pointer, which is true on Berkeley systems but not System V.  Since
6561  * System V doesn't have job control yet, this isn't a problem now.
6562  */
6563
6564
6565
6566 static void setjobctl(int enable)
6567 {
6568 #ifdef OLD_TTY_DRIVER
6569         int ldisc;
6570 #endif
6571
6572         if (enable == jobctl || rootshell == 0)
6573                 return;
6574         if (enable) {
6575                 do { /* while we are in the background */
6576 #ifdef OLD_TTY_DRIVER
6577                         if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6578 #else
6579                         initialpgrp = tcgetpgrp(2);
6580                         if (initialpgrp < 0) {
6581 #endif
6582                                 out2str("sh: can't access tty; job cenabletrol turned off\n");
6583                                 mflag = 0;
6584                                 return;
6585                         }
6586                         if (initialpgrp == -1)
6587                                 initialpgrp = getpgrp();
6588                         else if (initialpgrp != getpgrp()) {
6589                                 killpg(initialpgrp, SIGTTIN);
6590                                 continue;
6591                         }
6592                 } while (0);
6593 #ifdef OLD_TTY_DRIVER
6594                 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6595                         out2str("sh: need new tty driver to run job cenabletrol; job cenabletrol turned off\n");
6596                         mflag = 0;
6597                         return;
6598                 }
6599 #endif
6600                 setsignal(SIGTSTP);
6601                 setsignal(SIGTTOU);
6602                 setsignal(SIGTTIN);
6603                 setpgid(0, rootpid);
6604 #ifdef OLD_TTY_DRIVER
6605                 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6606 #else
6607                 tcsetpgrp(2, rootpid);
6608 #endif
6609         } else { /* turning job cenabletrol off */
6610                 setpgid(0, initialpgrp);
6611 #ifdef OLD_TTY_DRIVER
6612                 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6613 #else
6614                 tcsetpgrp(2, initialpgrp);
6615 #endif
6616                 setsignal(SIGTSTP);
6617                 setsignal(SIGTTOU);
6618                 setsignal(SIGTTIN);
6619         }
6620         jobctl = enable;
6621 }
6622 #endif
6623
6624
6625 /* A translation list so we can be polite to our users. */
6626 static char *signal_names[NSIG + 2] = {
6627     "EXIT",
6628     "SIGHUP",
6629     "SIGINT",
6630     "SIGQUIT",
6631     "SIGILL",
6632     "SIGTRAP",
6633     "SIGABRT",
6634     "SIGBUS",
6635     "SIGFPE",
6636     "SIGKILL",
6637     "SIGUSR1",
6638     "SIGSEGV",
6639     "SIGUSR2",
6640     "SIGPIPE",
6641     "SIGALRM",
6642     "SIGTERM",
6643     "SIGJUNK(16)",
6644     "SIGCHLD",
6645     "SIGCONT",
6646     "SIGSTOP",
6647     "SIGTSTP",
6648     "SIGTTIN",
6649     "SIGTTOU",
6650     "SIGURG",
6651     "SIGXCPU",
6652     "SIGXFSZ",
6653     "SIGVTALRM",
6654     "SIGPROF",
6655     "SIGWINCH",
6656     "SIGIO",
6657     "SIGPWR",
6658     "SIGSYS",
6659     "SIGRTMIN",
6660     "SIGRTMIN+1",
6661     "SIGRTMIN+2",
6662     "SIGRTMIN+3",
6663     "SIGRTMIN+4",
6664     "SIGRTMIN+5",
6665     "SIGRTMIN+6",
6666     "SIGRTMIN+7",
6667     "SIGRTMIN+8",
6668     "SIGRTMIN+9",
6669     "SIGRTMIN+10",
6670     "SIGRTMIN+11",
6671     "SIGRTMIN+12",
6672     "SIGRTMIN+13",
6673     "SIGRTMIN+14",
6674     "SIGRTMIN+15",
6675     "SIGRTMAX-15",
6676     "SIGRTMAX-14",
6677     "SIGRTMAX-13",
6678     "SIGRTMAX-12",
6679     "SIGRTMAX-11",
6680     "SIGRTMAX-10",
6681     "SIGRTMAX-9",
6682     "SIGRTMAX-8",
6683     "SIGRTMAX-7",
6684     "SIGRTMAX-6",
6685     "SIGRTMAX-5",
6686     "SIGRTMAX-4",
6687     "SIGRTMAX-3",
6688     "SIGRTMAX-2",
6689     "SIGRTMAX-1",
6690     "SIGRTMAX",
6691     "DEBUG",
6692     (char *)0x0,
6693 };
6694
6695
6696
6697 #ifdef JOBS
6698 static int
6699 killcmd(argc, argv)
6700         int argc;
6701         char **argv;
6702 {
6703         int signo = -1;
6704         int list = 0;
6705         int i;
6706         pid_t pid;
6707         struct job *jp;
6708
6709         if (argc <= 1) {
6710 usage:
6711                 error(
6712 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6713 "kill -l [exitstatus]"
6714                 );
6715         }
6716
6717         if (*argv[1] == '-') {
6718                 signo = decode_signal(argv[1] + 1, 1);
6719                 if (signo < 0) {
6720                         int c;
6721
6722                         while ((c = nextopt("ls:")) != '\0')
6723                                 switch (c) {
6724                                 case 'l':
6725                                         list = 1;
6726                                         break;
6727                                 case 's':
6728                                         signo = decode_signal(optionarg, 1);
6729                                         if (signo < 0) {
6730                                                 error(
6731                                                         "invalid signal number or name: %s",
6732                                                         optionarg
6733                                                 );
6734                                         }
6735                                         break;
6736 #ifdef DEBUG
6737                                 default:
6738                                         error(
6739         "nextopt returned character code 0%o", c);
6740 #endif
6741                         }
6742                 } else
6743                         argptr++;
6744         }
6745
6746         if (!list && signo < 0)
6747                 signo = SIGTERM;
6748
6749         if ((signo < 0 || !*argptr) ^ list) {
6750                 goto usage;
6751         }
6752
6753         if (list) {
6754                 if (!*argptr) {
6755                         out1str("0\n");
6756                         for (i = 1; i < NSIG; i++) {
6757                                 out1fmt(snlfmt, signal_names[i] + 3);
6758                         }
6759                         return 0;
6760                 }
6761                 signo = atoi(*argptr);
6762                 if (signo > 128)
6763                         signo -= 128;
6764                 if (0 < signo && signo < NSIG)
6765                                 out1fmt(snlfmt, signal_names[signo] + 3);
6766                 else
6767                         error("invalid signal number or exit status: %s",
6768                               *argptr);
6769                 return 0;
6770         }
6771
6772         do {
6773                 if (**argptr == '%') {
6774                         jp = getjob(*argptr);
6775                         if (jp->jobctl == 0)
6776                                 error("job %s not created under job control",
6777                                       *argptr);
6778                         pid = -jp->ps[0].pid;
6779                 } else
6780                         pid = atoi(*argptr);
6781                 if (kill(pid, signo) != 0)
6782                         error("%s: %m", *argptr);
6783         } while (*++argptr);
6784
6785         return 0;
6786 }
6787
6788 static int
6789 fgcmd(argc, argv)
6790         int argc;
6791         char **argv;
6792 {
6793         struct job *jp;
6794         int pgrp;
6795         int status;
6796
6797         jp = getjob(argv[1]);
6798         if (jp->jobctl == 0)
6799                 error("job not created under job control");
6800         pgrp = jp->ps[0].pid;
6801 #ifdef OLD_TTY_DRIVER
6802         ioctl(2, TIOCSPGRP, (char *)&pgrp);
6803 #else
6804         tcsetpgrp(2, pgrp);
6805 #endif
6806         restartjob(jp);
6807         INTOFF;
6808         status = waitforjob(jp);
6809         INTON;
6810         return status;
6811 }
6812
6813
6814 static int
6815 bgcmd(argc, argv)
6816         int argc;
6817         char **argv;
6818 {
6819         struct job *jp;
6820
6821         do {
6822                 jp = getjob(*++argv);
6823                 if (jp->jobctl == 0)
6824                         error("job not created under job control");
6825                 restartjob(jp);
6826         } while (--argc > 1);
6827         return 0;
6828 }
6829
6830
6831 static void
6832 restartjob(jp)
6833         struct job *jp;
6834 {
6835         struct procstat *ps;
6836         int i;
6837
6838         if (jp->state == JOBDONE)
6839                 return;
6840         INTOFF;
6841         killpg(jp->ps[0].pid, SIGCONT);
6842         for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6843                 if (WIFSTOPPED(ps->status)) {
6844                         ps->status = -1;
6845                         jp->state = 0;
6846                 }
6847         }
6848         INTON;
6849 }
6850 #endif
6851
6852 static void showjobs(int change);
6853
6854
6855 static int
6856 jobscmd(argc, argv)
6857         int argc;
6858         char **argv;
6859 {
6860         showjobs(0);
6861         return 0;
6862 }
6863
6864
6865 /*
6866  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6867  * statuses have changed since the last call to showjobs.
6868  *
6869  * If the shell is interrupted in the process of creating a job, the
6870  * result may be a job structure containing zero processes.  Such structures
6871  * will be freed here.
6872  */
6873
6874 static void
6875 showjobs(change)
6876         int change;
6877 {
6878         int jobno;
6879         int procno;
6880         int i;
6881         struct job *jp;
6882         struct procstat *ps;
6883         int col;
6884         char s[64];
6885
6886         TRACE(("showjobs(%d) called\n", change));
6887         while (dowait(0, (struct job *)NULL) > 0);
6888         for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6889                 if (! jp->used)
6890                         continue;
6891                 if (jp->nprocs == 0) {
6892                         freejob(jp);
6893                         continue;
6894                 }
6895                 if (change && ! jp->changed)
6896                         continue;
6897                 procno = jp->nprocs;
6898                 for (ps = jp->ps ; ; ps++) {    /* for each process */
6899                         if (ps == jp->ps)
6900                                 snprintf(s, 64, "[%d] %ld ", jobno,
6901                                     (long)ps->pid);
6902                         else
6903                                 snprintf(s, 64, "    %ld ",
6904                                     (long)ps->pid);
6905                         out1str(s);
6906                         col = strlen(s);
6907                         s[0] = '\0';
6908                         if (ps->status == -1) {
6909                                 /* don't print anything */
6910                         } else if (WIFEXITED(ps->status)) {
6911                                 snprintf(s, 64, "Exit %d",
6912                                        WEXITSTATUS(ps->status));
6913                         } else {
6914 #ifdef JOBS
6915                                 if (WIFSTOPPED(ps->status))
6916                                         i = WSTOPSIG(ps->status);
6917                                 else /* WIFSIGNALED(ps->status) */
6918 #endif
6919                                         i = WTERMSIG(ps->status);
6920                                 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6921                                         strcpy(s, sys_siglist[i & 0x7F]);
6922                                 else
6923                                         snprintf(s, 64, "Signal %d", i & 0x7F);
6924                                 if (WCOREDUMP(ps->status))
6925                                         strcat(s, " (core dumped)");
6926                         }
6927                         out1str(s);
6928                         col += strlen(s);
6929                         out1fmt(
6930                                 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6931                                 ps->cmd
6932                         );
6933                         if (--procno <= 0)
6934                                 break;
6935                 }
6936                 jp->changed = 0;
6937                 if (jp->state == JOBDONE) {
6938                         freejob(jp);
6939                 }
6940         }
6941 }
6942
6943
6944 /*
6945  * Mark a job structure as unused.
6946  */
6947
6948 static void
6949 freejob(jp)
6950         struct job *jp;
6951         {
6952         struct procstat *ps;
6953         int i;
6954
6955         INTOFF;
6956         for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6957                 if (ps->cmd != nullstr)
6958                         ckfree(ps->cmd);
6959         }
6960         if (jp->ps != &jp->ps0)
6961                 ckfree(jp->ps);
6962         jp->used = 0;
6963 #ifdef JOBS
6964         if (curjob == jp - jobtab + 1)
6965                 curjob = 0;
6966 #endif
6967         INTON;
6968 }
6969
6970
6971
6972 static int
6973 waitcmd(argc, argv)
6974         int argc;
6975         char **argv;
6976 {
6977         struct job *job;
6978         int status, retval;
6979         struct job *jp;
6980
6981         if (--argc > 0) {
6982 start:
6983                 job = getjob(*++argv);
6984         } else {
6985                 job = NULL;
6986         }
6987         for (;;) {      /* loop until process terminated or stopped */
6988                 if (job != NULL) {
6989                         if (job->state) {
6990                                 status = job->ps[job->nprocs - 1].status;
6991                                 if (! iflag)
6992                                         freejob(job);
6993                                 if (--argc) {
6994                                         goto start;
6995                                 }
6996                                 if (WIFEXITED(status))
6997                                         retval = WEXITSTATUS(status);
6998 #ifdef JOBS
6999                                 else if (WIFSTOPPED(status))
7000                                         retval = WSTOPSIG(status) + 128;
7001 #endif
7002                                 else {
7003                                         /* XXX: limits number of signals */
7004                                         retval = WTERMSIG(status) + 128;
7005                                 }
7006                                 return retval;
7007                         }
7008                 } else {
7009                         for (jp = jobtab ; ; jp++) {
7010                                 if (jp >= jobtab + njobs) {     /* no running procs */
7011                                         return 0;
7012                                 }
7013                                 if (jp->used && jp->state == 0)
7014                                         break;
7015                         }
7016                 }
7017                 if (dowait(2, 0) < 0 && errno == EINTR) {
7018                         return 129;
7019                 }
7020         }
7021 }
7022
7023
7024
7025 /*
7026  * Convert a job name to a job structure.
7027  */
7028
7029 static struct job *
7030 getjob(const char *name)
7031 {
7032         int jobno;
7033         struct job *jp;
7034         int pid;
7035         int i;
7036
7037         if (name == NULL) {
7038 #ifdef JOBS
7039 currentjob:
7040                 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
7041                         error("No current job");
7042                 return &jobtab[jobno - 1];
7043 #else
7044                 error("No current job");
7045 #endif
7046         } else if (name[0] == '%') {
7047                 if (is_digit(name[1])) {
7048                         jobno = number(name + 1);
7049                         if (jobno > 0 && jobno <= njobs
7050                          && jobtab[jobno - 1].used != 0)
7051                                 return &jobtab[jobno - 1];
7052 #ifdef JOBS
7053                 } else if (name[1] == '%' && name[2] == '\0') {
7054                         goto currentjob;
7055 #endif
7056                 } else {
7057                         struct job *found = NULL;
7058                         for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
7059                                 if (jp->used && jp->nprocs > 0
7060                                  && prefix(name + 1, jp->ps[0].cmd)) {
7061                                         if (found)
7062                                                 error("%s: ambiguous", name);
7063                                         found = jp;
7064                                 }
7065                         }
7066                         if (found)
7067                                 return found;
7068                 }
7069         } else if (is_number(name, &pid)) {
7070                 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
7071                         if (jp->used && jp->nprocs > 0
7072                          && jp->ps[jp->nprocs - 1].pid == pid)
7073                                 return jp;
7074                 }
7075         }
7076         error("No such job: %s", name);
7077         /* NOTREACHED */
7078 }
7079
7080
7081
7082 /*
7083  * Return a new job structure,
7084  */
7085
7086 static struct job *
7087 makejob(node, nprocs)
7088         union node *node;
7089         int nprocs;
7090 {
7091         int i;
7092         struct job *jp;
7093
7094         for (i = njobs, jp = jobtab ; ; jp++) {
7095                 if (--i < 0) {
7096                         INTOFF;
7097                         if (njobs == 0) {
7098                                 jobtab = ckmalloc(4 * sizeof jobtab[0]);
7099                         } else {
7100                                 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
7101                                 memcpy(jp, jobtab, njobs * sizeof jp[0]);
7102                                 /* Relocate `ps' pointers */
7103                                 for (i = 0; i < njobs; i++)
7104                                         if (jp[i].ps == &jobtab[i].ps0)
7105                                                 jp[i].ps = &jp[i].ps0;
7106                                 ckfree(jobtab);
7107                                 jobtab = jp;
7108                         }
7109                         jp = jobtab + njobs;
7110                         for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
7111                         INTON;
7112                         break;
7113                 }
7114                 if (jp->used == 0)
7115                         break;
7116         }
7117         INTOFF;
7118         jp->state = 0;
7119         jp->used = 1;
7120         jp->changed = 0;
7121         jp->nprocs = 0;
7122 #ifdef JOBS
7123         jp->jobctl = jobctl;
7124 #endif
7125         if (nprocs > 1) {
7126                 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7127         } else {
7128                 jp->ps = &jp->ps0;
7129         }
7130         INTON;
7131         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7132             jp - jobtab + 1));
7133         return jp;
7134 }
7135
7136
7137 /*
7138  * Fork of a subshell.  If we are doing job control, give the subshell its
7139  * own process group.  Jp is a job structure that the job is to be added to.
7140  * N is the command that will be evaluated by the child.  Both jp and n may
7141  * be NULL.  The mode parameter can be one of the following:
7142  *      FORK_FG - Fork off a foreground process.
7143  *      FORK_BG - Fork off a background process.
7144  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
7145  *                   process group even if job control is on.
7146  *
7147  * When job control is turned off, background processes have their standard
7148  * input redirected to /dev/null (except for the second and later processes
7149  * in a pipeline).
7150  */
7151
7152
7153
7154 static int
7155 forkshell(struct job *jp, union node *n, int mode)
7156 {
7157         int pid;
7158         int pgrp;
7159         const char *devnull = _PATH_DEVNULL;
7160         const char *nullerr = "Can't open %s";
7161
7162         TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
7163             mode));
7164         INTOFF;
7165         pid = fork();
7166         if (pid == -1) {
7167                 TRACE(("Fork failed, errno=%d\n", errno));
7168                 INTON;
7169                 error("Cannot fork");
7170         }
7171         if (pid == 0) {
7172                 struct job *p;
7173                 int wasroot;
7174                 int i;
7175
7176                 TRACE(("Child shell %d\n", getpid()));
7177                 wasroot = rootshell;
7178                 rootshell = 0;
7179                 closescript();
7180                 INTON;
7181                 clear_traps();
7182 #ifdef JOBS
7183                 jobctl = 0;             /* do job control only in root shell */
7184                 if (wasroot && mode != FORK_NOJOB && mflag) {
7185                         if (jp == NULL || jp->nprocs == 0)
7186                                 pgrp = getpid();
7187                         else
7188                                 pgrp = jp->ps[0].pid;
7189                         setpgid(0, pgrp);
7190                         if (mode == FORK_FG) {
7191                                 /*** this causes superfluous TIOCSPGRPS ***/
7192 #ifdef OLD_TTY_DRIVER
7193                                 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
7194                                         error("TIOCSPGRP failed, errno=%d", errno);
7195 #else
7196                                 if (tcsetpgrp(2, pgrp) < 0)
7197                                         error("tcsetpgrp failed, errno=%d", errno);
7198 #endif
7199                         }
7200                         setsignal(SIGTSTP);
7201                         setsignal(SIGTTOU);
7202                 } else if (mode == FORK_BG) {
7203                         ignoresig(SIGINT);
7204                         ignoresig(SIGQUIT);
7205                         if ((jp == NULL || jp->nprocs == 0) &&
7206                             ! fd0_redirected_p ()) {
7207                                 close(0);
7208                                 if (open(devnull, O_RDONLY) != 0)
7209                                         error(nullerr, devnull);
7210                         }
7211                 }
7212 #else
7213                 if (mode == FORK_BG) {
7214                         ignoresig(SIGINT);
7215                         ignoresig(SIGQUIT);
7216                         if ((jp == NULL || jp->nprocs == 0) &&
7217                             ! fd0_redirected_p ()) {
7218                                 close(0);
7219                                 if (open(devnull, O_RDONLY) != 0)
7220                                         error(nullerr, devnull);
7221                         }
7222                 }
7223 #endif
7224                 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
7225                         if (p->used)
7226                                 freejob(p);
7227                 if (wasroot && iflag) {
7228                         setsignal(SIGINT);
7229                         setsignal(SIGQUIT);
7230                         setsignal(SIGTERM);
7231                 }
7232                 return pid;
7233         }
7234         if (rootshell && mode != FORK_NOJOB && mflag) {
7235                 if (jp == NULL || jp->nprocs == 0)
7236                         pgrp = pid;
7237                 else
7238                         pgrp = jp->ps[0].pid;
7239                 setpgid(pid, pgrp);
7240         }
7241         if (mode == FORK_BG)
7242                 backgndpid = pid;               /* set $! */
7243         if (jp) {
7244                 struct procstat *ps = &jp->ps[jp->nprocs++];
7245                 ps->pid = pid;
7246                 ps->status = -1;
7247                 ps->cmd = nullstr;
7248                 if (iflag && rootshell && n)
7249                         ps->cmd = commandtext(n);
7250         }
7251         INTON;
7252         TRACE(("In parent shell:  child = %d\n", pid));
7253         return pid;
7254 }
7255
7256
7257
7258 /*
7259  * Wait for job to finish.
7260  *
7261  * Under job control we have the problem that while a child process is
7262  * running interrupts generated by the user are sent to the child but not
7263  * to the shell.  This means that an infinite loop started by an inter-
7264  * active user may be hard to kill.  With job control turned off, an
7265  * interactive user may place an interactive program inside a loop.  If
7266  * the interactive program catches interrupts, the user doesn't want
7267  * these interrupts to also abort the loop.  The approach we take here
7268  * is to have the shell ignore interrupt signals while waiting for a
7269  * forground process to terminate, and then send itself an interrupt
7270  * signal if the child process was terminated by an interrupt signal.
7271  * Unfortunately, some programs want to do a bit of cleanup and then
7272  * exit on interrupt; unless these processes terminate themselves by
7273  * sending a signal to themselves (instead of calling exit) they will
7274  * confuse this approach.
7275  */
7276
7277 static int
7278 waitforjob(jp)
7279         struct job *jp;
7280         {
7281 #ifdef JOBS
7282         int mypgrp = getpgrp();
7283 #endif
7284         int status;
7285         int st;
7286         struct sigaction act, oact;
7287
7288         INTOFF;
7289         intreceived = 0;
7290 #ifdef JOBS
7291         if (!jobctl) {
7292 #else
7293         if (!iflag) {
7294 #endif
7295                 sigaction(SIGINT, 0, &act);
7296                 act.sa_handler = waitonint;
7297                 sigaction(SIGINT, &act, &oact);
7298         }
7299         TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7300         while (jp->state == 0) {
7301                 dowait(1, jp);
7302         }
7303 #ifdef JOBS
7304         if (!jobctl) {
7305 #else
7306         if (!iflag) {
7307 #endif
7308                 sigaction(SIGINT, &oact, 0);
7309                 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7310         }
7311 #ifdef JOBS
7312         if (jp->jobctl) {
7313 #ifdef OLD_TTY_DRIVER
7314                 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7315                         error("TIOCSPGRP failed, errno=%d\n", errno);
7316 #else
7317                 if (tcsetpgrp(2, mypgrp) < 0)
7318                         error("tcsetpgrp failed, errno=%d\n", errno);
7319 #endif
7320         }
7321         if (jp->state == JOBSTOPPED)
7322                 curjob = jp - jobtab + 1;
7323 #endif
7324         status = jp->ps[jp->nprocs - 1].status;
7325         /* convert to 8 bits */
7326         if (WIFEXITED(status))
7327                 st = WEXITSTATUS(status);
7328 #ifdef JOBS
7329         else if (WIFSTOPPED(status))
7330                 st = WSTOPSIG(status) + 128;
7331 #endif
7332         else
7333                 st = WTERMSIG(status) + 128;
7334 #ifdef JOBS
7335         if (jp->jobctl) {
7336                 /*
7337                  * This is truly gross.
7338                  * If we're doing job control, then we did a TIOCSPGRP which
7339                  * caused us (the shell) to no longer be in the controlling
7340                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
7341                  * intuit from the subprocess exit status whether a SIGINT
7342                  * occured, and if so interrupt ourselves.  Yuck.  - mycroft
7343                  */
7344                 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7345                         raise(SIGINT);
7346         }
7347         if (jp->state == JOBDONE)
7348
7349 #endif
7350                 freejob(jp);
7351         INTON;
7352         return st;
7353 }
7354
7355
7356
7357 /*
7358  * Wait for a process to terminate.
7359  */
7360
7361 static int
7362 dowait(block, job)
7363         int block;
7364         struct job *job;
7365 {
7366         int pid;
7367         int status;
7368         struct procstat *sp;
7369         struct job *jp;
7370         struct job *thisjob;
7371         int done;
7372         int stopped;
7373         int core;
7374         int sig;
7375
7376         TRACE(("dowait(%d) called\n", block));
7377         do {
7378                 pid = waitproc(block, &status);
7379                 TRACE(("wait returns %d, status=%d\n", pid, status));
7380         } while (!(block & 2) && pid == -1 && errno == EINTR);
7381         if (pid <= 0)
7382                 return pid;
7383         INTOFF;
7384         thisjob = NULL;
7385         for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7386                 if (jp->used) {
7387                         done = 1;
7388                         stopped = 1;
7389                         for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7390                                 if (sp->pid == -1)
7391                                         continue;
7392                                 if (sp->pid == pid) {
7393                                         TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7394                                         sp->status = status;
7395                                         thisjob = jp;
7396                                 }
7397                                 if (sp->status == -1)
7398                                         stopped = 0;
7399                                 else if (WIFSTOPPED(sp->status))
7400                                         done = 0;
7401                         }
7402                         if (stopped) {          /* stopped or done */
7403                                 int state = done? JOBDONE : JOBSTOPPED;
7404                                 if (jp->state != state) {
7405                                         TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7406                                         jp->state = state;
7407 #ifdef JOBS
7408                                         if (done && curjob == jp - jobtab + 1)
7409                                                 curjob = 0;             /* no current job */
7410 #endif
7411                                 }
7412                         }
7413                 }
7414         }
7415         INTON;
7416         if (! rootshell || ! iflag || (job && thisjob == job)) {
7417                 core = WCOREDUMP(status);
7418 #ifdef JOBS
7419                 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7420                 else
7421 #endif
7422                 if (WIFEXITED(status)) sig = 0;
7423                 else sig = WTERMSIG(status);
7424
7425                 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7426                         if (thisjob != job)
7427                                 out2fmt("%d: ", pid);
7428 #ifdef JOBS
7429                         if (sig == SIGTSTP && rootshell && iflag)
7430                                 out2fmt("%%%ld ",
7431                                     (long)(job - jobtab + 1));
7432 #endif
7433                         if (sig < NSIG && sys_siglist[sig])
7434                                 out2str(sys_siglist[sig]);
7435                         else
7436                                 out2fmt("Signal %d", sig);
7437                         if (core)
7438                                 out2str(" - core dumped");
7439                         out2c('\n');
7440                 } else {
7441                         TRACE(("Not printing status: status=%d, sig=%d\n",
7442                                status, sig));
7443                 }
7444         } else {
7445                 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7446                 if (thisjob)
7447                         thisjob->changed = 1;
7448         }
7449         return pid;
7450 }
7451
7452
7453
7454 /*
7455  * Do a wait system call.  If job control is compiled in, we accept
7456  * stopped processes.  If block is zero, we return a value of zero
7457  * rather than blocking.
7458  *
7459  * System V doesn't have a non-blocking wait system call.  It does
7460  * have a SIGCLD signal that is sent to a process when one of it's
7461  * children dies.  The obvious way to use SIGCLD would be to install
7462  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7463  * was received, and have waitproc bump another counter when it got
7464  * the status of a process.  Waitproc would then know that a wait
7465  * system call would not block if the two counters were different.
7466  * This approach doesn't work because if a process has children that
7467  * have not been waited for, System V will send it a SIGCLD when it
7468  * installs a signal handler for SIGCLD.  What this means is that when
7469  * a child exits, the shell will be sent SIGCLD signals continuously
7470  * until is runs out of stack space, unless it does a wait call before
7471  * restoring the signal handler.  The code below takes advantage of
7472  * this (mis)feature by installing a signal handler for SIGCLD and
7473  * then checking to see whether it was called.  If there are any
7474  * children to be waited for, it will be.
7475  *
7476  */
7477
7478 static int
7479 waitproc(block, status)
7480         int block;
7481         int *status;
7482 {
7483         int flags;
7484
7485         flags = 0;
7486 #ifdef JOBS
7487         if (jobctl)
7488                 flags |= WUNTRACED;
7489 #endif
7490         if (block == 0)
7491                 flags |= WNOHANG;
7492         return wait3(status, flags, (struct rusage *)NULL);
7493 }
7494
7495 /*
7496  * return 1 if there are stopped jobs, otherwise 0
7497  */
7498 static int
7499 stoppedjobs(void)
7500 {
7501         int jobno;
7502         struct job *jp;
7503
7504         if (job_warning)
7505                 return (0);
7506         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7507                 if (jp->used == 0)
7508                         continue;
7509                 if (jp->state == JOBSTOPPED) {
7510                         out2str("You have stopped jobs.\n");
7511                         job_warning = 2;
7512                         return (1);
7513                 }
7514         }
7515
7516         return (0);
7517 }
7518
7519 /*
7520  * Return a string identifying a command (to be printed by the
7521  * jobs command.
7522  */
7523
7524 static char *cmdnextc;
7525 static int cmdnleft;
7526 #define MAXCMDTEXT      200
7527
7528 static void
7529 cmdputs(const char *s)
7530 {
7531         const char *p;
7532         char *q;
7533         char c;
7534         int subtype = 0;
7535
7536         if (cmdnleft <= 0)
7537                 return;
7538         p = s;
7539         q = cmdnextc;
7540         while ((c = *p++) != '\0') {
7541                 if (c == CTLESC)
7542                         *q++ = *p++;
7543                 else if (c == CTLVAR) {
7544                         *q++ = '$';
7545                         if (--cmdnleft > 0)
7546                                 *q++ = '{';
7547                         subtype = *p++;
7548                 } else if (c == '=' && subtype != 0) {
7549                         *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7550                         subtype = 0;
7551                 } else if (c == CTLENDVAR) {
7552                         *q++ = '}';
7553                 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7554                         cmdnleft++;             /* ignore it */
7555                 else
7556                         *q++ = c;
7557                 if (--cmdnleft <= 0) {
7558                         *q++ = '.';
7559                         *q++ = '.';
7560                         *q++ = '.';
7561                         break;
7562                 }
7563         }
7564         cmdnextc = q;
7565 }
7566
7567
7568 static void
7569 cmdtxt(const union node *n)
7570 {
7571         union node *np;
7572         struct nodelist *lp;
7573         const char *p;
7574         int i;
7575         char s[2];
7576
7577         if (n == NULL)
7578                 return;
7579         switch (n->type) {
7580         case NSEMI:
7581                 cmdtxt(n->nbinary.ch1);
7582                 cmdputs("; ");
7583                 cmdtxt(n->nbinary.ch2);
7584                 break;
7585         case NAND:
7586                 cmdtxt(n->nbinary.ch1);
7587                 cmdputs(" && ");
7588                 cmdtxt(n->nbinary.ch2);
7589                 break;
7590         case NOR:
7591                 cmdtxt(n->nbinary.ch1);
7592                 cmdputs(" || ");
7593                 cmdtxt(n->nbinary.ch2);
7594                 break;
7595         case NPIPE:
7596                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7597                         cmdtxt(lp->n);
7598                         if (lp->next)
7599                                 cmdputs(" | ");
7600                 }
7601                 break;
7602         case NSUBSHELL:
7603                 cmdputs("(");
7604                 cmdtxt(n->nredir.n);
7605                 cmdputs(")");
7606                 break;
7607         case NREDIR:
7608         case NBACKGND:
7609                 cmdtxt(n->nredir.n);
7610                 break;
7611         case NIF:
7612                 cmdputs("if ");
7613                 cmdtxt(n->nif.test);
7614                 cmdputs("; then ");
7615                 cmdtxt(n->nif.ifpart);
7616                 cmdputs("...");
7617                 break;
7618         case NWHILE:
7619                 cmdputs("while ");
7620                 goto until;
7621         case NUNTIL:
7622                 cmdputs("until ");
7623 until:
7624                 cmdtxt(n->nbinary.ch1);
7625                 cmdputs("; do ");
7626                 cmdtxt(n->nbinary.ch2);
7627                 cmdputs("; done");
7628                 break;
7629         case NFOR:
7630                 cmdputs("for ");
7631                 cmdputs(n->nfor.var);
7632                 cmdputs(" in ...");
7633                 break;
7634         case NCASE:
7635                 cmdputs("case ");
7636                 cmdputs(n->ncase.expr->narg.text);
7637                 cmdputs(" in ...");
7638                 break;
7639         case NDEFUN:
7640                 cmdputs(n->narg.text);
7641                 cmdputs("() ...");
7642                 break;
7643         case NCMD:
7644                 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7645                         cmdtxt(np);
7646                         if (np->narg.next)
7647                                 cmdputs(spcstr);
7648                 }
7649                 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7650                         cmdputs(spcstr);
7651                         cmdtxt(np);
7652                 }
7653                 break;
7654         case NARG:
7655                 cmdputs(n->narg.text);
7656                 break;
7657         case NTO:
7658                 p = ">";  i = 1;  goto redir;
7659         case NAPPEND:
7660                 p = ">>";  i = 1;  goto redir;
7661         case NTOFD:
7662                 p = ">&";  i = 1;  goto redir;
7663         case NTOOV:
7664                 p = ">|";  i = 1;  goto redir;
7665         case NFROM:
7666                 p = "<";  i = 0;  goto redir;
7667         case NFROMFD:
7668                 p = "<&";  i = 0;  goto redir;
7669         case NFROMTO:
7670                 p = "<>";  i = 0;  goto redir;
7671 redir:
7672                 if (n->nfile.fd != i) {
7673                         s[0] = n->nfile.fd + '0';
7674                         s[1] = '\0';
7675                         cmdputs(s);
7676                 }
7677                 cmdputs(p);
7678                 if (n->type == NTOFD || n->type == NFROMFD) {
7679                         s[0] = n->ndup.dupfd + '0';
7680                         s[1] = '\0';
7681                         cmdputs(s);
7682                 } else {
7683                         cmdtxt(n->nfile.fname);
7684                 }
7685                 break;
7686         case NHERE:
7687         case NXHERE:
7688                 cmdputs("<<...");
7689                 break;
7690         default:
7691                 cmdputs("???");
7692                 break;
7693         }
7694 }
7695
7696
7697 static char *
7698 commandtext(const union node *n)
7699 {
7700         char *name;
7701
7702         cmdnextc = name = ckmalloc(MAXCMDTEXT);
7703         cmdnleft = MAXCMDTEXT - 4;
7704         cmdtxt(n);
7705         *cmdnextc = '\0';
7706         return name;
7707 }
7708
7709
7710 static void waitonint(int sig) {
7711         intreceived = 1;
7712         return;
7713 }
7714 /*
7715  * Routines to check for mail.  (Perhaps make part of main.c?)
7716  */
7717
7718
7719 #define MAXMBOXES 10
7720
7721
7722 static int nmboxes;                     /* number of mailboxes */
7723 static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
7724
7725
7726
7727 /*
7728  * Print appropriate message(s) if mail has arrived.  If the argument is
7729  * nozero, then the value of MAIL has changed, so we just update the
7730  * values.
7731  */
7732
7733 static void
7734 chkmail(int silent)
7735 {
7736         int i;
7737         const char *mpath;
7738         char *p;
7739         char *q;
7740         struct stackmark smark;
7741         struct stat statb;
7742
7743         if (silent)
7744                 nmboxes = 10;
7745         if (nmboxes == 0)
7746                 return;
7747         setstackmark(&smark);
7748         mpath = mpathset()? mpathval() : mailval();
7749         for (i = 0 ; i < nmboxes ; i++) {
7750                 p = padvance(&mpath, nullstr);
7751                 if (p == NULL)
7752                         break;
7753                 if (*p == '\0')
7754                         continue;
7755                 for (q = p ; *q ; q++);
7756 #ifdef DEBUG
7757                 if (q[-1] != '/')
7758                         abort();
7759 #endif
7760                 q[-1] = '\0';                   /* delete trailing '/' */
7761                 if (stat(p, &statb) < 0)
7762                         statb.st_size = 0;
7763                 if (statb.st_size > mailtime[i] && ! silent) {
7764                         out2fmt(snlfmt,
7765                                 pathopt? pathopt : "you have mail");
7766                 }
7767                 mailtime[i] = statb.st_size;
7768         }
7769         nmboxes = i;
7770         popstackmark(&smark);
7771 }
7772
7773 #define PROFILE 0
7774
7775 #if PROFILE
7776 static short profile_buf[16384];
7777 extern int etext();
7778 #endif
7779
7780 static void read_profile (const char *);
7781 static char *find_dot_file (char *);
7782 static void cmdloop (int);
7783 static void options (int);
7784 static void minus_o (char *, int);
7785 static void setoption (int, int);
7786 static void procargs (int, char **);
7787
7788
7789 /*
7790  * Main routine.  We initialize things, parse the arguments, execute
7791  * profiles if we're a login shell, and then call cmdloop to execute
7792  * commands.  The setjmp call sets up the location to jump to when an
7793  * exception occurs.  When an exception occurs the variable "state"
7794  * is used to figure out how far we had gotten.
7795  */
7796
7797 int
7798 shell_main(argc, argv)
7799         int argc;
7800         char **argv;
7801 {
7802         struct jmploc jmploc;
7803         struct stackmark smark;
7804         volatile int state;
7805         char *shinit;
7806
7807         DOTCMD = find_builtin(".");
7808         BLTINCMD = find_builtin("builtin");
7809         EXECCMD = find_builtin("exec");
7810         EVALCMD = find_builtin("eval");
7811
7812 #ifndef BB_FEATURE_SH_FANCY_PROMPT
7813         unsetenv("PS1");
7814         unsetenv("PS2");
7815 #endif
7816
7817 #if PROFILE
7818         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7819 #endif
7820 #if defined(linux) || defined(__GNU__)
7821         signal(SIGCHLD, SIG_DFL);
7822 #endif
7823         state = 0;
7824         if (setjmp(jmploc.loc)) {
7825                 INTOFF;
7826                 /*
7827                  * When a shell procedure is executed, we raise the
7828                  * exception EXSHELLPROC to clean up before executing
7829                  * the shell procedure.
7830                  */
7831                 switch (exception) {
7832                 case EXSHELLPROC:
7833                         rootpid = getpid();
7834                         rootshell = 1;
7835                         minusc = NULL;
7836                         state = 3;
7837                         break;
7838
7839                 case EXEXEC:
7840                         exitstatus = exerrno;
7841                         break;
7842
7843                 case EXERROR:
7844                         exitstatus = 2;
7845                         break;
7846
7847                 default:
7848                         break;
7849                 }
7850
7851                 if (exception != EXSHELLPROC) {
7852                     if (state == 0 || iflag == 0 || ! rootshell)
7853                             exitshell(exitstatus);
7854                 }
7855                 reset();
7856                 if (exception == EXINT) {
7857                         out2c('\n');
7858                 }
7859                 popstackmark(&smark);
7860                 FORCEINTON;                             /* enable interrupts */
7861                 if (state == 1)
7862                         goto state1;
7863                 else if (state == 2)
7864                         goto state2;
7865                 else if (state == 3)
7866                         goto state3;
7867                 else
7868                         goto state4;
7869         }
7870         handler = &jmploc;
7871 #ifdef DEBUG
7872         opentrace();
7873         trputs("Shell args:  ");  trargs(argv);
7874 #endif
7875         rootpid = getpid();
7876         rootshell = 1;
7877         init();
7878         setstackmark(&smark);
7879         procargs(argc, argv);
7880         if (argv[0] && argv[0][0] == '-') {
7881                 state = 1;
7882                 read_profile("/etc/profile");
7883 state1:
7884                 state = 2;
7885                 read_profile(".profile");
7886         }
7887 state2:
7888         state = 3;
7889 #ifndef linux
7890         if (getuid() == geteuid() && getgid() == getegid()) {
7891 #endif
7892                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7893                         state = 3;
7894                         read_profile(shinit);
7895                 }
7896 #ifndef linux
7897         }
7898 #endif
7899 state3:
7900         state = 4;
7901         if (sflag == 0 || minusc) {
7902                 static int sigs[] =  {
7903                     SIGINT, SIGQUIT, SIGHUP,
7904 #ifdef SIGTSTP
7905                     SIGTSTP,
7906 #endif
7907                     SIGPIPE
7908                 };
7909 #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
7910                 int i;
7911
7912                 for (i = 0; i < SIGSSIZE; i++)
7913                     setsignal(sigs[i]);
7914         }
7915
7916         if (minusc)
7917                 evalstring(minusc, 0);
7918
7919         if (sflag || minusc == NULL) {
7920 state4: /* XXX ??? - why isn't this before the "if" statement */
7921                 cmdloop(1);
7922         }
7923 #if PROFILE
7924         monitor(0);
7925 #endif
7926         exitshell(exitstatus);
7927         /* NOTREACHED */
7928 }
7929
7930
7931 /*
7932  * Read and execute commands.  "Top" is nonzero for the top level command
7933  * loop; it turns on prompting if the shell is interactive.
7934  */
7935
7936 static void
7937 cmdloop(int top)
7938 {
7939         union node *n;
7940         struct stackmark smark;
7941         int inter;
7942         int numeof = 0;
7943
7944         TRACE(("cmdloop(%d) called\n", top));
7945         setstackmark(&smark);
7946         for (;;) {
7947                 if (pendingsigs)
7948                         dotrap();
7949                 inter = 0;
7950                 if (iflag && top) {
7951                         inter++;
7952                         showjobs(1);
7953                         chkmail(0);
7954                         flushall();
7955                 }
7956                 n = parsecmd(inter);
7957                 /* showtree(n); DEBUG */
7958                 if (n == NEOF) {
7959                         if (!top || numeof >= 50)
7960                                 break;
7961                         if (!stoppedjobs()) {
7962                                 if (!Iflag)
7963                                         break;
7964                                 out2str("\nUse \"exit\" to leave shell.\n");
7965                         }
7966                         numeof++;
7967                 } else if (n != NULL && nflag == 0) {
7968                         job_warning = (job_warning == 2) ? 1 : 0;
7969                         numeof = 0;
7970                         evaltree(n, 0);
7971                 }
7972                 popstackmark(&smark);
7973                 setstackmark(&smark);
7974                 if (evalskip == SKIPFILE) {
7975                         evalskip = 0;
7976                         break;
7977                 }
7978         }
7979         popstackmark(&smark);
7980 }
7981
7982
7983
7984 /*
7985  * Read /etc/profile or .profile.  Return on error.
7986  */
7987
7988 static void
7989 read_profile(name)
7990         const char *name;
7991 {
7992         int fd;
7993         int xflag_set = 0;
7994         int vflag_set = 0;
7995
7996         INTOFF;
7997         if ((fd = open(name, O_RDONLY)) >= 0)
7998                 setinputfd(fd, 1);
7999         INTON;
8000         if (fd < 0)
8001                 return;
8002         /* -q turns off -x and -v just when executing init files */
8003         if (qflag)  {
8004             if (xflag)
8005                     xflag = 0, xflag_set = 1;
8006             if (vflag)
8007                     vflag = 0, vflag_set = 1;
8008         }
8009         cmdloop(0);
8010         if (qflag)  {
8011             if (xflag_set)
8012                     xflag = 1;
8013             if (vflag_set)
8014                     vflag = 1;
8015         }
8016         popfile();
8017 }
8018
8019
8020
8021 /*
8022  * Read a file containing shell functions.
8023  */
8024
8025 static void
8026 readcmdfile(const char *name)
8027 {
8028         int fd;
8029
8030         INTOFF;
8031         if ((fd = open(name, O_RDONLY)) >= 0)
8032                 setinputfd(fd, 1);
8033         else
8034                 error("Can't open %s", name);
8035         INTON;
8036         cmdloop(0);
8037         popfile();
8038 }
8039
8040
8041
8042 /*
8043  * Take commands from a file.  To be compatable we should do a path
8044  * search for the file, which is necessary to find sub-commands.
8045  */
8046
8047
8048 static char *
8049 find_dot_file(mybasename)
8050         char *mybasename;
8051 {
8052         char *fullname;
8053         const char *path = pathval();
8054         struct stat statb;
8055
8056         /* don't try this for absolute or relative paths */
8057         if (strchr(mybasename, '/'))
8058                 return mybasename;
8059
8060         while ((fullname = padvance(&path, mybasename)) != NULL) {
8061                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8062                         /*
8063                          * Don't bother freeing here, since it will
8064                          * be freed by the caller.
8065                          */
8066                         return fullname;
8067                 }
8068                 stunalloc(fullname);
8069         }
8070
8071         /* not found in the PATH */
8072         error("%s: not found", mybasename);
8073         /* NOTREACHED */
8074 }
8075
8076 static int
8077 dotcmd(argc, argv)
8078         int argc;
8079         char **argv;
8080 {
8081         struct strlist *sp;
8082         exitstatus = 0;
8083
8084         for (sp = cmdenviron; sp ; sp = sp->next)
8085                 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
8086
8087         if (argc >= 2) {                /* That's what SVR2 does */
8088                 char *fullname;
8089                 struct stackmark smark;
8090
8091                 setstackmark(&smark);
8092                 fullname = find_dot_file(argv[1]);
8093                 setinputfile(fullname, 1);
8094                 commandname = fullname;
8095                 cmdloop(0);
8096                 popfile();
8097                 popstackmark(&smark);
8098         }
8099         return exitstatus;
8100 }
8101
8102
8103 static int
8104 exitcmd(argc, argv)
8105         int argc;
8106         char **argv;
8107 {
8108         if (stoppedjobs())
8109                 return 0;
8110         if (argc > 1)
8111                 exitstatus = number(argv[1]);
8112         else
8113                 exitstatus = oexitstatus;
8114         exitshell(exitstatus);
8115         /* NOTREACHED */
8116 }
8117 static pointer
8118 stalloc(int nbytes)
8119 {
8120         char *p;
8121
8122         nbytes = ALIGN(nbytes);
8123         if (nbytes > stacknleft) {
8124                 int blocksize;
8125                 struct stack_block *sp;
8126
8127                 blocksize = nbytes;
8128                 if (blocksize < MINSIZE)
8129                         blocksize = MINSIZE;
8130                 INTOFF;
8131                 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
8132                 sp->prev = stackp;
8133                 stacknxt = sp->space;
8134                 stacknleft = blocksize;
8135                 stackp = sp;
8136                 INTON;
8137         }
8138         p = stacknxt;
8139         stacknxt += nbytes;
8140         stacknleft -= nbytes;
8141         return p;
8142 }
8143
8144
8145 static void
8146 stunalloc(pointer p)
8147 {
8148 #ifdef DEBUG
8149         if (p == NULL) {                /*DEBUG */
8150                 write(2, "stunalloc\n", 10);
8151                 abort();
8152         }
8153 #endif
8154         if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
8155                 p = stackp->space;
8156         }
8157         stacknleft += stacknxt - (char *)p;
8158         stacknxt = p;
8159 }
8160
8161
8162 static void
8163 setstackmark(struct stackmark *mark)
8164 {
8165         mark->stackp = stackp;
8166         mark->stacknxt = stacknxt;
8167         mark->stacknleft = stacknleft;
8168         mark->marknext = markp;
8169         markp = mark;
8170 }
8171
8172
8173 static void
8174 popstackmark(struct stackmark *mark)
8175 {
8176         struct stack_block *sp;
8177
8178         INTOFF;
8179         markp = mark->marknext;
8180         while (stackp != mark->stackp) {
8181                 sp = stackp;
8182                 stackp = sp->prev;
8183                 ckfree(sp);
8184         }
8185         stacknxt = mark->stacknxt;
8186         stacknleft = mark->stacknleft;
8187         INTON;
8188 }
8189
8190
8191 /*
8192  * When the parser reads in a string, it wants to stick the string on the
8193  * stack and only adjust the stack pointer when it knows how big the
8194  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
8195  * of space on top of the stack and stackblocklen returns the length of
8196  * this block.  Growstackblock will grow this space by at least one byte,
8197  * possibly moving it (like realloc).  Grabstackblock actually allocates the
8198  * part of the block that has been used.
8199  */
8200
8201 static void
8202 growstackblock(void) {
8203         char *p;
8204         int newlen = ALIGN(stacknleft * 2 + 100);
8205         char *oldspace = stacknxt;
8206         int oldlen = stacknleft;
8207         struct stack_block *sp;
8208         struct stack_block *oldstackp;
8209
8210         if (stacknxt == stackp->space && stackp != &stackbase) {
8211                 INTOFF;
8212                 oldstackp = stackp;
8213                 sp = stackp;
8214                 stackp = sp->prev;
8215                 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8216                 sp->prev = stackp;
8217                 stackp = sp;
8218                 stacknxt = sp->space;
8219                 stacknleft = newlen;
8220                 {
8221                   /* Stack marks pointing to the start of the old block
8222                    * must be relocated to point to the new block
8223                    */
8224                   struct stackmark *xmark;
8225                   xmark = markp;
8226                   while (xmark != NULL && xmark->stackp == oldstackp) {
8227                     xmark->stackp = stackp;
8228                     xmark->stacknxt = stacknxt;
8229                     xmark->stacknleft = stacknleft;
8230                     xmark = xmark->marknext;
8231                   }
8232                 }
8233                 INTON;
8234         } else {
8235                 p = stalloc(newlen);
8236                 memcpy(p, oldspace, oldlen);
8237                 stacknxt = p;                   /* free the space */
8238                 stacknleft += newlen;           /* we just allocated */
8239         }
8240 }
8241
8242
8243
8244 static inline void
8245 grabstackblock(int len)
8246 {
8247         len = ALIGN(len);
8248         stacknxt += len;
8249         stacknleft -= len;
8250 }
8251
8252
8253
8254 /*
8255  * The following routines are somewhat easier to use that the above.
8256  * The user declares a variable of type STACKSTR, which may be declared
8257  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
8258  * the user uses the macro STPUTC to add characters to the string.  In
8259  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8260  * grown as necessary.  When the user is done, she can just leave the
8261  * string there and refer to it using stackblock().  Or she can allocate
8262  * the space for it using grabstackstr().  If it is necessary to allow
8263  * someone else to use the stack temporarily and then continue to grow
8264  * the string, the user should use grabstack to allocate the space, and
8265  * then call ungrabstr(p) to return to the previous mode of operation.
8266  *
8267  * USTPUTC is like STPUTC except that it doesn't check for overflow.
8268  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8269  * is space for at least one character.
8270  */
8271
8272
8273 static char *
8274 growstackstr(void) {
8275         int len = stackblocksize();
8276         if (herefd >= 0 && len >= 1024) {
8277                 xwrite(herefd, stackblock(), len);
8278                 sstrnleft = len - 1;
8279                 return stackblock();
8280         }
8281         growstackblock();
8282         sstrnleft = stackblocksize() - len - 1;
8283         return stackblock() + len;
8284 }
8285
8286
8287 /*
8288  * Called from CHECKSTRSPACE.
8289  */
8290
8291 static char *
8292 makestrspace(size_t newlen) {
8293         int len = stackblocksize() - sstrnleft;
8294         do {
8295                 growstackblock();
8296                 sstrnleft = stackblocksize() - len;
8297         } while (sstrnleft < newlen);
8298         return stackblock() + len;
8299 }
8300
8301
8302
8303 static void
8304 ungrabstackstr(char *s, char *p)
8305 {
8306         stacknleft += stacknxt - s;
8307         stacknxt = s;
8308         sstrnleft = stacknleft - (p - s);
8309 }
8310 /*
8311  * Miscelaneous builtins.
8312  */
8313
8314
8315 #undef rflag
8316
8317 #ifdef __GLIBC__
8318 static mode_t getmode(const void *, mode_t);
8319 static void *setmode(const char *);
8320
8321 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8322 typedef enum __rlimit_resource rlim_t;
8323 #endif
8324 #endif
8325
8326
8327
8328 /*
8329  * The read builtin.  The -e option causes backslashes to escape the
8330  * following character.
8331  *
8332  * This uses unbuffered input, which may be avoidable in some cases.
8333  */
8334
8335 static int
8336 readcmd(argc, argv)
8337         int argc;
8338         char **argv;
8339 {
8340         char **ap;
8341         int backslash;
8342         char c;
8343         int rflag;
8344         char *prompt;
8345         const char *ifs;
8346         char *p;
8347         int startword;
8348         int status;
8349         int i;
8350
8351         rflag = 0;
8352         prompt = NULL;
8353         while ((i = nextopt("p:r")) != '\0') {
8354                 if (i == 'p')
8355                         prompt = optionarg;
8356                 else
8357                         rflag = 1;
8358         }
8359         if (prompt && isatty(0)) {
8360                 putprompt(prompt);
8361                 flushall();
8362         }
8363         if (*(ap = argptr) == NULL)
8364                 error("arg count");
8365         if ((ifs = bltinlookup("IFS")) == NULL)
8366                 ifs = defifs;
8367         status = 0;
8368         startword = 1;
8369         backslash = 0;
8370         STARTSTACKSTR(p);
8371         for (;;) {
8372                 if (read(0, &c, 1) != 1) {
8373                         status = 1;
8374                         break;
8375                 }
8376                 if (c == '\0')
8377                         continue;
8378                 if (backslash) {
8379                         backslash = 0;
8380                         if (c != '\n')
8381                                 STPUTC(c, p);
8382                         continue;
8383                 }
8384                 if (!rflag && c == '\\') {
8385                         backslash++;
8386                         continue;
8387                 }
8388                 if (c == '\n')
8389                         break;
8390                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8391                         continue;
8392                 }
8393                 startword = 0;
8394                 if (backslash && c == '\\') {
8395                         if (read(0, &c, 1) != 1) {
8396                                 status = 1;
8397                                 break;
8398                         }
8399                         STPUTC(c, p);
8400                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8401                         STACKSTRNUL(p);
8402                         setvar(*ap, stackblock(), 0);
8403                         ap++;
8404                         startword = 1;
8405                         STARTSTACKSTR(p);
8406                 } else {
8407                         STPUTC(c, p);
8408                 }
8409         }
8410         STACKSTRNUL(p);
8411         /* Remove trailing blanks */
8412         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8413                 *p = '\0';
8414         setvar(*ap, stackblock(), 0);
8415         while (*++ap != NULL)
8416                 setvar(*ap, nullstr, 0);
8417         return status;
8418 }
8419
8420
8421
8422 static int
8423 umaskcmd(argc, argv)
8424         int argc;
8425         char **argv;
8426 {
8427         char *ap;
8428         int mask;
8429         int i;
8430         int symbolic_mode = 0;
8431
8432         while ((i = nextopt("S")) != '\0') {
8433                 symbolic_mode = 1;
8434         }
8435
8436         INTOFF;
8437         mask = umask(0);
8438         umask(mask);
8439         INTON;
8440
8441         if ((ap = *argptr) == NULL) {
8442                 if (symbolic_mode) {
8443                         char u[4], g[4], o[4];
8444
8445                         i = 0;
8446                         if ((mask & S_IRUSR) == 0)
8447                                 u[i++] = 'r';
8448                         if ((mask & S_IWUSR) == 0)
8449                                 u[i++] = 'w';
8450                         if ((mask & S_IXUSR) == 0)
8451                                 u[i++] = 'x';
8452                         u[i] = '\0';
8453
8454                         i = 0;
8455                         if ((mask & S_IRGRP) == 0)
8456                                 g[i++] = 'r';
8457                         if ((mask & S_IWGRP) == 0)
8458                                 g[i++] = 'w';
8459                         if ((mask & S_IXGRP) == 0)
8460                                 g[i++] = 'x';
8461                         g[i] = '\0';
8462
8463                         i = 0;
8464                         if ((mask & S_IROTH) == 0)
8465                                 o[i++] = 'r';
8466                         if ((mask & S_IWOTH) == 0)
8467                                 o[i++] = 'w';
8468                         if ((mask & S_IXOTH) == 0)
8469                                 o[i++] = 'x';
8470                         o[i] = '\0';
8471
8472                         out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
8473                 } else {
8474                         out1fmt("%.4o\n", mask);
8475                 }
8476         } else {
8477                 if (isdigit((unsigned char)*ap)) {
8478                         mask = 0;
8479                         do {
8480                                 if (*ap >= '8' || *ap < '0')
8481                                         error("Illegal number: %s", argv[1]);
8482                                 mask = (mask << 3) + (*ap - '0');
8483                         } while (*++ap != '\0');
8484                         umask(mask);
8485                 } else {
8486                         void *set;
8487
8488                         INTOFF;
8489                         if ((set = setmode(ap)) != 0) {
8490                                 mask = getmode(set, ~mask & 0777);
8491                                 ckfree(set);
8492                         }
8493                         INTON;
8494                         if (!set)
8495                                 error("Illegal mode: %s", ap);
8496
8497                         umask(~mask & 0777);
8498                 }
8499         }
8500         return 0;
8501 }
8502
8503 /*
8504  * ulimit builtin
8505  *
8506  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8507  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8508  * ash by J.T. Conklin.
8509  *
8510  * Public domain.
8511  */
8512
8513 struct limits {
8514         const char *name;
8515         int     cmd;
8516         int     factor; /* multiply by to get rlim_{cur,max} values */
8517         char    option;
8518 };
8519
8520 static const struct limits limits[] = {
8521 #ifdef RLIMIT_CPU
8522         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
8523 #endif
8524 #ifdef RLIMIT_FSIZE
8525         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
8526 #endif
8527 #ifdef RLIMIT_DATA
8528         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
8529 #endif
8530 #ifdef RLIMIT_STACK
8531         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
8532 #endif
8533 #ifdef  RLIMIT_CORE
8534         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
8535 #endif
8536 #ifdef RLIMIT_RSS
8537         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
8538 #endif
8539 #ifdef RLIMIT_MEMLOCK
8540         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
8541 #endif
8542 #ifdef RLIMIT_NPROC
8543         { "process(processes)",         RLIMIT_NPROC,      1, 'p' },
8544 #endif
8545 #ifdef RLIMIT_NOFILE
8546         { "nofiles(descriptors)",       RLIMIT_NOFILE,     1, 'n' },
8547 #endif
8548 #ifdef RLIMIT_VMEM
8549         { "vmemory(kbytes)",            RLIMIT_VMEM,    1024, 'v' },
8550 #endif
8551 #ifdef RLIMIT_SWAP
8552         { "swap(kbytes)",               RLIMIT_SWAP,    1024, 'w' },
8553 #endif
8554         { (char *) 0,                   0,                 0,  '\0' }
8555 };
8556
8557 static int
8558 ulimitcmd(argc, argv)
8559         int argc;
8560         char **argv;
8561 {
8562         int     c;
8563         rlim_t val = 0;
8564         enum { SOFT = 0x1, HARD = 0x2 }
8565                         how = SOFT | HARD;
8566         const struct limits     *l;
8567         int             set, all = 0;
8568         int             optc, what;
8569         struct rlimit   limit;
8570
8571         what = 'f';
8572         while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
8573                 switch (optc) {
8574                 case 'H':
8575                         how = HARD;
8576                         break;
8577                 case 'S':
8578                         how = SOFT;
8579                         break;
8580                 case 'a':
8581                         all = 1;
8582                         break;
8583                 default:
8584                         what = optc;
8585                 }
8586
8587         for (l = limits; l->name && l->option != what; l++)
8588                 ;
8589         if (!l->name)
8590                 error("internal error (%c)", what);
8591
8592         set = *argptr ? 1 : 0;
8593         if (set) {
8594                 char *p = *argptr;
8595
8596                 if (all || argptr[1])
8597                         error("too many arguments");
8598                 if (strcmp(p, "unlimited") == 0)
8599                         val = RLIM_INFINITY;
8600                 else {
8601                         val = (rlim_t) 0;
8602
8603                         while ((c = *p++) >= '0' && c <= '9')
8604                         {
8605                                 val = (val * 10) + (long)(c - '0');
8606                                 if (val < (rlim_t) 0)
8607                                         break;
8608                         }
8609                         if (c)
8610                                 error("bad number");
8611                         val *= l->factor;
8612                 }
8613         }
8614         if (all) {
8615                 for (l = limits; l->name; l++) {
8616                         getrlimit(l->cmd, &limit);
8617                         if (how & SOFT)
8618                                 val = limit.rlim_cur;
8619                         else if (how & HARD)
8620                                 val = limit.rlim_max;
8621
8622                         out1fmt("%-20s ", l->name);
8623                         if (val == RLIM_INFINITY)
8624                                 out1fmt("unlimited\n");
8625                         else
8626                         {
8627                                 val /= l->factor;
8628                                 out1fmt("%lld\n", (long long) val);
8629                         }
8630                 }
8631                 return 0;
8632         }
8633
8634         getrlimit(l->cmd, &limit);
8635         if (set) {
8636                 if (how & HARD)
8637                         limit.rlim_max = val;
8638                 if (how & SOFT)
8639                         limit.rlim_cur = val;
8640                 if (setrlimit(l->cmd, &limit) < 0)
8641                         error("error setting limit (%m)");
8642         } else {
8643                 if (how & SOFT)
8644                         val = limit.rlim_cur;
8645                 else if (how & HARD)
8646                         val = limit.rlim_max;
8647
8648                 if (val == RLIM_INFINITY)
8649                         out1fmt("unlimited\n");
8650                 else
8651                 {
8652                         val /= l->factor;
8653                         out1fmt("%lld\n", (long long) val);
8654                 }
8655         }
8656         return 0;
8657 }
8658 /*
8659  * prefix -- see if pfx is a prefix of string.
8660  */
8661
8662 static int
8663 prefix(pfx, string)
8664         char const *pfx;
8665         char const *string;
8666         {
8667         while (*pfx) {
8668                 if (*pfx++ != *string++)
8669                         return 0;
8670         }
8671         return 1;
8672 }
8673
8674 /*
8675  * Return true if s is a string of digits, and save munber in intptr
8676  * nagative is bad
8677  */
8678
8679 static int
8680 is_number(const char *p, int *intptr)
8681 {
8682         int ret = 0;
8683
8684         do {
8685                 if (! is_digit(*p))
8686                         return 0;
8687                 ret *= 10;
8688                 ret += digit_val(*p);
8689                 p++;
8690         } while (*p != '\0');
8691
8692         *intptr = ret;
8693         return 1;
8694 }
8695
8696 /*
8697  * Convert a string of digits to an integer, printing an error message on
8698  * failure.
8699  */
8700
8701 static int
8702 number(const char *s)
8703 {
8704         int i;
8705         if (! is_number(s, &i))
8706                 error("Illegal number: %s", s);
8707         return i;
8708 }
8709
8710 /*
8711  * Produce a possibly single quoted string suitable as input to the shell.
8712  * The return string is allocated on the stack.
8713  */
8714
8715 static char *
8716 single_quote(const char *s) {
8717         char *p;
8718
8719         STARTSTACKSTR(p);
8720
8721         do {
8722                 char *q = p;
8723                 size_t len1, len1p, len2, len2p;
8724
8725                 len1 = strcspn(s, "'");
8726                 len2 = strspn(s + len1, "'");
8727
8728                 len1p = len1 ? len1 + 2 : len1;
8729                 switch (len2) {
8730                 case 0:
8731                         len2p = 0;
8732                         break;
8733                 case 1:
8734                         len2p = 2;
8735                         break;
8736                 default:
8737                         len2p = len2 + 2;
8738                 }
8739
8740                 CHECKSTRSPACE(len1p + len2p + 1, p);
8741
8742                 if (len1) {
8743                         *p = '\'';
8744 #ifdef _GNU_SOURCE
8745                         q = mempcpy(p + 1, s, len1);
8746 #else
8747                         q = p + 1 + len1;
8748                         memcpy(p + 1, s, len1);
8749 #endif
8750                         *q++ = '\'';
8751                         s += len1;
8752                 }
8753
8754                 switch (len2) {
8755                 case 0:
8756                         break;
8757                 case 1:
8758                         *q++ = '\\';
8759                         *q = '\'';
8760                         s++;
8761                         break;
8762                 default:
8763                         *q = '"';
8764 #ifdef _GNU_SOURCE
8765                         *(char *) mempcpy(q + 1, s, len2) = '"';
8766 #else
8767                         q += 1 + len2;
8768                         memcpy(q + 1, s, len2);
8769                         *q = '"';
8770 #endif
8771                         s += len2;
8772                 }
8773
8774                 STADJUST(len1p + len2p, p);
8775         } while (*s);
8776
8777         USTPUTC(0, p);
8778
8779         return grabstackstr(p);
8780 }
8781
8782 /*
8783  * Like strdup but works with the ash stack.
8784  */
8785
8786 static char *
8787 sstrdup(const char *p)
8788 {
8789         size_t len = strlen(p) + 1;
8790         return memcpy(stalloc(len), p, len);
8791 }
8792
8793
8794 /*
8795  * This file was generated by the mknodes program.
8796  */
8797
8798 /*
8799  * Routine for dealing with parsed shell commands.
8800  */
8801
8802
8803 static int     funcblocksize;           /* size of structures in function */
8804 static int     funcstringsize;          /* size of strings in node */
8805 static pointer funcblock;              /* block to allocate function from */
8806 static char   *funcstring;              /* block to allocate strings from */
8807
8808 static const short nodesize[26] = {
8809       ALIGN(sizeof (struct nbinary)),
8810       ALIGN(sizeof (struct ncmd)),
8811       ALIGN(sizeof (struct npipe)),
8812       ALIGN(sizeof (struct nredir)),
8813       ALIGN(sizeof (struct nredir)),
8814       ALIGN(sizeof (struct nredir)),
8815       ALIGN(sizeof (struct nbinary)),
8816       ALIGN(sizeof (struct nbinary)),
8817       ALIGN(sizeof (struct nif)),
8818       ALIGN(sizeof (struct nbinary)),
8819       ALIGN(sizeof (struct nbinary)),
8820       ALIGN(sizeof (struct nfor)),
8821       ALIGN(sizeof (struct ncase)),
8822       ALIGN(sizeof (struct nclist)),
8823       ALIGN(sizeof (struct narg)),
8824       ALIGN(sizeof (struct narg)),
8825       ALIGN(sizeof (struct nfile)),
8826       ALIGN(sizeof (struct nfile)),
8827       ALIGN(sizeof (struct nfile)),
8828       ALIGN(sizeof (struct nfile)),
8829       ALIGN(sizeof (struct nfile)),
8830       ALIGN(sizeof (struct ndup)),
8831       ALIGN(sizeof (struct ndup)),
8832       ALIGN(sizeof (struct nhere)),
8833       ALIGN(sizeof (struct nhere)),
8834       ALIGN(sizeof (struct nnot)),
8835 };
8836
8837
8838 static void calcsize (union node *);
8839 static void sizenodelist (struct nodelist *);
8840 static union node *copynode (union node *);
8841 static struct nodelist *copynodelist (struct nodelist *);
8842 static char *nodesavestr (char *);
8843
8844
8845
8846 /*
8847  * Make a copy of a parse tree.
8848  */
8849
8850 static union node *
8851 copyfunc(union node *n)
8852 {
8853         if (n == NULL)
8854                 return NULL;
8855         funcblocksize = 0;
8856         funcstringsize = 0;
8857         calcsize(n);
8858         funcblock = ckmalloc(funcblocksize + funcstringsize);
8859         funcstring = (char *) funcblock + funcblocksize;
8860         return copynode(n);
8861 }
8862
8863
8864
8865 static void
8866 calcsize(n)
8867         union node *n;
8868 {
8869       if (n == NULL)
8870             return;
8871       funcblocksize += nodesize[n->type];
8872       switch (n->type) {
8873       case NSEMI:
8874       case NAND:
8875       case NOR:
8876       case NWHILE:
8877       case NUNTIL:
8878             calcsize(n->nbinary.ch2);
8879             calcsize(n->nbinary.ch1);
8880             break;
8881       case NCMD:
8882             calcsize(n->ncmd.redirect);
8883             calcsize(n->ncmd.args);
8884             calcsize(n->ncmd.assign);
8885             break;
8886       case NPIPE:
8887             sizenodelist(n->npipe.cmdlist);
8888             break;
8889       case NREDIR:
8890       case NBACKGND:
8891       case NSUBSHELL:
8892             calcsize(n->nredir.redirect);
8893             calcsize(n->nredir.n);
8894             break;
8895       case NIF:
8896             calcsize(n->nif.elsepart);
8897             calcsize(n->nif.ifpart);
8898             calcsize(n->nif.test);
8899             break;
8900       case NFOR:
8901             funcstringsize += strlen(n->nfor.var) + 1;
8902             calcsize(n->nfor.body);
8903             calcsize(n->nfor.args);
8904             break;
8905       case NCASE:
8906             calcsize(n->ncase.cases);
8907             calcsize(n->ncase.expr);
8908             break;
8909       case NCLIST:
8910             calcsize(n->nclist.body);
8911             calcsize(n->nclist.pattern);
8912             calcsize(n->nclist.next);
8913             break;
8914       case NDEFUN:
8915       case NARG:
8916             sizenodelist(n->narg.backquote);
8917             funcstringsize += strlen(n->narg.text) + 1;
8918             calcsize(n->narg.next);
8919             break;
8920       case NTO:
8921       case NFROM:
8922       case NFROMTO:
8923       case NAPPEND:
8924       case NTOOV:
8925             calcsize(n->nfile.fname);
8926             calcsize(n->nfile.next);
8927             break;
8928       case NTOFD:
8929       case NFROMFD:
8930             calcsize(n->ndup.vname);
8931             calcsize(n->ndup.next);
8932             break;
8933       case NHERE:
8934       case NXHERE:
8935             calcsize(n->nhere.doc);
8936             calcsize(n->nhere.next);
8937             break;
8938       case NNOT:
8939             calcsize(n->nnot.com);
8940             break;
8941       };
8942 }
8943
8944
8945
8946 static void
8947 sizenodelist(lp)
8948         struct nodelist *lp;
8949 {
8950         while (lp) {
8951                 funcblocksize += ALIGN(sizeof(struct nodelist));
8952                 calcsize(lp->n);
8953                 lp = lp->next;
8954         }
8955 }
8956
8957
8958
8959 static union node *
8960 copynode(n)
8961         union node *n;
8962 {
8963         union node *new;
8964
8965       if (n == NULL)
8966             return NULL;
8967       new = funcblock;
8968       funcblock = (char *) funcblock + nodesize[n->type];
8969       switch (n->type) {
8970       case NSEMI:
8971       case NAND:
8972       case NOR:
8973       case NWHILE:
8974       case NUNTIL:
8975             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8976             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8977             break;
8978       case NCMD:
8979             new->ncmd.redirect = copynode(n->ncmd.redirect);
8980             new->ncmd.args = copynode(n->ncmd.args);
8981             new->ncmd.assign = copynode(n->ncmd.assign);
8982             new->ncmd.backgnd = n->ncmd.backgnd;
8983             break;
8984       case NPIPE:
8985             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8986             new->npipe.backgnd = n->npipe.backgnd;
8987             break;
8988       case NREDIR:
8989       case NBACKGND:
8990       case NSUBSHELL:
8991             new->nredir.redirect = copynode(n->nredir.redirect);
8992             new->nredir.n = copynode(n->nredir.n);
8993             break;
8994       case NIF:
8995             new->nif.elsepart = copynode(n->nif.elsepart);
8996             new->nif.ifpart = copynode(n->nif.ifpart);
8997             new->nif.test = copynode(n->nif.test);
8998             break;
8999       case NFOR:
9000             new->nfor.var = nodesavestr(n->nfor.var);
9001             new->nfor.body = copynode(n->nfor.body);
9002             new->nfor.args = copynode(n->nfor.args);
9003             break;
9004       case NCASE:
9005             new->ncase.cases = copynode(n->ncase.cases);
9006             new->ncase.expr = copynode(n->ncase.expr);
9007             break;
9008       case NCLIST:
9009             new->nclist.body = copynode(n->nclist.body);
9010             new->nclist.pattern = copynode(n->nclist.pattern);
9011             new->nclist.next = copynode(n->nclist.next);
9012             break;
9013       case NDEFUN:
9014       case NARG:
9015             new->narg.backquote = copynodelist(n->narg.backquote);
9016             new->narg.text = nodesavestr(n->narg.text);
9017             new->narg.next = copynode(n->narg.next);
9018             break;
9019       case NTO:
9020       case NFROM:
9021       case NFROMTO:
9022       case NAPPEND:
9023       case NTOOV:
9024             new->nfile.fname = copynode(n->nfile.fname);
9025             new->nfile.fd = n->nfile.fd;
9026             new->nfile.next = copynode(n->nfile.next);
9027             break;
9028       case NTOFD:
9029       case NFROMFD:
9030             new->ndup.vname = copynode(n->ndup.vname);
9031             new->ndup.dupfd = n->ndup.dupfd;
9032             new->ndup.fd = n->ndup.fd;
9033             new->ndup.next = copynode(n->ndup.next);
9034             break;
9035       case NHERE:
9036       case NXHERE:
9037             new->nhere.doc = copynode(n->nhere.doc);
9038             new->nhere.fd = n->nhere.fd;
9039             new->nhere.next = copynode(n->nhere.next);
9040             break;
9041       case NNOT:
9042             new->nnot.com = copynode(n->nnot.com);
9043             break;
9044       };
9045       new->type = n->type;
9046         return new;
9047 }
9048
9049
9050 static struct nodelist *
9051 copynodelist(lp)
9052         struct nodelist *lp;
9053 {
9054         struct nodelist *start;
9055         struct nodelist **lpp;
9056
9057         lpp = &start;
9058         while (lp) {
9059                 *lpp = funcblock;
9060                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
9061                 (*lpp)->n = copynode(lp->n);
9062                 lp = lp->next;
9063                 lpp = &(*lpp)->next;
9064         }
9065         *lpp = NULL;
9066         return start;
9067 }
9068
9069
9070
9071 static char *
9072 nodesavestr(s)
9073         char   *s;
9074 {
9075 #ifdef _GNU_SOURCE
9076         char   *rtn = funcstring;
9077
9078         funcstring = stpcpy(funcstring, s) + 1;
9079         return rtn;
9080 #else
9081         register char *p = s;
9082         register char *q = funcstring;
9083         char   *rtn = funcstring;
9084
9085         while ((*q++ = *p++) != '\0')
9086                 continue;
9087         funcstring = q;
9088         return rtn;
9089 #endif
9090 }
9091
9092 #ifdef ASH_GETOPTS
9093 static int getopts (char *, char *, char **, int *, int *);
9094 #endif
9095
9096
9097 /*
9098  * Process the shell command line arguments.
9099  */
9100
9101 static void
9102 procargs(argc, argv)
9103         int argc;
9104         char **argv;
9105 {
9106         int i;
9107
9108         argptr = argv;
9109         if (argc > 0)
9110                 argptr++;
9111         for (i = 0; i < NOPTS; i++)
9112                 optent_val(i) = 2;
9113         options(1);
9114         if (*argptr == NULL && minusc == NULL)
9115                 sflag = 1;
9116         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
9117                 iflag = 1;
9118         if (mflag == 2)
9119                 mflag = iflag;
9120         for (i = 0; i < NOPTS; i++)
9121                 if (optent_val(i) == 2)
9122                         optent_val(i) = 0;
9123         arg0 = argv[0];
9124         if (sflag == 0 && minusc == NULL) {
9125                 commandname = argv[0];
9126                 arg0 = *argptr++;
9127                 setinputfile(arg0, 0);
9128                 commandname = arg0;
9129         }
9130         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
9131         if (argptr && minusc && *argptr)
9132                 arg0 = *argptr++;
9133
9134         shellparam.p = argptr;
9135         shellparam.optind = 1;
9136         shellparam.optoff = -1;
9137         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
9138         while (*argptr) {
9139                 shellparam.nparam++;
9140                 argptr++;
9141         }
9142         optschanged();
9143 }
9144
9145
9146
9147 /*
9148  * Process shell options.  The global variable argptr contains a pointer
9149  * to the argument list; we advance it past the options.
9150  */
9151
9152 static void
9153 options(cmdline)
9154         int cmdline;
9155 {
9156         char *p;
9157         int val;
9158         int c;
9159
9160         if (cmdline)
9161                 minusc = NULL;
9162         while ((p = *argptr) != NULL) {
9163                 argptr++;
9164                 if ((c = *p++) == '-') {
9165                         val = 1;
9166                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
9167                                 if (!cmdline) {
9168                                         /* "-" means turn off -x and -v */
9169                                         if (p[0] == '\0')
9170                                                 xflag = vflag = 0;
9171                                         /* "--" means reset params */
9172                                         else if (*argptr == NULL)
9173                                                 setparam(argptr);
9174                                 }
9175                                 break;    /* "-" or  "--" terminates options */
9176                         }
9177                 } else if (c == '+') {
9178                         val = 0;
9179                 } else {
9180                         argptr--;
9181                         break;
9182                 }
9183                 while ((c = *p++) != '\0') {
9184                         if (c == 'c' && cmdline) {
9185                                 char *q;
9186 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
9187                                 if (*p == '\0')
9188 #endif
9189                                         q = *argptr++;
9190                                 if (q == NULL || minusc != NULL)
9191                                         error("Bad -c option");
9192                                 minusc = q;
9193 #ifdef NOHACK
9194                                 break;
9195 #endif
9196                         } else if (c == 'o') {
9197                                 minus_o(*argptr, val);
9198                                 if (*argptr)
9199                                         argptr++;
9200                         } else {
9201                                 setoption(c, val);
9202                         }
9203                 }
9204         }
9205 }
9206
9207 static void
9208 minus_o(name, val)
9209         char *name;
9210         int val;
9211 {
9212         int i;
9213
9214         if (name == NULL) {
9215                 out1str("Current option settings\n");
9216                 for (i = 0; i < NOPTS; i++)
9217                         out1fmt("%-16s%s\n", optent_name(optlist[i]),
9218                                 optent_val(i) ? "on" : "off");
9219         } else {
9220                 for (i = 0; i < NOPTS; i++)
9221                         if (equal(name, optent_name(optlist[i]))) {
9222                                 setoption(optent_letter(optlist[i]), val);
9223                                 return;
9224                         }
9225                 error("Illegal option -o %s", name);
9226         }
9227 }
9228
9229
9230 static void
9231 setoption(int flag, int val)
9232 {
9233         int i;
9234
9235         for (i = 0; i < NOPTS; i++)
9236                 if (optent_letter(optlist[i]) == flag) {
9237                         optent_val(i) = val;
9238                         if (val) {
9239                                 /* #%$ hack for ksh semantics */
9240                                 if (flag == 'V')
9241                                         Eflag = 0;
9242                                 else if (flag == 'E')
9243                                         Vflag = 0;
9244                         }
9245                         return;
9246                 }
9247         error("Illegal option -%c", flag);
9248         /* NOTREACHED */
9249 }
9250
9251
9252
9253 /*
9254  * Set the shell parameters.
9255  */
9256
9257 static void
9258 setparam(char **argv)
9259 {
9260         char **newparam;
9261         char **ap;
9262         int nparam;
9263
9264         for (nparam = 0 ; argv[nparam] ; nparam++);
9265         ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9266         while (*argv) {
9267                 *ap++ = savestr(*argv++);
9268         }
9269         *ap = NULL;
9270         freeparam(&shellparam);
9271         shellparam.malloc = 1;
9272         shellparam.nparam = nparam;
9273         shellparam.p = newparam;
9274         shellparam.optind = 1;
9275         shellparam.optoff = -1;
9276 }
9277
9278
9279 /*
9280  * Free the list of positional parameters.
9281  */
9282
9283 static void
9284 freeparam(volatile struct shparam *param)
9285 {
9286         char **ap;
9287
9288         if (param->malloc) {
9289                 for (ap = param->p ; *ap ; ap++)
9290                         ckfree(*ap);
9291                 ckfree(param->p);
9292         }
9293 }
9294
9295
9296
9297 /*
9298  * The shift builtin command.
9299  */
9300
9301 static int
9302 shiftcmd(argc, argv)
9303         int argc;
9304         char **argv;
9305 {
9306         int n;
9307         char **ap1, **ap2;
9308
9309         n = 1;
9310         if (argc > 1)
9311                 n = number(argv[1]);
9312         if (n > shellparam.nparam)
9313                 error("can't shift that many");
9314         INTOFF;
9315         shellparam.nparam -= n;
9316         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9317                 if (shellparam.malloc)
9318                         ckfree(*ap1);
9319         }
9320         ap2 = shellparam.p;
9321         while ((*ap2++ = *ap1++) != NULL);
9322         shellparam.optind = 1;
9323         shellparam.optoff = -1;
9324         INTON;
9325         return 0;
9326 }
9327
9328
9329
9330 /*
9331  * The set command builtin.
9332  */
9333
9334 static int
9335 setcmd(argc, argv)
9336         int argc;
9337         char **argv;
9338 {
9339         if (argc == 1)
9340                 return showvarscmd(argc, argv);
9341         INTOFF;
9342         options(0);
9343         optschanged();
9344         if (*argptr != NULL) {
9345                 setparam(argptr);
9346         }
9347         INTON;
9348         return 0;
9349 }
9350
9351
9352 static void
9353 getoptsreset(const char *value)
9354 {
9355         shellparam.optind = number(value);
9356         shellparam.optoff = -1;
9357 }
9358
9359 #ifdef BB_LOCALE_SUPPORT
9360 static void change_lc_all(const char *value)
9361 {
9362         if(value != 0 && *value != 0)
9363                 setlocale(LC_ALL, value);
9364 }
9365
9366 static void change_lc_ctype(const char *value)
9367 {
9368         if(value != 0 && *value != 0)
9369                 setlocale(LC_CTYPE, value);
9370 }
9371
9372 #endif
9373
9374 #ifdef ASH_GETOPTS
9375 /*
9376  * The getopts builtin.  Shellparam.optnext points to the next argument
9377  * to be processed.  Shellparam.optptr points to the next character to
9378  * be processed in the current argument.  If shellparam.optnext is NULL,
9379  * then it's the first time getopts has been called.
9380  */
9381
9382 static int
9383 getoptscmd(argc, argv)
9384         int argc;
9385         char **argv;
9386 {
9387         char **optbase;
9388
9389         if (argc < 3)
9390                 error("Usage: getopts optstring var [arg]");
9391         else if (argc == 3) {
9392                 optbase = shellparam.p;
9393                 if (shellparam.optind > shellparam.nparam + 1) {
9394                         shellparam.optind = 1;
9395                         shellparam.optoff = -1;
9396                 }
9397         }
9398         else {
9399                 optbase = &argv[3];
9400                 if (shellparam.optind > argc - 2) {
9401                         shellparam.optind = 1;
9402                         shellparam.optoff = -1;
9403                 }
9404         }
9405
9406         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9407                        &shellparam.optoff);
9408 }
9409
9410 /*
9411  * Safe version of setvar, returns 1 on success 0 on failure.
9412  */
9413
9414 static int
9415 setvarsafe(name, val, flags)
9416         const char *name, *val;
9417         int flags;
9418 {
9419         struct jmploc jmploc;
9420         struct jmploc *volatile savehandler = handler;
9421         int err = 0;
9422 #ifdef __GNUC__
9423         (void) &err;
9424 #endif
9425
9426         if (setjmp(jmploc.loc))
9427                 err = 1;
9428         else {
9429                 handler = &jmploc;
9430                 setvar(name, val, flags);
9431         }
9432         handler = savehandler;
9433         return err;
9434 }
9435
9436 static int
9437 getopts(optstr, optvar, optfirst, myoptind, optoff)
9438         char *optstr;
9439         char *optvar;
9440         char **optfirst;
9441         int *myoptind;
9442         int *optoff;
9443 {
9444         char *p, *q;
9445         char c = '?';
9446         int done = 0;
9447         int err = 0;
9448         char s[10];
9449         char **optnext = optfirst + *myoptind - 1;
9450
9451         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9452             strlen(*(optnext - 1)) < *optoff)
9453                 p = NULL;
9454         else
9455                 p = *(optnext - 1) + *optoff;
9456         if (p == NULL || *p == '\0') {
9457                 /* Current word is done, advance */
9458                 if (optnext == NULL)
9459                         return 1;
9460                 p = *optnext;
9461                 if (p == NULL || *p != '-' || *++p == '\0') {
9462 atend:
9463                         *myoptind = optnext - optfirst + 1;
9464                         p = NULL;
9465                         done = 1;
9466                         goto out;
9467                 }
9468                 optnext++;
9469                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9470                         goto atend;
9471         }
9472
9473         c = *p++;
9474         for (q = optstr; *q != c; ) {
9475                 if (*q == '\0') {
9476                         if (optstr[0] == ':') {
9477                                 s[0] = c;
9478                                 s[1] = '\0';
9479                                 err |= setvarsafe("OPTARG", s, 0);
9480                         }
9481                         else {
9482                                 out2fmt("Illegal option -%c\n", c);
9483                                 (void) unsetvar("OPTARG");
9484                         }
9485                         c = '?';
9486                         goto bad;
9487                 }
9488                 if (*++q == ':')
9489                         q++;
9490         }
9491
9492         if (*++q == ':') {
9493                 if (*p == '\0' && (p = *optnext) == NULL) {
9494                         if (optstr[0] == ':') {
9495                                 s[0] = c;
9496                                 s[1] = '\0';
9497                                 err |= setvarsafe("OPTARG", s, 0);
9498                                 c = ':';
9499                         }
9500                         else {
9501                                 out2fmt("No arg for -%c option\n", c);
9502                                 (void) unsetvar("OPTARG");
9503                                 c = '?';
9504                         }
9505                         goto bad;
9506                 }
9507
9508                 if (p == *optnext)
9509                         optnext++;
9510                 setvarsafe("OPTARG", p, 0);
9511                 p = NULL;
9512         }
9513         else
9514                 setvarsafe("OPTARG", "", 0);
9515         *myoptind = optnext - optfirst + 1;
9516         goto out;
9517
9518 bad:
9519         *myoptind = 1;
9520         p = NULL;
9521 out:
9522         *optoff = p ? p - *(optnext - 1) : -1;
9523         snprintf(s, sizeof(s), "%d", *myoptind);
9524         err |= setvarsafe("OPTIND", s, VNOFUNC);
9525         s[0] = c;
9526         s[1] = '\0';
9527         err |= setvarsafe(optvar, s, 0);
9528         if (err) {
9529                 *myoptind = 1;
9530                 *optoff = -1;
9531                 flushall();
9532                 exraise(EXERROR);
9533         }
9534         return done;
9535 }
9536 #endif
9537
9538 /*
9539  * XXX - should get rid of.  have all builtins use getopt(3).  the
9540  * library getopt must have the BSD extension static variable "optreset"
9541  * otherwise it can't be used within the shell safely.
9542  *
9543  * Standard option processing (a la getopt) for builtin routines.  The
9544  * only argument that is passed to nextopt is the option string; the
9545  * other arguments are unnecessary.  It return the character, or '\0' on
9546  * end of input.
9547  */
9548
9549 static int
9550 nextopt(optstring)
9551         const char *optstring;
9552         {
9553         char *p;
9554         const char *q;
9555         char c;
9556
9557         if ((p = optptr) == NULL || *p == '\0') {
9558                 p = *argptr;
9559                 if (p == NULL || *p != '-' || *++p == '\0')
9560                         return '\0';
9561                 argptr++;
9562                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9563                         return '\0';
9564         }
9565         c = *p++;
9566         for (q = optstring ; *q != c ; ) {
9567                 if (*q == '\0')
9568                         error("Illegal option -%c", c);
9569                 if (*++q == ':')
9570                         q++;
9571         }
9572         if (*++q == ':') {
9573                 if (*p == '\0' && (p = *argptr++) == NULL)
9574                         error("No arg for -%c option", c);
9575                 optionarg = p;
9576                 p = NULL;
9577         }
9578         optptr = p;
9579         return c;
9580 }
9581
9582 static void
9583 flushall() {
9584         INTOFF;
9585         fflush(stdout);
9586         INTON;
9587 }
9588
9589
9590 static void
9591 out2fmt(const char *fmt, ...)
9592 {
9593         va_list ap;
9594         va_start(ap, fmt);
9595         vfprintf(stderr, fmt, ap);
9596         va_end(ap);
9597 }
9598
9599
9600 static void
9601 out1fmt(const char *fmt, ...)
9602 {
9603         va_list ap;
9604         va_start(ap, fmt);
9605         vfprintf(stdout, fmt, ap);
9606         va_end(ap);
9607 }
9608
9609 /*
9610  * Version of write which resumes after a signal is caught.
9611  */
9612
9613 static int
9614 xwrite(int fd, const char *buf, int nbytes)
9615 {
9616         int ntry;
9617         int i;
9618         int n;
9619
9620         n = nbytes;
9621         ntry = 0;
9622         for (;;) {
9623                 i = write(fd, buf, n);
9624                 if (i > 0) {
9625                         if ((n -= i) <= 0)
9626                                 return nbytes;
9627                         buf += i;
9628                         ntry = 0;
9629                 } else if (i == 0) {
9630                         if (++ntry > 10)
9631                                 return nbytes - n;
9632                 } else if (errno != EINTR) {
9633                         return -1;
9634                 }
9635         }
9636 }
9637
9638
9639 /*
9640  * Shell command parser.
9641  */
9642
9643 #define EOFMARKLEN 79
9644
9645
9646
9647 struct heredoc {
9648         struct heredoc *next;   /* next here document in list */
9649         union node *here;               /* redirection node */
9650         char *eofmark;          /* string indicating end of input */
9651         int striptabs;          /* if set, strip leading tabs */
9652 };
9653
9654 static struct heredoc *heredoclist;     /* list of here documents to read */
9655 static int parsebackquote;              /* nonzero if we are inside backquotes */
9656 static int doprompt;                    /* if set, prompt the user */
9657 static int needprompt;                  /* true if interactive and at start of line */
9658 static int lasttoken;                   /* last token read */
9659
9660 static char *wordtext;                  /* text of last word returned by readtoken */
9661
9662 static struct nodelist *backquotelist;
9663 static union node *redirnode;
9664 struct heredoc *heredoc;
9665 static int quoteflag;                   /* set if (part of) last token was quoted */
9666 static int startlinno;                  /* line # where last token started */
9667
9668
9669 static union node *list (int);
9670 static union node *andor (void);
9671 static union node *pipeline (void);
9672 static union node *command (void);
9673 static union node *simplecmd (void);
9674 static void parsefname (void);
9675 static void parseheredoc (void);
9676 static int peektoken (void);
9677 static int readtoken (void);
9678 static int xxreadtoken (void);
9679 static int readtoken1 (int, char const *, char *, int);
9680 static int noexpand (char *);
9681 static void synexpect (int) __attribute__((noreturn));
9682 static void synerror (const char *) __attribute__((noreturn));
9683 static void setprompt (int);
9684
9685
9686 /*
9687  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9688  * valid parse tree indicating a blank line.)
9689  */
9690
9691 static union node *
9692 parsecmd(int interact)
9693 {
9694         int t;
9695
9696         tokpushback = 0;
9697         doprompt = interact;
9698         if (doprompt)
9699                 setprompt(1);
9700         else
9701                 setprompt(0);
9702         needprompt = 0;
9703         t = readtoken();
9704         if (t == TEOF)
9705                 return NEOF;
9706         if (t == TNL)
9707                 return NULL;
9708         tokpushback++;
9709         return list(1);
9710 }
9711
9712
9713 static union node *
9714 list(nlflag)
9715         int nlflag;
9716 {
9717         union node *n1, *n2, *n3;
9718         int tok;
9719
9720         checkkwd = 2;
9721         if (nlflag == 0 && tokendlist[peektoken()])
9722                 return NULL;
9723         n1 = NULL;
9724         for (;;) {
9725                 n2 = andor();
9726                 tok = readtoken();
9727                 if (tok == TBACKGND) {
9728                         if (n2->type == NCMD || n2->type == NPIPE) {
9729                                 n2->ncmd.backgnd = 1;
9730                         } else if (n2->type == NREDIR) {
9731                                 n2->type = NBACKGND;
9732                         } else {
9733                                 n3 = (union node *)stalloc(sizeof (struct nredir));
9734                                 n3->type = NBACKGND;
9735                                 n3->nredir.n = n2;
9736                                 n3->nredir.redirect = NULL;
9737                                 n2 = n3;
9738                         }
9739                 }
9740                 if (n1 == NULL) {
9741                         n1 = n2;
9742                 }
9743                 else {
9744                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9745                         n3->type = NSEMI;
9746                         n3->nbinary.ch1 = n1;
9747                         n3->nbinary.ch2 = n2;
9748                         n1 = n3;
9749                 }
9750                 switch (tok) {
9751                 case TBACKGND:
9752                 case TSEMI:
9753                         tok = readtoken();
9754                         /* fall through */
9755                 case TNL:
9756                         if (tok == TNL) {
9757                                 parseheredoc();
9758                                 if (nlflag)
9759                                         return n1;
9760                         } else {
9761                                 tokpushback++;
9762                         }
9763                         checkkwd = 2;
9764                         if (tokendlist[peektoken()])
9765                                 return n1;
9766                         break;
9767                 case TEOF:
9768                         if (heredoclist)
9769                                 parseheredoc();
9770                         else
9771                                 pungetc();              /* push back EOF on input */
9772                         return n1;
9773                 default:
9774                         if (nlflag)
9775                                 synexpect(-1);
9776                         tokpushback++;
9777                         return n1;
9778                 }
9779         }
9780 }
9781
9782
9783
9784 static union node *
9785 andor() {
9786         union node *n1, *n2, *n3;
9787         int t;
9788
9789         checkkwd = 1;
9790         n1 = pipeline();
9791         for (;;) {
9792                 if ((t = readtoken()) == TAND) {
9793                         t = NAND;
9794                 } else if (t == TOR) {
9795                         t = NOR;
9796                 } else {
9797                         tokpushback++;
9798                         return n1;
9799                 }
9800                 checkkwd = 2;
9801                 n2 = pipeline();
9802                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9803                 n3->type = t;
9804                 n3->nbinary.ch1 = n1;
9805                 n3->nbinary.ch2 = n2;
9806                 n1 = n3;
9807         }
9808 }
9809
9810
9811
9812 static union node *
9813 pipeline() {
9814         union node *n1, *n2, *pipenode;
9815         struct nodelist *lp, *prev;
9816         int negate;
9817
9818         negate = 0;
9819         TRACE(("pipeline: entered\n"));
9820         if (readtoken() == TNOT) {
9821                 negate = !negate;
9822                 checkkwd = 1;
9823         } else
9824                 tokpushback++;
9825         n1 = command();
9826         if (readtoken() == TPIPE) {
9827                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9828                 pipenode->type = NPIPE;
9829                 pipenode->npipe.backgnd = 0;
9830                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9831                 pipenode->npipe.cmdlist = lp;
9832                 lp->n = n1;
9833                 do {
9834                         prev = lp;
9835                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9836                         checkkwd = 2;
9837                         lp->n = command();
9838                         prev->next = lp;
9839                 } while (readtoken() == TPIPE);
9840                 lp->next = NULL;
9841                 n1 = pipenode;
9842         }
9843         tokpushback++;
9844         if (negate) {
9845                 n2 = (union node *)stalloc(sizeof (struct nnot));
9846                 n2->type = NNOT;
9847                 n2->nnot.com = n1;
9848                 return n2;
9849         } else
9850                 return n1;
9851 }
9852
9853
9854
9855 static union node *
9856 command() {
9857         union node *n1, *n2;
9858         union node *ap, **app;
9859         union node *cp, **cpp;
9860         union node *redir, **rpp;
9861         int t;
9862
9863         redir = NULL;
9864         n1 = NULL;
9865         rpp = &redir;
9866
9867         switch (readtoken()) {
9868         case TIF:
9869                 n1 = (union node *)stalloc(sizeof (struct nif));
9870                 n1->type = NIF;
9871                 n1->nif.test = list(0);
9872                 if (readtoken() != TTHEN)
9873                         synexpect(TTHEN);
9874                 n1->nif.ifpart = list(0);
9875                 n2 = n1;
9876                 while (readtoken() == TELIF) {
9877                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9878                         n2 = n2->nif.elsepart;
9879                         n2->type = NIF;
9880                         n2->nif.test = list(0);
9881                         if (readtoken() != TTHEN)
9882                                 synexpect(TTHEN);
9883                         n2->nif.ifpart = list(0);
9884                 }
9885                 if (lasttoken == TELSE)
9886                         n2->nif.elsepart = list(0);
9887                 else {
9888                         n2->nif.elsepart = NULL;
9889                         tokpushback++;
9890                 }
9891                 if (readtoken() != TFI)
9892                         synexpect(TFI);
9893                 checkkwd = 1;
9894                 break;
9895         case TWHILE:
9896         case TUNTIL: {
9897                 int got;
9898                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9899                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9900                 n1->nbinary.ch1 = list(0);
9901                 if ((got=readtoken()) != TDO) {
9902 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
9903                         synexpect(TDO);
9904                 }
9905                 n1->nbinary.ch2 = list(0);
9906                 if (readtoken() != TDONE)
9907                         synexpect(TDONE);
9908                 checkkwd = 1;
9909                 break;
9910         }
9911         case TFOR:
9912                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9913                         synerror("Bad for loop variable");
9914                 n1 = (union node *)stalloc(sizeof (struct nfor));
9915                 n1->type = NFOR;
9916                 n1->nfor.var = wordtext;
9917                 checkkwd = 1;
9918                 if (readtoken() == TIN) {
9919                         app = &ap;
9920                         while (readtoken() == TWORD) {
9921                                 n2 = (union node *)stalloc(sizeof (struct narg));
9922                                 n2->type = NARG;
9923                                 n2->narg.text = wordtext;
9924                                 n2->narg.backquote = backquotelist;
9925                                 *app = n2;
9926                                 app = &n2->narg.next;
9927                         }
9928                         *app = NULL;
9929                         n1->nfor.args = ap;
9930                         if (lasttoken != TNL && lasttoken != TSEMI)
9931                                 synexpect(-1);
9932                 } else {
9933                         static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9934                                                                    '@', '=', '\0'};
9935                         n2 = (union node *)stalloc(sizeof (struct narg));
9936                         n2->type = NARG;
9937                         n2->narg.text = argvars;
9938                         n2->narg.backquote = NULL;
9939                         n2->narg.next = NULL;
9940                         n1->nfor.args = n2;
9941                         /*
9942                          * Newline or semicolon here is optional (but note
9943                          * that the original Bourne shell only allowed NL).
9944                          */
9945                         if (lasttoken != TNL && lasttoken != TSEMI)
9946                                 tokpushback++;
9947                 }
9948                 checkkwd = 2;
9949                 if (readtoken() != TDO)
9950                         synexpect(TDO);
9951                 n1->nfor.body = list(0);
9952                 if (readtoken() != TDONE)
9953                         synexpect(TDONE);
9954                 checkkwd = 1;
9955                 break;
9956         case TCASE:
9957                 n1 = (union node *)stalloc(sizeof (struct ncase));
9958                 n1->type = NCASE;
9959                 if (readtoken() != TWORD)
9960                         synexpect(TWORD);
9961                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9962                 n2->type = NARG;
9963                 n2->narg.text = wordtext;
9964                 n2->narg.backquote = backquotelist;
9965                 n2->narg.next = NULL;
9966                 do {
9967                         checkkwd = 1;
9968                 } while (readtoken() == TNL);
9969                 if (lasttoken != TIN)
9970                         synerror("expecting \"in\"");
9971                 cpp = &n1->ncase.cases;
9972                 checkkwd = 2, readtoken();
9973                 do {
9974                         if (lasttoken == TLP)
9975                                 readtoken();
9976                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9977                         cp->type = NCLIST;
9978                         app = &cp->nclist.pattern;
9979                         for (;;) {
9980                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9981                                 ap->type = NARG;
9982                                 ap->narg.text = wordtext;
9983                                 ap->narg.backquote = backquotelist;
9984                                 if (checkkwd = 2, readtoken() != TPIPE)
9985                                         break;
9986                                 app = &ap->narg.next;
9987                                 readtoken();
9988                         }
9989                         ap->narg.next = NULL;
9990                         if (lasttoken != TRP)
9991                                 synexpect(TRP);
9992                         cp->nclist.body = list(0);
9993
9994                         checkkwd = 2;
9995                         if ((t = readtoken()) != TESAC) {
9996                                 if (t != TENDCASE)
9997                                         synexpect(TENDCASE);
9998                                 else
9999                                         checkkwd = 2, readtoken();
10000                         }
10001                         cpp = &cp->nclist.next;
10002                 } while(lasttoken != TESAC);
10003                 *cpp = NULL;
10004                 checkkwd = 1;
10005                 break;
10006         case TLP:
10007                 n1 = (union node *)stalloc(sizeof (struct nredir));
10008                 n1->type = NSUBSHELL;
10009                 n1->nredir.n = list(0);
10010                 n1->nredir.redirect = NULL;
10011                 if (readtoken() != TRP)
10012                         synexpect(TRP);
10013                 checkkwd = 1;
10014                 break;
10015         case TBEGIN:
10016                 n1 = list(0);
10017                 if (readtoken() != TEND)
10018                         synexpect(TEND);
10019                 checkkwd = 1;
10020                 break;
10021         /* Handle an empty command like other simple commands.  */
10022         case TSEMI:
10023         case TAND:
10024         case TOR:
10025         case TNL:
10026         case TEOF:
10027         case TRP:
10028         case TBACKGND:
10029                 /*
10030                  * An empty command before a ; doesn't make much sense, and
10031                  * should certainly be disallowed in the case of `if ;'.
10032                  */
10033                 if (!redir)
10034                         synexpect(-1);
10035         case TWORD:
10036         case TREDIR:
10037                 tokpushback++;
10038                 n1 = simplecmd();
10039                 return n1;
10040         default:
10041                 synexpect(-1);
10042                 /* NOTREACHED */
10043         }
10044
10045         /* Now check for redirection which may follow command */
10046         while (readtoken() == TREDIR) {
10047                 *rpp = n2 = redirnode;
10048                 rpp = &n2->nfile.next;
10049                 parsefname();
10050         }
10051         tokpushback++;
10052         *rpp = NULL;
10053         if (redir) {
10054                 if (n1->type != NSUBSHELL) {
10055                         n2 = (union node *)stalloc(sizeof (struct nredir));
10056                         n2->type = NREDIR;
10057                         n2->nredir.n = n1;
10058                         n1 = n2;
10059                 }
10060                 n1->nredir.redirect = redir;
10061         }
10062
10063         return n1;
10064 }
10065
10066
10067 static union node *
10068 simplecmd() {
10069         union node *args, **app;
10070         union node *n = NULL;
10071         union node *vars, **vpp;
10072         union node **rpp, *redir;
10073
10074         args = NULL;
10075         app = &args;
10076         vars = NULL;
10077         vpp = &vars;
10078         redir = NULL;
10079         rpp = &redir;
10080
10081 #ifdef ASH_ALIAS
10082         checkalias = 2;
10083 #endif
10084         for (;;) {
10085                 switch (readtoken()) {
10086                 case TWORD:
10087                 case TASSIGN:
10088                         n = (union node *)stalloc(sizeof (struct narg));
10089                         n->type = NARG;
10090                         n->narg.text = wordtext;
10091                         n->narg.backquote = backquotelist;
10092                         if (lasttoken == TWORD) {
10093                                 *app = n;
10094                                 app = &n->narg.next;
10095                         } else {
10096                                 *vpp = n;
10097                                 vpp = &n->narg.next;
10098                         }
10099                         break;
10100                 case TREDIR:
10101                         *rpp = n = redirnode;
10102                         rpp = &n->nfile.next;
10103                         parsefname();   /* read name of redirection file */
10104                         break;
10105                 case TLP:
10106                         if (
10107                                 args && app == &args->narg.next &&
10108                                 !vars && !redir
10109                         ) {
10110                                 /* We have a function */
10111                                 if (readtoken() != TRP)
10112                                         synexpect(TRP);
10113                                 n->type = NDEFUN;
10114                                 checkkwd = 2;
10115                                 n->narg.next = command();
10116                                 return n;
10117                         }
10118                         /* fall through */
10119                 default:
10120                         tokpushback++;
10121                         goto out;
10122                 }
10123         }
10124 out:
10125         *app = NULL;
10126         *vpp = NULL;
10127         *rpp = NULL;
10128         n = (union node *)stalloc(sizeof (struct ncmd));
10129         n->type = NCMD;
10130         n->ncmd.backgnd = 0;
10131         n->ncmd.args = args;
10132         n->ncmd.assign = vars;
10133         n->ncmd.redirect = redir;
10134         return n;
10135 }
10136
10137 static union node *
10138 makename(void) {
10139         union node *n;
10140
10141         n = (union node *)stalloc(sizeof (struct narg));
10142         n->type = NARG;
10143         n->narg.next = NULL;
10144         n->narg.text = wordtext;
10145         n->narg.backquote = backquotelist;
10146         return n;
10147 }
10148
10149 static void fixredir(union node *n, const char *text, int err)
10150 {
10151         TRACE(("Fix redir %s %d\n", text, err));
10152         if (!err)
10153                 n->ndup.vname = NULL;
10154
10155         if (is_digit(text[0]) && text[1] == '\0')
10156                 n->ndup.dupfd = digit_val(text[0]);
10157         else if (text[0] == '-' && text[1] == '\0')
10158                 n->ndup.dupfd = -1;
10159         else {
10160
10161                 if (err)
10162                         synerror("Bad fd number");
10163                 else
10164                         n->ndup.vname = makename();
10165         }
10166 }
10167
10168
10169 static void
10170 parsefname(void) {
10171         union node *n = redirnode;
10172
10173         if (readtoken() != TWORD)
10174                 synexpect(-1);
10175         if (n->type == NHERE) {
10176                 struct heredoc *here = heredoc;
10177                 struct heredoc *p;
10178                 int i;
10179
10180                 if (quoteflag == 0)
10181                         n->type = NXHERE;
10182                 TRACE(("Here document %d\n", n->type));
10183                 if (here->striptabs) {
10184                         while (*wordtext == '\t')
10185                                 wordtext++;
10186                 }
10187                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10188                         synerror("Illegal eof marker for << redirection");
10189                 rmescapes(wordtext);
10190                 here->eofmark = wordtext;
10191                 here->next = NULL;
10192                 if (heredoclist == NULL)
10193                         heredoclist = here;
10194                 else {
10195                         for (p = heredoclist ; p->next ; p = p->next);
10196                         p->next = here;
10197                 }
10198         } else if (n->type == NTOFD || n->type == NFROMFD) {
10199                 fixredir(n, wordtext, 0);
10200         } else {
10201                 n->nfile.fname = makename();
10202         }
10203 }
10204
10205
10206 /*
10207  * Input any here documents.
10208  */
10209
10210 static void
10211 parseheredoc() {
10212         struct heredoc *here;
10213         union node *n;
10214
10215         while (heredoclist) {
10216                 here = heredoclist;
10217                 heredoclist = here->next;
10218                 if (needprompt) {
10219                         setprompt(2);
10220                         needprompt = 0;
10221                 }
10222                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10223                                 here->eofmark, here->striptabs);
10224                 n = (union node *)stalloc(sizeof (struct narg));
10225                 n->narg.type = NARG;
10226                 n->narg.next = NULL;
10227                 n->narg.text = wordtext;
10228                 n->narg.backquote = backquotelist;
10229                 here->here->nhere.doc = n;
10230         }
10231 }
10232
10233 static int
10234 peektoken() {
10235         int t;
10236
10237         t = readtoken();
10238         tokpushback++;
10239         return (t);
10240 }
10241
10242 static int
10243 readtoken() {
10244         int t;
10245 #ifdef ASH_ALIAS
10246         int savecheckkwd = checkkwd;
10247         int savecheckalias = checkalias;
10248         struct alias *ap;
10249 #endif
10250
10251 #ifdef DEBUG
10252         int alreadyseen = tokpushback;
10253 #endif
10254
10255 #ifdef ASH_ALIAS
10256 top:
10257 #endif
10258
10259         t = xxreadtoken();
10260
10261 #ifdef ASH_ALIAS
10262         checkalias = savecheckalias;
10263 #endif
10264
10265         if (checkkwd) {
10266                 /*
10267                  * eat newlines
10268                  */
10269                 if (checkkwd == 2) {
10270                         checkkwd = 0;
10271                         while (t == TNL) {
10272                                 parseheredoc();
10273                                 t = xxreadtoken();
10274                         }
10275                 }
10276                 checkkwd = 0;
10277                 /*
10278                  * check for keywords
10279                  */
10280                 if (t == TWORD && !quoteflag)
10281                 {
10282                         const char *const *pp;
10283
10284                         if ((pp = findkwd(wordtext))) {
10285                                 lasttoken = t = pp - parsekwd + KWDOFFSET;
10286                                 TRACE(("keyword %s recognized\n", tokname[t]));
10287                                 goto out;
10288                         }
10289                 }
10290         }
10291
10292 #ifdef ASH_ALIAS
10293         if (t != TWORD) {
10294                 if (t != TREDIR) {
10295                         checkalias = 0;
10296                 }
10297         } else if (checkalias == 2 && isassignment(wordtext)) {
10298                 lasttoken = t = TASSIGN;
10299         } else if (checkalias) {
10300                 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10301                         if (*ap->val) {
10302                                 pushstring(ap->val, strlen(ap->val), ap);
10303                         }
10304                         checkkwd = savecheckkwd;
10305                         goto top;
10306                 }
10307                 checkalias = 0;
10308         }
10309 #endif
10310 out:
10311 #ifdef DEBUG
10312         if (!alreadyseen)
10313             TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10314         else
10315             TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10316 #endif
10317         return (t);
10318 }
10319
10320
10321 /*
10322  * Read the next input token.
10323  * If the token is a word, we set backquotelist to the list of cmds in
10324  *      backquotes.  We set quoteflag to true if any part of the word was
10325  *      quoted.
10326  * If the token is TREDIR, then we set redirnode to a structure containing
10327  *      the redirection.
10328  * In all cases, the variable startlinno is set to the number of the line
10329  *      on which the token starts.
10330  *
10331  * [Change comment:  here documents and internal procedures]
10332  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10333  *  word parsing code into a separate routine.  In this case, readtoken
10334  *  doesn't need to have any internal procedures, but parseword does.
10335  *  We could also make parseoperator in essence the main routine, and
10336  *  have parseword (readtoken1?) handle both words and redirection.]
10337  */
10338
10339 #define RETURN(token)   return lasttoken = token
10340
10341 static int
10342 xxreadtoken() {
10343         int c;
10344
10345         if (tokpushback) {
10346                 tokpushback = 0;
10347                 return lasttoken;
10348         }
10349         if (needprompt) {
10350                 setprompt(2);
10351                 needprompt = 0;
10352         }
10353         startlinno = plinno;
10354         for (;;) {      /* until token or start of word found */
10355                 c = pgetc_macro();
10356                 switch (c) {
10357                 case ' ': case '\t':
10358 #ifdef ASH_ALIAS
10359                 case PEOA:
10360 #endif
10361                         continue;
10362                 case '#':
10363                         while ((c = pgetc()) != '\n' && c != PEOF);
10364                         pungetc();
10365                         continue;
10366                 case '\\':
10367                         if (pgetc() == '\n') {
10368                                 startlinno = ++plinno;
10369                                 if (doprompt)
10370                                         setprompt(2);
10371                                 else
10372                                         setprompt(0);
10373                                 continue;
10374                         }
10375                         pungetc();
10376                         goto breakloop;
10377                 case '\n':
10378                         plinno++;
10379                         needprompt = doprompt;
10380                         RETURN(TNL);
10381                 case PEOF:
10382                         RETURN(TEOF);
10383                 case '&':
10384                         if (pgetc() == '&')
10385                                 RETURN(TAND);
10386                         pungetc();
10387                         RETURN(TBACKGND);
10388                 case '|':
10389                         if (pgetc() == '|')
10390                                 RETURN(TOR);
10391                         pungetc();
10392                         RETURN(TPIPE);
10393                 case ';':
10394                         if (pgetc() == ';')
10395                                 RETURN(TENDCASE);
10396                         pungetc();
10397                         RETURN(TSEMI);
10398                 case '(':
10399                         RETURN(TLP);
10400                 case ')':
10401                         RETURN(TRP);
10402                 default:
10403                         goto breakloop;
10404                 }
10405         }
10406 breakloop:
10407         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10408 #undef RETURN
10409 }
10410
10411
10412
10413 /*
10414  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10415  * is not NULL, read a here document.  In the latter case, eofmark is the
10416  * word which marks the end of the document and striptabs is true if
10417  * leading tabs should be stripped from the document.  The argument firstc
10418  * is the first character of the input token or document.
10419  *
10420  * Because C does not have internal subroutines, I have simulated them
10421  * using goto's to implement the subroutine linkage.  The following macros
10422  * will run code that appears at the end of readtoken1.
10423  */
10424
10425 #define CHECKEND()      {goto checkend; checkend_return:;}
10426 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10427 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10428 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10429 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10430 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10431
10432 static int
10433 readtoken1(firstc, syntax, eofmark, striptabs)
10434         int firstc;
10435         char const *syntax;
10436         char *eofmark;
10437         int striptabs;
10438         {
10439         int c = firstc;
10440         char *out;
10441         int len;
10442         char line[EOFMARKLEN + 1];
10443         struct nodelist *bqlist;
10444         int quotef;
10445         int dblquote;
10446         int varnest;    /* levels of variables expansion */
10447         int arinest;    /* levels of arithmetic expansion */
10448         int parenlevel; /* levels of parens in arithmetic */
10449         int dqvarnest;  /* levels of variables expansion within double quotes */
10450         int oldstyle;
10451         char const *prevsyntax; /* syntax before arithmetic */
10452 #if __GNUC__
10453         /* Avoid longjmp clobbering */
10454         (void) &out;
10455         (void) &quotef;
10456         (void) &dblquote;
10457         (void) &varnest;
10458         (void) &arinest;
10459         (void) &parenlevel;
10460         (void) &dqvarnest;
10461         (void) &oldstyle;
10462         (void) &prevsyntax;
10463         (void) &syntax;
10464 #endif
10465
10466         startlinno = plinno;
10467         dblquote = 0;
10468         if (syntax == DQSYNTAX)
10469                 dblquote = 1;
10470         quotef = 0;
10471         bqlist = NULL;
10472         varnest = 0;
10473         arinest = 0;
10474         parenlevel = 0;
10475         dqvarnest = 0;
10476
10477         STARTSTACKSTR(out);
10478         loop: { /* for each line, until end of word */
10479                 CHECKEND();     /* set c to PEOF if at end of here document */
10480                 for (;;) {      /* until end of line or end of word */
10481                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10482                         switch(syntax[c]) {
10483                         case CNL:       /* '\n' */
10484                                 if (syntax == BASESYNTAX)
10485                                         goto endword;   /* exit outer loop */
10486                                 USTPUTC(c, out);
10487                                 plinno++;
10488                                 if (doprompt)
10489                                         setprompt(2);
10490                                 else
10491                                         setprompt(0);
10492                                 c = pgetc();
10493                                 goto loop;              /* continue outer loop */
10494                         case CWORD:
10495                                 USTPUTC(c, out);
10496                                 break;
10497                         case CCTL:
10498                                 if ((eofmark == NULL || dblquote) &&
10499                                     dqvarnest == 0)
10500                                         USTPUTC(CTLESC, out);
10501                                 USTPUTC(c, out);
10502                                 break;
10503                         case CBACK:     /* backslash */
10504                                 c = pgetc2();
10505                                 if (c == PEOF) {
10506                                         USTPUTC('\\', out);
10507                                         pungetc();
10508                                 } else if (c == '\n') {
10509                                         if (doprompt)
10510                                                 setprompt(2);
10511                                         else
10512                                                 setprompt(0);
10513                                 } else {
10514                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10515                                                          && (c != '"' || eofmark != NULL))
10516                                                 USTPUTC('\\', out);
10517                                         if (SQSYNTAX[c] == CCTL)
10518                                                 USTPUTC(CTLESC, out);
10519                                         else if (eofmark == NULL)
10520                                                 USTPUTC(CTLQUOTEMARK, out);
10521                                         USTPUTC(c, out);
10522                                         quotef++;
10523                                 }
10524                                 break;
10525                         case CSQUOTE:
10526                                 if (eofmark == NULL)
10527                                         USTPUTC(CTLQUOTEMARK, out);
10528                                 syntax = SQSYNTAX;
10529                                 break;
10530                         case CDQUOTE:
10531                                 if (eofmark == NULL)
10532                                         USTPUTC(CTLQUOTEMARK, out);
10533                                 syntax = DQSYNTAX;
10534                                 dblquote = 1;
10535                                 break;
10536                         case CENDQUOTE:
10537                                 if (eofmark != NULL && arinest == 0 &&
10538                                     varnest == 0) {
10539                                         USTPUTC(c, out);
10540                                 } else {
10541                                         if (arinest) {
10542                                                 syntax = ARISYNTAX;
10543                                                 dblquote = 0;
10544                                         } else if (eofmark == NULL &&
10545                                                    dqvarnest == 0) {
10546                                                 syntax = BASESYNTAX;
10547                                                 dblquote = 0;
10548                                         }
10549                                         quotef++;
10550                                 }
10551                                 break;
10552                         case CVAR:      /* '$' */
10553                                 PARSESUB();             /* parse substitution */
10554                                 break;
10555                         case CENDVAR:   /* '}' */
10556                                 if (varnest > 0) {
10557                                         varnest--;
10558                                         if (dqvarnest > 0) {
10559                                                 dqvarnest--;
10560                                         }
10561                                         USTPUTC(CTLENDVAR, out);
10562                                 } else {
10563                                         USTPUTC(c, out);
10564                                 }
10565                                 break;
10566 #ifdef ASH_MATH_SUPPORT
10567                         case CLP:       /* '(' in arithmetic */
10568                                 parenlevel++;
10569                                 USTPUTC(c, out);
10570                                 break;
10571                         case CRP:       /* ')' in arithmetic */
10572                                 if (parenlevel > 0) {
10573                                         USTPUTC(c, out);
10574                                         --parenlevel;
10575                                 } else {
10576                                         if (pgetc() == ')') {
10577                                                 if (--arinest == 0) {
10578                                                         USTPUTC(CTLENDARI, out);
10579                                                         syntax = prevsyntax;
10580                                                         if (syntax == DQSYNTAX)
10581                                                                 dblquote = 1;
10582                                                         else
10583                                                                 dblquote = 0;
10584                                                 } else
10585                                                         USTPUTC(')', out);
10586                                         } else {
10587                                                 /*
10588                                                  * unbalanced parens
10589                                                  *  (don't 2nd guess - no error)
10590                                                  */
10591                                                 pungetc();
10592                                                 USTPUTC(')', out);
10593                                         }
10594                                 }
10595                                 break;
10596 #endif
10597                         case CBQUOTE:   /* '`' */
10598                                 PARSEBACKQOLD();
10599                                 break;
10600                         case CENDFILE:
10601                                 goto endword;           /* exit outer loop */
10602                         case CIGN:
10603                                 break;
10604                         default:
10605                                 if (varnest == 0)
10606                                         goto endword;   /* exit outer loop */
10607 #ifdef ASH_ALIAS
10608                                 if (c != PEOA)
10609 #endif
10610                                         USTPUTC(c, out);
10611
10612                         }
10613                         c = pgetc_macro();
10614                 }
10615         }
10616 endword:
10617         if (syntax == ARISYNTAX)
10618                 synerror("Missing '))'");
10619         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10620                 synerror("Unterminated quoted string");
10621         if (varnest != 0) {
10622                 startlinno = plinno;
10623                 synerror("Missing '}'");
10624         }
10625         USTPUTC('\0', out);
10626         len = out - stackblock();
10627         out = stackblock();
10628         if (eofmark == NULL) {
10629                 if ((c == '>' || c == '<')
10630                  && quotef == 0
10631                  && len <= 2
10632                  && (*out == '\0' || is_digit(*out))) {
10633                         PARSEREDIR();
10634                         return lasttoken = TREDIR;
10635                 } else {
10636                         pungetc();
10637                 }
10638         }
10639         quoteflag = quotef;
10640         backquotelist = bqlist;
10641         grabstackblock(len);
10642         wordtext = out;
10643         return lasttoken = TWORD;
10644 /* end of readtoken routine */
10645
10646
10647
10648 /*
10649  * Check to see whether we are at the end of the here document.  When this
10650  * is called, c is set to the first character of the next input line.  If
10651  * we are at the end of the here document, this routine sets the c to PEOF.
10652  */
10653
10654 checkend: {
10655         if (eofmark) {
10656 #ifdef ASH_ALIAS
10657                 if (c == PEOA) {
10658                         c = pgetc2();
10659                 }
10660 #endif
10661                 if (striptabs) {
10662                         while (c == '\t') {
10663                                 c = pgetc2();
10664                         }
10665                 }
10666                 if (c == *eofmark) {
10667                         if (pfgets(line, sizeof line) != NULL) {
10668                                 char *p, *q;
10669
10670                                 p = line;
10671                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10672                                 if (*p == '\n' && *q == '\0') {
10673                                         c = PEOF;
10674                                         plinno++;
10675                                         needprompt = doprompt;
10676                                 } else {
10677                                         pushstring(line, strlen(line), NULL);
10678                                 }
10679                         }
10680                 }
10681         }
10682         goto checkend_return;
10683 }
10684
10685
10686 /*
10687  * Parse a redirection operator.  The variable "out" points to a string
10688  * specifying the fd to be redirected.  The variable "c" contains the
10689  * first character of the redirection operator.
10690  */
10691
10692 parseredir: {
10693         char fd = *out;
10694         union node *np;
10695
10696         np = (union node *)stalloc(sizeof (struct nfile));
10697         if (c == '>') {
10698                 np->nfile.fd = 1;
10699                 c = pgetc();
10700                 if (c == '>')
10701                         np->type = NAPPEND;
10702                 else if (c == '&')
10703                         np->type = NTOFD;
10704                 else if (c == '|')
10705                         np->type = NTOOV;
10706                 else {
10707                         np->type = NTO;
10708                         pungetc();
10709                 }
10710         } else {        /* c == '<' */
10711                 np->nfile.fd = 0;
10712                 switch (c = pgetc()) {
10713                 case '<':
10714                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10715                                 np = (union node *)stalloc(sizeof (struct nhere));
10716                                 np->nfile.fd = 0;
10717                         }
10718                         np->type = NHERE;
10719                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10720                         heredoc->here = np;
10721                         if ((c = pgetc()) == '-') {
10722                                 heredoc->striptabs = 1;
10723                         } else {
10724                                 heredoc->striptabs = 0;
10725                                 pungetc();
10726                         }
10727                         break;
10728
10729                 case '&':
10730                         np->type = NFROMFD;
10731                         break;
10732
10733                 case '>':
10734                         np->type = NFROMTO;
10735                         break;
10736
10737                 default:
10738                         np->type = NFROM;
10739                         pungetc();
10740                         break;
10741                 }
10742         }
10743         if (fd != '\0')
10744                 np->nfile.fd = digit_val(fd);
10745         redirnode = np;
10746         goto parseredir_return;
10747 }
10748
10749
10750 /*
10751  * Parse a substitution.  At this point, we have read the dollar sign
10752  * and nothing else.
10753  */
10754
10755 parsesub: {
10756         int subtype;
10757         int typeloc;
10758         int flags;
10759         char *p;
10760         static const char types[] = "}-+?=";
10761
10762         c = pgetc();
10763         if (
10764                 c <= PEOA  ||
10765                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10766         ) {
10767                 USTPUTC('$', out);
10768                 pungetc();
10769         } else if (c == '(') {  /* $(command) or $((arith)) */
10770                 if (pgetc() == '(') {
10771                         PARSEARITH();
10772                 } else {
10773                         pungetc();
10774                         PARSEBACKQNEW();
10775                 }
10776         } else {
10777                 USTPUTC(CTLVAR, out);
10778                 typeloc = out - stackblock();
10779                 USTPUTC(VSNORMAL, out);
10780                 subtype = VSNORMAL;
10781                 if (c == '{') {
10782                         c = pgetc();
10783                         if (c == '#') {
10784                                 if ((c = pgetc()) == '}')
10785                                         c = '#';
10786                                 else
10787                                         subtype = VSLENGTH;
10788                         }
10789                         else
10790                                 subtype = 0;
10791                 }
10792                 if (c > PEOA && is_name(c)) {
10793                         do {
10794                                 STPUTC(c, out);
10795                                 c = pgetc();
10796                         } while (c > PEOA && is_in_name(c));
10797                 } else if (is_digit(c)) {
10798                         do {
10799                                 USTPUTC(c, out);
10800                                 c = pgetc();
10801                         } while (is_digit(c));
10802                 }
10803                 else if (is_special(c)) {
10804                         USTPUTC(c, out);
10805                         c = pgetc();
10806                 }
10807                 else
10808 badsub:                 synerror("Bad substitution");
10809
10810                 STPUTC('=', out);
10811                 flags = 0;
10812                 if (subtype == 0) {
10813                         switch (c) {
10814                         case ':':
10815                                 flags = VSNUL;
10816                                 c = pgetc();
10817                                 /*FALLTHROUGH*/
10818                         default:
10819                                 p = strchr(types, c);
10820                                 if (p == NULL)
10821                                         goto badsub;
10822                                 subtype = p - types + VSNORMAL;
10823                                 break;
10824                         case '%':
10825                         case '#':
10826                                 {
10827                                         int cc = c;
10828                                         subtype = c == '#' ? VSTRIMLEFT :
10829                                                              VSTRIMRIGHT;
10830                                         c = pgetc();
10831                                         if (c == cc)
10832                                                 subtype++;
10833                                         else
10834                                                 pungetc();
10835                                         break;
10836                                 }
10837                         }
10838                 } else {
10839                         pungetc();
10840                 }
10841                 if (dblquote || arinest)
10842                         flags |= VSQUOTE;
10843                 *(stackblock() + typeloc) = subtype | flags;
10844                 if (subtype != VSNORMAL) {
10845                         varnest++;
10846                         if (dblquote) {
10847                                 dqvarnest++;
10848                         }
10849                 }
10850         }
10851         goto parsesub_return;
10852 }
10853
10854
10855 /*
10856  * Called to parse command substitutions.  Newstyle is set if the command
10857  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10858  * list of commands (passed by reference), and savelen is the number of
10859  * characters on the top of the stack which must be preserved.
10860  */
10861
10862 parsebackq: {
10863         struct nodelist **nlpp;
10864         int savepbq;
10865         union node *n;
10866         char *volatile str;
10867         struct jmploc jmploc;
10868         struct jmploc *volatile savehandler;
10869         int savelen;
10870         int saveprompt;
10871 #ifdef __GNUC__
10872         (void) &saveprompt;
10873 #endif
10874
10875         savepbq = parsebackquote;
10876         if (setjmp(jmploc.loc)) {
10877                 if (str)
10878                         ckfree(str);
10879                 parsebackquote = 0;
10880                 handler = savehandler;
10881                 longjmp(handler->loc, 1);
10882         }
10883         INTOFF;
10884         str = NULL;
10885         savelen = out - stackblock();
10886         if (savelen > 0) {
10887                 str = ckmalloc(savelen);
10888                 memcpy(str, stackblock(), savelen);
10889         }
10890         savehandler = handler;
10891         handler = &jmploc;
10892         INTON;
10893         if (oldstyle) {
10894                 /* We must read until the closing backquote, giving special
10895                    treatment to some slashes, and then push the string and
10896                    reread it as input, interpreting it normally.  */
10897                 char *pout;
10898                 int pc;
10899                 int psavelen;
10900                 char *pstr;
10901
10902
10903                 STARTSTACKSTR(pout);
10904                 for (;;) {
10905                         if (needprompt) {
10906                                 setprompt(2);
10907                                 needprompt = 0;
10908                         }
10909                         switch (pc = pgetc()) {
10910                         case '`':
10911                                 goto done;
10912
10913                         case '\\':
10914                                 if ((pc = pgetc()) == '\n') {
10915                                         plinno++;
10916                                         if (doprompt)
10917                                                 setprompt(2);
10918                                         else
10919                                                 setprompt(0);
10920                                         /*
10921                                          * If eating a newline, avoid putting
10922                                          * the newline into the new character
10923                                          * stream (via the STPUTC after the
10924                                          * switch).
10925                                          */
10926                                         continue;
10927                                 }
10928                                 if (pc != '\\' && pc != '`' && pc != '$'
10929                                     && (!dblquote || pc != '"'))
10930                                         STPUTC('\\', pout);
10931                                 if (pc > PEOA) {
10932                                         break;
10933                                 }
10934                                 /* fall through */
10935
10936                         case PEOF:
10937 #ifdef ASH_ALIAS
10938                         case PEOA:
10939 #endif
10940                                 startlinno = plinno;
10941                                 synerror("EOF in backquote substitution");
10942
10943                         case '\n':
10944                                 plinno++;
10945                                 needprompt = doprompt;
10946                                 break;
10947
10948                         default:
10949                                 break;
10950                         }
10951                         STPUTC(pc, pout);
10952                 }
10953 done:
10954                 STPUTC('\0', pout);
10955                 psavelen = pout - stackblock();
10956                 if (psavelen > 0) {
10957                         pstr = grabstackstr(pout);
10958                         setinputstring(pstr);
10959                 }
10960         }
10961         nlpp = &bqlist;
10962         while (*nlpp)
10963                 nlpp = &(*nlpp)->next;
10964         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10965         (*nlpp)->next = NULL;
10966         parsebackquote = oldstyle;
10967
10968         if (oldstyle) {
10969                 saveprompt = doprompt;
10970                 doprompt = 0;
10971         }
10972
10973         n = list(0);
10974
10975         if (oldstyle)
10976                 doprompt = saveprompt;
10977         else {
10978                 if (readtoken() != TRP)
10979                         synexpect(TRP);
10980         }
10981
10982         (*nlpp)->n = n;
10983         if (oldstyle) {
10984                 /*
10985                  * Start reading from old file again, ignoring any pushed back
10986                  * tokens left from the backquote parsing
10987                  */
10988                 popfile();
10989                 tokpushback = 0;
10990         }
10991         while (stackblocksize() <= savelen)
10992                 growstackblock();
10993         STARTSTACKSTR(out);
10994         if (str) {
10995                 memcpy(out, str, savelen);
10996                 STADJUST(savelen, out);
10997                 INTOFF;
10998                 ckfree(str);
10999                 str = NULL;
11000                 INTON;
11001         }
11002         parsebackquote = savepbq;
11003         handler = savehandler;
11004         if (arinest || dblquote)
11005                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11006         else
11007                 USTPUTC(CTLBACKQ, out);
11008         if (oldstyle)
11009                 goto parsebackq_oldreturn;
11010         else
11011                 goto parsebackq_newreturn;
11012 }
11013
11014 /*
11015  * Parse an arithmetic expansion (indicate start of one and set state)
11016  */
11017 parsearith: {
11018
11019         if (++arinest == 1) {
11020                 prevsyntax = syntax;
11021                 syntax = ARISYNTAX;
11022                 USTPUTC(CTLARI, out);
11023                 if (dblquote)
11024                         USTPUTC('"',out);
11025                 else
11026                         USTPUTC(' ',out);
11027         } else {
11028                 /*
11029                  * we collapse embedded arithmetic expansion to
11030                  * parenthesis, which should be equivalent
11031                  */
11032                 USTPUTC('(', out);
11033         }
11034         goto parsearith_return;
11035 }
11036
11037 } /* end of readtoken */
11038
11039
11040 /*
11041  * Returns true if the text contains nothing to expand (no dollar signs
11042  * or backquotes).
11043  */
11044
11045 static int
11046 noexpand(text)
11047         char *text;
11048         {
11049         char *p;
11050         char c;
11051
11052         p = text;
11053         while ((c = *p++) != '\0') {
11054                 if (c == CTLQUOTEMARK)
11055                         continue;
11056                 if (c == CTLESC)
11057                         p++;
11058                 else if (BASESYNTAX[(int)c] == CCTL)
11059                         return 0;
11060         }
11061         return 1;
11062 }
11063
11064
11065 /*
11066  * Return true if the argument is a legal variable name (a letter or
11067  * underscore followed by zero or more letters, underscores, and digits).
11068  */
11069
11070 static int
11071 goodname(const char *name)
11072 {
11073         const char *p;
11074
11075         p = name;
11076         if (! is_name(*p))
11077                 return 0;
11078         while (*++p) {
11079                 if (! is_in_name(*p))
11080                         return 0;
11081         }
11082         return 1;
11083 }
11084
11085
11086 /*
11087  * Called when an unexpected token is read during the parse.  The argument
11088  * is the token that is expected, or -1 if more than one type of token can
11089  * occur at this point.
11090  */
11091
11092 static void
11093 synexpect(token)
11094         int token;
11095 {
11096         char msg[64];
11097
11098         if (token >= 0) {
11099                 snprintf(msg, 64, "%s unexpected (expecting %s)",
11100                         tokname[lasttoken], tokname[token]);
11101         } else {
11102                 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
11103         }
11104         synerror(msg);
11105         /* NOTREACHED */
11106 }
11107
11108
11109 static void
11110 synerror(const char *msg)
11111 {
11112         if (commandname)
11113                 out2fmt("%s: %d: ", commandname, startlinno);
11114         out2fmt("Syntax error: %s\n", msg);
11115         error((char *)NULL);
11116         /* NOTREACHED */
11117 }
11118
11119
11120 /*
11121  * called by editline -- any expansions to the prompt
11122  *    should be added here.
11123  */
11124 static inline const char *
11125 getprompt(void *unused)
11126 {
11127         switch (whichprompt) {
11128         case 0:
11129                 return "";
11130         case 1:
11131                 return ps1val();
11132         case 2:
11133                 return ps2val();
11134         default:
11135                 return "<internal prompt error>";
11136         }
11137 }
11138
11139 static void
11140 setprompt(int which)
11141 {
11142     whichprompt = which;
11143     putprompt(getprompt(NULL));
11144 }
11145
11146
11147 /*
11148  * Code for dealing with input/output redirection.
11149  */
11150
11151 #define EMPTY -2                /* marks an unused slot in redirtab */
11152 #ifndef PIPE_BUF
11153 # define PIPESIZE 4096          /* amount of buffering in a pipe */
11154 #else
11155 # define PIPESIZE PIPE_BUF
11156 #endif
11157
11158
11159
11160 /*
11161  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11162  * old file descriptors are stashed away so that the redirection can be
11163  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11164  * standard output, and the standard error if it becomes a duplicate of
11165  * stdout.
11166  */
11167
11168 static void
11169 redirect(redir, flags)
11170         union node *redir;
11171         int flags;
11172         {
11173         union node *n;
11174         struct redirtab *sv = NULL;
11175         int i;
11176         int fd;
11177         int newfd;
11178         int try;
11179         char memory[10];        /* file descriptors to write to memory */
11180
11181         for (i = 10 ; --i >= 0 ; )
11182                 memory[i] = 0;
11183         memory[1] = flags & REDIR_BACKQ;
11184         if (flags & REDIR_PUSH) {
11185                 sv = ckmalloc(sizeof (struct redirtab));
11186                 for (i = 0 ; i < 10 ; i++)
11187                         sv->renamed[i] = EMPTY;
11188                 sv->next = redirlist;
11189                 redirlist = sv;
11190         }
11191         for (n = redir ; n ; n = n->nfile.next) {
11192                 fd = n->nfile.fd;
11193                 try = 0;
11194                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11195                     n->ndup.dupfd == fd)
11196                         continue; /* redirect from/to same file descriptor */
11197
11198                 INTOFF;
11199                 newfd = openredirect(n);
11200                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11201                         if (newfd == fd) {
11202                                 try++;
11203                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11204                                 switch (errno) {
11205                                 case EBADF:
11206                                         if (!try) {
11207                                                 dupredirect(n, newfd, memory);
11208                                                 try++;
11209                                                 break;
11210                                         }
11211                                         /* FALLTHROUGH*/
11212                                 default:
11213                                         if (newfd >= 0) {
11214                                                 close(newfd);
11215                                         }
11216                                         INTON;
11217                                         error("%d: %m", fd);
11218                                         /* NOTREACHED */
11219                                 }
11220                         }
11221                         if (!try) {
11222                                 close(fd);
11223                                 if (flags & REDIR_PUSH) {
11224                                         sv->renamed[fd] = i;
11225                                 }
11226                         }
11227                 } else if (fd != newfd) {
11228                         close(fd);
11229                 }
11230                 if (fd == 0)
11231                         fd0_redirected++;
11232                 if (!try)
11233                         dupredirect(n, newfd, memory);
11234                 INTON;
11235         }
11236 }
11237
11238
11239 static int
11240 openredirect(redir)
11241         union node *redir;
11242         {
11243         char *fname;
11244         int f;
11245
11246         switch (redir->nfile.type) {
11247         case NFROM:
11248                 fname = redir->nfile.expfname;
11249                 if ((f = open(fname, O_RDONLY)) < 0)
11250                         goto eopen;
11251                 break;
11252         case NFROMTO:
11253                 fname = redir->nfile.expfname;
11254                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11255                         goto ecreate;
11256                 break;
11257         case NTO:
11258                 /* Take care of noclobber mode. */
11259                 if (Cflag) {
11260                         fname = redir->nfile.expfname;
11261                         if ((f = noclobberopen(fname)) < 0)
11262                                 goto ecreate;
11263                         break;
11264                 }
11265         case NTOOV:
11266                 fname = redir->nfile.expfname;
11267 #ifdef O_CREAT
11268                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11269                         goto ecreate;
11270 #else
11271                 if ((f = creat(fname, 0666)) < 0)
11272                         goto ecreate;
11273 #endif
11274                 break;
11275         case NAPPEND:
11276                 fname = redir->nfile.expfname;
11277 #ifdef O_APPEND
11278                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11279                         goto ecreate;
11280 #else
11281                 if ((f = open(fname, O_WRONLY)) < 0
11282                  && (f = creat(fname, 0666)) < 0)
11283                         goto ecreate;
11284                 lseek(f, (off_t)0, 2);
11285 #endif
11286                 break;
11287         default:
11288 #ifdef DEBUG
11289                 abort();
11290 #endif
11291                 /* Fall through to eliminate warning. */
11292         case NTOFD:
11293         case NFROMFD:
11294                 f = -1;
11295                 break;
11296         case NHERE:
11297         case NXHERE:
11298                 f = openhere(redir);
11299                 break;
11300         }
11301
11302         return f;
11303 ecreate:
11304         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11305 eopen:
11306         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11307 }
11308
11309
11310 static void
11311 dupredirect(union node *redir, int f, char memory[10])
11312 {
11313         int fd = redir->nfile.fd;
11314
11315         memory[fd] = 0;
11316         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11317                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11318                         if (memory[redir->ndup.dupfd])
11319                                 memory[fd] = 1;
11320                         else
11321                                 dup_as_newfd(redir->ndup.dupfd, fd);
11322                 }
11323                 return;
11324         }
11325
11326         if (f != fd) {
11327                 dup_as_newfd(f, fd);
11328                 close(f);
11329         }
11330         return;
11331 }
11332
11333
11334 /*
11335  * Handle here documents.  Normally we fork off a process to write the
11336  * data to a pipe.  If the document is short, we can stuff the data in
11337  * the pipe without forking.
11338  */
11339
11340 static int
11341 openhere(redir)
11342         union node *redir;
11343         {
11344         int pip[2];
11345         int len = 0;
11346
11347         if (pipe(pip) < 0)
11348                 error("Pipe call failed");
11349         if (redir->type == NHERE) {
11350                 len = strlen(redir->nhere.doc->narg.text);
11351                 if (len <= PIPESIZE) {
11352                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11353                         goto out;
11354                 }
11355         }
11356         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11357                 close(pip[0]);
11358                 signal(SIGINT, SIG_IGN);
11359                 signal(SIGQUIT, SIG_IGN);
11360                 signal(SIGHUP, SIG_IGN);
11361 #ifdef SIGTSTP
11362                 signal(SIGTSTP, SIG_IGN);
11363 #endif
11364                 signal(SIGPIPE, SIG_DFL);
11365                 if (redir->type == NHERE)
11366                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11367                 else
11368                         expandhere(redir->nhere.doc, pip[1]);
11369                 _exit(0);
11370         }
11371 out:
11372         close(pip[1]);
11373         return pip[0];
11374 }
11375
11376
11377 /*
11378  * Undo the effects of the last redirection.
11379  */
11380
11381 static void
11382 popredir(void)
11383 {
11384         struct redirtab *rp = redirlist;
11385         int i;
11386
11387         INTOFF;
11388         for (i = 0 ; i < 10 ; i++) {
11389                 if (rp->renamed[i] != EMPTY) {
11390                         if (i == 0)
11391                                 fd0_redirected--;
11392                         close(i);
11393                         if (rp->renamed[i] >= 0) {
11394                                 dup_as_newfd(rp->renamed[i], i);
11395                                 close(rp->renamed[i]);
11396                         }
11397                 }
11398         }
11399         redirlist = rp->next;
11400         ckfree(rp);
11401         INTON;
11402 }
11403
11404 /*
11405  * Discard all saved file descriptors.
11406  */
11407
11408 static void
11409 clearredir(void) {
11410         struct redirtab *rp;
11411         int i;
11412
11413         for (rp = redirlist ; rp ; rp = rp->next) {
11414                 for (i = 0 ; i < 10 ; i++) {
11415                         if (rp->renamed[i] >= 0) {
11416                                 close(rp->renamed[i]);
11417                         }
11418                         rp->renamed[i] = EMPTY;
11419                 }
11420         }
11421 }
11422
11423
11424 /*
11425  * Copy a file descriptor to be >= to.  Returns -1
11426  * if the source file descriptor is closed, EMPTY if there are no unused
11427  * file descriptors left.
11428  */
11429
11430 static int
11431 dup_as_newfd(from, to)
11432         int from;
11433         int to;
11434 {
11435         int newfd;
11436
11437         newfd = fcntl(from, F_DUPFD, to);
11438         if (newfd < 0) {
11439                 if (errno == EMFILE)
11440                         return EMPTY;
11441                 else
11442                         error("%d: %m", from);
11443         }
11444         return newfd;
11445 }
11446
11447 /*
11448  * Open a file in noclobber mode.
11449  * The code was copied from bash.
11450  */
11451 static int
11452 noclobberopen(const char *fname)
11453 {
11454         int r, fd;
11455         struct stat finfo, finfo2;
11456
11457         /*
11458          * If the file exists and is a regular file, return an error
11459          * immediately.
11460          */
11461         r = stat(fname, &finfo);
11462         if (r == 0 && S_ISREG(finfo.st_mode)) {
11463                 errno = EEXIST;
11464                 return -1;
11465         }
11466
11467         /*
11468          * If the file was not present (r != 0), make sure we open it
11469          * exclusively so that if it is created before we open it, our open
11470          * will fail.  Make sure that we do not truncate an existing file.
11471          * Note that we don't turn on O_EXCL unless the stat failed -- if the
11472          * file was not a regular file, we leave O_EXCL off.
11473          */
11474         if (r != 0)
11475                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11476         fd = open(fname, O_WRONLY|O_CREAT, 0666);
11477
11478         /* If the open failed, return the file descriptor right away. */
11479         if (fd < 0)
11480                 return fd;
11481
11482         /*
11483          * OK, the open succeeded, but the file may have been changed from a
11484          * non-regular file to a regular file between the stat and the open.
11485          * We are assuming that the O_EXCL open handles the case where FILENAME
11486          * did not exist and is symlinked to an existing file between the stat
11487          * and open.
11488          */
11489
11490         /*
11491          * If we can open it and fstat the file descriptor, and neither check
11492          * revealed that it was a regular file, and the file has not been
11493          * replaced, return the file descriptor.
11494          */
11495          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11496              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11497                 return fd;
11498
11499         /* The file has been replaced.  badness. */
11500         close(fd);
11501         errno = EEXIST;
11502         return -1;
11503 }
11504 /*#ifdef __weak_alias
11505 __weak_alias(getmode,_getmode)
11506 __weak_alias(setmode,_setmode)
11507 #endif*/
11508
11509 #ifdef __GLIBC__
11510 #define S_ISTXT __S_ISVTX
11511 #endif
11512
11513 #define SET_LEN 6               /* initial # of bitcmd struct to malloc */
11514 #define SET_LEN_INCR 4          /* # of bitcmd structs to add as needed */
11515
11516 typedef struct bitcmd {
11517         char    cmd;
11518         char    cmd2;
11519         mode_t  bits;
11520 } BITCMD;
11521
11522 #define CMD2_CLR        0x01
11523 #define CMD2_SET        0x02
11524 #define CMD2_GBITS      0x04
11525 #define CMD2_OBITS      0x08
11526 #define CMD2_UBITS      0x10
11527
11528 static BITCMD   *addcmd (BITCMD *, int, int, int, u_int);
11529 static void      compress_mode (BITCMD *);
11530 #ifdef SETMODE_DEBUG
11531 static void      dumpmode (BITCMD *);
11532 #endif
11533
11534 /*
11535  * Given the old mode and an array of bitcmd structures, apply the operations
11536  * described in the bitcmd structures to the old mode, and return the new mode.
11537  * Note that there is no '=' command; a strict assignment is just a '-' (clear
11538  * bits) followed by a '+' (set bits).
11539  */
11540 static mode_t
11541 getmode(bbox, omode)
11542         const void *bbox;
11543         mode_t omode;
11544 {
11545         const BITCMD *set;
11546         mode_t clrval, newmode, value;
11547
11548         _DIAGASSERT(bbox != NULL);
11549
11550         set = (const BITCMD *)bbox;
11551         newmode = omode;
11552         for (value = 0;; set++)
11553                 switch(set->cmd) {
11554                 /*
11555                  * When copying the user, group or other bits around, we "know"
11556                  * where the bits are in the mode so that we can do shifts to
11557                  * copy them around.  If we don't use shifts, it gets real
11558                  * grundgy with lots of single bit checks and bit sets.
11559                  */
11560                 case 'u':
11561                         value = (newmode & S_IRWXU) >> 6;
11562                         goto common;
11563
11564                 case 'g':
11565                         value = (newmode & S_IRWXG) >> 3;
11566                         goto common;
11567
11568                 case 'o':
11569                         value = newmode & S_IRWXO;
11570 common:                 if (set->cmd2 & CMD2_CLR) {
11571                                 clrval =
11572                                     (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
11573                                 if (set->cmd2 & CMD2_UBITS)
11574                                         newmode &= ~((clrval<<6) & set->bits);
11575                                 if (set->cmd2 & CMD2_GBITS)
11576                                         newmode &= ~((clrval<<3) & set->bits);
11577                                 if (set->cmd2 & CMD2_OBITS)
11578                                         newmode &= ~(clrval & set->bits);
11579                         }
11580                         if (set->cmd2 & CMD2_SET) {
11581                                 if (set->cmd2 & CMD2_UBITS)
11582                                         newmode |= (value<<6) & set->bits;
11583                                 if (set->cmd2 & CMD2_GBITS)
11584                                         newmode |= (value<<3) & set->bits;
11585                                 if (set->cmd2 & CMD2_OBITS)
11586                                         newmode |= value & set->bits;
11587                         }
11588                         break;
11589
11590                 case '+':
11591                         newmode |= set->bits;
11592                         break;
11593
11594                 case '-':
11595                         newmode &= ~set->bits;
11596                         break;
11597
11598                 case 'X':
11599                         if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11600                                 newmode |= set->bits;
11601                         break;
11602
11603                 case '\0':
11604                 default:
11605 #ifdef SETMODE_DEBUG
11606                         (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11607 #endif
11608                         return (newmode);
11609                 }
11610 }
11611
11612 #define ADDCMD(a, b, c, d) do {                                         \
11613         if (set >= endset) {                                            \
11614                 BITCMD *newset;                                         \
11615                 setlen += SET_LEN_INCR;                                 \
11616                 newset = realloc(saveset, sizeof(BITCMD) * setlen);     \
11617                 if (newset == NULL) {                                   \
11618                         free(saveset);                                  \
11619                         return (NULL);                                  \
11620                 }                                                       \
11621                 set = newset + (set - saveset);                         \
11622                 saveset = newset;                                       \
11623                 endset = newset + (setlen - 2);                         \
11624         }                                                               \
11625         set = addcmd(set, (a), (b), (c), (d));                          \
11626 } while (/*CONSTCOND*/0)
11627
11628 #define STANDARD_BITS   (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11629
11630 static void *
11631 setmode(p)
11632         const char *p;
11633 {
11634         int perm, who;
11635         char op, *ep;
11636         BITCMD *set, *saveset, *endset;
11637         sigset_t mysigset, sigoset;
11638         mode_t mask;
11639         int equalopdone = 0;    /* pacify gcc */
11640         int permXbits, setlen;
11641
11642         if (!*p)
11643                 return (NULL);
11644
11645         /*
11646          * Get a copy of the mask for the permissions that are mask relative.
11647          * Flip the bits, we want what's not set.  Since it's possible that
11648          * the caller is opening files inside a signal handler, protect them
11649          * as best we can.
11650          */
11651         sigfillset(&mysigset);
11652         (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11653         (void)umask(mask = umask(0));
11654         mask = ~mask;
11655         (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11656
11657         setlen = SET_LEN + 2;
11658
11659         if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11660                 return (NULL);
11661         saveset = set;
11662         endset = set + (setlen - 2);
11663
11664         /*
11665          * If an absolute number, get it and return; disallow non-octal digits
11666          * or illegal bits.
11667          */
11668         if (isdigit((unsigned char)*p)) {
11669                 perm = (mode_t)strtol(p, &ep, 8);
11670                 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11671                         free(saveset);
11672                         return (NULL);
11673                 }
11674                 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11675                 set->cmd = 0;
11676                 return (saveset);
11677         }
11678
11679         /*
11680          * Build list of structures to set/clear/copy bits as described by
11681          * each clause of the symbolic mode.
11682          */
11683         for (;;) {
11684                 /* First, find out which bits might be modified. */
11685                 for (who = 0;; ++p) {
11686                         switch (*p) {
11687                         case 'a':
11688                                 who |= STANDARD_BITS;
11689                                 break;
11690                         case 'u':
11691                                 who |= S_ISUID|S_IRWXU;
11692                                 break;
11693                         case 'g':
11694                                 who |= S_ISGID|S_IRWXG;
11695                                 break;
11696                         case 'o':
11697                                 who |= S_IRWXO;
11698                                 break;
11699                         default:
11700                                 goto getop;
11701                         }
11702                 }
11703
11704 getop:          if ((op = *p++) != '+' && op != '-' && op != '=') {
11705                         free(saveset);
11706                         return (NULL);
11707                 }
11708                 if (op == '=')
11709                         equalopdone = 0;
11710
11711                 who &= ~S_ISTXT;
11712                 for (perm = 0, permXbits = 0;; ++p) {
11713                         switch (*p) {
11714                         case 'r':
11715                                 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11716                                 break;
11717                         case 's':
11718                                 /*
11719                                  * If specific bits where requested and
11720                                  * only "other" bits ignore set-id.
11721                                  */
11722                                 if (who == 0 || (who & ~S_IRWXO))
11723                                         perm |= S_ISUID|S_ISGID;
11724                                 break;
11725                         case 't':
11726                                 /*
11727                                  * If specific bits where requested and
11728                                  * only "other" bits ignore set-id.
11729                                  */
11730                                 if (who == 0 || (who & ~S_IRWXO)) {
11731                                         who |= S_ISTXT;
11732                                         perm |= S_ISTXT;
11733                                 }
11734                                 break;
11735                         case 'w':
11736                                 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11737                                 break;
11738                         case 'X':
11739                                 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11740                                 break;
11741                         case 'x':
11742                                 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11743                                 break;
11744                         case 'u':
11745                         case 'g':
11746                         case 'o':
11747                                 /*
11748                                  * When ever we hit 'u', 'g', or 'o', we have
11749                                  * to flush out any partial mode that we have,
11750                                  * and then do the copying of the mode bits.
11751                                  */
11752                                 if (perm) {
11753                                         ADDCMD(op, who, perm, mask);
11754                                         perm = 0;
11755                                 }
11756                                 if (op == '=')
11757                                         equalopdone = 1;
11758                                 if (op == '+' && permXbits) {
11759                                         ADDCMD('X', who, permXbits, mask);
11760                                         permXbits = 0;
11761                                 }
11762                                 ADDCMD(*p, who, op, mask);
11763                                 break;
11764
11765                         default:
11766                                 /*
11767                                  * Add any permissions that we haven't already
11768                                  * done.
11769                                  */
11770                                 if (perm || (op == '=' && !equalopdone)) {
11771                                         if (op == '=')
11772                                                 equalopdone = 1;
11773                                         ADDCMD(op, who, perm, mask);
11774                                         perm = 0;
11775                                 }
11776                                 if (permXbits) {
11777                                         ADDCMD('X', who, permXbits, mask);
11778                                         permXbits = 0;
11779                                 }
11780                                 goto apply;
11781                         }
11782                 }
11783
11784 apply:          if (!*p)
11785                         break;
11786                 if (*p != ',')
11787                         goto getop;
11788                 ++p;
11789         }
11790         set->cmd = 0;
11791 #ifdef SETMODE_DEBUG
11792         (void)printf("Before compress_mode()\n");
11793         dumpmode(saveset);
11794 #endif
11795         compress_mode(saveset);
11796 #ifdef SETMODE_DEBUG
11797         (void)printf("After compress_mode()\n");
11798         dumpmode(saveset);
11799 #endif
11800         return (saveset);
11801 }
11802
11803 static BITCMD *
11804 addcmd(set, op, who, oparg, mask)
11805         BITCMD *set;
11806         int oparg, who;
11807         int op;
11808         u_int mask;
11809 {
11810
11811         _DIAGASSERT(set != NULL);
11812
11813         switch (op) {
11814         case '=':
11815                 set->cmd = '-';
11816                 set->bits = who ? who : STANDARD_BITS;
11817                 set++;
11818
11819                 op = '+';
11820                 /* FALLTHROUGH */
11821         case '+':
11822         case '-':
11823         case 'X':
11824                 set->cmd = op;
11825                 set->bits = (who ? who : mask) & oparg;
11826                 break;
11827
11828         case 'u':
11829         case 'g':
11830         case 'o':
11831                 set->cmd = op;
11832                 if (who) {
11833                         set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11834                                     ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11835                                     ((who & S_IROTH) ? CMD2_OBITS : 0);
11836                         set->bits = (mode_t)~0;
11837                 } else {
11838                         set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11839                         set->bits = mask;
11840                 }
11841
11842                 if (oparg == '+')
11843                         set->cmd2 |= CMD2_SET;
11844                 else if (oparg == '-')
11845                         set->cmd2 |= CMD2_CLR;
11846                 else if (oparg == '=')
11847                         set->cmd2 |= CMD2_SET|CMD2_CLR;
11848                 break;
11849         }
11850         return (set + 1);
11851 }
11852
11853 #ifdef SETMODE_DEBUG
11854 static void
11855 dumpmode(set)
11856         BITCMD *set;
11857 {
11858
11859         _DIAGASSERT(set != NULL);
11860
11861         for (; set->cmd; ++set)
11862                 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11863                     set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11864                     set->cmd2 & CMD2_CLR ? " CLR" : "",
11865                     set->cmd2 & CMD2_SET ? " SET" : "",
11866                     set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11867                     set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11868                     set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11869 }
11870 #endif
11871
11872 /*
11873  * Given an array of bitcmd structures, compress by compacting consecutive
11874  * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
11875  * 'g' and 'o' commands continue to be separate.  They could probably be
11876  * compacted, but it's not worth the effort.
11877  */
11878 static void
11879 compress_mode(set)
11880         BITCMD *set;
11881 {
11882         BITCMD *nset;
11883         int setbits, clrbits, Xbits, op;
11884
11885         _DIAGASSERT(set != NULL);
11886
11887         for (nset = set;;) {
11888                 /* Copy over any 'u', 'g' and 'o' commands. */
11889                 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11890                         *set++ = *nset++;
11891                         if (!op)
11892                                 return;
11893                 }
11894
11895                 for (setbits = clrbits = Xbits = 0;; nset++) {
11896                         if ((op = nset->cmd) == '-') {
11897                                 clrbits |= nset->bits;
11898                                 setbits &= ~nset->bits;
11899                                 Xbits &= ~nset->bits;
11900                         } else if (op == '+') {
11901                                 setbits |= nset->bits;
11902                                 clrbits &= ~nset->bits;
11903                                 Xbits &= ~nset->bits;
11904                         } else if (op == 'X')
11905                                 Xbits |= nset->bits & ~setbits;
11906                         else
11907                                 break;
11908                 }
11909                 if (clrbits) {
11910                         set->cmd = '-';
11911                         set->cmd2 = 0;
11912                         set->bits = clrbits;
11913                         set++;
11914                 }
11915                 if (setbits) {
11916                         set->cmd = '+';
11917                         set->cmd2 = 0;
11918                         set->bits = setbits;
11919                         set++;
11920                 }
11921                 if (Xbits) {
11922                         set->cmd = 'X';
11923                         set->cmd2 = 0;
11924                         set->bits = Xbits;
11925                         set++;
11926                 }
11927         }
11928 }
11929 #ifdef DEBUG
11930 static void shtree (union node *, int, char *, FILE*);
11931 static void shcmd (union node *, FILE *);
11932 static void sharg (union node *, FILE *);
11933 static void indent (int, char *, FILE *);
11934 static void trstring (char *);
11935
11936
11937 static void
11938 showtree(n)
11939         union node *n;
11940 {
11941         trputs("showtree called\n");
11942         shtree(n, 1, NULL, stdout);
11943 }
11944
11945
11946 static void
11947 shtree(n, ind, pfx, fp)
11948         union node *n;
11949         int ind;
11950         char *pfx;
11951         FILE *fp;
11952 {
11953         struct nodelist *lp;
11954         const char *s;
11955
11956         if (n == NULL)
11957                 return;
11958
11959         indent(ind, pfx, fp);
11960         switch(n->type) {
11961         case NSEMI:
11962                 s = "; ";
11963                 goto binop;
11964         case NAND:
11965                 s = " && ";
11966                 goto binop;
11967         case NOR:
11968                 s = " || ";
11969 binop:
11970                 shtree(n->nbinary.ch1, ind, NULL, fp);
11971            /*    if (ind < 0) */
11972                         fputs(s, fp);
11973                 shtree(n->nbinary.ch2, ind, NULL, fp);
11974                 break;
11975         case NCMD:
11976                 shcmd(n, fp);
11977                 if (ind >= 0)
11978                         putc('\n', fp);
11979                 break;
11980         case NPIPE:
11981                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11982                         shcmd(lp->n, fp);
11983                         if (lp->next)
11984                                 fputs(" | ", fp);
11985                 }
11986                 if (n->npipe.backgnd)
11987                         fputs(" &", fp);
11988                 if (ind >= 0)
11989                         putc('\n', fp);
11990                 break;
11991         default:
11992                 fprintf(fp, "<node type %d>", n->type);
11993                 if (ind >= 0)
11994                         putc('\n', fp);
11995                 break;
11996         }
11997 }
11998
11999
12000
12001 static void
12002 shcmd(cmd, fp)
12003         union node *cmd;
12004         FILE *fp;
12005 {
12006         union node *np;
12007         int first;
12008         const char *s;
12009         int dftfd;
12010
12011         first = 1;
12012         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
12013                 if (! first)
12014                         putchar(' ');
12015                 sharg(np, fp);
12016                 first = 0;
12017         }
12018         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
12019                 if (! first)
12020                         putchar(' ');
12021                 switch (np->nfile.type) {
12022                         case NTO:       s = ">";  dftfd = 1; break;
12023                         case NAPPEND:   s = ">>"; dftfd = 1; break;
12024                         case NTOFD:     s = ">&"; dftfd = 1; break;
12025                         case NTOOV:     s = ">|"; dftfd = 1; break;
12026                         case NFROM:     s = "<";  dftfd = 0; break;
12027                         case NFROMFD:   s = "<&"; dftfd = 0; break;
12028                         case NFROMTO:   s = "<>"; dftfd = 0; break;
12029                         default:        s = "*error*"; dftfd = 0; break;
12030                 }
12031                 if (np->nfile.fd != dftfd)
12032                         fprintf(fp, "%d", np->nfile.fd);
12033                 fputs(s, fp);
12034                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
12035                         fprintf(fp, "%d", np->ndup.dupfd);
12036                 } else {
12037                         sharg(np->nfile.fname, fp);
12038                 }
12039                 first = 0;
12040         }
12041 }
12042
12043
12044
12045 static void
12046 sharg(arg, fp)
12047         union node *arg;
12048         FILE *fp;
12049         {
12050         char *p;
12051         struct nodelist *bqlist;
12052         int subtype;
12053
12054         if (arg->type != NARG) {
12055                 printf("<node type %d>\n", arg->type);
12056                 fflush(stdout);
12057                 abort();
12058         }
12059         bqlist = arg->narg.backquote;
12060         for (p = arg->narg.text ; *p ; p++) {
12061                 switch (*p) {
12062                 case CTLESC:
12063                         putc(*++p, fp);
12064                         break;
12065                 case CTLVAR:
12066                         putc('$', fp);
12067                         putc('{', fp);
12068                         subtype = *++p;
12069                         if (subtype == VSLENGTH)
12070                                 putc('#', fp);
12071
12072                         while (*p != '=')
12073                                 putc(*p++, fp);
12074
12075                         if (subtype & VSNUL)
12076                                 putc(':', fp);
12077
12078                         switch (subtype & VSTYPE) {
12079                         case VSNORMAL:
12080                                 putc('}', fp);
12081                                 break;
12082                         case VSMINUS:
12083                                 putc('-', fp);
12084                                 break;
12085                         case VSPLUS:
12086                                 putc('+', fp);
12087                                 break;
12088                         case VSQUESTION:
12089                                 putc('?', fp);
12090                                 break;
12091                         case VSASSIGN:
12092                                 putc('=', fp);
12093                                 break;
12094                         case VSTRIMLEFT:
12095                                 putc('#', fp);
12096                                 break;
12097                         case VSTRIMLEFTMAX:
12098                                 putc('#', fp);
12099                                 putc('#', fp);
12100                                 break;
12101                         case VSTRIMRIGHT:
12102                                 putc('%', fp);
12103                                 break;
12104                         case VSTRIMRIGHTMAX:
12105                                 putc('%', fp);
12106                                 putc('%', fp);
12107                                 break;
12108                         case VSLENGTH:
12109                                 break;
12110                         default:
12111                                 printf("<subtype %d>", subtype);
12112                         }
12113                         break;
12114                 case CTLENDVAR:
12115                      putc('}', fp);
12116                      break;
12117                 case CTLBACKQ:
12118                 case CTLBACKQ|CTLQUOTE:
12119                         putc('$', fp);
12120                         putc('(', fp);
12121                         shtree(bqlist->n, -1, NULL, fp);
12122                         putc(')', fp);
12123                         break;
12124                 default:
12125                         putc(*p, fp);
12126                         break;
12127                 }
12128         }
12129 }
12130
12131
12132 static void
12133 indent(amount, pfx, fp)
12134         int amount;
12135         char *pfx;
12136         FILE *fp;
12137 {
12138         int i;
12139
12140         for (i = 0 ; i < amount ; i++) {
12141                 if (pfx && i == amount - 1)
12142                         fputs(pfx, fp);
12143                 putc('\t', fp);
12144         }
12145 }
12146 #endif
12147
12148
12149
12150 /*
12151  * Debugging stuff.
12152  */
12153
12154
12155 #ifdef DEBUG
12156 FILE *tracefile;
12157
12158 #if DEBUG == 2
12159 static int debug = 1;
12160 #else
12161 static int debug = 0;
12162 #endif
12163
12164
12165 static void
12166 trputc(c)
12167         int c;
12168 {
12169         if (tracefile == NULL)
12170                 return;
12171         putc(c, tracefile);
12172         if (c == '\n')
12173                 fflush(tracefile);
12174 }
12175
12176 static void
12177 trace(const char *fmt, ...)
12178 {
12179         va_list va;
12180 #ifdef __STDC__
12181         va_start(va, fmt);
12182 #else
12183         char *fmt;
12184         va_start(va);
12185         fmt = va_arg(va, char *);
12186 #endif
12187         if (tracefile != NULL) {
12188                 (void) vfprintf(tracefile, fmt, va);
12189                 if (strchr(fmt, '\n'))
12190                         (void) fflush(tracefile);
12191         }
12192         va_end(va);
12193 }
12194
12195
12196 static void
12197 trputs(s)
12198         const char *s;
12199 {
12200         if (tracefile == NULL)
12201                 return;
12202         fputs(s, tracefile);
12203         if (strchr(s, '\n'))
12204                 fflush(tracefile);
12205 }
12206
12207
12208 static void
12209 trstring(s)
12210         char *s;
12211 {
12212         char *p;
12213         char c;
12214
12215         if (tracefile == NULL)
12216                 return;
12217         putc('"', tracefile);
12218         for (p = s ; *p ; p++) {
12219                 switch (*p) {
12220                 case '\n':  c = 'n';  goto backslash;
12221                 case '\t':  c = 't';  goto backslash;
12222                 case '\r':  c = 'r';  goto backslash;
12223                 case '"':  c = '"';  goto backslash;
12224                 case '\\':  c = '\\';  goto backslash;
12225                 case CTLESC:  c = 'e';  goto backslash;
12226                 case CTLVAR:  c = 'v';  goto backslash;
12227                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
12228                 case CTLBACKQ:  c = 'q';  goto backslash;
12229                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
12230 backslash:        putc('\\', tracefile);
12231                         putc(c, tracefile);
12232                         break;
12233                 default:
12234                         if (*p >= ' ' && *p <= '~')
12235                                 putc(*p, tracefile);
12236                         else {
12237                                 putc('\\', tracefile);
12238                                 putc(*p >> 6 & 03, tracefile);
12239                                 putc(*p >> 3 & 07, tracefile);
12240                                 putc(*p & 07, tracefile);
12241                         }
12242                         break;
12243                 }
12244         }
12245         putc('"', tracefile);
12246 }
12247
12248
12249 static void
12250 trargs(ap)
12251         char **ap;
12252 {
12253         if (tracefile == NULL)
12254                 return;
12255         while (*ap) {
12256                 trstring(*ap++);
12257                 if (*ap)
12258                         putc(' ', tracefile);
12259                 else
12260                         putc('\n', tracefile);
12261         }
12262         fflush(tracefile);
12263 }
12264
12265
12266 static void
12267 opentrace() {
12268         char s[100];
12269 #ifdef O_APPEND
12270         int flags;
12271 #endif
12272
12273         if (!debug)
12274                 return;
12275 #ifdef not_this_way
12276         {
12277                 char *p;
12278                 if ((p = getenv("HOME")) == NULL) {
12279                         if (geteuid() == 0)
12280                                 p = "/";
12281                         else
12282                                 p = "/tmp";
12283                 }
12284                 strcpy(s, p);
12285                 strcat(s, "/trace");
12286         }
12287 #else
12288         strcpy(s, "./trace");
12289 #endif /* not_this_way */
12290         if ((tracefile = fopen(s, "a")) == NULL) {
12291                 fprintf(stderr, "Can't open %s\n", s);
12292                 return;
12293         }
12294 #ifdef O_APPEND
12295         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
12296                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
12297 #endif
12298         fputs("\nTracing started.\n", tracefile);
12299         fflush(tracefile);
12300 }
12301 #endif /* DEBUG */
12302
12303
12304 /*
12305  * The trap builtin.
12306  */
12307
12308 static int
12309 trapcmd(argc, argv)
12310         int argc;
12311         char **argv;
12312 {
12313         char *action;
12314         char **ap;
12315         int signo;
12316
12317         if (argc <= 1) {
12318                 for (signo = 0 ; signo < NSIG ; signo++) {
12319                         if (trap[signo] != NULL) {
12320                                 char *p;
12321
12322                                 p = single_quote(trap[signo]);
12323                                 out1fmt("trap -- %s %s\n", p,
12324                                         signal_names[signo] + (signo ? 3 : 0)
12325                                 );
12326                                 stunalloc(p);
12327                         }
12328                 }
12329                 return 0;
12330         }
12331         ap = argv + 1;
12332         if (argc == 2)
12333                 action = NULL;
12334         else
12335                 action = *ap++;
12336         while (*ap) {
12337                 if ((signo = decode_signal(*ap, 0)) < 0)
12338                         error("%s: bad trap", *ap);
12339                 INTOFF;
12340                 if (action) {
12341                         if (action[0] == '-' && action[1] == '\0')
12342                                 action = NULL;
12343                         else
12344                                 action = savestr(action);
12345                 }
12346                 if (trap[signo])
12347                         ckfree(trap[signo]);
12348                 trap[signo] = action;
12349                 if (signo != 0)
12350                         setsignal(signo);
12351                 INTON;
12352                 ap++;
12353         }
12354         return 0;
12355 }
12356
12357
12358
12359
12360
12361
12362 /*
12363  * Set the signal handler for the specified signal.  The routine figures
12364  * out what it should be set to.
12365  */
12366
12367 static void
12368 setsignal(int signo)
12369 {
12370         int action;
12371         char *t;
12372         struct sigaction act;
12373
12374         if ((t = trap[signo]) == NULL)
12375                 action = S_DFL;
12376         else if (*t != '\0')
12377                 action = S_CATCH;
12378         else
12379                 action = S_IGN;
12380         if (rootshell && action == S_DFL) {
12381                 switch (signo) {
12382                 case SIGINT:
12383                         if (iflag || minusc || sflag == 0)
12384                                 action = S_CATCH;
12385                         break;
12386                 case SIGQUIT:
12387 #ifdef DEBUG
12388                         {
12389
12390                         if (debug)
12391                                 break;
12392                         }
12393 #endif
12394                         /* FALLTHROUGH */
12395                 case SIGTERM:
12396                         if (iflag)
12397                                 action = S_IGN;
12398                         break;
12399 #ifdef JOBS
12400                 case SIGTSTP:
12401                 case SIGTTOU:
12402                         if (mflag)
12403                                 action = S_IGN;
12404                         break;
12405 #endif
12406                 }
12407         }
12408
12409         t = &sigmode[signo - 1];
12410         if (*t == 0) {
12411                 /*
12412                  * current setting unknown
12413                  */
12414                 if (sigaction(signo, 0, &act) == -1) {
12415                         /*
12416                          * Pretend it worked; maybe we should give a warning
12417                          * here, but other shells don't. We don't alter
12418                          * sigmode, so that we retry every time.
12419                          */
12420                         return;
12421                 }
12422                 if (act.sa_handler == SIG_IGN) {
12423                         if (mflag && (signo == SIGTSTP ||
12424                              signo == SIGTTIN || signo == SIGTTOU)) {
12425                                 *t = S_IGN;     /* don't hard ignore these */
12426                         } else
12427                                 *t = S_HARD_IGN;
12428                 } else {
12429                         *t = S_RESET;   /* force to be set */
12430                 }
12431         }
12432         if (*t == S_HARD_IGN || *t == action)
12433                 return;
12434         switch (action) {
12435         case S_CATCH:
12436                 act.sa_handler = onsig;
12437                 break;
12438         case S_IGN:
12439                 act.sa_handler = SIG_IGN;
12440                 break;
12441         default:
12442                 act.sa_handler = SIG_DFL;
12443         }
12444         *t = action;
12445         act.sa_flags = 0;
12446         sigemptyset(&act.sa_mask);
12447         sigaction(signo, &act, 0);
12448 }
12449
12450 /*
12451  * Ignore a signal.
12452  */
12453
12454 static void
12455 ignoresig(signo)
12456         int signo;
12457 {
12458         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12459                 signal(signo, SIG_IGN);
12460         }
12461         sigmode[signo - 1] = S_HARD_IGN;
12462 }
12463
12464
12465 /*
12466  * Signal handler.
12467  */
12468
12469 static void
12470 onsig(int signo)
12471 {
12472         if (signo == SIGINT && trap[SIGINT] == NULL) {
12473                 onint();
12474                 return;
12475         }
12476         gotsig[signo - 1] = 1;
12477         pendingsigs++;
12478 }
12479
12480
12481 /*
12482  * Called to execute a trap.  Perhaps we should avoid entering new trap
12483  * handlers while we are executing a trap handler.
12484  */
12485
12486 static void
12487 dotrap(void)
12488 {
12489         int i;
12490         int savestatus;
12491
12492         for (;;) {
12493                 for (i = 1 ; ; i++) {
12494                         if (gotsig[i - 1])
12495                                 break;
12496                         if (i >= NSIG - 1)
12497                                 goto done;
12498                 }
12499                 gotsig[i - 1] = 0;
12500                 savestatus=exitstatus;
12501                 evalstring(trap[i], 0);
12502                 exitstatus=savestatus;
12503         }
12504 done:
12505         pendingsigs = 0;
12506 }
12507
12508 /*
12509  * Called to exit the shell.
12510  */
12511
12512 static void
12513 exitshell(int status)
12514 {
12515         struct jmploc loc1, loc2;
12516         char *p;
12517
12518         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12519         if (setjmp(loc1.loc)) {
12520                 goto l1;
12521         }
12522         if (setjmp(loc2.loc)) {
12523                 goto l2;
12524         }
12525         handler = &loc1;
12526         if ((p = trap[0]) != NULL && *p != '\0') {
12527                 trap[0] = NULL;
12528                 evalstring(p, 0);
12529         }
12530 l1:   handler = &loc2;                  /* probably unnecessary */
12531         flushall();
12532 #ifdef JOBS
12533         setjobctl(0);
12534 #endif
12535 l2:   _exit(status);
12536         /* NOTREACHED */
12537 }
12538
12539 static int decode_signal(const char *string, int minsig)
12540 {
12541         int signo;
12542
12543         if (is_number(string, &signo)) {
12544                 if (signo >= NSIG) {
12545                         return -1;
12546                 }
12547                 return signo;
12548         }
12549
12550         signo = minsig;
12551         if (!signo) {
12552                 goto zero;
12553         }
12554         for (; signo < NSIG; signo++) {
12555                 if (!strcasecmp(string, &(signal_names[signo])[3])) {
12556                         return signo;
12557                 }
12558 zero:
12559                 if (!strcasecmp(string, signal_names[signo])) {
12560                         return signo;
12561                 }
12562         }
12563
12564         return -1;
12565 }
12566 static struct var **hashvar (const char *);
12567 static void showvars (const char *, int, int);
12568 static struct var **findvar (struct var **, const char *);
12569
12570 /*
12571  * Initialize the varable symbol tables and import the environment
12572  */
12573
12574 /*
12575  * This routine initializes the builtin variables.  It is called when the
12576  * shell is initialized and again when a shell procedure is spawned.
12577  */
12578
12579 static void
12580 initvar() {
12581         const struct varinit *ip;
12582         struct var *vp;
12583         struct var **vpp;
12584
12585         for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12586                 if ((vp->flags & VEXPORT) == 0) {
12587                         vpp = hashvar(ip->text);
12588                         vp->next = *vpp;
12589                         *vpp = vp;
12590                         vp->text = strdup(ip->text);
12591                         vp->flags = ip->flags;
12592                         vp->func = ip->func;
12593                 }
12594         }
12595         /*
12596          * PS1 depends on uid
12597          */
12598         if ((vps1.flags & VEXPORT) == 0) {
12599                 vpp = hashvar("PS1=");
12600                 vps1.next = *vpp;
12601                 *vpp = &vps1;
12602                 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12603                 vps1.flags = VSTRFIXED|VTEXTFIXED;
12604         }
12605 }
12606
12607 /*
12608  * Set the value of a variable.  The flags argument is ored with the
12609  * flags of the variable.  If val is NULL, the variable is unset.
12610  */
12611
12612 static void
12613 setvar(name, val, flags)
12614         const char *name, *val;
12615         int flags;
12616 {
12617         const char *p;
12618         int len;
12619         int namelen;
12620         char *nameeq;
12621         int isbad;
12622         int vallen = 0;
12623
12624         isbad = 0;
12625         p = name;
12626         if (! is_name(*p))
12627                 isbad = 1;
12628         p++;
12629         for (;;) {
12630                 if (! is_in_name(*p)) {
12631                         if (*p == '\0' || *p == '=')
12632                                 break;
12633                         isbad = 1;
12634                 }
12635                 p++;
12636         }
12637         namelen = p - name;
12638         if (isbad)
12639                 error("%.*s: bad variable name", namelen, name);
12640         len = namelen + 2;              /* 2 is space for '=' and '\0' */
12641         if (val == NULL) {
12642                 flags |= VUNSET;
12643         } else {
12644                 len += vallen = strlen(val);
12645         }
12646         INTOFF;
12647         nameeq = ckmalloc(len);
12648         memcpy(nameeq, name, namelen);
12649         nameeq[namelen] = '=';
12650         if (val) {
12651                 memcpy(nameeq + namelen + 1, val, vallen + 1);
12652         } else {
12653                 nameeq[namelen + 1] = '\0';
12654         }
12655         setvareq(nameeq, flags);
12656         INTON;
12657 }
12658
12659
12660
12661 /*
12662  * Same as setvar except that the variable and value are passed in
12663  * the first argument as name=value.  Since the first argument will
12664  * be actually stored in the table, it should not be a string that
12665  * will go away.
12666  */
12667
12668 static void
12669 setvareq(s, flags)
12670         char *s;
12671         int flags;
12672 {
12673         struct var *vp, **vpp;
12674
12675         vpp = hashvar(s);
12676         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12677         if ((vp = *findvar(vpp, s))) {
12678                 if (vp->flags & VREADONLY) {
12679                         size_t len = strchr(s, '=') - s;
12680                         error("%.*s: is read only", len, s);
12681                 }
12682                 INTOFF;
12683
12684                 if (vp->func && (flags & VNOFUNC) == 0)
12685                         (*vp->func)(strchr(s, '=') + 1);
12686
12687                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12688                         ckfree(vp->text);
12689
12690                 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12691                 vp->flags |= flags;
12692                 vp->text = s;
12693
12694                 /*
12695                  * We could roll this to a function, to handle it as
12696                  * a regular variable function callback, but why bother?
12697                  */
12698                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12699                         chkmail(1);
12700                 INTON;
12701                 return;
12702         }
12703         /* not found */
12704         vp = ckmalloc(sizeof (*vp));
12705         vp->flags = flags;
12706         vp->text = s;
12707         vp->next = *vpp;
12708         vp->func = NULL;
12709         *vpp = vp;
12710 }
12711
12712
12713
12714 /*
12715  * Process a linked list of variable assignments.
12716  */
12717
12718 static void
12719 listsetvar(mylist)
12720         struct strlist *mylist;
12721         {
12722         struct strlist *lp;
12723
12724         INTOFF;
12725         for (lp = mylist ; lp ; lp = lp->next) {
12726                 setvareq(savestr(lp->text), 0);
12727         }
12728         INTON;
12729 }
12730
12731
12732
12733 /*
12734  * Find the value of a variable.  Returns NULL if not set.
12735  */
12736
12737 static char *
12738 lookupvar(name)
12739         const char *name;
12740         {
12741         struct var *v;
12742
12743         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12744                 return strchr(v->text, '=') + 1;
12745         }
12746         return NULL;
12747 }
12748
12749
12750
12751 /*
12752  * Search the environment of a builtin command.
12753  */
12754
12755 static char *
12756 bltinlookup(name)
12757         const char *name;
12758 {
12759         struct strlist *sp;
12760
12761         for (sp = cmdenviron ; sp ; sp = sp->next) {
12762                 if (varequal(sp->text, name))
12763                         return strchr(sp->text, '=') + 1;
12764         }
12765         return lookupvar(name);
12766 }
12767
12768
12769
12770 /*
12771  * Generate a list of exported variables.  This routine is used to construct
12772  * the third argument to execve when executing a program.
12773  */
12774
12775 static char **
12776 environment() {
12777         int nenv;
12778         struct var **vpp;
12779         struct var *vp;
12780         char **env;
12781         char **ep;
12782
12783         nenv = 0;
12784         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12785                 for (vp = *vpp ; vp ; vp = vp->next)
12786                         if (vp->flags & VEXPORT)
12787                                 nenv++;
12788         }
12789         ep = env = stalloc((nenv + 1) * sizeof *env);
12790         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12791                 for (vp = *vpp ; vp ; vp = vp->next)
12792                         if (vp->flags & VEXPORT)
12793                                 *ep++ = vp->text;
12794         }
12795         *ep = NULL;
12796         return env;
12797 }
12798
12799
12800 /*
12801  * Called when a shell procedure is invoked to clear out nonexported
12802  * variables.  It is also necessary to reallocate variables of with
12803  * VSTACK set since these are currently allocated on the stack.
12804  */
12805
12806 static void
12807 shprocvar(void) {
12808         struct var **vpp;
12809         struct var *vp, **prev;
12810
12811         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12812                 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12813                         if ((vp->flags & VEXPORT) == 0) {
12814                                 *prev = vp->next;
12815                                 if ((vp->flags & VTEXTFIXED) == 0)
12816                                         ckfree(vp->text);
12817                                 if ((vp->flags & VSTRFIXED) == 0)
12818                                         ckfree(vp);
12819                         } else {
12820                                 if (vp->flags & VSTACK) {
12821                                         vp->text = savestr(vp->text);
12822                                         vp->flags &=~ VSTACK;
12823                                 }
12824                                 prev = &vp->next;
12825                         }
12826                 }
12827         }
12828         initvar();
12829 }
12830
12831
12832
12833 /*
12834  * Command to list all variables which are set.  Currently this command
12835  * is invoked from the set command when the set command is called without
12836  * any variables.
12837  */
12838
12839 static int
12840 showvarscmd(argc, argv)
12841         int argc;
12842         char **argv;
12843 {
12844         showvars(nullstr, VUNSET, VUNSET);
12845         return 0;
12846 }
12847
12848
12849
12850 /*
12851  * The export and readonly commands.
12852  */
12853
12854 static int
12855 exportcmd(argc, argv)
12856         int argc;
12857         char **argv;
12858 {
12859         struct var *vp;
12860         char *name;
12861         const char *p;
12862         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12863         int pflag;
12864
12865         listsetvar(cmdenviron);
12866         pflag = (nextopt("p") == 'p');
12867         if (argc > 1 && !pflag) {
12868                 while ((name = *argptr++) != NULL) {
12869                         if ((p = strchr(name, '=')) != NULL) {
12870                                 p++;
12871                         } else {
12872                                 if ((vp = *findvar(hashvar(name), name))) {
12873                                         vp->flags |= flag;
12874                                         goto found;
12875                                 }
12876                         }
12877                         setvar(name, p, flag);
12878 found:;
12879                 }
12880         } else {
12881                 showvars(argv[0], flag, 0);
12882         }
12883         return 0;
12884 }
12885
12886
12887 /*
12888  * The "local" command.
12889  */
12890
12891 /* funcnest nonzero if we are currently evaluating a function */
12892
12893 static int
12894 localcmd(argc, argv)
12895         int argc;
12896         char **argv;
12897 {
12898         char *name;
12899
12900         if (! funcnest)
12901                 error("Not in a function");
12902         while ((name = *argptr++) != NULL) {
12903                 mklocal(name);
12904         }
12905         return 0;
12906 }
12907
12908
12909 /*
12910  * Make a variable a local variable.  When a variable is made local, it's
12911  * value and flags are saved in a localvar structure.  The saved values
12912  * will be restored when the shell function returns.  We handle the name
12913  * "-" as a special case.
12914  */
12915
12916 static void
12917 mklocal(name)
12918         char *name;
12919         {
12920         struct localvar *lvp;
12921         struct var **vpp;
12922         struct var *vp;
12923
12924         INTOFF;
12925         lvp = ckmalloc(sizeof (struct localvar));
12926         if (name[0] == '-' && name[1] == '\0') {
12927                 char *p;
12928                 p = ckmalloc(sizeof optet_vals);
12929                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12930                 vp = NULL;
12931         } else {
12932                 vpp = hashvar(name);
12933                 vp = *findvar(vpp, name);
12934                 if (vp == NULL) {
12935                         if (strchr(name, '='))
12936                                 setvareq(savestr(name), VSTRFIXED);
12937                         else
12938                                 setvar(name, NULL, VSTRFIXED);
12939                         vp = *vpp;      /* the new variable */
12940                         lvp->text = NULL;
12941                         lvp->flags = VUNSET;
12942                 } else {
12943                         lvp->text = vp->text;
12944                         lvp->flags = vp->flags;
12945                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12946                         if (strchr(name, '='))
12947                                 setvareq(savestr(name), 0);
12948                 }
12949         }
12950         lvp->vp = vp;
12951         lvp->next = localvars;
12952         localvars = lvp;
12953         INTON;
12954 }
12955
12956
12957 /*
12958  * Called after a function returns.
12959  */
12960
12961 static void
12962 poplocalvars() {
12963         struct localvar *lvp;
12964         struct var *vp;
12965
12966         while ((lvp = localvars) != NULL) {
12967                 localvars = lvp->next;
12968                 vp = lvp->vp;
12969                 if (vp == NULL) {       /* $- saved */
12970                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12971                         ckfree(lvp->text);
12972                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12973                         (void)unsetvar(vp->text);
12974                 } else {
12975                         if ((vp->flags & VTEXTFIXED) == 0)
12976                                 ckfree(vp->text);
12977                         vp->flags = lvp->flags;
12978                         vp->text = lvp->text;
12979                 }
12980                 ckfree(lvp);
12981         }
12982 }
12983
12984
12985 static int
12986 setvarcmd(argc, argv)
12987         int argc;
12988         char **argv;
12989 {
12990         if (argc <= 2)
12991                 return unsetcmd(argc, argv);
12992         else if (argc == 3)
12993                 setvar(argv[1], argv[2], 0);
12994         else
12995                 error("List assignment not implemented");
12996         return 0;
12997 }
12998
12999
13000 /*
13001  * The unset builtin command.  We unset the function before we unset the
13002  * variable to allow a function to be unset when there is a readonly variable
13003  * with the same name.
13004  */
13005
13006 static int
13007 unsetcmd(argc, argv)
13008         int argc;
13009         char **argv;
13010 {
13011         char **ap;
13012         int i;
13013         int flg_func = 0;
13014         int flg_var = 0;
13015         int ret = 0;
13016
13017         while ((i = nextopt("vf")) != '\0') {
13018                 if (i == 'f')
13019                         flg_func = 1;
13020                 else
13021                         flg_var = 1;
13022         }
13023         if (flg_func == 0 && flg_var == 0)
13024                 flg_var = 1;
13025
13026         for (ap = argptr; *ap ; ap++) {
13027                 if (flg_func)
13028                         unsetfunc(*ap);
13029                 if (flg_var)
13030                         ret |= unsetvar(*ap);
13031         }
13032         return ret;
13033 }
13034
13035
13036 /*
13037  * Unset the specified variable.
13038  */
13039
13040 static int
13041 unsetvar(s)
13042         const char *s;
13043         {
13044         struct var **vpp;
13045         struct var *vp;
13046
13047         vpp = findvar(hashvar(s), s);
13048         vp = *vpp;
13049         if (vp) {
13050                 if (vp->flags & VREADONLY)
13051                         return (1);
13052                 INTOFF;
13053                 if (*(strchr(vp->text, '=') + 1) != '\0')
13054                         setvar(s, nullstr, 0);
13055                 vp->flags &= ~VEXPORT;
13056                 vp->flags |= VUNSET;
13057                 if ((vp->flags & VSTRFIXED) == 0) {
13058                         if ((vp->flags & VTEXTFIXED) == 0)
13059                                 ckfree(vp->text);
13060                         *vpp = vp->next;
13061                         ckfree(vp);
13062                 }
13063                 INTON;
13064                 return (0);
13065         }
13066
13067         return (0);
13068 }
13069
13070
13071
13072 /*
13073  * Find the appropriate entry in the hash table from the name.
13074  */
13075
13076 static struct var **
13077 hashvar(p)
13078         const char *p;
13079         {
13080         unsigned int hashval;
13081
13082         hashval = ((unsigned char) *p) << 4;
13083         while (*p && *p != '=')
13084                 hashval += (unsigned char) *p++;
13085         return &vartab[hashval % VTABSIZE];
13086 }
13087
13088
13089
13090 /*
13091  * Returns true if the two strings specify the same varable.  The first
13092  * variable name is terminated by '='; the second may be terminated by
13093  * either '=' or '\0'.
13094  */
13095
13096 static int
13097 varequal(p, q)
13098         const char *p, *q;
13099         {
13100         while (*p == *q++) {
13101                 if (*p++ == '=')
13102                         return 1;
13103         }
13104         if (*p == '=' && *(q - 1) == '\0')
13105                 return 1;
13106         return 0;
13107 }
13108
13109 static void
13110 showvars(const char *myprefix, int mask, int xor)
13111 {
13112         struct var **vpp;
13113         struct var *vp;
13114         const char *sep = myprefix == nullstr ? myprefix : spcstr;
13115
13116         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
13117                 for (vp = *vpp ; vp ; vp = vp->next) {
13118                         if ((vp->flags & mask) ^ xor) {
13119                                 char *p;
13120                                 int len;
13121
13122                                 p = strchr(vp->text, '=') + 1;
13123                                 len = p - vp->text;
13124                                 p = single_quote(p);
13125
13126                                 out1fmt(
13127                                         "%s%s%.*s%s\n", myprefix, sep, len,
13128                                         vp->text, p
13129                                 );
13130                                 stunalloc(p);
13131                         }
13132                 }
13133         }
13134 }
13135
13136 static struct var **
13137 findvar(struct var **vpp, const char *name)
13138 {
13139         for (; *vpp; vpp = &(*vpp)->next) {
13140                 if (varequal((*vpp)->text, name)) {
13141                         break;
13142                 }
13143         }
13144         return vpp;
13145 }
13146
13147 /*
13148  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
13149  * This file contains code for the times builtin.
13150  * $Id: ash.c,v 1.7 2001/07/07 00:05:55 andersen Exp $
13151  */
13152 static int timescmd (int argc, char **argv)
13153 {
13154         struct tms buf;
13155         long int clk_tck = sysconf(_SC_CLK_TCK);
13156
13157         times(&buf);
13158         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
13159                (int) (buf.tms_utime / clk_tck / 60),
13160                ((double) buf.tms_utime) / clk_tck,
13161                (int) (buf.tms_stime / clk_tck / 60),
13162                ((double) buf.tms_stime) / clk_tck,
13163                (int) (buf.tms_cutime / clk_tck / 60),
13164                ((double) buf.tms_cutime) / clk_tck,
13165                (int) (buf.tms_cstime / clk_tck / 60),
13166                ((double) buf.tms_cstime) / clk_tck);
13167         return 0;
13168 }
13169
13170
13171 /*-
13172  * Copyright (c) 1989, 1991, 1993, 1994
13173  *      The Regents of the University of California.  All rights reserved.
13174  *
13175  * This code is derived from software contributed to Berkeley by
13176  * Kenneth Almquist.
13177  *
13178  * Redistribution and use in source and binary forms, with or without
13179  * modification, are permitted provided that the following conditions
13180  * are met:
13181  * 1. Redistributions of source code must retain the above copyright
13182  *    notice, this list of conditions and the following disclaimer.
13183  * 2. Redistributions in binary form must reproduce the above copyright
13184  *    notice, this list of conditions and the following disclaimer in the
13185  *    documentation and/or other materials provided with the distribution.
13186  *
13187  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
13188  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
13189  *
13190  * 4. Neither the name of the University nor the names of its contributors
13191  *    may be used to endorse or promote products derived from this software
13192  *    without specific prior written permission.
13193  *
13194  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13195  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13196  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13197  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13198  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13199  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13200  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13201  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13202  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13203  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13204  * SUCH DAMAGE.
13205  */