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