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