177ec1c26c08e149b175a69b5b4704d7881ae8b9
[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 > loopnest)
3000                 n = loopnest;
3001         if (n > 0) {
3002                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3003                 skipcount = n;
3004         }
3005         return 0;
3006 }
3007
3008
3009 /*
3010  * The return command.
3011  */
3012
3013 static int
3014 returncmd(int argc, char **argv)
3015 {
3016         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3017
3018         if (funcnest) {
3019                 evalskip = SKIPFUNC;
3020                 skipcount = 1;
3021                 return ret;
3022         }
3023         else {
3024                 /* Do what ksh does; skip the rest of the file */
3025                 evalskip = SKIPFILE;
3026                 skipcount = 1;
3027                 return ret;
3028         }
3029 }
3030
3031
3032 #ifndef CONFIG_FALSE
3033 static int
3034 false_main(int argc, char **argv)
3035 {
3036         return 1;
3037 }
3038 #endif
3039
3040 #ifndef CONFIG_TRUE
3041 static int
3042 true_main(int argc, char **argv)
3043 {
3044         return 0;
3045 }
3046 #endif
3047
3048 /*
3049  * Controls whether the shell is interactive or not.
3050  */
3051
3052 static void setsignal(int signo);
3053
3054 #ifdef ASH_MAIL
3055 static void chkmail(int silent);
3056 #endif
3057
3058 static void
3059 setinteractive(int on)
3060 {
3061         static int is_interactive;
3062         static int do_banner=0;
3063
3064         if (on == is_interactive)
3065                 return;
3066         setsignal(SIGINT);
3067         setsignal(SIGQUIT);
3068         setsignal(SIGTERM);
3069 #ifdef ASH_MAIL
3070         chkmail(1);
3071 #endif
3072         is_interactive = on;
3073         if (do_banner==0 && is_interactive) {
3074                 /* Looks like they want an interactive shell */
3075 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 
3076                 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3077                 printf( "Enter 'help' for a list of built-in commands.\n\n");
3078 #endif
3079                 do_banner=1;
3080         }
3081 }
3082
3083 static void
3084 optschanged(void)
3085 {
3086         setinteractive(iflag);
3087         setjobctl(mflag);
3088 }
3089
3090
3091 static int
3092 execcmd(int argc, char **argv)
3093 {
3094         if (argc > 1) {
3095                 struct strlist *sp;
3096
3097                 iflag = 0;              /* exit on error */
3098                 mflag = 0;
3099                 optschanged();
3100                 for (sp = cmdenviron; sp ; sp = sp->next)
3101                         setvareq(sp->text, VEXPORT|VSTACK);
3102                 shellexec(argv + 1, environment(), pathval(), 0);
3103         }
3104         return 0;
3105 }
3106
3107 static void
3108 eprintlist(struct strlist *sp)
3109 {
3110         for (; sp; sp = sp->next) {
3111                 out2fmt(" %s",sp->text);
3112         }
3113 }
3114
3115 /*
3116  * Exec a program.  Never returns.  If you change this routine, you may
3117  * have to change the find_command routine as well.
3118  */
3119
3120 static const char *pathopt;     /* set by padvance */
3121
3122 static void
3123 shellexec(char **argv, char **envp, const char *path, int idx)
3124 {
3125         char *cmdname;
3126         int e;
3127
3128         if (strchr(argv[0], '/') != NULL) {
3129                 tryexec(argv[0], argv, envp);
3130                 e = errno;
3131         } else {
3132                 e = ENOENT;
3133                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3134                         if (--idx < 0 && pathopt == NULL) {
3135                                 tryexec(cmdname, argv, envp);
3136                                 if (errno != ENOENT && errno != ENOTDIR)
3137                                         e = errno;
3138                         }
3139                         stunalloc(cmdname);
3140                 }
3141         }
3142
3143         /* Map to POSIX errors */
3144         switch (e) {
3145         case EACCES:
3146                 exerrno = 126;
3147                 break;
3148         case ENOENT:
3149                 exerrno = 127;
3150                 break;
3151         default:
3152                 exerrno = 2;
3153                 break;
3154         }
3155         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3156         /* NOTREACHED */
3157 }
3158
3159 /*
3160  * Clear traps on a fork.
3161  */
3162 static void
3163 clear_traps(void)
3164 {
3165         char **tp;
3166
3167         for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3168                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
3169                         INTOFF;
3170                         ckfree(*tp);
3171                         *tp = NULL;
3172                         if (tp != &trap[0])
3173                                 setsignal(tp - trap);
3174                         INTON;
3175                 }
3176         }
3177 }
3178
3179
3180 static void
3181 initshellproc(void)
3182 {
3183
3184 #ifdef ASH_ALIAS
3185       /* from alias.c: */
3186       {
3187               rmaliases();
3188       }
3189 #endif
3190       /* from eval.c: */
3191       {
3192               exitstatus = 0;
3193       }
3194
3195       /* from exec.c: */
3196       {
3197               deletefuncs();
3198       }
3199
3200       /* from jobs.c: */
3201       {
3202               backgndpid = -1;
3203 #ifdef JOBS
3204               jobctl = 0;
3205 #endif
3206       }
3207
3208       /* from options.c: */
3209       {
3210               int i;
3211
3212               for (i = 0; i < NOPTS; i++)
3213                       optent_val(i) = 0;
3214               optschanged();
3215
3216       }
3217
3218       /* from redir.c: */
3219       {
3220               clearredir();
3221       }
3222
3223       /* from trap.c: */
3224       {
3225               char *sm;
3226
3227               clear_traps();
3228               for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3229                       if (*sm == S_IGN)
3230                               *sm = S_HARD_IGN;
3231               }
3232       }
3233
3234       /* from var.c: */
3235       {
3236               shprocvar();
3237       }
3238 }
3239
3240 static int preadbuffer(void);
3241 static void pushfile (void);
3242
3243 /*
3244  * Read a character from the script, returning PEOF on end of file.
3245  * Nul characters in the input are silently discarded.
3246  */
3247
3248 #ifndef ASH_OPTIMIZE_FOR_SIZE
3249 #define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3250 static int
3251 pgetc(void)
3252 {
3253         return pgetc_macro();
3254 }
3255 #else
3256 static int
3257 pgetc_macro(void)
3258 {
3259         return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3260 }
3261
3262 static inline int
3263 pgetc(void)
3264 {
3265         return pgetc_macro();
3266 }
3267 #endif
3268
3269
3270 /*
3271  * Undo the last call to pgetc.  Only one character may be pushed back.
3272  * PEOF may be pushed back.
3273  */
3274
3275 static void pungetc(void) 
3276 {
3277         parsenleft++;
3278         parsenextc--;
3279 }
3280
3281
3282 static void
3283 popfile(void)
3284 {
3285         struct parsefile *pf = parsefile;
3286
3287         INTOFF;
3288         if (pf->fd >= 0)
3289                 close(pf->fd);
3290         if (pf->buf)
3291                 ckfree(pf->buf);
3292         while (pf->strpush)
3293                 popstring();
3294         parsefile = pf->prev;
3295         ckfree(pf);
3296         parsenleft = parsefile->nleft;
3297         parselleft = parsefile->lleft;
3298         parsenextc = parsefile->nextc;
3299         plinno = parsefile->linno;
3300         INTON;
3301 }
3302
3303
3304 /*
3305  * Return to top level.
3306  */
3307
3308 static void
3309 popallfiles(void)
3310 {
3311         while (parsefile != &basepf)
3312                 popfile();
3313 }
3314
3315 /*
3316  * Close the file(s) that the shell is reading commands from.  Called
3317  * after a fork is done.
3318  */
3319
3320 static void closescript(void) 
3321 {
3322         popallfiles();
3323         if (parsefile->fd > 0) {
3324                 close(parsefile->fd);
3325                 parsefile->fd = 0;
3326         }
3327 }
3328
3329
3330 /*
3331  * Like setinputfile, but takes an open file descriptor.  Call this with
3332  * interrupts off.
3333  */
3334
3335 static void setinputfd(int fd, int push)
3336 {
3337         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3338         if (push) {
3339                 pushfile();
3340                 parsefile->buf = 0;
3341         } else {
3342                 closescript();
3343                 while (parsefile->strpush)
3344                         popstring();
3345         }
3346         parsefile->fd = fd;
3347         if (parsefile->buf == NULL)
3348                 parsefile->buf = xmalloc(BUFSIZ);
3349         parselleft = parsenleft = 0;
3350         plinno = 1;
3351 }
3352
3353
3354 /*
3355  * Set the input to take input from a file.  If push is set, push the
3356  * old input onto the stack first.
3357  */
3358
3359 static void
3360 setinputfile(const char *fname, int push)
3361 {
3362         int fd;
3363         int myfileno2;
3364
3365         INTOFF;
3366         if ((fd = open(fname, O_RDONLY)) < 0)
3367                 error("Can't open %s", fname);
3368         if (fd < 10) {
3369                 myfileno2 = dup_as_newfd(fd, 10);
3370                 close(fd);
3371                 if (myfileno2 < 0)
3372                         error("Out of file descriptors");
3373                 fd = myfileno2;
3374         }
3375         setinputfd(fd, push);
3376         INTON;
3377 }
3378
3379
3380 static void
3381 tryexec(char *cmd, char **argv, char **envp)
3382 {
3383         int e;
3384
3385 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3386         char *name = cmd;
3387         char** argv_l=argv;
3388         int argc_l;
3389 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3390         name = get_last_path_component(name);
3391 #endif
3392         argv_l=envp;
3393         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3394                 putenv(*argv_l);
3395         argv_l=argv;
3396         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3397         optind = 1;
3398         run_applet_by_name(name, argc_l, argv);
3399 #endif
3400         execve(cmd, argv, envp);
3401         e = errno;
3402         if (e == ENOEXEC) {
3403                 INTOFF;
3404                 initshellproc();
3405                 setinputfile(cmd, 0);
3406                 commandname = arg0 = xstrdup(argv[0]);
3407                 setparam(argv + 1);
3408                 exraise(EXSHELLPROC);
3409         }
3410         errno = e;
3411 }
3412
3413 static char *commandtext (const union node *);
3414
3415 /*
3416  * Do a path search.  The variable path (passed by reference) should be
3417  * set to the start of the path before the first call; padvance will update
3418  * this value as it proceeds.  Successive calls to padvance will return
3419  * the possible path expansions in sequence.  If an option (indicated by
3420  * a percent sign) appears in the path entry then the global variable
3421  * pathopt will be set to point to it; otherwise pathopt will be set to
3422  * NULL.
3423  */
3424
3425 static const char *pathopt;
3426
3427 static void growstackblock(void);
3428
3429
3430 static char *
3431 padvance(const char **path, const char *name)
3432 {
3433         const char *p;
3434         char *q;
3435         const char *start;
3436         int len;
3437
3438         if (*path == NULL)
3439                 return NULL;
3440         start = *path;
3441         for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3442         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3443         while (stackblocksize() < len)
3444                 growstackblock();
3445         q = stackblock();
3446         if (p != start) {
3447                 memcpy(q, start, p - start);
3448                 q += p - start;
3449                 *q++ = '/';
3450         }
3451         strcpy(q, name);
3452         pathopt = NULL;
3453         if (*p == '%') {
3454                 pathopt = ++p;
3455                 while (*p && *p != ':')  p++;
3456         }
3457         if (*p == ':')
3458                 *path = p + 1;
3459         else
3460                 *path = NULL;
3461         return stalloc(len);
3462 }
3463
3464 /*
3465  * Wrapper around strcmp for qsort/bsearch/...
3466  */
3467 static int
3468 pstrcmp(const void *a, const void *b)
3469 {
3470         return strcmp((const char *) a, (*(const char *const *) b) + 1);
3471 }
3472
3473 /*
3474  * Find a keyword is in a sorted array.
3475  */
3476
3477 static const char *const *
3478 findkwd(const char *s)
3479 {
3480         return  bsearch(s, tokname_array + KWDOFFSET,
3481                                         (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET,
3482                                         sizeof(const char *), pstrcmp);
3483 }
3484
3485
3486 /*** Command hashing code ***/
3487
3488
3489 static int
3490 hashcmd(int argc, char **argv)
3491 {
3492         struct tblentry **pp;
3493         struct tblentry *cmdp;
3494         int c;
3495         int verbose;
3496         struct cmdentry entry;
3497         char *name;
3498 #ifdef ASH_ALIAS
3499         const struct alias *ap;
3500 #endif
3501
3502         verbose = 0;
3503         while ((c = nextopt("rvV")) != '\0') {
3504                 if (c == 'r') {
3505                         clearcmdentry(0);
3506                         return 0;
3507                 } else if (c == 'v' || c == 'V') {
3508                         verbose = c;
3509                 }
3510         }
3511         if (*argptr == NULL) {
3512                 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3513                         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3514                                 if (cmdp->cmdtype != CMDBUILTIN) {
3515                                         printentry(cmdp, verbose);
3516                                 }
3517                         }
3518                 }
3519                 return 0;
3520         }
3521         c = 0;
3522         while ((name = *argptr++) != NULL) {
3523                 if ((cmdp = cmdlookup(name, 0)) != NULL
3524                  && (cmdp->cmdtype == CMDNORMAL
3525                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3526                         delete_cmd_entry();
3527 #ifdef ASH_ALIAS
3528         /* Then look at the aliases */
3529                 if ((ap = *__lookupalias(name)) != NULL) {
3530                         if (verbose=='v')
3531                                 printf("%s is an alias for %s\n", name, ap->val);
3532                         else
3533                                 printalias(ap);
3534                         continue;
3535                 }
3536 #endif
3537                         /* First look at the keywords */
3538                 if (findkwd(name)!=0) {
3539                         if (verbose=='v')
3540                                 printf("%s is a shell keyword\n", name);
3541                         else
3542                                 puts(name);
3543                         continue;
3544                 }
3545
3546                 find_command(name, &entry, DO_ERR, pathval());
3547                 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3548                 else if (verbose) {
3549                         cmdp = cmdlookup(name, 0);
3550                         if (cmdp) printentry(cmdp, verbose=='v');
3551                         flushall();
3552                 }
3553         }
3554         return c;
3555 }
3556
3557 static void
3558 printentry(struct tblentry *cmdp, int verbose)
3559 {
3560         int idx;
3561         const char *path;
3562         char *name;
3563
3564         printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3565         if (cmdp->cmdtype == CMDNORMAL) {
3566                 idx = cmdp->param.index;
3567                 path = pathval();
3568                 do {
3569                         name = padvance(&path, cmdp->cmdname);
3570                         stunalloc(name);
3571                 } while (--idx >= 0);
3572                 if(verbose)
3573                         out1str(name);
3574         } else if (cmdp->cmdtype == CMDBUILTIN) {
3575                 if(verbose)
3576                         out1str("a shell builtin");
3577         } else if (cmdp->cmdtype == CMDFUNCTION) {
3578                 if (verbose) {
3579                         INTOFF;
3580                         out1str("a function\n");
3581                         name = commandtext(cmdp->param.func);
3582                         printf("%s() {\n %s\n}", cmdp->cmdname, name);
3583                         ckfree(name);
3584                         INTON;
3585                 }
3586 #ifdef DEBUG
3587         } else {
3588                 error("internal error: cmdtype %d", cmdp->cmdtype);
3589 #endif
3590         }
3591         puts(cmdp->rehash ? "*" : nullstr);
3592 }
3593
3594
3595
3596 /*** List the available builtins ***/
3597
3598
3599 static int helpcmd(int argc, char** argv)
3600 {
3601         int col, i;
3602
3603         printf("\nBuilt-in commands:\n-------------------\n");
3604         for (col=0, i=0; i < NUMBUILTINS; i++) {
3605                 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3606                                 builtincmds[i].name+1);
3607                 if (col > 60) {
3608                         printf("\n");
3609                         col = 0;
3610                 }
3611         }
3612 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3613         {
3614                 extern const struct BB_applet applets[];
3615                 extern const size_t NUM_APPLETS;
3616
3617                 for (i=0; i < NUM_APPLETS; i++) {
3618
3619                         col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3620                                         applets[i].name);
3621                         if (col > 60) {
3622                                 printf("\n");
3623                                 col = 0;
3624                         }
3625                 }
3626         }
3627 #endif
3628         printf("\n\n");
3629         return EXIT_SUCCESS;
3630 }
3631
3632 /*
3633  * Resolve a command name.  If you change this routine, you may have to
3634  * change the shellexec routine as well.
3635  */
3636
3637 static int prefix (const char *, const char *);
3638
3639 static void
3640 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3641 {
3642         struct tblentry *cmdp;
3643         int idx;
3644         int prev;
3645         char *fullname;
3646         struct stat statb;
3647         int e;
3648         int bltin;
3649         int firstchange;
3650         int updatetbl;
3651         int regular;
3652         struct builtincmd *bcmd;
3653
3654         /* If name contains a slash, don't use the hash table */
3655         if (strchr(name, '/') != NULL) {
3656                 if (act & DO_ABS) {
3657                         while (stat(name, &statb) < 0) {
3658                                 if (errno != ENOENT && errno != ENOTDIR)
3659                                         e = errno;
3660                                 entry->cmdtype = CMDUNKNOWN;
3661                                 entry->u.index = -1;
3662                                 return;
3663                         }
3664                         entry->cmdtype = CMDNORMAL;
3665                         entry->u.index = -1;
3666                         return;
3667                 }
3668                 entry->cmdtype = CMDNORMAL;
3669                 entry->u.index = 0;
3670                 return;
3671         }
3672
3673         updatetbl = 1;
3674         if (act & DO_BRUTE) {
3675                 firstchange = path_change(path, &bltin);
3676         } else {
3677                 bltin = builtinloc;
3678                 firstchange = 9999;
3679         }
3680
3681         /* If name is in the table, and not invalidated by cd, we're done */
3682         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3683                 if (cmdp->cmdtype == CMDFUNCTION) {
3684                         if (act & DO_NOFUN) {
3685                                 updatetbl = 0;
3686                         } else {
3687                                 goto success;
3688                         }
3689                 } else if (act & DO_BRUTE) {
3690                         if ((cmdp->cmdtype == CMDNORMAL &&
3691                              cmdp->param.index >= firstchange) ||
3692                             (cmdp->cmdtype == CMDBUILTIN &&
3693                              ((builtinloc < 0 && bltin >= 0) ?
3694                               bltin : builtinloc) >= firstchange)) {
3695                                 /* need to recompute the entry */
3696                         } else {
3697                                 goto success;
3698                         }
3699                 } else {
3700                         goto success;
3701                 }
3702         }
3703
3704         bcmd = find_builtin(name);
3705         regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3706
3707         if (regular) {
3708                 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3709                         goto success;
3710                 }
3711         } else if (act & DO_BRUTE) {
3712                 if (firstchange == 0) {
3713                         updatetbl = 0;
3714                 }
3715         }
3716
3717         /* If %builtin not in path, check for builtin next */
3718         if (regular || (bltin < 0 && bcmd)) {
3719 builtin:
3720                 if (!updatetbl) {
3721                         entry->cmdtype = CMDBUILTIN;
3722                         entry->u.cmd = bcmd;
3723                         return;
3724                 }
3725                 INTOFF;
3726                 cmdp = cmdlookup(name, 1);
3727                 cmdp->cmdtype = CMDBUILTIN;
3728                 cmdp->param.cmd = bcmd;
3729                 INTON;
3730                 goto success;
3731         }
3732
3733         /* We have to search path. */
3734         prev = -1;              /* where to start */
3735         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3736                 if (cmdp->cmdtype == CMDBUILTIN)
3737                         prev = builtinloc;
3738                 else
3739                         prev = cmdp->param.index;
3740         }
3741
3742         e = ENOENT;
3743         idx = -1;
3744 loop:
3745         while ((fullname = padvance(&path, name)) != NULL) {
3746                 stunalloc(fullname);
3747                 idx++;
3748                 if (idx >= firstchange) {
3749                         updatetbl = 0;
3750                 }
3751                 if (pathopt) {
3752                         if (prefix("builtin", pathopt)) {
3753                                 if ((bcmd = find_builtin(name))) {
3754                                         goto builtin;
3755                                 }
3756                                 continue;
3757                         } else if (!(act & DO_NOFUN) &&
3758                                    prefix("func", pathopt)) {
3759                                 /* handled below */
3760                         } else {
3761                                 continue;       /* ignore unimplemented options */
3762                         }
3763                 }
3764                 /* if rehash, don't redo absolute path names */
3765                 if (fullname[0] == '/' && idx <= prev &&
3766                     idx < firstchange) {
3767                         if (idx < prev)
3768                                 continue;
3769                         TRACE(("searchexec \"%s\": no change\n", name));
3770                         goto success;
3771                 }
3772                 while (stat(fullname, &statb) < 0) {
3773                         if (errno != ENOENT && errno != ENOTDIR)
3774                                 e = errno;
3775                         goto loop;
3776                 }
3777                 e = EACCES;     /* if we fail, this will be the error */
3778                 if (!S_ISREG(statb.st_mode))
3779                         continue;
3780                 if (pathopt) {          /* this is a %func directory */
3781                         stalloc(strlen(fullname) + 1);
3782                         readcmdfile(fullname);
3783                         if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
3784                                 error("%s not defined in %s", name, fullname);
3785                         stunalloc(fullname);
3786                         goto success;
3787                 }
3788                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3789                 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3790                    be a function and we're being called with DO_NOFUN */
3791                 if (!updatetbl) {
3792                         entry->cmdtype = CMDNORMAL;
3793                         entry->u.index = idx;
3794                         return;
3795                 }
3796                 INTOFF;
3797                 cmdp = cmdlookup(name, 1);
3798                 cmdp->cmdtype = CMDNORMAL;
3799                 cmdp->param.index = idx;
3800                 INTON;
3801                 goto success;
3802         }
3803
3804         /* We failed.  If there was an entry for this command, delete it */
3805         if (cmdp && updatetbl)
3806                 delete_cmd_entry();
3807         if (act & DO_ERR)
3808                 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3809         entry->cmdtype = CMDUNKNOWN;
3810         return;
3811
3812 success:
3813         cmdp->rehash = 0;
3814         entry->cmdtype = cmdp->cmdtype;
3815         entry->u = cmdp->param;
3816 }
3817
3818
3819
3820 /*
3821  * Search the table of builtin commands.
3822  */
3823
3824 static int
3825 bstrcmp(const void *name, const void *b)
3826 {
3827         return strcmp((const char *)name, (*(const char *const *) b)+1);
3828 }
3829
3830 static struct builtincmd *
3831 find_builtin(const char *name)
3832 {
3833         struct builtincmd *bp;
3834
3835         bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3836                 bstrcmp
3837         );
3838         return bp;
3839 }
3840
3841
3842 /*
3843  * Called when a cd is done.  Marks all commands so the next time they
3844  * are executed they will be rehashed.
3845  */
3846
3847 static inline void
3848 hashcd(void)
3849 {
3850         struct tblentry **pp;
3851         struct tblentry *cmdp;
3852
3853         for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3854                 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3855                         if (cmdp->cmdtype == CMDNORMAL
3856                          || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
3857                                 cmdp->rehash = 1;
3858                 }
3859         }
3860 }
3861
3862
3863
3864 /*
3865  * Called before PATH is changed.  The argument is the new value of PATH;
3866  * pathval() still returns the old value at this point.  Called with
3867  * interrupts off.
3868  */
3869
3870 static void
3871 changepath(const char *newval)
3872 {
3873         int firstchange;
3874         int bltin;
3875
3876         firstchange = path_change(newval, &bltin);
3877         if (builtinloc < 0 && bltin >= 0)
3878                 builtinloc = bltin;             /* zap builtins */
3879         clearcmdentry(firstchange);
3880         builtinloc = bltin;
3881 }
3882
3883
3884 /*
3885  * Clear out command entries.  The argument specifies the first entry in
3886  * PATH which has changed.
3887  */
3888
3889 static void
3890 clearcmdentry(int firstchange)
3891 {
3892         struct tblentry **tblp;
3893         struct tblentry **pp;
3894         struct tblentry *cmdp;
3895
3896         INTOFF;
3897         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
3898                 pp = tblp;
3899                 while ((cmdp = *pp) != NULL) {
3900                         if ((cmdp->cmdtype == CMDNORMAL &&
3901                              cmdp->param.index >= firstchange)
3902                          || (cmdp->cmdtype == CMDBUILTIN &&
3903                              builtinloc >= firstchange)) {
3904                                 *pp = cmdp->next;
3905                                 ckfree(cmdp);
3906                         } else {
3907                                 pp = &cmdp->next;
3908                         }
3909                 }
3910         }
3911         INTON;
3912 }
3913
3914
3915 /*
3916  * Delete all functions.
3917  */
3918
3919 static void
3920 deletefuncs(void)
3921 {
3922         struct tblentry **tblp;
3923         struct tblentry **pp;
3924         struct tblentry *cmdp;
3925
3926         INTOFF;
3927         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
3928                 pp = tblp;
3929                 while ((cmdp = *pp) != NULL) {
3930                         if (cmdp->cmdtype == CMDFUNCTION) {
3931                                 *pp = cmdp->next;
3932                                 freefunc(cmdp->param.func);
3933                                 ckfree(cmdp);
3934                         } else {
3935                                 pp = &cmdp->next;
3936                         }
3937                 }
3938         }
3939         INTON;
3940 }
3941
3942
3943
3944 /*
3945  * Locate a command in the command hash table.  If "add" is nonzero,
3946  * add the command to the table if it is not already present.  The
3947  * variable "lastcmdentry" is set to point to the address of the link
3948  * pointing to the entry, so that delete_cmd_entry can delete the
3949  * entry.
3950  */
3951
3952 static struct tblentry **lastcmdentry;
3953
3954 static struct tblentry *
3955 cmdlookup(const char *name, int add)
3956 {
3957         int hashval;
3958         const char *p;
3959         struct tblentry *cmdp;
3960         struct tblentry **pp;
3961
3962         p = name;
3963         hashval = *p << 4;
3964         while (*p)
3965                 hashval += *p++;
3966         hashval &= 0x7FFF;
3967         pp = &cmdtable[hashval % CMDTABLESIZE];
3968         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3969                 if (equal(cmdp->cmdname, name))
3970                         break;
3971                 pp = &cmdp->next;
3972         }
3973         if (add && cmdp == NULL) {
3974                 INTOFF;
3975                 cmdp = *pp = xmalloc(sizeof (struct tblentry) - ARB
3976                                         + strlen(name) + 1);
3977                 cmdp->next = NULL;
3978                 cmdp->cmdtype = CMDUNKNOWN;
3979                 cmdp->rehash = 0;
3980                 strcpy(cmdp->cmdname, name);
3981                 INTON;
3982         }
3983         lastcmdentry = pp;
3984         return cmdp;
3985 }
3986
3987 /*
3988  * Delete the command entry returned on the last lookup.
3989  */
3990
3991 static void
3992 delete_cmd_entry()
3993 {
3994         struct tblentry *cmdp;
3995
3996         INTOFF;
3997         cmdp = *lastcmdentry;
3998         *lastcmdentry = cmdp->next;
3999         ckfree(cmdp);
4000         INTON;
4001 }
4002
4003
4004
4005
4006
4007 static const unsigned char nodesize[26] = {
4008       ALIGN(sizeof (struct nbinary)),
4009       ALIGN(sizeof (struct ncmd)),
4010       ALIGN(sizeof (struct npipe)),
4011       ALIGN(sizeof (struct nredir)),
4012       ALIGN(sizeof (struct nredir)),
4013       ALIGN(sizeof (struct nredir)),
4014       ALIGN(sizeof (struct nbinary)),
4015       ALIGN(sizeof (struct nbinary)),
4016       ALIGN(sizeof (struct nif)),
4017       ALIGN(sizeof (struct nbinary)),
4018       ALIGN(sizeof (struct nbinary)),
4019       ALIGN(sizeof (struct nfor)),
4020       ALIGN(sizeof (struct ncase)),
4021       ALIGN(sizeof (struct nclist)),
4022       ALIGN(sizeof (struct narg)),
4023       ALIGN(sizeof (struct narg)),
4024       ALIGN(sizeof (struct nfile)),
4025       ALIGN(sizeof (struct nfile)),
4026       ALIGN(sizeof (struct nfile)),
4027       ALIGN(sizeof (struct nfile)),
4028       ALIGN(sizeof (struct nfile)),
4029       ALIGN(sizeof (struct ndup)),
4030       ALIGN(sizeof (struct ndup)),
4031       ALIGN(sizeof (struct nhere)),
4032       ALIGN(sizeof (struct nhere)),
4033       ALIGN(sizeof (struct nnot)),
4034 };
4035
4036
4037
4038 /*
4039  * Delete a function if it exists.
4040  */
4041
4042 static void
4043 unsetfunc(char *name)
4044 {
4045         struct tblentry *cmdp;
4046
4047         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4048                 freefunc(cmdp->param.func);
4049                 delete_cmd_entry();
4050         }
4051 }
4052
4053
4054 /*
4055  * Locate and print what a word is...
4056  */
4057
4058 static int
4059 typecmd(int argc, char **argv)
4060 {
4061         int i;
4062         int err = 0;
4063         char *argv_a[2];
4064
4065         argv_a[1] = 0;
4066
4067         for (i = 1; i < argc; i++) {
4068                 argv_a[0] = argv[i];
4069                 argptr = argv_a;
4070                 optptr = "v";
4071                 err |= hashcmd(argc, argv);
4072         }
4073         return err;
4074 }
4075
4076 #ifdef ASH_CMDCMD
4077 static int
4078 commandcmd(int argc, char **argv)
4079 {
4080         int c;
4081         int default_path = 0;
4082         int verify_only = 0;
4083         int verbose_verify_only = 0;
4084
4085         while ((c = nextopt("pvV")) != '\0')
4086                 switch (c) {
4087                 case 'p':
4088                         default_path = 1;
4089                         break;
4090                 case 'v':
4091                         verify_only = 1;
4092                         break;
4093                 case 'V':
4094                         verbose_verify_only = 1;
4095                         break;
4096                 }
4097
4098         if (default_path + verify_only + verbose_verify_only > 1 ||
4099             !*argptr) {
4100                         out2str(
4101                                 "command [-p] command [arg ...]\n"
4102                                 "command {-v|-V} command\n");
4103                         return EX_USAGE;
4104         }
4105
4106         if (verify_only || verbose_verify_only) {
4107                 char *argv_a[2];
4108
4109                 argv_a[1] = 0;
4110                 argv_a[0] = *argptr;
4111                 argptr = argv_a;
4112                 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
4113                 return hashcmd(argc, argv);
4114         }
4115
4116         return 0;
4117 }
4118 #endif
4119
4120 static int
4121 path_change(const char *newval, int *bltin)
4122 {
4123         const char *old, *new;
4124         int idx;
4125         int firstchange;
4126
4127         old = pathval();
4128         new = newval;
4129         firstchange = 9999;     /* assume no change */
4130         idx = 0;
4131         *bltin = -1;
4132         for (;;) {
4133                 if (*old != *new) {
4134                         firstchange = idx;
4135                         if ((*old == '\0' && *new == ':')
4136                          || (*old == ':' && *new == '\0'))
4137                                 firstchange++;
4138                         old = new;      /* ignore subsequent differences */
4139                 }
4140                 if (*new == '\0')
4141                         break;
4142                 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4143                         *bltin = idx;
4144                 if (*new == ':') {
4145                         idx++;
4146                 }
4147                 new++, old++;
4148         }
4149         if (builtinloc >= 0 && *bltin < 0)
4150                 firstchange = 0;
4151         return firstchange;
4152 }
4153 /*
4154  * Routines to expand arguments to commands.  We have to deal with
4155  * backquotes, shell variables, and file metacharacters.
4156  */
4157 /*
4158  * _rmescape() flags
4159  */
4160 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4161 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4162
4163 /*
4164  * Structure specifying which parts of the string should be searched
4165  * for IFS characters.
4166  */
4167
4168 struct ifsregion {
4169         struct ifsregion *next; /* next region in list */
4170         int begoff;             /* offset of start of region */
4171         int endoff;             /* offset of end of region */
4172         int nulonly;            /* search for nul bytes only */
4173 };
4174
4175
4176 static char *expdest;                   /* output of current string */
4177 static struct nodelist *argbackq;      /* list of back quote expressions */
4178 static struct ifsregion ifsfirst;      /* first struct in list of ifs regions */
4179 static struct ifsregion *ifslastp;     /* last struct in list */
4180 static struct arglist exparg;          /* holds expanded arg list */
4181
4182 static void argstr (char *, int);
4183 static char *exptilde (char *, int);
4184 static void expbackq (union node *, int, int);
4185 static int subevalvar (char *, char *, int, int, int, int, int);
4186 static int varisset (char *, int);
4187 static void strtodest (const char *, int, int);
4188 static inline void varvalue (char *, int, int);
4189 static void recordregion (int, int, int);
4190 static void removerecordregions (int);
4191 static void ifsbreakup (char *, struct arglist *);
4192 static void ifsfree (void);
4193 static void expandmeta (struct strlist *, int);
4194 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4195 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4196 #if !defined(GLOB_BROKEN)
4197 static inline void addglob (const glob_t *);
4198 #endif
4199 #endif
4200 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4201 static void expmeta (char *, char *);
4202 #endif
4203 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4204 static struct strlist *expsort (struct strlist *);
4205 static struct strlist *msort (struct strlist *, int);
4206 #endif
4207 static int patmatch (char *, char *, int);
4208 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4209 static int patmatch2 (char *, char *, int);
4210 #else
4211 static int pmatch (char *, char *, int);
4212 #define patmatch2 patmatch
4213 #endif
4214 static char *cvtnum (int, char *);
4215
4216 /*
4217  * Expand shell variables and backquotes inside a here document.
4218  */
4219
4220 /* arg: the document, fd: where to write the expanded version */
4221 static inline void
4222 expandhere(union node *arg, int fd)
4223 {
4224         herefd = fd;
4225         expandarg(arg, (struct arglist *)NULL, 0);
4226         xwrite(fd, stackblock(), expdest - stackblock());
4227 }
4228
4229
4230 /*
4231  * Perform variable substitution and command substitution on an argument,
4232  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
4233  * perform splitting and file name expansion.  When arglist is NULL, perform
4234  * here document expansion.
4235  */
4236
4237 static void
4238 expandarg(union node *arg, struct arglist *arglist, int flag)
4239 {
4240         struct strlist *sp;
4241         char *p;
4242
4243         argbackq = arg->narg.backquote;
4244         STARTSTACKSTR(expdest);
4245         ifsfirst.next = NULL;
4246         ifslastp = NULL;
4247         argstr(arg->narg.text, flag);
4248         if (arglist == NULL) {
4249                 return;                 /* here document expanded */
4250         }
4251         STPUTC('\0', expdest);
4252         p = grabstackstr(expdest);
4253         exparg.lastp = &exparg.list;
4254         /*
4255          * TODO - EXP_REDIR
4256          */
4257         if (flag & EXP_FULL) {
4258                 ifsbreakup(p, &exparg);
4259                 *exparg.lastp = NULL;
4260                 exparg.lastp = &exparg.list;
4261                 expandmeta(exparg.list, flag);
4262         } else {
4263                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4264                         rmescapes(p);
4265                 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4266                 sp->text = p;
4267                 *exparg.lastp = sp;
4268                 exparg.lastp = &sp->next;
4269         }
4270         ifsfree();
4271         *exparg.lastp = NULL;
4272         if (exparg.list) {
4273                 *arglist->lastp = exparg.list;
4274                 arglist->lastp = exparg.lastp;
4275         }
4276 }
4277
4278
4279 /*
4280  * Expand a variable, and return a pointer to the next character in the
4281  * input string.
4282  */
4283
4284 static inline char * evalvar(char *p, int flag)
4285 {
4286         int subtype;
4287         int varflags;
4288         char *var;
4289         const char *val;
4290         int patloc;
4291         int c;
4292         int set;
4293         int special;
4294         int startloc;
4295         int varlen;
4296         int easy;
4297         int quotes = flag & (EXP_FULL | EXP_CASE);
4298
4299         varflags = *p++;
4300         subtype = varflags & VSTYPE;
4301         var = p;
4302         special = 0;
4303         if (! is_name(*p))
4304                 special = 1;
4305         p = strchr(p, '=') + 1;
4306 again: /* jump here after setting a variable with ${var=text} */
4307         if (special) {
4308                 set = varisset(var, varflags & VSNUL);
4309                 val = NULL;
4310         } else {
4311                 val = lookupvar(var);
4312                 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4313                         val = NULL;
4314                         set = 0;
4315                 } else
4316                         set = 1;
4317         }
4318         varlen = 0;
4319         startloc = expdest - stackblock();
4320         if (set && subtype != VSPLUS) {
4321                 /* insert the value of the variable */
4322                 if (special) {
4323                         varvalue(var, varflags & VSQUOTE, flag);
4324                         if (subtype == VSLENGTH) {
4325                                 varlen = expdest - stackblock() - startloc;
4326                                 STADJUST(-varlen, expdest);
4327                         }
4328                 } else {
4329                         if (subtype == VSLENGTH) {
4330                                 varlen = strlen(val);
4331                         } else {
4332                                 strtodest(
4333                                         val,
4334                                         varflags & VSQUOTE ?
4335                                                 DQSYNTAX : BASESYNTAX,
4336                                         quotes
4337                                 );
4338                         }
4339                 }
4340         }
4341
4342         if (subtype == VSPLUS)
4343                 set = ! set;
4344
4345         easy = ((varflags & VSQUOTE) == 0 ||
4346                 (*var == '@' && shellparam.nparam != 1));
4347
4348
4349         switch (subtype) {
4350         case VSLENGTH:
4351                 expdest = cvtnum(varlen, expdest);
4352                 goto record;
4353
4354         case VSNORMAL:
4355                 if (!easy)
4356                         break;
4357 record:
4358                 recordregion(startloc, expdest - stackblock(),
4359                              varflags & VSQUOTE);
4360                 break;
4361
4362         case VSPLUS:
4363         case VSMINUS:
4364                 if (!set) {
4365                         argstr(p, flag);
4366                         break;
4367                 }
4368                 if (easy)
4369                         goto record;
4370                 break;
4371
4372         case VSTRIMLEFT:
4373         case VSTRIMLEFTMAX:
4374         case VSTRIMRIGHT:
4375         case VSTRIMRIGHTMAX:
4376                 if (!set)
4377                         break;
4378                 /*
4379                  * Terminate the string and start recording the pattern
4380                  * right after it
4381                  */
4382                 STPUTC('\0', expdest);
4383                 patloc = expdest - stackblock();
4384                 if (subevalvar(p, NULL, patloc, subtype,
4385                                startloc, varflags, quotes) == 0) {
4386                         int amount = (expdest - stackblock() - patloc) + 1;
4387                         STADJUST(-amount, expdest);
4388                 }
4389                 /* Remove any recorded regions beyond start of variable */
4390                 removerecordregions(startloc);
4391                 goto record;
4392
4393         case VSASSIGN:
4394         case VSQUESTION:
4395                 if (!set) {
4396                         if (subevalvar(p, var, 0, subtype, startloc,
4397                                        varflags, quotes)) {
4398                                 varflags &= ~VSNUL;
4399                                 /*
4400                                  * Remove any recorded regions beyond
4401                                  * start of variable
4402                                  */
4403                                 removerecordregions(startloc);
4404                                 goto again;
4405                         }
4406                         break;
4407                 }
4408                 if (easy)
4409                         goto record;
4410                 break;
4411
4412 #ifdef DEBUG
4413         default:
4414                 abort();
4415 #endif
4416         }
4417
4418         if (subtype != VSNORMAL) {      /* skip to end of alternative */
4419                 int nesting = 1;
4420                 for (;;) {
4421                         if ((c = *p++) == CTLESC)
4422                                 p++;
4423                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
4424                                 if (set)
4425                                         argbackq = argbackq->next;
4426                         } else if (c == CTLVAR) {
4427                                 if ((*p++ & VSTYPE) != VSNORMAL)
4428                                         nesting++;
4429                         } else if (c == CTLENDVAR) {
4430                                 if (--nesting == 0)
4431                                         break;
4432                         }
4433                 }
4434         }
4435         return p;
4436 }
4437
4438
4439 /*
4440  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
4441  * characters to allow for further processing.  Otherwise treat
4442  * $@ like $* since no splitting will be performed.
4443  */
4444
4445 static void
4446 argstr(char *p, int flag)
4447 {
4448         char c;
4449         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
4450         int firsteq = 1;
4451
4452         if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4453                 p = exptilde(p, flag);
4454         for (;;) {
4455                 switch (c = *p++) {
4456                 case '\0':
4457                 case CTLENDVAR: /* ??? */
4458                         return;
4459                 case CTLQUOTEMARK:
4460                         /* "$@" syntax adherence hack */
4461                         if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4462                                 break;
4463                         if ((flag & EXP_FULL) != 0)
4464                                 STPUTC(c, expdest);
4465                         break;
4466                 case CTLESC:
4467                         if (quotes)
4468                                 STPUTC(c, expdest);
4469                         c = *p++;
4470                         STPUTC(c, expdest);
4471                         break;
4472                 case CTLVAR:
4473                         p = evalvar(p, flag);
4474                         break;
4475                 case CTLBACKQ:
4476                 case CTLBACKQ|CTLQUOTE:
4477                         expbackq(argbackq->n, c & CTLQUOTE, flag);
4478                         argbackq = argbackq->next;
4479                         break;
4480 #ifdef ASH_MATH_SUPPORT
4481                 case CTLENDARI:
4482                         expari(flag);
4483                         break;
4484 #endif
4485                 case ':':
4486                 case '=':
4487                         /*
4488                          * sort of a hack - expand tildes in variable
4489                          * assignments (after the first '=' and after ':'s).
4490                          */
4491                         STPUTC(c, expdest);
4492                         if (flag & EXP_VARTILDE && *p == '~') {
4493                                 if (c == '=') {
4494                                         if (firsteq)
4495                                                 firsteq = 0;
4496                                         else
4497                                                 break;
4498                                 }
4499                                 p = exptilde(p, flag);
4500                         }
4501                         break;
4502                 default:
4503                         STPUTC(c, expdest);
4504                 }
4505         }
4506         return;
4507 }
4508
4509 static char *
4510 exptilde(char *p, int flag)
4511 {
4512         char c, *startp = p;
4513         struct passwd *pw;
4514         const char *home;
4515         int quotes = flag & (EXP_FULL | EXP_CASE);
4516
4517         while ((c = *p) != '\0') {
4518                 switch(c) {
4519                 case CTLESC:
4520                         return (startp);
4521                 case CTLQUOTEMARK:
4522                         return (startp);
4523                 case ':':
4524                         if (flag & EXP_VARTILDE)
4525                                 goto done;
4526                         break;
4527                 case '/':
4528                         goto done;
4529                 }
4530                 p++;
4531         }
4532 done:
4533         *p = '\0';
4534         if (*(startp+1) == '\0') {
4535                 if ((home = lookupvar("HOME")) == NULL)
4536                         goto lose;
4537         } else {
4538                 if ((pw = getpwnam(startp+1)) == NULL)
4539                         goto lose;
4540                 home = pw->pw_dir;
4541         }
4542         if (*home == '\0')
4543                 goto lose;
4544         *p = c;
4545         strtodest(home, SQSYNTAX, quotes);
4546         return (p);
4547 lose:
4548         *p = c;
4549         return (startp);
4550 }
4551
4552
4553 static void
4554 removerecordregions(int endoff)
4555 {
4556         if (ifslastp == NULL)
4557                 return;
4558
4559         if (ifsfirst.endoff > endoff) {
4560                 while (ifsfirst.next != NULL) {
4561                         struct ifsregion *ifsp;
4562                         INTOFF;
4563                         ifsp = ifsfirst.next->next;
4564                         ckfree(ifsfirst.next);
4565                         ifsfirst.next = ifsp;
4566                         INTON;
4567                 }
4568                 if (ifsfirst.begoff > endoff)
4569                         ifslastp = NULL;
4570                 else {
4571                         ifslastp = &ifsfirst;
4572                         ifsfirst.endoff = endoff;
4573                 }
4574                 return;
4575         }
4576
4577         ifslastp = &ifsfirst;
4578         while (ifslastp->next && ifslastp->next->begoff < endoff)
4579                 ifslastp=ifslastp->next;
4580         while (ifslastp->next != NULL) {
4581                 struct ifsregion *ifsp;
4582                 INTOFF;
4583                 ifsp = ifslastp->next->next;
4584                 ckfree(ifslastp->next);
4585                 ifslastp->next = ifsp;
4586                 INTON;
4587         }
4588         if (ifslastp->endoff > endoff)
4589                 ifslastp->endoff = endoff;
4590 }
4591
4592
4593 #ifdef ASH_MATH_SUPPORT
4594 /*
4595  * Expand arithmetic expression.  Backup to start of expression,
4596  * evaluate, place result in (backed up) result, adjust string position.
4597  */
4598 static void
4599 expari(int flag)
4600 {
4601         char *p, *start;
4602         int errcode;
4603         int result;
4604         int begoff;
4605         int quotes = flag & (EXP_FULL | EXP_CASE);
4606         int quoted;
4607
4608         /*      ifsfree(); */
4609
4610         /*
4611          * This routine is slightly over-complicated for
4612          * efficiency.  First we make sure there is
4613          * enough space for the result, which may be bigger
4614          * than the expression if we add exponentation.  Next we
4615          * scan backwards looking for the start of arithmetic.  If the
4616          * next previous character is a CTLESC character, then we
4617          * have to rescan starting from the beginning since CTLESC
4618          * characters have to be processed left to right.
4619          */
4620         CHECKSTRSPACE(10, expdest);
4621         USTPUTC('\0', expdest);
4622         start = stackblock();
4623         p = expdest - 1;
4624         while (*p != CTLARI && p >= start)
4625                 --p;
4626         if (*p != CTLARI)
4627                 error("missing CTLARI (shouldn't happen)");
4628         if (p > start && *(p-1) == CTLESC)
4629                 for (p = start; *p != CTLARI; p++)
4630                         if (*p == CTLESC)
4631                                 p++;
4632
4633         if (p[1] == '"')
4634                 quoted=1;
4635         else
4636                 quoted=0;
4637         begoff = p - start;
4638         removerecordregions(begoff);
4639         if (quotes)
4640                 rmescapes(p+2);
4641         result = arith(p+2, &errcode);
4642         if (errcode < 0) {
4643                 if(errcode == -2)
4644                         error("divide by zero");
4645                 else
4646                         error("syntax error: \"%s\"\n", p+2);
4647         }
4648         snprintf(p, 12, "%d", result);
4649
4650         while (*p++)
4651                 ;
4652
4653         if (quoted == 0)
4654                 recordregion(begoff, p - 1 - start, 0);
4655         result = expdest - p + 1;
4656         STADJUST(-result, expdest);
4657 }
4658 #endif
4659
4660 /*
4661  * Expand stuff in backwards quotes.
4662  */
4663
4664 static void
4665 expbackq(union node *cmd, int quoted, int flag)
4666 {
4667         volatile struct backcmd in;
4668         int i;
4669         char buf[128];
4670         char *p;
4671         char *dest = expdest;
4672         volatile struct ifsregion saveifs;
4673         struct ifsregion *volatile savelastp;
4674         struct nodelist *volatile saveargbackq;
4675         char lastc;
4676         int startloc = dest - stackblock();
4677         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4678         volatile int saveherefd;
4679         int quotes = flag & (EXP_FULL | EXP_CASE);
4680         struct jmploc jmploc;
4681         struct jmploc *volatile savehandler;
4682         int ex;
4683
4684 #if __GNUC__
4685         /* Avoid longjmp clobbering */
4686         (void) &dest;
4687         (void) &syntax;
4688 #endif
4689
4690         in.fd = -1;
4691         in.buf = 0;
4692         in.jp = 0;
4693
4694         INTOFF;
4695         saveifs = ifsfirst;
4696         savelastp = ifslastp;
4697         saveargbackq = argbackq;
4698         saveherefd = herefd;
4699         herefd = -1;
4700         if ((ex = setjmp(jmploc.loc))) {
4701                 goto err1;
4702         }
4703         savehandler = handler;
4704         handler = &jmploc;
4705         INTON;
4706         p = grabstackstr(dest);
4707         evalbackcmd(cmd, (struct backcmd *) &in);
4708         ungrabstackstr(p, dest);
4709 err1:
4710         INTOFF;
4711         ifsfirst = saveifs;
4712         ifslastp = savelastp;
4713         argbackq = saveargbackq;
4714         herefd = saveherefd;
4715         if (ex) {
4716                 goto err2;
4717         }
4718
4719         p = in.buf;
4720         lastc = '\0';
4721         for (;;) {
4722                 if (--in.nleft < 0) {
4723                         if (in.fd < 0)
4724                                 break;
4725                         i = safe_read(in.fd, buf, sizeof buf);
4726                         TRACE(("expbackq: read returns %d\n", i));
4727                         if (i <= 0)
4728                                 break;
4729                         p = buf;
4730                         in.nleft = i - 1;
4731                 }
4732                 lastc = *p++;
4733                 if (lastc != '\0') {
4734                         if (quotes && SIT(lastc, syntax) == CCTL)
4735                                 STPUTC(CTLESC, dest);
4736                         STPUTC(lastc, dest);
4737                 }
4738         }
4739
4740         /* Eat all trailing newlines */
4741         for (; dest > stackblock() && dest[-1] == '\n';)
4742                 STUNPUTC(dest);
4743
4744 err2:
4745         if (in.fd >= 0)
4746                 close(in.fd);
4747         if (in.buf)
4748                 ckfree(in.buf);
4749         if (in.jp)
4750                 exitstatus = waitforjob(in.jp);
4751         handler = savehandler;
4752         if (ex) {
4753                 longjmp(handler->loc, 1);
4754         }
4755         if (quoted == 0)
4756                 recordregion(startloc, dest - stackblock(), 0);
4757         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4758                 (dest - stackblock()) - startloc,
4759                 (dest - stackblock()) - startloc,
4760                 stackblock() + startloc));
4761         expdest = dest;
4762         INTON;
4763 }
4764
4765 static int
4766 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
4767 {
4768         char *startp;
4769         char *loc = NULL;
4770         char *q;
4771         int c = 0;
4772         int saveherefd = herefd;
4773         struct nodelist *saveargbackq = argbackq;
4774         int amount;
4775
4776         herefd = -1;
4777         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4778         STACKSTRNUL(expdest);
4779         herefd = saveherefd;
4780         argbackq = saveargbackq;
4781         startp = stackblock() + startloc;
4782         if (str == NULL)
4783             str = stackblock() + strloc;
4784
4785         switch (subtype) {
4786         case VSASSIGN:
4787                 setvar(str, startp, 0);
4788                 amount = startp - expdest;
4789                 STADJUST(amount, expdest);
4790                 varflags &= ~VSNUL;
4791                 if (c != 0)
4792                         *loc = c;
4793                 return 1;
4794
4795         case VSQUESTION:
4796                 if (*p != CTLENDVAR) {
4797                         out2fmt(snlfmt, startp);
4798                         error((char *)NULL);
4799                 }
4800                 error("%.*s: parameter %snot set", p - str - 1,
4801                       str, (varflags & VSNUL) ? "null or "
4802                                               : nullstr);
4803                 /* NOTREACHED */
4804
4805         case VSTRIMLEFT:
4806                 for (loc = startp; loc < str; loc++) {
4807                         c = *loc;
4808                         *loc = '\0';
4809                         if (patmatch2(str, startp, quotes))
4810                                 goto recordleft;
4811                         *loc = c;
4812                         if (quotes && *loc == CTLESC)
4813                                 loc++;
4814                 }
4815                 return 0;
4816
4817         case VSTRIMLEFTMAX:
4818                 for (loc = str - 1; loc >= startp;) {
4819                         c = *loc;
4820                         *loc = '\0';
4821                         if (patmatch2(str, startp, quotes))
4822                                 goto recordleft;
4823                         *loc = c;
4824                         loc--;
4825                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4826                                 for (q = startp; q < loc; q++)
4827                                         if (*q == CTLESC)
4828                                                 q++;
4829                                 if (q > loc)
4830                                         loc--;
4831                         }
4832                 }
4833                 return 0;
4834
4835         case VSTRIMRIGHT:
4836                 for (loc = str - 1; loc >= startp;) {
4837                         if (patmatch2(str, loc, quotes))
4838                                 goto recordright;
4839                         loc--;
4840                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4841                                 for (q = startp; q < loc; q++)
4842                                         if (*q == CTLESC)
4843                                                 q++;
4844                                 if (q > loc)
4845                                         loc--;
4846                         }
4847                 }
4848                 return 0;
4849
4850         case VSTRIMRIGHTMAX:
4851                 for (loc = startp; loc < str - 1; loc++) {
4852                         if (patmatch2(str, loc, quotes))
4853                                 goto recordright;
4854                         if (quotes && *loc == CTLESC)
4855                                 loc++;
4856                 }
4857                 return 0;
4858
4859 #ifdef DEBUG
4860         default:
4861                 abort();
4862 #endif
4863         }
4864
4865 recordleft:
4866         *loc = c;
4867         amount = ((str - 1) - (loc - startp)) - expdest;
4868         STADJUST(amount, expdest);
4869         while (loc != str - 1)
4870                 *startp++ = *loc++;
4871         return 1;
4872
4873 recordright:
4874         amount = loc - expdest;
4875         STADJUST(amount, expdest);
4876         STPUTC('\0', expdest);
4877         STADJUST(-1, expdest);
4878         return 1;
4879 }
4880
4881
4882 /*
4883  * Test whether a specialized variable is set.
4884  */
4885
4886 static int
4887 varisset(char *name, int nulok)
4888 {
4889         if (*name == '!')
4890                 return backgndpid != -1;
4891         else if (*name == '@' || *name == '*') {
4892                 if (*shellparam.p == NULL)
4893                         return 0;
4894
4895                 if (nulok) {
4896                         char **av;
4897
4898                         for (av = shellparam.p; *av; av++)
4899                                 if (**av != '\0')
4900                                         return 1;
4901                         return 0;
4902                 }
4903         } else if (is_digit(*name)) {
4904                 char *ap;
4905                 int num = atoi(name);
4906
4907                 if (num > shellparam.nparam)
4908                         return 0;
4909
4910                 if (num == 0)
4911                         ap = arg0;
4912                 else
4913                         ap = shellparam.p[num - 1];
4914
4915                 if (nulok && (ap == NULL || *ap == '\0'))
4916                         return 0;
4917         }
4918         return 1;
4919 }
4920
4921 /*
4922  * Put a string on the stack.
4923  */
4924
4925 static void
4926 strtodest(const char *p, int syntax, int quotes)
4927 {
4928         while (*p) {
4929                 if (quotes && SIT(*p,syntax) == CCTL)
4930                         STPUTC(CTLESC, expdest);
4931                 STPUTC(*p++, expdest);
4932         }
4933 }
4934
4935 /*
4936  * Add the value of a specialized variable to the stack string.
4937  */
4938
4939 static inline void
4940 varvalue(char *name, int quoted, int flags)
4941 {
4942         int num;
4943         char *p;
4944         int i;
4945         int sep;
4946         int sepq = 0;
4947         char **ap;
4948         int syntax;
4949         int allow_split = flags & EXP_FULL;
4950         int quotes = flags & (EXP_FULL | EXP_CASE);
4951
4952         syntax = quoted ? DQSYNTAX : BASESYNTAX;
4953         switch (*name) {
4954         case '$':
4955                 num = rootpid;
4956                 goto numvar;
4957         case '?':
4958                 num = oexitstatus;
4959                 goto numvar;
4960         case '#':
4961                 num = shellparam.nparam;
4962                 goto numvar;
4963         case '!':
4964                 num = backgndpid;
4965 numvar:
4966                 expdest = cvtnum(num, expdest);
4967                 break;
4968         case '-':
4969                 for (i = 0 ; i < NOPTS ; i++) {
4970                         if (optent_val(i))
4971                                 STPUTC(optent_letter(optlist[i]), expdest);
4972                 }
4973                 break;
4974         case '@':
4975                 if (allow_split && quoted) {
4976                         sep = 1 << CHAR_BIT;
4977                         goto param;
4978                 }
4979                 /* fall through */
4980         case '*':
4981                 sep = ifsset() ? ifsval()[0] : ' ';
4982                 if (quotes) {
4983                         sepq = SIT(sep,syntax) == CCTL;
4984                 }
4985 param:
4986                 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
4987                         strtodest(p, syntax, quotes);
4988                         if (*ap && sep) {
4989                                 if (sepq)
4990                                         STPUTC(CTLESC, expdest);
4991                                 STPUTC(sep, expdest);
4992                         }
4993                 }
4994                 break;
4995         case '0':
4996                 strtodest(arg0, syntax, quotes);
4997                 break;
4998         default:
4999                 num = atoi(name);
5000                 if (num > 0 && num <= shellparam.nparam) {
5001                         strtodest(shellparam.p[num - 1], syntax, quotes);
5002                 }
5003                 break;
5004         }
5005 }
5006
5007
5008 /*
5009  * Record the fact that we have to scan this region of the
5010  * string for IFS characters.
5011  */
5012
5013 static void
5014 recordregion(int start, int end, int nulonly)
5015 {
5016         struct ifsregion *ifsp;
5017
5018         if (ifslastp == NULL) {
5019                 ifsp = &ifsfirst;
5020         } else {
5021                 INTOFF;
5022                 ifsp = (struct ifsregion *)xmalloc(sizeof (struct ifsregion));
5023                 ifsp->next = NULL;
5024                 ifslastp->next = ifsp;
5025                 INTON;
5026         }
5027         ifslastp = ifsp;
5028         ifslastp->begoff = start;
5029         ifslastp->endoff = end;
5030         ifslastp->nulonly = nulonly;
5031 }
5032
5033
5034
5035 /*
5036  * Break the argument string into pieces based upon IFS and add the
5037  * strings to the argument list.  The regions of the string to be
5038  * searched for IFS characters have been stored by recordregion.
5039  */
5040 static void
5041 ifsbreakup(char *string, struct arglist *arglist)
5042 {
5043         struct ifsregion *ifsp;
5044         struct strlist *sp;
5045         char *start;
5046         char *p;
5047         char *q;
5048         const char *ifs, *realifs;
5049         int ifsspc;
5050         int nulonly;
5051
5052
5053         start = string;
5054         ifsspc = 0;
5055         nulonly = 0;
5056         realifs = ifsset() ? ifsval() : defifs;
5057         if (ifslastp != NULL) {
5058                 ifsp = &ifsfirst;
5059                 do {
5060                         p = string + ifsp->begoff;
5061                         nulonly = ifsp->nulonly;
5062                         ifs = nulonly ? nullstr : realifs;
5063                         ifsspc = 0;
5064                         while (p < string + ifsp->endoff) {
5065                                 q = p;
5066                                 if (*p == CTLESC)
5067                                         p++;
5068                                 if (strchr(ifs, *p)) {
5069                                         if (!nulonly)
5070                                                 ifsspc = (strchr(defifs, *p) != NULL);
5071                                         /* Ignore IFS whitespace at start */
5072                                         if (q == start && ifsspc) {
5073                                                 p++;
5074                                                 start = p;
5075                                                 continue;
5076                                         }
5077                                         *q = '\0';
5078                                         sp = (struct strlist *)stalloc(sizeof *sp);
5079                                         sp->text = start;
5080                                         *arglist->lastp = sp;
5081                                         arglist->lastp = &sp->next;
5082                                         p++;
5083                                         if (!nulonly) {
5084                                                 for (;;) {
5085                                                         if (p >= string + ifsp->endoff) {
5086                                                                 break;
5087                                                         }
5088                                                         q = p;
5089                                                         if (*p == CTLESC)
5090                                                                 p++;
5091                                                         if (strchr(ifs, *p) == NULL ) {
5092                                                                 p = q;
5093                                                                 break;
5094                                                         } else if (strchr(defifs, *p) == NULL) {
5095                                                                 if (ifsspc) {
5096                                                                         p++;
5097                                                                         ifsspc = 0;
5098                                                                 } else {
5099                                                                         p = q;
5100                                                                         break;
5101                                                                 }
5102                                                         } else
5103                                                                 p++;
5104                                                 }
5105                                         }
5106                                         start = p;
5107                                 } else
5108                                         p++;
5109                         }
5110                 } while ((ifsp = ifsp->next) != NULL);
5111                 if (!(*start || (!ifsspc && start > string && nulonly))) {
5112                         return;
5113                 }
5114         }
5115
5116         sp = (struct strlist *)stalloc(sizeof *sp);
5117         sp->text = start;
5118         *arglist->lastp = sp;
5119         arglist->lastp = &sp->next;
5120 }
5121
5122 static void
5123 ifsfree(void)
5124 {
5125         while (ifsfirst.next != NULL) {
5126                 struct ifsregion *ifsp;
5127                 INTOFF;
5128                 ifsp = ifsfirst.next->next;
5129                 ckfree(ifsfirst.next);
5130                 ifsfirst.next = ifsp;
5131                 INTON;
5132         }
5133         ifslastp = NULL;
5134         ifsfirst.next = NULL;
5135 }
5136
5137 /*
5138  * Add a file name to the list.
5139  */
5140
5141 static void
5142 addfname(const char *name)
5143 {
5144         char *p;
5145         struct strlist *sp;
5146
5147         p = sstrdup(name);
5148         sp = (struct strlist *)stalloc(sizeof *sp);
5149         sp->text = p;
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         INTOFF;
6310         status = waitforjob(jp);
6311         INTON;
6312         return status;
6313 }
6314
6315
6316 static int
6317 bgcmd(int argc, char **argv)
6318 {
6319         struct job *jp;
6320
6321         do {
6322                 jp = getjob(*++argv);
6323                 if (jp->jobctl == 0)
6324                         error("job not created under job control");
6325                 restartjob(jp);
6326         } while (--argc > 1);
6327         return 0;
6328 }
6329
6330
6331 static void
6332 restartjob(struct job *jp)
6333 {
6334         struct procstat *ps;
6335         int i;
6336
6337         if (jp->state == JOBDONE)
6338                 return;
6339         INTOFF;
6340         killpg(jp->ps[0].pid, SIGCONT);
6341         for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6342                 if (WIFSTOPPED(ps->status)) {
6343                         ps->status = -1;
6344                         jp->state = 0;
6345                 }
6346         }
6347         INTON;
6348 }
6349 #endif
6350
6351 static void showjobs(int change);
6352
6353
6354 static int
6355 jobscmd(int argc, char **argv)
6356 {
6357         showjobs(0);
6358         return 0;
6359 }
6360
6361
6362 /*
6363  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6364  * statuses have changed since the last call to showjobs.
6365  *
6366  * If the shell is interrupted in the process of creating a job, the
6367  * result may be a job structure containing zero processes.  Such structures
6368  * will be freed here.
6369  */
6370
6371 static void
6372 showjobs(int change)
6373 {
6374         int jobno;
6375         int procno;
6376         int i;
6377         struct job *jp;
6378         struct procstat *ps;
6379         int col;
6380         char s[64];
6381
6382         TRACE(("showjobs(%d) called\n", change));
6383         while (dowait(0, (struct job *)NULL) > 0);
6384         for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6385                 if (! jp->used)
6386                         continue;
6387                 if (jp->nprocs == 0) {
6388                         freejob(jp);
6389                         continue;
6390                 }
6391                 if (change && ! jp->changed)
6392                         continue;
6393                 procno = jp->nprocs;
6394                 for (ps = jp->ps ; ; ps++) {    /* for each process */
6395                         if (ps == jp->ps)
6396                                 snprintf(s, 64, "[%d] %ld ", jobno,
6397                                     (long)ps->pid);
6398                         else
6399                                 snprintf(s, 64, "    %ld ",
6400                                     (long)ps->pid);
6401                         out1str(s);
6402                         col = strlen(s);
6403                         s[0] = '\0';
6404                         if (ps->status == -1) {
6405                                 /* don't print anything */
6406                         } else if (WIFEXITED(ps->status)) {
6407                                 snprintf(s, 64, "Exit %d",
6408                                        WEXITSTATUS(ps->status));
6409                         } else {
6410 #ifdef JOBS
6411                                 if (WIFSTOPPED(ps->status))
6412                                         i = WSTOPSIG(ps->status);
6413                                 else /* WIFSIGNALED(ps->status) */
6414 #endif
6415                                         i = WTERMSIG(ps->status);
6416                                 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6417                                         strcpy(s, sys_siglist[i & 0x7F]);
6418                                 else
6419                                         snprintf(s, 64, "Signal %d", i & 0x7F);
6420                                 if (WCOREDUMP(ps->status))
6421                                         strcat(s, " (core dumped)");
6422                         }
6423                         out1str(s);
6424                         col += strlen(s);
6425                         printf(
6426                                 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6427                                 ps->cmd
6428                         );
6429                         if (--procno <= 0)
6430                                 break;
6431                 }
6432                 jp->changed = 0;
6433                 if (jp->state == JOBDONE) {
6434                         freejob(jp);
6435                 }
6436         }
6437 }
6438
6439
6440 /*
6441  * Mark a job structure as unused.
6442  */
6443
6444 static void
6445 freejob(struct job *jp)
6446 {
6447         const struct procstat *ps;
6448         int i;
6449
6450         INTOFF;
6451         for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6452                 if (ps->cmd != nullstr)
6453                         ckfree(ps->cmd);
6454         }
6455         if (jp->ps != &jp->ps0)
6456                 ckfree(jp->ps);
6457         jp->used = 0;
6458 #ifdef JOBS
6459         if (curjob == jp - jobtab + 1)
6460                 curjob = 0;
6461 #endif
6462         INTON;
6463 }
6464
6465
6466
6467 static int
6468 waitcmd(int argc, char **argv)
6469 {
6470         struct job *job;
6471         int status, retval;
6472         struct job *jp;
6473
6474         if (--argc > 0) {
6475 start:
6476                 job = getjob(*++argv);
6477         } else {
6478                 job = NULL;
6479         }
6480         for (;;) {      /* loop until process terminated or stopped */
6481                 if (job != NULL) {
6482                         if (job->state) {
6483                                 status = job->ps[job->nprocs - 1].status;
6484                                 if (! iflag)
6485                                         freejob(job);
6486                                 if (--argc) {
6487                                         goto start;
6488                                 }
6489                                 if (WIFEXITED(status))
6490                                         retval = WEXITSTATUS(status);
6491 #ifdef JOBS
6492                                 else if (WIFSTOPPED(status))
6493                                         retval = WSTOPSIG(status) + 128;
6494 #endif
6495                                 else {
6496                                         /* XXX: limits number of signals */
6497                                         retval = WTERMSIG(status) + 128;
6498                                 }
6499                                 return retval;
6500                         }
6501                 } else {
6502                         for (jp = jobtab ; ; jp++) {
6503                                 if (jp >= jobtab + njobs) {     /* no running procs */
6504                                         return 0;
6505                                 }
6506                                 if (jp->used && jp->state == 0)
6507                                         break;
6508                         }
6509                 }
6510                 if (dowait(2, 0) < 0 && errno == EINTR) {
6511                         return 129;
6512                 }
6513         }
6514 }
6515
6516
6517
6518 /*
6519  * Convert a job name to a job structure.
6520  */
6521
6522 static struct job *
6523 getjob(const char *name)
6524 {
6525         int jobno;
6526         struct job *jp;
6527         int pid;
6528         int i;
6529
6530         if (name == NULL) {
6531 #ifdef JOBS
6532 currentjob:
6533                 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6534                         error("No current job");
6535                 return &jobtab[jobno - 1];
6536 #else
6537                 error("No current job");
6538 #endif
6539         } else if (name[0] == '%') {
6540                 if (is_digit(name[1])) {
6541                         jobno = number(name + 1);
6542                         if (jobno > 0 && jobno <= njobs
6543                          && jobtab[jobno - 1].used != 0)
6544                                 return &jobtab[jobno - 1];
6545 #ifdef JOBS
6546                 } else if (name[1] == '%' && name[2] == '\0') {
6547                         goto currentjob;
6548 #endif
6549                 } else {
6550                         struct job *found = NULL;
6551                         for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6552                                 if (jp->used && jp->nprocs > 0
6553                                  && prefix(name + 1, jp->ps[0].cmd)) {
6554                                         if (found)
6555                                                 error("%s: ambiguous", name);
6556                                         found = jp;
6557                                 }
6558                         }
6559                         if (found)
6560                                 return found;
6561                 }
6562         } else if (is_number(name, &pid)) {
6563                 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6564                         if (jp->used && jp->nprocs > 0
6565                          && jp->ps[jp->nprocs - 1].pid == pid)
6566                                 return jp;
6567                 }
6568         }
6569         error("No such job: %s", name);
6570         /* NOTREACHED */
6571 }
6572
6573
6574
6575 /*
6576  * Return a new job structure,
6577  */
6578
6579 static struct job *
6580 makejob(const union node *node, int nprocs)
6581 {
6582         int i;
6583         struct job *jp;
6584
6585         for (i = njobs, jp = jobtab ; ; jp++) {
6586                 if (--i < 0) {
6587                         INTOFF;
6588                         if (njobs == 0) {
6589                                 jobtab = xmalloc(4 * sizeof jobtab[0]);
6590                         } else {
6591                                 jp = xmalloc((njobs + 4) * sizeof jobtab[0]);
6592                                 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6593                                 /* Relocate `ps' pointers */
6594                                 for (i = 0; i < njobs; i++)
6595                                         if (jp[i].ps == &jobtab[i].ps0)
6596                                                 jp[i].ps = &jp[i].ps0;
6597                                 ckfree(jobtab);
6598                                 jobtab = jp;
6599                         }
6600                         jp = jobtab + njobs;
6601                         for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
6602                         INTON;
6603                         break;
6604                 }
6605                 if (jp->used == 0)
6606                         break;
6607         }
6608         INTOFF;
6609         jp->state = 0;
6610         jp->used = 1;
6611         jp->changed = 0;
6612         jp->nprocs = 0;
6613 #ifdef JOBS
6614         jp->jobctl = jobctl;
6615 #endif
6616         if (nprocs > 1) {
6617                 jp->ps = xmalloc(nprocs * sizeof (struct procstat));
6618         } else {
6619                 jp->ps = &jp->ps0;
6620         }
6621         INTON;
6622         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
6623             jp - jobtab + 1));
6624         return jp;
6625 }
6626
6627
6628 /*
6629  * Fork of a subshell.  If we are doing job control, give the subshell its
6630  * own process group.  Jp is a job structure that the job is to be added to.
6631  * N is the command that will be evaluated by the child.  Both jp and n may
6632  * be NULL.  The mode parameter can be one of the following:
6633  *      FORK_FG - Fork off a foreground process.
6634  *      FORK_BG - Fork off a background process.
6635  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
6636  *                   process group even if job control is on.
6637  *
6638  * When job control is turned off, background processes have their standard
6639  * input redirected to /dev/null (except for the second and later processes
6640  * in a pipeline).
6641  */
6642
6643
6644
6645 static int
6646 forkshell(struct job *jp, const union node *n, int mode)
6647 {
6648         int pid;
6649 #ifdef JOBS
6650         int pgrp;
6651 #endif
6652         const char *devnull = _PATH_DEVNULL;
6653         const char *nullerr = "Can't open %s";
6654
6655         TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
6656             mode));
6657         INTOFF;
6658 #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
6659         pid = fork();
6660 #else
6661         pid = vfork();
6662 #endif
6663         if (pid == -1) {
6664                 TRACE(("Fork failed, errno=%d\n", errno));
6665                 INTON;
6666                 error("Cannot fork");
6667         }
6668         if (pid == 0) {
6669                 struct job *p;
6670                 int wasroot;
6671                 int i;
6672
6673                 TRACE(("Child shell %d\n", getpid()));
6674                 wasroot = rootshell;
6675                 rootshell = 0;
6676                 closescript();
6677                 INTON;
6678                 clear_traps();
6679 #ifdef JOBS
6680                 jobctl = 0;             /* do job control only in root shell */
6681                 if (wasroot && mode != FORK_NOJOB && mflag) {
6682                         if (jp == NULL || jp->nprocs == 0)
6683                                 pgrp = getpid();
6684                         else
6685                                 pgrp = jp->ps[0].pid;
6686                         setpgid(0, pgrp);
6687                         if (mode == FORK_FG) {
6688                                 /*** this causes superfluous TIOCSPGRPS ***/
6689 #ifdef OLD_TTY_DRIVER
6690                                 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
6691                                         error("TIOCSPGRP failed, errno=%d", errno);
6692 #else
6693                                 if (tcsetpgrp(2, pgrp) < 0)
6694                                         error("tcsetpgrp failed, errno=%d", errno);
6695 #endif
6696                         }
6697                         setsignal(SIGTSTP);
6698                         setsignal(SIGTTOU);
6699                 } else if (mode == FORK_BG) {
6700                         ignoresig(SIGINT);
6701                         ignoresig(SIGQUIT);
6702                         if ((jp == NULL || jp->nprocs == 0) &&
6703                             ! fd0_redirected_p ()) {
6704                                 close(0);
6705                                 if (open(devnull, O_RDONLY) != 0)
6706                                         error(nullerr, devnull);
6707                         }
6708                 }
6709 #else
6710                 if (mode == FORK_BG) {
6711                         ignoresig(SIGINT);
6712                         ignoresig(SIGQUIT);
6713                         if ((jp == NULL || jp->nprocs == 0) &&
6714                             ! fd0_redirected_p ()) {
6715                                 close(0);
6716                                 if (open(devnull, O_RDONLY) != 0)
6717                                         error(nullerr, devnull);
6718                         }
6719                 }
6720 #endif
6721                 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
6722                         if (p->used)
6723                                 freejob(p);
6724                 if (wasroot && iflag) {
6725                         setsignal(SIGINT);
6726                         setsignal(SIGQUIT);
6727                         setsignal(SIGTERM);
6728                 }
6729                 return pid;
6730         }
6731 #ifdef JOBS
6732         if (rootshell && mode != FORK_NOJOB && mflag) {
6733                 if (jp == NULL || jp->nprocs == 0)
6734                         pgrp = pid;
6735                 else
6736                         pgrp = jp->ps[0].pid;
6737                 setpgid(pid, pgrp);
6738         }
6739 #endif
6740         if (mode == FORK_BG)
6741                 backgndpid = pid;               /* set $! */
6742         if (jp) {
6743                 struct procstat *ps = &jp->ps[jp->nprocs++];
6744                 ps->pid = pid;
6745                 ps->status = -1;
6746                 ps->cmd = nullstr;
6747                 if (iflag && rootshell && n)
6748                         ps->cmd = commandtext(n);
6749         }
6750         INTON;
6751         TRACE(("In parent shell:  child = %d\n", pid));
6752         return pid;
6753 }
6754
6755
6756
6757 /*
6758  * Wait for job to finish.
6759  *
6760  * Under job control we have the problem that while a child process is
6761  * running interrupts generated by the user are sent to the child but not
6762  * to the shell.  This means that an infinite loop started by an inter-
6763  * active user may be hard to kill.  With job control turned off, an
6764  * interactive user may place an interactive program inside a loop.  If
6765  * the interactive program catches interrupts, the user doesn't want
6766  * these interrupts to also abort the loop.  The approach we take here
6767  * is to have the shell ignore interrupt signals while waiting for a
6768  * forground process to terminate, and then send itself an interrupt
6769  * signal if the child process was terminated by an interrupt signal.
6770  * Unfortunately, some programs want to do a bit of cleanup and then
6771  * exit on interrupt; unless these processes terminate themselves by
6772  * sending a signal to themselves (instead of calling exit) they will
6773  * confuse this approach.
6774  */
6775
6776 static int
6777 waitforjob(struct job *jp)
6778 {
6779 #ifdef JOBS
6780         int mypgrp = getpgrp();
6781 #endif
6782         int status;
6783         int st;
6784         struct sigaction act, oact;
6785
6786         INTOFF;
6787         intreceived = 0;
6788 #ifdef JOBS
6789         if (!jobctl) {
6790 #else
6791         if (!iflag) {
6792 #endif
6793                 sigaction(SIGINT, 0, &act);
6794                 act.sa_handler = waitonint;
6795                 sigaction(SIGINT, &act, &oact);
6796         }
6797         TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
6798         while (jp->state == 0) {
6799                 dowait(1, jp);
6800         }
6801 #ifdef JOBS
6802         if (!jobctl) {
6803 #else
6804         if (!iflag) {
6805 #endif
6806                 sigaction(SIGINT, &oact, 0);
6807                 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
6808         }
6809 #ifdef JOBS
6810         if (jp->jobctl) {
6811 #ifdef OLD_TTY_DRIVER
6812                 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
6813                         error("TIOCSPGRP failed, errno=%d\n", errno);
6814 #else
6815                 if (tcsetpgrp(2, mypgrp) < 0)
6816                         error("tcsetpgrp failed, errno=%d\n", errno);
6817 #endif
6818         }
6819         if (jp->state == JOBSTOPPED)
6820                 curjob = jp - jobtab + 1;
6821 #endif
6822         status = jp->ps[jp->nprocs - 1].status;
6823         /* convert to 8 bits */
6824         if (WIFEXITED(status))
6825                 st = WEXITSTATUS(status);
6826 #ifdef JOBS
6827         else if (WIFSTOPPED(status))
6828                 st = WSTOPSIG(status) + 128;
6829 #endif
6830         else
6831                 st = WTERMSIG(status) + 128;
6832 #ifdef JOBS
6833         if (jp->jobctl) {
6834                 /*
6835                  * This is truly gross.
6836                  * If we're doing job control, then we did a TIOCSPGRP which
6837                  * caused us (the shell) to no longer be in the controlling
6838                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
6839                  * intuit from the subprocess exit status whether a SIGINT
6840                  * occured, and if so interrupt ourselves.  Yuck.  - mycroft
6841                  */
6842                 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
6843                         raise(SIGINT);
6844         }
6845         if (jp->state == JOBDONE)
6846
6847 #endif
6848                 freejob(jp);
6849         INTON;
6850         return st;
6851 }
6852
6853
6854
6855 /*
6856  * Wait for a process to terminate.
6857  */
6858
6859 /*
6860  * Do a wait system call.  If job control is compiled in, we accept
6861  * stopped processes.  If block is zero, we return a value of zero
6862  * rather than blocking.
6863  *
6864  * System V doesn't have a non-blocking wait system call.  It does
6865  * have a SIGCLD signal that is sent to a process when one of it's
6866  * children dies.  The obvious way to use SIGCLD would be to install
6867  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
6868  * was received, and have waitproc bump another counter when it got
6869  * the status of a process.  Waitproc would then know that a wait
6870  * system call would not block if the two counters were different.
6871  * This approach doesn't work because if a process has children that
6872  * have not been waited for, System V will send it a SIGCLD when it
6873  * installs a signal handler for SIGCLD.  What this means is that when
6874  * a child exits, the shell will be sent SIGCLD signals continuously
6875  * until is runs out of stack space, unless it does a wait call before
6876  * restoring the signal handler.  The code below takes advantage of
6877  * this (mis)feature by installing a signal handler for SIGCLD and
6878  * then checking to see whether it was called.  If there are any
6879  * children to be waited for, it will be.
6880  *
6881  */
6882
6883 static inline int
6884 waitproc(int block, int *status)
6885 {
6886         int flags;
6887
6888         flags = 0;
6889 #ifdef JOBS
6890         if (jobctl)
6891                 flags |= WUNTRACED;
6892 #endif
6893         if (block == 0)
6894                 flags |= WNOHANG;
6895         return wait3(status, flags, (struct rusage *)NULL);
6896 }
6897
6898 static int
6899 dowait(int block, struct job *job)
6900 {
6901         int pid;
6902         int status;
6903         struct procstat *sp;
6904         struct job *jp;
6905         struct job *thisjob;
6906         int done;
6907         int stopped;
6908         int core;
6909         int sig;
6910
6911         TRACE(("dowait(%d) called\n", block));
6912         do {
6913                 pid = waitproc(block, &status);
6914                 TRACE(("wait returns %d, status=%d\n", pid, status));
6915         } while (!(block & 2) && pid == -1 && errno == EINTR);
6916         if (pid <= 0)
6917                 return pid;
6918         INTOFF;
6919         thisjob = NULL;
6920         for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
6921                 if (jp->used) {
6922                         done = 1;
6923                         stopped = 1;
6924                         for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
6925                                 if (sp->pid == -1)
6926                                         continue;
6927                                 if (sp->pid == pid) {
6928                                         TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
6929                                         sp->status = status;
6930                                         thisjob = jp;
6931                                 }
6932                                 if (sp->status == -1)
6933                                         stopped = 0;
6934                                 else if (WIFSTOPPED(sp->status))
6935                                         done = 0;
6936                         }
6937                         if (stopped) {          /* stopped or done */
6938                                 int state = done? JOBDONE : JOBSTOPPED;
6939                                 if (jp->state != state) {
6940                                         TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
6941                                         jp->state = state;
6942 #ifdef JOBS
6943                                         if (done && curjob == jp - jobtab + 1)
6944                                                 curjob = 0;             /* no current job */
6945 #endif
6946                                 }
6947                         }
6948                 }
6949         }
6950         INTON;
6951         if (! rootshell || ! iflag || (job && thisjob == job)) {
6952                 core = WCOREDUMP(status);
6953 #ifdef JOBS
6954                 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
6955                 else
6956 #endif
6957                 if (WIFEXITED(status)) sig = 0;
6958                 else sig = WTERMSIG(status);
6959
6960                 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
6961                         if (thisjob != job)
6962                                 out2fmt("%d: ", pid);
6963 #ifdef JOBS
6964                         if (sig == SIGTSTP && rootshell && iflag)
6965                                 out2fmt("%%%ld ",
6966                                     (long)(job - jobtab + 1));
6967 #endif
6968                         if (sig < NSIG && sys_siglist[sig])
6969                                 out2str(sys_siglist[sig]);
6970                         else
6971                                 out2fmt("Signal %d", sig);
6972                         if (core)
6973                                 out2str(" - core dumped");
6974                         out2c('\n');
6975                 } else {
6976                         TRACE(("Not printing status: status=%d, sig=%d\n",
6977                                status, sig));
6978                 }
6979         } else {
6980                 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
6981                 if (thisjob)
6982                         thisjob->changed = 1;
6983         }
6984         return pid;
6985 }
6986
6987
6988
6989
6990 /*
6991  * return 1 if there are stopped jobs, otherwise 0
6992  */
6993 static int
6994 stoppedjobs(void)
6995 {
6996         int jobno;
6997         struct job *jp;
6998
6999         if (job_warning)
7000                 return (0);
7001         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7002                 if (jp->used == 0)
7003                         continue;
7004                 if (jp->state == JOBSTOPPED) {
7005                         out2str("You have stopped jobs.\n");
7006                         job_warning = 2;
7007                         return (1);
7008                 }
7009         }
7010
7011         return (0);
7012 }
7013
7014 /*
7015  * Return a string identifying a command (to be printed by the
7016  * jobs command.
7017  */
7018
7019 static char *cmdnextc;
7020 static int cmdnleft;
7021 #define MAXCMDTEXT      200
7022
7023 static void
7024 cmdputs(const char *s)
7025 {
7026         const char *p;
7027         char *q;
7028         char c;
7029         int subtype = 0;
7030
7031         if (cmdnleft <= 0)
7032                 return;
7033         p = s;
7034         q = cmdnextc;
7035         while ((c = *p++) != '\0') {
7036                 if (c == CTLESC)
7037                         *q++ = *p++;
7038                 else if (c == CTLVAR) {
7039                         *q++ = '$';
7040                         if (--cmdnleft > 0)
7041                                 *q++ = '{';
7042                         subtype = *p++;
7043                 } else if (c == '=' && subtype != 0) {
7044                         *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7045                         subtype = 0;
7046                 } else if (c == CTLENDVAR) {
7047                         *q++ = '}';
7048                 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7049                         cmdnleft++;             /* ignore it */
7050                 else
7051                         *q++ = c;
7052                 if (--cmdnleft <= 0) {
7053                         *q++ = '.';
7054                         *q++ = '.';
7055                         *q++ = '.';
7056                         break;
7057                 }
7058         }
7059         cmdnextc = q;
7060 }
7061
7062 #define CMDTXT_TABLE
7063 #ifdef CMDTXT_TABLE
7064 /*
7065  * To collect a lot of redundant code in cmdtxt() case statements, we
7066  * implement a mini language here.  Each type of node struct has an
7067  * associated instruction sequence that operates on its members via
7068  * their offsets.  The instruction are pack in unsigned chars with
7069  * format   IIDDDDDE   where the bits are
7070  *   I : part of the instruction opcode, which are
7071  *       00 : member is a pointer to another node -- process it recursively
7072  *       40 : member is a pointer to a char string -- output it
7073  *       80 : output the string whose index is stored in the data field
7074  *       CC : flag signaling that this case needs external processing
7075  *   D : data - either the (shifted) index of a fixed string to output or
7076  *              the actual offset of the member to operate on in the struct
7077  *              (since we assume bit 0 is set, the offset is not shifted)
7078  *   E : flag signaling end of instruction sequence
7079  *
7080  * WARNING: In order to handle larger offsets for 64bit archs, this code
7081  *          assumes that no offset can be an odd number and stores the
7082  *          end-of-instructions flag in bit 0.
7083  */
7084
7085 #define CMDTXT_NOMORE      0x01 /* NOTE: no offset should be odd */
7086 #define CMDTXT_CHARPTR     0x40
7087 #define CMDTXT_STRING      0x80
7088 #define CMDTXT_SPECIAL     0xC0
7089 #define CMDTXT_OFFSETMASK  0x3E
7090
7091 static const char * const cmdtxt_strings[] = {
7092  /* 0     1    2    3       4       5      6          7     */
7093         "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
7094  /* 8         9        10       11        12      13       */
7095     "while ", "; do ", "; done", "until ", "for ", " in ...",
7096  /* 14       15     16        17     */
7097         "case ", "???", "() ...", "<<..."
7098 };
7099
7100 static const char * const redir_strings[] = {
7101         ">", "<", "<>", ">>", ">|", ">&", "<&"
7102 };
7103
7104 static const unsigned char cmdtxt_ops[] = {
7105 #define CMDTXT_NSEMI    0
7106         offsetof(union node, nbinary.ch1),
7107         0|CMDTXT_STRING,
7108         offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7109 #define CMDTXT_NCMD     (CMDTXT_NSEMI + 3)
7110 #define CMDTXT_NPIPE    (CMDTXT_NCMD)
7111 #define  CMDTXT_NCASE    (CMDTXT_NCMD)
7112 #define  CMDTXT_NTO      (CMDTXT_NCMD)
7113 #define  CMDTXT_NFROM    (CMDTXT_NCMD)
7114 #define  CMDTXT_NFROMTO  (CMDTXT_NCMD)
7115 #define  CMDTXT_NAPPEND  (CMDTXT_NCMD)
7116 #define  CMDTXT_NTOOV    (CMDTXT_NCMD)
7117 #define  CMDTXT_NTOFD    (CMDTXT_NCMD)
7118 #define  CMDTXT_NFROMFD  (CMDTXT_NCMD)
7119         CMDTXT_SPECIAL,
7120 #define CMDTXT_NREDIR   (CMDTXT_NPIPE + 1)
7121 #define CMDTXT_NBACKGND (CMDTXT_NREDIR)
7122         offsetof(union node, nredir.n)|CMDTXT_NOMORE,
7123 #define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
7124         (1*2)|CMDTXT_STRING,
7125         offsetof(union node, nredir.n),
7126         (2*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7127 #define CMDTXT_NAND     (CMDTXT_NSUBSHELL + 3)
7128         offsetof(union node, nbinary.ch1),
7129         (3*2)|CMDTXT_STRING,
7130         offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7131 #define CMDTXT_NOR      (CMDTXT_NAND + 3)
7132         offsetof(union node, nbinary.ch1),
7133         (4*2)|CMDTXT_STRING,
7134         offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7135 #define CMDTXT_NIF      (CMDTXT_NOR + 3)
7136         (5*2)|CMDTXT_STRING,
7137         offsetof(union node, nif.test),
7138         (6*2)|CMDTXT_STRING,
7139         offsetof(union node, nif.ifpart),
7140         (7*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7141 #define CMDTXT_NWHILE   (CMDTXT_NIF + 5)
7142         (8*2)|CMDTXT_STRING,
7143         offsetof(union node, nbinary.ch1),
7144         (9*2)|CMDTXT_STRING,
7145         offsetof(union node, nbinary.ch2),
7146         (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7147 #define CMDTXT_NUNTIL   (CMDTXT_NWHILE + 5)
7148         (11*2)|CMDTXT_STRING,
7149         offsetof(union node, nbinary.ch1),
7150         (9*2)|CMDTXT_STRING,
7151         offsetof(union node, nbinary.ch2),
7152         (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7153 #define CMDTXT_NFOR     (CMDTXT_NUNTIL + 5)
7154         (12*2)|CMDTXT_STRING,
7155         offsetof(union node, nfor.var)|CMDTXT_CHARPTR,
7156         (13*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7157 #define CMDTXT_NCLIST   (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */
7158 #define  CMDTXT_NNOT     (CMDTXT_NCLIST)        /* TODO: IS THIS CORRECT??? */
7159         (15*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7160 #define CMDTXT_NDEFUN   (CMDTXT_NCLIST + 1)
7161         offsetof(union node, narg.text)|CMDTXT_CHARPTR,
7162         (16*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7163 #define CMDTXT_NARG     (CMDTXT_NDEFUN + 2)
7164         offsetof(union node, narg.text)|CMDTXT_CHARPTR|CMDTXT_NOMORE,
7165 #define CMDTXT_NHERE    (CMDTXT_NARG + 1)
7166 #define CMDTXT_NXHERE   (CMDTXT_NHERE)
7167         (17*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7168 };
7169
7170 #if CMDTXT_NXHERE != 36
7171 #error CMDTXT_NXHERE
7172 #endif
7173
7174 static const unsigned char cmdtxt_ops_index[26] = {
7175         CMDTXT_NSEMI,
7176         CMDTXT_NCMD,
7177         CMDTXT_NPIPE,
7178         CMDTXT_NREDIR,
7179         CMDTXT_NBACKGND,
7180         CMDTXT_NSUBSHELL,
7181         CMDTXT_NAND,
7182         CMDTXT_NOR,
7183         CMDTXT_NIF,
7184         CMDTXT_NWHILE,
7185         CMDTXT_NUNTIL,
7186         CMDTXT_NFOR,
7187         CMDTXT_NCASE,
7188         CMDTXT_NCLIST,
7189         CMDTXT_NDEFUN,
7190         CMDTXT_NARG,
7191         CMDTXT_NTO,
7192         CMDTXT_NFROM,
7193         CMDTXT_NFROMTO,
7194         CMDTXT_NAPPEND,
7195         CMDTXT_NTOOV,
7196         CMDTXT_NTOFD,
7197         CMDTXT_NFROMFD,
7198         CMDTXT_NHERE,
7199         CMDTXT_NXHERE,
7200         CMDTXT_NNOT,
7201 };
7202
7203 static void
7204 cmdtxt(const union node *n)
7205 {
7206         const char *p;
7207
7208         if (n == NULL)
7209                 return;
7210
7211         p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
7212         if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */
7213                 do {
7214                         if (*p & CMDTXT_STRING) { /* output fixed string */
7215                                 cmdputs(cmdtxt_strings[((int)(*p & CMDTXT_OFFSETMASK) >> 1)]);
7216                         } else {
7217                                 const char *pf = ((const char *) n)
7218                                                                   + ((int)(*p & CMDTXT_OFFSETMASK));
7219                                 if (*p & CMDTXT_CHARPTR) { /* output dynamic string */
7220                                         cmdputs(*((const char **) pf));
7221                                 } else {                /* output field */
7222                                         cmdtxt(*((const union node **) pf));
7223                                 }
7224                         }
7225                 } while (!(*p++ & CMDTXT_NOMORE));
7226         } else if (n->type == NCMD) {
7227                 union node *np;
7228                 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7229                         cmdtxt(np);
7230                         if (np->narg.next)
7231                                 cmdputs(spcstr);
7232                 }
7233                 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7234                         cmdputs(spcstr);
7235                         cmdtxt(np);
7236                 }
7237         } else if (n->type == NPIPE) {
7238                 struct nodelist *lp;
7239                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7240                         cmdtxt(lp->n);
7241                         if (lp->next)
7242                                 cmdputs(" | ");
7243                 }
7244         } else if (n->type == NCASE) {
7245                 cmdputs(cmdtxt_strings[14]);
7246                 cmdputs(n->ncase.expr->narg.text);
7247                 cmdputs(cmdtxt_strings[13]);
7248         } else {
7249 #if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7250 #error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7251 #endif
7252                 char s[2];
7253
7254 #ifdef DEBUG
7255                 assert((n->type >= NTO) && (n->type <= NFROMFD));
7256 #endif
7257
7258                 p = redir_strings[n->type - NTO];
7259                 if (n->nfile.fd != ('>' == *p)) {
7260                         s[0] = n->nfile.fd + '0';
7261                         s[1] = '\0';
7262                         cmdputs(s);
7263                 }
7264                 cmdputs(p);
7265                 if (n->type >= NTOFD) {
7266                         s[0] = n->ndup.dupfd + '0';
7267                         s[1] = '\0';
7268                         cmdputs(s);
7269                 } else {
7270                         cmdtxt(n->nfile.fname);
7271                 }
7272         }
7273 }
7274 #else  /* CMDTXT_TABLE */
7275 static void
7276 cmdtxt(const union node *n)
7277 {
7278         union node *np;
7279         struct nodelist *lp;
7280         const char *p;
7281         int i;
7282         char s[2];
7283
7284         if (n == NULL)
7285                 return;
7286         switch (n->type) {
7287         case NSEMI:
7288                 cmdtxt(n->nbinary.ch1);
7289                 cmdputs("; ");
7290                 cmdtxt(n->nbinary.ch2);
7291                 break;
7292         case NAND:
7293                 cmdtxt(n->nbinary.ch1);
7294                 cmdputs(" && ");
7295                 cmdtxt(n->nbinary.ch2);
7296                 break;
7297         case NOR:
7298                 cmdtxt(n->nbinary.ch1);
7299                 cmdputs(" || ");
7300                 cmdtxt(n->nbinary.ch2);
7301                 break;
7302         case NPIPE:
7303                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7304                         cmdtxt(lp->n);
7305                         if (lp->next)
7306                                 cmdputs(" | ");
7307                 }
7308                 break;
7309         case NSUBSHELL:
7310                 cmdputs("(");
7311                 cmdtxt(n->nredir.n);
7312                 cmdputs(")");
7313                 break;
7314         case NREDIR:
7315         case NBACKGND:
7316                 cmdtxt(n->nredir.n);
7317                 break;
7318         case NIF:
7319                 cmdputs("if ");
7320                 cmdtxt(n->nif.test);
7321                 cmdputs("; then ");
7322                 cmdtxt(n->nif.ifpart);
7323                 cmdputs("...");
7324                 break;
7325         case NWHILE:
7326                 cmdputs("while ");
7327                 goto until;
7328         case NUNTIL:
7329                 cmdputs("until ");
7330 until:
7331                 cmdtxt(n->nbinary.ch1);
7332                 cmdputs("; do ");
7333                 cmdtxt(n->nbinary.ch2);
7334                 cmdputs("; done");
7335                 break;
7336         case NFOR:
7337                 cmdputs("for ");
7338                 cmdputs(n->nfor.var);
7339                 cmdputs(" in ...");
7340                 break;
7341         case NCASE:
7342                 cmdputs("case ");
7343                 cmdputs(n->ncase.expr->narg.text);
7344                 cmdputs(" in ...");
7345                 break;
7346         case NDEFUN:
7347                 cmdputs(n->narg.text);
7348                 cmdputs("() ...");
7349                 break;
7350         case NCMD:
7351                 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7352                         cmdtxt(np);
7353                         if (np->narg.next)
7354                                 cmdputs(spcstr);
7355                 }
7356                 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7357                         cmdputs(spcstr);
7358                         cmdtxt(np);
7359                 }
7360                 break;
7361         case NARG:
7362                 cmdputs(n->narg.text);
7363                 break;
7364         case NTO:
7365                 p = ">";  i = 1;  goto redir;
7366         case NAPPEND:
7367                 p = ">>";  i = 1;  goto redir;
7368         case NTOFD:
7369                 p = ">&";  i = 1;  goto redir;
7370         case NTOOV:
7371                 p = ">|";  i = 1;  goto redir;
7372         case NFROM:
7373                 p = "<";  i = 0;  goto redir;
7374         case NFROMFD:
7375                 p = "<&";  i = 0;  goto redir;
7376         case NFROMTO:
7377                 p = "<>";  i = 0;  goto redir;
7378 redir:
7379                 if (n->nfile.fd != i) {
7380                         s[0] = n->nfile.fd + '0';
7381                         s[1] = '\0';
7382                         cmdputs(s);
7383                 }
7384                 cmdputs(p);
7385                 if (n->type == NTOFD || n->type == NFROMFD) {
7386                         s[0] = n->ndup.dupfd + '0';
7387                         s[1] = '\0';
7388                         cmdputs(s);
7389                 } else {
7390                         cmdtxt(n->nfile.fname);
7391                 }
7392                 break;
7393         case NHERE:
7394         case NXHERE:
7395                 cmdputs("<<...");
7396                 break;
7397         default:
7398                 cmdputs("???");
7399                 break;
7400         }
7401 }
7402 #endif /* CMDTXT_TABLE */
7403
7404 static char *
7405 commandtext(const union node *n)
7406 {
7407         char *name;
7408
7409         cmdnextc = name = xmalloc(MAXCMDTEXT);
7410         cmdnleft = MAXCMDTEXT - 4;
7411         cmdtxt(n);
7412         *cmdnextc = '\0';
7413         return name;
7414 }
7415
7416
7417 static void waitonint(int sig) {
7418         intreceived = 1;
7419         return;
7420 }
7421
7422 #ifdef ASH_MAIL
7423
7424 /*
7425  * Routines to check for mail.
7426  */
7427
7428
7429 #define MAXMBOXES 10
7430
7431
7432 static int nmboxes;                     /* number of mailboxes */
7433 static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
7434
7435
7436
7437 /*
7438  * Print appropriate message(s) if mail has arrived.  If the argument is
7439  * nozero, then the value of MAIL has changed, so we just update the
7440  * values.
7441  */
7442
7443 static void
7444 chkmail(int silent)
7445 {
7446         int i;
7447         const char *mpath;
7448         char *p;
7449         char *q;
7450         struct stackmark smark;
7451         struct stat statb;
7452
7453         if (silent)
7454                 nmboxes = 10;
7455         if (nmboxes == 0)
7456                 return;
7457         setstackmark(&smark);
7458         mpath = mpathset()? mpathval() : mailval();
7459         for (i = 0 ; i < nmboxes ; i++) {
7460                 p = padvance(&mpath, nullstr);
7461                 if (p == NULL)
7462                         break;
7463                 if (*p == '\0')
7464                         continue;
7465                 for (q = p ; *q ; q++);
7466 #ifdef DEBUG
7467                 if (q[-1] != '/')
7468                         abort();
7469 #endif
7470                 q[-1] = '\0';                   /* delete trailing '/' */
7471                 if (stat(p, &statb) < 0)
7472                         statb.st_size = 0;
7473                 if (statb.st_size > mailtime[i] && ! silent) {
7474                         out2fmt(snlfmt,
7475                                 pathopt? pathopt : "you have mail");
7476                 }
7477                 mailtime[i] = statb.st_size;
7478         }
7479         nmboxes = i;
7480         popstackmark(&smark);
7481 }
7482
7483 #endif /* ASH_MAIL */
7484
7485 #define PROFILE 0
7486
7487 #if PROFILE
7488 static short profile_buf[16384];
7489 extern int etext();
7490 #endif
7491
7492 static void read_profile (const char *);
7493 static void cmdloop (int);
7494 static void options (int);
7495 static void setoption (int, int);
7496 static void procargs (int, char **);
7497
7498
7499 /*
7500  * Main routine.  We initialize things, parse the arguments, execute
7501  * profiles if we're a login shell, and then call cmdloop to execute
7502  * commands.  The setjmp call sets up the location to jump to when an
7503  * exception occurs.  When an exception occurs the variable "state"
7504  * is used to figure out how far we had gotten.
7505  */
7506
7507 int
7508 ash_main(int argc, char **argv)
7509 {
7510         struct jmploc jmploc;
7511         struct stackmark smark;
7512         volatile int state;
7513         const char *shinit;
7514
7515         BLTINCMD = find_builtin("builtin");
7516         EXECCMD = find_builtin("exec");
7517         EVALCMD = find_builtin("eval");
7518
7519 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7520         unsetenv("PS1");
7521         unsetenv("PS2");
7522 #endif
7523
7524 #if PROFILE
7525         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7526 #endif
7527 #if defined(linux) || defined(__GNU__)
7528         signal(SIGCHLD, SIG_DFL);
7529 #endif
7530         state = 0;
7531         if (setjmp(jmploc.loc)) {
7532                 INTOFF;
7533                 /*
7534                  * When a shell procedure is executed, we raise the
7535                  * exception EXSHELLPROC to clean up before executing
7536                  * the shell procedure.
7537                  */
7538                 if (exception == EXSHELLPROC) {
7539                         rootpid = getpid();
7540                         rootshell = 1;
7541                         minusc = NULL;
7542                         state = 3;
7543                 } else {
7544                         if (exception == EXEXEC) {
7545                                 exitstatus = exerrno;
7546                         } else if (exception == EXERROR) {
7547                                 exitstatus = 2;
7548                         }
7549                     if (state == 0 || iflag == 0 || ! rootshell)
7550                             exitshell(exitstatus);
7551                 }
7552                 reset();
7553                 if (exception == EXINT) {
7554                         out2c('\n');
7555                 }
7556                 popstackmark(&smark);
7557                 FORCEINTON;                             /* enable interrupts */
7558                 if (state == 1)
7559                         goto state1;
7560                 else if (state == 2)
7561                         goto state2;
7562                 else if (state == 3)
7563                         goto state3;
7564                 else
7565                         goto state4;
7566         }
7567         handler = &jmploc;
7568 #ifdef DEBUG
7569         opentrace();
7570         trputs("Shell args:  ");  trargs(argv);
7571 #endif
7572         rootpid = getpid();
7573         rootshell = 1;
7574         init();
7575         setstackmark(&smark);
7576         procargs(argc, argv);
7577         if (argv[0] && argv[0][0] == '-') {
7578                 state = 1;
7579                 read_profile("/etc/profile");
7580 state1:
7581                 state = 2;
7582                 read_profile(".profile");
7583         }
7584 state2:
7585         state = 3;
7586 #ifndef linux
7587         if (getuid() == geteuid() && getgid() == getegid()) {
7588 #endif
7589                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7590                         state = 3;
7591                         read_profile(shinit);
7592                 }
7593 #ifndef linux
7594         }
7595 #endif
7596 state3:
7597         state = 4;
7598         if (sflag == 0 || minusc) {
7599                 static const char sigs[] =  {
7600                     SIGINT, SIGQUIT, SIGHUP,
7601 #ifdef SIGTSTP
7602                     SIGTSTP,
7603 #endif
7604                     SIGPIPE
7605                 };
7606 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7607                 int i;
7608
7609                 for (i = 0; i < SIGSSIZE; i++)
7610                     setsignal(sigs[i]);
7611         }
7612
7613         if (minusc)
7614                 evalstring(minusc, 0);
7615
7616         if (sflag || minusc == NULL) {
7617 state4: /* XXX ??? - why isn't this before the "if" statement */
7618                 cmdloop(1);
7619         }
7620 #if PROFILE
7621         monitor(0);
7622 #endif
7623         exitshell(exitstatus);
7624         /* NOTREACHED */
7625 }
7626
7627
7628 /*
7629  * Read and execute commands.  "Top" is nonzero for the top level command
7630  * loop; it turns on prompting if the shell is interactive.
7631  */
7632
7633 static void
7634 cmdloop(int top)
7635 {
7636         union node *n;
7637         struct stackmark smark;
7638         int inter;
7639         int numeof = 0;
7640
7641         TRACE(("cmdloop(%d) called\n", top));
7642         setstackmark(&smark);
7643         for (;;) {
7644                 if (pendingsigs)
7645                         dotrap();
7646                 inter = 0;
7647                 if (iflag && top) {
7648                         inter++;
7649                         showjobs(1);
7650 #ifdef ASH_MAIL
7651                         chkmail(0);
7652 #endif
7653                         flushall();
7654                 }
7655                 n = parsecmd(inter);
7656                 /* showtree(n); DEBUG */
7657                 if (n == NEOF) {
7658                         if (!top || numeof >= 50)
7659                                 break;
7660                         if (!stoppedjobs()) {
7661                                 if (!Iflag)
7662                                         break;
7663                                 out2str("\nUse \"exit\" to leave shell.\n");
7664                         }
7665                         numeof++;
7666                 } else if (n != NULL && nflag == 0) {
7667                         job_warning = (job_warning == 2) ? 1 : 0;
7668                         numeof = 0;
7669                         evaltree(n, 0);
7670                 }
7671                 popstackmark(&smark);
7672                 setstackmark(&smark);
7673                 if (evalskip == SKIPFILE) {
7674                         evalskip = 0;
7675                         break;
7676                 }
7677         }
7678         popstackmark(&smark);
7679 }
7680
7681
7682
7683 /*
7684  * Read /etc/profile or .profile.  Return on error.
7685  */
7686
7687 static void
7688 read_profile(const char *name)
7689 {
7690         int fd;
7691         int xflag_save;
7692         int vflag_save;
7693
7694         INTOFF;
7695         if ((fd = open(name, O_RDONLY)) >= 0)
7696                 setinputfd(fd, 1);
7697         INTON;
7698         if (fd < 0)
7699                 return;
7700         /* -q turns off -x and -v just when executing init files */
7701         /* Note: Might do a little redundant work, but reduces code size. */
7702         xflag_save = xflag;
7703         vflag_save = vflag;
7704         if (qflag)  {
7705                 vflag = xflag = 0;
7706         }
7707         cmdloop(0);
7708         xflag = xflag_save;
7709         vflag = vflag_save;
7710         popfile();
7711 }
7712
7713
7714
7715 /*
7716  * Read a file containing shell functions.
7717  */
7718
7719 static void
7720 readcmdfile(const char *name)
7721 {
7722         int fd;
7723
7724         INTOFF;
7725         if ((fd = open(name, O_RDONLY)) >= 0)
7726                 setinputfd(fd, 1);
7727         else
7728                 error("Can't open %s", name);
7729         INTON;
7730         cmdloop(0);
7731         popfile();
7732 }
7733
7734
7735
7736 /*
7737  * Take commands from a file.  To be compatable we should do a path
7738  * search for the file, which is necessary to find sub-commands.
7739  */
7740
7741 static inline char *
7742 find_dot_file(char *mybasename)
7743 {
7744         char *fullname;
7745         const char *path = pathval();
7746         struct stat statb;
7747
7748         /* don't try this for absolute or relative paths */
7749         if (strchr(mybasename, '/'))
7750                 return mybasename;
7751
7752         while ((fullname = padvance(&path, mybasename)) != NULL) {
7753                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7754                         /*
7755                          * Don't bother freeing here, since it will
7756                          * be freed by the caller.
7757                          */
7758                         return fullname;
7759                 }
7760                 stunalloc(fullname);
7761         }
7762
7763         /* not found in the PATH */
7764         error("%s: not found", mybasename);
7765         /* NOTREACHED */
7766 }
7767
7768 static int
7769 dotcmd(int argc, char **argv)
7770 {
7771         struct strlist *sp;
7772         volatile struct shparam saveparam;
7773         exitstatus = 0;
7774
7775         for (sp = cmdenviron; sp ; sp = sp->next)
7776                 setvareq(xstrdup(sp->text), VSTRFIXED|VTEXTFIXED);
7777
7778         if (argc >= 2) {                /* That's what SVR2 does */
7779                 char *fullname;
7780                 struct stackmark smark;
7781
7782                 setstackmark(&smark);
7783                 fullname = find_dot_file(argv[1]);
7784
7785                 if (argc>2) {
7786                         saveparam = shellparam;
7787                         shellparam.malloc = 0;
7788                         shellparam.nparam = argc - 2;
7789                         shellparam.p = argv + 2;
7790                 };
7791
7792                 setinputfile(fullname, 1);
7793                 commandname = fullname;
7794                 cmdloop(0);
7795                 popfile();
7796
7797                 if (argc>2) {
7798                         freeparam(&shellparam);
7799                         shellparam = saveparam;
7800                 };
7801
7802                 popstackmark(&smark);
7803         }
7804         return exitstatus;
7805 }
7806
7807
7808 static int
7809 exitcmd(int argc, char **argv)
7810 {
7811         if (stoppedjobs())
7812                 return 0;
7813         if (argc > 1)
7814                 exitstatus = number(argv[1]);
7815         else
7816                 exitstatus = oexitstatus;
7817         exitshell(exitstatus);
7818         /* NOTREACHED */
7819 }
7820
7821 static pointer
7822 stalloc(int nbytes)
7823 {
7824         char *p;
7825
7826         nbytes = ALIGN(nbytes);
7827         if (nbytes > stacknleft) {
7828                 int blocksize;
7829                 struct stack_block *sp;
7830
7831                 blocksize = nbytes;
7832                 if (blocksize < MINSIZE)
7833                         blocksize = MINSIZE;
7834                 INTOFF;
7835                 sp = xmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7836                 sp->prev = stackp;
7837                 stacknxt = sp->space;
7838                 stacknleft = blocksize;
7839                 stackp = sp;
7840                 INTON;
7841         }
7842         p = stacknxt;
7843         stacknxt += nbytes;
7844         stacknleft -= nbytes;
7845         return p;
7846 }
7847
7848
7849 static void
7850 stunalloc(pointer p)
7851 {
7852 #ifdef DEBUG
7853         if (p == NULL) {                /*DEBUG */
7854                 write(2, "stunalloc\n", 10);
7855                 abort();
7856         }
7857 #endif
7858         if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
7859                 p = stackp->space;
7860         }
7861         stacknleft += stacknxt - (char *)p;
7862         stacknxt = p;
7863 }
7864
7865
7866 static void
7867 setstackmark(struct stackmark *mark)
7868 {
7869         mark->stackp = stackp;
7870         mark->stacknxt = stacknxt;
7871         mark->stacknleft = stacknleft;
7872         mark->marknext = markp;
7873         markp = mark;
7874 }
7875
7876
7877 static void
7878 popstackmark(struct stackmark *mark)
7879 {
7880         struct stack_block *sp;
7881
7882         INTOFF;
7883         markp = mark->marknext;
7884         while (stackp != mark->stackp) {
7885                 sp = stackp;
7886                 stackp = sp->prev;
7887                 ckfree(sp);
7888         }
7889         stacknxt = mark->stacknxt;
7890         stacknleft = mark->stacknleft;
7891         INTON;
7892 }
7893
7894
7895 /*
7896  * When the parser reads in a string, it wants to stick the string on the
7897  * stack and only adjust the stack pointer when it knows how big the
7898  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
7899  * of space on top of the stack and stackblocklen returns the length of
7900  * this block.  Growstackblock will grow this space by at least one byte,
7901  * possibly moving it (like realloc).  Grabstackblock actually allocates the
7902  * part of the block that has been used.
7903  */
7904
7905 static void
7906 growstackblock(void) {
7907         char *p;
7908         int newlen = ALIGN(stacknleft * 2 + 100);
7909         char *oldspace = stacknxt;
7910         int oldlen = stacknleft;
7911         struct stack_block *sp;
7912         struct stack_block *oldstackp;
7913
7914         if (stacknxt == stackp->space && stackp != &stackbase) {
7915                 INTOFF;
7916                 oldstackp = stackp;
7917                 sp = stackp;
7918                 stackp = sp->prev;
7919                 sp = xrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
7920                 sp->prev = stackp;
7921                 stackp = sp;
7922                 stacknxt = sp->space;
7923                 stacknleft = newlen;
7924                 {
7925                   /* Stack marks pointing to the start of the old block
7926                    * must be relocated to point to the new block
7927                    */
7928                   struct stackmark *xmark;
7929                   xmark = markp;
7930                   while (xmark != NULL && xmark->stackp == oldstackp) {
7931                     xmark->stackp = stackp;
7932                     xmark->stacknxt = stacknxt;
7933                     xmark->stacknleft = stacknleft;
7934                     xmark = xmark->marknext;
7935                   }
7936                 }
7937                 INTON;
7938         } else {
7939                 p = stalloc(newlen);
7940                 memcpy(p, oldspace, oldlen);
7941                 stacknxt = p;                   /* free the space */
7942                 stacknleft += newlen;           /* we just allocated */
7943         }
7944 }
7945
7946
7947
7948 static inline void
7949 grabstackblock(int len)
7950 {
7951         len = ALIGN(len);
7952         stacknxt += len;
7953         stacknleft -= len;
7954 }
7955
7956
7957
7958 /*
7959  * The following routines are somewhat easier to use that the above.
7960  * The user declares a variable of type STACKSTR, which may be declared
7961  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
7962  * the user uses the macro STPUTC to add characters to the string.  In
7963  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
7964  * grown as necessary.  When the user is done, she can just leave the
7965  * string there and refer to it using stackblock().  Or she can allocate
7966  * the space for it using grabstackstr().  If it is necessary to allow
7967  * someone else to use the stack temporarily and then continue to grow
7968  * the string, the user should use grabstack to allocate the space, and
7969  * then call ungrabstr(p) to return to the previous mode of operation.
7970  *
7971  * USTPUTC is like STPUTC except that it doesn't check for overflow.
7972  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
7973  * is space for at least one character.
7974  */
7975
7976
7977 static char *
7978 growstackstr(void) {
7979         int len = stackblocksize();
7980         if (herefd >= 0 && len >= 1024) {
7981                 xwrite(herefd, stackblock(), len);
7982                 sstrnleft = len - 1;
7983                 return stackblock();
7984         }
7985         growstackblock();
7986         sstrnleft = stackblocksize() - len - 1;
7987         return stackblock() + len;
7988 }
7989
7990
7991 /*
7992  * Called from CHECKSTRSPACE.
7993  */
7994
7995 static char *
7996 makestrspace(size_t newlen) {
7997         int len = stackblocksize() - sstrnleft;
7998         do {
7999                 growstackblock();
8000                 sstrnleft = stackblocksize() - len;
8001         } while (sstrnleft < newlen);
8002         return stackblock() + len;
8003 }
8004
8005
8006
8007 static void
8008 ungrabstackstr(char *s, char *p)
8009 {
8010         stacknleft += stacknxt - s;
8011         stacknxt = s;
8012         sstrnleft = stacknleft - (p - s);
8013 }
8014 /*
8015  * Miscelaneous builtins.
8016  */
8017
8018
8019 #undef rflag
8020
8021 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8022 typedef long rlim_t;
8023 #endif
8024
8025
8026
8027 /*
8028  * The read builtin.  The -e option causes backslashes to escape the
8029  * following character.
8030  *
8031  * This uses unbuffered input, which may be avoidable in some cases.
8032  */
8033
8034 static int
8035 readcmd(int argc, char **argv)
8036 {
8037         char **ap;
8038         int backslash;
8039         char c;
8040         int rflag;
8041         char *prompt;
8042         const char *ifs;
8043         char *p;
8044         int startword;
8045         int status;
8046         int i;
8047
8048         rflag = 0;
8049         prompt = NULL;
8050         while ((i = nextopt("p:r")) != '\0') {
8051                 if (i == 'p')
8052                         prompt = optionarg;
8053                 else
8054                         rflag = 1;
8055         }
8056         if (prompt && isatty(0)) {
8057                 out2str(prompt);     /* read without cmdedit */
8058                 flushall();
8059         }
8060         if (*(ap = argptr) == NULL)
8061                 error("arg count");
8062         if ((ifs = bltinlookup("IFS")) == NULL)
8063                 ifs = defifs;
8064         status = 0;
8065         startword = 1;
8066         backslash = 0;
8067         STARTSTACKSTR(p);
8068         for (;;) {
8069                 if (read(0, &c, 1) != 1) {
8070                         status = 1;
8071                         break;
8072                 }
8073                 if (c == '\0')
8074                         continue;
8075                 if (backslash) {
8076                         backslash = 0;
8077                         if (c != '\n')
8078                                 STPUTC(c, p);
8079                         continue;
8080                 }
8081                 if (!rflag && c == '\\') {
8082                         backslash++;
8083                         continue;
8084                 }
8085                 if (c == '\n')
8086                         break;
8087                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8088                         continue;
8089                 }
8090                 startword = 0;
8091                 if (backslash && c == '\\') {
8092                         if (read(0, &c, 1) != 1) {
8093                                 status = 1;
8094                                 break;
8095                         }
8096                         STPUTC(c, p);
8097                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8098                         STACKSTRNUL(p);
8099                         setvar(*ap, stackblock(), 0);
8100                         ap++;
8101                         startword = 1;
8102                         STARTSTACKSTR(p);
8103                 } else {
8104                         STPUTC(c, p);
8105                 }
8106         }
8107         STACKSTRNUL(p);
8108         /* Remove trailing blanks */
8109         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8110                 *p = '\0';
8111         setvar(*ap, stackblock(), 0);
8112         while (*++ap != NULL)
8113                 setvar(*ap, nullstr, 0);
8114         return status;
8115 }
8116
8117
8118
8119 static int
8120 umaskcmd(int argc, char **argv)
8121 {
8122         static const char permuser[3] = "ugo";
8123         static const char permmode[3] = "rwx";
8124         static const short int permmask[] = {
8125                 S_IRUSR, S_IWUSR, S_IXUSR,
8126                 S_IRGRP, S_IWGRP, S_IXGRP,
8127                 S_IROTH, S_IWOTH, S_IXOTH
8128         };
8129
8130         char *ap;
8131         mode_t mask;
8132         int i;
8133         int symbolic_mode = 0;
8134
8135         while (nextopt("S") != '\0') {
8136                 symbolic_mode = 1;
8137         }
8138
8139         INTOFF;
8140         mask = umask(0);
8141         umask(mask);
8142         INTON;
8143
8144         if ((ap = *argptr) == NULL) {
8145                 if (symbolic_mode) {
8146                         char buf[18];
8147                         char *p = buf;
8148                         for (i=0 ; i<3 ; i++) {
8149                                 int j;
8150                                 *p++ = permuser[i];
8151                                 *p++ = '=';
8152                                 for (j=0 ; j<3 ; j++) {
8153                                         if ((mask & permmask[3*i+j]) == 0) {
8154                                                 *p++ = permmode[j];
8155                                         }
8156                                 }
8157                                 *p++ = ',';
8158                         }
8159                         *--p = 0;
8160                         puts(buf);
8161                 } else {
8162                         printf("%.4o\n", mask);
8163                 }
8164         } else {
8165                 if (is_digit((unsigned char)*ap)) {
8166                         mask = 0;
8167                         do {
8168                                 if (*ap >= '8' || *ap < '0')
8169                                         error("Illegal number: %s", argv[1]);
8170                                 mask = (mask << 3) + (*ap - '0');
8171                         } while (*++ap != '\0');
8172                         umask(mask);
8173                 } else {
8174                         mask = ~mask & 0777;
8175                         if (! parse_mode(ap, &mask)) {
8176                                 error("Illegal mode: %s", ap);
8177                         }
8178                         umask(~mask & 0777);
8179                 }
8180         }
8181         return 0;
8182 }
8183
8184 /*
8185  * ulimit builtin
8186  *
8187  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8188  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8189  * ash by J.T. Conklin.
8190  *
8191  * Public domain.
8192  */
8193
8194 struct limits {
8195         const char *name;
8196         short   cmd;
8197         short   factor; /* multiply by to get rlim_{cur,max} values */
8198 };
8199
8200 static const struct limits limits[] = {
8201 #ifdef RLIMIT_CPU
8202         { "time(seconds)",             RLIMIT_CPU,        1 },
8203 #endif
8204 #ifdef RLIMIT_FSIZE
8205         { "file(blocks)",              RLIMIT_FSIZE,    512 },
8206 #endif
8207 #ifdef RLIMIT_DATA
8208         { "data(kbytes)",              RLIMIT_DATA,    1024 },
8209 #endif
8210 #ifdef RLIMIT_STACK
8211         { "stack(kbytes)",             RLIMIT_STACK,   1024 },
8212 #endif
8213 #ifdef  RLIMIT_CORE
8214         { "coredump(blocks)",          RLIMIT_CORE,     512 },
8215 #endif
8216 #ifdef RLIMIT_RSS
8217         { "memory(kbytes)",            RLIMIT_RSS,     1024 },
8218 #endif
8219 #ifdef RLIMIT_MEMLOCK
8220         { "locked memory(kbytes)",     RLIMIT_MEMLOCK, 1024 },
8221 #endif
8222 #ifdef RLIMIT_NPROC
8223         { "process(processes)",        RLIMIT_NPROC,      1 },
8224 #endif
8225 #ifdef RLIMIT_NOFILE
8226         { "nofiles(descriptors)",      RLIMIT_NOFILE,     1 },
8227 #endif
8228 #ifdef RLIMIT_VMEM
8229         { "vmemory(kbytes)",           RLIMIT_VMEM,    1024 },
8230 #endif
8231 #ifdef RLIMIT_SWAP
8232         { "swap(kbytes)",              RLIMIT_SWAP,    1024 },
8233 #endif
8234         { NULL,                         0,                 0 }
8235 };
8236
8237 static int
8238 ulimitcmd(int argc, char **argv)
8239 {
8240         static const char unlimited_string[] = "unlimited";
8241         int     c;
8242         rlim_t val = 0;
8243         enum { SOFT = 0x1, HARD = 0x2 }
8244                         how = SOFT | HARD;
8245         const struct limits     *l;
8246         int             set, all = 0;
8247         int             optc, what;
8248         struct rlimit   limit;
8249
8250         what = 'f';
8251
8252         while ((optc = nextopt("HSa"
8253 #ifdef RLIMIT_CPU
8254         "t"
8255 #endif
8256 #ifdef RLIMIT_FSIZE
8257         "f"
8258 #endif
8259 #ifdef RLIMIT_DATA
8260         "d"
8261 #endif
8262 #ifdef RLIMIT_STACK
8263         "s"
8264 #endif
8265 #ifdef  RLIMIT_CORE
8266         "c"
8267 #endif
8268 #ifdef RLIMIT_RSS
8269         "m"
8270 #endif
8271 #ifdef RLIMIT_MEMLOCK
8272         "l"
8273 #endif
8274 #ifdef RLIMIT_NPROC
8275         "p"
8276 #endif
8277 #ifdef RLIMIT_NOFILE
8278         "n"
8279 #endif
8280 #ifdef RLIMIT_VMEM
8281         "v"
8282 #endif
8283 #ifdef RLIMIT_SWAP
8284         "w"
8285 #endif
8286                                         )) != '\0') {
8287                 if (optc == 'H') {
8288                         how = HARD;
8289                 } else if (optc == 'S') {
8290                         how = SOFT;
8291                 } else if (optc == 'a') {
8292                         all = 1;
8293                 } else {
8294                         what = optc;
8295                 }
8296         }
8297
8298         for (l = limits; l->name; l++) {
8299                 if(l->name[0] == what)
8300                         break;
8301                 if(l->name[1]=='w' && what=='w')
8302                         break;
8303         }
8304
8305         set = *argptr ? 1 : 0;
8306         if (set) {
8307                 char *p = *argptr;
8308
8309                 if (all || argptr[1])
8310                         error("too many arguments");
8311                 if (strcmp(p, unlimited_string) == 0)
8312                         val = RLIM_INFINITY;
8313                 else {
8314                         val = (rlim_t) 0;
8315
8316                         while ((c = *p++) >= '0' && c <= '9')
8317                         {
8318                                 val = (val * 10) + (long)(c - '0');
8319                                 if (val < (rlim_t) 0)
8320                                         break;
8321                         }
8322                         if (c)
8323                                 error("bad number");
8324                         val *= l->factor;
8325                 }
8326         }
8327
8328         if (all) {
8329                 for (l = limits; l->name; l++) {
8330                         printf("%-20s ", l->name);
8331                         getrlimit(l->cmd, &limit);
8332                 OUTPUT_LIMIT:
8333                         if (how & SOFT)
8334                                 val = limit.rlim_cur;
8335                         else if (how & HARD)
8336                                 val = limit.rlim_max;
8337
8338                         if (val == RLIM_INFINITY)
8339                                 puts(unlimited_string);
8340                         else
8341                         {
8342                                 val /= l->factor;
8343                                 printf("%lld\n", (long long) val);
8344                         }
8345                         if (!all) {
8346                                 break;
8347                         }
8348                 }
8349                 return 0;
8350         }
8351
8352         if (!set) {
8353                 goto OUTPUT_LIMIT;
8354         }
8355
8356         getrlimit(l->cmd, &limit);
8357         if (how & HARD)
8358                 limit.rlim_max = val;
8359         if (how & SOFT)
8360                 limit.rlim_cur = val;
8361         if (setrlimit(l->cmd, &limit) < 0)
8362                 error("error setting limit (%m)");
8363         return 0;
8364 }
8365 /*
8366  * prefix -- see if pfx is a prefix of string.
8367  */
8368
8369 static int
8370 prefix(char const *pfx, char const *string)
8371 {
8372         while (*pfx) {
8373                 if (*pfx++ != *string++)
8374                         return 0;
8375         }
8376         return 1;
8377 }
8378
8379 /*
8380  * Return true if s is a string of digits, and save munber in intptr
8381  * nagative is bad
8382  */
8383
8384 static int
8385 is_number(const char *p, int *intptr)
8386 {
8387         int ret = 0;
8388
8389         do {
8390                 if (! is_digit(*p))
8391                         return 0;
8392                 ret *= 10;
8393                 ret += digit_val(*p);
8394                 p++;
8395         } while (*p != '\0');
8396
8397         *intptr = ret;
8398         return 1;
8399 }
8400
8401 /*
8402  * Convert a string of digits to an integer, printing an error message on
8403  * failure.
8404  */
8405
8406 static int
8407 number(const char *s)
8408 {
8409         int i;
8410         if (! is_number(s, &i))
8411                 error("Illegal number: %s", s);
8412         return i;
8413 }
8414
8415 /*
8416  * Produce a possibly single quoted string suitable as input to the shell.
8417  * The return string is allocated on the stack.
8418  */
8419
8420 static char *
8421 single_quote(const char *s)
8422 {
8423         char *p;
8424
8425         STARTSTACKSTR(p);
8426
8427         do {
8428                 char *q = p;
8429                 size_t len1, len1p, len2, len2p;
8430
8431                 len1 = strcspn(s, "'");
8432                 len2 = strspn(s + len1, "'");
8433
8434                 len1p = len1 ? len1 + 2 : len1;
8435                 len2p = len2 + ((len2 < 2) ? len2 : 2);
8436
8437                 CHECKSTRSPACE(len1p + len2p + 1, p);
8438
8439                 if (len1) {
8440                         *p = '\'';
8441                         q = p + 1 + len1;
8442                         memcpy(p + 1, s, len1);
8443                         *q++ = '\'';
8444                         s += len1;
8445                 }
8446
8447                 if (len2 > 1) {
8448                         *q = '"';
8449                         q += 1 + len2;
8450                         memcpy(q + 1, s, len2);
8451                         *q = '"';
8452                         s += len2;
8453                 } else if (len2 == 1) {
8454                         *q++ = '\\';
8455                         *q = '\'';
8456                         s++;
8457                 }
8458
8459                 STADJUST(len1p + len2p, p);
8460         } while (*s);
8461
8462         USTPUTC(0, p);
8463
8464         return grabstackstr(p);
8465 }
8466
8467 /*
8468  * Like strdup but works with the ash stack.
8469  */
8470
8471 static char *
8472 sstrdup(const char *p)
8473 {
8474         size_t len = strlen(p) + 1;
8475         return memcpy(stalloc(len), p, len);
8476 }
8477
8478
8479 /*
8480  * Routine for dealing with parsed shell commands.
8481  */
8482
8483
8484 static void sizenodelist (const struct nodelist *);
8485 static struct nodelist *copynodelist (const struct nodelist *);
8486 static char *nodexstrdup (const char *);
8487
8488 #define CALCSIZE_TABLE
8489 #define COPYNODE_TABLE
8490 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8491 /*
8492  * To collect a lot of redundant code in case statements for copynode()
8493  * and calcsize(), we implement a mini language here.  Each type of node
8494  * struct has an associated instruction sequence that operates on its
8495  * members via their offsets.  The instruction are pack in unsigned chars
8496  * with format   IIDDDDDE   where the bits are
8497  *   I : part of the instruction opcode, which are
8498  *       00 : member is a pointer to another node
8499  *       40 : member is an integer
8500  *       80 : member is a pointer to a nodelist
8501  *       CC : member is a pointer to a char string
8502  *   D : data - the actual offset of the member to operate on in the struct
8503  *              (since we assume bit 0 is set, it is not shifted)
8504  *   E : flag signaling end of instruction sequence
8505  *
8506  * WARNING: In order to handle larger offsets for 64bit archs, this code
8507  *          assumes that no offset can be an odd number and stores the
8508  *          end-of-instructions flag in bit 0.
8509  */
8510
8511 #define NODE_INTEGER    0x40
8512 #define NODE_NODELIST   0x80
8513 #define NODE_CHARPTR    0xC0
8514 #define NODE_NOMORE             0x01    /* Note: no offset should be odd (aligned)*/
8515 #define NODE_MBRMASK    0xC0
8516 #define NODE_OFFSETMASK 0x3E
8517
8518 static const unsigned char copynode_ops[35] = {
8519 #define COPYNODE_OPS0   0
8520         offsetof(union node, nbinary.ch2),
8521         offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8522 #define COPYNODE_OPS1   (COPYNODE_OPS0 + 2)
8523         offsetof(union node, ncmd.redirect),
8524         offsetof(union node, ncmd.args),
8525         offsetof(union node, ncmd.assign),
8526         offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8527 #define COPYNODE_OPS2   (COPYNODE_OPS1 + 4)
8528         offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8529         offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8530 #define COPYNODE_OPS3   (COPYNODE_OPS2 + 2)
8531         offsetof(union node, nredir.redirect),
8532         offsetof(union node, nredir.n)|NODE_NOMORE,
8533 #define COPYNODE_OPS4   (COPYNODE_OPS3 + 2)
8534         offsetof(union node, nif.elsepart),
8535         offsetof(union node, nif.ifpart),
8536         offsetof(union node, nif.test)|NODE_NOMORE,
8537 #define COPYNODE_OPS5   (COPYNODE_OPS4 + 3)
8538         offsetof(union node, nfor.var)|NODE_CHARPTR,
8539         offsetof(union node, nfor.body),
8540         offsetof(union node, nfor.args)|NODE_NOMORE,
8541 #define COPYNODE_OPS6   (COPYNODE_OPS5 + 3)
8542         offsetof(union node, ncase.cases),
8543         offsetof(union node, ncase.expr)|NODE_NOMORE,
8544 #define COPYNODE_OPS7   (COPYNODE_OPS6 + 2)
8545         offsetof(union node, nclist.body),
8546         offsetof(union node, nclist.pattern),
8547         offsetof(union node, nclist.next)|NODE_NOMORE,
8548 #define COPYNODE_OPS8   (COPYNODE_OPS7 + 3)
8549         offsetof(union node, narg.backquote)|NODE_NODELIST,
8550         offsetof(union node, narg.text)|NODE_CHARPTR,
8551         offsetof(union node, narg.next)|NODE_NOMORE,
8552 #define COPYNODE_OPS9   (COPYNODE_OPS8 + 3)
8553         offsetof(union node, nfile.fname),
8554         offsetof(union node, nfile.fd)|NODE_INTEGER,
8555         offsetof(union node, nfile.next)|NODE_NOMORE,
8556 #define COPYNODE_OPS10   (COPYNODE_OPS9 + 3)
8557         offsetof(union node, ndup.vname),
8558         offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8559         offsetof(union node, ndup.fd)|NODE_INTEGER,
8560         offsetof(union node, ndup.next)|NODE_NOMORE,
8561 #define COPYNODE_OPS11   (COPYNODE_OPS10 + 4)
8562         offsetof(union node, nhere.doc),
8563         offsetof(union node, nhere.fd)|NODE_INTEGER,
8564         offsetof(union node, nhere.next)|NODE_NOMORE,
8565 #define COPYNODE_OPS12   (COPYNODE_OPS11 + 3)
8566         offsetof(union node, nnot.com)|NODE_NOMORE,
8567 };
8568
8569 #if COPYNODE_OPS12 != 34
8570 #error COPYNODE_OPS12 is incorrect
8571 #endif
8572
8573 static const unsigned char copynode_ops_index[26] = {
8574         COPYNODE_OPS0, /* NSEMI */
8575         COPYNODE_OPS1, /* NCMD */
8576         COPYNODE_OPS2, /* NPIPE */
8577         COPYNODE_OPS3, /* NREDIR */
8578         COPYNODE_OPS3, /* NBACKGND */
8579         COPYNODE_OPS3, /* NSUBSHELL */
8580         COPYNODE_OPS0, /* NAND */
8581         COPYNODE_OPS0, /* NOR */
8582         COPYNODE_OPS4, /* NIF */
8583         COPYNODE_OPS0, /* NWHILE */
8584         COPYNODE_OPS0, /* NUNTIL */
8585         COPYNODE_OPS5, /* NFOR */
8586         COPYNODE_OPS6, /* NCASE */
8587         COPYNODE_OPS7, /* NCLIST */
8588         COPYNODE_OPS8, /* NDEFUN */
8589         COPYNODE_OPS8, /* NARG */
8590         COPYNODE_OPS9, /* NTO */
8591         COPYNODE_OPS9, /* NFROM */
8592         COPYNODE_OPS9, /* NFROMTO */
8593         COPYNODE_OPS9, /* NAPPEND */
8594         COPYNODE_OPS9, /* NTOOV */
8595         COPYNODE_OPS10, /* NTOFD */
8596         COPYNODE_OPS10, /* NFROMFD */
8597         COPYNODE_OPS11, /* NHERE */
8598         COPYNODE_OPS11, /* NXHERE */
8599         COPYNODE_OPS12, /* NNOT */
8600 };
8601
8602 #if NODE_CHARPTR != NODE_MBRMASK
8603 #error NODE_CHARPTR != NODE_MBRMASK!!!
8604 #endif
8605 #endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8606
8607 #ifdef COPYNODE_TABLE
8608 static union node *
8609 copynode(const union node *n)
8610 {
8611       union node *new;
8612           const unsigned char *p;
8613
8614       if (n == NULL) {
8615           return NULL;
8616           }
8617       new = funcblock;
8618       new->type = n->type;
8619       funcblock = (char *) funcblock + (int) nodesize[n->type];
8620           p = copynode_ops + (int) copynode_ops_index[n->type];
8621           do {
8622                   char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8623                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8624
8625                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8626                           *((union node **)nn) = copynode(*((const union node **) no));
8627                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8628                           *((const char **)nn) = nodexstrdup(*((const char **)no));
8629                   } else if (*p & NODE_NODELIST) { /* nodelist */
8630                           *((struct nodelist **)nn)
8631                                   = copynodelist(*((const struct nodelist **) no));
8632                   } else {                              /* integer */
8633                           *((int *) nn) = *((int *) no);
8634                   }
8635           } while (!(*p++ & NODE_NOMORE));
8636       return new;
8637 }
8638 #else  /* COPYNODE_TABLE */
8639 static union node *
8640 copynode(const union node *n)
8641 {
8642       union node *new;
8643
8644       if (n == NULL)
8645         return NULL;
8646       new = funcblock;
8647       funcblock = (char *) funcblock + nodesize[n->type];
8648       switch (n->type) {
8649       case NSEMI:
8650       case NAND:
8651       case NOR:
8652       case NWHILE:
8653       case NUNTIL:
8654             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8655             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8656             break;
8657       case NCMD:
8658             new->ncmd.redirect = copynode(n->ncmd.redirect);
8659             new->ncmd.args = copynode(n->ncmd.args);
8660             new->ncmd.assign = copynode(n->ncmd.assign);
8661             new->ncmd.backgnd = n->ncmd.backgnd;
8662             break;
8663       case NPIPE:
8664             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8665             new->npipe.backgnd = n->npipe.backgnd;
8666             break;
8667       case NREDIR:
8668       case NBACKGND:
8669       case NSUBSHELL:
8670             new->nredir.redirect = copynode(n->nredir.redirect);
8671             new->nredir.n = copynode(n->nredir.n);
8672             break;
8673       case NIF:
8674             new->nif.elsepart = copynode(n->nif.elsepart);
8675             new->nif.ifpart = copynode(n->nif.ifpart);
8676             new->nif.test = copynode(n->nif.test);
8677             break;
8678       case NFOR:
8679             new->nfor.var = nodexstrdup(n->nfor.var);
8680             new->nfor.body = copynode(n->nfor.body);
8681             new->nfor.args = copynode(n->nfor.args);
8682             break;
8683       case NCASE:
8684             new->ncase.cases = copynode(n->ncase.cases);
8685             new->ncase.expr = copynode(n->ncase.expr);
8686             break;
8687       case NCLIST:
8688             new->nclist.body = copynode(n->nclist.body);
8689             new->nclist.pattern = copynode(n->nclist.pattern);
8690             new->nclist.next = copynode(n->nclist.next);
8691             break;
8692       case NDEFUN:
8693       case NARG:
8694             new->narg.backquote = copynodelist(n->narg.backquote);
8695             new->narg.text = nodexstrdup(n->narg.text);
8696             new->narg.next = copynode(n->narg.next);
8697             break;
8698       case NTO:
8699       case NFROM:
8700       case NFROMTO:
8701       case NAPPEND:
8702       case NTOOV:
8703             new->nfile.fname = copynode(n->nfile.fname);
8704             new->nfile.fd = n->nfile.fd;
8705             new->nfile.next = copynode(n->nfile.next);
8706             break;
8707       case NTOFD:
8708       case NFROMFD:
8709             new->ndup.vname = copynode(n->ndup.vname);
8710             new->ndup.dupfd = n->ndup.dupfd;
8711             new->ndup.fd = n->ndup.fd;
8712             new->ndup.next = copynode(n->ndup.next);
8713             break;
8714       case NHERE:
8715       case NXHERE:
8716             new->nhere.doc = copynode(n->nhere.doc);
8717             new->nhere.fd = n->nhere.fd;
8718             new->nhere.next = copynode(n->nhere.next);
8719             break;
8720       case NNOT:
8721             new->nnot.com = copynode(n->nnot.com);
8722             break;
8723       };
8724       new->type = n->type;
8725       return new;
8726 }
8727 #endif /* COPYNODE_TABLE */
8728
8729 #ifdef CALCSIZE_TABLE
8730 static void
8731 calcsize(const union node *n)
8732 {
8733           const unsigned char *p;
8734
8735       if (n == NULL)
8736             return;
8737       funcblocksize += (int) nodesize[n->type];
8738
8739           p = copynode_ops + (int) copynode_ops_index[n->type];
8740           do {
8741                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8742
8743                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8744                           calcsize(*((const union node **) no));
8745                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8746                           funcstringsize += strlen(*((const char **)no)) + 1;
8747                   } else if (*p & NODE_NODELIST) { /* nodelist */
8748                           sizenodelist(*((const struct nodelist **) no));
8749                   }     /* else integer -- ignore */
8750           } while (!(*p++ & NODE_NOMORE));
8751 }
8752 #else  /* CALCSIZE_TABLE */
8753 static void
8754 calcsize(const union node *n)
8755 {
8756       if (n == NULL)
8757             return;
8758       funcblocksize += nodesize[n->type];
8759       switch (n->type) {
8760       case NSEMI:
8761       case NAND:
8762       case NOR:
8763       case NWHILE:
8764       case NUNTIL:
8765             calcsize(n->nbinary.ch2);
8766             calcsize(n->nbinary.ch1);
8767             break;
8768       case NCMD:
8769             calcsize(n->ncmd.redirect);
8770             calcsize(n->ncmd.args);
8771             calcsize(n->ncmd.assign);
8772             break;
8773       case NPIPE:
8774             sizenodelist(n->npipe.cmdlist);
8775             break;
8776       case NREDIR:
8777       case NBACKGND:
8778       case NSUBSHELL:
8779             calcsize(n->nredir.redirect);
8780             calcsize(n->nredir.n);
8781             break;
8782       case NIF:
8783             calcsize(n->nif.elsepart);
8784             calcsize(n->nif.ifpart);
8785             calcsize(n->nif.test);
8786             break;
8787       case NFOR:
8788             funcstringsize += strlen(n->nfor.var) + 1;
8789             calcsize(n->nfor.body);
8790             calcsize(n->nfor.args);
8791             break;
8792       case NCASE:
8793             calcsize(n->ncase.cases);
8794             calcsize(n->ncase.expr);
8795             break;
8796       case NCLIST:
8797             calcsize(n->nclist.body);
8798             calcsize(n->nclist.pattern);
8799             calcsize(n->nclist.next);
8800             break;
8801       case NDEFUN:
8802       case NARG:
8803             sizenodelist(n->narg.backquote);
8804             funcstringsize += strlen(n->narg.text) + 1;
8805             calcsize(n->narg.next);
8806             break;
8807       case NTO:
8808       case NFROM:
8809       case NFROMTO:
8810       case NAPPEND:
8811       case NTOOV:
8812             calcsize(n->nfile.fname);
8813             calcsize(n->nfile.next);
8814             break;
8815       case NTOFD:
8816       case NFROMFD:
8817             calcsize(n->ndup.vname);
8818             calcsize(n->ndup.next);
8819             break;
8820       case NHERE:
8821       case NXHERE:
8822             calcsize(n->nhere.doc);
8823             calcsize(n->nhere.next);
8824             break;
8825       case NNOT:
8826             calcsize(n->nnot.com);
8827             break;
8828       };
8829 }
8830 #endif /* CALCSIZE_TABLE */
8831
8832 static void
8833 sizenodelist(const struct nodelist *lp)
8834 {
8835         while (lp) {
8836                 funcblocksize += ALIGN(sizeof(struct nodelist));
8837                 calcsize(lp->n);
8838                 lp = lp->next;
8839         }
8840 }
8841
8842
8843 static struct nodelist *
8844 copynodelist(const struct nodelist *lp)
8845 {
8846         struct nodelist *start;
8847         struct nodelist **lpp;
8848
8849         lpp = &start;
8850         while (lp) {
8851                 *lpp = funcblock;
8852                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8853                 (*lpp)->n = copynode(lp->n);
8854                 lp = lp->next;
8855                 lpp = &(*lpp)->next;
8856         }
8857         *lpp = NULL;
8858         return start;
8859 }
8860
8861
8862 static char *
8863 nodexstrdup(const char *s)
8864 {
8865         const char *p = s;
8866         char *q = funcstring;
8867         char   *rtn = funcstring;
8868
8869         while ((*q++ = *p++) != '\0')
8870                 continue;
8871         funcstring = q;
8872         return rtn;
8873 }
8874
8875 #ifdef ASH_GETOPTS
8876 static int getopts (char *, char *, char **, int *, int *);
8877 #endif
8878
8879
8880 /*
8881  * Process the shell command line arguments.
8882  */
8883
8884 static void
8885 procargs(int argc, char **argv)
8886 {
8887         int i;
8888
8889         argptr = argv;
8890         if (argc > 0)
8891                 argptr++;
8892         for (i = 0; i < NOPTS; i++)
8893                 optent_val(i) = 2;
8894         options(1);
8895         if (*argptr == NULL && minusc == NULL)
8896                 sflag = 1;
8897         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8898                 iflag = 1;
8899         if (mflag == 2)
8900                 mflag = iflag;
8901         for (i = 0; i < NOPTS; i++)
8902                 if (optent_val(i) == 2)
8903                         optent_val(i) = 0;
8904         arg0 = argv[0];
8905         if (sflag == 0 && minusc == NULL) {
8906                 commandname = argv[0];
8907                 arg0 = *argptr++;
8908                 setinputfile(arg0, 0);
8909                 commandname = arg0;
8910         }
8911         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8912         if (argptr && minusc && *argptr)
8913                 arg0 = *argptr++;
8914
8915         shellparam.p = argptr;
8916         shellparam.optind = 1;
8917         shellparam.optoff = -1;
8918         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8919         while (*argptr) {
8920                 shellparam.nparam++;
8921                 argptr++;
8922         }
8923         optschanged();
8924 }
8925
8926
8927
8928 /*
8929  * Process shell options.  The global variable argptr contains a pointer
8930  * to the argument list; we advance it past the options.
8931  */
8932
8933 static inline void
8934 minus_o(const char *name, int val)
8935 {
8936         int i;
8937
8938         if (name == NULL) {
8939                 out1str("Current option settings\n");
8940                 for (i = 0; i < NOPTS; i++)
8941                         printf("%-16s%s\n", optent_name(optlist[i]),
8942                                 optent_val(i) ? "on" : "off");
8943         } else {
8944                 for (i = 0; i < NOPTS; i++)
8945                         if (equal(name, optent_name(optlist[i]))) {
8946                                 setoption(optent_letter(optlist[i]), val);
8947                                 return;
8948                         }
8949                 error("Illegal option -o %s", name);
8950         }
8951 }
8952
8953
8954 static void
8955 options(int cmdline)
8956 {
8957         char *p;
8958         int val;
8959         int c;
8960
8961         if (cmdline)
8962                 minusc = NULL;
8963         while ((p = *argptr) != NULL) {
8964                 argptr++;
8965                 if ((c = *p++) == '-') {
8966                         val = 1;
8967                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8968                                 if (!cmdline) {
8969                                         /* "-" means turn off -x and -v */
8970                                         if (p[0] == '\0')
8971                                                 xflag = vflag = 0;
8972                                         /* "--" means reset params */
8973                                         else if (*argptr == NULL)
8974                                                 setparam(argptr);
8975                                 }
8976                                 break;    /* "-" or  "--" terminates options */
8977                         }
8978                 } else if (c == '+') {
8979                         val = 0;
8980                 } else {
8981                         argptr--;
8982                         break;
8983                 }
8984                 while ((c = *p++) != '\0') {
8985                         if (c == 'c' && cmdline) {
8986                                 char *q;
8987 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
8988                                 if (*p == '\0')
8989 #endif
8990                                         q = *argptr++;
8991                                 if (q == NULL || minusc != NULL)
8992                                         error("Bad -c option");
8993                                 minusc = q;
8994 #ifdef NOHACK
8995                                 break;
8996 #endif
8997                         } else if (c == 'o') {
8998                                 minus_o(*argptr, val);
8999                                 if (*argptr)
9000                                         argptr++;
9001                         } else {
9002                                 setoption(c, val);
9003                         }
9004                 }
9005         }
9006 }
9007
9008
9009 static void
9010 setoption(int flag, int val)
9011 {
9012         int i;
9013
9014         for (i = 0; i < NOPTS; i++)
9015                 if (optent_letter(optlist[i]) == flag) {
9016                         optent_val(i) = val;
9017                         if (val) {
9018                                 /* #%$ hack for ksh semantics */
9019                                 if (flag == 'V')
9020                                         Eflag = 0;
9021                                 else if (flag == 'E')
9022                                         Vflag = 0;
9023                         }
9024                         return;
9025                 }
9026         error("Illegal option -%c", flag);
9027         /* NOTREACHED */
9028 }
9029
9030
9031
9032 /*
9033  * Set the shell parameters.
9034  */
9035
9036 static void
9037 setparam(char **argv)
9038 {
9039         char **newparam;
9040         char **ap;
9041         int nparam;
9042
9043         for (nparam = 0 ; argv[nparam] ; nparam++);
9044         ap = newparam = xmalloc((nparam + 1) * sizeof *ap);
9045         while (*argv) {
9046                 *ap++ = xstrdup(*argv++);
9047         }
9048         *ap = NULL;
9049         freeparam(&shellparam);
9050         shellparam.malloc = 1;
9051         shellparam.nparam = nparam;
9052         shellparam.p = newparam;
9053         shellparam.optind = 1;
9054         shellparam.optoff = -1;
9055 }
9056
9057
9058 /*
9059  * Free the list of positional parameters.
9060  */
9061
9062 static void
9063 freeparam(volatile struct shparam *param)
9064 {
9065         char **ap;
9066
9067         if (param->malloc) {
9068                 for (ap = param->p ; *ap ; ap++)
9069                         ckfree(*ap);
9070                 ckfree(param->p);
9071         }
9072 }
9073
9074
9075
9076 /*
9077  * The shift builtin command.
9078  */
9079
9080 static int
9081 shiftcmd(int argc, char **argv)
9082 {
9083         int n;
9084         char **ap1, **ap2;
9085
9086         n = 1;
9087         if (argc > 1)
9088                 n = number(argv[1]);
9089         if (n > shellparam.nparam)
9090                 error("can't shift that many");
9091         INTOFF;
9092         shellparam.nparam -= n;
9093         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9094                 if (shellparam.malloc)
9095                         ckfree(*ap1);
9096         }
9097         ap2 = shellparam.p;
9098         while ((*ap2++ = *ap1++) != NULL);
9099         shellparam.optind = 1;
9100         shellparam.optoff = -1;
9101         INTON;
9102         return 0;
9103 }
9104
9105
9106
9107 /*
9108  * The set command builtin.
9109  */
9110
9111 static int
9112 setcmd(int argc, char **argv)
9113 {
9114         if (argc == 1)
9115                 return showvarscmd(argc, argv);
9116         INTOFF;
9117         options(0);
9118         optschanged();
9119         if (*argptr != NULL) {
9120                 setparam(argptr);
9121         }
9122         INTON;
9123         return 0;
9124 }
9125
9126
9127 static void
9128 getoptsreset(const char *value)
9129 {
9130         shellparam.optind = number(value);
9131         shellparam.optoff = -1;
9132 }
9133
9134 #ifdef CONFIG_LOCALE_SUPPORT
9135 static void change_lc_all(const char *value)
9136 {
9137         if(value != 0 && *value != 0)
9138                 setlocale(LC_ALL, value);
9139 }
9140
9141 static void change_lc_ctype(const char *value)
9142 {
9143         if(value != 0 && *value != 0)
9144                 setlocale(LC_CTYPE, value);
9145 }
9146
9147 #endif
9148
9149 #ifdef ASH_GETOPTS
9150 /*
9151  * The getopts builtin.  Shellparam.optnext points to the next argument
9152  * to be processed.  Shellparam.optptr points to the next character to
9153  * be processed in the current argument.  If shellparam.optnext is NULL,
9154  * then it's the first time getopts has been called.
9155  */
9156
9157 static int
9158 getoptscmd(int argc, char **argv)
9159 {
9160         char **optbase;
9161
9162         if (argc < 3)
9163                 error("Usage: getopts optstring var [arg]");
9164         else if (argc == 3) {
9165                 optbase = shellparam.p;
9166                 if (shellparam.optind > shellparam.nparam + 1) {
9167                         shellparam.optind = 1;
9168                         shellparam.optoff = -1;
9169                 }
9170         }
9171         else {
9172                 optbase = &argv[3];
9173                 if (shellparam.optind > argc - 2) {
9174                         shellparam.optind = 1;
9175                         shellparam.optoff = -1;
9176                 }
9177         }
9178
9179         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9180                        &shellparam.optoff);
9181 }
9182
9183 /*
9184  * Safe version of setvar, returns 1 on success 0 on failure.
9185  */
9186
9187 static int
9188 setvarsafe(const char *name, const char *val, int flags)
9189 {
9190         struct jmploc jmploc;
9191         struct jmploc *volatile savehandler = handler;
9192         int err = 0;
9193 #ifdef __GNUC__
9194         (void) &err;
9195 #endif
9196
9197         if (setjmp(jmploc.loc))
9198                 err = 1;
9199         else {
9200                 handler = &jmploc;
9201                 setvar(name, val, flags);
9202         }
9203         handler = savehandler;
9204         return err;
9205 }
9206
9207 static int
9208 getopts(char *optstr, char *optvar, char **optfirst, int *myoptind, int *optoff)
9209 {
9210         char *p, *q;
9211         char c = '?';
9212         int done = 0;
9213         int err = 0;
9214         char s[10];
9215         char **optnext = optfirst + *myoptind - 1;
9216
9217         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9218             strlen(*(optnext - 1)) < *optoff)
9219                 p = NULL;
9220         else
9221                 p = *(optnext - 1) + *optoff;
9222         if (p == NULL || *p == '\0') {
9223                 /* Current word is done, advance */
9224                 if (optnext == NULL)
9225                         return 1;
9226                 p = *optnext;
9227                 if (p == NULL || *p != '-' || *++p == '\0') {
9228 atend:
9229                         *myoptind = optnext - optfirst + 1;
9230                         p = NULL;
9231                         done = 1;
9232                         goto out;
9233                 }
9234                 optnext++;
9235                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9236                         goto atend;
9237         }
9238
9239         c = *p++;
9240         for (q = optstr; *q != c; ) {
9241                 if (*q == '\0') {
9242                         if (optstr[0] == ':') {
9243                                 s[0] = c;
9244                                 s[1] = '\0';
9245                                 err |= setvarsafe("OPTARG", s, 0);
9246                         }
9247                         else {
9248                                 out2fmt("Illegal option -%c\n", c);
9249                                 (void) unsetvar("OPTARG");
9250                         }
9251                         c = '?';
9252                         goto bad;
9253                 }
9254                 if (*++q == ':')
9255                         q++;
9256         }
9257
9258         if (*++q == ':') {
9259                 if (*p == '\0' && (p = *optnext) == NULL) {
9260                         if (optstr[0] == ':') {
9261                                 s[0] = c;
9262                                 s[1] = '\0';
9263                                 err |= setvarsafe("OPTARG", s, 0);
9264                                 c = ':';
9265                         }
9266                         else {
9267                                 out2fmt("No arg for -%c option\n", c);
9268                                 (void) unsetvar("OPTARG");
9269                                 c = '?';
9270                         }
9271                         goto bad;
9272                 }
9273
9274                 if (p == *optnext)
9275                         optnext++;
9276                 setvarsafe("OPTARG", p, 0);
9277                 p = NULL;
9278         }
9279         else
9280                 setvarsafe("OPTARG", "", 0);
9281         *myoptind = optnext - optfirst + 1;
9282         goto out;
9283
9284 bad:
9285         *myoptind = 1;
9286         p = NULL;
9287 out:
9288         *optoff = p ? p - *(optnext - 1) : -1;
9289         snprintf(s, sizeof(s), "%d", *myoptind);
9290         err |= setvarsafe("OPTIND", s, VNOFUNC);
9291         s[0] = c;
9292         s[1] = '\0';
9293         err |= setvarsafe(optvar, s, 0);
9294         if (err) {
9295                 *myoptind = 1;
9296                 *optoff = -1;
9297                 exraise(EXERROR);
9298         }
9299         return done;
9300 }
9301 #endif
9302
9303 /*
9304  * XXX - should get rid of.  have all builtins use getopt(3).  the
9305  * library getopt must have the BSD extension static variable "optreset"
9306  * otherwise it can't be used within the shell safely.
9307  *
9308  * Standard option processing (a la getopt) for builtin routines.  The
9309  * only argument that is passed to nextopt is the option string; the
9310  * other arguments are unnecessary.  It return the character, or '\0' on
9311  * end of input.
9312  */
9313
9314 static int
9315 nextopt(const char *optstring)
9316 {
9317         char *p;
9318         const char *q;
9319         char c;
9320
9321         if ((p = optptr) == NULL || *p == '\0') {
9322                 p = *argptr;
9323                 if (p == NULL || *p != '-' || *++p == '\0')
9324                         return '\0';
9325                 argptr++;
9326                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9327                         return '\0';
9328         }
9329         c = *p++;
9330         for (q = optstring ; *q != c ; ) {
9331                 if (*q == '\0')
9332                         error("Illegal option -%c", c);
9333                 if (*++q == ':')
9334                         q++;
9335         }
9336         if (*++q == ':') {
9337                 if (*p == '\0' && (p = *argptr++) == NULL)
9338                         error("No arg for -%c option", c);
9339                 optionarg = p;
9340                 p = NULL;
9341         }
9342         optptr = p;
9343         return c;
9344 }
9345
9346 static void
9347 flushall() {
9348         INTOFF;
9349         fflush(stdout);
9350         INTON;
9351 }
9352
9353
9354 static void
9355 out2fmt(const char *fmt, ...)
9356 {
9357         va_list ap;
9358         va_start(ap, fmt);
9359         vfprintf(stderr, fmt, ap);
9360         va_end(ap);
9361 }
9362
9363 /*
9364  * Version of write which resumes after a signal is caught.
9365  */
9366
9367 static int
9368 xwrite(int fd, const char *buf, int nbytes)
9369 {
9370         int ntry;
9371         int i;
9372         int n;
9373
9374         n = nbytes;
9375         ntry = 0;
9376         for (;;) {
9377                 i = write(fd, buf, n);
9378                 if (i > 0) {
9379                         if ((n -= i) <= 0)
9380                                 return nbytes;
9381                         buf += i;
9382                         ntry = 0;
9383                 } else if (i == 0) {
9384                         if (++ntry > 10)
9385                                 return nbytes - n;
9386                 } else if (errno != EINTR) {
9387                         return -1;
9388                 }
9389         }
9390 }
9391
9392
9393 /*
9394  * Shell command parser.
9395  */
9396
9397 #define EOFMARKLEN 79
9398
9399
9400
9401 struct heredoc {
9402         struct heredoc *next;   /* next here document in list */
9403         union node *here;               /* redirection node */
9404         char *eofmark;          /* string indicating end of input */
9405         int striptabs;          /* if set, strip leading tabs */
9406 };
9407
9408 static struct heredoc *heredoclist;     /* list of here documents to read */
9409 static int parsebackquote;              /* nonzero if we are inside backquotes */
9410 static int doprompt;                    /* if set, prompt the user */
9411 static int needprompt;                  /* true if interactive and at start of line */
9412 static int lasttoken;                   /* last token read */
9413
9414 static char *wordtext;                  /* text of last word returned by readtoken */
9415
9416 static struct nodelist *backquotelist;
9417 static union node *redirnode;
9418 static struct heredoc *heredoc;
9419 static int quoteflag;                   /* set if (part of) last token was quoted */
9420 static int startlinno;                  /* line # where last token started */
9421
9422
9423 static union node *list (int);
9424 static union node *andor (void);
9425 static union node *pipeline (void);
9426 static union node *command (void);
9427 static union node *simplecmd(union node **rpp, union node *redir);
9428 static void parsefname (void);
9429 static void parseheredoc (void);
9430 static char peektoken (void);
9431 static int readtoken (void);
9432 static int xxreadtoken (void);
9433 static int readtoken1 (int, int, const char *, int);
9434 static int noexpand (char *);
9435 static void synexpect (int) __attribute__((noreturn));
9436 static void synerror (const char *) __attribute__((noreturn));
9437 static void setprompt (int);
9438
9439
9440 /*
9441  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9442  * valid parse tree indicating a blank line.)
9443  */
9444
9445 static union node *
9446 parsecmd(int interact)
9447 {
9448         int t;
9449
9450         tokpushback = 0;
9451         doprompt = interact;
9452         if (doprompt)
9453                 setprompt(1);
9454         else
9455                 setprompt(0);
9456         needprompt = 0;
9457         t = readtoken();
9458         if (t == TEOF)
9459                 return NEOF;
9460         if (t == TNL)
9461                 return NULL;
9462         tokpushback++;
9463         return list(1);
9464 }
9465
9466
9467 static union node *
9468 list(int nlflag)
9469 {
9470         union node *n1, *n2, *n3;
9471         int tok;
9472
9473         checkkwd = 2;
9474         if (nlflag == 0 && peektoken())
9475                 return NULL;
9476         n1 = NULL;
9477         for (;;) {
9478                 n2 = andor();
9479                 tok = readtoken();
9480                 if (tok == TBACKGND) {
9481                         if (n2->type == NCMD || n2->type == NPIPE) {
9482                                 n2->ncmd.backgnd = 1;
9483                         } else if (n2->type == NREDIR) {
9484                                 n2->type = NBACKGND;
9485                         } else {
9486                                 n3 = (union node *)stalloc(sizeof (struct nredir));
9487                                 n3->type = NBACKGND;
9488                                 n3->nredir.n = n2;
9489                                 n3->nredir.redirect = NULL;
9490                                 n2 = n3;
9491                         }
9492                 }
9493                 if (n1 == NULL) {
9494                         n1 = n2;
9495                 }
9496                 else {
9497                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9498                         n3->type = NSEMI;
9499                         n3->nbinary.ch1 = n1;
9500                         n3->nbinary.ch2 = n2;
9501                         n1 = n3;
9502                 }
9503                 switch (tok) {
9504                 case TBACKGND:
9505                 case TSEMI:
9506                         tok = readtoken();
9507                         /* fall through */
9508                 case TNL:
9509                         if (tok == TNL) {
9510                                 parseheredoc();
9511                                 if (nlflag)
9512                                         return n1;
9513                         } else {
9514                                 tokpushback++;
9515                         }
9516                         checkkwd = 2;
9517                         if (peektoken())
9518                                 return n1;
9519                         break;
9520                 case TEOF:
9521                         if (heredoclist)
9522                                 parseheredoc();
9523                         else
9524                                 pungetc();              /* push back EOF on input */
9525                         return n1;
9526                 default:
9527                         if (nlflag)
9528                                 synexpect(-1);
9529                         tokpushback++;
9530                         return n1;
9531                 }
9532         }
9533 }
9534
9535
9536
9537 static union node *
9538 andor() {
9539         union node *n1, *n2, *n3;
9540         int t;
9541
9542         checkkwd = 1;
9543         n1 = pipeline();
9544         for (;;) {
9545                 if ((t = readtoken()) == TAND) {
9546                         t = NAND;
9547                 } else if (t == TOR) {
9548                         t = NOR;
9549                 } else {
9550                         tokpushback++;
9551                         return n1;
9552                 }
9553                 checkkwd = 2;
9554                 n2 = pipeline();
9555                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9556                 n3->type = t;
9557                 n3->nbinary.ch1 = n1;
9558                 n3->nbinary.ch2 = n2;
9559                 n1 = n3;
9560         }
9561 }
9562
9563
9564
9565 static union node *
9566 pipeline() {
9567         union node *n1, *n2, *pipenode;
9568         struct nodelist *lp, *prev;
9569         int negate;
9570
9571         negate = 0;
9572         TRACE(("pipeline: entered\n"));
9573         if (readtoken() == TNOT) {
9574                 negate = !negate;
9575                 checkkwd = 1;
9576         } else
9577                 tokpushback++;
9578         n1 = command();
9579         if (readtoken() == TPIPE) {
9580                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9581                 pipenode->type = NPIPE;
9582                 pipenode->npipe.backgnd = 0;
9583                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9584                 pipenode->npipe.cmdlist = lp;
9585                 lp->n = n1;
9586                 do {
9587                         prev = lp;
9588                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9589                         checkkwd = 2;
9590                         lp->n = command();
9591                         prev->next = lp;
9592                 } while (readtoken() == TPIPE);
9593                 lp->next = NULL;
9594                 n1 = pipenode;
9595         }
9596         tokpushback++;
9597         if (negate) {
9598                 n2 = (union node *)stalloc(sizeof (struct nnot));
9599                 n2->type = NNOT;
9600                 n2->nnot.com = n1;
9601                 return n2;
9602         } else
9603                 return n1;
9604 }
9605
9606
9607
9608 static union node *
9609 command(void) {
9610         union node *n1, *n2;
9611         union node *ap, **app;
9612         union node *cp, **cpp;
9613         union node *redir, **rpp;
9614         int t;
9615
9616         redir = NULL;
9617         n1 = NULL;
9618         rpp = &redir;
9619
9620         /* Check for redirection which may precede command */
9621         while (readtoken() == TREDIR) {
9622                 *rpp = n2 = redirnode;
9623                 rpp = &n2->nfile.next;
9624                 parsefname();
9625         }
9626         tokpushback++;
9627
9628         switch (readtoken()) {
9629         case TIF:
9630                 n1 = (union node *)stalloc(sizeof (struct nif));
9631                 n1->type = NIF;
9632                 n1->nif.test = list(0);
9633                 if (readtoken() != TTHEN)
9634                         synexpect(TTHEN);
9635                 n1->nif.ifpart = list(0);
9636                 n2 = n1;
9637                 while (readtoken() == TELIF) {
9638                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9639                         n2 = n2->nif.elsepart;
9640                         n2->type = NIF;
9641                         n2->nif.test = list(0);
9642                         if (readtoken() != TTHEN)
9643                                 synexpect(TTHEN);
9644                         n2->nif.ifpart = list(0);
9645                 }
9646                 if (lasttoken == TELSE)
9647                         n2->nif.elsepart = list(0);
9648                 else {
9649                         n2->nif.elsepart = NULL;
9650                         tokpushback++;
9651                 }
9652                 if (readtoken() != TFI)
9653                         synexpect(TFI);
9654                 checkkwd = 1;
9655                 break;
9656         case TWHILE:
9657         case TUNTIL: {
9658                 int got;
9659                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9660                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9661                 n1->nbinary.ch1 = list(0);
9662                 if ((got=readtoken()) != TDO) {
9663 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9664                         synexpect(TDO);
9665                 }
9666                 n1->nbinary.ch2 = list(0);
9667                 if (readtoken() != TDONE)
9668                         synexpect(TDONE);
9669                 checkkwd = 1;
9670                 break;
9671         }
9672         case TFOR:
9673                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9674                         synerror("Bad for loop variable");
9675                 n1 = (union node *)stalloc(sizeof (struct nfor));
9676                 n1->type = NFOR;
9677                 n1->nfor.var = wordtext;
9678                 checkkwd = 1;
9679                 if (readtoken() == TIN) {
9680                         app = &ap;
9681                         while (readtoken() == TWORD) {
9682                                 n2 = (union node *)stalloc(sizeof (struct narg));
9683                                 n2->type = NARG;
9684                                 n2->narg.text = wordtext;
9685                                 n2->narg.backquote = backquotelist;
9686                                 *app = n2;
9687                                 app = &n2->narg.next;
9688                         }
9689                         *app = NULL;
9690                         n1->nfor.args = ap;
9691                         if (lasttoken != TNL && lasttoken != TSEMI)
9692                                 synexpect(-1);
9693                 } else {
9694                         static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9695                                                                    '@', '=', '\0'};
9696                         n2 = (union node *)stalloc(sizeof (struct narg));
9697                         n2->type = NARG;
9698                         n2->narg.text = argvars;
9699                         n2->narg.backquote = NULL;
9700                         n2->narg.next = NULL;
9701                         n1->nfor.args = n2;
9702                         /*
9703                          * Newline or semicolon here is optional (but note
9704                          * that the original Bourne shell only allowed NL).
9705                          */
9706                         if (lasttoken != TNL && lasttoken != TSEMI)
9707                                 tokpushback++;
9708                 }
9709                 checkkwd = 2;
9710                 if (readtoken() != TDO)
9711                         synexpect(TDO);
9712                 n1->nfor.body = list(0);
9713                 if (readtoken() != TDONE)
9714                         synexpect(TDONE);
9715                 checkkwd = 1;
9716                 break;
9717         case TCASE:
9718                 n1 = (union node *)stalloc(sizeof (struct ncase));
9719                 n1->type = NCASE;
9720                 if (readtoken() != TWORD)
9721                         synexpect(TWORD);
9722                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9723                 n2->type = NARG;
9724                 n2->narg.text = wordtext;
9725                 n2->narg.backquote = backquotelist;
9726                 n2->narg.next = NULL;
9727                 do {
9728                         checkkwd = 1;
9729                 } while (readtoken() == TNL);
9730                 if (lasttoken != TIN)
9731                         synerror("expecting \"in\"");
9732                 cpp = &n1->ncase.cases;
9733                 checkkwd = 2, readtoken();
9734                 do {
9735                         if (lasttoken == TLP)
9736                                 readtoken();
9737                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9738                         cp->type = NCLIST;
9739                         app = &cp->nclist.pattern;
9740                         for (;;) {
9741                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9742                                 ap->type = NARG;
9743                                 ap->narg.text = wordtext;
9744                                 ap->narg.backquote = backquotelist;
9745                                 if (checkkwd = 2, readtoken() != TPIPE)
9746                                         break;
9747                                 app = &ap->narg.next;
9748                                 readtoken();
9749                         }
9750                         ap->narg.next = NULL;
9751                         if (lasttoken != TRP)
9752                                 synexpect(TRP);
9753                         cp->nclist.body = list(0);
9754
9755                         checkkwd = 2;
9756                         if ((t = readtoken()) != TESAC) {
9757                                 if (t != TENDCASE)
9758                                         synexpect(TENDCASE);
9759                                 else
9760                                         checkkwd = 2, readtoken();
9761                         }
9762                         cpp = &cp->nclist.next;
9763                 } while(lasttoken != TESAC);
9764                 *cpp = NULL;
9765                 checkkwd = 1;
9766                 break;
9767         case TLP:
9768                 n1 = (union node *)stalloc(sizeof (struct nredir));
9769                 n1->type = NSUBSHELL;
9770                 n1->nredir.n = list(0);
9771                 n1->nredir.redirect = NULL;
9772                 if (readtoken() != TRP)
9773                         synexpect(TRP);
9774                 checkkwd = 1;
9775                 break;
9776         case TBEGIN:
9777                 n1 = list(0);
9778                 if (readtoken() != TEND)
9779                         synexpect(TEND);
9780                 checkkwd = 1;
9781                 break;
9782         /* Handle an empty command like other simple commands.  */
9783         case TSEMI:
9784         case TAND:
9785         case TOR:
9786         case TNL:
9787         case TEOF:
9788         case TRP:
9789         case TBACKGND:
9790                 /*
9791                  * An empty command before a ; doesn't make much sense, and
9792                  * should certainly be disallowed in the case of `if ;'.
9793                  */
9794                 if (!redir)
9795                         synexpect(-1);
9796         case TWORD:
9797                 tokpushback++;
9798                 n1 = simplecmd(rpp, redir);
9799                 return n1;
9800         default:
9801                 synexpect(-1);
9802                 /* NOTREACHED */
9803         }
9804
9805         /* Now check for redirection which may follow command */
9806         while (readtoken() == TREDIR) {
9807                 *rpp = n2 = redirnode;
9808                 rpp = &n2->nfile.next;
9809                 parsefname();
9810         }
9811         tokpushback++;
9812         *rpp = NULL;
9813         if (redir) {
9814                 if (n1->type != NSUBSHELL) {
9815                         n2 = (union node *)stalloc(sizeof (struct nredir));
9816                         n2->type = NREDIR;
9817                         n2->nredir.n = n1;
9818                         n1 = n2;
9819                 }
9820                 n1->nredir.redirect = redir;
9821         }
9822
9823         return n1;
9824 }
9825
9826
9827 static union node *
9828 simplecmd(union node **rpp, union node *redir) {
9829         union node *args, **app;
9830         union node *n = NULL;
9831         union node *vars, **vpp;
9832         union node **orig_rpp;
9833
9834         args = NULL;
9835         app = &args;
9836         vars = NULL;
9837         vpp = &vars;
9838
9839         /* If we don't have any redirections already, then we must reset
9840           rpp to be the address of the local redir variable.  */
9841         if (redir == 0)
9842         rpp = &redir;
9843         /* We save the incoming value, because we need this for shell
9844           functions.  There can not be a redirect or an argument between
9845           the function name and the open parenthesis.  */
9846         orig_rpp = rpp;
9847
9848         checkalias = 2;
9849         for (;;) {
9850                 switch (readtoken()) {
9851                 case TWORD:
9852                 case TASSIGN:
9853                         n = (union node *)stalloc(sizeof (struct narg));
9854                         n->type = NARG;
9855                         n->narg.text = wordtext;
9856                         n->narg.backquote = backquotelist;
9857                         if (lasttoken == TWORD) {
9858                                 *app = n;
9859                                 app = &n->narg.next;
9860                         } else {
9861                                 *vpp = n;
9862                                 vpp = &n->narg.next;
9863                         }
9864                         break;
9865                 case TREDIR:
9866                         *rpp = n = redirnode;
9867                         rpp = &n->nfile.next;
9868                         parsefname();   /* read name of redirection file */
9869                         break;
9870                 case TLP:
9871                         if (
9872                                 args && app == &args->narg.next &&
9873                                 !vars && rpp == orig_rpp
9874                         ) {
9875                                 /* We have a function */
9876                                 if (readtoken() != TRP)
9877                                         synexpect(TRP);
9878                                 n->type = NDEFUN;
9879                                 checkkwd = 2;
9880                                 n->narg.next = command();
9881                                 return n;
9882                         }
9883                         /* fall through */
9884                 default:
9885                         tokpushback++;
9886                         goto out;
9887                 }
9888         }
9889 out:
9890         *app = NULL;
9891         *vpp = NULL;
9892         *rpp = NULL;
9893         n = (union node *)stalloc(sizeof (struct ncmd));
9894         n->type = NCMD;
9895         n->ncmd.backgnd = 0;
9896         n->ncmd.args = args;
9897         n->ncmd.assign = vars;
9898         n->ncmd.redirect = redir;
9899         return n;
9900 }
9901
9902 static union node *
9903 makename(void) {
9904         union node *n;
9905
9906         n = (union node *)stalloc(sizeof (struct narg));
9907         n->type = NARG;
9908         n->narg.next = NULL;
9909         n->narg.text = wordtext;
9910         n->narg.backquote = backquotelist;
9911         return n;
9912 }
9913
9914 static void fixredir(union node *n, const char *text, int err)
9915 {
9916         TRACE(("Fix redir %s %d\n", text, err));
9917         if (!err)
9918                 n->ndup.vname = NULL;
9919
9920         if (is_digit(text[0]) && text[1] == '\0')
9921                 n->ndup.dupfd = digit_val(text[0]);
9922         else if (text[0] == '-' && text[1] == '\0')
9923                 n->ndup.dupfd = -1;
9924         else {
9925
9926                 if (err)
9927                         synerror("Bad fd number");
9928                 else
9929                         n->ndup.vname = makename();
9930         }
9931 }
9932
9933
9934 static void
9935 parsefname(void) {
9936         union node *n = redirnode;
9937
9938         if (readtoken() != TWORD)
9939                 synexpect(-1);
9940         if (n->type == NHERE) {
9941                 struct heredoc *here = heredoc;
9942                 struct heredoc *p;
9943                 int i;
9944
9945                 if (quoteflag == 0)
9946                         n->type = NXHERE;
9947                 TRACE(("Here document %d\n", n->type));
9948                 if (here->striptabs) {
9949                         while (*wordtext == '\t')
9950                                 wordtext++;
9951                 }
9952                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9953                         synerror("Illegal eof marker for << redirection");
9954                 rmescapes(wordtext);
9955                 here->eofmark = wordtext;
9956                 here->next = NULL;
9957                 if (heredoclist == NULL)
9958                         heredoclist = here;
9959                 else {
9960                         for (p = heredoclist ; p->next ; p = p->next);
9961                         p->next = here;
9962                 }
9963         } else if (n->type == NTOFD || n->type == NFROMFD) {
9964                 fixredir(n, wordtext, 0);
9965         } else {
9966                 n->nfile.fname = makename();
9967         }
9968 }
9969
9970
9971 /*
9972  * Input any here documents.
9973  */
9974
9975 static void
9976 parseheredoc() {
9977         struct heredoc *here;
9978         union node *n;
9979
9980         while (heredoclist) {
9981                 here = heredoclist;
9982                 heredoclist = here->next;
9983                 if (needprompt) {
9984                         setprompt(2);
9985                         needprompt = 0;
9986                 }
9987                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9988                                 here->eofmark, here->striptabs);
9989                 n = (union node *)stalloc(sizeof (struct narg));
9990                 n->narg.type = NARG;
9991                 n->narg.next = NULL;
9992                 n->narg.text = wordtext;
9993                 n->narg.backquote = backquotelist;
9994                 here->here->nhere.doc = n;
9995         }
9996 }
9997
9998 static char
9999 peektoken() {
10000         int t;
10001
10002         t = readtoken();
10003         tokpushback++;
10004         return tokname_array[t][0];
10005 }
10006
10007 static int
10008 readtoken() {
10009         int t;
10010
10011 #ifdef ASH_ALIAS
10012         int savecheckalias = checkalias;
10013         int savecheckkwd = checkkwd;
10014         struct alias *ap;
10015 #endif
10016
10017 #ifdef DEBUG
10018         int alreadyseen = tokpushback;
10019 #endif
10020
10021 #ifdef ASH_ALIAS
10022 top:
10023 #endif
10024
10025         t = xxreadtoken();
10026
10027 #ifdef ASH_ALIAS
10028         checkalias = savecheckalias;
10029 #endif
10030
10031         if (checkkwd) {
10032                 /*
10033                  * eat newlines
10034                  */
10035                 if (checkkwd == 2) {
10036                         checkkwd = 0;
10037                         while (t == TNL) {
10038                                 parseheredoc();
10039                                 t = xxreadtoken();
10040                         }
10041                 }
10042                 checkkwd = 0;
10043                 /*
10044                  * check for keywords
10045                  */
10046                 if (t == TWORD && !quoteflag)
10047                 {
10048                         const char *const *pp;
10049
10050                         if ((pp = findkwd(wordtext))) {
10051                                 lasttoken = t = pp - tokname_array;
10052                                 TRACE(("keyword %s recognized\n", tokname(t)));
10053                                 goto out;
10054                         }
10055                 }
10056         }
10057
10058
10059         if (t != TWORD) {
10060                 if (t != TREDIR) {
10061                         checkalias = 0;
10062                 }
10063         } else if (checkalias == 2 && isassignment(wordtext)) {
10064                 lasttoken = t = TASSIGN;
10065 #ifdef ASH_ALIAS
10066         } else if (checkalias) {
10067                 if (!quoteflag && (ap = *__lookupalias(wordtext)) != NULL && !(ap->flag & ALIASINUSE)) {
10068                         if (*ap->val) {
10069                                 pushstring(ap->val, strlen(ap->val), ap);
10070                         }
10071                         checkkwd = savecheckkwd;
10072                         goto top;
10073                 }
10074                 checkalias = 0;
10075 #endif
10076         }
10077 out:
10078 #ifdef DEBUG
10079         if (!alreadyseen)
10080             TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10081         else
10082             TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10083 #endif
10084         return (t);
10085 }
10086
10087
10088 /*
10089  * Read the next input token.
10090  * If the token is a word, we set backquotelist to the list of cmds in
10091  *      backquotes.  We set quoteflag to true if any part of the word was
10092  *      quoted.
10093  * If the token is TREDIR, then we set redirnode to a structure containing
10094  *      the redirection.
10095  * In all cases, the variable startlinno is set to the number of the line
10096  *      on which the token starts.
10097  *
10098  * [Change comment:  here documents and internal procedures]
10099  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10100  *  word parsing code into a separate routine.  In this case, readtoken
10101  *  doesn't need to have any internal procedures, but parseword does.
10102  *  We could also make parseoperator in essence the main routine, and
10103  *  have parseword (readtoken1?) handle both words and redirection.]
10104  */
10105
10106 #define NEW_xxreadtoken
10107 #ifdef NEW_xxreadtoken
10108
10109 static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */
10110 static const char xxreadtoken_tokens[] = {
10111         TNL, TLP, TRP,                          /* only single occurrence allowed */
10112         TBACKGND, TPIPE, TSEMI,         /* if single occurrence */
10113         TEOF,                                           /* corresponds to trailing nul */
10114         TAND, TOR, TENDCASE,            /* if double occurrence */
10115 };
10116
10117 #define xxreadtoken_doubles \
10118         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10119 #define xxreadtoken_singles \
10120         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10121
10122 static int
10123 xxreadtoken() {
10124         int c;
10125
10126         if (tokpushback) {
10127                 tokpushback = 0;
10128                 return lasttoken;
10129         }
10130         if (needprompt) {
10131                 setprompt(2);
10132                 needprompt = 0;
10133         }
10134         startlinno = plinno;
10135         for (;;) {      /* until token or start of word found */
10136                 c = pgetc_macro();
10137
10138                 if ((c!=' ') && (c!='\t')
10139 #ifdef ASH_ALIAS
10140                         && (c!=PEOA)
10141 #endif
10142                         ) {
10143                         if (c=='#') {
10144                                 while ((c = pgetc()) != '\n' && c != PEOF);
10145                                 pungetc();
10146                         } else if (c=='\\') {
10147                                 if (pgetc() != '\n') {
10148                                         pungetc();
10149                                         goto READTOKEN1;
10150                                 }
10151                                 startlinno = ++plinno;
10152                                 setprompt(doprompt ? 2 : 0);
10153                         } else {
10154                                 const char *p
10155                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10156
10157                                 if (c!=PEOF) {
10158                                         if (c=='\n') {
10159                                                 plinno++;
10160                                                 needprompt = doprompt;
10161                                         }
10162
10163                                         p = strchr(xxreadtoken_chars, c);
10164                                         if (p == NULL) {
10165                                         READTOKEN1:
10166                                                 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10167                                         }
10168                         
10169                                         if (p-xxreadtoken_chars >= xxreadtoken_singles) {
10170                                                 if (pgetc() == *p) { /* double occurrence? */
10171                                                         p += xxreadtoken_doubles + 1;
10172                                                 } else {
10173                                                         pungetc();
10174                                                 }
10175                                         }
10176                                 }
10177
10178                                 return lasttoken = xxreadtoken_tokens[p-xxreadtoken_chars];
10179                         }
10180                 }
10181         }
10182 }
10183
10184
10185 #else
10186 #define RETURN(token)   return lasttoken = token
10187
10188 static int
10189 xxreadtoken() {
10190         int c;
10191
10192         if (tokpushback) {
10193                 tokpushback = 0;
10194                 return lasttoken;
10195         }
10196         if (needprompt) {
10197                 setprompt(2);
10198                 needprompt = 0;
10199         }
10200         startlinno = plinno;
10201         for (;;) {      /* until token or start of word found */
10202                 c = pgetc_macro();
10203                 switch (c) {
10204                 case ' ': case '\t':
10205 #ifdef ASH_ALIAS
10206                 case PEOA:
10207 #endif
10208                         continue;
10209                 case '#':
10210                         while ((c = pgetc()) != '\n' && c != PEOF);
10211                         pungetc();
10212                         continue;
10213                 case '\\':
10214                         if (pgetc() == '\n') {
10215                                 startlinno = ++plinno;
10216                                 if (doprompt)
10217                                         setprompt(2);
10218                                 else
10219                                         setprompt(0);
10220                                 continue;
10221                         }
10222                         pungetc();
10223                         goto breakloop;
10224                 case '\n':
10225                         plinno++;
10226                         needprompt = doprompt;
10227                         RETURN(TNL);
10228                 case PEOF:
10229                         RETURN(TEOF);
10230                 case '&':
10231                         if (pgetc() == '&')
10232                                 RETURN(TAND);
10233                         pungetc();
10234                         RETURN(TBACKGND);
10235                 case '|':
10236                         if (pgetc() == '|')
10237                                 RETURN(TOR);
10238                         pungetc();
10239                         RETURN(TPIPE);
10240                 case ';':
10241                         if (pgetc() == ';')
10242                                 RETURN(TENDCASE);
10243                         pungetc();
10244                         RETURN(TSEMI);
10245                 case '(':
10246                         RETURN(TLP);
10247                 case ')':
10248                         RETURN(TRP);
10249                 default:
10250                         goto breakloop;
10251                 }
10252         }
10253 breakloop:
10254         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10255 #undef RETURN
10256 }
10257 #endif
10258
10259 /*
10260  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10261  * is not NULL, read a here document.  In the latter case, eofmark is the
10262  * word which marks the end of the document and striptabs is true if
10263  * leading tabs should be stripped from the document.  The argument firstc
10264  * is the first character of the input token or document.
10265  *
10266  * Because C does not have internal subroutines, I have simulated them
10267  * using goto's to implement the subroutine linkage.  The following macros
10268  * will run code that appears at the end of readtoken1.
10269  */
10270
10271 #define CHECKEND()      {goto checkend; checkend_return:;}
10272 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10273 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10274 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10275 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10276 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10277
10278 static int
10279 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10280 {
10281         int c = firstc;
10282         char *out;
10283         int len;
10284         char line[EOFMARKLEN + 1];
10285         struct nodelist *bqlist;
10286         int quotef;
10287         int dblquote;
10288         int varnest;    /* levels of variables expansion */
10289         int arinest;    /* levels of arithmetic expansion */
10290         int parenlevel; /* levels of parens in arithmetic */
10291         int dqvarnest;  /* levels of variables expansion within double quotes */
10292         int oldstyle;
10293         int prevsyntax; /* syntax before arithmetic */
10294 #if __GNUC__
10295         /* Avoid longjmp clobbering */
10296         (void) &out;
10297         (void) &quotef;
10298         (void) &dblquote;
10299         (void) &varnest;
10300         (void) &arinest;
10301         (void) &parenlevel;
10302         (void) &dqvarnest;
10303         (void) &oldstyle;
10304         (void) &prevsyntax;
10305         (void) &syntax;
10306 #endif
10307
10308         startlinno = plinno;
10309         dblquote = 0;
10310         if (syntax == DQSYNTAX)
10311                 dblquote = 1;
10312         quotef = 0;
10313         bqlist = NULL;
10314         varnest = 0;
10315         arinest = 0;
10316         parenlevel = 0;
10317         dqvarnest = 0;
10318
10319         STARTSTACKSTR(out);
10320         loop: { /* for each line, until end of word */
10321                 CHECKEND();     /* set c to PEOF if at end of here document */
10322                 for (;;) {      /* until end of line or end of word */
10323                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10324                         switch(SIT(c,syntax)) {
10325                         case CNL:       /* '\n' */
10326                                 if (syntax == BASESYNTAX)
10327                                         goto endword;   /* exit outer loop */
10328                                 USTPUTC(c, out);
10329                                 plinno++;
10330                                 if (doprompt)
10331                                         setprompt(2);
10332                                 else
10333                                         setprompt(0);
10334                                 c = pgetc();
10335                                 goto loop;              /* continue outer loop */
10336                         case CWORD:
10337                                 USTPUTC(c, out);
10338                                 break;
10339                         case CCTL:
10340                                 if ((eofmark == NULL || dblquote) &&
10341                                     dqvarnest == 0)
10342                                         USTPUTC(CTLESC, out);
10343                                 USTPUTC(c, out);
10344                                 break;
10345                         case CBACK:     /* backslash */
10346                                 c = pgetc2();
10347                                 if (c == PEOF) {
10348                                         USTPUTC('\\', out);
10349                                         pungetc();
10350                                 } else if (c == '\n') {
10351                                         if (doprompt)
10352                                                 setprompt(2);
10353                                         else
10354                                                 setprompt(0);
10355                                 } else {
10356                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10357                                                          && (c != '"' || eofmark != NULL))
10358                                                 USTPUTC('\\', out);
10359                                         if (SIT(c,SQSYNTAX) == CCTL)
10360                                                 USTPUTC(CTLESC, out);
10361                                         else if (eofmark == NULL)
10362                                                 USTPUTC(CTLQUOTEMARK, out);
10363                                         USTPUTC(c, out);
10364                                         quotef++;
10365                                 }
10366                                 break;
10367                         case CSQUOTE:
10368                                 if (eofmark == NULL)
10369                                         USTPUTC(CTLQUOTEMARK, out);
10370                                 syntax = SQSYNTAX;
10371                                 break;
10372                         case CDQUOTE:
10373                                 if (eofmark == NULL)
10374                                         USTPUTC(CTLQUOTEMARK, out);
10375                                 syntax = DQSYNTAX;
10376                                 dblquote = 1;
10377                                 break;
10378                         case CENDQUOTE:
10379                                 if (eofmark != NULL && arinest == 0 &&
10380                                     varnest == 0) {
10381                                         USTPUTC(c, out);
10382                                 } else {
10383                                         if (arinest) {
10384                                                 syntax = ARISYNTAX;
10385                                                 dblquote = 0;
10386                                         } else if (eofmark == NULL &&
10387                                                    dqvarnest == 0) {
10388                                                 syntax = BASESYNTAX;
10389                                                 dblquote = 0;
10390                                         }
10391                                         quotef++;
10392                                 }
10393                                 break;
10394                         case CVAR:      /* '$' */
10395                                 PARSESUB();             /* parse substitution */
10396                                 break;
10397                         case CENDVAR:   /* '}' */
10398                                 if (varnest > 0) {
10399                                         varnest--;
10400                                         if (dqvarnest > 0) {
10401                                                 dqvarnest--;
10402                                         }
10403                                         USTPUTC(CTLENDVAR, out);
10404                                 } else {
10405                                         USTPUTC(c, out);
10406                                 }
10407                                 break;
10408 #ifdef ASH_MATH_SUPPORT
10409                         case CLP:       /* '(' in arithmetic */
10410                                 parenlevel++;
10411                                 USTPUTC(c, out);
10412                                 break;
10413                         case CRP:       /* ')' in arithmetic */
10414                                 if (parenlevel > 0) {
10415                                         USTPUTC(c, out);
10416                                         --parenlevel;
10417                                 } else {
10418                                         if (pgetc() == ')') {
10419                                                 if (--arinest == 0) {
10420                                                         USTPUTC(CTLENDARI, out);
10421                                                         syntax = prevsyntax;
10422                                                         if (syntax == DQSYNTAX)
10423                                                                 dblquote = 1;
10424                                                         else
10425                                                                 dblquote = 0;
10426                                                 } else
10427                                                         USTPUTC(')', out);
10428                                         } else {
10429                                                 /*
10430                                                  * unbalanced parens
10431                                                  *  (don't 2nd guess - no error)
10432                                                  */
10433                                                 pungetc();
10434                                                 USTPUTC(')', out);
10435                                         }
10436                                 }
10437                                 break;
10438 #endif
10439                         case CBQUOTE:   /* '`' */
10440                                 PARSEBACKQOLD();
10441                                 break;
10442                         case CENDFILE:
10443                                 goto endword;           /* exit outer loop */
10444                         case CIGN:
10445                                 break;
10446                         default:
10447                                 if (varnest == 0)
10448                                         goto endword;   /* exit outer loop */
10449 #ifdef ASH_ALIAS
10450                                 if (c != PEOA)
10451 #endif
10452                                         USTPUTC(c, out);
10453
10454                         }
10455                         c = pgetc_macro();
10456                 }
10457         }
10458 endword:
10459         if (syntax == ARISYNTAX)
10460                 synerror("Missing '))'");
10461         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10462                 synerror("Unterminated quoted string");
10463         if (varnest != 0) {
10464                 startlinno = plinno;
10465                 synerror("Missing '}'");
10466         }
10467         USTPUTC('\0', out);
10468         len = out - stackblock();
10469         out = stackblock();
10470         if (eofmark == NULL) {
10471                 if ((c == '>' || c == '<')
10472                  && quotef == 0
10473                  && len <= 2
10474                  && (*out == '\0' || is_digit(*out))) {
10475                         PARSEREDIR();
10476                         return lasttoken = TREDIR;
10477                 } else {
10478                         pungetc();
10479                 }
10480         }
10481         quoteflag = quotef;
10482         backquotelist = bqlist;
10483         grabstackblock(len);
10484         wordtext = out;
10485         return lasttoken = TWORD;
10486 /* end of readtoken routine */
10487
10488
10489
10490 /*
10491  * Check to see whether we are at the end of the here document.  When this
10492  * is called, c is set to the first character of the next input line.  If
10493  * we are at the end of the here document, this routine sets the c to PEOF.
10494  */
10495
10496 checkend: {
10497         if (eofmark) {
10498 #ifdef ASH_ALIAS
10499                 if (c == PEOA) {
10500                         c = pgetc2();
10501                 }
10502 #endif
10503                 if (striptabs) {
10504                         while (c == '\t') {
10505                                 c = pgetc2();
10506                         }
10507                 }
10508                 if (c == *eofmark) {
10509                         if (pfgets(line, sizeof line) != NULL) {
10510                                 const char *p, *q;
10511
10512                                 p = line;
10513                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10514                                 if (*p == '\n' && *q == '\0') {
10515                                         c = PEOF;
10516                                         plinno++;
10517                                         needprompt = doprompt;
10518                                 } else {
10519                                         pushstring(line, strlen(line), NULL);
10520                                 }
10521                         }
10522                 }
10523         }
10524         goto checkend_return;
10525 }
10526
10527
10528 /*
10529  * Parse a redirection operator.  The variable "out" points to a string
10530  * specifying the fd to be redirected.  The variable "c" contains the
10531  * first character of the redirection operator.
10532  */
10533
10534 parseredir: {
10535         char fd = *out;
10536         union node *np;
10537
10538         np = (union node *)stalloc(sizeof (struct nfile));
10539         if (c == '>') {
10540                 np->nfile.fd = 1;
10541                 c = pgetc();
10542                 if (c == '>')
10543                         np->type = NAPPEND;
10544                 else if (c == '&')
10545                         np->type = NTOFD;
10546                 else if (c == '|')
10547                         np->type = NTOOV;
10548                 else {
10549                         np->type = NTO;
10550                         pungetc();
10551                 }
10552         } else {        /* c == '<' */
10553                 np->nfile.fd = 0;
10554                 switch (c = pgetc()) {
10555                 case '<':
10556                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10557                                 np = (union node *)stalloc(sizeof (struct nhere));
10558                                 np->nfile.fd = 0;
10559                         }
10560                         np->type = NHERE;
10561                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10562                         heredoc->here = np;
10563                         if ((c = pgetc()) == '-') {
10564                                 heredoc->striptabs = 1;
10565                         } else {
10566                                 heredoc->striptabs = 0;
10567                                 pungetc();
10568                         }
10569                         break;
10570
10571                 case '&':
10572                         np->type = NFROMFD;
10573                         break;
10574
10575                 case '>':
10576                         np->type = NFROMTO;
10577                         break;
10578
10579                 default:
10580                         np->type = NFROM;
10581                         pungetc();
10582                         break;
10583                 }
10584         }
10585         if (fd != '\0')
10586                 np->nfile.fd = digit_val(fd);
10587         redirnode = np;
10588         goto parseredir_return;
10589 }
10590
10591
10592 /*
10593  * Parse a substitution.  At this point, we have read the dollar sign
10594  * and nothing else.
10595  */
10596
10597 parsesub: {
10598         int subtype;
10599         int typeloc;
10600         int flags;
10601         char *p;
10602         static const char types[] = "}-+?=";
10603
10604         c = pgetc();
10605         if (
10606                 c <= PEOA  ||
10607                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10608         ) {
10609                 USTPUTC('$', out);
10610                 pungetc();
10611         } else if (c == '(') {  /* $(command) or $((arith)) */
10612                 if (pgetc() == '(') {
10613                         PARSEARITH();
10614                 } else {
10615                         pungetc();
10616                         PARSEBACKQNEW();
10617                 }
10618         } else {
10619                 USTPUTC(CTLVAR, out);
10620                 typeloc = out - stackblock();
10621                 USTPUTC(VSNORMAL, out);
10622                 subtype = VSNORMAL;
10623                 if (c == '{') {
10624                         c = pgetc();
10625                         if (c == '#') {
10626                                 if ((c = pgetc()) == '}')
10627                                         c = '#';
10628                                 else
10629                                         subtype = VSLENGTH;
10630                         }
10631                         else
10632                                 subtype = 0;
10633                 }
10634                 if (c > PEOA && is_name(c)) {
10635                         do {
10636                                 STPUTC(c, out);
10637                                 c = pgetc();
10638                         } while (c > PEOA && is_in_name(c));
10639                 } else if (is_digit(c)) {
10640                         do {
10641                                 USTPUTC(c, out);
10642                                 c = pgetc();
10643                         } while (is_digit(c));
10644                 }
10645                 else if (is_special(c)) {
10646                         USTPUTC(c, out);
10647                         c = pgetc();
10648                 }
10649                 else
10650 badsub:                 synerror("Bad substitution");
10651
10652                 STPUTC('=', out);
10653                 flags = 0;
10654                 if (subtype == 0) {
10655                         switch (c) {
10656                         case ':':
10657                                 flags = VSNUL;
10658                                 c = pgetc();
10659                                 /*FALLTHROUGH*/
10660                         default:
10661                                 p = strchr(types, c);
10662                                 if (p == NULL)
10663                                         goto badsub;
10664                                 subtype = p - types + VSNORMAL;
10665                                 break;
10666                         case '%':
10667                         case '#':
10668                                 {
10669                                         int cc = c;
10670                                         subtype = c == '#' ? VSTRIMLEFT :
10671                                                              VSTRIMRIGHT;
10672                                         c = pgetc();
10673                                         if (c == cc)
10674                                                 subtype++;
10675                                         else
10676                                                 pungetc();
10677                                         break;
10678                                 }
10679                         }
10680                 } else {
10681                         pungetc();
10682                 }
10683                 if (dblquote || arinest)
10684                         flags |= VSQUOTE;
10685                 *(stackblock() + typeloc) = subtype | flags;
10686                 if (subtype != VSNORMAL) {
10687                         varnest++;
10688                         if (dblquote) {
10689                                 dqvarnest++;
10690                         }
10691                 }
10692         }
10693         goto parsesub_return;
10694 }
10695
10696
10697 /*
10698  * Called to parse command substitutions.  Newstyle is set if the command
10699  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10700  * list of commands (passed by reference), and savelen is the number of
10701  * characters on the top of the stack which must be preserved.
10702  */
10703
10704 parsebackq: {
10705         struct nodelist **nlpp;
10706         int savepbq;
10707         union node *n;
10708         char *volatile str;
10709         struct jmploc jmploc;
10710         struct jmploc *volatile savehandler;
10711         int savelen;
10712         int saveprompt;
10713 #ifdef __GNUC__
10714         (void) &saveprompt;
10715 #endif
10716
10717         savepbq = parsebackquote;
10718         if (setjmp(jmploc.loc)) {
10719                 if (str)
10720                         ckfree(str);
10721                 parsebackquote = 0;
10722                 handler = savehandler;
10723                 longjmp(handler->loc, 1);
10724         }
10725         INTOFF;
10726         str = NULL;
10727         savelen = out - stackblock();
10728         if (savelen > 0) {
10729                 str = xmalloc(savelen);
10730                 memcpy(str, stackblock(), savelen);
10731         }
10732         savehandler = handler;
10733         handler = &jmploc;
10734         INTON;
10735         if (oldstyle) {
10736                 /* We must read until the closing backquote, giving special
10737                    treatment to some slashes, and then push the string and
10738                    reread it as input, interpreting it normally.  */
10739                 char *pout;
10740                 int pc;
10741                 int psavelen;
10742                 char *pstr;
10743
10744
10745                 STARTSTACKSTR(pout);
10746                 for (;;) {
10747                         if (needprompt) {
10748                                 setprompt(2);
10749                                 needprompt = 0;
10750                         }
10751                         switch (pc = pgetc()) {
10752                         case '`':
10753                                 goto done;
10754
10755                         case '\\':
10756                                 if ((pc = pgetc()) == '\n') {
10757                                         plinno++;
10758                                         if (doprompt)
10759                                                 setprompt(2);
10760                                         else
10761                                                 setprompt(0);
10762                                         /*
10763                                          * If eating a newline, avoid putting
10764                                          * the newline into the new character
10765                                          * stream (via the STPUTC after the
10766                                          * switch).
10767                                          */
10768                                         continue;
10769                                 }
10770                                 if (pc != '\\' && pc != '`' && pc != '$'
10771                                     && (!dblquote || pc != '"'))
10772                                         STPUTC('\\', pout);
10773                                 if (pc > PEOA) {
10774                                         break;
10775                                 }
10776                                 /* fall through */
10777
10778                         case PEOF:
10779 #ifdef ASH_ALIAS
10780                         case PEOA:
10781 #endif
10782                                 startlinno = plinno;
10783                                 synerror("EOF in backquote substitution");
10784
10785                         case '\n':
10786                                 plinno++;
10787                                 needprompt = doprompt;
10788                                 break;
10789
10790                         default:
10791                                 break;
10792                         }
10793                         STPUTC(pc, pout);
10794                 }
10795 done:
10796                 STPUTC('\0', pout);
10797                 psavelen = pout - stackblock();
10798                 if (psavelen > 0) {
10799                         pstr = grabstackstr(pout);
10800                         setinputstring(pstr);
10801                 }
10802         }
10803         nlpp = &bqlist;
10804         while (*nlpp)
10805                 nlpp = &(*nlpp)->next;
10806         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10807         (*nlpp)->next = NULL;
10808         parsebackquote = oldstyle;
10809
10810         if (oldstyle) {
10811                 saveprompt = doprompt;
10812                 doprompt = 0;
10813         }
10814
10815         n = list(0);
10816
10817         if (oldstyle)
10818                 doprompt = saveprompt;
10819         else {
10820                 if (readtoken() != TRP)
10821                         synexpect(TRP);
10822         }
10823
10824         (*nlpp)->n = n;
10825         if (oldstyle) {
10826                 /*
10827                  * Start reading from old file again, ignoring any pushed back
10828                  * tokens left from the backquote parsing
10829                  */
10830                 popfile();
10831                 tokpushback = 0;
10832         }
10833         while (stackblocksize() <= savelen)
10834                 growstackblock();
10835         STARTSTACKSTR(out);
10836         if (str) {
10837                 memcpy(out, str, savelen);
10838                 STADJUST(savelen, out);
10839                 INTOFF;
10840                 ckfree(str);
10841                 str = NULL;
10842                 INTON;
10843         }
10844         parsebackquote = savepbq;
10845         handler = savehandler;
10846         if (arinest || dblquote)
10847                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10848         else
10849                 USTPUTC(CTLBACKQ, out);
10850         if (oldstyle)
10851                 goto parsebackq_oldreturn;
10852         else
10853                 goto parsebackq_newreturn;
10854 }
10855
10856 /*
10857  * Parse an arithmetic expansion (indicate start of one and set state)
10858  */
10859 parsearith: {
10860
10861         if (++arinest == 1) {
10862                 prevsyntax = syntax;
10863                 syntax = ARISYNTAX;
10864                 USTPUTC(CTLARI, out);
10865                 if (dblquote)
10866                         USTPUTC('"',out);
10867                 else
10868                         USTPUTC(' ',out);
10869         } else {
10870                 /*
10871                  * we collapse embedded arithmetic expansion to
10872                  * parenthesis, which should be equivalent
10873                  */
10874                 USTPUTC('(', out);
10875         }
10876         goto parsearith_return;
10877 }
10878
10879 } /* end of readtoken */
10880
10881
10882 /*
10883  * Returns true if the text contains nothing to expand (no dollar signs
10884  * or backquotes).
10885  */
10886
10887 static int
10888 noexpand(char *text)
10889 {
10890         char *p;
10891         char c;
10892
10893         p = text;
10894         while ((c = *p++) != '\0') {
10895                 if (c == CTLQUOTEMARK)
10896                         continue;
10897                 if (c == CTLESC)
10898                         p++;
10899                 else if (SIT(c,BASESYNTAX) == CCTL)
10900                         return 0;
10901         }
10902         return 1;
10903 }
10904
10905
10906 /*
10907  * Return true if the argument is a legal variable name (a letter or
10908  * underscore followed by zero or more letters, underscores, and digits).
10909  */
10910
10911 static int
10912 goodname(const char *name)
10913 {
10914         const char *p;
10915
10916         p = name;
10917         if (! is_name(*p))
10918                 return 0;
10919         while (*++p) {
10920                 if (! is_in_name(*p))
10921                         return 0;
10922         }
10923         return 1;
10924 }
10925
10926
10927 /*
10928  * Called when an unexpected token is read during the parse.  The argument
10929  * is the token that is expected, or -1 if more than one type of token can
10930  * occur at this point.
10931  */
10932
10933 static void
10934 synexpect(int token)
10935 {
10936         char msg[64];
10937         int l;
10938
10939         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10940         if (token >= 0)
10941                 sprintf(msg+l, " (expecting %s)", tokname(token));
10942         synerror(msg);
10943         /* NOTREACHED */
10944 }
10945
10946
10947 static void
10948 synerror(const char *msg)
10949 {
10950         if (commandname)
10951                 out2fmt("%s: %d: ", commandname, startlinno);
10952         out2fmt("Syntax error: %s\n", msg);
10953         error((char *)NULL);
10954         /* NOTREACHED */
10955 }
10956
10957
10958 /*
10959  * called by editline -- any expansions to the prompt
10960  *    should be added here.
10961  */
10962 static void
10963 setprompt(int whichprompt)
10964 {
10965     char *prompt;
10966     switch (whichprompt) {
10967         case 1:
10968                 prompt = ps1val();
10969                 break;
10970         case 2:
10971                 prompt = ps2val();
10972                 break;
10973         default:                /* 0 */
10974                 prompt = "";
10975     }
10976     putprompt(prompt);
10977 }
10978
10979
10980 /*
10981  * Code for dealing with input/output redirection.
10982  */
10983
10984 #define EMPTY -2                /* marks an unused slot in redirtab */
10985 #ifndef PIPE_BUF
10986 # define PIPESIZE 4096          /* amount of buffering in a pipe */
10987 #else
10988 # define PIPESIZE PIPE_BUF
10989 #endif
10990
10991
10992 /*
10993  * Open a file in noclobber mode.
10994  * The code was copied from bash.
10995  */
10996 static inline int
10997 noclobberopen(const char *fname)
10998 {
10999         int r, fd;
11000         struct stat finfo, finfo2;
11001
11002         /*
11003          * If the file exists and is a regular file, return an error
11004          * immediately.
11005          */
11006         r = stat(fname, &finfo);
11007         if (r == 0 && S_ISREG(finfo.st_mode)) {
11008                 errno = EEXIST;
11009                 return -1;
11010         }
11011
11012         /*
11013          * If the file was not present (r != 0), make sure we open it
11014          * exclusively so that if it is created before we open it, our open
11015          * will fail.  Make sure that we do not truncate an existing file.
11016          * Note that we don't turn on O_EXCL unless the stat failed -- if the
11017          * file was not a regular file, we leave O_EXCL off.
11018          */
11019         if (r != 0)
11020                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11021         fd = open(fname, O_WRONLY|O_CREAT, 0666);
11022
11023         /* If the open failed, return the file descriptor right away. */
11024         if (fd < 0)
11025                 return fd;
11026
11027         /*
11028          * OK, the open succeeded, but the file may have been changed from a
11029          * non-regular file to a regular file between the stat and the open.
11030          * We are assuming that the O_EXCL open handles the case where FILENAME
11031          * did not exist and is symlinked to an existing file between the stat
11032          * and open.
11033          */
11034
11035         /*
11036          * If we can open it and fstat the file descriptor, and neither check
11037          * revealed that it was a regular file, and the file has not been
11038          * replaced, return the file descriptor.
11039          */
11040          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11041              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11042                 return fd;
11043
11044         /* The file has been replaced.  badness. */
11045         close(fd);
11046         errno = EEXIST;
11047         return -1;
11048 }
11049
11050 /*
11051  * Handle here documents.  Normally we fork off a process to write the
11052  * data to a pipe.  If the document is short, we can stuff the data in
11053  * the pipe without forking.
11054  */
11055
11056 static inline int
11057 openhere(const union node *redir)
11058 {
11059         int pip[2];
11060         int len = 0;
11061
11062         if (pipe(pip) < 0)
11063                 error("Pipe call failed");
11064         if (redir->type == NHERE) {
11065                 len = strlen(redir->nhere.doc->narg.text);
11066                 if (len <= PIPESIZE) {
11067                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11068                         goto out;
11069                 }
11070         }
11071         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11072                 close(pip[0]);
11073                 signal(SIGINT, SIG_IGN);
11074                 signal(SIGQUIT, SIG_IGN);
11075                 signal(SIGHUP, SIG_IGN);
11076 #ifdef SIGTSTP
11077                 signal(SIGTSTP, SIG_IGN);
11078 #endif
11079                 signal(SIGPIPE, SIG_DFL);
11080                 if (redir->type == NHERE)
11081                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11082                 else
11083                         expandhere(redir->nhere.doc, pip[1]);
11084                 _exit(0);
11085         }
11086 out:
11087         close(pip[1]);
11088         return pip[0];
11089 }
11090
11091
11092 static inline int
11093 openredirect(const union node *redir)
11094 {
11095         char *fname;
11096         int f;
11097
11098         switch (redir->nfile.type) {
11099         case NFROM:
11100                 fname = redir->nfile.expfname;
11101                 if ((f = open(fname, O_RDONLY)) < 0)
11102                         goto eopen;
11103                 break;
11104         case NFROMTO:
11105                 fname = redir->nfile.expfname;
11106                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11107                         goto ecreate;
11108                 break;
11109         case NTO:
11110                 /* Take care of noclobber mode. */
11111                 if (Cflag) {
11112                         fname = redir->nfile.expfname;
11113                         if ((f = noclobberopen(fname)) < 0)
11114                                 goto ecreate;
11115                         break;
11116                 }
11117         case NTOOV:
11118                 fname = redir->nfile.expfname;
11119 #ifdef O_CREAT
11120                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11121                         goto ecreate;
11122 #else
11123                 if ((f = creat(fname, 0666)) < 0)
11124                         goto ecreate;
11125 #endif
11126                 break;
11127         case NAPPEND:
11128                 fname = redir->nfile.expfname;
11129 #ifdef O_APPEND
11130                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11131                         goto ecreate;
11132 #else
11133                 if ((f = open(fname, O_WRONLY)) < 0
11134                  && (f = creat(fname, 0666)) < 0)
11135                         goto ecreate;
11136                 lseek(f, (off_t)0, 2);
11137 #endif
11138                 break;
11139         default:
11140 #ifdef DEBUG
11141                 abort();
11142 #endif
11143                 /* Fall through to eliminate warning. */
11144         case NTOFD:
11145         case NFROMFD:
11146                 f = -1;
11147                 break;
11148         case NHERE:
11149         case NXHERE:
11150                 f = openhere(redir);
11151                 break;
11152         }
11153
11154         return f;
11155 ecreate:
11156         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11157 eopen:
11158         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11159 }
11160
11161
11162 /*
11163  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11164  * old file descriptors are stashed away so that the redirection can be
11165  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11166  * standard output, and the standard error if it becomes a duplicate of
11167  * stdout.
11168  */
11169
11170 static void
11171 redirect(union node *redir, int flags)
11172 {
11173         union node *n;
11174         struct redirtab *sv = NULL;
11175         int i;
11176         int fd;
11177         int newfd;
11178         int try;
11179         int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11180
11181         if (flags & REDIR_PUSH) {
11182                 sv = xmalloc(sizeof (struct redirtab));
11183                 for (i = 0 ; i < 10 ; i++)
11184                         sv->renamed[i] = EMPTY;
11185                 sv->next = redirlist;
11186                 redirlist = sv;
11187         }
11188         for (n = redir ; n ; n = n->nfile.next) {
11189                 fd = n->nfile.fd;
11190                 try = 0;
11191                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11192                     n->ndup.dupfd == fd)
11193                         continue; /* redirect from/to same file descriptor */
11194
11195                 INTOFF;
11196                 newfd = openredirect(n);
11197                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11198                         if (newfd == fd) {
11199                                 try++;
11200                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11201                                 switch (errno) {
11202                                 case EBADF:
11203                                         if (!try) {
11204                                                 dupredirect(n, newfd, fd1dup);
11205                                                 try++;
11206                                                 break;
11207                                         }
11208                                         /* FALLTHROUGH*/
11209                                 default:
11210                                         if (newfd >= 0) {
11211                                                 close(newfd);
11212                                         }
11213                                         INTON;
11214                                         error("%d: %m", fd);
11215                                         /* NOTREACHED */
11216                                 }
11217                         }
11218                         if (!try) {
11219                                 close(fd);
11220                                 if (flags & REDIR_PUSH) {
11221                                         sv->renamed[fd] = i;
11222                                 }
11223                         }
11224                 } else if (fd != newfd) {
11225                         close(fd);
11226                 }
11227                 if (fd == 0)
11228                         fd0_redirected++;
11229                 if (!try)
11230                         dupredirect(n, newfd, fd1dup);
11231                 INTON;
11232         }
11233 }
11234
11235
11236 static void
11237 dupredirect(const union node *redir, int f, int fd1dup)
11238 {
11239         int fd = redir->nfile.fd;
11240
11241         if(fd==1)
11242                 fd1dup = 0;
11243         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11244                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11245                         if (redir->ndup.dupfd!=1 || fd1dup!=1)
11246                                 dup_as_newfd(redir->ndup.dupfd, fd);
11247                 }
11248                 return;
11249         }
11250
11251         if (f != fd) {
11252                 dup_as_newfd(f, fd);
11253                 close(f);
11254         }
11255         return;
11256 }
11257
11258
11259
11260 /*
11261  * Undo the effects of the last redirection.
11262  */
11263
11264 static void
11265 popredir(void)
11266 {
11267         struct redirtab *rp = redirlist;
11268         int i;
11269
11270         INTOFF;
11271         for (i = 0 ; i < 10 ; i++) {
11272                 if (rp->renamed[i] != EMPTY) {
11273                         if (i == 0)
11274                                 fd0_redirected--;
11275                         close(i);
11276                         if (rp->renamed[i] >= 0) {
11277                                 dup_as_newfd(rp->renamed[i], i);
11278                                 close(rp->renamed[i]);
11279                         }
11280                 }
11281         }
11282         redirlist = rp->next;
11283         ckfree(rp);
11284         INTON;
11285 }
11286
11287 /*
11288  * Discard all saved file descriptors.
11289  */
11290
11291 static void
11292 clearredir(void) {
11293         struct redirtab *rp;
11294         int i;
11295
11296         for (rp = redirlist ; rp ; rp = rp->next) {
11297                 for (i = 0 ; i < 10 ; i++) {
11298                         if (rp->renamed[i] >= 0) {
11299                                 close(rp->renamed[i]);
11300                         }
11301                         rp->renamed[i] = EMPTY;
11302                 }
11303         }
11304 }
11305
11306
11307 /*
11308  * Copy a file descriptor to be >= to.  Returns -1
11309  * if the source file descriptor is closed, EMPTY if there are no unused
11310  * file descriptors left.
11311  */
11312
11313 static int
11314 dup_as_newfd(int from, int to)
11315 {
11316         int newfd;
11317
11318         newfd = fcntl(from, F_DUPFD, to);
11319         if (newfd < 0) {
11320                 if (errno == EMFILE)
11321                         return EMPTY;
11322                 else
11323                         error("%d: %m", from);
11324         }
11325         return newfd;
11326 }
11327
11328 #ifdef DEBUG
11329 /*
11330  * Debugging stuff.
11331  */
11332 static void shtree (union node *, int, char *, FILE*);
11333 static void shcmd (union node *, FILE *);
11334 static void sharg (union node *, FILE *);
11335 static void indent (int, char *, FILE *);
11336 static void trstring (char *);
11337
11338
11339 static void
11340 showtree(n)
11341         unode *n;
11342 {
11343         trputs("showtree called\n");
11344         shtree(n, 1, NULL, stdout);
11345 }
11346
11347
11348 static void
11349 shtree(union node *n, int ind, char *pfx, FILE *fp)
11350 {
11351         struct nodelist *lp;
11352         const char *s;
11353
11354         if (n == NULL)
11355                 return;
11356
11357         indent(ind, pfx, fp);
11358         switch(n->type) {
11359         case NSEMI:
11360                 s = "; ";
11361                 goto binop;
11362         case NAND:
11363                 s = " && ";
11364                 goto binop;
11365         case NOR:
11366                 s = " || ";
11367 binop:
11368                 shtree(n->nbinary.ch1, ind, NULL, fp);
11369            /*    if (ind < 0) */
11370                         fputs(s, fp);
11371                 shtree(n->nbinary.ch2, ind, NULL, fp);
11372                 break;
11373         case NCMD:
11374                 shcmd(n, fp);
11375                 if (ind >= 0)
11376                         putc('\n', fp);
11377                 break;
11378         case NPIPE:
11379                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11380                         shcmd(lp->n, fp);
11381                         if (lp->next)
11382                                 fputs(" | ", fp);
11383                 }
11384                 if (n->npipe.backgnd)
11385                         fputs(" &", fp);
11386                 if (ind >= 0)
11387                         putc('\n', fp);
11388                 break;
11389         default:
11390                 fprintf(fp, "<node type %d>", n->type);
11391                 if (ind >= 0)
11392                         putc('\n', fp);
11393                 break;
11394         }
11395 }
11396
11397
11398
11399 static void
11400 shcmd(union node *cmd, FILE *fp)
11401 {
11402         union node *np;
11403         int first;
11404         const char *s;
11405         int dftfd;
11406
11407         first = 1;
11408         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11409                 if (! first)
11410                         putchar(' ');
11411                 sharg(np, fp);
11412                 first = 0;
11413         }
11414         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11415                 if (! first)
11416                         putchar(' ');
11417 #if 1
11418                 s = "*error*";
11419                 dftfd = 0;
11420                 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11421                         s = redir_strings[np->nfile.type - NTO];
11422                         if (*s == '>') {
11423                                 dftfd = 1;
11424                         }
11425                 }
11426 #else
11427                 switch (np->nfile.type) {
11428                         case NTO:       s = ">";  dftfd = 1; break;
11429                         case NAPPEND:   s = ">>"; dftfd = 1; break;
11430                         case NTOFD:     s = ">&"; dftfd = 1; break;
11431                         case NTOOV:     s = ">|"; dftfd = 1; break;
11432                         case NFROM:     s = "<";  dftfd = 0; break;
11433                         case NFROMFD:   s = "<&"; dftfd = 0; break;
11434                         case NFROMTO:   s = "<>"; dftfd = 0; break;
11435                         default:        s = "*error*"; dftfd = 0; break;
11436                 }
11437 #endif
11438                 if (np->nfile.fd != dftfd)
11439                         fprintf(fp, "%d", np->nfile.fd);
11440                 fputs(s, fp);
11441                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11442                         fprintf(fp, "%d", np->ndup.dupfd);
11443                 } else {
11444                         sharg(np->nfile.fname, fp);
11445                 }
11446                 first = 0;
11447         }
11448 }
11449
11450 static void
11451 sharg(union node *arg, FILE *fp)
11452 {
11453         char *p;
11454         struct nodelist *bqlist;
11455         int subtype;
11456
11457         if (arg->type != NARG) {
11458                 printf("<node type %d>\n", arg->type);
11459                 fflush(stdout);
11460                 abort();
11461         }
11462         bqlist = arg->narg.backquote;
11463         for (p = arg->narg.text ; *p ; p++) {
11464                 switch (*p) {
11465                 case CTLESC:
11466                         putc(*++p, fp);
11467                         break;
11468                 case CTLVAR:
11469                         putc('$', fp);
11470                         putc('{', fp);
11471                         subtype = *++p;
11472                         if (subtype == VSLENGTH)
11473                                 putc('#', fp);
11474
11475                         while (*p != '=')
11476                                 putc(*p++, fp);
11477
11478                         if (subtype & VSNUL)
11479                                 putc(':', fp);
11480
11481                         switch (subtype & VSTYPE) {
11482                         case VSNORMAL:
11483                                 putc('}', fp);
11484                                 break;
11485                         case VSMINUS:
11486                                 putc('-', fp);
11487                                 break;
11488                         case VSPLUS:
11489                                 putc('+', fp);
11490                                 break;
11491                         case VSQUESTION:
11492                                 putc('?', fp);
11493                                 break;
11494                         case VSASSIGN:
11495                                 putc('=', fp);
11496                                 break;
11497                         case VSTRIMLEFT:
11498                                 putc('#', fp);
11499                                 break;
11500                         case VSTRIMLEFTMAX:
11501                                 putc('#', fp);
11502                                 putc('#', fp);
11503                                 break;
11504                         case VSTRIMRIGHT:
11505                                 putc('%', fp);
11506                                 break;
11507                         case VSTRIMRIGHTMAX:
11508                                 putc('%', fp);
11509                                 putc('%', fp);
11510                                 break;
11511                         case VSLENGTH:
11512                                 break;
11513                         default:
11514                                 printf("<subtype %d>", subtype);
11515                         }
11516                         break;
11517                 case CTLENDVAR:
11518                      putc('}', fp);
11519                      break;
11520                 case CTLBACKQ:
11521                 case CTLBACKQ|CTLQUOTE:
11522                         putc('$', fp);
11523                         putc('(', fp);
11524                         shtree(bqlist->n, -1, NULL, fp);
11525                         putc(')', fp);
11526                         break;
11527                 default:
11528                         putc(*p, fp);
11529                         break;
11530                 }
11531         }
11532 }
11533
11534
11535 static void
11536 indent(int amount, char *pfx, FILE *fp)
11537 {
11538         int i;
11539
11540         for (i = 0 ; i < amount ; i++) {
11541                 if (pfx && i == amount - 1)
11542                         fputs(pfx, fp);
11543                 putc('\t', fp);
11544         }
11545 }
11546
11547
11548 FILE *tracefile;
11549
11550 #if DEBUG == 2
11551 static int debug = 1;
11552 #else
11553 static int debug = 0;
11554 #endif
11555
11556
11557 static void
11558 trputc(int c)
11559 {
11560         if (tracefile == NULL)
11561                 return;
11562         putc(c, tracefile);
11563         if (c == '\n')
11564                 fflush(tracefile);
11565 }
11566
11567 static void
11568 trace(const char *fmt, ...)
11569 {
11570         va_list va;
11571         va_start(va, fmt);
11572         if (tracefile != NULL) {
11573                 (void) vfprintf(tracefile, fmt, va);
11574                 if (strchr(fmt, '\n'))
11575                         (void) fflush(tracefile);
11576         }
11577         va_end(va);
11578 }
11579
11580
11581 static void
11582 trputs(const char *s)
11583 {
11584         if (tracefile == NULL)
11585                 return;
11586         fputs(s, tracefile);
11587         if (strchr(s, '\n'))
11588                 fflush(tracefile);
11589 }
11590
11591
11592 static void
11593 trstring(char *s)
11594 {
11595         char *p;
11596         char c;
11597
11598         if (tracefile == NULL)
11599                 return;
11600         putc('"', tracefile);
11601         for (p = s ; *p ; p++) {
11602                 switch (*p) {
11603                 case '\n':  c = 'n';  goto backslash;
11604                 case '\t':  c = 't';  goto backslash;
11605                 case '\r':  c = 'r';  goto backslash;
11606                 case '"':  c = '"';  goto backslash;
11607                 case '\\':  c = '\\';  goto backslash;
11608                 case CTLESC:  c = 'e';  goto backslash;
11609                 case CTLVAR:  c = 'v';  goto backslash;
11610                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
11611                 case CTLBACKQ:  c = 'q';  goto backslash;
11612                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
11613 backslash:        putc('\\', tracefile);
11614                         putc(c, tracefile);
11615                         break;
11616                 default:
11617                         if (*p >= ' ' && *p <= '~')
11618                                 putc(*p, tracefile);
11619                         else {
11620                                 putc('\\', tracefile);
11621                                 putc(*p >> 6 & 03, tracefile);
11622                                 putc(*p >> 3 & 07, tracefile);
11623                                 putc(*p & 07, tracefile);
11624                         }
11625                         break;
11626                 }
11627         }
11628         putc('"', tracefile);
11629 }
11630
11631
11632 static void
11633 trargs(char **ap)
11634 {
11635         if (tracefile == NULL)
11636                 return;
11637         while (*ap) {
11638                 trstring(*ap++);
11639                 if (*ap)
11640                         putc(' ', tracefile);
11641                 else
11642                         putc('\n', tracefile);
11643         }
11644         fflush(tracefile);
11645 }
11646
11647
11648 static void
11649 opentrace()
11650 {
11651         char s[100];
11652 #ifdef O_APPEND
11653         int flags;
11654 #endif
11655
11656         if (!debug)
11657                 return;
11658 #ifdef not_this_way
11659         {
11660                 char *p;
11661                 if ((p = getenv("HOME")) == NULL) {
11662                         if (geteuid() == 0)
11663                                 p = "/";
11664                         else
11665                                 p = "/tmp";
11666                 }
11667                 strcpy(s, p);
11668                 strcat(s, "/trace");
11669         }
11670 #else
11671         strcpy(s, "./trace");
11672 #endif /* not_this_way */
11673         if ((tracefile = wfopen(s, "a")) == NULL)
11674                 return;
11675 #ifdef O_APPEND
11676         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11677                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11678 #endif
11679         fputs("\nTracing started.\n", tracefile);
11680         fflush(tracefile);
11681 }
11682 #endif /* DEBUG */
11683
11684
11685 /*
11686  * The trap builtin.
11687  */
11688
11689 static int
11690 trapcmd(int argc, char **argv)
11691 {
11692         char *action;
11693         char **ap;
11694         int signo;
11695
11696         if (argc <= 1) {
11697                 for (signo = 0 ; signo < NSIG ; signo++) {
11698                         if (trap[signo] != NULL) {
11699                                 char *p;
11700                                 const char *sn;
11701
11702                                 p = single_quote(trap[signo]);
11703                                 sn = sys_siglist[signo];
11704                                 if(sn==NULL)
11705                                         sn = u_signal_names(0, &signo, 0);
11706                                 if(sn==NULL)
11707                                         sn = "???";
11708                                 printf("trap -- %s %s\n", p, sn);
11709                                 stunalloc(p);
11710                         }
11711                 }
11712                 return 0;
11713         }
11714         ap = argv + 1;
11715         if (argc == 2)
11716                 action = NULL;
11717         else
11718                 action = *ap++;
11719         while (*ap) {
11720                 if ((signo = decode_signal(*ap, 0)) < 0)
11721                         error("%s: bad trap", *ap);
11722                 INTOFF;
11723                 if (action) {
11724                         if (action[0] == '-' && action[1] == '\0')
11725                                 action = NULL;
11726                         else
11727                                 action = xstrdup(action);
11728                 }
11729                 if (trap[signo])
11730                         ckfree(trap[signo]);
11731                 trap[signo] = action;
11732                 if (signo != 0)
11733                         setsignal(signo);
11734                 INTON;
11735                 ap++;
11736         }
11737         return 0;
11738 }
11739
11740
11741
11742
11743
11744
11745 /*
11746  * Set the signal handler for the specified signal.  The routine figures
11747  * out what it should be set to.
11748  */
11749
11750 static void
11751 setsignal(int signo)
11752 {
11753         int action;
11754         char *t;
11755         struct sigaction act;
11756
11757         if ((t = trap[signo]) == NULL)
11758                 action = S_DFL;
11759         else if (*t != '\0')
11760                 action = S_CATCH;
11761         else
11762                 action = S_IGN;
11763         if (rootshell && action == S_DFL) {
11764                 switch (signo) {
11765                 case SIGINT:
11766                         if (iflag || minusc || sflag == 0)
11767                                 action = S_CATCH;
11768                         break;
11769                 case SIGQUIT:
11770 #ifdef DEBUG
11771                         {
11772
11773                         if (debug)
11774                                 break;
11775                         }
11776 #endif
11777                         /* FALLTHROUGH */
11778                 case SIGTERM:
11779                         if (iflag)
11780                                 action = S_IGN;
11781                         break;
11782 #ifdef JOBS
11783                 case SIGTSTP:
11784                 case SIGTTOU:
11785                         if (mflag)
11786                                 action = S_IGN;
11787                         break;
11788 #endif
11789                 }
11790         }
11791
11792         t = &sigmode[signo - 1];
11793         if (*t == 0) {
11794                 /*
11795                  * current setting unknown
11796                  */
11797                 if (sigaction(signo, 0, &act) == -1) {
11798                         /*
11799                          * Pretend it worked; maybe we should give a warning
11800                          * here, but other shells don't. We don't alter
11801                          * sigmode, so that we retry every time.
11802                          */
11803                         return;
11804                 }
11805                 if (act.sa_handler == SIG_IGN) {
11806                         if (mflag && (signo == SIGTSTP ||
11807                              signo == SIGTTIN || signo == SIGTTOU)) {
11808                                 *t = S_IGN;     /* don't hard ignore these */
11809                         } else
11810                                 *t = S_HARD_IGN;
11811                 } else {
11812                         *t = S_RESET;   /* force to be set */
11813                 }
11814         }
11815         if (*t == S_HARD_IGN || *t == action)
11816                 return;
11817         act.sa_handler = ((action == S_CATCH) ? onsig
11818                                           : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
11819         *t = action;
11820         act.sa_flags = 0;
11821         sigemptyset(&act.sa_mask);
11822         sigaction(signo, &act, 0);
11823 }
11824
11825 /*
11826  * Ignore a signal.
11827  */
11828
11829 static void
11830 ignoresig(int signo)
11831 {
11832         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11833                 signal(signo, SIG_IGN);
11834         }
11835         sigmode[signo - 1] = S_HARD_IGN;
11836 }
11837
11838
11839 /*
11840  * Signal handler.
11841  */
11842
11843 static void
11844 onsig(int signo)
11845 {
11846         if (signo == SIGINT && trap[SIGINT] == NULL) {
11847                 onint();
11848                 return;
11849         }
11850         gotsig[signo - 1] = 1;
11851         pendingsigs++;
11852 }
11853
11854
11855 /*
11856  * Called to execute a trap.  Perhaps we should avoid entering new trap
11857  * handlers while we are executing a trap handler.
11858  */
11859
11860 static void
11861 dotrap(void)
11862 {
11863         int i;
11864         int savestatus;
11865
11866         for (;;) {
11867                 for (i = 1 ; ; i++) {
11868                         if (gotsig[i - 1])
11869                                 break;
11870                         if (i >= NSIG - 1)
11871                                 goto done;
11872                 }
11873                 gotsig[i - 1] = 0;
11874                 savestatus=exitstatus;
11875                 evalstring(trap[i], 0);
11876                 exitstatus=savestatus;
11877         }
11878 done:
11879         pendingsigs = 0;
11880 }
11881
11882 /*
11883  * Called to exit the shell.
11884  */
11885
11886 static void
11887 exitshell(int status)
11888 {
11889         struct jmploc loc1, loc2;
11890         char *p;
11891
11892         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
11893         if (setjmp(loc1.loc)) {
11894                 goto l1;
11895         }
11896         if (setjmp(loc2.loc)) {
11897                 goto l2;
11898         }
11899         handler = &loc1;
11900         if ((p = trap[0]) != NULL && *p != '\0') {
11901                 trap[0] = NULL;
11902                 evalstring(p, 0);
11903         }
11904 l1:   handler = &loc2;                  /* probably unnecessary */
11905         flushall();
11906 #ifdef JOBS
11907         setjobctl(0);
11908 #endif
11909 l2:   _exit(status);
11910         /* NOTREACHED */
11911 }
11912
11913 static int decode_signal(const char *string, int minsig)
11914 {
11915         int signo;
11916         const char *name = u_signal_names(string, &signo, minsig);
11917
11918         return name ? signo : -1;
11919 }
11920
11921 static struct var **hashvar (const char *);
11922 static void showvars (const char *, int, int);
11923 static struct var **findvar (struct var **, const char *);
11924
11925 /*
11926  * Initialize the varable symbol tables and import the environment
11927  */
11928
11929 /*
11930  * This routine initializes the builtin variables.  It is called when the
11931  * shell is initialized and again when a shell procedure is spawned.
11932  */
11933
11934 static void
11935 initvar() {
11936         const struct varinit *ip;
11937         struct var *vp;
11938         struct var **vpp;
11939
11940         for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
11941                 if ((vp->flags & VEXPORT) == 0) {
11942                         vpp = hashvar(ip->text);
11943                         vp->next = *vpp;
11944                         *vpp = vp;
11945                         vp->text = xstrdup(ip->text);
11946                         vp->flags = ip->flags;
11947                         vp->func = ip->func;
11948                 }
11949         }
11950         /*
11951          * PS1 depends on uid
11952          */
11953         if ((vps1.flags & VEXPORT) == 0) {
11954                 vpp = hashvar("PS1=");
11955                 vps1.next = *vpp;
11956                 *vpp = &vps1;
11957                 vps1.text = xstrdup(geteuid() ? "PS1=$ " : "PS1=# ");
11958                 vps1.flags = VSTRFIXED|VTEXTFIXED;
11959         }
11960 }
11961
11962 /*
11963  * Set the value of a variable.  The flags argument is ored with the
11964  * flags of the variable.  If val is NULL, the variable is unset.
11965  */
11966
11967 static void
11968 setvar(const char *name, const char *val, int flags)
11969 {
11970         const char *p;
11971         int len;
11972         int namelen;
11973         char *nameeq;
11974         int isbad;
11975         int vallen = 0;
11976
11977         isbad = 0;
11978         p = name;
11979         if (! is_name(*p))
11980                 isbad = 1;
11981         p++;
11982         for (;;) {
11983                 if (! is_in_name(*p)) {
11984                         if (*p == '\0' || *p == '=')
11985                                 break;
11986                         isbad = 1;
11987                 }
11988                 p++;
11989         }
11990         namelen = p - name;
11991         if (isbad)
11992                 error("%.*s: bad variable name", namelen, name);
11993         len = namelen + 2;              /* 2 is space for '=' and '\0' */
11994         if (val == NULL) {
11995                 flags |= VUNSET;
11996         } else {
11997                 len += vallen = strlen(val);
11998         }
11999         INTOFF;
12000         nameeq = xmalloc(len);
12001         memcpy(nameeq, name, namelen);
12002         nameeq[namelen] = '=';
12003         if (val) {
12004                 memcpy(nameeq + namelen + 1, val, vallen + 1);
12005         } else {
12006                 nameeq[namelen + 1] = '\0';
12007         }
12008         setvareq(nameeq, flags);
12009         INTON;
12010 }
12011
12012
12013
12014 /*
12015  * Same as setvar except that the variable and value are passed in
12016  * the first argument as name=value.  Since the first argument will
12017  * be actually stored in the table, it should not be a string that
12018  * will go away.
12019  */
12020
12021 static void
12022 setvareq(char *s, int flags)
12023 {
12024         struct var *vp, **vpp;
12025
12026         vpp = hashvar(s);
12027         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12028         if ((vp = *findvar(vpp, s))) {
12029                 if (vp->flags & VREADONLY) {
12030                         size_t len = strchr(s, '=') - s;
12031                         error("%.*s: is read only", len, s);
12032                 }
12033                 INTOFF;
12034
12035                 if (vp->func && (flags & VNOFUNC) == 0)
12036                         (*vp->func)(strchr(s, '=') + 1);
12037
12038                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12039                         ckfree(vp->text);
12040
12041                 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12042                 vp->flags |= flags;
12043                 vp->text = s;
12044
12045 #ifdef ASH_MAIL
12046                 /*
12047                  * We could roll this to a function, to handle it as
12048                  * a regular variable function callback, but why bother?
12049                  */
12050                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12051                         chkmail(1);
12052 #endif
12053                 INTON;
12054                 return;
12055         }
12056         /* not found */
12057         vp = xmalloc(sizeof (*vp));
12058         vp->flags = flags;
12059         vp->text = s;
12060         vp->next = *vpp;
12061         vp->func = NULL;
12062         *vpp = vp;
12063 }
12064
12065
12066
12067 /*
12068  * Process a linked list of variable assignments.
12069  */
12070
12071 static void
12072 listsetvar(struct strlist *mylist)
12073 {
12074         struct strlist *lp;
12075
12076         INTOFF;
12077         for (lp = mylist ; lp ; lp = lp->next) {
12078                 setvareq(xstrdup(lp->text), 0);
12079         }
12080         INTON;
12081 }
12082
12083
12084
12085 /*
12086  * Find the value of a variable.  Returns NULL if not set.
12087  */
12088
12089 static const char *
12090 lookupvar(const char *name)
12091 {
12092         struct var *v;
12093
12094         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12095                 return strchr(v->text, '=') + 1;
12096         }
12097         return NULL;
12098 }
12099
12100
12101
12102 /*
12103  * Search the environment of a builtin command.
12104  */
12105
12106 static const char *
12107 bltinlookup(const char *name)
12108 {
12109         const struct strlist *sp;
12110
12111         for (sp = cmdenviron ; sp ; sp = sp->next) {
12112                 if (varequal(sp->text, name))
12113                         return strchr(sp->text, '=') + 1;
12114         }
12115         return lookupvar(name);
12116 }
12117
12118
12119
12120 /*
12121  * Generate a list of exported variables.  This routine is used to construct
12122  * the third argument to execve when executing a program.
12123  */
12124
12125 static char **
12126 environment() {
12127         int nenv;
12128         struct var **vpp;
12129         struct var *vp;
12130         char **env;
12131         char **ep;
12132
12133         nenv = 0;
12134         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12135                 for (vp = *vpp ; vp ; vp = vp->next)
12136                         if (vp->flags & VEXPORT)
12137                                 nenv++;
12138         }
12139         ep = env = stalloc((nenv + 1) * sizeof *env);
12140         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12141                 for (vp = *vpp ; vp ; vp = vp->next)
12142                         if (vp->flags & VEXPORT)
12143                                 *ep++ = vp->text;
12144         }
12145         *ep = NULL;
12146         return env;
12147 }
12148
12149
12150 /*
12151  * Called when a shell procedure is invoked to clear out nonexported
12152  * variables.  It is also necessary to reallocate variables of with
12153  * VSTACK set since these are currently allocated on the stack.
12154  */
12155
12156 static void
12157 shprocvar(void) {
12158         struct var **vpp;
12159         struct var *vp, **prev;
12160
12161         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12162                 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12163                         if ((vp->flags & VEXPORT) == 0) {
12164                                 *prev = vp->next;
12165                                 if ((vp->flags & VTEXTFIXED) == 0)
12166                                         ckfree(vp->text);
12167                                 if ((vp->flags & VSTRFIXED) == 0)
12168                                         ckfree(vp);
12169                         } else {
12170                                 if (vp->flags & VSTACK) {
12171                                         vp->text = xstrdup(vp->text);
12172                                         vp->flags &=~ VSTACK;
12173                                 }
12174                                 prev = &vp->next;
12175                         }
12176                 }
12177         }
12178         initvar();
12179 }
12180
12181
12182
12183 /*
12184  * Command to list all variables which are set.  Currently this command
12185  * is invoked from the set command when the set command is called without
12186  * any variables.
12187  */
12188
12189 static int
12190 showvarscmd(int argc, char **argv)
12191 {
12192         showvars(nullstr, VUNSET, VUNSET);
12193         return 0;
12194 }
12195
12196
12197
12198 /*
12199  * The export and readonly commands.
12200  */
12201
12202 static int
12203 exportcmd(int argc, char **argv)
12204 {
12205         struct var *vp;
12206         char *name;
12207         const char *p;
12208         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12209         int pflag;
12210
12211         listsetvar(cmdenviron);
12212         pflag = (nextopt("p") == 'p');
12213         if (argc > 1 && !pflag) {
12214                 while ((name = *argptr++) != NULL) {
12215                         if ((p = strchr(name, '=')) != NULL) {
12216                                 p++;
12217                         } else {
12218                                 if ((vp = *findvar(hashvar(name), name))) {
12219                                         vp->flags |= flag;
12220                                         goto found;
12221                                 }
12222                         }
12223                         setvar(name, p, flag);
12224 found:;
12225                 }
12226         } else {
12227                 showvars(argv[0], flag, 0);
12228         }
12229         return 0;
12230 }
12231
12232
12233 /*
12234  * The "local" command.
12235  */
12236
12237 /* funcnest nonzero if we are currently evaluating a function */
12238
12239 static int
12240 localcmd(int argc, char **argv)
12241 {
12242         char *name;
12243
12244         if (! funcnest)
12245                 error("Not in a function");
12246         while ((name = *argptr++) != NULL) {
12247                 mklocal(name);
12248         }
12249         return 0;
12250 }
12251
12252
12253 /*
12254  * Make a variable a local variable.  When a variable is made local, it's
12255  * value and flags are saved in a localvar structure.  The saved values
12256  * will be restored when the shell function returns.  We handle the name
12257  * "-" as a special case.
12258  */
12259
12260 static void
12261 mklocal(char *name)
12262 {
12263         struct localvar *lvp;
12264         struct var **vpp;
12265         struct var *vp;
12266
12267         INTOFF;
12268         lvp = xmalloc(sizeof (struct localvar));
12269         if (name[0] == '-' && name[1] == '\0') {
12270                 char *p;
12271                 p = xmalloc(sizeof optet_vals);
12272                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12273                 vp = NULL;
12274         } else {
12275                 vpp = hashvar(name);
12276                 vp = *findvar(vpp, name);
12277                 if (vp == NULL) {
12278                         if (strchr(name, '='))
12279                                 setvareq(xstrdup(name), VSTRFIXED);
12280                         else
12281                                 setvar(name, NULL, VSTRFIXED);
12282                         vp = *vpp;      /* the new variable */
12283                         lvp->text = NULL;
12284                         lvp->flags = VUNSET;
12285                 } else {
12286                         lvp->text = vp->text;
12287                         lvp->flags = vp->flags;
12288                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12289                         if (strchr(name, '='))
12290                                 setvareq(xstrdup(name), 0);
12291                 }
12292         }
12293         lvp->vp = vp;
12294         lvp->next = localvars;
12295         localvars = lvp;
12296         INTON;
12297 }
12298
12299
12300 /*
12301  * Called after a function returns.
12302  */
12303
12304 static void
12305 poplocalvars() {
12306         struct localvar *lvp;
12307         struct var *vp;
12308
12309         while ((lvp = localvars) != NULL) {
12310                 localvars = lvp->next;
12311                 vp = lvp->vp;
12312                 if (vp == NULL) {       /* $- saved */
12313                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12314                         ckfree(lvp->text);
12315                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12316                         (void)unsetvar(vp->text);
12317                 } else {
12318                         if ((vp->flags & VTEXTFIXED) == 0)
12319                                 ckfree(vp->text);
12320                         vp->flags = lvp->flags;
12321                         vp->text = lvp->text;
12322                 }
12323                 ckfree(lvp);
12324         }
12325 }
12326
12327
12328 static int
12329 setvarcmd(int argc, char **argv)
12330 {
12331         if (argc <= 2)
12332                 return unsetcmd(argc, argv);
12333         else if (argc == 3)
12334                 setvar(argv[1], argv[2], 0);
12335         else
12336                 error("List assignment not implemented");
12337         return 0;
12338 }
12339
12340
12341 /*
12342  * The unset builtin command.  We unset the function before we unset the
12343  * variable to allow a function to be unset when there is a readonly variable
12344  * with the same name.
12345  */
12346
12347 static int
12348 unsetcmd(int argc, char **argv)
12349 {
12350         char **ap;
12351         int i;
12352         int flg_func = 0;
12353         int flg_var = 0;
12354         int ret = 0;
12355
12356         while ((i = nextopt("vf")) != '\0') {
12357                 if (i == 'f')
12358                         flg_func = 1;
12359                 else
12360                         flg_var = 1;
12361         }
12362         if (flg_func == 0 && flg_var == 0)
12363                 flg_var = 1;
12364
12365         for (ap = argptr; *ap ; ap++) {
12366                 if (flg_func)
12367                         unsetfunc(*ap);
12368                 if (flg_var)
12369                         ret |= unsetvar(*ap);
12370         }
12371         return ret;
12372 }
12373
12374
12375 /*
12376  * Unset the specified variable.
12377  */
12378
12379 static int
12380 unsetvar(const char *s)
12381 {
12382         struct var **vpp;
12383         struct var *vp;
12384
12385         vpp = findvar(hashvar(s), s);
12386         vp = *vpp;
12387         if (vp) {
12388                 if (vp->flags & VREADONLY)
12389                         return (1);
12390                 INTOFF;
12391                 if (*(strchr(vp->text, '=') + 1) != '\0')
12392                         setvar(s, nullstr, 0);
12393                 vp->flags &= ~VEXPORT;
12394                 vp->flags |= VUNSET;
12395                 if ((vp->flags & VSTRFIXED) == 0) {
12396                         if ((vp->flags & VTEXTFIXED) == 0)
12397                                 ckfree(vp->text);
12398                         *vpp = vp->next;
12399                         ckfree(vp);
12400                 }
12401                 INTON;
12402                 return (0);
12403         }
12404
12405         return (0);
12406 }
12407
12408
12409
12410 /*
12411  * Find the appropriate entry in the hash table from the name.
12412  */
12413
12414 static struct var **
12415 hashvar(const char *p)
12416 {
12417         unsigned int hashval;
12418
12419         hashval = ((unsigned char) *p) << 4;
12420         while (*p && *p != '=')
12421                 hashval += (unsigned char) *p++;
12422         return &vartab[hashval % VTABSIZE];
12423 }
12424
12425
12426
12427 /*
12428  * Returns true if the two strings specify the same varable.  The first
12429  * variable name is terminated by '='; the second may be terminated by
12430  * either '=' or '\0'.
12431  */
12432
12433 static int
12434 varequal(const char *p, const char *q)
12435 {
12436         while (*p == *q++) {
12437                 if (*p++ == '=')
12438                         return 1;
12439         }
12440         if (*p == '=' && *(q - 1) == '\0')
12441                 return 1;
12442         return 0;
12443 }
12444
12445 static void
12446 showvars(const char *myprefix, int mask, int xor)
12447 {
12448         struct var **vpp;
12449         struct var *vp;
12450         const char *sep = myprefix == nullstr ? myprefix : spcstr;
12451
12452         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12453                 for (vp = *vpp ; vp ; vp = vp->next) {
12454                         if ((vp->flags & mask) ^ xor) {
12455                                 char *p;
12456                                 int len;
12457
12458                                 p = strchr(vp->text, '=') + 1;
12459                                 len = p - vp->text;
12460                                 p = single_quote(p);
12461
12462                                 printf("%s%s%.*s%s\n", myprefix, sep, len,
12463                                         vp->text, p);
12464                                 stunalloc(p);
12465                         }
12466                 }
12467         }
12468 }
12469
12470 static struct var **
12471 findvar(struct var **vpp, const char *name)
12472 {
12473         for (; *vpp; vpp = &(*vpp)->next) {
12474                 if (varequal((*vpp)->text, name)) {
12475                         break;
12476                 }
12477         }
12478         return vpp;
12479 }
12480
12481 /*
12482  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12483  * This file contains code for the times builtin.
12484  * $Id: ash.c,v 1.38 2001/12/20 23:13:19 kraai Exp $
12485  */
12486 static int timescmd (int argc, char **argv)
12487 {
12488         struct tms buf;
12489         long int clk_tck = sysconf(_SC_CLK_TCK);
12490
12491         times(&buf);
12492         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12493                (int) (buf.tms_utime / clk_tck / 60),
12494                ((double) buf.tms_utime) / clk_tck,
12495                (int) (buf.tms_stime / clk_tck / 60),
12496                ((double) buf.tms_stime) / clk_tck,
12497                (int) (buf.tms_cutime / clk_tck / 60),
12498                ((double) buf.tms_cutime) / clk_tck,
12499                (int) (buf.tms_cstime / clk_tck / 60),
12500                ((double) buf.tms_cstime) / clk_tck);
12501         return 0;
12502 }
12503
12504 #ifdef ASH_MATH_SUPPORT
12505 /* The let builtin.  */
12506 int letcmd(int argc, char **argv)
12507 {
12508         int errcode;
12509         long result=0;
12510         if (argc == 2) {
12511                 char *tmp, *expression, p[13];
12512                 expression = strchr(argv[1], '=');
12513                 if (!expression) {
12514                         /* Cannot use 'error()' here, or the return code
12515                          * will be incorrect */
12516                         out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12517                         return 0;
12518                 }
12519                 *expression = '\0';
12520                 tmp = ++expression;
12521                 result = arith(tmp, &errcode);
12522                 if (errcode < 0) {
12523                         /* Cannot use 'error()' here, or the return code
12524                          * will be incorrect */
12525                         out2fmt("sh: let: ");
12526                         if(errcode == -2)
12527                                 out2fmt("divide by zero");
12528                         else
12529                                 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12530                         return 0;
12531                 }
12532                 snprintf(p, 12, "%ld", result);
12533                 setvar(argv[1], xstrdup(p), 0);
12534         } else if (argc >= 3)
12535                 synerror("invalid operand");
12536         return !result;
12537 }
12538 #endif
12539
12540
12541
12542 /*-
12543  * Copyright (c) 1989, 1991, 1993, 1994
12544  *      The Regents of the University of California.  All rights reserved.
12545  *
12546  * This code is derived from software contributed to Berkeley by
12547  * Kenneth Almquist.
12548  *
12549  * Redistribution and use in source and binary forms, with or without
12550  * modification, are permitted provided that the following conditions
12551  * are met:
12552  * 1. Redistributions of source code must retain the above copyright
12553  *    notice, this list of conditions and the following disclaimer.
12554  * 2. Redistributions in binary form must reproduce the above copyright
12555  *    notice, this list of conditions and the following disclaimer in the
12556  *    documentation and/or other materials provided with the distribution.
12557  *
12558  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12559  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12560  *
12561  * 4. Neither the name of the University nor the names of its contributors
12562  *    may be used to endorse or promote products derived from this software
12563  *    without specific prior written permission.
12564  *
12565  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12566  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12567  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12568  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12569  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12570  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12571  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12572  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12573  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12574  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12575  * SUCH DAMAGE.
12576  */