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