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