vodz' latest update to ash.c
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Kenneth Almquist.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26  * package.
27  *
28  * Modified by Erik Andersen <andersee@debian.org> and
29  * Vladimir Oleynik <vodz@usa.net> to be used in busybox
30  *
31  *
32  * Original copyright notice is retained at the end of this file.
33  */
34
35
36 /* These defines allow you to adjust the feature set to be compiled
37  * into the ash shell.   As a rule, enabling these options will make
38  * ash get bigger...   With all of these options off, ash adds about
39  * 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                         while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
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 #ifdef ASH_ALIAS
6095 /* 1 == check for aliases, 2 == also check for assignments */
6096 static int checkalias;
6097 #endif
6098
6099 static void
6100 reset(void) {
6101
6102       /* from eval.c: */
6103       {
6104               evalskip = 0;
6105               loopnest = 0;
6106               funcnest = 0;
6107       }
6108
6109       /* from input.c: */
6110       {
6111               if (exception != EXSHELLPROC)
6112                       parselleft = parsenleft = 0;      /* clear input buffer */
6113               popallfiles();
6114       }
6115
6116       /* from parser.c: */
6117       {
6118               tokpushback = 0;
6119               checkkwd = 0;
6120 #ifdef ASH_ALIAS
6121               checkalias = 0;
6122 #endif
6123       }
6124
6125       /* from redir.c: */
6126       {
6127               while (redirlist)
6128                       popredir();
6129       }
6130
6131 }
6132
6133
6134
6135 /*
6136  * This file implements the input routines used by the parser.
6137  */
6138
6139 #ifdef BB_FEATURE_COMMAND_EDITING
6140 unsigned int shell_context;
6141 static const char * cmdedit_prompt;
6142 static inline void putprompt(const char *s) {
6143     cmdedit_prompt = s;
6144 }
6145 #else
6146 static inline void putprompt(const char *s) {
6147     out2str(s);
6148 }
6149 #endif
6150
6151 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
6152
6153
6154
6155 /*
6156  * Same as pgetc(), but ignores PEOA.
6157  */
6158
6159 #ifdef ASH_ALIAS
6160 static int
6161 pgetc2()
6162 {
6163         int c;
6164         do {
6165                 c = pgetc_macro();
6166         } while (c == PEOA);
6167         return c;
6168 }
6169 #else
6170 static inline int pgetc2() { return pgetc_macro(); }
6171 #endif
6172
6173 /*
6174  * Read a line from the script.
6175  */
6176
6177 static inline char *
6178 pfgets(char *line, int len)
6179 {
6180         char *p = line;
6181         int nleft = len;
6182         int c;
6183
6184         while (--nleft > 0) {
6185                 c = pgetc2();
6186                 if (c == PEOF) {
6187                         if (p == line)
6188                                 return NULL;
6189                         break;
6190                 }
6191                 *p++ = c;
6192                 if (c == '\n')
6193                         break;
6194         }
6195         *p = '\0';
6196         return line;
6197 }
6198
6199 static inline int
6200 preadfd(void)
6201 {
6202     int nr;
6203     char *buf =  parsefile->buf;
6204     parsenextc = buf;
6205
6206 retry:
6207 #ifdef BB_FEATURE_COMMAND_EDITING
6208         {
6209             if (parsefile->fd)
6210                 nr = read(parsefile->fd, buf, BUFSIZ - 1);
6211             else {
6212                 do {
6213                     cmdedit_read_input((char*)cmdedit_prompt, buf);
6214                     nr = strlen(buf);
6215                 } while (nr <=0 || shell_context);
6216                 cmdedit_terminate();
6217             }
6218         }
6219 #else
6220         nr = read(parsefile->fd, buf, BUFSIZ - 1);
6221 #endif
6222
6223         if (nr < 0) {
6224                 if (errno == EINTR)
6225                         goto retry;
6226                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6227                         int flags = fcntl(0, F_GETFL, 0);
6228                         if (flags >= 0 && flags & O_NONBLOCK) {
6229                                 flags &=~ O_NONBLOCK;
6230                                 if (fcntl(0, F_SETFL, flags) >= 0) {
6231                                         out2str("sh: turning off NDELAY mode\n");
6232                                         goto retry;
6233                                 }
6234                         }
6235                 }
6236         }
6237         return nr;
6238 }
6239
6240 static void
6241 popstring(void)
6242 {
6243         struct strpush *sp = parsefile->strpush;
6244
6245         INTOFF;
6246 #ifdef ASH_ALIAS
6247         if (sp->ap) {
6248                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6249                         if (!checkalias) {
6250                                 checkalias = 1;
6251                         }
6252                 }
6253                 if (sp->string != sp->ap->val) {
6254                         ckfree(sp->string);
6255                 }
6256
6257                 sp->ap->flag &= ~ALIASINUSE;
6258                 if (sp->ap->flag & ALIASDEAD) {
6259                         unalias(sp->ap->name);
6260                 }
6261         }
6262 #endif
6263         parsenextc = sp->prevstring;
6264         parsenleft = sp->prevnleft;
6265 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6266         parsefile->strpush = sp->prev;
6267         if (sp != &(parsefile->basestrpush))
6268                 ckfree(sp);
6269         INTON;
6270 }
6271
6272
6273 /*
6274  * Refill the input buffer and return the next input character:
6275  *
6276  * 1) If a string was pushed back on the input, pop it;
6277  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6278  *    from a string so we can't refill the buffer, return EOF.
6279  * 3) If the is more stuff in this buffer, use it else call read to fill it.
6280  * 4) Process input up to the next newline, deleting nul characters.
6281  */
6282
6283 static int
6284 preadbuffer(void)
6285 {
6286         char *p, *q;
6287         int more;
6288         char savec;
6289
6290         while (parsefile->strpush) {
6291 #ifdef ASH_ALIAS
6292                 if (parsenleft == -1 && parsefile->strpush->ap &&
6293                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6294                         return PEOA;
6295                 }
6296 #endif
6297                 popstring();
6298                 if (--parsenleft >= 0)
6299                         return (*parsenextc++);
6300         }
6301         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6302                 return PEOF;
6303         flushall();
6304
6305 again:
6306         if (parselleft <= 0) {
6307                 if ((parselleft = preadfd()) <= 0) {
6308                         parselleft = parsenleft = EOF_NLEFT;
6309                         return PEOF;
6310                 }
6311         }
6312
6313         q = p = parsenextc;
6314
6315         /* delete nul characters */
6316         for (more = 1; more;) {
6317                 switch (*p) {
6318                 case '\0':
6319                         p++;    /* Skip nul */
6320                         goto check;
6321
6322
6323                 case '\n':
6324                         parsenleft = q - parsenextc;
6325                         more = 0; /* Stop processing here */
6326                         break;
6327                 }
6328
6329                 *q++ = *p++;
6330 check:
6331                 if (--parselleft <= 0 && more) {
6332                         parsenleft = q - parsenextc - 1;
6333                         if (parsenleft < 0)
6334                                 goto again;
6335                         more = 0;
6336                 }
6337         }
6338
6339         savec = *q;
6340         *q = '\0';
6341
6342         if (vflag) {
6343                 out2str(parsenextc);
6344         }
6345
6346         *q = savec;
6347
6348         return *parsenextc++;
6349 }
6350
6351
6352 /*
6353  * Push a string back onto the input at this current parsefile level.
6354  * We handle aliases this way.
6355  */
6356 static void
6357 pushstring(char *s, int len, void *ap)
6358 {
6359         struct strpush *sp;
6360
6361         INTOFF;
6362 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6363         if (parsefile->strpush) {
6364                 sp = ckmalloc(sizeof (struct strpush));
6365                 sp->prev = parsefile->strpush;
6366                 parsefile->strpush = sp;
6367         } else
6368                 sp = parsefile->strpush = &(parsefile->basestrpush);
6369         sp->prevstring = parsenextc;
6370         sp->prevnleft = parsenleft;
6371 #ifdef ASH_ALIAS
6372         sp->ap = (struct alias *)ap;
6373         if (ap) {
6374                 ((struct alias *)ap)->flag |= ALIASINUSE;
6375                 sp->string = s;
6376         }
6377 #endif
6378         parsenextc = s;
6379         parsenleft = len;
6380         INTON;
6381 }
6382
6383
6384 /*
6385  * Like setinputfile, but takes input from a string.
6386  */
6387
6388 static void
6389 setinputstring(char *string)
6390 {
6391         INTOFF;
6392         pushfile();
6393         parsenextc = string;
6394         parsenleft = strlen(string);
6395         parsefile->buf = NULL;
6396         plinno = 1;
6397         INTON;
6398 }
6399
6400
6401
6402 /*
6403  * To handle the "." command, a stack of input files is used.  Pushfile
6404  * adds a new entry to the stack and popfile restores the previous level.
6405  */
6406
6407 static void
6408 pushfile(void) {
6409         struct parsefile *pf;
6410
6411         parsefile->nleft = parsenleft;
6412         parsefile->lleft = parselleft;
6413         parsefile->nextc = parsenextc;
6414         parsefile->linno = plinno;
6415         pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6416         pf->prev = parsefile;
6417         pf->fd = -1;
6418         pf->strpush = NULL;
6419         pf->basestrpush.prev = NULL;
6420         parsefile = pf;
6421 }
6422
6423 #ifdef JOBS
6424 static void restartjob (struct job *);
6425 #endif
6426 static void freejob (struct job *);
6427 static struct job *getjob (const char *);
6428 static int dowait (int, struct job *);
6429 static void waitonint(int);
6430
6431
6432 /*
6433  * We keep track of whether or not fd0 has been redirected.  This is for
6434  * background commands, where we want to redirect fd0 to /dev/null only
6435  * if it hasn't already been redirected.
6436 */
6437 static int fd0_redirected = 0;
6438
6439 /* Return true if fd 0 has already been redirected at least once.  */
6440 static inline int
6441 fd0_redirected_p () {
6442         return fd0_redirected != 0;
6443 }
6444
6445 static void dupredirect (const union node *, int, int fd1dup);
6446
6447 #ifdef JOBS
6448 /*
6449  * Turn job control on and off.
6450  *
6451  * Note:  This code assumes that the third arg to ioctl is a character
6452  * pointer, which is true on Berkeley systems but not System V.  Since
6453  * System V doesn't have job control yet, this isn't a problem now.
6454  */
6455
6456
6457
6458 static void setjobctl(int enable)
6459 {
6460 #ifdef OLD_TTY_DRIVER
6461         int ldisc;
6462 #endif
6463
6464         if (enable == jobctl || rootshell == 0)
6465                 return;
6466         if (enable) {
6467                 do { /* while we are in the background */
6468 #ifdef OLD_TTY_DRIVER
6469                         if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6470 #else
6471                         initialpgrp = tcgetpgrp(2);
6472                         if (initialpgrp < 0) {
6473 #endif
6474                                 out2str("sh: can't access tty; job cenabletrol turned off\n");
6475                                 mflag = 0;
6476                                 return;
6477                         }
6478                         if (initialpgrp == -1)
6479                                 initialpgrp = getpgrp();
6480                         else if (initialpgrp != getpgrp()) {
6481                                 killpg(initialpgrp, SIGTTIN);
6482                                 continue;
6483                         }
6484                 } while (0);
6485 #ifdef OLD_TTY_DRIVER
6486                 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6487                         out2str("sh: need new tty driver to run job cenabletrol; job cenabletrol turned off\n");
6488                         mflag = 0;
6489                         return;
6490                 }
6491 #endif
6492                 setsignal(SIGTSTP);
6493                 setsignal(SIGTTOU);
6494                 setsignal(SIGTTIN);
6495                 setpgid(0, rootpid);
6496 #ifdef OLD_TTY_DRIVER
6497                 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6498 #else
6499                 tcsetpgrp(2, rootpid);
6500 #endif
6501         } else { /* turning job cenabletrol off */
6502                 setpgid(0, initialpgrp);
6503 #ifdef OLD_TTY_DRIVER
6504                 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6505 #else
6506                 tcsetpgrp(2, initialpgrp);
6507 #endif
6508                 setsignal(SIGTSTP);
6509                 setsignal(SIGTTOU);
6510                 setsignal(SIGTTIN);
6511         }
6512         jobctl = enable;
6513 }
6514 #endif
6515
6516
6517 /* A translation list so we can be polite to our users. */
6518 static char *signal_names[NSIG + 2] = {
6519     "EXIT",
6520     "SIGHUP",
6521     "SIGINT",
6522     "SIGQUIT",
6523     "SIGILL",
6524     "SIGTRAP",
6525     "SIGABRT",
6526     "SIGBUS",
6527     "SIGFPE",
6528     "SIGKILL",
6529     "SIGUSR1",
6530     "SIGSEGV",
6531     "SIGUSR2",
6532     "SIGPIPE",
6533     "SIGALRM",
6534     "SIGTERM",
6535     "SIGJUNK(16)",
6536     "SIGCHLD",
6537     "SIGCONT",
6538     "SIGSTOP",
6539     "SIGTSTP",
6540     "SIGTTIN",
6541     "SIGTTOU",
6542     "SIGURG",
6543     "SIGXCPU",
6544     "SIGXFSZ",
6545     "SIGVTALRM",
6546     "SIGPROF",
6547     "SIGWINCH",
6548     "SIGIO",
6549     "SIGPWR",
6550     "SIGSYS",
6551 #ifdef SIGRTMIN
6552     "SIGRTMIN",
6553     "SIGRTMIN+1",
6554     "SIGRTMIN+2",
6555     "SIGRTMIN+3",
6556     "SIGRTMIN+4",
6557     "SIGRTMIN+5",
6558     "SIGRTMIN+6",
6559     "SIGRTMIN+7",
6560     "SIGRTMIN+8",
6561     "SIGRTMIN+9",
6562     "SIGRTMIN+10",
6563     "SIGRTMIN+11",
6564     "SIGRTMIN+12",
6565     "SIGRTMIN+13",
6566     "SIGRTMIN+14",
6567     "SIGRTMIN+15",
6568     "SIGRTMAX-15",
6569     "SIGRTMAX-14",
6570     "SIGRTMAX-13",
6571     "SIGRTMAX-12",
6572     "SIGRTMAX-11",
6573     "SIGRTMAX-10",
6574     "SIGRTMAX-9",
6575     "SIGRTMAX-8",
6576     "SIGRTMAX-7",
6577     "SIGRTMAX-6",
6578     "SIGRTMAX-5",
6579     "SIGRTMAX-4",
6580     "SIGRTMAX-3",
6581     "SIGRTMAX-2",
6582     "SIGRTMAX-1",
6583     "SIGRTMAX",
6584 #endif
6585     "DEBUG",
6586     (char *)0x0,
6587 };
6588
6589
6590
6591 #ifdef JOBS
6592 static int
6593 killcmd(argc, argv)
6594         int argc;
6595         char **argv;
6596 {
6597         int signo = -1;
6598         int list = 0;
6599         int i;
6600         pid_t pid;
6601         struct job *jp;
6602
6603         if (argc <= 1) {
6604 usage:
6605                 error(
6606 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6607 "kill -l [exitstatus]"
6608                 );
6609         }
6610
6611         if (*argv[1] == '-') {
6612                 signo = decode_signal(argv[1] + 1, 1);
6613                 if (signo < 0) {
6614                         int c;
6615
6616                         while ((c = nextopt("ls:")) != '\0')
6617                                 switch (c) {
6618                                 case 'l':
6619                                         list = 1;
6620                                         break;
6621                                 case 's':
6622                                         signo = decode_signal(optionarg, 1);
6623                                         if (signo < 0) {
6624                                                 error(
6625                                                         "invalid signal number or name: %s",
6626                                                         optionarg
6627                                                 );
6628                                         }
6629                                         break;
6630 #ifdef DEBUG
6631                                 default:
6632                                         error(
6633         "nextopt returned character code 0%o", c);
6634 #endif
6635                         }
6636                 } else
6637                         argptr++;
6638         }
6639
6640         if (!list && signo < 0)
6641                 signo = SIGTERM;
6642
6643         if ((signo < 0 || !*argptr) ^ list) {
6644                 goto usage;
6645         }
6646
6647         if (list) {
6648                 if (!*argptr) {
6649                         out1str("0\n");
6650                         for (i = 1; i < NSIG; i++) {
6651                                 printf(snlfmt, signal_names[i] + 3);
6652                         }
6653                         return 0;
6654                 }
6655                 signo = atoi(*argptr);
6656                 if (signo > 128)
6657                         signo -= 128;
6658                 if (0 < signo && signo < NSIG)
6659                                 printf(snlfmt, signal_names[signo] + 3);
6660                 else
6661                         error("invalid signal number or exit status: %s",
6662                               *argptr);
6663                 return 0;
6664         }
6665
6666         do {
6667                 if (**argptr == '%') {
6668                         jp = getjob(*argptr);
6669                         if (jp->jobctl == 0)
6670                                 error("job %s not created under job control",
6671                                       *argptr);
6672                         pid = -jp->ps[0].pid;
6673                 } else
6674                         pid = atoi(*argptr);
6675                 if (kill(pid, signo) != 0)
6676                         error("%s: %m", *argptr);
6677         } while (*++argptr);
6678
6679         return 0;
6680 }
6681
6682 static int
6683 fgcmd(argc, argv)
6684         int argc;
6685         char **argv;
6686 {
6687         struct job *jp;
6688         int pgrp;
6689         int status;
6690
6691         jp = getjob(argv[1]);
6692         if (jp->jobctl == 0)
6693                 error("job not created under job control");
6694         pgrp = jp->ps[0].pid;
6695 #ifdef OLD_TTY_DRIVER
6696         ioctl(2, TIOCSPGRP, (char *)&pgrp);
6697 #else
6698         tcsetpgrp(2, pgrp);
6699 #endif
6700         restartjob(jp);
6701         INTOFF;
6702         status = waitforjob(jp);
6703         INTON;
6704         return status;
6705 }
6706
6707
6708 static int
6709 bgcmd(argc, argv)
6710         int argc;
6711         char **argv;
6712 {
6713         struct job *jp;
6714
6715         do {
6716                 jp = getjob(*++argv);
6717                 if (jp->jobctl == 0)
6718                         error("job not created under job control");
6719                 restartjob(jp);
6720         } while (--argc > 1);
6721         return 0;
6722 }
6723
6724
6725 static void
6726 restartjob(jp)
6727         struct job *jp;
6728 {
6729         struct procstat *ps;
6730         int i;
6731
6732         if (jp->state == JOBDONE)
6733                 return;
6734         INTOFF;
6735         killpg(jp->ps[0].pid, SIGCONT);
6736         for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6737                 if (WIFSTOPPED(ps->status)) {
6738                         ps->status = -1;
6739                         jp->state = 0;
6740                 }
6741         }
6742         INTON;
6743 }
6744 #endif
6745
6746 static void showjobs(int change);
6747
6748
6749 static int
6750 jobscmd(argc, argv)
6751         int argc;
6752         char **argv;
6753 {
6754         showjobs(0);
6755         return 0;
6756 }
6757
6758
6759 /*
6760  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6761  * statuses have changed since the last call to showjobs.
6762  *
6763  * If the shell is interrupted in the process of creating a job, the
6764  * result may be a job structure containing zero processes.  Such structures
6765  * will be freed here.
6766  */
6767
6768 static void
6769 showjobs(change)
6770         int change;
6771 {
6772         int jobno;
6773         int procno;
6774         int i;
6775         struct job *jp;
6776         struct procstat *ps;
6777         int col;
6778         char s[64];
6779
6780         TRACE(("showjobs(%d) called\n", change));
6781         while (dowait(0, (struct job *)NULL) > 0);
6782         for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6783                 if (! jp->used)
6784                         continue;
6785                 if (jp->nprocs == 0) {
6786                         freejob(jp);
6787                         continue;
6788                 }
6789                 if (change && ! jp->changed)
6790                         continue;
6791                 procno = jp->nprocs;
6792                 for (ps = jp->ps ; ; ps++) {    /* for each process */
6793                         if (ps == jp->ps)
6794                                 snprintf(s, 64, "[%d] %ld ", jobno,
6795                                     (long)ps->pid);
6796                         else
6797                                 snprintf(s, 64, "    %ld ",
6798                                     (long)ps->pid);
6799                         out1str(s);
6800                         col = strlen(s);
6801                         s[0] = '\0';
6802                         if (ps->status == -1) {
6803                                 /* don't print anything */
6804                         } else if (WIFEXITED(ps->status)) {
6805                                 snprintf(s, 64, "Exit %d",
6806                                        WEXITSTATUS(ps->status));
6807                         } else {
6808 #ifdef JOBS
6809                                 if (WIFSTOPPED(ps->status))
6810                                         i = WSTOPSIG(ps->status);
6811                                 else /* WIFSIGNALED(ps->status) */
6812 #endif
6813                                         i = WTERMSIG(ps->status);
6814                                 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6815                                         strcpy(s, sys_siglist[i & 0x7F]);
6816                                 else
6817                                         snprintf(s, 64, "Signal %d", i & 0x7F);
6818                                 if (WCOREDUMP(ps->status))
6819                                         strcat(s, " (core dumped)");
6820                         }
6821                         out1str(s);
6822                         col += strlen(s);
6823                         printf(
6824                                 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6825                                 ps->cmd
6826                         );
6827                         if (--procno <= 0)
6828                                 break;
6829                 }
6830                 jp->changed = 0;
6831                 if (jp->state == JOBDONE) {
6832                         freejob(jp);
6833                 }
6834         }
6835 }
6836
6837
6838 /*
6839  * Mark a job structure as unused.
6840  */
6841
6842 static void
6843 freejob(struct job *jp)
6844 {
6845         const struct procstat *ps;
6846         int i;
6847
6848         INTOFF;
6849         for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6850                 if (ps->cmd != nullstr)
6851                         ckfree(ps->cmd);
6852         }
6853         if (jp->ps != &jp->ps0)
6854                 ckfree(jp->ps);
6855         jp->used = 0;
6856 #ifdef JOBS
6857         if (curjob == jp - jobtab + 1)
6858                 curjob = 0;
6859 #endif
6860         INTON;
6861 }
6862
6863
6864
6865 static int
6866 waitcmd(argc, argv)
6867         int argc;
6868         char **argv;
6869 {
6870         struct job *job;
6871         int status, retval;
6872         struct job *jp;
6873
6874         if (--argc > 0) {
6875 start:
6876                 job = getjob(*++argv);
6877         } else {
6878                 job = NULL;
6879         }
6880         for (;;) {      /* loop until process terminated or stopped */
6881                 if (job != NULL) {
6882                         if (job->state) {
6883                                 status = job->ps[job->nprocs - 1].status;
6884                                 if (! iflag)
6885                                         freejob(job);
6886                                 if (--argc) {
6887                                         goto start;
6888                                 }
6889                                 if (WIFEXITED(status))
6890                                         retval = WEXITSTATUS(status);
6891 #ifdef JOBS
6892                                 else if (WIFSTOPPED(status))
6893                                         retval = WSTOPSIG(status) + 128;
6894 #endif
6895                                 else {
6896                                         /* XXX: limits number of signals */
6897                                         retval = WTERMSIG(status) + 128;
6898                                 }
6899                                 return retval;
6900                         }
6901                 } else {
6902                         for (jp = jobtab ; ; jp++) {
6903                                 if (jp >= jobtab + njobs) {     /* no running procs */
6904                                         return 0;
6905                                 }
6906                                 if (jp->used && jp->state == 0)
6907                                         break;
6908                         }
6909                 }
6910                 if (dowait(2, 0) < 0 && errno == EINTR) {
6911                         return 129;
6912                 }
6913         }
6914 }
6915
6916
6917
6918 /*
6919  * Convert a job name to a job structure.
6920  */
6921
6922 static struct job *
6923 getjob(const char *name)
6924 {
6925         int jobno;
6926         struct job *jp;
6927         int pid;
6928         int i;
6929
6930         if (name == NULL) {
6931 #ifdef JOBS
6932 currentjob:
6933                 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6934                         error("No current job");
6935                 return &jobtab[jobno - 1];
6936 #else
6937                 error("No current job");
6938 #endif
6939         } else if (name[0] == '%') {
6940                 if (is_digit(name[1])) {
6941                         jobno = number(name + 1);
6942                         if (jobno > 0 && jobno <= njobs
6943                          && jobtab[jobno - 1].used != 0)
6944                                 return &jobtab[jobno - 1];
6945 #ifdef JOBS
6946                 } else if (name[1] == '%' && name[2] == '\0') {
6947                         goto currentjob;
6948 #endif
6949                 } else {
6950                         struct job *found = NULL;
6951                         for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6952                                 if (jp->used && jp->nprocs > 0
6953                                  && prefix(name + 1, jp->ps[0].cmd)) {
6954                                         if (found)
6955                                                 error("%s: ambiguous", name);
6956                                         found = jp;
6957                                 }
6958                         }
6959                         if (found)
6960                                 return found;
6961                 }
6962         } else if (is_number(name, &pid)) {
6963                 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6964                         if (jp->used && jp->nprocs > 0
6965                          && jp->ps[jp->nprocs - 1].pid == pid)
6966                                 return jp;
6967                 }
6968         }
6969         error("No such job: %s", name);
6970         /* NOTREACHED */
6971 }
6972
6973
6974
6975 /*
6976  * Return a new job structure,
6977  */
6978
6979 static struct job *
6980 makejob(const union node *node, int nprocs)
6981 {
6982         int i;
6983         struct job *jp;
6984
6985         for (i = njobs, jp = jobtab ; ; jp++) {
6986                 if (--i < 0) {
6987                         INTOFF;
6988                         if (njobs == 0) {
6989                                 jobtab = ckmalloc(4 * sizeof jobtab[0]);
6990                         } else {
6991                                 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
6992                                 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6993                                 /* Relocate `ps' pointers */
6994                                 for (i = 0; i < njobs; i++)
6995                                         if (jp[i].ps == &jobtab[i].ps0)
6996                                                 jp[i].ps = &jp[i].ps0;
6997                                 ckfree(jobtab);
6998                                 jobtab = jp;
6999                         }
7000                         jp = jobtab + njobs;
7001                         for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
7002                         INTON;
7003                         break;
7004                 }
7005                 if (jp->used == 0)
7006                         break;
7007         }
7008         INTOFF;
7009         jp->state = 0;
7010         jp->used = 1;
7011         jp->changed = 0;
7012         jp->nprocs = 0;
7013 #ifdef JOBS
7014         jp->jobctl = jobctl;
7015 #endif
7016         if (nprocs > 1) {
7017                 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7018         } else {
7019                 jp->ps = &jp->ps0;
7020         }
7021         INTON;
7022         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7023             jp - jobtab + 1));
7024         return jp;
7025 }
7026
7027
7028 /*
7029  * Fork of a subshell.  If we are doing job control, give the subshell its
7030  * own process group.  Jp is a job structure that the job is to be added to.
7031  * N is the command that will be evaluated by the child.  Both jp and n may
7032  * be NULL.  The mode parameter can be one of the following:
7033  *      FORK_FG - Fork off a foreground process.
7034  *      FORK_BG - Fork off a background process.
7035  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
7036  *                   process group even if job control is on.
7037  *
7038  * When job control is turned off, background processes have their standard
7039  * input redirected to /dev/null (except for the second and later processes
7040  * in a pipeline).
7041  */
7042
7043
7044
7045 static int
7046 forkshell(struct job *jp, const union node *n, int mode)
7047 {
7048         int pid;
7049 #ifdef JOBS
7050         int pgrp;
7051 #endif
7052         const char *devnull = _PATH_DEVNULL;
7053         const char *nullerr = "Can't open %s";
7054
7055         TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
7056             mode));
7057         INTOFF;
7058         pid = fork();
7059         if (pid == -1) {
7060                 TRACE(("Fork failed, errno=%d\n", errno));
7061                 INTON;
7062                 error("Cannot fork");
7063         }
7064         if (pid == 0) {
7065                 struct job *p;
7066                 int wasroot;
7067                 int i;
7068
7069                 TRACE(("Child shell %d\n", getpid()));
7070                 wasroot = rootshell;
7071                 rootshell = 0;
7072                 closescript();
7073                 INTON;
7074                 clear_traps();
7075 #ifdef JOBS
7076                 jobctl = 0;             /* do job control only in root shell */
7077                 if (wasroot && mode != FORK_NOJOB && mflag) {
7078                         if (jp == NULL || jp->nprocs == 0)
7079                                 pgrp = getpid();
7080                         else
7081                                 pgrp = jp->ps[0].pid;
7082                         setpgid(0, pgrp);
7083                         if (mode == FORK_FG) {
7084                                 /*** this causes superfluous TIOCSPGRPS ***/
7085 #ifdef OLD_TTY_DRIVER
7086                                 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
7087                                         error("TIOCSPGRP failed, errno=%d", errno);
7088 #else
7089                                 if (tcsetpgrp(2, pgrp) < 0)
7090                                         error("tcsetpgrp failed, errno=%d", errno);
7091 #endif
7092                         }
7093                         setsignal(SIGTSTP);
7094                         setsignal(SIGTTOU);
7095                 } else 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 #else
7106                 if (mode == FORK_BG) {
7107                         ignoresig(SIGINT);
7108                         ignoresig(SIGQUIT);
7109                         if ((jp == NULL || jp->nprocs == 0) &&
7110                             ! fd0_redirected_p ()) {
7111                                 close(0);
7112                                 if (open(devnull, O_RDONLY) != 0)
7113                                         error(nullerr, devnull);
7114                         }
7115                 }
7116 #endif
7117                 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
7118                         if (p->used)
7119                                 freejob(p);
7120                 if (wasroot && iflag) {
7121                         setsignal(SIGINT);
7122                         setsignal(SIGQUIT);
7123                         setsignal(SIGTERM);
7124                 }
7125                 return pid;
7126         }
7127 #ifdef JOBS
7128         if (rootshell && mode != FORK_NOJOB && mflag) {
7129                 if (jp == NULL || jp->nprocs == 0)
7130                         pgrp = pid;
7131                 else
7132                         pgrp = jp->ps[0].pid;
7133                 setpgid(pid, pgrp);
7134         }
7135 #endif
7136         if (mode == FORK_BG)
7137                 backgndpid = pid;               /* set $! */
7138         if (jp) {
7139                 struct procstat *ps = &jp->ps[jp->nprocs++];
7140                 ps->pid = pid;
7141                 ps->status = -1;
7142                 ps->cmd = nullstr;
7143                 if (iflag && rootshell && n)
7144                         ps->cmd = commandtext(n);
7145         }
7146         INTON;
7147         TRACE(("In parent shell:  child = %d\n", pid));
7148         return pid;
7149 }
7150
7151
7152
7153 /*
7154  * Wait for job to finish.
7155  *
7156  * Under job control we have the problem that while a child process is
7157  * running interrupts generated by the user are sent to the child but not
7158  * to the shell.  This means that an infinite loop started by an inter-
7159  * active user may be hard to kill.  With job control turned off, an
7160  * interactive user may place an interactive program inside a loop.  If
7161  * the interactive program catches interrupts, the user doesn't want
7162  * these interrupts to also abort the loop.  The approach we take here
7163  * is to have the shell ignore interrupt signals while waiting for a
7164  * forground process to terminate, and then send itself an interrupt
7165  * signal if the child process was terminated by an interrupt signal.
7166  * Unfortunately, some programs want to do a bit of cleanup and then
7167  * exit on interrupt; unless these processes terminate themselves by
7168  * sending a signal to themselves (instead of calling exit) they will
7169  * confuse this approach.
7170  */
7171
7172 static int
7173 waitforjob(struct job *jp)
7174 {
7175 #ifdef JOBS
7176         int mypgrp = getpgrp();
7177 #endif
7178         int status;
7179         int st;
7180         struct sigaction act, oact;
7181
7182         INTOFF;
7183         intreceived = 0;
7184 #ifdef JOBS
7185         if (!jobctl) {
7186 #else
7187         if (!iflag) {
7188 #endif
7189                 sigaction(SIGINT, 0, &act);
7190                 act.sa_handler = waitonint;
7191                 sigaction(SIGINT, &act, &oact);
7192         }
7193         TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7194         while (jp->state == 0) {
7195                 dowait(1, jp);
7196         }
7197 #ifdef JOBS
7198         if (!jobctl) {
7199 #else
7200         if (!iflag) {
7201 #endif
7202                 sigaction(SIGINT, &oact, 0);
7203                 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7204         }
7205 #ifdef JOBS
7206         if (jp->jobctl) {
7207 #ifdef OLD_TTY_DRIVER
7208                 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7209                         error("TIOCSPGRP failed, errno=%d\n", errno);
7210 #else
7211                 if (tcsetpgrp(2, mypgrp) < 0)
7212                         error("tcsetpgrp failed, errno=%d\n", errno);
7213 #endif
7214         }
7215         if (jp->state == JOBSTOPPED)
7216                 curjob = jp - jobtab + 1;
7217 #endif
7218         status = jp->ps[jp->nprocs - 1].status;
7219         /* convert to 8 bits */
7220         if (WIFEXITED(status))
7221                 st = WEXITSTATUS(status);
7222 #ifdef JOBS
7223         else if (WIFSTOPPED(status))
7224                 st = WSTOPSIG(status) + 128;
7225 #endif
7226         else
7227                 st = WTERMSIG(status) + 128;
7228 #ifdef JOBS
7229         if (jp->jobctl) {
7230                 /*
7231                  * This is truly gross.
7232                  * If we're doing job control, then we did a TIOCSPGRP which
7233                  * caused us (the shell) to no longer be in the controlling
7234                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
7235                  * intuit from the subprocess exit status whether a SIGINT
7236                  * occured, and if so interrupt ourselves.  Yuck.  - mycroft
7237                  */
7238                 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7239                         raise(SIGINT);
7240         }
7241         if (jp->state == JOBDONE)
7242
7243 #endif
7244                 freejob(jp);
7245         INTON;
7246         return st;
7247 }
7248
7249
7250
7251 /*
7252  * Wait for a process to terminate.
7253  */
7254
7255 /*
7256  * Do a wait system call.  If job control is compiled in, we accept
7257  * stopped processes.  If block is zero, we return a value of zero
7258  * rather than blocking.
7259  *
7260  * System V doesn't have a non-blocking wait system call.  It does
7261  * have a SIGCLD signal that is sent to a process when one of it's
7262  * children dies.  The obvious way to use SIGCLD would be to install
7263  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7264  * was received, and have waitproc bump another counter when it got
7265  * the status of a process.  Waitproc would then know that a wait
7266  * system call would not block if the two counters were different.
7267  * This approach doesn't work because if a process has children that
7268  * have not been waited for, System V will send it a SIGCLD when it
7269  * installs a signal handler for SIGCLD.  What this means is that when
7270  * a child exits, the shell will be sent SIGCLD signals continuously
7271  * until is runs out of stack space, unless it does a wait call before
7272  * restoring the signal handler.  The code below takes advantage of
7273  * this (mis)feature by installing a signal handler for SIGCLD and
7274  * then checking to see whether it was called.  If there are any
7275  * children to be waited for, it will be.
7276  *
7277  */
7278
7279 static inline int
7280 waitproc(int block, int *status)
7281 {
7282         int flags;
7283
7284         flags = 0;
7285 #ifdef JOBS
7286         if (jobctl)
7287                 flags |= WUNTRACED;
7288 #endif
7289         if (block == 0)
7290                 flags |= WNOHANG;
7291         return wait3(status, flags, (struct rusage *)NULL);
7292 }
7293
7294 static int
7295 dowait(int block, struct job *job)
7296 {
7297         int pid;
7298         int status;
7299         struct procstat *sp;
7300         struct job *jp;
7301         struct job *thisjob;
7302         int done;
7303         int stopped;
7304         int core;
7305         int sig;
7306
7307         TRACE(("dowait(%d) called\n", block));
7308         do {
7309                 pid = waitproc(block, &status);
7310                 TRACE(("wait returns %d, status=%d\n", pid, status));
7311         } while (!(block & 2) && pid == -1 && errno == EINTR);
7312         if (pid <= 0)
7313                 return pid;
7314         INTOFF;
7315         thisjob = NULL;
7316         for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7317                 if (jp->used) {
7318                         done = 1;
7319                         stopped = 1;
7320                         for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7321                                 if (sp->pid == -1)
7322                                         continue;
7323                                 if (sp->pid == pid) {
7324                                         TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7325                                         sp->status = status;
7326                                         thisjob = jp;
7327                                 }
7328                                 if (sp->status == -1)
7329                                         stopped = 0;
7330                                 else if (WIFSTOPPED(sp->status))
7331                                         done = 0;
7332                         }
7333                         if (stopped) {          /* stopped or done */
7334                                 int state = done? JOBDONE : JOBSTOPPED;
7335                                 if (jp->state != state) {
7336                                         TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7337                                         jp->state = state;
7338 #ifdef JOBS
7339                                         if (done && curjob == jp - jobtab + 1)
7340                                                 curjob = 0;             /* no current job */
7341 #endif
7342                                 }
7343                         }
7344                 }
7345         }
7346         INTON;
7347         if (! rootshell || ! iflag || (job && thisjob == job)) {
7348                 core = WCOREDUMP(status);
7349 #ifdef JOBS
7350                 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7351                 else
7352 #endif
7353                 if (WIFEXITED(status)) sig = 0;
7354                 else sig = WTERMSIG(status);
7355
7356                 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7357                         if (thisjob != job)
7358                                 out2fmt("%d: ", pid);
7359 #ifdef JOBS
7360                         if (sig == SIGTSTP && rootshell && iflag)
7361                                 out2fmt("%%%ld ",
7362                                     (long)(job - jobtab + 1));
7363 #endif
7364                         if (sig < NSIG && sys_siglist[sig])
7365                                 out2str(sys_siglist[sig]);
7366                         else
7367                                 out2fmt("Signal %d", sig);
7368                         if (core)
7369                                 out2str(" - core dumped");
7370                         out2c('\n');
7371                 } else {
7372                         TRACE(("Not printing status: status=%d, sig=%d\n",
7373                                status, sig));
7374                 }
7375         } else {
7376                 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7377                 if (thisjob)
7378                         thisjob->changed = 1;
7379         }
7380         return pid;
7381 }
7382
7383
7384
7385
7386 /*
7387  * return 1 if there are stopped jobs, otherwise 0
7388  */
7389 static int
7390 stoppedjobs(void)
7391 {
7392         int jobno;
7393         struct job *jp;
7394
7395         if (job_warning)
7396                 return (0);
7397         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7398                 if (jp->used == 0)
7399                         continue;
7400                 if (jp->state == JOBSTOPPED) {
7401                         out2str("You have stopped jobs.\n");
7402                         job_warning = 2;
7403                         return (1);
7404                 }
7405         }
7406
7407         return (0);
7408 }
7409
7410 /*
7411  * Return a string identifying a command (to be printed by the
7412  * jobs command.
7413  */
7414
7415 static char *cmdnextc;
7416 static int cmdnleft;
7417 #define MAXCMDTEXT      200
7418
7419 static void
7420 cmdputs(const char *s)
7421 {
7422         const char *p;
7423         char *q;
7424         char c;
7425         int subtype = 0;
7426
7427         if (cmdnleft <= 0)
7428                 return;
7429         p = s;
7430         q = cmdnextc;
7431         while ((c = *p++) != '\0') {
7432                 if (c == CTLESC)
7433                         *q++ = *p++;
7434                 else if (c == CTLVAR) {
7435                         *q++ = '$';
7436                         if (--cmdnleft > 0)
7437                                 *q++ = '{';
7438                         subtype = *p++;
7439                 } else if (c == '=' && subtype != 0) {
7440                         *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7441                         subtype = 0;
7442                 } else if (c == CTLENDVAR) {
7443                         *q++ = '}';
7444                 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7445                         cmdnleft++;             /* ignore it */
7446                 else
7447                         *q++ = c;
7448                 if (--cmdnleft <= 0) {
7449                         *q++ = '.';
7450                         *q++ = '.';
7451                         *q++ = '.';
7452                         break;
7453                 }
7454         }
7455         cmdnextc = q;
7456 }
7457
7458
7459 static void
7460 cmdtxt(const union node *n)
7461 {
7462         union node *np;
7463         struct nodelist *lp;
7464         const char *p;
7465         int i;
7466         char s[2];
7467
7468         if (n == NULL)
7469                 return;
7470         switch (n->type) {
7471         case NSEMI:
7472                 cmdtxt(n->nbinary.ch1);
7473                 cmdputs("; ");
7474                 cmdtxt(n->nbinary.ch2);
7475                 break;
7476         case NAND:
7477                 cmdtxt(n->nbinary.ch1);
7478                 cmdputs(" && ");
7479                 cmdtxt(n->nbinary.ch2);
7480                 break;
7481         case NOR:
7482                 cmdtxt(n->nbinary.ch1);
7483                 cmdputs(" || ");
7484                 cmdtxt(n->nbinary.ch2);
7485                 break;
7486         case NPIPE:
7487                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7488                         cmdtxt(lp->n);
7489                         if (lp->next)
7490                                 cmdputs(" | ");
7491                 }
7492                 break;
7493         case NSUBSHELL:
7494                 cmdputs("(");
7495                 cmdtxt(n->nredir.n);
7496                 cmdputs(")");
7497                 break;
7498         case NREDIR:
7499         case NBACKGND:
7500                 cmdtxt(n->nredir.n);
7501                 break;
7502         case NIF:
7503                 cmdputs("if ");
7504                 cmdtxt(n->nif.test);
7505                 cmdputs("; then ");
7506                 cmdtxt(n->nif.ifpart);
7507                 cmdputs("...");
7508                 break;
7509         case NWHILE:
7510                 cmdputs("while ");
7511                 goto until;
7512         case NUNTIL:
7513                 cmdputs("until ");
7514 until:
7515                 cmdtxt(n->nbinary.ch1);
7516                 cmdputs("; do ");
7517                 cmdtxt(n->nbinary.ch2);
7518                 cmdputs("; done");
7519                 break;
7520         case NFOR:
7521                 cmdputs("for ");
7522                 cmdputs(n->nfor.var);
7523                 cmdputs(" in ...");
7524                 break;
7525         case NCASE:
7526                 cmdputs("case ");
7527                 cmdputs(n->ncase.expr->narg.text);
7528                 cmdputs(" in ...");
7529                 break;
7530         case NDEFUN:
7531                 cmdputs(n->narg.text);
7532                 cmdputs("() ...");
7533                 break;
7534         case NCMD:
7535                 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7536                         cmdtxt(np);
7537                         if (np->narg.next)
7538                                 cmdputs(spcstr);
7539                 }
7540                 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7541                         cmdputs(spcstr);
7542                         cmdtxt(np);
7543                 }
7544                 break;
7545         case NARG:
7546                 cmdputs(n->narg.text);
7547                 break;
7548         case NTO:
7549                 p = ">";  i = 1;  goto redir;
7550         case NAPPEND:
7551                 p = ">>";  i = 1;  goto redir;
7552         case NTOFD:
7553                 p = ">&";  i = 1;  goto redir;
7554         case NTOOV:
7555                 p = ">|";  i = 1;  goto redir;
7556         case NFROM:
7557                 p = "<";  i = 0;  goto redir;
7558         case NFROMFD:
7559                 p = "<&";  i = 0;  goto redir;
7560         case NFROMTO:
7561                 p = "<>";  i = 0;  goto redir;
7562 redir:
7563                 if (n->nfile.fd != i) {
7564                         s[0] = n->nfile.fd + '0';
7565                         s[1] = '\0';
7566                         cmdputs(s);
7567                 }
7568                 cmdputs(p);
7569                 if (n->type == NTOFD || n->type == NFROMFD) {
7570                         s[0] = n->ndup.dupfd + '0';
7571                         s[1] = '\0';
7572                         cmdputs(s);
7573                 } else {
7574                         cmdtxt(n->nfile.fname);
7575                 }
7576                 break;
7577         case NHERE:
7578         case NXHERE:
7579                 cmdputs("<<...");
7580                 break;
7581         default:
7582                 cmdputs("???");
7583                 break;
7584         }
7585 }
7586
7587
7588 static char *
7589 commandtext(const union node *n)
7590 {
7591         char *name;
7592
7593         cmdnextc = name = ckmalloc(MAXCMDTEXT);
7594         cmdnleft = MAXCMDTEXT - 4;
7595         cmdtxt(n);
7596         *cmdnextc = '\0';
7597         return name;
7598 }
7599
7600
7601 static void waitonint(int sig) {
7602         intreceived = 1;
7603         return;
7604 }
7605 /*
7606  * Routines to check for mail.  (Perhaps make part of main.c?)
7607  */
7608
7609
7610 #define MAXMBOXES 10
7611
7612
7613 static int nmboxes;                     /* number of mailboxes */
7614 static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
7615
7616
7617
7618 /*
7619  * Print appropriate message(s) if mail has arrived.  If the argument is
7620  * nozero, then the value of MAIL has changed, so we just update the
7621  * values.
7622  */
7623
7624 static void
7625 chkmail(int silent)
7626 {
7627         int i;
7628         const char *mpath;
7629         char *p;
7630         char *q;
7631         struct stackmark smark;
7632         struct stat statb;
7633
7634         if (silent)
7635                 nmboxes = 10;
7636         if (nmboxes == 0)
7637                 return;
7638         setstackmark(&smark);
7639         mpath = mpathset()? mpathval() : mailval();
7640         for (i = 0 ; i < nmboxes ; i++) {
7641                 p = padvance(&mpath, nullstr);
7642                 if (p == NULL)
7643                         break;
7644                 if (*p == '\0')
7645                         continue;
7646                 for (q = p ; *q ; q++);
7647 #ifdef DEBUG
7648                 if (q[-1] != '/')
7649                         abort();
7650 #endif
7651                 q[-1] = '\0';                   /* delete trailing '/' */
7652                 if (stat(p, &statb) < 0)
7653                         statb.st_size = 0;
7654                 if (statb.st_size > mailtime[i] && ! silent) {
7655                         out2fmt(snlfmt,
7656                                 pathopt? pathopt : "you have mail");
7657                 }
7658                 mailtime[i] = statb.st_size;
7659         }
7660         nmboxes = i;
7661         popstackmark(&smark);
7662 }
7663
7664 #define PROFILE 0
7665
7666 #if PROFILE
7667 static short profile_buf[16384];
7668 extern int etext();
7669 #endif
7670
7671 static void read_profile (const char *);
7672 static void cmdloop (int);
7673 static void options (int);
7674 static void setoption (int, int);
7675 static void procargs (int, char **);
7676
7677
7678 /*
7679  * Main routine.  We initialize things, parse the arguments, execute
7680  * profiles if we're a login shell, and then call cmdloop to execute
7681  * commands.  The setjmp call sets up the location to jump to when an
7682  * exception occurs.  When an exception occurs the variable "state"
7683  * is used to figure out how far we had gotten.
7684  */
7685
7686 int
7687 shell_main(argc, argv)
7688         int argc;
7689         char **argv;
7690 {
7691         struct jmploc jmploc;
7692         struct stackmark smark;
7693         volatile int state;
7694         const char *shinit;
7695
7696         BLTINCMD = find_builtin("builtin");
7697         EXECCMD = find_builtin("exec");
7698         EVALCMD = find_builtin("eval");
7699
7700 #ifndef BB_FEATURE_SH_FANCY_PROMPT
7701         unsetenv("PS1");
7702         unsetenv("PS2");
7703 #endif
7704
7705 #if PROFILE
7706         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7707 #endif
7708 #if defined(linux) || defined(__GNU__)
7709         signal(SIGCHLD, SIG_DFL);
7710 #endif
7711         state = 0;
7712         if (setjmp(jmploc.loc)) {
7713                 INTOFF;
7714                 /*
7715                  * When a shell procedure is executed, we raise the
7716                  * exception EXSHELLPROC to clean up before executing
7717                  * the shell procedure.
7718                  */
7719                 switch (exception) {
7720                 case EXSHELLPROC:
7721                         rootpid = getpid();
7722                         rootshell = 1;
7723                         minusc = NULL;
7724                         state = 3;
7725                         break;
7726
7727                 case EXEXEC:
7728                         exitstatus = exerrno;
7729                         break;
7730
7731                 case EXERROR:
7732                         exitstatus = 2;
7733                         break;
7734
7735                 default:
7736                         break;
7737                 }
7738
7739                 if (exception != EXSHELLPROC) {
7740                     if (state == 0 || iflag == 0 || ! rootshell)
7741                             exitshell(exitstatus);
7742                 }
7743                 reset();
7744                 if (exception == EXINT) {
7745                         out2c('\n');
7746                 }
7747                 popstackmark(&smark);
7748                 FORCEINTON;                             /* enable interrupts */
7749                 if (state == 1)
7750                         goto state1;
7751                 else if (state == 2)
7752                         goto state2;
7753                 else if (state == 3)
7754                         goto state3;
7755                 else
7756                         goto state4;
7757         }
7758         handler = &jmploc;
7759 #ifdef DEBUG
7760         opentrace();
7761         trputs("Shell args:  ");  trargs(argv);
7762 #endif
7763         rootpid = getpid();
7764         rootshell = 1;
7765         init();
7766         setstackmark(&smark);
7767         procargs(argc, argv);
7768         if (argv[0] && argv[0][0] == '-') {
7769                 state = 1;
7770                 read_profile("/etc/profile");
7771 state1:
7772                 state = 2;
7773                 read_profile(".profile");
7774         }
7775 state2:
7776         state = 3;
7777 #ifndef linux
7778         if (getuid() == geteuid() && getgid() == getegid()) {
7779 #endif
7780                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7781                         state = 3;
7782                         read_profile(shinit);
7783                 }
7784 #ifndef linux
7785         }
7786 #endif
7787 state3:
7788         state = 4;
7789         if (sflag == 0 || minusc) {
7790                 static int sigs[] =  {
7791                     SIGINT, SIGQUIT, SIGHUP,
7792 #ifdef SIGTSTP
7793                     SIGTSTP,
7794 #endif
7795                     SIGPIPE
7796                 };
7797 #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
7798                 int i;
7799
7800                 for (i = 0; i < SIGSSIZE; i++)
7801                     setsignal(sigs[i]);
7802         }
7803
7804         if (minusc)
7805                 evalstring(minusc, 0);
7806
7807         if (sflag || minusc == NULL) {
7808 state4: /* XXX ??? - why isn't this before the "if" statement */
7809                 cmdloop(1);
7810         }
7811 #if PROFILE
7812         monitor(0);
7813 #endif
7814         exitshell(exitstatus);
7815         /* NOTREACHED */
7816 }
7817
7818
7819 /*
7820  * Read and execute commands.  "Top" is nonzero for the top level command
7821  * loop; it turns on prompting if the shell is interactive.
7822  */
7823
7824 static void
7825 cmdloop(int top)
7826 {
7827         union node *n;
7828         struct stackmark smark;
7829         int inter;
7830         int numeof = 0;
7831
7832         TRACE(("cmdloop(%d) called\n", top));
7833         setstackmark(&smark);
7834         for (;;) {
7835                 if (pendingsigs)
7836                         dotrap();
7837                 inter = 0;
7838                 if (iflag && top) {
7839                         inter++;
7840                         showjobs(1);
7841                         chkmail(0);
7842                         flushall();
7843                 }
7844                 n = parsecmd(inter);
7845                 /* showtree(n); DEBUG */
7846                 if (n == NEOF) {
7847                         if (!top || numeof >= 50)
7848                                 break;
7849                         if (!stoppedjobs()) {
7850                                 if (!Iflag)
7851                                         break;
7852                                 out2str("\nUse \"exit\" to leave shell.\n");
7853                         }
7854                         numeof++;
7855                 } else if (n != NULL && nflag == 0) {
7856                         job_warning = (job_warning == 2) ? 1 : 0;
7857                         numeof = 0;
7858                         evaltree(n, 0);
7859                 }
7860                 popstackmark(&smark);
7861                 setstackmark(&smark);
7862                 if (evalskip == SKIPFILE) {
7863                         evalskip = 0;
7864                         break;
7865                 }
7866         }
7867         popstackmark(&smark);
7868 }
7869
7870
7871
7872 /*
7873  * Read /etc/profile or .profile.  Return on error.
7874  */
7875
7876 static void
7877 read_profile(name)
7878         const char *name;
7879 {
7880         int fd;
7881         int xflag_set = 0;
7882         int vflag_set = 0;
7883
7884         INTOFF;
7885         if ((fd = open(name, O_RDONLY)) >= 0)
7886                 setinputfd(fd, 1);
7887         INTON;
7888         if (fd < 0)
7889                 return;
7890         /* -q turns off -x and -v just when executing init files */
7891         if (qflag)  {
7892             if (xflag)
7893                     xflag = 0, xflag_set = 1;
7894             if (vflag)
7895                     vflag = 0, vflag_set = 1;
7896         }
7897         cmdloop(0);
7898         if (qflag)  {
7899             if (xflag_set)
7900                     xflag = 1;
7901             if (vflag_set)
7902                     vflag = 1;
7903         }
7904         popfile();
7905 }
7906
7907
7908
7909 /*
7910  * Read a file containing shell functions.
7911  */
7912
7913 static void
7914 readcmdfile(const char *name)
7915 {
7916         int fd;
7917
7918         INTOFF;
7919         if ((fd = open(name, O_RDONLY)) >= 0)
7920                 setinputfd(fd, 1);
7921         else
7922                 error("Can't open %s", name);
7923         INTON;
7924         cmdloop(0);
7925         popfile();
7926 }
7927
7928
7929
7930 /*
7931  * Take commands from a file.  To be compatable we should do a path
7932  * search for the file, which is necessary to find sub-commands.
7933  */
7934
7935
7936 static inline char *
7937 find_dot_file(mybasename)
7938         char *mybasename;
7939 {
7940         char *fullname;
7941         const char *path = pathval();
7942         struct stat statb;
7943
7944         /* don't try this for absolute or relative paths */
7945         if (strchr(mybasename, '/'))
7946                 return mybasename;
7947
7948         while ((fullname = padvance(&path, mybasename)) != NULL) {
7949                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7950                         /*
7951                          * Don't bother freeing here, since it will
7952                          * be freed by the caller.
7953                          */
7954                         return fullname;
7955                 }
7956                 stunalloc(fullname);
7957         }
7958
7959         /* not found in the PATH */
7960         error("%s: not found", mybasename);
7961         /* NOTREACHED */
7962 }
7963
7964 static int
7965 dotcmd(argc, argv)
7966         int argc;
7967         char **argv;
7968 {
7969         struct strlist *sp;
7970         exitstatus = 0;
7971
7972         for (sp = cmdenviron; sp ; sp = sp->next)
7973                 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7974
7975         if (argc >= 2) {                /* That's what SVR2 does */
7976                 char *fullname;
7977                 struct stackmark smark;
7978
7979                 setstackmark(&smark);
7980                 fullname = find_dot_file(argv[1]);
7981                 setinputfile(fullname, 1);
7982                 commandname = fullname;
7983                 cmdloop(0);
7984                 popfile();
7985                 popstackmark(&smark);
7986         }
7987         return exitstatus;
7988 }
7989
7990
7991 static int
7992 exitcmd(argc, argv)
7993         int argc;
7994         char **argv;
7995 {
7996         if (stoppedjobs())
7997                 return 0;
7998         if (argc > 1)
7999                 exitstatus = number(argv[1]);
8000         else
8001                 exitstatus = oexitstatus;
8002         exitshell(exitstatus);
8003         /* NOTREACHED */
8004 }
8005
8006 static pointer
8007 stalloc(int nbytes)
8008 {
8009         char *p;
8010
8011         nbytes = ALIGN(nbytes);
8012         if (nbytes > stacknleft) {
8013                 int blocksize;
8014                 struct stack_block *sp;
8015
8016                 blocksize = nbytes;
8017                 if (blocksize < MINSIZE)
8018                         blocksize = MINSIZE;
8019                 INTOFF;
8020                 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
8021                 sp->prev = stackp;
8022                 stacknxt = sp->space;
8023                 stacknleft = blocksize;
8024                 stackp = sp;
8025                 INTON;
8026         }
8027         p = stacknxt;
8028         stacknxt += nbytes;
8029         stacknleft -= nbytes;
8030         return p;
8031 }
8032
8033
8034 static void
8035 stunalloc(pointer p)
8036 {
8037 #ifdef DEBUG
8038         if (p == NULL) {                /*DEBUG */
8039                 write(2, "stunalloc\n", 10);
8040                 abort();
8041         }
8042 #endif
8043         if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
8044                 p = stackp->space;
8045         }
8046         stacknleft += stacknxt - (char *)p;
8047         stacknxt = p;
8048 }
8049
8050
8051 static void
8052 setstackmark(struct stackmark *mark)
8053 {
8054         mark->stackp = stackp;
8055         mark->stacknxt = stacknxt;
8056         mark->stacknleft = stacknleft;
8057         mark->marknext = markp;
8058         markp = mark;
8059 }
8060
8061
8062 static void
8063 popstackmark(struct stackmark *mark)
8064 {
8065         struct stack_block *sp;
8066
8067         INTOFF;
8068         markp = mark->marknext;
8069         while (stackp != mark->stackp) {
8070                 sp = stackp;
8071                 stackp = sp->prev;
8072                 ckfree(sp);
8073         }
8074         stacknxt = mark->stacknxt;
8075         stacknleft = mark->stacknleft;
8076         INTON;
8077 }
8078
8079
8080 /*
8081  * When the parser reads in a string, it wants to stick the string on the
8082  * stack and only adjust the stack pointer when it knows how big the
8083  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
8084  * of space on top of the stack and stackblocklen returns the length of
8085  * this block.  Growstackblock will grow this space by at least one byte,
8086  * possibly moving it (like realloc).  Grabstackblock actually allocates the
8087  * part of the block that has been used.
8088  */
8089
8090 static void
8091 growstackblock(void) {
8092         char *p;
8093         int newlen = ALIGN(stacknleft * 2 + 100);
8094         char *oldspace = stacknxt;
8095         int oldlen = stacknleft;
8096         struct stack_block *sp;
8097         struct stack_block *oldstackp;
8098
8099         if (stacknxt == stackp->space && stackp != &stackbase) {
8100                 INTOFF;
8101                 oldstackp = stackp;
8102                 sp = stackp;
8103                 stackp = sp->prev;
8104                 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8105                 sp->prev = stackp;
8106                 stackp = sp;
8107                 stacknxt = sp->space;
8108                 stacknleft = newlen;
8109                 {
8110                   /* Stack marks pointing to the start of the old block
8111                    * must be relocated to point to the new block
8112                    */
8113                   struct stackmark *xmark;
8114                   xmark = markp;
8115                   while (xmark != NULL && xmark->stackp == oldstackp) {
8116                     xmark->stackp = stackp;
8117                     xmark->stacknxt = stacknxt;
8118                     xmark->stacknleft = stacknleft;
8119                     xmark = xmark->marknext;
8120                   }
8121                 }
8122                 INTON;
8123         } else {
8124                 p = stalloc(newlen);
8125                 memcpy(p, oldspace, oldlen);
8126                 stacknxt = p;                   /* free the space */
8127                 stacknleft += newlen;           /* we just allocated */
8128         }
8129 }
8130
8131
8132
8133 static inline void
8134 grabstackblock(int len)
8135 {
8136         len = ALIGN(len);
8137         stacknxt += len;
8138         stacknleft -= len;
8139 }
8140
8141
8142
8143 /*
8144  * The following routines are somewhat easier to use that the above.
8145  * The user declares a variable of type STACKSTR, which may be declared
8146  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
8147  * the user uses the macro STPUTC to add characters to the string.  In
8148  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8149  * grown as necessary.  When the user is done, she can just leave the
8150  * string there and refer to it using stackblock().  Or she can allocate
8151  * the space for it using grabstackstr().  If it is necessary to allow
8152  * someone else to use the stack temporarily and then continue to grow
8153  * the string, the user should use grabstack to allocate the space, and
8154  * then call ungrabstr(p) to return to the previous mode of operation.
8155  *
8156  * USTPUTC is like STPUTC except that it doesn't check for overflow.
8157  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8158  * is space for at least one character.
8159  */
8160
8161
8162 static char *
8163 growstackstr(void) {
8164         int len = stackblocksize();
8165         if (herefd >= 0 && len >= 1024) {
8166                 xwrite(herefd, stackblock(), len);
8167                 sstrnleft = len - 1;
8168                 return stackblock();
8169         }
8170         growstackblock();
8171         sstrnleft = stackblocksize() - len - 1;
8172         return stackblock() + len;
8173 }
8174
8175
8176 /*
8177  * Called from CHECKSTRSPACE.
8178  */
8179
8180 static char *
8181 makestrspace(size_t newlen) {
8182         int len = stackblocksize() - sstrnleft;
8183         do {
8184                 growstackblock();
8185                 sstrnleft = stackblocksize() - len;
8186         } while (sstrnleft < newlen);
8187         return stackblock() + len;
8188 }
8189
8190
8191
8192 static void
8193 ungrabstackstr(char *s, char *p)
8194 {
8195         stacknleft += stacknxt - s;
8196         stacknxt = s;
8197         sstrnleft = stacknleft - (p - s);
8198 }
8199 /*
8200  * Miscelaneous builtins.
8201  */
8202
8203
8204 #undef rflag
8205
8206 //#ifdef __GLIBC__
8207 static mode_t getmode(const void *, mode_t);
8208 static void *setmode(const char *);
8209 //#endif
8210
8211 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8212 typedef long rlim_t;
8213 #endif
8214
8215
8216
8217 /*
8218  * The read builtin.  The -e option causes backslashes to escape the
8219  * following character.
8220  *
8221  * This uses unbuffered input, which may be avoidable in some cases.
8222  */
8223
8224 static int
8225 readcmd(argc, argv)
8226         int argc;
8227         char **argv;
8228 {
8229         char **ap;
8230         int backslash;
8231         char c;
8232         int rflag;
8233         char *prompt;
8234         const char *ifs;
8235         char *p;
8236         int startword;
8237         int status;
8238         int i;
8239
8240         rflag = 0;
8241         prompt = NULL;
8242         while ((i = nextopt("p:r")) != '\0') {
8243                 if (i == 'p')
8244                         prompt = optionarg;
8245                 else
8246                         rflag = 1;
8247         }
8248         if (prompt && isatty(0)) {
8249                 putprompt(prompt);
8250                 flushall();
8251         }
8252         if (*(ap = argptr) == NULL)
8253                 error("arg count");
8254         if ((ifs = bltinlookup("IFS")) == NULL)
8255                 ifs = defifs;
8256         status = 0;
8257         startword = 1;
8258         backslash = 0;
8259         STARTSTACKSTR(p);
8260         for (;;) {
8261                 if (read(0, &c, 1) != 1) {
8262                         status = 1;
8263                         break;
8264                 }
8265                 if (c == '\0')
8266                         continue;
8267                 if (backslash) {
8268                         backslash = 0;
8269                         if (c != '\n')
8270                                 STPUTC(c, p);
8271                         continue;
8272                 }
8273                 if (!rflag && c == '\\') {
8274                         backslash++;
8275                         continue;
8276                 }
8277                 if (c == '\n')
8278                         break;
8279                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8280                         continue;
8281                 }
8282                 startword = 0;
8283                 if (backslash && c == '\\') {
8284                         if (read(0, &c, 1) != 1) {
8285                                 status = 1;
8286                                 break;
8287                         }
8288                         STPUTC(c, p);
8289                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8290                         STACKSTRNUL(p);
8291                         setvar(*ap, stackblock(), 0);
8292                         ap++;
8293                         startword = 1;
8294                         STARTSTACKSTR(p);
8295                 } else {
8296                         STPUTC(c, p);
8297                 }
8298         }
8299         STACKSTRNUL(p);
8300         /* Remove trailing blanks */
8301         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8302                 *p = '\0';
8303         setvar(*ap, stackblock(), 0);
8304         while (*++ap != NULL)
8305                 setvar(*ap, nullstr, 0);
8306         return status;
8307 }
8308
8309
8310
8311 static int
8312 umaskcmd(argc, argv)
8313         int argc;
8314         char **argv;
8315 {
8316         char *ap;
8317         int mask;
8318         int i;
8319         int symbolic_mode = 0;
8320
8321         while (nextopt("S") != '\0') {
8322                 symbolic_mode = 1;
8323         }
8324
8325         INTOFF;
8326         mask = umask(0);
8327         umask(mask);
8328         INTON;
8329
8330         if ((ap = *argptr) == NULL) {
8331                 if (symbolic_mode) {
8332                         char u[4], g[4], o[4];
8333
8334                         i = 0;
8335                         if ((mask & S_IRUSR) == 0)
8336                                 u[i++] = 'r';
8337                         if ((mask & S_IWUSR) == 0)
8338                                 u[i++] = 'w';
8339                         if ((mask & S_IXUSR) == 0)
8340                                 u[i++] = 'x';
8341                         u[i] = '\0';
8342
8343                         i = 0;
8344                         if ((mask & S_IRGRP) == 0)
8345                                 g[i++] = 'r';
8346                         if ((mask & S_IWGRP) == 0)
8347                                 g[i++] = 'w';
8348                         if ((mask & S_IXGRP) == 0)
8349                                 g[i++] = 'x';
8350                         g[i] = '\0';
8351
8352                         i = 0;
8353                         if ((mask & S_IROTH) == 0)
8354                                 o[i++] = 'r';
8355                         if ((mask & S_IWOTH) == 0)
8356                                 o[i++] = 'w';
8357                         if ((mask & S_IXOTH) == 0)
8358                                 o[i++] = 'x';
8359                         o[i] = '\0';
8360
8361                         printf("u=%s,g=%s,o=%s\n", u, g, o);
8362                 } else {
8363                         printf("%.4o\n", mask);
8364                 }
8365         } else {
8366                 if (is_digit((unsigned char)*ap)) {
8367                         mask = 0;
8368                         do {
8369                                 if (*ap >= '8' || *ap < '0')
8370                                         error("Illegal number: %s", argv[1]);
8371                                 mask = (mask << 3) + (*ap - '0');
8372                         } while (*++ap != '\0');
8373                         umask(mask);
8374                 } else {
8375                         void *set;
8376
8377                         INTOFF;
8378                         if ((set = setmode(ap)) != 0) {
8379                                 mask = getmode(set, ~mask & 0777);
8380                                 ckfree(set);
8381                         }
8382                         INTON;
8383                         if (!set)
8384                                 error("Illegal mode: %s", ap);
8385
8386                         umask(~mask & 0777);
8387                 }
8388         }
8389         return 0;
8390 }
8391
8392 /*
8393  * ulimit builtin
8394  *
8395  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8396  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8397  * ash by J.T. Conklin.
8398  *
8399  * Public domain.
8400  */
8401
8402 struct limits {
8403         const char *name;
8404         int     cmd;
8405         int     factor; /* multiply by to get rlim_{cur,max} values */
8406         char    option;
8407 };
8408
8409 static const struct limits limits[] = {
8410 #ifdef RLIMIT_CPU
8411         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
8412 #endif
8413 #ifdef RLIMIT_FSIZE
8414         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
8415 #endif
8416 #ifdef RLIMIT_DATA
8417         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
8418 #endif
8419 #ifdef RLIMIT_STACK
8420         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
8421 #endif
8422 #ifdef  RLIMIT_CORE
8423         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
8424 #endif
8425 #ifdef RLIMIT_RSS
8426         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
8427 #endif
8428 #ifdef RLIMIT_MEMLOCK
8429         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
8430 #endif
8431 #ifdef RLIMIT_NPROC
8432         { "process(processes)",         RLIMIT_NPROC,      1, 'p' },
8433 #endif
8434 #ifdef RLIMIT_NOFILE
8435         { "nofiles(descriptors)",       RLIMIT_NOFILE,     1, 'n' },
8436 #endif
8437 #ifdef RLIMIT_VMEM
8438         { "vmemory(kbytes)",            RLIMIT_VMEM,    1024, 'v' },
8439 #endif
8440 #ifdef RLIMIT_SWAP
8441         { "swap(kbytes)",               RLIMIT_SWAP,    1024, 'w' },
8442 #endif
8443         { (char *) 0,                   0,                 0,  '\0' }
8444 };
8445
8446 static int
8447 ulimitcmd(argc, argv)
8448         int argc;
8449         char **argv;
8450 {
8451         int     c;
8452         rlim_t val = 0;
8453         enum { SOFT = 0x1, HARD = 0x2 }
8454                         how = SOFT | HARD;
8455         const struct limits     *l;
8456         int             set, all = 0;
8457         int             optc, what;
8458         struct rlimit   limit;
8459
8460         what = 'f';
8461         while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
8462                 switch (optc) {
8463                 case 'H':
8464                         how = HARD;
8465                         break;
8466                 case 'S':
8467                         how = SOFT;
8468                         break;
8469                 case 'a':
8470                         all = 1;
8471                         break;
8472                 default:
8473                         what = optc;
8474                 }
8475
8476         for (l = limits; l->name && l->option != what; l++)
8477                 ;
8478         if (!l->name)
8479                 error("internal error (%c)", what);
8480
8481         set = *argptr ? 1 : 0;
8482         if (set) {
8483                 char *p = *argptr;
8484
8485                 if (all || argptr[1])
8486                         error("too many arguments");
8487                 if (strcmp(p, "unlimited") == 0)
8488                         val = RLIM_INFINITY;
8489                 else {
8490                         val = (rlim_t) 0;
8491
8492                         while ((c = *p++) >= '0' && c <= '9')
8493                         {
8494                                 val = (val * 10) + (long)(c - '0');
8495                                 if (val < (rlim_t) 0)
8496                                         break;
8497                         }
8498                         if (c)
8499                                 error("bad number");
8500                         val *= l->factor;
8501                 }
8502         }
8503         if (all) {
8504                 for (l = limits; l->name; l++) {
8505                         getrlimit(l->cmd, &limit);
8506                         if (how & SOFT)
8507                                 val = limit.rlim_cur;
8508                         else if (how & HARD)
8509                                 val = limit.rlim_max;
8510
8511                         printf("%-20s ", l->name);
8512                         if (val == RLIM_INFINITY)
8513                                 printf("unlimited\n");
8514                         else
8515                         {
8516                                 val /= l->factor;
8517                                 printf("%lld\n", (long long) val);
8518                         }
8519                 }
8520                 return 0;
8521         }
8522
8523         getrlimit(l->cmd, &limit);
8524         if (set) {
8525                 if (how & HARD)
8526                         limit.rlim_max = val;
8527                 if (how & SOFT)
8528                         limit.rlim_cur = val;
8529                 if (setrlimit(l->cmd, &limit) < 0)
8530                         error("error setting limit (%m)");
8531         } else {
8532                 if (how & SOFT)
8533                         val = limit.rlim_cur;
8534                 else if (how & HARD)
8535                         val = limit.rlim_max;
8536
8537                 if (val == RLIM_INFINITY)
8538                         printf("unlimited\n");
8539                 else
8540                 {
8541                         val /= l->factor;
8542                         printf("%lld\n", (long long) val);
8543                 }
8544         }
8545         return 0;
8546 }
8547 /*
8548  * prefix -- see if pfx is a prefix of string.
8549  */
8550
8551 static int
8552 prefix(char const *pfx, char const *string)
8553 {
8554         while (*pfx) {
8555                 if (*pfx++ != *string++)
8556                         return 0;
8557         }
8558         return 1;
8559 }
8560
8561 /*
8562  * Return true if s is a string of digits, and save munber in intptr
8563  * nagative is bad
8564  */
8565
8566 static int
8567 is_number(const char *p, int *intptr)
8568 {
8569         int ret = 0;
8570
8571         do {
8572                 if (! is_digit(*p))
8573                         return 0;
8574                 ret *= 10;
8575                 ret += digit_val(*p);
8576                 p++;
8577         } while (*p != '\0');
8578
8579         *intptr = ret;
8580         return 1;
8581 }
8582
8583 /*
8584  * Convert a string of digits to an integer, printing an error message on
8585  * failure.
8586  */
8587
8588 static int
8589 number(const char *s)
8590 {
8591         int i;
8592         if (! is_number(s, &i))
8593                 error("Illegal number: %s", s);
8594         return i;
8595 }
8596
8597 /*
8598  * Produce a possibly single quoted string suitable as input to the shell.
8599  * The return string is allocated on the stack.
8600  */
8601
8602 static char *
8603 single_quote(const char *s) {
8604         char *p;
8605
8606         STARTSTACKSTR(p);
8607
8608         do {
8609                 char *q = p;
8610                 size_t len1, len1p, len2, len2p;
8611
8612                 len1 = strcspn(s, "'");
8613                 len2 = strspn(s + len1, "'");
8614
8615                 len1p = len1 ? len1 + 2 : len1;
8616                 switch (len2) {
8617                 case 0:
8618                         len2p = 0;
8619                         break;
8620                 case 1:
8621                         len2p = 2;
8622                         break;
8623                 default:
8624                         len2p = len2 + 2;
8625                 }
8626
8627                 CHECKSTRSPACE(len1p + len2p + 1, p);
8628
8629                 if (len1) {
8630                         *p = '\'';
8631                         q = p + 1 + len1;
8632                         memcpy(p + 1, s, len1);
8633                         *q++ = '\'';
8634                         s += len1;
8635                 }
8636
8637                 switch (len2) {
8638                 case 0:
8639                         break;
8640                 case 1:
8641                         *q++ = '\\';
8642                         *q = '\'';
8643                         s++;
8644                         break;
8645                 default:
8646                         *q = '"';
8647                         q += 1 + len2;
8648                         memcpy(q + 1, s, len2);
8649                         *q = '"';
8650                         s += len2;
8651                 }
8652
8653                 STADJUST(len1p + len2p, p);
8654         } while (*s);
8655
8656         USTPUTC(0, p);
8657
8658         return grabstackstr(p);
8659 }
8660
8661 /*
8662  * Like strdup but works with the ash stack.
8663  */
8664
8665 static char *
8666 sstrdup(const char *p)
8667 {
8668         size_t len = strlen(p) + 1;
8669         return memcpy(stalloc(len), p, len);
8670 }
8671
8672
8673 /*
8674  * Routine for dealing with parsed shell commands.
8675  */
8676
8677
8678 static void sizenodelist (const struct nodelist *);
8679 static struct nodelist *copynodelist (const struct nodelist *);
8680 static char *nodesavestr (const char *);
8681
8682 static void
8683 calcsize(const union node *n)
8684 {
8685       if (n == NULL)
8686             return;
8687       funcblocksize += nodesize[n->type];
8688       switch (n->type) {
8689       case NSEMI:
8690       case NAND:
8691       case NOR:
8692       case NWHILE:
8693       case NUNTIL:
8694             calcsize(n->nbinary.ch2);
8695             calcsize(n->nbinary.ch1);
8696             break;
8697       case NCMD:
8698             calcsize(n->ncmd.redirect);
8699             calcsize(n->ncmd.args);
8700             calcsize(n->ncmd.assign);
8701             break;
8702       case NPIPE:
8703             sizenodelist(n->npipe.cmdlist);
8704             break;
8705       case NREDIR:
8706       case NBACKGND:
8707       case NSUBSHELL:
8708             calcsize(n->nredir.redirect);
8709             calcsize(n->nredir.n);
8710             break;
8711       case NIF:
8712             calcsize(n->nif.elsepart);
8713             calcsize(n->nif.ifpart);
8714             calcsize(n->nif.test);
8715             break;
8716       case NFOR:
8717             funcstringsize += strlen(n->nfor.var) + 1;
8718             calcsize(n->nfor.body);
8719             calcsize(n->nfor.args);
8720             break;
8721       case NCASE:
8722             calcsize(n->ncase.cases);
8723             calcsize(n->ncase.expr);
8724             break;
8725       case NCLIST:
8726             calcsize(n->nclist.body);
8727             calcsize(n->nclist.pattern);
8728             calcsize(n->nclist.next);
8729             break;
8730       case NDEFUN:
8731       case NARG:
8732             sizenodelist(n->narg.backquote);
8733             funcstringsize += strlen(n->narg.text) + 1;
8734             calcsize(n->narg.next);
8735             break;
8736       case NTO:
8737       case NFROM:
8738       case NFROMTO:
8739       case NAPPEND:
8740       case NTOOV:
8741             calcsize(n->nfile.fname);
8742             calcsize(n->nfile.next);
8743             break;
8744       case NTOFD:
8745       case NFROMFD:
8746             calcsize(n->ndup.vname);
8747             calcsize(n->ndup.next);
8748             break;
8749       case NHERE:
8750       case NXHERE:
8751             calcsize(n->nhere.doc);
8752             calcsize(n->nhere.next);
8753             break;
8754       case NNOT:
8755             calcsize(n->nnot.com);
8756             break;
8757       };
8758 }
8759
8760 static void
8761 sizenodelist(const struct nodelist *lp)
8762 {
8763         while (lp) {
8764                 funcblocksize += ALIGN(sizeof(struct nodelist));
8765                 calcsize(lp->n);
8766                 lp = lp->next;
8767         }
8768 }
8769
8770
8771 static union node *
8772 copynode(const union node *n)
8773 {
8774       union node *new;
8775
8776       if (n == NULL)
8777             return NULL;
8778       new = funcblock;
8779       funcblock = (char *) funcblock + nodesize[n->type];
8780       switch (n->type) {
8781       case NSEMI:
8782       case NAND:
8783       case NOR:
8784       case NWHILE:
8785       case NUNTIL:
8786             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8787             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8788             break;
8789       case NCMD:
8790             new->ncmd.redirect = copynode(n->ncmd.redirect);
8791             new->ncmd.args = copynode(n->ncmd.args);
8792             new->ncmd.assign = copynode(n->ncmd.assign);
8793             new->ncmd.backgnd = n->ncmd.backgnd;
8794             break;
8795       case NPIPE:
8796             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8797             new->npipe.backgnd = n->npipe.backgnd;
8798             break;
8799       case NREDIR:
8800       case NBACKGND:
8801       case NSUBSHELL:
8802             new->nredir.redirect = copynode(n->nredir.redirect);
8803             new->nredir.n = copynode(n->nredir.n);
8804             break;
8805       case NIF:
8806             new->nif.elsepart = copynode(n->nif.elsepart);
8807             new->nif.ifpart = copynode(n->nif.ifpart);
8808             new->nif.test = copynode(n->nif.test);
8809             break;
8810       case NFOR:
8811             new->nfor.var = nodesavestr(n->nfor.var);
8812             new->nfor.body = copynode(n->nfor.body);
8813             new->nfor.args = copynode(n->nfor.args);
8814             break;
8815       case NCASE:
8816             new->ncase.cases = copynode(n->ncase.cases);
8817             new->ncase.expr = copynode(n->ncase.expr);
8818             break;
8819       case NCLIST:
8820             new->nclist.body = copynode(n->nclist.body);
8821             new->nclist.pattern = copynode(n->nclist.pattern);
8822             new->nclist.next = copynode(n->nclist.next);
8823             break;
8824       case NDEFUN:
8825       case NARG:
8826             new->narg.backquote = copynodelist(n->narg.backquote);
8827             new->narg.text = nodesavestr(n->narg.text);
8828             new->narg.next = copynode(n->narg.next);
8829             break;
8830       case NTO:
8831       case NFROM:
8832       case NFROMTO:
8833       case NAPPEND:
8834       case NTOOV:
8835             new->nfile.fname = copynode(n->nfile.fname);
8836             new->nfile.fd = n->nfile.fd;
8837             new->nfile.next = copynode(n->nfile.next);
8838             break;
8839       case NTOFD:
8840       case NFROMFD:
8841             new->ndup.vname = copynode(n->ndup.vname);
8842             new->ndup.dupfd = n->ndup.dupfd;
8843             new->ndup.fd = n->ndup.fd;
8844             new->ndup.next = copynode(n->ndup.next);
8845             break;
8846       case NHERE:
8847       case NXHERE:
8848             new->nhere.doc = copynode(n->nhere.doc);
8849             new->nhere.fd = n->nhere.fd;
8850             new->nhere.next = copynode(n->nhere.next);
8851             break;
8852       case NNOT:
8853             new->nnot.com = copynode(n->nnot.com);
8854             break;
8855       };
8856       new->type = n->type;
8857       return new;
8858 }
8859
8860
8861 static struct nodelist *
8862 copynodelist(const struct nodelist *lp)
8863 {
8864         struct nodelist *start;
8865         struct nodelist **lpp;
8866
8867         lpp = &start;
8868         while (lp) {
8869                 *lpp = funcblock;
8870                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8871                 (*lpp)->n = copynode(lp->n);
8872                 lp = lp->next;
8873                 lpp = &(*lpp)->next;
8874         }
8875         *lpp = NULL;
8876         return start;
8877 }
8878
8879
8880 static char *
8881 nodesavestr(const char *s)
8882 {
8883 #ifdef _GNU_SOURCE
8884         char   *rtn = funcstring;
8885
8886         funcstring = stpcpy(funcstring, s) + 1;
8887         return rtn;
8888 #else
8889         const char *p = s;
8890         char *q = funcstring;
8891         char   *rtn = funcstring;
8892
8893         while ((*q++ = *p++) != '\0')
8894                 continue;
8895         funcstring = q;
8896         return rtn;
8897 #endif
8898 }
8899
8900 #ifdef ASH_GETOPTS
8901 static int getopts (char *, char *, char **, int *, int *);
8902 #endif
8903
8904
8905 /*
8906  * Process the shell command line arguments.
8907  */
8908
8909 static void
8910 procargs(argc, argv)
8911         int argc;
8912         char **argv;
8913 {
8914         int i;
8915
8916         argptr = argv;
8917         if (argc > 0)
8918                 argptr++;
8919         for (i = 0; i < NOPTS; i++)
8920                 optent_val(i) = 2;
8921         options(1);
8922         if (*argptr == NULL && minusc == NULL)
8923                 sflag = 1;
8924         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8925                 iflag = 1;
8926         if (mflag == 2)
8927                 mflag = iflag;
8928         for (i = 0; i < NOPTS; i++)
8929                 if (optent_val(i) == 2)
8930                         optent_val(i) = 0;
8931         arg0 = argv[0];
8932         if (sflag == 0 && minusc == NULL) {
8933                 commandname = argv[0];
8934                 arg0 = *argptr++;
8935                 setinputfile(arg0, 0);
8936                 commandname = arg0;
8937         }
8938         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8939         if (argptr && minusc && *argptr)
8940                 arg0 = *argptr++;
8941
8942         shellparam.p = argptr;
8943         shellparam.optind = 1;
8944         shellparam.optoff = -1;
8945         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8946         while (*argptr) {
8947                 shellparam.nparam++;
8948                 argptr++;
8949         }
8950         optschanged();
8951 }
8952
8953
8954
8955 /*
8956  * Process shell options.  The global variable argptr contains a pointer
8957  * to the argument list; we advance it past the options.
8958  */
8959
8960 static inline void
8961 minus_o(const char *name, int val)
8962 {
8963         int i;
8964
8965         if (name == NULL) {
8966                 out1str("Current option settings\n");
8967                 for (i = 0; i < NOPTS; i++)
8968                         printf("%-16s%s\n", optent_name(optlist[i]),
8969                                 optent_val(i) ? "on" : "off");
8970         } else {
8971                 for (i = 0; i < NOPTS; i++)
8972                         if (equal(name, optent_name(optlist[i]))) {
8973                                 setoption(optent_letter(optlist[i]), val);
8974                                 return;
8975                         }
8976                 error("Illegal option -o %s", name);
8977         }
8978 }
8979
8980
8981 static void
8982 options(int cmdline)
8983 {
8984         char *p;
8985         int val;
8986         int c;
8987
8988         if (cmdline)
8989                 minusc = NULL;
8990         while ((p = *argptr) != NULL) {
8991                 argptr++;
8992                 if ((c = *p++) == '-') {
8993                         val = 1;
8994                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8995                                 if (!cmdline) {
8996                                         /* "-" means turn off -x and -v */
8997                                         if (p[0] == '\0')
8998                                                 xflag = vflag = 0;
8999                                         /* "--" means reset params */
9000                                         else if (*argptr == NULL)
9001                                                 setparam(argptr);
9002                                 }
9003                                 break;    /* "-" or  "--" terminates options */
9004                         }
9005                 } else if (c == '+') {
9006                         val = 0;
9007                 } else {
9008                         argptr--;
9009                         break;
9010                 }
9011                 while ((c = *p++) != '\0') {
9012                         if (c == 'c' && cmdline) {
9013                                 char *q;
9014 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
9015                                 if (*p == '\0')
9016 #endif
9017                                         q = *argptr++;
9018                                 if (q == NULL || minusc != NULL)
9019                                         error("Bad -c option");
9020                                 minusc = q;
9021 #ifdef NOHACK
9022                                 break;
9023 #endif
9024                         } else if (c == 'o') {
9025                                 minus_o(*argptr, val);
9026                                 if (*argptr)
9027                                         argptr++;
9028                         } else {
9029                                 setoption(c, val);
9030                         }
9031                 }
9032         }
9033 }
9034
9035
9036 static void
9037 setoption(int flag, int val)
9038 {
9039         int i;
9040
9041         for (i = 0; i < NOPTS; i++)
9042                 if (optent_letter(optlist[i]) == flag) {
9043                         optent_val(i) = val;
9044                         if (val) {
9045                                 /* #%$ hack for ksh semantics */
9046                                 if (flag == 'V')
9047                                         Eflag = 0;
9048                                 else if (flag == 'E')
9049                                         Vflag = 0;
9050                         }
9051                         return;
9052                 }
9053         error("Illegal option -%c", flag);
9054         /* NOTREACHED */
9055 }
9056
9057
9058
9059 /*
9060  * Set the shell parameters.
9061  */
9062
9063 static void
9064 setparam(char **argv)
9065 {
9066         char **newparam;
9067         char **ap;
9068         int nparam;
9069
9070         for (nparam = 0 ; argv[nparam] ; nparam++);
9071         ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9072         while (*argv) {
9073                 *ap++ = savestr(*argv++);
9074         }
9075         *ap = NULL;
9076         freeparam(&shellparam);
9077         shellparam.malloc = 1;
9078         shellparam.nparam = nparam;
9079         shellparam.p = newparam;
9080         shellparam.optind = 1;
9081         shellparam.optoff = -1;
9082 }
9083
9084
9085 /*
9086  * Free the list of positional parameters.
9087  */
9088
9089 static void
9090 freeparam(volatile struct shparam *param)
9091 {
9092         char **ap;
9093
9094         if (param->malloc) {
9095                 for (ap = param->p ; *ap ; ap++)
9096                         ckfree(*ap);
9097                 ckfree(param->p);
9098         }
9099 }
9100
9101
9102
9103 /*
9104  * The shift builtin command.
9105  */
9106
9107 static int
9108 shiftcmd(argc, argv)
9109         int argc;
9110         char **argv;
9111 {
9112         int n;
9113         char **ap1, **ap2;
9114
9115         n = 1;
9116         if (argc > 1)
9117                 n = number(argv[1]);
9118         if (n > shellparam.nparam)
9119                 error("can't shift that many");
9120         INTOFF;
9121         shellparam.nparam -= n;
9122         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9123                 if (shellparam.malloc)
9124                         ckfree(*ap1);
9125         }
9126         ap2 = shellparam.p;
9127         while ((*ap2++ = *ap1++) != NULL);
9128         shellparam.optind = 1;
9129         shellparam.optoff = -1;
9130         INTON;
9131         return 0;
9132 }
9133
9134
9135
9136 /*
9137  * The set command builtin.
9138  */
9139
9140 static int
9141 setcmd(argc, argv)
9142         int argc;
9143         char **argv;
9144 {
9145         if (argc == 1)
9146                 return showvarscmd(argc, argv);
9147         INTOFF;
9148         options(0);
9149         optschanged();
9150         if (*argptr != NULL) {
9151                 setparam(argptr);
9152         }
9153         INTON;
9154         return 0;
9155 }
9156
9157
9158 static void
9159 getoptsreset(const char *value)
9160 {
9161         shellparam.optind = number(value);
9162         shellparam.optoff = -1;
9163 }
9164
9165 #ifdef BB_LOCALE_SUPPORT
9166 static void change_lc_all(const char *value)
9167 {
9168         if(value != 0 && *value != 0)
9169                 setlocale(LC_ALL, value);
9170 }
9171
9172 static void change_lc_ctype(const char *value)
9173 {
9174         if(value != 0 && *value != 0)
9175                 setlocale(LC_CTYPE, value);
9176 }
9177
9178 #endif
9179
9180 #ifdef ASH_GETOPTS
9181 /*
9182  * The getopts builtin.  Shellparam.optnext points to the next argument
9183  * to be processed.  Shellparam.optptr points to the next character to
9184  * be processed in the current argument.  If shellparam.optnext is NULL,
9185  * then it's the first time getopts has been called.
9186  */
9187
9188 static int
9189 getoptscmd(argc, argv)
9190         int argc;
9191         char **argv;
9192 {
9193         char **optbase;
9194
9195         if (argc < 3)
9196                 error("Usage: getopts optstring var [arg]");
9197         else if (argc == 3) {
9198                 optbase = shellparam.p;
9199                 if (shellparam.optind > shellparam.nparam + 1) {
9200                         shellparam.optind = 1;
9201                         shellparam.optoff = -1;
9202                 }
9203         }
9204         else {
9205                 optbase = &argv[3];
9206                 if (shellparam.optind > argc - 2) {
9207                         shellparam.optind = 1;
9208                         shellparam.optoff = -1;
9209                 }
9210         }
9211
9212         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9213                        &shellparam.optoff);
9214 }
9215
9216 /*
9217  * Safe version of setvar, returns 1 on success 0 on failure.
9218  */
9219
9220 static int
9221 setvarsafe(name, val, flags)
9222         const char *name, *val;
9223         int flags;
9224 {
9225         struct jmploc jmploc;
9226         struct jmploc *volatile savehandler = handler;
9227         int err = 0;
9228 #ifdef __GNUC__
9229         (void) &err;
9230 #endif
9231
9232         if (setjmp(jmploc.loc))
9233                 err = 1;
9234         else {
9235                 handler = &jmploc;
9236                 setvar(name, val, flags);
9237         }
9238         handler = savehandler;
9239         return err;
9240 }
9241
9242 static int
9243 getopts(optstr, optvar, optfirst, myoptind, optoff)
9244         char *optstr;
9245         char *optvar;
9246         char **optfirst;
9247         int *myoptind;
9248         int *optoff;
9249 {
9250         char *p, *q;
9251         char c = '?';
9252         int done = 0;
9253         int err = 0;
9254         char s[10];
9255         char **optnext = optfirst + *myoptind - 1;
9256
9257         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9258             strlen(*(optnext - 1)) < *optoff)
9259                 p = NULL;
9260         else
9261                 p = *(optnext - 1) + *optoff;
9262         if (p == NULL || *p == '\0') {
9263                 /* Current word is done, advance */
9264                 if (optnext == NULL)
9265                         return 1;
9266                 p = *optnext;
9267                 if (p == NULL || *p != '-' || *++p == '\0') {
9268 atend:
9269                         *myoptind = optnext - optfirst + 1;
9270                         p = NULL;
9271                         done = 1;
9272                         goto out;
9273                 }
9274                 optnext++;
9275                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9276                         goto atend;
9277         }
9278
9279         c = *p++;
9280         for (q = optstr; *q != c; ) {
9281                 if (*q == '\0') {
9282                         if (optstr[0] == ':') {
9283                                 s[0] = c;
9284                                 s[1] = '\0';
9285                                 err |= setvarsafe("OPTARG", s, 0);
9286                         }
9287                         else {
9288                                 out2fmt("Illegal option -%c\n", c);
9289                                 (void) unsetvar("OPTARG");
9290                         }
9291                         c = '?';
9292                         goto bad;
9293                 }
9294                 if (*++q == ':')
9295                         q++;
9296         }
9297
9298         if (*++q == ':') {
9299                 if (*p == '\0' && (p = *optnext) == NULL) {
9300                         if (optstr[0] == ':') {
9301                                 s[0] = c;
9302                                 s[1] = '\0';
9303                                 err |= setvarsafe("OPTARG", s, 0);
9304                                 c = ':';
9305                         }
9306                         else {
9307                                 out2fmt("No arg for -%c option\n", c);
9308                                 (void) unsetvar("OPTARG");
9309                                 c = '?';
9310                         }
9311                         goto bad;
9312                 }
9313
9314                 if (p == *optnext)
9315                         optnext++;
9316                 setvarsafe("OPTARG", p, 0);
9317                 p = NULL;
9318         }
9319         else
9320                 setvarsafe("OPTARG", "", 0);
9321         *myoptind = optnext - optfirst + 1;
9322         goto out;
9323
9324 bad:
9325         *myoptind = 1;
9326         p = NULL;
9327 out:
9328         *optoff = p ? p - *(optnext - 1) : -1;
9329         snprintf(s, sizeof(s), "%d", *myoptind);
9330         err |= setvarsafe("OPTIND", s, VNOFUNC);
9331         s[0] = c;
9332         s[1] = '\0';
9333         err |= setvarsafe(optvar, s, 0);
9334         if (err) {
9335                 *myoptind = 1;
9336                 *optoff = -1;
9337                 exraise(EXERROR);
9338         }
9339         return done;
9340 }
9341 #endif
9342
9343 /*
9344  * XXX - should get rid of.  have all builtins use getopt(3).  the
9345  * library getopt must have the BSD extension static variable "optreset"
9346  * otherwise it can't be used within the shell safely.
9347  *
9348  * Standard option processing (a la getopt) for builtin routines.  The
9349  * only argument that is passed to nextopt is the option string; the
9350  * other arguments are unnecessary.  It return the character, or '\0' on
9351  * end of input.
9352  */
9353
9354 static int
9355 nextopt(const char *optstring)
9356 {
9357         char *p;
9358         const char *q;
9359         char c;
9360
9361         if ((p = optptr) == NULL || *p == '\0') {
9362                 p = *argptr;
9363                 if (p == NULL || *p != '-' || *++p == '\0')
9364                         return '\0';
9365                 argptr++;
9366                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9367                         return '\0';
9368         }
9369         c = *p++;
9370         for (q = optstring ; *q != c ; ) {
9371                 if (*q == '\0')
9372                         error("Illegal option -%c", c);
9373                 if (*++q == ':')
9374                         q++;
9375         }
9376         if (*++q == ':') {
9377                 if (*p == '\0' && (p = *argptr++) == NULL)
9378                         error("No arg for -%c option", c);
9379                 optionarg = p;
9380                 p = NULL;
9381         }
9382         optptr = p;
9383         return c;
9384 }
9385
9386 static void
9387 flushall() {
9388         INTOFF;
9389         fflush(stdout);
9390         INTON;
9391 }
9392
9393
9394 static void
9395 out2fmt(const char *fmt, ...)
9396 {
9397         va_list ap;
9398         va_start(ap, fmt);
9399         vfprintf(stderr, fmt, ap);
9400         va_end(ap);
9401 }
9402
9403 /*
9404  * Version of write which resumes after a signal is caught.
9405  */
9406
9407 static int
9408 xwrite(int fd, const char *buf, int nbytes)
9409 {
9410         int ntry;
9411         int i;
9412         int n;
9413
9414         n = nbytes;
9415         ntry = 0;
9416         for (;;) {
9417                 i = write(fd, buf, n);
9418                 if (i > 0) {
9419                         if ((n -= i) <= 0)
9420                                 return nbytes;
9421                         buf += i;
9422                         ntry = 0;
9423                 } else if (i == 0) {
9424                         if (++ntry > 10)
9425                                 return nbytes - n;
9426                 } else if (errno != EINTR) {
9427                         return -1;
9428                 }
9429         }
9430 }
9431
9432
9433 /*
9434  * Shell command parser.
9435  */
9436
9437 #define EOFMARKLEN 79
9438
9439
9440
9441 struct heredoc {
9442         struct heredoc *next;   /* next here document in list */
9443         union node *here;               /* redirection node */
9444         char *eofmark;          /* string indicating end of input */
9445         int striptabs;          /* if set, strip leading tabs */
9446 };
9447
9448 static struct heredoc *heredoclist;     /* list of here documents to read */
9449 static int parsebackquote;              /* nonzero if we are inside backquotes */
9450 static int doprompt;                    /* if set, prompt the user */
9451 static int needprompt;                  /* true if interactive and at start of line */
9452 static int lasttoken;                   /* last token read */
9453
9454 static char *wordtext;                  /* text of last word returned by readtoken */
9455
9456 static struct nodelist *backquotelist;
9457 static union node *redirnode;
9458 struct heredoc *heredoc;
9459 static int quoteflag;                   /* set if (part of) last token was quoted */
9460 static int startlinno;                  /* line # where last token started */
9461
9462
9463 static union node *list (int);
9464 static union node *andor (void);
9465 static union node *pipeline (void);
9466 static union node *command (void);
9467 static union node *simplecmd (void);
9468 static void parsefname (void);
9469 static void parseheredoc (void);
9470 static int peektoken (void);
9471 static int readtoken (void);
9472 static int xxreadtoken (void);
9473 static int readtoken1 (int, char const *, char *, int);
9474 static int noexpand (char *);
9475 static void synexpect (int) __attribute__((noreturn));
9476 static void synerror (const char *) __attribute__((noreturn));
9477 static void setprompt (int);
9478
9479
9480 /*
9481  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9482  * valid parse tree indicating a blank line.)
9483  */
9484
9485 static union node *
9486 parsecmd(int interact)
9487 {
9488         int t;
9489
9490         tokpushback = 0;
9491         doprompt = interact;
9492         if (doprompt)
9493                 setprompt(1);
9494         else
9495                 setprompt(0);
9496         needprompt = 0;
9497         t = readtoken();
9498         if (t == TEOF)
9499                 return NEOF;
9500         if (t == TNL)
9501                 return NULL;
9502         tokpushback++;
9503         return list(1);
9504 }
9505
9506
9507 static union node *
9508 list(nlflag)
9509         int nlflag;
9510 {
9511         union node *n1, *n2, *n3;
9512         int tok;
9513
9514         checkkwd = 2;
9515         if (nlflag == 0 && tokendlist[peektoken()])
9516                 return NULL;
9517         n1 = NULL;
9518         for (;;) {
9519                 n2 = andor();
9520                 tok = readtoken();
9521                 if (tok == TBACKGND) {
9522                         if (n2->type == NCMD || n2->type == NPIPE) {
9523                                 n2->ncmd.backgnd = 1;
9524                         } else if (n2->type == NREDIR) {
9525                                 n2->type = NBACKGND;
9526                         } else {
9527                                 n3 = (union node *)stalloc(sizeof (struct nredir));
9528                                 n3->type = NBACKGND;
9529                                 n3->nredir.n = n2;
9530                                 n3->nredir.redirect = NULL;
9531                                 n2 = n3;
9532                         }
9533                 }
9534                 if (n1 == NULL) {
9535                         n1 = n2;
9536                 }
9537                 else {
9538                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9539                         n3->type = NSEMI;
9540                         n3->nbinary.ch1 = n1;
9541                         n3->nbinary.ch2 = n2;
9542                         n1 = n3;
9543                 }
9544                 switch (tok) {
9545                 case TBACKGND:
9546                 case TSEMI:
9547                         tok = readtoken();
9548                         /* fall through */
9549                 case TNL:
9550                         if (tok == TNL) {
9551                                 parseheredoc();
9552                                 if (nlflag)
9553                                         return n1;
9554                         } else {
9555                                 tokpushback++;
9556                         }
9557                         checkkwd = 2;
9558                         if (tokendlist[peektoken()])
9559                                 return n1;
9560                         break;
9561                 case TEOF:
9562                         if (heredoclist)
9563                                 parseheredoc();
9564                         else
9565                                 pungetc();              /* push back EOF on input */
9566                         return n1;
9567                 default:
9568                         if (nlflag)
9569                                 synexpect(-1);
9570                         tokpushback++;
9571                         return n1;
9572                 }
9573         }
9574 }
9575
9576
9577
9578 static union node *
9579 andor() {
9580         union node *n1, *n2, *n3;
9581         int t;
9582
9583         checkkwd = 1;
9584         n1 = pipeline();
9585         for (;;) {
9586                 if ((t = readtoken()) == TAND) {
9587                         t = NAND;
9588                 } else if (t == TOR) {
9589                         t = NOR;
9590                 } else {
9591                         tokpushback++;
9592                         return n1;
9593                 }
9594                 checkkwd = 2;
9595                 n2 = pipeline();
9596                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9597                 n3->type = t;
9598                 n3->nbinary.ch1 = n1;
9599                 n3->nbinary.ch2 = n2;
9600                 n1 = n3;
9601         }
9602 }
9603
9604
9605
9606 static union node *
9607 pipeline() {
9608         union node *n1, *n2, *pipenode;
9609         struct nodelist *lp, *prev;
9610         int negate;
9611
9612         negate = 0;
9613         TRACE(("pipeline: entered\n"));
9614         if (readtoken() == TNOT) {
9615                 negate = !negate;
9616                 checkkwd = 1;
9617         } else
9618                 tokpushback++;
9619         n1 = command();
9620         if (readtoken() == TPIPE) {
9621                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9622                 pipenode->type = NPIPE;
9623                 pipenode->npipe.backgnd = 0;
9624                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9625                 pipenode->npipe.cmdlist = lp;
9626                 lp->n = n1;
9627                 do {
9628                         prev = lp;
9629                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9630                         checkkwd = 2;
9631                         lp->n = command();
9632                         prev->next = lp;
9633                 } while (readtoken() == TPIPE);
9634                 lp->next = NULL;
9635                 n1 = pipenode;
9636         }
9637         tokpushback++;
9638         if (negate) {
9639                 n2 = (union node *)stalloc(sizeof (struct nnot));
9640                 n2->type = NNOT;
9641                 n2->nnot.com = n1;
9642                 return n2;
9643         } else
9644                 return n1;
9645 }
9646
9647
9648
9649 static union node *
9650 command() {
9651         union node *n1, *n2;
9652         union node *ap, **app;
9653         union node *cp, **cpp;
9654         union node *redir, **rpp;
9655         int t;
9656
9657         redir = NULL;
9658         n1 = NULL;
9659         rpp = &redir;
9660
9661         switch (readtoken()) {
9662         case TIF:
9663                 n1 = (union node *)stalloc(sizeof (struct nif));
9664                 n1->type = NIF;
9665                 n1->nif.test = list(0);
9666                 if (readtoken() != TTHEN)
9667                         synexpect(TTHEN);
9668                 n1->nif.ifpart = list(0);
9669                 n2 = n1;
9670                 while (readtoken() == TELIF) {
9671                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9672                         n2 = n2->nif.elsepart;
9673                         n2->type = NIF;
9674                         n2->nif.test = list(0);
9675                         if (readtoken() != TTHEN)
9676                                 synexpect(TTHEN);
9677                         n2->nif.ifpart = list(0);
9678                 }
9679                 if (lasttoken == TELSE)
9680                         n2->nif.elsepart = list(0);
9681                 else {
9682                         n2->nif.elsepart = NULL;
9683                         tokpushback++;
9684                 }
9685                 if (readtoken() != TFI)
9686                         synexpect(TFI);
9687                 checkkwd = 1;
9688                 break;
9689         case TWHILE:
9690         case TUNTIL: {
9691                 int got;
9692                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9693                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9694                 n1->nbinary.ch1 = list(0);
9695                 if ((got=readtoken()) != TDO) {
9696 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
9697                         synexpect(TDO);
9698                 }
9699                 n1->nbinary.ch2 = list(0);
9700                 if (readtoken() != TDONE)
9701                         synexpect(TDONE);
9702                 checkkwd = 1;
9703                 break;
9704         }
9705         case TFOR:
9706                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9707                         synerror("Bad for loop variable");
9708                 n1 = (union node *)stalloc(sizeof (struct nfor));
9709                 n1->type = NFOR;
9710                 n1->nfor.var = wordtext;
9711                 checkkwd = 1;
9712                 if (readtoken() == TIN) {
9713                         app = &ap;
9714                         while (readtoken() == TWORD) {
9715                                 n2 = (union node *)stalloc(sizeof (struct narg));
9716                                 n2->type = NARG;
9717                                 n2->narg.text = wordtext;
9718                                 n2->narg.backquote = backquotelist;
9719                                 *app = n2;
9720                                 app = &n2->narg.next;
9721                         }
9722                         *app = NULL;
9723                         n1->nfor.args = ap;
9724                         if (lasttoken != TNL && lasttoken != TSEMI)
9725                                 synexpect(-1);
9726                 } else {
9727                         static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9728                                                                    '@', '=', '\0'};
9729                         n2 = (union node *)stalloc(sizeof (struct narg));
9730                         n2->type = NARG;
9731                         n2->narg.text = argvars;
9732                         n2->narg.backquote = NULL;
9733                         n2->narg.next = NULL;
9734                         n1->nfor.args = n2;
9735                         /*
9736                          * Newline or semicolon here is optional (but note
9737                          * that the original Bourne shell only allowed NL).
9738                          */
9739                         if (lasttoken != TNL && lasttoken != TSEMI)
9740                                 tokpushback++;
9741                 }
9742                 checkkwd = 2;
9743                 if (readtoken() != TDO)
9744                         synexpect(TDO);
9745                 n1->nfor.body = list(0);
9746                 if (readtoken() != TDONE)
9747                         synexpect(TDONE);
9748                 checkkwd = 1;
9749                 break;
9750         case TCASE:
9751                 n1 = (union node *)stalloc(sizeof (struct ncase));
9752                 n1->type = NCASE;
9753                 if (readtoken() != TWORD)
9754                         synexpect(TWORD);
9755                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9756                 n2->type = NARG;
9757                 n2->narg.text = wordtext;
9758                 n2->narg.backquote = backquotelist;
9759                 n2->narg.next = NULL;
9760                 do {
9761                         checkkwd = 1;
9762                 } while (readtoken() == TNL);
9763                 if (lasttoken != TIN)
9764                         synerror("expecting \"in\"");
9765                 cpp = &n1->ncase.cases;
9766                 checkkwd = 2, readtoken();
9767                 do {
9768                         if (lasttoken == TLP)
9769                                 readtoken();
9770                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9771                         cp->type = NCLIST;
9772                         app = &cp->nclist.pattern;
9773                         for (;;) {
9774                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9775                                 ap->type = NARG;
9776                                 ap->narg.text = wordtext;
9777                                 ap->narg.backquote = backquotelist;
9778                                 if (checkkwd = 2, readtoken() != TPIPE)
9779                                         break;
9780                                 app = &ap->narg.next;
9781                                 readtoken();
9782                         }
9783                         ap->narg.next = NULL;
9784                         if (lasttoken != TRP)
9785                                 synexpect(TRP);
9786                         cp->nclist.body = list(0);
9787
9788                         checkkwd = 2;
9789                         if ((t = readtoken()) != TESAC) {
9790                                 if (t != TENDCASE)
9791                                         synexpect(TENDCASE);
9792                                 else
9793                                         checkkwd = 2, readtoken();
9794                         }
9795                         cpp = &cp->nclist.next;
9796                 } while(lasttoken != TESAC);
9797                 *cpp = NULL;
9798                 checkkwd = 1;
9799                 break;
9800         case TLP:
9801                 n1 = (union node *)stalloc(sizeof (struct nredir));
9802                 n1->type = NSUBSHELL;
9803                 n1->nredir.n = list(0);
9804                 n1->nredir.redirect = NULL;
9805                 if (readtoken() != TRP)
9806                         synexpect(TRP);
9807                 checkkwd = 1;
9808                 break;
9809         case TBEGIN:
9810                 n1 = list(0);
9811                 if (readtoken() != TEND)
9812                         synexpect(TEND);
9813                 checkkwd = 1;
9814                 break;
9815         /* Handle an empty command like other simple commands.  */
9816         case TSEMI:
9817         case TAND:
9818         case TOR:
9819         case TNL:
9820         case TEOF:
9821         case TRP:
9822         case TBACKGND:
9823                 /*
9824                  * An empty command before a ; doesn't make much sense, and
9825                  * should certainly be disallowed in the case of `if ;'.
9826                  */
9827                 if (!redir)
9828                         synexpect(-1);
9829         case TWORD:
9830         case TREDIR:
9831                 tokpushback++;
9832                 n1 = simplecmd();
9833                 return n1;
9834         default:
9835                 synexpect(-1);
9836                 /* NOTREACHED */
9837         }
9838
9839         /* Now check for redirection which may follow command */
9840         while (readtoken() == TREDIR) {
9841                 *rpp = n2 = redirnode;
9842                 rpp = &n2->nfile.next;
9843                 parsefname();
9844         }
9845         tokpushback++;
9846         *rpp = NULL;
9847         if (redir) {
9848                 if (n1->type != NSUBSHELL) {
9849                         n2 = (union node *)stalloc(sizeof (struct nredir));
9850                         n2->type = NREDIR;
9851                         n2->nredir.n = n1;
9852                         n1 = n2;
9853                 }
9854                 n1->nredir.redirect = redir;
9855         }
9856
9857         return n1;
9858 }
9859
9860
9861 static union node *
9862 simplecmd() {
9863         union node *args, **app;
9864         union node *n = NULL;
9865         union node *vars, **vpp;
9866         union node **rpp, *redir;
9867
9868         args = NULL;
9869         app = &args;
9870         vars = NULL;
9871         vpp = &vars;
9872         redir = NULL;
9873         rpp = &redir;
9874
9875 #ifdef ASH_ALIAS
9876         checkalias = 2;
9877 #endif
9878         for (;;) {
9879                 switch (readtoken()) {
9880                 case TWORD:
9881                 case TASSIGN:
9882                         n = (union node *)stalloc(sizeof (struct narg));
9883                         n->type = NARG;
9884                         n->narg.text = wordtext;
9885                         n->narg.backquote = backquotelist;
9886                         if (lasttoken == TWORD) {
9887                                 *app = n;
9888                                 app = &n->narg.next;
9889                         } else {
9890                                 *vpp = n;
9891                                 vpp = &n->narg.next;
9892                         }
9893                         break;
9894                 case TREDIR:
9895                         *rpp = n = redirnode;
9896                         rpp = &n->nfile.next;
9897                         parsefname();   /* read name of redirection file */
9898                         break;
9899                 case TLP:
9900                         if (
9901                                 args && app == &args->narg.next &&
9902                                 !vars && !redir
9903                         ) {
9904                                 /* We have a function */
9905                                 if (readtoken() != TRP)
9906                                         synexpect(TRP);
9907                                 n->type = NDEFUN;
9908                                 checkkwd = 2;
9909                                 n->narg.next = command();
9910                                 return n;
9911                         }
9912                         /* fall through */
9913                 default:
9914                         tokpushback++;
9915                         goto out;
9916                 }
9917         }
9918 out:
9919         *app = NULL;
9920         *vpp = NULL;
9921         *rpp = NULL;
9922         n = (union node *)stalloc(sizeof (struct ncmd));
9923         n->type = NCMD;
9924         n->ncmd.backgnd = 0;
9925         n->ncmd.args = args;
9926         n->ncmd.assign = vars;
9927         n->ncmd.redirect = redir;
9928         return n;
9929 }
9930
9931 static union node *
9932 makename(void) {
9933         union node *n;
9934
9935         n = (union node *)stalloc(sizeof (struct narg));
9936         n->type = NARG;
9937         n->narg.next = NULL;
9938         n->narg.text = wordtext;
9939         n->narg.backquote = backquotelist;
9940         return n;
9941 }
9942
9943 static void fixredir(union node *n, const char *text, int err)
9944 {
9945         TRACE(("Fix redir %s %d\n", text, err));
9946         if (!err)
9947                 n->ndup.vname = NULL;
9948
9949         if (is_digit(text[0]) && text[1] == '\0')
9950                 n->ndup.dupfd = digit_val(text[0]);
9951         else if (text[0] == '-' && text[1] == '\0')
9952                 n->ndup.dupfd = -1;
9953         else {
9954
9955                 if (err)
9956                         synerror("Bad fd number");
9957                 else
9958                         n->ndup.vname = makename();
9959         }
9960 }
9961
9962
9963 static void
9964 parsefname(void) {
9965         union node *n = redirnode;
9966
9967         if (readtoken() != TWORD)
9968                 synexpect(-1);
9969         if (n->type == NHERE) {
9970                 struct heredoc *here = heredoc;
9971                 struct heredoc *p;
9972                 int i;
9973
9974                 if (quoteflag == 0)
9975                         n->type = NXHERE;
9976                 TRACE(("Here document %d\n", n->type));
9977                 if (here->striptabs) {
9978                         while (*wordtext == '\t')
9979                                 wordtext++;
9980                 }
9981                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9982                         synerror("Illegal eof marker for << redirection");
9983                 rmescapes(wordtext);
9984                 here->eofmark = wordtext;
9985                 here->next = NULL;
9986                 if (heredoclist == NULL)
9987                         heredoclist = here;
9988                 else {
9989                         for (p = heredoclist ; p->next ; p = p->next);
9990                         p->next = here;
9991                 }
9992         } else if (n->type == NTOFD || n->type == NFROMFD) {
9993                 fixredir(n, wordtext, 0);
9994         } else {
9995                 n->nfile.fname = makename();
9996         }
9997 }
9998
9999
10000 /*
10001  * Input any here documents.
10002  */
10003
10004 static void
10005 parseheredoc() {
10006         struct heredoc *here;
10007         union node *n;
10008
10009         while (heredoclist) {
10010                 here = heredoclist;
10011                 heredoclist = here->next;
10012                 if (needprompt) {
10013                         setprompt(2);
10014                         needprompt = 0;
10015                 }
10016                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10017                                 here->eofmark, here->striptabs);
10018                 n = (union node *)stalloc(sizeof (struct narg));
10019                 n->narg.type = NARG;
10020                 n->narg.next = NULL;
10021                 n->narg.text = wordtext;
10022                 n->narg.backquote = backquotelist;
10023                 here->here->nhere.doc = n;
10024         }
10025 }
10026
10027 static int
10028 peektoken() {
10029         int t;
10030
10031         t = readtoken();
10032         tokpushback++;
10033         return (t);
10034 }
10035
10036 static int
10037 readtoken() {
10038         int t;
10039 #ifdef ASH_ALIAS
10040         int savecheckkwd = checkkwd;
10041         int savecheckalias = checkalias;
10042         struct alias *ap;
10043 #endif
10044
10045 #ifdef DEBUG
10046         int alreadyseen = tokpushback;
10047 #endif
10048
10049 #ifdef ASH_ALIAS
10050 top:
10051 #endif
10052
10053         t = xxreadtoken();
10054
10055 #ifdef ASH_ALIAS
10056         checkalias = savecheckalias;
10057 #endif
10058
10059         if (checkkwd) {
10060                 /*
10061                  * eat newlines
10062                  */
10063                 if (checkkwd == 2) {
10064                         checkkwd = 0;
10065                         while (t == TNL) {
10066                                 parseheredoc();
10067                                 t = xxreadtoken();
10068                         }
10069                 }
10070                 checkkwd = 0;
10071                 /*
10072                  * check for keywords
10073                  */
10074                 if (t == TWORD && !quoteflag)
10075                 {
10076                         const char *const *pp;
10077
10078                         if ((pp = findkwd(wordtext))) {
10079                                 lasttoken = t = pp - parsekwd + KWDOFFSET;
10080                                 TRACE(("keyword %s recognized\n", tokname[t]));
10081                                 goto out;
10082                         }
10083                 }
10084         }
10085
10086 #ifdef ASH_ALIAS
10087         if (t != TWORD) {
10088                 if (t != TREDIR) {
10089                         checkalias = 0;
10090                 }
10091         } else if (checkalias == 2 && isassignment(wordtext)) {
10092                 lasttoken = t = TASSIGN;
10093         } else if (checkalias) {
10094                 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10095                         if (*ap->val) {
10096                                 pushstring(ap->val, strlen(ap->val), ap);
10097                         }
10098                         checkkwd = savecheckkwd;
10099                         goto top;
10100                 }
10101                 checkalias = 0;
10102         }
10103 #endif
10104 out:
10105 #ifdef DEBUG
10106         if (!alreadyseen)
10107             TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10108         else
10109             TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10110 #endif
10111         return (t);
10112 }
10113
10114
10115 /*
10116  * Read the next input token.
10117  * If the token is a word, we set backquotelist to the list of cmds in
10118  *      backquotes.  We set quoteflag to true if any part of the word was
10119  *      quoted.
10120  * If the token is TREDIR, then we set redirnode to a structure containing
10121  *      the redirection.
10122  * In all cases, the variable startlinno is set to the number of the line
10123  *      on which the token starts.
10124  *
10125  * [Change comment:  here documents and internal procedures]
10126  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10127  *  word parsing code into a separate routine.  In this case, readtoken
10128  *  doesn't need to have any internal procedures, but parseword does.
10129  *  We could also make parseoperator in essence the main routine, and
10130  *  have parseword (readtoken1?) handle both words and redirection.]
10131  */
10132
10133 #define RETURN(token)   return lasttoken = token
10134
10135 static int
10136 xxreadtoken() {
10137         int c;
10138
10139         if (tokpushback) {
10140                 tokpushback = 0;
10141                 return lasttoken;
10142         }
10143         if (needprompt) {
10144                 setprompt(2);
10145                 needprompt = 0;
10146         }
10147         startlinno = plinno;
10148         for (;;) {      /* until token or start of word found */
10149                 c = pgetc_macro();
10150                 switch (c) {
10151                 case ' ': case '\t':
10152 #ifdef ASH_ALIAS
10153                 case PEOA:
10154 #endif
10155                         continue;
10156                 case '#':
10157                         while ((c = pgetc()) != '\n' && c != PEOF);
10158                         pungetc();
10159                         continue;
10160                 case '\\':
10161                         if (pgetc() == '\n') {
10162                                 startlinno = ++plinno;
10163                                 if (doprompt)
10164                                         setprompt(2);
10165                                 else
10166                                         setprompt(0);
10167                                 continue;
10168                         }
10169                         pungetc();
10170                         goto breakloop;
10171                 case '\n':
10172                         plinno++;
10173                         needprompt = doprompt;
10174                         RETURN(TNL);
10175                 case PEOF:
10176                         RETURN(TEOF);
10177                 case '&':
10178                         if (pgetc() == '&')
10179                                 RETURN(TAND);
10180                         pungetc();
10181                         RETURN(TBACKGND);
10182                 case '|':
10183                         if (pgetc() == '|')
10184                                 RETURN(TOR);
10185                         pungetc();
10186                         RETURN(TPIPE);
10187                 case ';':
10188                         if (pgetc() == ';')
10189                                 RETURN(TENDCASE);
10190                         pungetc();
10191                         RETURN(TSEMI);
10192                 case '(':
10193                         RETURN(TLP);
10194                 case ')':
10195                         RETURN(TRP);
10196                 default:
10197                         goto breakloop;
10198                 }
10199         }
10200 breakloop:
10201         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10202 #undef RETURN
10203 }
10204
10205
10206
10207 /*
10208  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10209  * is not NULL, read a here document.  In the latter case, eofmark is the
10210  * word which marks the end of the document and striptabs is true if
10211  * leading tabs should be stripped from the document.  The argument firstc
10212  * is the first character of the input token or document.
10213  *
10214  * Because C does not have internal subroutines, I have simulated them
10215  * using goto's to implement the subroutine linkage.  The following macros
10216  * will run code that appears at the end of readtoken1.
10217  */
10218
10219 #define CHECKEND()      {goto checkend; checkend_return:;}
10220 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10221 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10222 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10223 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10224 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10225
10226 static int
10227 readtoken1(firstc, syntax, eofmark, striptabs)
10228         int firstc;
10229         char const *syntax;
10230         char *eofmark;
10231         int striptabs;
10232         {
10233         int c = firstc;
10234         char *out;
10235         int len;
10236         char line[EOFMARKLEN + 1];
10237         struct nodelist *bqlist;
10238         int quotef;
10239         int dblquote;
10240         int varnest;    /* levels of variables expansion */
10241         int arinest;    /* levels of arithmetic expansion */
10242         int parenlevel; /* levels of parens in arithmetic */
10243         int dqvarnest;  /* levels of variables expansion within double quotes */
10244         int oldstyle;
10245         char const *prevsyntax; /* syntax before arithmetic */
10246 #if __GNUC__
10247         /* Avoid longjmp clobbering */
10248         (void) &out;
10249         (void) &quotef;
10250         (void) &dblquote;
10251         (void) &varnest;
10252         (void) &arinest;
10253         (void) &parenlevel;
10254         (void) &dqvarnest;
10255         (void) &oldstyle;
10256         (void) &prevsyntax;
10257         (void) &syntax;
10258 #endif
10259
10260         startlinno = plinno;
10261         dblquote = 0;
10262         if (syntax == DQSYNTAX)
10263                 dblquote = 1;
10264         quotef = 0;
10265         bqlist = NULL;
10266         varnest = 0;
10267         arinest = 0;
10268         parenlevel = 0;
10269         dqvarnest = 0;
10270
10271         STARTSTACKSTR(out);
10272         loop: { /* for each line, until end of word */
10273                 CHECKEND();     /* set c to PEOF if at end of here document */
10274                 for (;;) {      /* until end of line or end of word */
10275                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10276                         switch(syntax[c]) {
10277                         case CNL:       /* '\n' */
10278                                 if (syntax == BASESYNTAX)
10279                                         goto endword;   /* exit outer loop */
10280                                 USTPUTC(c, out);
10281                                 plinno++;
10282                                 if (doprompt)
10283                                         setprompt(2);
10284                                 else
10285                                         setprompt(0);
10286                                 c = pgetc();
10287                                 goto loop;              /* continue outer loop */
10288                         case CWORD:
10289                                 USTPUTC(c, out);
10290                                 break;
10291                         case CCTL:
10292                                 if ((eofmark == NULL || dblquote) &&
10293                                     dqvarnest == 0)
10294                                         USTPUTC(CTLESC, out);
10295                                 USTPUTC(c, out);
10296                                 break;
10297                         case CBACK:     /* backslash */
10298                                 c = pgetc2();
10299                                 if (c == PEOF) {
10300                                         USTPUTC('\\', out);
10301                                         pungetc();
10302                                 } else if (c == '\n') {
10303                                         if (doprompt)
10304                                                 setprompt(2);
10305                                         else
10306                                                 setprompt(0);
10307                                 } else {
10308                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10309                                                          && (c != '"' || eofmark != NULL))
10310                                                 USTPUTC('\\', out);
10311                                         if (SQSYNTAX[c] == CCTL)
10312                                                 USTPUTC(CTLESC, out);
10313                                         else if (eofmark == NULL)
10314                                                 USTPUTC(CTLQUOTEMARK, out);
10315                                         USTPUTC(c, out);
10316                                         quotef++;
10317                                 }
10318                                 break;
10319                         case CSQUOTE:
10320                                 if (eofmark == NULL)
10321                                         USTPUTC(CTLQUOTEMARK, out);
10322                                 syntax = SQSYNTAX;
10323                                 break;
10324                         case CDQUOTE:
10325                                 if (eofmark == NULL)
10326                                         USTPUTC(CTLQUOTEMARK, out);
10327                                 syntax = DQSYNTAX;
10328                                 dblquote = 1;
10329                                 break;
10330                         case CENDQUOTE:
10331                                 if (eofmark != NULL && arinest == 0 &&
10332                                     varnest == 0) {
10333                                         USTPUTC(c, out);
10334                                 } else {
10335                                         if (arinest) {
10336                                                 syntax = ARISYNTAX;
10337                                                 dblquote = 0;
10338                                         } else if (eofmark == NULL &&
10339                                                    dqvarnest == 0) {
10340                                                 syntax = BASESYNTAX;
10341                                                 dblquote = 0;
10342                                         }
10343                                         quotef++;
10344                                 }
10345                                 break;
10346                         case CVAR:      /* '$' */
10347                                 PARSESUB();             /* parse substitution */
10348                                 break;
10349                         case CENDVAR:   /* '}' */
10350                                 if (varnest > 0) {
10351                                         varnest--;
10352                                         if (dqvarnest > 0) {
10353                                                 dqvarnest--;
10354                                         }
10355                                         USTPUTC(CTLENDVAR, out);
10356                                 } else {
10357                                         USTPUTC(c, out);
10358                                 }
10359                                 break;
10360 #ifdef ASH_MATH_SUPPORT
10361                         case CLP:       /* '(' in arithmetic */
10362                                 parenlevel++;
10363                                 USTPUTC(c, out);
10364                                 break;
10365                         case CRP:       /* ')' in arithmetic */
10366                                 if (parenlevel > 0) {
10367                                         USTPUTC(c, out);
10368                                         --parenlevel;
10369                                 } else {
10370                                         if (pgetc() == ')') {
10371                                                 if (--arinest == 0) {
10372                                                         USTPUTC(CTLENDARI, out);
10373                                                         syntax = prevsyntax;
10374                                                         if (syntax == DQSYNTAX)
10375                                                                 dblquote = 1;
10376                                                         else
10377                                                                 dblquote = 0;
10378                                                 } else
10379                                                         USTPUTC(')', out);
10380                                         } else {
10381                                                 /*
10382                                                  * unbalanced parens
10383                                                  *  (don't 2nd guess - no error)
10384                                                  */
10385                                                 pungetc();
10386                                                 USTPUTC(')', out);
10387                                         }
10388                                 }
10389                                 break;
10390 #endif
10391                         case CBQUOTE:   /* '`' */
10392                                 PARSEBACKQOLD();
10393                                 break;
10394                         case CENDFILE:
10395                                 goto endword;           /* exit outer loop */
10396                         case CIGN:
10397                                 break;
10398                         default:
10399                                 if (varnest == 0)
10400                                         goto endword;   /* exit outer loop */
10401 #ifdef ASH_ALIAS
10402                                 if (c != PEOA)
10403 #endif
10404                                         USTPUTC(c, out);
10405
10406                         }
10407                         c = pgetc_macro();
10408                 }
10409         }
10410 endword:
10411         if (syntax == ARISYNTAX)
10412                 synerror("Missing '))'");
10413         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10414                 synerror("Unterminated quoted string");
10415         if (varnest != 0) {
10416                 startlinno = plinno;
10417                 synerror("Missing '}'");
10418         }
10419         USTPUTC('\0', out);
10420         len = out - stackblock();
10421         out = stackblock();
10422         if (eofmark == NULL) {
10423                 if ((c == '>' || c == '<')
10424                  && quotef == 0
10425                  && len <= 2
10426                  && (*out == '\0' || is_digit(*out))) {
10427                         PARSEREDIR();
10428                         return lasttoken = TREDIR;
10429                 } else {
10430                         pungetc();
10431                 }
10432         }
10433         quoteflag = quotef;
10434         backquotelist = bqlist;
10435         grabstackblock(len);
10436         wordtext = out;
10437         return lasttoken = TWORD;
10438 /* end of readtoken routine */
10439
10440
10441
10442 /*
10443  * Check to see whether we are at the end of the here document.  When this
10444  * is called, c is set to the first character of the next input line.  If
10445  * we are at the end of the here document, this routine sets the c to PEOF.
10446  */
10447
10448 checkend: {
10449         if (eofmark) {
10450 #ifdef ASH_ALIAS
10451                 if (c == PEOA) {
10452                         c = pgetc2();
10453                 }
10454 #endif
10455                 if (striptabs) {
10456                         while (c == '\t') {
10457                                 c = pgetc2();
10458                         }
10459                 }
10460                 if (c == *eofmark) {
10461                         if (pfgets(line, sizeof line) != NULL) {
10462                                 char *p, *q;
10463
10464                                 p = line;
10465                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10466                                 if (*p == '\n' && *q == '\0') {
10467                                         c = PEOF;
10468                                         plinno++;
10469                                         needprompt = doprompt;
10470                                 } else {
10471                                         pushstring(line, strlen(line), NULL);
10472                                 }
10473                         }
10474                 }
10475         }
10476         goto checkend_return;
10477 }
10478
10479
10480 /*
10481  * Parse a redirection operator.  The variable "out" points to a string
10482  * specifying the fd to be redirected.  The variable "c" contains the
10483  * first character of the redirection operator.
10484  */
10485
10486 parseredir: {
10487         char fd = *out;
10488         union node *np;
10489
10490         np = (union node *)stalloc(sizeof (struct nfile));
10491         if (c == '>') {
10492                 np->nfile.fd = 1;
10493                 c = pgetc();
10494                 if (c == '>')
10495                         np->type = NAPPEND;
10496                 else if (c == '&')
10497                         np->type = NTOFD;
10498                 else if (c == '|')
10499                         np->type = NTOOV;
10500                 else {
10501                         np->type = NTO;
10502                         pungetc();
10503                 }
10504         } else {        /* c == '<' */
10505                 np->nfile.fd = 0;
10506                 switch (c = pgetc()) {
10507                 case '<':
10508                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10509                                 np = (union node *)stalloc(sizeof (struct nhere));
10510                                 np->nfile.fd = 0;
10511                         }
10512                         np->type = NHERE;
10513                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10514                         heredoc->here = np;
10515                         if ((c = pgetc()) == '-') {
10516                                 heredoc->striptabs = 1;
10517                         } else {
10518                                 heredoc->striptabs = 0;
10519                                 pungetc();
10520                         }
10521                         break;
10522
10523                 case '&':
10524                         np->type = NFROMFD;
10525                         break;
10526
10527                 case '>':
10528                         np->type = NFROMTO;
10529                         break;
10530
10531                 default:
10532                         np->type = NFROM;
10533                         pungetc();
10534                         break;
10535                 }
10536         }
10537         if (fd != '\0')
10538                 np->nfile.fd = digit_val(fd);
10539         redirnode = np;
10540         goto parseredir_return;
10541 }
10542
10543
10544 /*
10545  * Parse a substitution.  At this point, we have read the dollar sign
10546  * and nothing else.
10547  */
10548
10549 parsesub: {
10550         int subtype;
10551         int typeloc;
10552         int flags;
10553         char *p;
10554         static const char types[] = "}-+?=";
10555
10556         c = pgetc();
10557         if (
10558                 c <= PEOA  ||
10559                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10560         ) {
10561                 USTPUTC('$', out);
10562                 pungetc();
10563         } else if (c == '(') {  /* $(command) or $((arith)) */
10564                 if (pgetc() == '(') {
10565                         PARSEARITH();
10566                 } else {
10567                         pungetc();
10568                         PARSEBACKQNEW();
10569                 }
10570         } else {
10571                 USTPUTC(CTLVAR, out);
10572                 typeloc = out - stackblock();
10573                 USTPUTC(VSNORMAL, out);
10574                 subtype = VSNORMAL;
10575                 if (c == '{') {
10576                         c = pgetc();
10577                         if (c == '#') {
10578                                 if ((c = pgetc()) == '}')
10579                                         c = '#';
10580                                 else
10581                                         subtype = VSLENGTH;
10582                         }
10583                         else
10584                                 subtype = 0;
10585                 }
10586                 if (c > PEOA && is_name(c)) {
10587                         do {
10588                                 STPUTC(c, out);
10589                                 c = pgetc();
10590                         } while (c > PEOA && is_in_name(c));
10591                 } else if (is_digit(c)) {
10592                         do {
10593                                 USTPUTC(c, out);
10594                                 c = pgetc();
10595                         } while (is_digit(c));
10596                 }
10597                 else if (is_special(c)) {
10598                         USTPUTC(c, out);
10599                         c = pgetc();
10600                 }
10601                 else
10602 badsub:                 synerror("Bad substitution");
10603
10604                 STPUTC('=', out);
10605                 flags = 0;
10606                 if (subtype == 0) {
10607                         switch (c) {
10608                         case ':':
10609                                 flags = VSNUL;
10610                                 c = pgetc();
10611                                 /*FALLTHROUGH*/
10612                         default:
10613                                 p = strchr(types, c);
10614                                 if (p == NULL)
10615                                         goto badsub;
10616                                 subtype = p - types + VSNORMAL;
10617                                 break;
10618                         case '%':
10619                         case '#':
10620                                 {
10621                                         int cc = c;
10622                                         subtype = c == '#' ? VSTRIMLEFT :
10623                                                              VSTRIMRIGHT;
10624                                         c = pgetc();
10625                                         if (c == cc)
10626                                                 subtype++;
10627                                         else
10628                                                 pungetc();
10629                                         break;
10630                                 }
10631                         }
10632                 } else {
10633                         pungetc();
10634                 }
10635                 if (dblquote || arinest)
10636                         flags |= VSQUOTE;
10637                 *(stackblock() + typeloc) = subtype | flags;
10638                 if (subtype != VSNORMAL) {
10639                         varnest++;
10640                         if (dblquote) {
10641                                 dqvarnest++;
10642                         }
10643                 }
10644         }
10645         goto parsesub_return;
10646 }
10647
10648
10649 /*
10650  * Called to parse command substitutions.  Newstyle is set if the command
10651  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10652  * list of commands (passed by reference), and savelen is the number of
10653  * characters on the top of the stack which must be preserved.
10654  */
10655
10656 parsebackq: {
10657         struct nodelist **nlpp;
10658         int savepbq;
10659         union node *n;
10660         char *volatile str;
10661         struct jmploc jmploc;
10662         struct jmploc *volatile savehandler;
10663         int savelen;
10664         int saveprompt;
10665 #ifdef __GNUC__
10666         (void) &saveprompt;
10667 #endif
10668
10669         savepbq = parsebackquote;
10670         if (setjmp(jmploc.loc)) {
10671                 if (str)
10672                         ckfree(str);
10673                 parsebackquote = 0;
10674                 handler = savehandler;
10675                 longjmp(handler->loc, 1);
10676         }
10677         INTOFF;
10678         str = NULL;
10679         savelen = out - stackblock();
10680         if (savelen > 0) {
10681                 str = ckmalloc(savelen);
10682                 memcpy(str, stackblock(), savelen);
10683         }
10684         savehandler = handler;
10685         handler = &jmploc;
10686         INTON;
10687         if (oldstyle) {
10688                 /* We must read until the closing backquote, giving special
10689                    treatment to some slashes, and then push the string and
10690                    reread it as input, interpreting it normally.  */
10691                 char *pout;
10692                 int pc;
10693                 int psavelen;
10694                 char *pstr;
10695
10696
10697                 STARTSTACKSTR(pout);
10698                 for (;;) {
10699                         if (needprompt) {
10700                                 setprompt(2);
10701                                 needprompt = 0;
10702                         }
10703                         switch (pc = pgetc()) {
10704                         case '`':
10705                                 goto done;
10706
10707                         case '\\':
10708                                 if ((pc = pgetc()) == '\n') {
10709                                         plinno++;
10710                                         if (doprompt)
10711                                                 setprompt(2);
10712                                         else
10713                                                 setprompt(0);
10714                                         /*
10715                                          * If eating a newline, avoid putting
10716                                          * the newline into the new character
10717                                          * stream (via the STPUTC after the
10718                                          * switch).
10719                                          */
10720                                         continue;
10721                                 }
10722                                 if (pc != '\\' && pc != '`' && pc != '$'
10723                                     && (!dblquote || pc != '"'))
10724                                         STPUTC('\\', pout);
10725                                 if (pc > PEOA) {
10726                                         break;
10727                                 }
10728                                 /* fall through */
10729
10730                         case PEOF:
10731 #ifdef ASH_ALIAS
10732                         case PEOA:
10733 #endif
10734                                 startlinno = plinno;
10735                                 synerror("EOF in backquote substitution");
10736
10737                         case '\n':
10738                                 plinno++;
10739                                 needprompt = doprompt;
10740                                 break;
10741
10742                         default:
10743                                 break;
10744                         }
10745                         STPUTC(pc, pout);
10746                 }
10747 done:
10748                 STPUTC('\0', pout);
10749                 psavelen = pout - stackblock();
10750                 if (psavelen > 0) {
10751                         pstr = grabstackstr(pout);
10752                         setinputstring(pstr);
10753                 }
10754         }
10755         nlpp = &bqlist;
10756         while (*nlpp)
10757                 nlpp = &(*nlpp)->next;
10758         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10759         (*nlpp)->next = NULL;
10760         parsebackquote = oldstyle;
10761
10762         if (oldstyle) {
10763                 saveprompt = doprompt;
10764                 doprompt = 0;
10765         }
10766
10767         n = list(0);
10768
10769         if (oldstyle)
10770                 doprompt = saveprompt;
10771         else {
10772                 if (readtoken() != TRP)
10773                         synexpect(TRP);
10774         }
10775
10776         (*nlpp)->n = n;
10777         if (oldstyle) {
10778                 /*
10779                  * Start reading from old file again, ignoring any pushed back
10780                  * tokens left from the backquote parsing
10781                  */
10782                 popfile();
10783                 tokpushback = 0;
10784         }
10785         while (stackblocksize() <= savelen)
10786                 growstackblock();
10787         STARTSTACKSTR(out);
10788         if (str) {
10789                 memcpy(out, str, savelen);
10790                 STADJUST(savelen, out);
10791                 INTOFF;
10792                 ckfree(str);
10793                 str = NULL;
10794                 INTON;
10795         }
10796         parsebackquote = savepbq;
10797         handler = savehandler;
10798         if (arinest || dblquote)
10799                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10800         else
10801                 USTPUTC(CTLBACKQ, out);
10802         if (oldstyle)
10803                 goto parsebackq_oldreturn;
10804         else
10805                 goto parsebackq_newreturn;
10806 }
10807
10808 /*
10809  * Parse an arithmetic expansion (indicate start of one and set state)
10810  */
10811 parsearith: {
10812
10813         if (++arinest == 1) {
10814                 prevsyntax = syntax;
10815                 syntax = ARISYNTAX;
10816                 USTPUTC(CTLARI, out);
10817                 if (dblquote)
10818                         USTPUTC('"',out);
10819                 else
10820                         USTPUTC(' ',out);
10821         } else {
10822                 /*
10823                  * we collapse embedded arithmetic expansion to
10824                  * parenthesis, which should be equivalent
10825                  */
10826                 USTPUTC('(', out);
10827         }
10828         goto parsearith_return;
10829 }
10830
10831 } /* end of readtoken */
10832
10833
10834 /*
10835  * Returns true if the text contains nothing to expand (no dollar signs
10836  * or backquotes).
10837  */
10838
10839 static int
10840 noexpand(text)
10841         char *text;
10842         {
10843         char *p;
10844         char c;
10845
10846         p = text;
10847         while ((c = *p++) != '\0') {
10848                 if (c == CTLQUOTEMARK)
10849                         continue;
10850                 if (c == CTLESC)
10851                         p++;
10852                 else if (BASESYNTAX[(int)c] == CCTL)
10853                         return 0;
10854         }
10855         return 1;
10856 }
10857
10858
10859 /*
10860  * Return true if the argument is a legal variable name (a letter or
10861  * underscore followed by zero or more letters, underscores, and digits).
10862  */
10863
10864 static int
10865 goodname(const char *name)
10866 {
10867         const char *p;
10868
10869         p = name;
10870         if (! is_name(*p))
10871                 return 0;
10872         while (*++p) {
10873                 if (! is_in_name(*p))
10874                         return 0;
10875         }
10876         return 1;
10877 }
10878
10879
10880 /*
10881  * Called when an unexpected token is read during the parse.  The argument
10882  * is the token that is expected, or -1 if more than one type of token can
10883  * occur at this point.
10884  */
10885
10886 static void
10887 synexpect(token)
10888         int token;
10889 {
10890         char msg[64];
10891
10892         if (token >= 0) {
10893                 snprintf(msg, 64, "%s unexpected (expecting %s)",
10894                         tokname[lasttoken], tokname[token]);
10895         } else {
10896                 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
10897         }
10898         synerror(msg);
10899         /* NOTREACHED */
10900 }
10901
10902
10903 static void
10904 synerror(const char *msg)
10905 {
10906         if (commandname)
10907                 out2fmt("%s: %d: ", commandname, startlinno);
10908         out2fmt("Syntax error: %s\n", msg);
10909         error((char *)NULL);
10910         /* NOTREACHED */
10911 }
10912
10913
10914 /*
10915  * called by editline -- any expansions to the prompt
10916  *    should be added here.
10917  */
10918 static void
10919 setprompt(int whichprompt)
10920 {
10921     char *prompt;
10922     switch (whichprompt) {
10923         case 1:
10924                 prompt = ps1val();
10925                 break;
10926         case 2:
10927                 prompt = ps2val();
10928                 break;
10929         default:                /* 0 */
10930                 prompt = "";
10931     }
10932     putprompt(prompt);
10933 }
10934
10935
10936 /*
10937  * Code for dealing with input/output redirection.
10938  */
10939
10940 #define EMPTY -2                /* marks an unused slot in redirtab */
10941 #ifndef PIPE_BUF
10942 # define PIPESIZE 4096          /* amount of buffering in a pipe */
10943 #else
10944 # define PIPESIZE PIPE_BUF
10945 #endif
10946
10947
10948 /*
10949  * Open a file in noclobber mode.
10950  * The code was copied from bash.
10951  */
10952 static inline int
10953 noclobberopen(const char *fname)
10954 {
10955         int r, fd;
10956         struct stat finfo, finfo2;
10957
10958         /*
10959          * If the file exists and is a regular file, return an error
10960          * immediately.
10961          */
10962         r = stat(fname, &finfo);
10963         if (r == 0 && S_ISREG(finfo.st_mode)) {
10964                 errno = EEXIST;
10965                 return -1;
10966         }
10967
10968         /*
10969          * If the file was not present (r != 0), make sure we open it
10970          * exclusively so that if it is created before we open it, our open
10971          * will fail.  Make sure that we do not truncate an existing file.
10972          * Note that we don't turn on O_EXCL unless the stat failed -- if the
10973          * file was not a regular file, we leave O_EXCL off.
10974          */
10975         if (r != 0)
10976                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10977         fd = open(fname, O_WRONLY|O_CREAT, 0666);
10978
10979         /* If the open failed, return the file descriptor right away. */
10980         if (fd < 0)
10981                 return fd;
10982
10983         /*
10984          * OK, the open succeeded, but the file may have been changed from a
10985          * non-regular file to a regular file between the stat and the open.
10986          * We are assuming that the O_EXCL open handles the case where FILENAME
10987          * did not exist and is symlinked to an existing file between the stat
10988          * and open.
10989          */
10990
10991         /*
10992          * If we can open it and fstat the file descriptor, and neither check
10993          * revealed that it was a regular file, and the file has not been
10994          * replaced, return the file descriptor.
10995          */
10996          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10997              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10998                 return fd;
10999
11000         /* The file has been replaced.  badness. */
11001         close(fd);
11002         errno = EEXIST;
11003         return -1;
11004 }
11005
11006 /*
11007  * Handle here documents.  Normally we fork off a process to write the
11008  * data to a pipe.  If the document is short, we can stuff the data in
11009  * the pipe without forking.
11010  */
11011
11012 static inline int
11013 openhere(const union node *redir)
11014 {
11015         int pip[2];
11016         int len = 0;
11017
11018         if (pipe(pip) < 0)
11019                 error("Pipe call failed");
11020         if (redir->type == NHERE) {
11021                 len = strlen(redir->nhere.doc->narg.text);
11022                 if (len <= PIPESIZE) {
11023                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11024                         goto out;
11025                 }
11026         }
11027         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11028                 close(pip[0]);
11029                 signal(SIGINT, SIG_IGN);
11030                 signal(SIGQUIT, SIG_IGN);
11031                 signal(SIGHUP, SIG_IGN);
11032 #ifdef SIGTSTP
11033                 signal(SIGTSTP, SIG_IGN);
11034 #endif
11035                 signal(SIGPIPE, SIG_DFL);
11036                 if (redir->type == NHERE)
11037                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11038                 else
11039                         expandhere(redir->nhere.doc, pip[1]);
11040                 _exit(0);
11041         }
11042 out:
11043         close(pip[1]);
11044         return pip[0];
11045 }
11046
11047
11048 static inline int
11049 openredirect(const union node *redir)
11050 {
11051         char *fname;
11052         int f;
11053
11054         switch (redir->nfile.type) {
11055         case NFROM:
11056                 fname = redir->nfile.expfname;
11057                 if ((f = open(fname, O_RDONLY)) < 0)
11058                         goto eopen;
11059                 break;
11060         case NFROMTO:
11061                 fname = redir->nfile.expfname;
11062                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11063                         goto ecreate;
11064                 break;
11065         case NTO:
11066                 /* Take care of noclobber mode. */
11067                 if (Cflag) {
11068                         fname = redir->nfile.expfname;
11069                         if ((f = noclobberopen(fname)) < 0)
11070                                 goto ecreate;
11071                         break;
11072                 }
11073         case NTOOV:
11074                 fname = redir->nfile.expfname;
11075 #ifdef O_CREAT
11076                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11077                         goto ecreate;
11078 #else
11079                 if ((f = creat(fname, 0666)) < 0)
11080                         goto ecreate;
11081 #endif
11082                 break;
11083         case NAPPEND:
11084                 fname = redir->nfile.expfname;
11085 #ifdef O_APPEND
11086                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11087                         goto ecreate;
11088 #else
11089                 if ((f = open(fname, O_WRONLY)) < 0
11090                  && (f = creat(fname, 0666)) < 0)
11091                         goto ecreate;
11092                 lseek(f, (off_t)0, 2);
11093 #endif
11094                 break;
11095         default:
11096 #ifdef DEBUG
11097                 abort();
11098 #endif
11099                 /* Fall through to eliminate warning. */
11100         case NTOFD:
11101         case NFROMFD:
11102                 f = -1;
11103                 break;
11104         case NHERE:
11105         case NXHERE:
11106                 f = openhere(redir);
11107                 break;
11108         }
11109
11110         return f;
11111 ecreate:
11112         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11113 eopen:
11114         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11115 }
11116
11117
11118 /*
11119  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11120  * old file descriptors are stashed away so that the redirection can be
11121  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11122  * standard output, and the standard error if it becomes a duplicate of
11123  * stdout.
11124  */
11125
11126 static void
11127 redirect(union node *redir, int flags)
11128 {
11129         union node *n;
11130         struct redirtab *sv = NULL;
11131         int i;
11132         int fd;
11133         int newfd;
11134         int try;
11135         int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11136
11137         if (flags & REDIR_PUSH) {
11138                 sv = ckmalloc(sizeof (struct redirtab));
11139                 for (i = 0 ; i < 10 ; i++)
11140                         sv->renamed[i] = EMPTY;
11141                 sv->next = redirlist;
11142                 redirlist = sv;
11143         }
11144         for (n = redir ; n ; n = n->nfile.next) {
11145                 fd = n->nfile.fd;
11146                 try = 0;
11147                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11148                     n->ndup.dupfd == fd)
11149                         continue; /* redirect from/to same file descriptor */
11150
11151                 INTOFF;
11152                 newfd = openredirect(n);
11153                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11154                         if (newfd == fd) {
11155                                 try++;
11156                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11157                                 switch (errno) {
11158                                 case EBADF:
11159                                         if (!try) {
11160                                                 dupredirect(n, newfd, fd1dup);
11161                                                 try++;
11162                                                 break;
11163                                         }
11164                                         /* FALLTHROUGH*/
11165                                 default:
11166                                         if (newfd >= 0) {
11167                                                 close(newfd);
11168                                         }
11169                                         INTON;
11170                                         error("%d: %m", fd);
11171                                         /* NOTREACHED */
11172                                 }
11173                         }
11174                         if (!try) {
11175                                 close(fd);
11176                                 if (flags & REDIR_PUSH) {
11177                                         sv->renamed[fd] = i;
11178                                 }
11179                         }
11180                 } else if (fd != newfd) {
11181                         close(fd);
11182                 }
11183                 if (fd == 0)
11184                         fd0_redirected++;
11185                 if (!try)
11186                         dupredirect(n, newfd, fd1dup);
11187                 INTON;
11188         }
11189 }
11190
11191
11192 static void
11193 dupredirect(const union node *redir, int f, int fd1dup)
11194 {
11195         int fd = redir->nfile.fd;
11196
11197         if(fd==1)
11198                 fd1dup = 0;
11199         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11200                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11201                         if (redir->ndup.dupfd!=1 || fd1dup!=1)
11202                                 dup_as_newfd(redir->ndup.dupfd, fd);
11203                 }
11204                 return;
11205         }
11206
11207         if (f != fd) {
11208                 dup_as_newfd(f, fd);
11209                 close(f);
11210         }
11211         return;
11212 }
11213
11214
11215
11216 /*
11217  * Undo the effects of the last redirection.
11218  */
11219
11220 static void
11221 popredir(void)
11222 {
11223         struct redirtab *rp = redirlist;
11224         int i;
11225
11226         INTOFF;
11227         for (i = 0 ; i < 10 ; i++) {
11228                 if (rp->renamed[i] != EMPTY) {
11229                         if (i == 0)
11230                                 fd0_redirected--;
11231                         close(i);
11232                         if (rp->renamed[i] >= 0) {
11233                                 dup_as_newfd(rp->renamed[i], i);
11234                                 close(rp->renamed[i]);
11235                         }
11236                 }
11237         }
11238         redirlist = rp->next;
11239         ckfree(rp);
11240         INTON;
11241 }
11242
11243 /*
11244  * Discard all saved file descriptors.
11245  */
11246
11247 static void
11248 clearredir(void) {
11249         struct redirtab *rp;
11250         int i;
11251
11252         for (rp = redirlist ; rp ; rp = rp->next) {
11253                 for (i = 0 ; i < 10 ; i++) {
11254                         if (rp->renamed[i] >= 0) {
11255                                 close(rp->renamed[i]);
11256                         }
11257                         rp->renamed[i] = EMPTY;
11258                 }
11259         }
11260 }
11261
11262
11263 /*
11264  * Copy a file descriptor to be >= to.  Returns -1
11265  * if the source file descriptor is closed, EMPTY if there are no unused
11266  * file descriptors left.
11267  */
11268
11269 static int
11270 dup_as_newfd(from, to)
11271         int from;
11272         int to;
11273 {
11274         int newfd;
11275
11276         newfd = fcntl(from, F_DUPFD, to);
11277         if (newfd < 0) {
11278                 if (errno == EMFILE)
11279                         return EMPTY;
11280                 else
11281                         error("%d: %m", from);
11282         }
11283         return newfd;
11284 }
11285
11286 /*#ifdef __weak_alias
11287 __weak_alias(getmode,_getmode)
11288 __weak_alias(setmode,_setmode)
11289 #endif*/
11290
11291 #ifndef S_ISTXT
11292 #if defined(__GLIBC__) && __GLIBC__ >= 2
11293 #define S_ISTXT __S_ISVTX
11294 #else
11295 #define S_ISTXT S_ISVTX
11296 #endif
11297 #endif
11298
11299 #define SET_LEN 6               /* initial # of bitcmd struct to malloc */
11300 #define SET_LEN_INCR 4          /* # of bitcmd structs to add as needed */
11301
11302 typedef struct bitcmd {
11303         char    cmd;
11304         char    cmd2;
11305         mode_t  bits;
11306 } BITCMD;
11307
11308 #define CMD2_CLR        0x01
11309 #define CMD2_SET        0x02
11310 #define CMD2_GBITS      0x04
11311 #define CMD2_OBITS      0x08
11312 #define CMD2_UBITS      0x10
11313
11314 static BITCMD   *addcmd (BITCMD *, int, int, int, u_int);
11315 static void      compress_mode (BITCMD *);
11316 #ifdef SETMODE_DEBUG
11317 static void      dumpmode (BITCMD *);
11318 #endif
11319
11320 /*
11321  * Given the old mode and an array of bitcmd structures, apply the operations
11322  * described in the bitcmd structures to the old mode, and return the new mode.
11323  * Note that there is no '=' command; a strict assignment is just a '-' (clear
11324  * bits) followed by a '+' (set bits).
11325  */
11326 static mode_t
11327 getmode(bbox, omode)
11328         const void *bbox;
11329         mode_t omode;
11330 {
11331         const BITCMD *set;
11332         mode_t clrval, newmode, value;
11333
11334         _DIAGASSERT(bbox != NULL);
11335
11336         set = (const BITCMD *)bbox;
11337         newmode = omode;
11338         for (value = 0;; set++)
11339                 switch(set->cmd) {
11340                 /*
11341                  * When copying the user, group or other bits around, we "know"
11342                  * where the bits are in the mode so that we can do shifts to
11343                  * copy them around.  If we don't use shifts, it gets real
11344                  * grundgy with lots of single bit checks and bit sets.
11345                  */
11346                 case 'u':
11347                         value = (newmode & S_IRWXU) >> 6;
11348                         goto common;
11349
11350                 case 'g':
11351                         value = (newmode & S_IRWXG) >> 3;
11352                         goto common;
11353
11354                 case 'o':
11355                         value = newmode & S_IRWXO;
11356 common:                 if (set->cmd2 & CMD2_CLR) {
11357                                 clrval =
11358                                     (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
11359                                 if (set->cmd2 & CMD2_UBITS)
11360                                         newmode &= ~((clrval<<6) & set->bits);
11361                                 if (set->cmd2 & CMD2_GBITS)
11362                                         newmode &= ~((clrval<<3) & set->bits);
11363                                 if (set->cmd2 & CMD2_OBITS)
11364                                         newmode &= ~(clrval & set->bits);
11365                         }
11366                         if (set->cmd2 & CMD2_SET) {
11367                                 if (set->cmd2 & CMD2_UBITS)
11368                                         newmode |= (value<<6) & set->bits;
11369                                 if (set->cmd2 & CMD2_GBITS)
11370                                         newmode |= (value<<3) & set->bits;
11371                                 if (set->cmd2 & CMD2_OBITS)
11372                                         newmode |= value & set->bits;
11373                         }
11374                         break;
11375
11376                 case '+':
11377                         newmode |= set->bits;
11378                         break;
11379
11380                 case '-':
11381                         newmode &= ~set->bits;
11382                         break;
11383
11384                 case 'X':
11385                         if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11386                                 newmode |= set->bits;
11387                         break;
11388
11389                 case '\0':
11390                 default:
11391 #ifdef SETMODE_DEBUG
11392                         (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11393 #endif
11394                         return (newmode);
11395                 }
11396 }
11397
11398 #define ADDCMD(a, b, c, d) do {                                         \
11399         if (set >= endset) {                                            \
11400                 BITCMD *newset;                                         \
11401                 setlen += SET_LEN_INCR;                                 \
11402                 newset = realloc(saveset, sizeof(BITCMD) * setlen);     \
11403                 if (newset == NULL) {                                   \
11404                         free(saveset);                                  \
11405                         return (NULL);                                  \
11406                 }                                                       \
11407                 set = newset + (set - saveset);                         \
11408                 saveset = newset;                                       \
11409                 endset = newset + (setlen - 2);                         \
11410         }                                                               \
11411         set = addcmd(set, (a), (b), (c), (d));                          \
11412 } while (/*CONSTCOND*/0)
11413
11414 #define STANDARD_BITS   (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11415
11416 static void *
11417 setmode(p)
11418         const char *p;
11419 {
11420         int perm, who;
11421         char op, *ep;
11422         BITCMD *set, *saveset, *endset;
11423         sigset_t mysigset, sigoset;
11424         mode_t mask;
11425         int equalopdone = 0;    /* pacify gcc */
11426         int permXbits, setlen;
11427
11428         if (!*p)
11429                 return (NULL);
11430
11431         /*
11432          * Get a copy of the mask for the permissions that are mask relative.
11433          * Flip the bits, we want what's not set.  Since it's possible that
11434          * the caller is opening files inside a signal handler, protect them
11435          * as best we can.
11436          */
11437         sigfillset(&mysigset);
11438         (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11439         (void)umask(mask = umask(0));
11440         mask = ~mask;
11441         (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11442
11443         setlen = SET_LEN + 2;
11444
11445         if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11446                 return (NULL);
11447         saveset = set;
11448         endset = set + (setlen - 2);
11449
11450         /*
11451          * If an absolute number, get it and return; disallow non-octal digits
11452          * or illegal bits.
11453          */
11454         if (is_digit((unsigned char)*p)) {
11455                 perm = (mode_t)strtol(p, &ep, 8);
11456                 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11457                         free(saveset);
11458                         return (NULL);
11459                 }
11460                 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11461                 set->cmd = 0;
11462                 return (saveset);
11463         }
11464
11465         /*
11466          * Build list of structures to set/clear/copy bits as described by
11467          * each clause of the symbolic mode.
11468          */
11469         for (;;) {
11470                 /* First, find out which bits might be modified. */
11471                 for (who = 0;; ++p) {
11472                         switch (*p) {
11473                         case 'a':
11474                                 who |= STANDARD_BITS;
11475                                 break;
11476                         case 'u':
11477                                 who |= S_ISUID|S_IRWXU;
11478                                 break;
11479                         case 'g':
11480                                 who |= S_ISGID|S_IRWXG;
11481                                 break;
11482                         case 'o':
11483                                 who |= S_IRWXO;
11484                                 break;
11485                         default:
11486                                 goto getop;
11487                         }
11488                 }
11489
11490 getop:          if ((op = *p++) != '+' && op != '-' && op != '=') {
11491                         free(saveset);
11492                         return (NULL);
11493                 }
11494                 if (op == '=')
11495                         equalopdone = 0;
11496
11497                 who &= ~S_ISTXT;
11498                 for (perm = 0, permXbits = 0;; ++p) {
11499                         switch (*p) {
11500                         case 'r':
11501                                 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11502                                 break;
11503                         case 's':
11504                                 /*
11505                                  * If specific bits where requested and
11506                                  * only "other" bits ignore set-id.
11507                                  */
11508                                 if (who == 0 || (who & ~S_IRWXO))
11509                                         perm |= S_ISUID|S_ISGID;
11510                                 break;
11511                         case 't':
11512                                 /*
11513                                  * If specific bits where requested and
11514                                  * only "other" bits ignore set-id.
11515                                  */
11516                                 if (who == 0 || (who & ~S_IRWXO)) {
11517                                         who |= S_ISTXT;
11518                                         perm |= S_ISTXT;
11519                                 }
11520                                 break;
11521                         case 'w':
11522                                 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11523                                 break;
11524                         case 'X':
11525                                 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11526                                 break;
11527                         case 'x':
11528                                 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11529                                 break;
11530                         case 'u':
11531                         case 'g':
11532                         case 'o':
11533                                 /*
11534                                  * When ever we hit 'u', 'g', or 'o', we have
11535                                  * to flush out any partial mode that we have,
11536                                  * and then do the copying of the mode bits.
11537                                  */
11538                                 if (perm) {
11539                                         ADDCMD(op, who, perm, mask);
11540                                         perm = 0;
11541                                 }
11542                                 if (op == '=')
11543                                         equalopdone = 1;
11544                                 if (op == '+' && permXbits) {
11545                                         ADDCMD('X', who, permXbits, mask);
11546                                         permXbits = 0;
11547                                 }
11548                                 ADDCMD(*p, who, op, mask);
11549                                 break;
11550
11551                         default:
11552                                 /*
11553                                  * Add any permissions that we haven't already
11554                                  * done.
11555                                  */
11556                                 if (perm || (op == '=' && !equalopdone)) {
11557                                         if (op == '=')
11558                                                 equalopdone = 1;
11559                                         ADDCMD(op, who, perm, mask);
11560                                         perm = 0;
11561                                 }
11562                                 if (permXbits) {
11563                                         ADDCMD('X', who, permXbits, mask);
11564                                         permXbits = 0;
11565                                 }
11566                                 goto apply;
11567                         }
11568                 }
11569
11570 apply:          if (!*p)
11571                         break;
11572                 if (*p != ',')
11573                         goto getop;
11574                 ++p;
11575         }
11576         set->cmd = 0;
11577 #ifdef SETMODE_DEBUG
11578         (void)printf("Before compress_mode()\n");
11579         dumpmode(saveset);
11580 #endif
11581         compress_mode(saveset);
11582 #ifdef SETMODE_DEBUG
11583         (void)printf("After compress_mode()\n");
11584         dumpmode(saveset);
11585 #endif
11586         return (saveset);
11587 }
11588
11589 static BITCMD *
11590 addcmd(set, op, who, oparg, mask)
11591         BITCMD *set;
11592         int oparg, who;
11593         int op;
11594         u_int mask;
11595 {
11596
11597         _DIAGASSERT(set != NULL);
11598
11599         switch (op) {
11600         case '=':
11601                 set->cmd = '-';
11602                 set->bits = who ? who : STANDARD_BITS;
11603                 set++;
11604
11605                 op = '+';
11606                 /* FALLTHROUGH */
11607         case '+':
11608         case '-':
11609         case 'X':
11610                 set->cmd = op;
11611                 set->bits = (who ? who : mask) & oparg;
11612                 break;
11613
11614         case 'u':
11615         case 'g':
11616         case 'o':
11617                 set->cmd = op;
11618                 if (who) {
11619                         set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11620                                     ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11621                                     ((who & S_IROTH) ? CMD2_OBITS : 0);
11622                         set->bits = (mode_t)~0;
11623                 } else {
11624                         set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11625                         set->bits = mask;
11626                 }
11627
11628                 if (oparg == '+')
11629                         set->cmd2 |= CMD2_SET;
11630                 else if (oparg == '-')
11631                         set->cmd2 |= CMD2_CLR;
11632                 else if (oparg == '=')
11633                         set->cmd2 |= CMD2_SET|CMD2_CLR;
11634                 break;
11635         }
11636         return (set + 1);
11637 }
11638
11639 #ifdef SETMODE_DEBUG
11640 static void
11641 dumpmode(set)
11642         BITCMD *set;
11643 {
11644
11645         _DIAGASSERT(set != NULL);
11646
11647         for (; set->cmd; ++set)
11648                 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11649                     set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11650                     set->cmd2 & CMD2_CLR ? " CLR" : "",
11651                     set->cmd2 & CMD2_SET ? " SET" : "",
11652                     set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11653                     set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11654                     set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11655 }
11656 #endif
11657
11658 /*
11659  * Given an array of bitcmd structures, compress by compacting consecutive
11660  * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
11661  * 'g' and 'o' commands continue to be separate.  They could probably be
11662  * compacted, but it's not worth the effort.
11663  */
11664 static void
11665 compress_mode(set)
11666         BITCMD *set;
11667 {
11668         BITCMD *nset;
11669         int setbits, clrbits, Xbits, op;
11670
11671         _DIAGASSERT(set != NULL);
11672
11673         for (nset = set;;) {
11674                 /* Copy over any 'u', 'g' and 'o' commands. */
11675                 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11676                         *set++ = *nset++;
11677                         if (!op)
11678                                 return;
11679                 }
11680
11681                 for (setbits = clrbits = Xbits = 0;; nset++) {
11682                         if ((op = nset->cmd) == '-') {
11683                                 clrbits |= nset->bits;
11684                                 setbits &= ~nset->bits;
11685                                 Xbits &= ~nset->bits;
11686                         } else if (op == '+') {
11687                                 setbits |= nset->bits;
11688                                 clrbits &= ~nset->bits;
11689                                 Xbits &= ~nset->bits;
11690                         } else if (op == 'X')
11691                                 Xbits |= nset->bits & ~setbits;
11692                         else
11693                                 break;
11694                 }
11695                 if (clrbits) {
11696                         set->cmd = '-';
11697                         set->cmd2 = 0;
11698                         set->bits = clrbits;
11699                         set++;
11700                 }
11701                 if (setbits) {
11702                         set->cmd = '+';
11703                         set->cmd2 = 0;
11704                         set->bits = setbits;
11705                         set++;
11706                 }
11707                 if (Xbits) {
11708                         set->cmd = 'X';
11709                         set->cmd2 = 0;
11710                         set->bits = Xbits;
11711                         set++;
11712                 }
11713         }
11714 }
11715 #ifdef DEBUG
11716 static void shtree (union node *, int, char *, FILE*);
11717 static void shcmd (union node *, FILE *);
11718 static void sharg (union node *, FILE *);
11719 static void indent (int, char *, FILE *);
11720 static void trstring (char *);
11721
11722
11723 static void
11724 showtree(n)
11725         union node *n;
11726 {
11727         trputs("showtree called\n");
11728         shtree(n, 1, NULL, stdout);
11729 }
11730
11731
11732 static void
11733 shtree(n, ind, pfx, fp)
11734         union node *n;
11735         int ind;
11736         char *pfx;
11737         FILE *fp;
11738 {
11739         struct nodelist *lp;
11740         const char *s;
11741
11742         if (n == NULL)
11743                 return;
11744
11745         indent(ind, pfx, fp);
11746         switch(n->type) {
11747         case NSEMI:
11748                 s = "; ";
11749                 goto binop;
11750         case NAND:
11751                 s = " && ";
11752                 goto binop;
11753         case NOR:
11754                 s = " || ";
11755 binop:
11756                 shtree(n->nbinary.ch1, ind, NULL, fp);
11757            /*    if (ind < 0) */
11758                         fputs(s, fp);
11759                 shtree(n->nbinary.ch2, ind, NULL, fp);
11760                 break;
11761         case NCMD:
11762                 shcmd(n, fp);
11763                 if (ind >= 0)
11764                         putc('\n', fp);
11765                 break;
11766         case NPIPE:
11767                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11768                         shcmd(lp->n, fp);
11769                         if (lp->next)
11770                                 fputs(" | ", fp);
11771                 }
11772                 if (n->npipe.backgnd)
11773                         fputs(" &", fp);
11774                 if (ind >= 0)
11775                         putc('\n', fp);
11776                 break;
11777         default:
11778                 fprintf(fp, "<node type %d>", n->type);
11779                 if (ind >= 0)
11780                         putc('\n', fp);
11781                 break;
11782         }
11783 }
11784
11785
11786
11787 static void
11788 shcmd(cmd, fp)
11789         union node *cmd;
11790         FILE *fp;
11791 {
11792         union node *np;
11793         int first;
11794         const char *s;
11795         int dftfd;
11796
11797         first = 1;
11798         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11799                 if (! first)
11800                         putchar(' ');
11801                 sharg(np, fp);
11802                 first = 0;
11803         }
11804         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11805                 if (! first)
11806                         putchar(' ');
11807                 switch (np->nfile.type) {
11808                         case NTO:       s = ">";  dftfd = 1; break;
11809                         case NAPPEND:   s = ">>"; dftfd = 1; break;
11810                         case NTOFD:     s = ">&"; dftfd = 1; break;
11811                         case NTOOV:     s = ">|"; dftfd = 1; break;
11812                         case NFROM:     s = "<";  dftfd = 0; break;
11813                         case NFROMFD:   s = "<&"; dftfd = 0; break;
11814                         case NFROMTO:   s = "<>"; dftfd = 0; break;
11815                         default:        s = "*error*"; dftfd = 0; break;
11816                 }
11817                 if (np->nfile.fd != dftfd)
11818                         fprintf(fp, "%d", np->nfile.fd);
11819                 fputs(s, fp);
11820                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11821                         fprintf(fp, "%d", np->ndup.dupfd);
11822                 } else {
11823                         sharg(np->nfile.fname, fp);
11824                 }
11825                 first = 0;
11826         }
11827 }
11828
11829
11830
11831 static void
11832 sharg(arg, fp)
11833         union node *arg;
11834         FILE *fp;
11835         {
11836         char *p;
11837         struct nodelist *bqlist;
11838         int subtype;
11839
11840         if (arg->type != NARG) {
11841                 printf("<node type %d>\n", arg->type);
11842                 fflush(stdout);
11843                 abort();
11844         }
11845         bqlist = arg->narg.backquote;
11846         for (p = arg->narg.text ; *p ; p++) {
11847                 switch (*p) {
11848                 case CTLESC:
11849                         putc(*++p, fp);
11850                         break;
11851                 case CTLVAR:
11852                         putc('$', fp);
11853                         putc('{', fp);
11854                         subtype = *++p;
11855                         if (subtype == VSLENGTH)
11856                                 putc('#', fp);
11857
11858                         while (*p != '=')
11859                                 putc(*p++, fp);
11860
11861                         if (subtype & VSNUL)
11862                                 putc(':', fp);
11863
11864                         switch (subtype & VSTYPE) {
11865                         case VSNORMAL:
11866                                 putc('}', fp);
11867                                 break;
11868                         case VSMINUS:
11869                                 putc('-', fp);
11870                                 break;
11871                         case VSPLUS:
11872                                 putc('+', fp);
11873                                 break;
11874                         case VSQUESTION:
11875                                 putc('?', fp);
11876                                 break;
11877                         case VSASSIGN:
11878                                 putc('=', fp);
11879                                 break;
11880                         case VSTRIMLEFT:
11881                                 putc('#', fp);
11882                                 break;
11883                         case VSTRIMLEFTMAX:
11884                                 putc('#', fp);
11885                                 putc('#', fp);
11886                                 break;
11887                         case VSTRIMRIGHT:
11888                                 putc('%', fp);
11889                                 break;
11890                         case VSTRIMRIGHTMAX:
11891                                 putc('%', fp);
11892                                 putc('%', fp);
11893                                 break;
11894                         case VSLENGTH:
11895                                 break;
11896                         default:
11897                                 printf("<subtype %d>", subtype);
11898                         }
11899                         break;
11900                 case CTLENDVAR:
11901                      putc('}', fp);
11902                      break;
11903                 case CTLBACKQ:
11904                 case CTLBACKQ|CTLQUOTE:
11905                         putc('$', fp);
11906                         putc('(', fp);
11907                         shtree(bqlist->n, -1, NULL, fp);
11908                         putc(')', fp);
11909                         break;
11910                 default:
11911                         putc(*p, fp);
11912                         break;
11913                 }
11914         }
11915 }
11916
11917
11918 static void
11919 indent(amount, pfx, fp)
11920         int amount;
11921         char *pfx;
11922         FILE *fp;
11923 {
11924         int i;
11925
11926         for (i = 0 ; i < amount ; i++) {
11927                 if (pfx && i == amount - 1)
11928                         fputs(pfx, fp);
11929                 putc('\t', fp);
11930         }
11931 }
11932 #endif
11933
11934
11935
11936 /*
11937  * Debugging stuff.
11938  */
11939
11940
11941 #ifdef DEBUG
11942 FILE *tracefile;
11943
11944 #if DEBUG == 2
11945 static int debug = 1;
11946 #else
11947 static int debug = 0;
11948 #endif
11949
11950
11951 static void
11952 trputc(c)
11953         int c;
11954 {
11955         if (tracefile == NULL)
11956                 return;
11957         putc(c, tracefile);
11958         if (c == '\n')
11959                 fflush(tracefile);
11960 }
11961
11962 static void
11963 trace(const char *fmt, ...)
11964 {
11965         va_list va;
11966 #ifdef __STDC__
11967         va_start(va, fmt);
11968 #else
11969         char *fmt;
11970         va_start(va);
11971         fmt = va_arg(va, char *);
11972 #endif
11973         if (tracefile != NULL) {
11974                 (void) vfprintf(tracefile, fmt, va);
11975                 if (strchr(fmt, '\n'))
11976                         (void) fflush(tracefile);
11977         }
11978         va_end(va);
11979 }
11980
11981
11982 static void
11983 trputs(s)
11984         const char *s;
11985 {
11986         if (tracefile == NULL)
11987                 return;
11988         fputs(s, tracefile);
11989         if (strchr(s, '\n'))
11990                 fflush(tracefile);
11991 }
11992
11993
11994 static void
11995 trstring(s)
11996         char *s;
11997 {
11998         char *p;
11999         char c;
12000
12001         if (tracefile == NULL)
12002                 return;
12003         putc('"', tracefile);
12004         for (p = s ; *p ; p++) {
12005                 switch (*p) {
12006                 case '\n':  c = 'n';  goto backslash;
12007                 case '\t':  c = 't';  goto backslash;
12008                 case '\r':  c = 'r';  goto backslash;
12009                 case '"':  c = '"';  goto backslash;
12010                 case '\\':  c = '\\';  goto backslash;
12011                 case CTLESC:  c = 'e';  goto backslash;
12012                 case CTLVAR:  c = 'v';  goto backslash;
12013                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
12014                 case CTLBACKQ:  c = 'q';  goto backslash;
12015                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
12016 backslash:        putc('\\', tracefile);
12017                         putc(c, tracefile);
12018                         break;
12019                 default:
12020                         if (*p >= ' ' && *p <= '~')
12021                                 putc(*p, tracefile);
12022                         else {
12023                                 putc('\\', tracefile);
12024                                 putc(*p >> 6 & 03, tracefile);
12025                                 putc(*p >> 3 & 07, tracefile);
12026                                 putc(*p & 07, tracefile);
12027                         }
12028                         break;
12029                 }
12030         }
12031         putc('"', tracefile);
12032 }
12033
12034
12035 static void
12036 trargs(ap)
12037         char **ap;
12038 {
12039         if (tracefile == NULL)
12040                 return;
12041         while (*ap) {
12042                 trstring(*ap++);
12043                 if (*ap)
12044                         putc(' ', tracefile);
12045                 else
12046                         putc('\n', tracefile);
12047         }
12048         fflush(tracefile);
12049 }
12050
12051
12052 static void
12053 opentrace() {
12054         char s[100];
12055 #ifdef O_APPEND
12056         int flags;
12057 #endif
12058
12059         if (!debug)
12060                 return;
12061 #ifdef not_this_way
12062         {
12063                 char *p;
12064                 if ((p = getenv("HOME")) == NULL) {
12065                         if (geteuid() == 0)
12066                                 p = "/";
12067                         else
12068                                 p = "/tmp";
12069                 }
12070                 strcpy(s, p);
12071                 strcat(s, "/trace");
12072         }
12073 #else
12074         strcpy(s, "./trace");
12075 #endif /* not_this_way */
12076         if ((tracefile = fopen(s, "a")) == NULL) {
12077                 fprintf(stderr, "Can't open %s\n", s);
12078                 return;
12079         }
12080 #ifdef O_APPEND
12081         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
12082                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
12083 #endif
12084         fputs("\nTracing started.\n", tracefile);
12085         fflush(tracefile);
12086 }
12087 #endif /* DEBUG */
12088
12089
12090 /*
12091  * The trap builtin.
12092  */
12093
12094 static int
12095 trapcmd(argc, argv)
12096         int argc;
12097         char **argv;
12098 {
12099         char *action;
12100         char **ap;
12101         int signo;
12102
12103         if (argc <= 1) {
12104                 for (signo = 0 ; signo < NSIG ; signo++) {
12105                         if (trap[signo] != NULL) {
12106                                 char *p;
12107
12108                                 p = single_quote(trap[signo]);
12109                                 printf("trap -- %s %s\n", p,
12110                                         signal_names[signo] + (signo ? 3 : 0)
12111                                 );
12112                                 stunalloc(p);
12113                         }
12114                 }
12115                 return 0;
12116         }
12117         ap = argv + 1;
12118         if (argc == 2)
12119                 action = NULL;
12120         else
12121                 action = *ap++;
12122         while (*ap) {
12123                 if ((signo = decode_signal(*ap, 0)) < 0)
12124                         error("%s: bad trap", *ap);
12125                 INTOFF;
12126                 if (action) {
12127                         if (action[0] == '-' && action[1] == '\0')
12128                                 action = NULL;
12129                         else
12130                                 action = savestr(action);
12131                 }
12132                 if (trap[signo])
12133                         ckfree(trap[signo]);
12134                 trap[signo] = action;
12135                 if (signo != 0)
12136                         setsignal(signo);
12137                 INTON;
12138                 ap++;
12139         }
12140         return 0;
12141 }
12142
12143
12144
12145
12146
12147
12148 /*
12149  * Set the signal handler for the specified signal.  The routine figures
12150  * out what it should be set to.
12151  */
12152
12153 static void
12154 setsignal(int signo)
12155 {
12156         int action;
12157         char *t;
12158         struct sigaction act;
12159
12160         if ((t = trap[signo]) == NULL)
12161                 action = S_DFL;
12162         else if (*t != '\0')
12163                 action = S_CATCH;
12164         else
12165                 action = S_IGN;
12166         if (rootshell && action == S_DFL) {
12167                 switch (signo) {
12168                 case SIGINT:
12169                         if (iflag || minusc || sflag == 0)
12170                                 action = S_CATCH;
12171                         break;
12172                 case SIGQUIT:
12173 #ifdef DEBUG
12174                         {
12175
12176                         if (debug)
12177                                 break;
12178                         }
12179 #endif
12180                         /* FALLTHROUGH */
12181                 case SIGTERM:
12182                         if (iflag)
12183                                 action = S_IGN;
12184                         break;
12185 #ifdef JOBS
12186                 case SIGTSTP:
12187                 case SIGTTOU:
12188                         if (mflag)
12189                                 action = S_IGN;
12190                         break;
12191 #endif
12192                 }
12193         }
12194
12195         t = &sigmode[signo - 1];
12196         if (*t == 0) {
12197                 /*
12198                  * current setting unknown
12199                  */
12200                 if (sigaction(signo, 0, &act) == -1) {
12201                         /*
12202                          * Pretend it worked; maybe we should give a warning
12203                          * here, but other shells don't. We don't alter
12204                          * sigmode, so that we retry every time.
12205                          */
12206                         return;
12207                 }
12208                 if (act.sa_handler == SIG_IGN) {
12209                         if (mflag && (signo == SIGTSTP ||
12210                              signo == SIGTTIN || signo == SIGTTOU)) {
12211                                 *t = S_IGN;     /* don't hard ignore these */
12212                         } else
12213                                 *t = S_HARD_IGN;
12214                 } else {
12215                         *t = S_RESET;   /* force to be set */
12216                 }
12217         }
12218         if (*t == S_HARD_IGN || *t == action)
12219                 return;
12220         switch (action) {
12221         case S_CATCH:
12222                 act.sa_handler = onsig;
12223                 break;
12224         case S_IGN:
12225                 act.sa_handler = SIG_IGN;
12226                 break;
12227         default:
12228                 act.sa_handler = SIG_DFL;
12229         }
12230         *t = action;
12231         act.sa_flags = 0;
12232         sigemptyset(&act.sa_mask);
12233         sigaction(signo, &act, 0);
12234 }
12235
12236 /*
12237  * Ignore a signal.
12238  */
12239
12240 static void
12241 ignoresig(signo)
12242         int signo;
12243 {
12244         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12245                 signal(signo, SIG_IGN);
12246         }
12247         sigmode[signo - 1] = S_HARD_IGN;
12248 }
12249
12250
12251 /*
12252  * Signal handler.
12253  */
12254
12255 static void
12256 onsig(int signo)
12257 {
12258         if (signo == SIGINT && trap[SIGINT] == NULL) {
12259                 onint();
12260                 return;
12261         }
12262         gotsig[signo - 1] = 1;
12263         pendingsigs++;
12264 }
12265
12266
12267 /*
12268  * Called to execute a trap.  Perhaps we should avoid entering new trap
12269  * handlers while we are executing a trap handler.
12270  */
12271
12272 static void
12273 dotrap(void)
12274 {
12275         int i;
12276         int savestatus;
12277
12278         for (;;) {
12279                 for (i = 1 ; ; i++) {
12280                         if (gotsig[i - 1])
12281                                 break;
12282                         if (i >= NSIG - 1)
12283                                 goto done;
12284                 }
12285                 gotsig[i - 1] = 0;
12286                 savestatus=exitstatus;
12287                 evalstring(trap[i], 0);
12288                 exitstatus=savestatus;
12289         }
12290 done:
12291         pendingsigs = 0;
12292 }
12293
12294 /*
12295  * Called to exit the shell.
12296  */
12297
12298 static void
12299 exitshell(int status)
12300 {
12301         struct jmploc loc1, loc2;
12302         char *p;
12303
12304         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12305         if (setjmp(loc1.loc)) {
12306                 goto l1;
12307         }
12308         if (setjmp(loc2.loc)) {
12309                 goto l2;
12310         }
12311         handler = &loc1;
12312         if ((p = trap[0]) != NULL && *p != '\0') {
12313                 trap[0] = NULL;
12314                 evalstring(p, 0);
12315         }
12316 l1:   handler = &loc2;                  /* probably unnecessary */
12317         flushall();
12318 #ifdef JOBS
12319         setjobctl(0);
12320 #endif
12321 l2:   _exit(status);
12322         /* NOTREACHED */
12323 }
12324
12325 static int decode_signal(const char *string, int minsig)
12326 {
12327         int signo;
12328
12329         if (is_number(string, &signo)) {
12330                 if (signo >= NSIG) {
12331                         return -1;
12332                 }
12333                 return signo;
12334         }
12335
12336         signo = minsig;
12337         if (!signo) {
12338                 goto zero;
12339         }
12340         for (; signo < NSIG; signo++) {
12341                 if (!strcasecmp(string, &(signal_names[signo])[3])) {
12342                         return signo;
12343                 }
12344 zero:
12345                 if (!strcasecmp(string, signal_names[signo])) {
12346                         return signo;
12347                 }
12348         }
12349
12350         return -1;
12351 }
12352 static struct var **hashvar (const char *);
12353 static void showvars (const char *, int, int);
12354 static struct var **findvar (struct var **, const char *);
12355
12356 /*
12357  * Initialize the varable symbol tables and import the environment
12358  */
12359
12360 /*
12361  * This routine initializes the builtin variables.  It is called when the
12362  * shell is initialized and again when a shell procedure is spawned.
12363  */
12364
12365 static void
12366 initvar() {
12367         const struct varinit *ip;
12368         struct var *vp;
12369         struct var **vpp;
12370
12371         for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12372                 if ((vp->flags & VEXPORT) == 0) {
12373                         vpp = hashvar(ip->text);
12374                         vp->next = *vpp;
12375                         *vpp = vp;
12376                         vp->text = strdup(ip->text);
12377                         vp->flags = ip->flags;
12378                         vp->func = ip->func;
12379                 }
12380         }
12381         /*
12382          * PS1 depends on uid
12383          */
12384         if ((vps1.flags & VEXPORT) == 0) {
12385                 vpp = hashvar("PS1=");
12386                 vps1.next = *vpp;
12387                 *vpp = &vps1;
12388                 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12389                 vps1.flags = VSTRFIXED|VTEXTFIXED;
12390         }
12391 }
12392
12393 /*
12394  * Set the value of a variable.  The flags argument is ored with the
12395  * flags of the variable.  If val is NULL, the variable is unset.
12396  */
12397
12398 static void
12399 setvar(name, val, flags)
12400         const char *name, *val;
12401         int flags;
12402 {
12403         const char *p;
12404         int len;
12405         int namelen;
12406         char *nameeq;
12407         int isbad;
12408         int vallen = 0;
12409
12410         isbad = 0;
12411         p = name;
12412         if (! is_name(*p))
12413                 isbad = 1;
12414         p++;
12415         for (;;) {
12416                 if (! is_in_name(*p)) {
12417                         if (*p == '\0' || *p == '=')
12418                                 break;
12419                         isbad = 1;
12420                 }
12421                 p++;
12422         }
12423         namelen = p - name;
12424         if (isbad)
12425                 error("%.*s: bad variable name", namelen, name);
12426         len = namelen + 2;              /* 2 is space for '=' and '\0' */
12427         if (val == NULL) {
12428                 flags |= VUNSET;
12429         } else {
12430                 len += vallen = strlen(val);
12431         }
12432         INTOFF;
12433         nameeq = ckmalloc(len);
12434         memcpy(nameeq, name, namelen);
12435         nameeq[namelen] = '=';
12436         if (val) {
12437                 memcpy(nameeq + namelen + 1, val, vallen + 1);
12438         } else {
12439                 nameeq[namelen + 1] = '\0';
12440         }
12441         setvareq(nameeq, flags);
12442         INTON;
12443 }
12444
12445
12446
12447 /*
12448  * Same as setvar except that the variable and value are passed in
12449  * the first argument as name=value.  Since the first argument will
12450  * be actually stored in the table, it should not be a string that
12451  * will go away.
12452  */
12453
12454 static void
12455 setvareq(s, flags)
12456         char *s;
12457         int flags;
12458 {
12459         struct var *vp, **vpp;
12460
12461         vpp = hashvar(s);
12462         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12463         if ((vp = *findvar(vpp, s))) {
12464                 if (vp->flags & VREADONLY) {
12465                         size_t len = strchr(s, '=') - s;
12466                         error("%.*s: is read only", len, s);
12467                 }
12468                 INTOFF;
12469
12470                 if (vp->func && (flags & VNOFUNC) == 0)
12471                         (*vp->func)(strchr(s, '=') + 1);
12472
12473                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12474                         ckfree(vp->text);
12475
12476                 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12477                 vp->flags |= flags;
12478                 vp->text = s;
12479
12480                 /*
12481                  * We could roll this to a function, to handle it as
12482                  * a regular variable function callback, but why bother?
12483                  */
12484                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12485                         chkmail(1);
12486                 INTON;
12487                 return;
12488         }
12489         /* not found */
12490         vp = ckmalloc(sizeof (*vp));
12491         vp->flags = flags;
12492         vp->text = s;
12493         vp->next = *vpp;
12494         vp->func = NULL;
12495         *vpp = vp;
12496 }
12497
12498
12499
12500 /*
12501  * Process a linked list of variable assignments.
12502  */
12503
12504 static void
12505 listsetvar(mylist)
12506         struct strlist *mylist;
12507         {
12508         struct strlist *lp;
12509
12510         INTOFF;
12511         for (lp = mylist ; lp ; lp = lp->next) {
12512                 setvareq(savestr(lp->text), 0);
12513         }
12514         INTON;
12515 }
12516
12517
12518
12519 /*
12520  * Find the value of a variable.  Returns NULL if not set.
12521  */
12522
12523 static const char *
12524 lookupvar(name)
12525         const char *name;
12526         {
12527         struct var *v;
12528
12529         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12530                 return strchr(v->text, '=') + 1;
12531         }
12532         return NULL;
12533 }
12534
12535
12536
12537 /*
12538  * Search the environment of a builtin command.
12539  */
12540
12541 static const char *
12542 bltinlookup(const char *name)
12543 {
12544         const struct strlist *sp;
12545
12546         for (sp = cmdenviron ; sp ; sp = sp->next) {
12547                 if (varequal(sp->text, name))
12548                         return strchr(sp->text, '=') + 1;
12549         }
12550         return lookupvar(name);
12551 }
12552
12553
12554
12555 /*
12556  * Generate a list of exported variables.  This routine is used to construct
12557  * the third argument to execve when executing a program.
12558  */
12559
12560 static char **
12561 environment() {
12562         int nenv;
12563         struct var **vpp;
12564         struct var *vp;
12565         char **env;
12566         char **ep;
12567
12568         nenv = 0;
12569         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12570                 for (vp = *vpp ; vp ; vp = vp->next)
12571                         if (vp->flags & VEXPORT)
12572                                 nenv++;
12573         }
12574         ep = env = stalloc((nenv + 1) * sizeof *env);
12575         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12576                 for (vp = *vpp ; vp ; vp = vp->next)
12577                         if (vp->flags & VEXPORT)
12578                                 *ep++ = vp->text;
12579         }
12580         *ep = NULL;
12581         return env;
12582 }
12583
12584
12585 /*
12586  * Called when a shell procedure is invoked to clear out nonexported
12587  * variables.  It is also necessary to reallocate variables of with
12588  * VSTACK set since these are currently allocated on the stack.
12589  */
12590
12591 static void
12592 shprocvar(void) {
12593         struct var **vpp;
12594         struct var *vp, **prev;
12595
12596         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12597                 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12598                         if ((vp->flags & VEXPORT) == 0) {
12599                                 *prev = vp->next;
12600                                 if ((vp->flags & VTEXTFIXED) == 0)
12601                                         ckfree(vp->text);
12602                                 if ((vp->flags & VSTRFIXED) == 0)
12603                                         ckfree(vp);
12604                         } else {
12605                                 if (vp->flags & VSTACK) {
12606                                         vp->text = savestr(vp->text);
12607                                         vp->flags &=~ VSTACK;
12608                                 }
12609                                 prev = &vp->next;
12610                         }
12611                 }
12612         }
12613         initvar();
12614 }
12615
12616
12617
12618 /*
12619  * Command to list all variables which are set.  Currently this command
12620  * is invoked from the set command when the set command is called without
12621  * any variables.
12622  */
12623
12624 static int
12625 showvarscmd(argc, argv)
12626         int argc;
12627         char **argv;
12628 {
12629         showvars(nullstr, VUNSET, VUNSET);
12630         return 0;
12631 }
12632
12633
12634
12635 /*
12636  * The export and readonly commands.
12637  */
12638
12639 static int
12640 exportcmd(argc, argv)
12641         int argc;
12642         char **argv;
12643 {
12644         struct var *vp;
12645         char *name;
12646         const char *p;
12647         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12648         int pflag;
12649
12650         listsetvar(cmdenviron);
12651         pflag = (nextopt("p") == 'p');
12652         if (argc > 1 && !pflag) {
12653                 while ((name = *argptr++) != NULL) {
12654                         if ((p = strchr(name, '=')) != NULL) {
12655                                 p++;
12656                         } else {
12657                                 if ((vp = *findvar(hashvar(name), name))) {
12658                                         vp->flags |= flag;
12659                                         goto found;
12660                                 }
12661                         }
12662                         setvar(name, p, flag);
12663 found:;
12664                 }
12665         } else {
12666                 showvars(argv[0], flag, 0);
12667         }
12668         return 0;
12669 }
12670
12671
12672 /*
12673  * The "local" command.
12674  */
12675
12676 /* funcnest nonzero if we are currently evaluating a function */
12677
12678 static int
12679 localcmd(argc, argv)
12680         int argc;
12681         char **argv;
12682 {
12683         char *name;
12684
12685         if (! funcnest)
12686                 error("Not in a function");
12687         while ((name = *argptr++) != NULL) {
12688                 mklocal(name);
12689         }
12690         return 0;
12691 }
12692
12693
12694 /*
12695  * Make a variable a local variable.  When a variable is made local, it's
12696  * value and flags are saved in a localvar structure.  The saved values
12697  * will be restored when the shell function returns.  We handle the name
12698  * "-" as a special case.
12699  */
12700
12701 static void
12702 mklocal(name)
12703         char *name;
12704         {
12705         struct localvar *lvp;
12706         struct var **vpp;
12707         struct var *vp;
12708
12709         INTOFF;
12710         lvp = ckmalloc(sizeof (struct localvar));
12711         if (name[0] == '-' && name[1] == '\0') {
12712                 char *p;
12713                 p = ckmalloc(sizeof optet_vals);
12714                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12715                 vp = NULL;
12716         } else {
12717                 vpp = hashvar(name);
12718                 vp = *findvar(vpp, name);
12719                 if (vp == NULL) {
12720                         if (strchr(name, '='))
12721                                 setvareq(savestr(name), VSTRFIXED);
12722                         else
12723                                 setvar(name, NULL, VSTRFIXED);
12724                         vp = *vpp;      /* the new variable */
12725                         lvp->text = NULL;
12726                         lvp->flags = VUNSET;
12727                 } else {
12728                         lvp->text = vp->text;
12729                         lvp->flags = vp->flags;
12730                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12731                         if (strchr(name, '='))
12732                                 setvareq(savestr(name), 0);
12733                 }
12734         }
12735         lvp->vp = vp;
12736         lvp->next = localvars;
12737         localvars = lvp;
12738         INTON;
12739 }
12740
12741
12742 /*
12743  * Called after a function returns.
12744  */
12745
12746 static void
12747 poplocalvars() {
12748         struct localvar *lvp;
12749         struct var *vp;
12750
12751         while ((lvp = localvars) != NULL) {
12752                 localvars = lvp->next;
12753                 vp = lvp->vp;
12754                 if (vp == NULL) {       /* $- saved */
12755                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12756                         ckfree(lvp->text);
12757                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12758                         (void)unsetvar(vp->text);
12759                 } else {
12760                         if ((vp->flags & VTEXTFIXED) == 0)
12761                                 ckfree(vp->text);
12762                         vp->flags = lvp->flags;
12763                         vp->text = lvp->text;
12764                 }
12765                 ckfree(lvp);
12766         }
12767 }
12768
12769
12770 static int
12771 setvarcmd(argc, argv)
12772         int argc;
12773         char **argv;
12774 {
12775         if (argc <= 2)
12776                 return unsetcmd(argc, argv);
12777         else if (argc == 3)
12778                 setvar(argv[1], argv[2], 0);
12779         else
12780                 error("List assignment not implemented");
12781         return 0;
12782 }
12783
12784
12785 /*
12786  * The unset builtin command.  We unset the function before we unset the
12787  * variable to allow a function to be unset when there is a readonly variable
12788  * with the same name.
12789  */
12790
12791 static int
12792 unsetcmd(argc, argv)
12793         int argc;
12794         char **argv;
12795 {
12796         char **ap;
12797         int i;
12798         int flg_func = 0;
12799         int flg_var = 0;
12800         int ret = 0;
12801
12802         while ((i = nextopt("vf")) != '\0') {
12803                 if (i == 'f')
12804                         flg_func = 1;
12805                 else
12806                         flg_var = 1;
12807         }
12808         if (flg_func == 0 && flg_var == 0)
12809                 flg_var = 1;
12810
12811         for (ap = argptr; *ap ; ap++) {
12812                 if (flg_func)
12813                         unsetfunc(*ap);
12814                 if (flg_var)
12815                         ret |= unsetvar(*ap);
12816         }
12817         return ret;
12818 }
12819
12820
12821 /*
12822  * Unset the specified variable.
12823  */
12824
12825 static int
12826 unsetvar(const char *s)
12827 {
12828         struct var **vpp;
12829         struct var *vp;
12830
12831         vpp = findvar(hashvar(s), s);
12832         vp = *vpp;
12833         if (vp) {
12834                 if (vp->flags & VREADONLY)
12835                         return (1);
12836                 INTOFF;
12837                 if (*(strchr(vp->text, '=') + 1) != '\0')
12838                         setvar(s, nullstr, 0);
12839                 vp->flags &= ~VEXPORT;
12840                 vp->flags |= VUNSET;
12841                 if ((vp->flags & VSTRFIXED) == 0) {
12842                         if ((vp->flags & VTEXTFIXED) == 0)
12843                                 ckfree(vp->text);
12844                         *vpp = vp->next;
12845                         ckfree(vp);
12846                 }
12847                 INTON;
12848                 return (0);
12849         }
12850
12851         return (0);
12852 }
12853
12854
12855
12856 /*
12857  * Find the appropriate entry in the hash table from the name.
12858  */
12859
12860 static struct var **
12861 hashvar(const char *p)
12862 {
12863         unsigned int hashval;
12864
12865         hashval = ((unsigned char) *p) << 4;
12866         while (*p && *p != '=')
12867                 hashval += (unsigned char) *p++;
12868         return &vartab[hashval % VTABSIZE];
12869 }
12870
12871
12872
12873 /*
12874  * Returns true if the two strings specify the same varable.  The first
12875  * variable name is terminated by '='; the second may be terminated by
12876  * either '=' or '\0'.
12877  */
12878
12879 static int
12880 varequal(const char *p, const char *q)
12881 {
12882         while (*p == *q++) {
12883                 if (*p++ == '=')
12884                         return 1;
12885         }
12886         if (*p == '=' && *(q - 1) == '\0')
12887                 return 1;
12888         return 0;
12889 }
12890
12891 static void
12892 showvars(const char *myprefix, int mask, int xor)
12893 {
12894         struct var **vpp;
12895         struct var *vp;
12896         const char *sep = myprefix == nullstr ? myprefix : spcstr;
12897
12898         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12899                 for (vp = *vpp ; vp ; vp = vp->next) {
12900                         if ((vp->flags & mask) ^ xor) {
12901                                 char *p;
12902                                 int len;
12903
12904                                 p = strchr(vp->text, '=') + 1;
12905                                 len = p - vp->text;
12906                                 p = single_quote(p);
12907
12908                                 printf("%s%s%.*s%s\n", myprefix, sep, len,
12909                                         vp->text, p);
12910                                 stunalloc(p);
12911                         }
12912                 }
12913         }
12914 }
12915
12916 static struct var **
12917 findvar(struct var **vpp, const char *name)
12918 {
12919         for (; *vpp; vpp = &(*vpp)->next) {
12920                 if (varequal((*vpp)->text, name)) {
12921                         break;
12922                 }
12923         }
12924         return vpp;
12925 }
12926
12927 /*
12928  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12929  * This file contains code for the times builtin.
12930  * $Id: ash.c,v 1.8 2001/07/10 06:09:16 andersen Exp $
12931  */
12932 static int timescmd (int argc, char **argv)
12933 {
12934         struct tms buf;
12935         long int clk_tck = sysconf(_SC_CLK_TCK);
12936
12937         times(&buf);
12938         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12939                (int) (buf.tms_utime / clk_tck / 60),
12940                ((double) buf.tms_utime) / clk_tck,
12941                (int) (buf.tms_stime / clk_tck / 60),
12942                ((double) buf.tms_stime) / clk_tck,
12943                (int) (buf.tms_cutime / clk_tck / 60),
12944                ((double) buf.tms_cutime) / clk_tck,
12945                (int) (buf.tms_cstime / clk_tck / 60),
12946                ((double) buf.tms_cstime) / clk_tck);
12947         return 0;
12948 }
12949
12950
12951 /*-
12952  * Copyright (c) 1989, 1991, 1993, 1994
12953  *      The Regents of the University of California.  All rights reserved.
12954  *
12955  * This code is derived from software contributed to Berkeley by
12956  * Kenneth Almquist.
12957  *
12958  * Redistribution and use in source and binary forms, with or without
12959  * modification, are permitted provided that the following conditions
12960  * are met:
12961  * 1. Redistributions of source code must retain the above copyright
12962  *    notice, this list of conditions and the following disclaimer.
12963  * 2. Redistributions in binary form must reproduce the above copyright
12964  *    notice, this list of conditions and the following disclaimer in the
12965  *    documentation and/or other materials provided with the distribution.
12966  *
12967  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12968  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12969  *
12970  * 4. Neither the name of the University nor the names of its contributors
12971  *    may be used to endorse or promote products derived from this software
12972  *    without specific prior written permission.
12973  *
12974  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12975  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12976  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12977  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12978  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12979  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12980  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12981  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12982  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12983  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12984  * SUCH DAMAGE.
12985  */