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