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