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