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