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