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