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