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