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