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