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