1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
36 * The follow should be set to reflect the type of system you have:
37 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
38 * define SYSV if you are running under System V.
39 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
40 * define DEBUG=2 to compile in and turn on debugging.
42 * When debugging is on, debugging info will be written to ./trace and
43 * a quit signal will generate a core dump.
57 #include <sys/types.h>
58 #include <sys/ioctl.h>
59 #include <sys/param.h>
60 #include <sys/resource.h>
80 /*#include <stdint.h>*/
86 #ifdef CONFIG_ASH_JOB_CONTROL
92 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
100 static int *dash_errno;
102 #define errno (*dash_errno)
105 #if defined(__uClinux__)
106 #error "Do not even bother, ash will not run on uClinux"
110 #define _DIAGASSERT(assert_expr) assert(assert_expr)
112 #define _DIAGASSERT(assert_expr)
116 #ifdef CONFIG_ASH_ALIAS
129 static struct alias *lookupalias(const char *, int);
130 static int aliascmd(int, char **);
131 static int unaliascmd(int, char **);
132 static void rmaliases(void);
133 static int unalias(const char *);
134 static void printalias(const struct alias *);
140 static void setpwd(const char *, int);
146 * Types of operations (passed to the errmsg routine).
150 static const char not_found_msg[] = "%s: not found";
153 #define E_OPEN "No such file" /* opening a file */
154 #define E_CREAT "Directory nonexistent" /* creating a file */
155 #define E_EXEC not_found_msg+4 /* executing a program */
158 * We enclose jmp_buf in a structure so that we can declare pointers to
159 * jump locations. The global variable handler contains the location to
160 * jump to when an exception occurs, and the global variable exception
161 * contains a code identifying the exception. To implement nested
162 * exception handlers, the user should save the value of handler on entry
163 * to an inner scope, set handler to point to a jmploc structure for the
164 * inner scope, and restore handler on exit from the scope.
171 static struct jmploc *handler;
172 static int exception;
173 static volatile int suppressint;
174 static volatile sig_atomic_t intpending;
177 #define EXINT 0 /* SIGINT received */
178 #define EXERROR 1 /* a generic error */
179 #define EXSHELLPROC 2 /* execute a shell procedure */
180 #define EXEXEC 3 /* command execution failed */
181 #define EXEXIT 4 /* exit the shell */
182 #define EXSIG 5 /* trapped signal in wait(1) */
185 /* do we generate EXSIG events */
187 /* last pending signal */
188 static volatile sig_atomic_t pendingsigs;
191 * These macros allow the user to suspend the handling of interrupt signals
192 * over a period of time. This is similar to SIGHOLD to or sigblock, but
193 * much more efficient and portable. (But hacking the kernel is so much
194 * more fun than worrying about efficiency and portability. :-))
197 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
204 #define SAVEINT(v) ((v) = suppressint)
205 #define RESTOREINT(v) \
208 if ((suppressint = (v)) == 0 && intpending) onint(); \
219 /* EXSIG is turned off by evalbltin(). */
222 static void exraise(int) ATTRIBUTE_NORETURN;
223 static void onint(void) ATTRIBUTE_NORETURN;
225 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
226 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
228 static void sh_warnx(const char *, ...);
230 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
233 if (--suppressint == 0 && intpending) {
237 #define INTON inton()
238 static void forceinton(void)
244 #define FORCEINTON forceinton()
249 if (--suppressint == 0 && intpending) onint(); \
256 if (intpending) onint(); \
259 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
264 struct strlist *next;
270 struct strlist *list;
271 struct strlist **lastp;
277 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
278 #define EXP_TILDE 0x2 /* do normal tilde expansion */
279 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
280 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
281 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
282 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
283 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
284 #define EXP_WORD 0x80 /* expand word in parameter expansion */
285 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
289 static void expandarg(union node *, struct arglist *, int);
290 #define rmescapes(p) _rmescapes((p), 0)
291 static char *_rmescapes(char *, int);
292 static int casematch(union node *, char *);
294 #ifdef CONFIG_ASH_MATH_SUPPORT
295 static void expari(int);
300 static char *commandname; /* currently executing command */
301 static struct strlist *cmdenviron; /* environment for builtin command */
302 static int exitstatus; /* exit status of last command */
303 static int back_exitstatus; /* exit status of backquoted command */
306 struct backcmd { /* result of evalbackcmd */
307 int fd; /* file descriptor to read from */
308 char *buf; /* buffer */
309 int nleft; /* number of chars in buffer */
310 struct job *jp; /* job structure for command */
314 * This file was generated by the mknodes program.
350 union node *redirect;
357 struct nodelist *cmdlist;
364 union node *redirect;
379 union node *elsepart;
410 struct nodelist *backquote;
450 struct nredir nredir;
451 struct nbinary nbinary;
455 struct nclist nclist;
465 struct nodelist *next;
476 static void freefunc(struct funcnode *);
479 /* control characters in argument strings */
480 #define CTL_FIRST '\201' /* first 'special' character */
481 #define CTLESC '\201' /* escape next character */
482 #define CTLVAR '\202' /* variable defn */
483 #define CTLENDVAR '\203'
484 #define CTLBACKQ '\204'
485 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
486 /* CTLBACKQ | CTLQUOTE == '\205' */
487 #define CTLARI '\206' /* arithmetic expression */
488 #define CTLENDARI '\207'
489 #define CTLQUOTEMARK '\210'
490 #define CTL_LAST '\210' /* last 'special' character */
492 /* variable substitution byte (follows CTLVAR) */
493 #define VSTYPE 0x0f /* type of variable substitution */
494 #define VSNUL 0x10 /* colon--treat the empty string as unset */
495 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
497 /* values of VSTYPE field */
498 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
499 #define VSMINUS 0x2 /* ${var-text} */
500 #define VSPLUS 0x3 /* ${var+text} */
501 #define VSQUESTION 0x4 /* ${var?message} */
502 #define VSASSIGN 0x5 /* ${var=text} */
503 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
504 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
505 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
506 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
507 #define VSLENGTH 0xa /* ${#var} */
509 /* values of checkkwd variable */
514 #define IBUFSIZ (BUFSIZ + 1)
517 * NEOF is returned by parsecmd when it encounters an end of file. It
518 * must be distinct from NULL, so we use the address of a variable that
519 * happens to be handy.
521 static int plinno = 1; /* input line number */
523 /* number of characters left in input buffer */
524 static int parsenleft; /* copy of parsefile->nleft */
525 static int parselleft; /* copy of parsefile->lleft */
527 /* next character in input buffer */
528 static char *parsenextc; /* copy of parsefile->nextc */
531 struct strpush *prev; /* preceding string on stack */
534 #ifdef CONFIG_ASH_ALIAS
535 struct alias *ap; /* if push was associated with an alias */
537 char *string; /* remember the string since it may change */
541 struct parsefile *prev; /* preceding file on stack */
542 int linno; /* current line */
543 int fd; /* file descriptor (or -1 if string) */
544 int nleft; /* number of chars left in this line */
545 int lleft; /* number of chars left in this buffer */
546 char *nextc; /* next char in buffer */
547 char *buf; /* input buffer */
548 struct strpush *strpush; /* for pushing strings at this level */
549 struct strpush basestrpush; /* so pushing one is fast */
552 static struct parsefile basepf; /* top level input file */
553 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
554 static struct parsefile *parsefile = &basepf; /* current input file */
557 static int tokpushback; /* last token pushed back */
558 #define NEOF ((union node *)&tokpushback)
559 static int parsebackquote; /* nonzero if we are inside backquotes */
560 static int doprompt; /* if set, prompt the user */
561 static int needprompt; /* true if interactive and at start of line */
562 static int lasttoken; /* last token read */
563 static char *wordtext; /* text of last word returned by readtoken */
565 static struct nodelist *backquotelist;
566 static union node *redirnode;
567 static struct heredoc *heredoc;
568 static int quoteflag; /* set if (part of) last token was quoted */
569 static int startlinno; /* line # where last token started */
571 static union node *parsecmd(int);
572 static void fixredir(union node *, const char *, int);
573 static const char *const *findkwd(const char *);
574 static char *endofname(const char *);
578 typedef void *pointer;
580 static char nullstr[1]; /* zero length string */
581 static const char spcstr[] = " ";
582 static const char snlfmt[] = "%s\n";
583 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
584 static const char illnum[] = "Illegal number: %s";
585 static const char homestr[] = "HOME";
588 #define TRACE(param) trace param
589 #define TRACEV(param) tracev param
592 #define TRACEV(param)
595 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
596 #define __builtin_expect(x, expected_value) (x)
599 #define xlikely(x) __builtin_expect((x),1)
614 #define TENDBQUOTE 12
632 /* first char is indicating which tokens mark the end of a list */
633 static const char *const tokname_array[] = {
648 /* the following are keywords */
667 static const char *tokname(int tok)
673 sprintf(buf + (tok >= TSEMI), "%s%c",
674 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
681 * Most machines require the value returned from malloc to be aligned
682 * in some way. The following macro will get this right on many machines.
685 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
687 * It appears that grabstackstr() will barf with such alignments
688 * because stalloc() will return a string allocated in a new stackblock.
690 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
693 * This file was generated by the mksyntax program.
698 #define CWORD 0 /* character is nothing special */
699 #define CNL 1 /* newline character */
700 #define CBACK 2 /* a backslash character */
701 #define CSQUOTE 3 /* single quote */
702 #define CDQUOTE 4 /* double quote */
703 #define CENDQUOTE 5 /* a terminating quote */
704 #define CBQUOTE 6 /* backwards single quote */
705 #define CVAR 7 /* a dollar sign */
706 #define CENDVAR 8 /* a '}' character */
707 #define CLP 9 /* a left paren in arithmetic */
708 #define CRP 10 /* a right paren in arithmetic */
709 #define CENDFILE 11 /* end of file */
710 #define CCTL 12 /* like CWORD, except it must be escaped */
711 #define CSPCL 13 /* these terminate a word */
712 #define CIGN 14 /* character should be ignored */
714 #ifdef CONFIG_ASH_ALIAS
718 #define PEOA_OR_PEOF PEOA
722 #define PEOA_OR_PEOF PEOF
725 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
726 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
727 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
729 /* C99 say: "char" declaration may be signed or unsigned default */
730 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
733 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
734 * (assuming ascii char codes, as the original implementation did)
736 #define is_special(c) \
737 ( (((unsigned int)c) - 33 < 32) \
738 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
740 #define digit_val(c) ((c) - '0')
743 * This file was generated by the mksyntax program.
746 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
747 #define USE_SIT_FUNCTION
750 /* number syntax index */
751 #define BASESYNTAX 0 /* not in quotes */
752 #define DQSYNTAX 1 /* in double quotes */
753 #define SQSYNTAX 2 /* in single quotes */
754 #define ARISYNTAX 3 /* in arithmetic */
756 #ifdef CONFIG_ASH_MATH_SUPPORT
757 static const char S_I_T[][4] = {
758 #ifdef CONFIG_ASH_ALIAS
759 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
761 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
762 {CNL, CNL, CNL, CNL}, /* 2, \n */
763 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
764 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
765 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
766 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
767 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
768 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
769 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
770 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
771 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
772 #ifndef USE_SIT_FUNCTION
773 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
774 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
775 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
779 static const char S_I_T[][3] = {
780 #ifdef CONFIG_ASH_ALIAS
781 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
783 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
784 {CNL, CNL, CNL}, /* 2, \n */
785 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
786 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
787 {CVAR, CVAR, CWORD}, /* 5, $ */
788 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
789 {CSPCL, CWORD, CWORD}, /* 7, ( */
790 {CSPCL, CWORD, CWORD}, /* 8, ) */
791 {CBACK, CBACK, CCTL}, /* 9, \ */
792 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
793 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
794 #ifndef USE_SIT_FUNCTION
795 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
796 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
797 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
800 #endif /* CONFIG_ASH_MATH_SUPPORT */
802 #ifdef USE_SIT_FUNCTION
804 #define U_C(c) ((unsigned char)(c))
806 static int SIT(int c, int syntax)
808 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
809 #ifdef CONFIG_ASH_ALIAS
810 static const char syntax_index_table[] = {
811 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
812 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
813 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
817 static const char syntax_index_table[] = {
818 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
819 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
820 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
827 if (c == PEOF) /* 2^8+2 */
829 #ifdef CONFIG_ASH_ALIAS
830 if (c == PEOA) /* 2^8+1 */
834 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
837 s = strchr(spec_symbls, c);
838 if (s == 0 || *s == 0)
840 indx = syntax_index_table[(s - spec_symbls)];
842 return S_I_T[indx][syntax];
845 #else /* USE_SIT_FUNCTION */
847 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
849 #ifdef CONFIG_ASH_ALIAS
850 #define CSPCL_CIGN_CIGN_CIGN 0
851 #define CSPCL_CWORD_CWORD_CWORD 1
852 #define CNL_CNL_CNL_CNL 2
853 #define CWORD_CCTL_CCTL_CWORD 3
854 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
855 #define CVAR_CVAR_CWORD_CVAR 5
856 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
857 #define CSPCL_CWORD_CWORD_CLP 7
858 #define CSPCL_CWORD_CWORD_CRP 8
859 #define CBACK_CBACK_CCTL_CBACK 9
860 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
861 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
862 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
863 #define CWORD_CWORD_CWORD_CWORD 13
864 #define CCTL_CCTL_CCTL_CCTL 14
866 #define CSPCL_CWORD_CWORD_CWORD 0
867 #define CNL_CNL_CNL_CNL 1
868 #define CWORD_CCTL_CCTL_CWORD 2
869 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
870 #define CVAR_CVAR_CWORD_CVAR 4
871 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
872 #define CSPCL_CWORD_CWORD_CLP 6
873 #define CSPCL_CWORD_CWORD_CRP 7
874 #define CBACK_CBACK_CCTL_CBACK 8
875 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
876 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
877 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
878 #define CWORD_CWORD_CWORD_CWORD 12
879 #define CCTL_CCTL_CCTL_CCTL 13
882 static const char syntax_index_table[258] = {
883 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
884 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
885 #ifdef CONFIG_ASH_ALIAS
886 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
888 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
889 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
890 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
891 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
892 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
893 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
894 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
895 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
896 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
897 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
898 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
899 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
900 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
901 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
902 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
903 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
904 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
905 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
906 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
907 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
908 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
909 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
910 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
911 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
912 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
913 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
914 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
915 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
916 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
917 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
918 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
919 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
920 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
921 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
922 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
923 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
924 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
925 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
926 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
927 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
928 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
929 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
930 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
931 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
932 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
933 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
934 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
935 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
936 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
937 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
938 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
939 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
940 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
941 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
942 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
943 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
944 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
945 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
946 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
947 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
948 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
949 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
950 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
951 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
952 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
953 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
954 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
955 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
956 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
957 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
958 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
959 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
960 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
961 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
962 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
963 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
964 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
965 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
966 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
967 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
968 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
969 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
970 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
971 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
972 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
973 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
974 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
975 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
976 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
977 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
978 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
979 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
980 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
981 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
982 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
983 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
984 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
985 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
986 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
987 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
988 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
989 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
990 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
991 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
992 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
993 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
994 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
995 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
996 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
997 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
998 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
999 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1026 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1027 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1048 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1049 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1050 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1051 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1052 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1053 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1054 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1055 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1056 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1057 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1058 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1059 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1060 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1061 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1062 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1063 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1064 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1074 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1075 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1076 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1077 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1078 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1079 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1080 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1108 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1109 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1110 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1113 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1140 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1141 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1142 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1143 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1146 #endif /* USE_SIT_FUNCTION */
1153 static int funcblocksize; /* size of structures in function */
1154 static int funcstringsize; /* size of strings in node */
1155 static pointer funcblock; /* block to allocate function from */
1156 static char *funcstring; /* block to allocate strings from */
1158 static const short nodesize[26] = {
1159 SHELL_ALIGN(sizeof (struct ncmd)),
1160 SHELL_ALIGN(sizeof (struct npipe)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nredir)),
1163 SHELL_ALIGN(sizeof (struct nredir)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nbinary)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nif)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nbinary)),
1170 SHELL_ALIGN(sizeof (struct nfor)),
1171 SHELL_ALIGN(sizeof (struct ncase)),
1172 SHELL_ALIGN(sizeof (struct nclist)),
1173 SHELL_ALIGN(sizeof (struct narg)),
1174 SHELL_ALIGN(sizeof (struct narg)),
1175 SHELL_ALIGN(sizeof (struct nfile)),
1176 SHELL_ALIGN(sizeof (struct nfile)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct nfile)),
1180 SHELL_ALIGN(sizeof (struct ndup)),
1181 SHELL_ALIGN(sizeof (struct ndup)),
1182 SHELL_ALIGN(sizeof (struct nhere)),
1183 SHELL_ALIGN(sizeof (struct nhere)),
1184 SHELL_ALIGN(sizeof (struct nnot)),
1188 static void calcsize(union node *);
1189 static void sizenodelist(struct nodelist *);
1190 static union node *copynode(union node *);
1191 static struct nodelist *copynodelist(struct nodelist *);
1192 static char *nodesavestr(char *);
1195 static int evalstring(char *, int mask);
1196 union node; /* BLETCH for ansi C */
1197 static void evaltree(union node *, int);
1198 static void evalbackcmd(union node *, struct backcmd *);
1200 static int evalskip; /* set if we are skipping commands */
1201 static int skipcount; /* number of levels to skip */
1202 static int funcnest; /* depth of function calls */
1204 /* reasons for skipping commands (see comment on breakcmd routine) */
1205 #define SKIPBREAK (1 << 0)
1206 #define SKIPCONT (1 << 1)
1207 #define SKIPFUNC (1 << 2)
1208 #define SKIPFILE (1 << 3)
1209 #define SKIPEVAL (1 << 4)
1212 * This file was generated by the mkbuiltins program.
1216 static int bgcmd(int, char **);
1218 static int breakcmd(int, char **);
1219 static int cdcmd(int, char **);
1220 #ifdef CONFIG_ASH_CMDCMD
1221 static int commandcmd(int, char **);
1223 static int dotcmd(int, char **);
1224 static int evalcmd(int, char **);
1225 #ifdef CONFIG_ASH_BUILTIN_ECHO
1226 static int echocmd(int, char **);
1228 static int execcmd(int, char **);
1229 static int exitcmd(int, char **);
1230 static int exportcmd(int, char **);
1231 static int falsecmd(int, char **);
1233 static int fgcmd(int, char **);
1235 #ifdef CONFIG_ASH_GETOPTS
1236 static int getoptscmd(int, char **);
1238 static int hashcmd(int, char **);
1239 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1240 static int helpcmd(int argc, char **argv);
1243 static int jobscmd(int, char **);
1245 #ifdef CONFIG_ASH_MATH_SUPPORT
1246 static int letcmd(int, char **);
1248 static int localcmd(int, char **);
1249 static int pwdcmd(int, char **);
1250 static int readcmd(int, char **);
1251 static int returncmd(int, char **);
1252 static int setcmd(int, char **);
1253 static int shiftcmd(int, char **);
1254 static int timescmd(int, char **);
1255 static int trapcmd(int, char **);
1256 static int truecmd(int, char **);
1257 static int typecmd(int, char **);
1258 static int umaskcmd(int, char **);
1259 static int unsetcmd(int, char **);
1260 static int waitcmd(int, char **);
1261 static int ulimitcmd(int, char **);
1263 static int killcmd(int, char **);
1268 #ifdef CONFIG_ASH_MAIL
1269 static void chkmail(void);
1270 static void changemail(const char *);
1275 /* values of cmdtype */
1276 #define CMDUNKNOWN -1 /* no entry in table for command */
1277 #define CMDNORMAL 0 /* command is an executable program */
1278 #define CMDFUNCTION 1 /* command is a shell function */
1279 #define CMDBUILTIN 2 /* command is a shell builtin */
1283 int (*builtin)(int, char **);
1284 /* unsigned flags; */
1288 #define COMMANDCMD (builtincmd + 5 + \
1289 ENABLE_ASH_ALIAS + ENABLE_ASH_JOB_CONTROL)
1290 #define EXECCMD (builtincmd + 7 + \
1291 ENABLE_ASH_CMDCMD + ENABLE_ASH_ALIAS + \
1292 ENABLE_ASH_BUILTIN_ECHO + ENABLE_ASH_JOB_CONTROL)
1294 #define BUILTIN_NOSPEC "0"
1295 #define BUILTIN_SPECIAL "1"
1296 #define BUILTIN_REGULAR "2"
1297 #define BUILTIN_SPEC_REG "3"
1298 #define BUILTIN_ASSIGN "4"
1299 #define BUILTIN_SPEC_ASSG "5"
1300 #define BUILTIN_REG_ASSG "6"
1301 #define BUILTIN_SPEC_REG_ASSG "7"
1303 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1304 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1305 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1307 static const struct builtincmd builtincmd[] = {
1308 { BUILTIN_SPEC_REG ".", dotcmd },
1309 { BUILTIN_SPEC_REG ":", truecmd },
1310 #ifdef CONFIG_ASH_ALIAS
1311 { BUILTIN_REG_ASSG "alias", aliascmd },
1314 { BUILTIN_REGULAR "bg", bgcmd },
1316 { BUILTIN_SPEC_REG "break", breakcmd },
1317 { BUILTIN_REGULAR "cd", cdcmd },
1318 { BUILTIN_NOSPEC "chdir", cdcmd },
1319 #ifdef CONFIG_ASH_CMDCMD
1320 { BUILTIN_REGULAR "command", commandcmd },
1322 { BUILTIN_SPEC_REG "continue", breakcmd },
1323 #ifdef CONFIG_ASH_BUILTIN_ECHO
1324 { BUILTIN_REGULAR "echo", echocmd },
1326 { BUILTIN_SPEC_REG "eval", evalcmd },
1327 { BUILTIN_SPEC_REG "exec", execcmd },
1328 { BUILTIN_SPEC_REG "exit", exitcmd },
1329 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1330 { BUILTIN_REGULAR "false", falsecmd },
1332 { BUILTIN_REGULAR "fg", fgcmd },
1334 #ifdef CONFIG_ASH_GETOPTS
1335 { BUILTIN_REGULAR "getopts", getoptscmd },
1337 { BUILTIN_NOSPEC "hash", hashcmd },
1338 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1339 { BUILTIN_NOSPEC "help", helpcmd },
1342 { BUILTIN_REGULAR "jobs", jobscmd },
1343 { BUILTIN_REGULAR "kill", killcmd },
1345 #ifdef CONFIG_ASH_MATH_SUPPORT
1346 { BUILTIN_NOSPEC "let", letcmd },
1348 { BUILTIN_ASSIGN "local", localcmd },
1349 { BUILTIN_NOSPEC "pwd", pwdcmd },
1350 { BUILTIN_REGULAR "read", readcmd },
1351 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1352 { BUILTIN_SPEC_REG "return", returncmd },
1353 { BUILTIN_SPEC_REG "set", setcmd },
1354 { BUILTIN_SPEC_REG "source", dotcmd },
1355 { BUILTIN_SPEC_REG "shift", shiftcmd },
1356 { BUILTIN_SPEC_REG "times", timescmd },
1357 { BUILTIN_SPEC_REG "trap", trapcmd },
1358 { BUILTIN_REGULAR "true", truecmd },
1359 { BUILTIN_NOSPEC "type", typecmd },
1360 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1361 { BUILTIN_REGULAR "umask", umaskcmd },
1362 #ifdef CONFIG_ASH_ALIAS
1363 { BUILTIN_REGULAR "unalias", unaliascmd },
1365 { BUILTIN_SPEC_REG "unset", unsetcmd },
1366 { BUILTIN_REGULAR "wait", waitcmd },
1369 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1377 const struct builtincmd *cmd;
1378 struct funcnode *func;
1383 /* action to find_command() */
1384 #define DO_ERR 0x01 /* prints errors */
1385 #define DO_ABS 0x02 /* checks absolute paths */
1386 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1387 #define DO_ALTPATH 0x08 /* using alternate path */
1388 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1390 static const char *pathopt; /* set by padvance */
1392 static void shellexec(char **, const char *, int)
1394 static char *padvance(const char **, const char *);
1395 static void find_command(char *, struct cmdentry *, int, const char *);
1396 static struct builtincmd *find_builtin(const char *);
1397 static void hashcd(void);
1398 static void changepath(const char *);
1399 static void defun(char *, union node *);
1400 static void unsetfunc(const char *);
1402 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1403 typedef int64_t arith_t;
1404 #define arith_t_type (long long)
1406 typedef long arith_t;
1407 #define arith_t_type (long)
1410 #ifdef CONFIG_ASH_MATH_SUPPORT
1411 static arith_t dash_arith(const char *);
1412 static arith_t arith(const char *expr, int *perrcode);
1415 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1416 static unsigned long rseed;
1417 static void change_random(const char *);
1418 # ifndef DYNAMIC_VAR
1419 # define DYNAMIC_VAR
1425 static void reset(void);
1434 #define VEXPORT 0x01 /* variable is exported */
1435 #define VREADONLY 0x02 /* variable cannot be modified */
1436 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1437 #define VTEXTFIXED 0x08 /* text is statically allocated */
1438 #define VSTACK 0x10 /* text is allocated on the stack */
1439 #define VUNSET 0x20 /* the variable is not set */
1440 #define VNOFUNC 0x40 /* don't call the callback function */
1441 #define VNOSET 0x80 /* do not set variable - just readonly test */
1442 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1444 # define VDYNAMIC 0x200 /* dynamic variable */
1450 struct var *next; /* next entry in hash list */
1451 int flags; /* flags are defined above */
1452 const char *text; /* name=value */
1453 void (*func)(const char *); /* function to be called when */
1454 /* the variable gets set/unset */
1458 struct localvar *next; /* next local variable in list */
1459 struct var *vp; /* the variable that was made local */
1460 int flags; /* saved flags */
1461 const char *text; /* saved text */
1465 static struct localvar *localvars;
1471 #ifdef CONFIG_ASH_GETOPTS
1472 static void getoptsreset(const char *);
1475 #ifdef CONFIG_LOCALE_SUPPORT
1477 static void change_lc_all(const char *value);
1478 static void change_lc_ctype(const char *value);
1484 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1486 static const char defifsvar[] = "IFS= \t\n";
1487 #define defifs (defifsvar + 4)
1489 static const char defifs[] = " \t\n";
1493 static struct var varinit[] = {
1495 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1497 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1500 #ifdef CONFIG_ASH_MAIL
1501 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1502 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1505 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1506 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1507 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1508 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1509 #ifdef CONFIG_ASH_GETOPTS
1510 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1512 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1513 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1515 #ifdef CONFIG_LOCALE_SUPPORT
1516 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1517 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1519 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1520 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1524 #define vifs varinit[0]
1525 #ifdef CONFIG_ASH_MAIL
1526 #define vmail (&vifs)[1]
1527 #define vmpath (&vmail)[1]
1531 #define vpath (&vmpath)[1]
1532 #define vps1 (&vpath)[1]
1533 #define vps2 (&vps1)[1]
1534 #define vps4 (&vps2)[1]
1535 #define voptind (&vps4)[1]
1536 #ifdef CONFIG_ASH_GETOPTS
1537 #define vrandom (&voptind)[1]
1539 #define vrandom (&vps4)[1]
1541 #define defpath (defpathvar + 5)
1544 * The following macros access the values of the above variables.
1545 * They have to skip over the name. They return the null string
1546 * for unset variables.
1549 #define ifsval() (vifs.text + 4)
1550 #define ifsset() ((vifs.flags & VUNSET) == 0)
1551 #define mailval() (vmail.text + 5)
1552 #define mpathval() (vmpath.text + 9)
1553 #define pathval() (vpath.text + 5)
1554 #define ps1val() (vps1.text + 4)
1555 #define ps2val() (vps2.text + 4)
1556 #define ps4val() (vps4.text + 4)
1557 #define optindval() (voptind.text + 7)
1559 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1561 static void setvar(const char *, const char *, int);
1562 static void setvareq(char *, int);
1563 static void listsetvar(struct strlist *, int);
1564 static char *lookupvar(const char *);
1565 static char *bltinlookup(const char *);
1566 static char **listvars(int, int, char ***);
1567 #define environment() listvars(VEXPORT, VUNSET, 0)
1568 static int showvars(const char *, int, int);
1569 static void poplocalvars(void);
1570 static int unsetvar(const char *);
1571 #ifdef CONFIG_ASH_GETOPTS
1572 static int setvarsafe(const char *, const char *, int);
1574 static int varcmp(const char *, const char *);
1575 static struct var **hashvar(const char *);
1578 static inline int varequal(const char *a, const char *b) {
1579 return !varcmp(a, b);
1583 static int loopnest; /* current loop nesting level */
1586 * The parsefile structure pointed to by the global variable parsefile
1587 * contains information about the current file being read.
1592 struct redirtab *next;
1597 static struct redirtab *redirlist;
1598 static int nullredirs;
1600 extern char **environ;
1605 static void outstr(const char *, FILE *);
1606 static void outcslow(int, FILE *);
1607 static void flushall(void);
1608 static void flusherr(void);
1609 static int out1fmt(const char *, ...)
1610 __attribute__((__format__(__printf__,1,2)));
1611 static int fmtstr(char *, size_t, const char *, ...)
1612 __attribute__((__format__(__printf__,3,4)));
1614 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1617 static void out1str(const char *p)
1622 static void out2str(const char *p)
1629 * Initialization code.
1633 * This routine initializes the builtin variables.
1644 * PS1 depends on uid
1646 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1647 vps1.text = "PS1=\\w \\$ ";
1650 vps1.text = "PS1=# ";
1653 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1655 vpp = hashvar(vp->text);
1658 } while (++vp < end);
1667 basepf.nextc = basepf.buf = basebuf;
1672 signal(SIGCHLD, SIG_DFL);
1680 struct stat st1, st2;
1683 for (envp = environ ; envp && *envp ; envp++) {
1684 if (strchr(*envp, '=')) {
1685 setvareq(*envp, VEXPORT|VTEXTFIXED);
1689 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1690 setvar("PPID", ppid, 0);
1692 p = lookupvar("PWD");
1694 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1695 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1701 /* PEOF (the end of file marker) */
1704 INPUT_PUSH_FILE = 1,
1705 INPUT_NOFILE_OK = 2,
1709 * The input line number. Input.c just defines this variable, and saves
1710 * and restores it when files are pushed and popped. The user of this
1711 * package must set its value.
1714 static int pgetc(void);
1715 static int pgetc2(void);
1716 static int preadbuffer(void);
1717 static void pungetc(void);
1718 static void pushstring(char *, void *);
1719 static void popstring(void);
1720 static void setinputfd(int, int);
1721 static void setinputstring(char *);
1722 static void popfile(void);
1723 static void popallfiles(void);
1724 static void closescript(void);
1730 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1733 #define FORK_NOJOB 2
1735 /* mode flags for showjob(s) */
1736 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1737 #define SHOW_PID 0x04 /* include process pid */
1738 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1742 * A job structure contains information about a job. A job is either a
1743 * single process or a set of processes contained in a pipeline. In the
1744 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1749 pid_t pid; /* process id */
1750 int status; /* last process status from wait() */
1751 char *cmd; /* text of command being run */
1755 struct procstat ps0; /* status of process */
1756 struct procstat *ps; /* status or processes when more than one */
1758 int stopstatus; /* status of a stopped job */
1761 nprocs: 16, /* number of processes */
1763 #define JOBRUNNING 0 /* at least one proc running */
1764 #define JOBSTOPPED 1 /* all procs are stopped */
1765 #define JOBDONE 2 /* all procs are completed */
1767 sigint: 1, /* job was killed by SIGINT */
1768 jobctl: 1, /* job running under job control */
1770 waited: 1, /* true if this entry has been waited for */
1771 used: 1, /* true if this entry is in used */
1772 changed: 1; /* true if status has changed */
1773 struct job *prev_job; /* previous job */
1776 static pid_t backgndpid; /* pid of last background process */
1777 static int job_warning; /* user was warned about stopped jobs */
1779 static int jobctl; /* true if doing job control */
1782 static struct job *makejob(union node *, int);
1783 static int forkshell(struct job *, union node *, int);
1784 static int waitforjob(struct job *);
1785 static int stoppedjobs(void);
1788 #define setjobctl(on) /* do nothing */
1790 static void setjobctl(int);
1791 static void showjobs(FILE *, int);
1797 /* pid of main shell */
1799 /* shell level: 0 for the main shell, 1 for its children, and so on */
1801 #define rootshell (!shlvl)
1803 static void readcmdfile(char *);
1804 static int cmdloop(int);
1810 struct stack_block *stackp;
1813 struct stackmark *marknext;
1816 /* minimum size of a block */
1817 #define MINSIZE SHELL_ALIGN(504)
1819 struct stack_block {
1820 struct stack_block *prev;
1821 char space[MINSIZE];
1824 static struct stack_block stackbase;
1825 static struct stack_block *stackp = &stackbase;
1826 static struct stackmark *markp;
1827 static char *stacknxt = stackbase.space;
1828 static size_t stacknleft = MINSIZE;
1829 static char *sstrend = stackbase.space + MINSIZE;
1830 static int herefd = -1;
1833 static pointer ckmalloc(size_t);
1834 static pointer ckrealloc(pointer, size_t);
1835 static char *savestr(const char *);
1836 static pointer stalloc(size_t);
1837 static void stunalloc(pointer);
1838 static void setstackmark(struct stackmark *);
1839 static void popstackmark(struct stackmark *);
1840 static void growstackblock(void);
1841 static void *growstackstr(void);
1842 static char *makestrspace(size_t, char *);
1843 static char *stnputs(const char *, size_t, char *);
1844 static char *stputs(const char *, char *);
1847 static inline char *_STPUTC(int c, char *p) {
1854 #define stackblock() ((void *)stacknxt)
1855 #define stackblocksize() stacknleft
1856 #define STARTSTACKSTR(p) ((p) = stackblock())
1857 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1858 #define CHECKSTRSPACE(n, p) \
1862 size_t m = sstrend - q; \
1864 (p) = makestrspace(l, q); \
1867 #define USTPUTC(c, p) (*p++ = (c))
1868 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1869 #define STUNPUTC(p) (--p)
1870 #define STTOPC(p) p[-1]
1871 #define STADJUST(amount, p) (p += (amount))
1873 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1874 #define ungrabstackstr(s, p) stunalloc((s))
1875 #define stackstrend() ((void *)sstrend)
1877 #define ckfree(p) free((pointer)(p))
1882 #define DOLATSTRLEN 4
1884 static char *prefix(const char *, const char *);
1885 static int number(const char *);
1886 static int is_number(const char *);
1887 static char *single_quote(const char *);
1888 static char *sstrdup(const char *);
1890 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1891 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1896 int nparam; /* # of positional parameters (without $0) */
1897 unsigned char malloc; /* if parameter list dynamically allocated */
1898 char **p; /* parameter list */
1899 #ifdef CONFIG_ASH_GETOPTS
1900 int optind; /* next parameter to be processed by getopts */
1901 int optoff; /* used by getopts */
1906 #define eflag optlist[0]
1907 #define fflag optlist[1]
1908 #define Iflag optlist[2]
1909 #define iflag optlist[3]
1910 #define mflag optlist[4]
1911 #define nflag optlist[5]
1912 #define sflag optlist[6]
1913 #define xflag optlist[7]
1914 #define vflag optlist[8]
1915 #define Cflag optlist[9]
1916 #define aflag optlist[10]
1917 #define bflag optlist[11]
1918 #define uflag optlist[12]
1919 #define viflag optlist[13]
1922 #define nolog optlist[14]
1923 #define debug optlist[15]
1926 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1927 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1933 static const char *const optletters_optnames[] = {
1954 #define optletters(n) optletters_optnames[(n)][0]
1955 #define optnames(n) (&optletters_optnames[(n)][1])
1957 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1959 static char optlist[NOPTS];
1962 static char *arg0; /* value of $0 */
1963 static struct shparam shellparam; /* $@ current positional parameters */
1964 static char **argptr; /* argument list for builtin commands */
1965 static char *optionarg; /* set by nextopt (like getopt) */
1966 static char *optptr; /* used by nextopt */
1968 static char *minusc; /* argument to -c option */
1971 static void procargs(int, char **);
1972 static void optschanged(void);
1973 static void setparam(char **);
1974 static void freeparam(volatile struct shparam *);
1975 static int shiftcmd(int, char **);
1976 static int setcmd(int, char **);
1977 static int nextopt(const char *);
1981 /* flags passed to redirect */
1982 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1983 #define REDIR_SAVEFD2 03 /* set preverrout */
1986 static void redirect(union node *, int);
1987 static void popredir(int);
1988 static void clearredir(int);
1989 static int copyfd(int, int);
1990 static int redirectsafe(union node *, int);
1996 static void showtree(union node *);
1997 static void trace(const char *, ...);
1998 static void tracev(const char *, va_list);
1999 static void trargs(char **);
2000 static void trputc(int);
2001 static void trputs(const char *);
2002 static void opentrace(void);
2008 /* trap handler commands */
2009 static char *trap[NSIG];
2010 /* current value of signal */
2011 static char sigmode[NSIG - 1];
2012 /* indicates specified signal received */
2013 static char gotsig[NSIG - 1];
2015 static void clear_traps(void);
2016 static void setsignal(int);
2017 static void ignoresig(int);
2018 static void onsig(int);
2019 static int dotrap(void);
2020 static void setinteractive(int);
2021 static void exitshell(void) ATTRIBUTE_NORETURN;
2022 static int decode_signal(const char *, int);
2025 * This routine is called when an error or an interrupt occurs in an
2026 * interactive shell and control is returned to the main command loop.
2040 parselleft = parsenleft = 0; /* clear input buffer */
2044 /* from parser.c: */
2057 #ifdef CONFIG_ASH_ALIAS
2058 static struct alias *atab[ATABSIZE];
2060 static void setalias(const char *, const char *);
2061 static struct alias *freealias(struct alias *);
2062 static struct alias **__lookupalias(const char *);
2065 setalias(const char *name, const char *val)
2067 struct alias *ap, **app;
2069 app = __lookupalias(name);
2073 if (!(ap->flag & ALIASINUSE)) {
2076 ap->val = savestr(val);
2077 ap->flag &= ~ALIASDEAD;
2080 ap = ckmalloc(sizeof (struct alias));
2081 ap->name = savestr(name);
2082 ap->val = savestr(val);
2091 unalias(const char *name)
2095 app = __lookupalias(name);
2099 *app = freealias(*app);
2110 struct alias *ap, **app;
2114 for (i = 0; i < ATABSIZE; i++) {
2116 for (ap = *app; ap; ap = *app) {
2117 *app = freealias(*app);
2126 static struct alias *
2127 lookupalias(const char *name, int check)
2129 struct alias *ap = *__lookupalias(name);
2131 if (check && ap && (ap->flag & ALIASINUSE))
2137 * TODO - sort output
2140 aliascmd(int argc, char **argv)
2149 for (i = 0; i < ATABSIZE; i++)
2150 for (ap = atab[i]; ap; ap = ap->next) {
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);
2172 unaliascmd(int argc, char **argv)
2176 while ((i = nextopt("a")) != '\0') {
2182 for (i = 0; *argptr; argptr++) {
2183 if (unalias(*argptr)) {
2184 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2192 static struct alias *
2193 freealias(struct alias *ap) {
2196 if (ap->flag & ALIASINUSE) {
2197 ap->flag |= ALIASDEAD;
2209 printalias(const struct alias *ap) {
2210 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2213 static struct alias **
2214 __lookupalias(const char *name) {
2215 unsigned int hashval;
2222 ch = (unsigned char)*p;
2226 ch = (unsigned char)*++p;
2228 app = &atab[hashval % ATABSIZE];
2230 for (; *app; app = &(*app)->next) {
2231 if (equal(name, (*app)->name)) {
2238 #endif /* CONFIG_ASH_ALIAS */
2244 * The cd and pwd commands.
2247 #define CD_PHYSICAL 1
2250 static int docd(const char *, int);
2251 static int cdopt(void);
2253 static char *curdir = nullstr; /* current working directory */
2254 static char *physdir = nullstr; /* physical working directory */
2263 while ((i = nextopt("LP"))) {
2265 flags ^= CD_PHYSICAL;
2274 cdcmd(int argc, char **argv)
2286 dest = bltinlookup(homestr);
2287 else if (dest[0] == '-' && dest[1] == '\0') {
2288 dest = bltinlookup("OLDPWD");
2310 if (!(path = bltinlookup("CDPATH"))) {
2318 p = padvance(&path, dest);
2319 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2323 if (!docd(p, flags))
2328 sh_error("can't cd to %s", dest);
2331 if (flags & CD_PRINT)
2332 out1fmt(snlfmt, curdir);
2338 * Update curdir (the name of the current directory) in response to a
2342 static inline const char *
2343 updatepwd(const char *dir)
2350 cdcomppath = sstrdup(dir);
2353 if (curdir == nullstr)
2355 new = stputs(curdir, new);
2357 new = makestrspace(strlen(dir) + 2, new);
2358 lim = stackblock() + 1;
2362 if (new > lim && *lim == '/')
2367 if (dir[1] == '/' && dir[2] != '/') {
2373 p = strtok(cdcomppath, "/");
2377 if (p[1] == '.' && p[2] == '\0') {
2384 } else if (p[1] == '\0')
2388 new = stputs(p, new);
2396 return stackblock();
2400 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2401 * know that the current directory has changed.
2405 docd(const char *dest, int flags)
2407 const char *dir = 0;
2410 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2413 if (!(flags & CD_PHYSICAL)) {
2414 dir = updatepwd(dest);
2429 * Find out what the current directory is. If we already know the current
2430 * directory, this routine returns immediately.
2432 static inline char *
2435 char *dir = getcwd(0, 0);
2436 return dir ? dir : nullstr;
2440 pwdcmd(int argc, char **argv)
2443 const char *dir = curdir;
2447 if (physdir == nullstr)
2451 out1fmt(snlfmt, dir);
2456 setpwd(const char *val, int setold)
2460 oldcur = dir = curdir;
2463 setvar("OLDPWD", oldcur, VEXPORT);
2466 if (physdir != nullstr) {
2467 if (physdir != oldcur)
2471 if (oldcur == val || !val) {
2478 if (oldcur != dir && oldcur != nullstr) {
2483 setvar("PWD", dir, VEXPORT);
2489 * Errors and exceptions.
2493 * Code to handle exceptions in C.
2498 static void exverror(int, const char *, va_list)
2502 * Called to raise an exception. Since C doesn't include exceptions, we
2503 * just do a longjmp to the exception handler. The type of exception is
2504 * stored in the global variable "exception".
2511 if (handler == NULL)
2517 longjmp(handler->loc, 1);
2522 * Called from trap.c when a SIGINT is received. (If the user specifies
2523 * that SIGINT is to be trapped or ignored using the trap builtin, then
2524 * this routine is not called.) Suppressint is nonzero when interrupts
2525 * are held using the INTOFF macro. (The test for iflag is just
2526 * defensive programming.)
2535 /* comment by vodz: its strange for me, this programm don`t use other
2540 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2541 if (!(rootshell && iflag)) {
2542 signal(SIGINT, SIG_DFL);
2552 exvwarning(const char *msg, va_list ap)
2557 fprintf(errs, "%s: ", arg0);
2559 const char *fmt = (!iflag || parsefile->fd) ?
2560 "%s: %d: " : "%s: ";
2561 fprintf(errs, fmt, commandname, startlinno);
2563 vfprintf(errs, msg, ap);
2564 outcslow('\n', errs);
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.
2573 exverror(int cond, const char *msg, va_list ap)
2577 TRACE(("exverror(%d, \"", cond));
2579 TRACE(("\") pid=%d\n", getpid()));
2581 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2584 exvwarning(msg, ap);
2593 sh_error(const char *msg, ...)
2598 exverror(EXERROR, msg, ap);
2605 exerror(int cond, const char *msg, ...)
2610 exverror(cond, msg, ap);
2616 * error/warning routines for external builtins
2620 sh_warnx(const char *fmt, ...)
2625 exvwarning(fmt, ap);
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.
2637 errmsg(int e, const char *em)
2639 if(e == ENOENT || e == ENOTDIR) {
2650 * Evaluate a command.
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 */
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 **);
2672 static const struct builtincmd bltin = {
2678 * Called to reset things after an exception.
2686 evalcmd(int argc, char **argv)
2695 STARTSTACKSTR(concat);
2698 concat = stputs(p, concat);
2699 if ((p = *ap++) == NULL)
2701 STPUTC(' ', concat);
2703 STPUTC('\0', concat);
2704 p = grabstackstr(concat);
2706 evalstring(p, ~SKIPEVAL);
2714 * Execute a command or commands contained in a string.
2718 evalstring(char *s, int mask)
2721 struct stackmark smark;
2725 setstackmark(&smark);
2728 while ((n = parsecmd(0)) != NEOF) {
2730 popstackmark(&smark);
2745 * Evaluate a parse tree. The value is left in the global variable
2750 evaltree(union node *n, int flags)
2753 void (*evalfn)(union node *, int);
2757 TRACE(("evaltree(NULL) called\n"));
2760 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2761 getpid(), n, n->type, flags));
2765 out1fmt("Node type = %d\n", n->type);
2770 evaltree(n->nnot.com, EV_TESTED);
2771 status = !exitstatus;
2774 expredir(n->nredir.redirect);
2775 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2777 evaltree(n->nredir.n, flags & EV_TESTED);
2778 status = exitstatus;
2783 evalfn = evalcommand;
2785 if (eflag && !(flags & EV_TESTED))
2797 evalfn = evalsubshell;
2809 #error NAND + 1 != NOR
2811 #if NOR + 1 != NSEMI
2812 #error NOR + 1 != NSEMI
2814 isor = n->type - NAND;
2817 (flags | ((isor >> 1) - 1)) & EV_TESTED
2819 if (!exitstatus == isor)
2831 evaltree(n->nif.test, EV_TESTED);
2834 if (exitstatus == 0) {
2837 } else if (n->nif.elsepart) {
2838 n = n->nif.elsepart;
2843 defun(n->narg.text, n->narg.next);
2847 exitstatus = status;
2851 if ((checkexit & exitstatus))
2852 evalskip |= SKIPEVAL;
2853 else if (pendingsigs && dotrap())
2856 if (flags & EV_EXIT) {
2863 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2866 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2870 evalloop(union node *n, int flags)
2880 evaltree(n->nbinary.ch1, EV_TESTED);
2882 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2886 if (evalskip == SKIPBREAK && --skipcount <= 0)
2891 if (n->type != NWHILE)
2895 evaltree(n->nbinary.ch2, flags);
2896 status = exitstatus;
2901 exitstatus = status;
2907 evalfor(union node *n, int flags)
2909 struct arglist arglist;
2912 struct stackmark smark;
2914 setstackmark(&smark);
2915 arglist.lastp = &arglist.list;
2916 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2917 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2922 *arglist.lastp = NULL;
2927 for (sp = arglist.list ; sp ; sp = sp->next) {
2928 setvar(n->nfor.var, sp->text, 0);
2929 evaltree(n->nfor.body, flags);
2931 if (evalskip == SKIPCONT && --skipcount <= 0) {
2935 if (evalskip == SKIPBREAK && --skipcount <= 0)
2942 popstackmark(&smark);
2948 evalcase(union node *n, int flags)
2952 struct arglist arglist;
2953 struct stackmark smark;
2955 setstackmark(&smark);
2956 arglist.lastp = &arglist.list;
2957 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2959 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2960 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2961 if (casematch(patp, arglist.list->text)) {
2962 if (evalskip == 0) {
2963 evaltree(cp->nclist.body, flags);
2970 popstackmark(&smark);
2976 * Kick off a subshell to evaluate a tree.
2980 evalsubshell(union node *n, int flags)
2983 int backgnd = (n->type == NBACKGND);
2986 expredir(n->nredir.redirect);
2987 if (!backgnd && flags & EV_EXIT && !trap[0])
2991 if (forkshell(jp, n, backgnd) == 0) {
2995 flags &=~ EV_TESTED;
2997 redirect(n->nredir.redirect, 0);
2998 evaltreenr(n->nredir.n, flags);
3003 status = waitforjob(jp);
3004 exitstatus = status;
3011 * Compute the names of the files in a redirection list.
3015 expredir(union node *n)
3019 for (redir = n ; redir ; redir = redir->nfile.next) {
3021 fn.lastp = &fn.list;
3022 switch (redir->type) {
3028 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3029 redir->nfile.expfname = fn.list->text;
3033 if (redir->ndup.vname) {
3034 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3035 fixredir(redir, fn.list->text, 1);
3045 * Evaluate a pipeline. All the processes in the pipeline are children
3046 * of the process creating the pipeline. (This differs from some versions
3047 * of the shell, which make the last process in a pipeline the parent
3052 evalpipe(union node *n, int flags)
3055 struct nodelist *lp;
3060 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3062 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3066 jp = makejob(n, pipelen);
3068 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3072 if (pipe(pip) < 0) {
3074 sh_error("Pipe call failed");
3077 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3090 evaltreenr(lp->n, flags);
3098 if (n->npipe.backgnd == 0) {
3099 exitstatus = waitforjob(jp);
3100 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3108 * Execute a command inside back quotes. If it's a builtin command, we
3109 * want to save its output in a block obtained from malloc. Otherwise
3110 * we fork off a subprocess and get the output of the command via a pipe.
3111 * Should be called with interrupts off.
3115 evalbackcmd(union node *n, struct backcmd *result)
3127 saveherefd = herefd;
3135 sh_error("Pipe call failed");
3137 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3146 evaltreenr(n, EV_EXIT);
3150 result->fd = pip[0];
3153 herefd = saveherefd;
3155 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3156 result->fd, result->buf, result->nleft, result->jp));
3159 #ifdef CONFIG_ASH_CMDCMD
3160 static inline char **
3161 parse_command_args(char **argv, const char **path)
3173 if (c == '-' && !*cp) {
3183 /* run 'typecmd' for other options */
3186 } while ((c = *cp++));
3193 isassignment(const char *p)
3195 const char *q = endofname(p);
3201 #ifdef CONFIG_ASH_EXPAND_PRMT
3202 static const char *expandstr(const char *ps);
3204 #define expandstr(s) s
3208 * Execute a simple command.
3212 evalcommand(union node *cmd, int flags)
3214 struct stackmark smark;
3216 struct arglist arglist;
3217 struct arglist varlist;
3220 const struct strlist *sp;
3221 struct cmdentry cmdentry;
3229 struct builtincmd *bcmd;
3230 int pseudovarflag = 0;
3232 /* First expand the arguments. */
3233 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3234 setstackmark(&smark);
3235 back_exitstatus = 0;
3237 cmdentry.cmdtype = CMDBUILTIN;
3238 cmdentry.u.cmd = &bltin;
3239 varlist.lastp = &varlist.list;
3240 *varlist.lastp = NULL;
3241 arglist.lastp = &arglist.list;
3242 *arglist.lastp = NULL;
3247 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3248 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3251 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3252 struct strlist **spp;
3254 spp = arglist.lastp;
3255 if (pseudovarflag && isassignment(argp->narg.text))
3256 expandarg(argp, &arglist, EXP_VARTILDE);
3258 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3260 for (sp = *spp; sp; sp = sp->next)
3264 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3265 for (sp = arglist.list ; sp ; sp = sp->next) {
3266 TRACE(("evalcommand arg: %s\n", sp->text));
3267 *nargv++ = sp->text;
3272 if (iflag && funcnest == 0 && argc > 0)
3273 lastarg = nargv[-1];
3276 expredir(cmd->ncmd.redirect);
3277 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3280 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3281 struct strlist **spp;
3284 spp = varlist.lastp;
3285 expandarg(argp, &varlist, EXP_VARTILDE);
3288 * Modify the command lookup path, if a PATH= assignment
3292 if (varequal(p, path))
3296 /* Print the command if xflag is set. */
3299 const char *p = " %s";
3302 dprintf(preverrout_fd, p, expandstr(ps4val()));
3305 for(n = 0; n < 2; n++) {
3307 dprintf(preverrout_fd, p, sp->text);
3315 bb_full_write(preverrout_fd, "\n", 1);
3321 /* Now locate the command. */
3323 const char *oldpath;
3324 int cmd_flag = DO_ERR;
3329 find_command(argv[0], &cmdentry, cmd_flag, path);
3330 if (cmdentry.cmdtype == CMDUNKNOWN) {
3336 /* implement bltin and command here */
3337 if (cmdentry.cmdtype != CMDBUILTIN)
3340 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3341 if (cmdentry.u.cmd == EXECCMD)
3343 #ifdef CONFIG_ASH_CMDCMD
3344 if (cmdentry.u.cmd == COMMANDCMD) {
3347 nargv = parse_command_args(argv, &path);
3350 argc -= nargv - argv;
3352 cmd_flag |= DO_NOFUNC;
3360 /* We have a redirection error. */
3364 exitstatus = status;
3368 /* Execute the command. */
3369 switch (cmdentry.cmdtype) {
3371 /* Fork off a child process if necessary. */
3372 if (!(flags & EV_EXIT) || trap[0]) {
3374 jp = makejob(cmd, 1);
3375 if (forkshell(jp, cmd, FORK_FG) != 0) {
3376 exitstatus = waitforjob(jp);
3382 listsetvar(varlist.list, VEXPORT|VSTACK);
3383 shellexec(argv, path, cmdentry.u.index);
3387 cmdenviron = varlist.list;
3389 struct strlist *list = cmdenviron;
3391 if (spclbltin > 0 || argc == 0) {
3393 if (cmd_is_exec && argc > 1)
3396 listsetvar(list, i);
3398 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3413 exit_status = j + 128;
3414 exitstatus = exit_status;
3416 if (i == EXINT || spclbltin > 0) {
3418 longjmp(handler->loc, 1);
3425 listsetvar(varlist.list, 0);
3426 if (evalfun(cmdentry.u.func, argc, argv, flags))
3432 popredir(cmd_is_exec);
3434 /* dsl: I think this is intended to be used to support
3435 * '_' in 'vi' command mode during line editing...
3436 * However I implemented that within libedit itself.
3438 setvar("_", lastarg, 0);
3439 popstackmark(&smark);
3443 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3444 char *volatile savecmdname;
3445 struct jmploc *volatile savehandler;
3446 struct jmploc jmploc;
3449 savecmdname = commandname;
3450 if ((i = setjmp(jmploc.loc)))
3452 savehandler = handler;
3454 commandname = argv[0];
3456 optptr = NULL; /* initialize nextopt */
3457 exitstatus = (*cmd->builtin)(argc, argv);
3460 exitstatus |= ferror(stdout);
3461 commandname = savecmdname;
3463 handler = savehandler;
3469 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3471 volatile struct shparam saveparam;
3472 struct localvar *volatile savelocalvars;
3473 struct jmploc *volatile savehandler;
3474 struct jmploc jmploc;
3477 saveparam = shellparam;
3478 savelocalvars = localvars;
3479 if ((e = setjmp(jmploc.loc))) {
3483 savehandler = handler;
3486 shellparam.malloc = 0;
3490 shellparam.nparam = argc - 1;
3491 shellparam.p = argv + 1;
3492 #ifdef CONFIG_ASH_GETOPTS
3493 shellparam.optind = 1;
3494 shellparam.optoff = -1;
3496 evaltree(&func->n, flags & EV_TESTED);
3502 localvars = savelocalvars;
3503 freeparam(&shellparam);
3504 shellparam = saveparam;
3505 handler = savehandler;
3507 evalskip &= ~SKIPFUNC;
3513 goodname(const char *p)
3515 return !*endofname(p);
3519 * Search for a command. This is called before we fork so that the
3520 * location of the command will be available in the parent as well as
3521 * the child. The check for "goodname" is an overly conservative
3522 * check that the name will not be subject to expansion.
3526 prehash(union node *n)
3528 struct cmdentry entry;
3530 if (n->type == NCMD && n->ncmd.args)
3531 if (goodname(n->ncmd.args->narg.text))
3532 find_command(n->ncmd.args->narg.text, &entry, 0,
3539 * Builtin commands. Builtin commands whose functions are closely
3540 * tied to evaluation are implemented here.
3548 bltincmd(int argc, char **argv)
3551 * Preserve exitstatus of a previous possible redirection
3554 return back_exitstatus;
3559 * Handle break and continue commands. Break, continue, and return are
3560 * all handled by setting the evalskip flag. The evaluation routines
3561 * above all check this flag, and if it is set they start skipping
3562 * commands rather than executing them. The variable skipcount is
3563 * the number of loops to break/continue, or the number of function
3564 * levels to return. (The latter is always 1.) It should probably
3565 * be an error to break out of more loops than exist, but it isn't
3566 * in the standard shell so we don't make it one here.
3570 breakcmd(int argc, char **argv)
3572 int n = argc > 1 ? number(argv[1]) : 1;
3575 sh_error(illnum, argv[1]);
3579 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3587 * The return command.
3591 returncmd(int argc, char **argv)
3594 * If called outside a function, do what ksh does;
3595 * skip the rest of the file.
3597 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3598 return argv[1] ? number(argv[1]) : exitstatus;
3603 falsecmd(int argc, char **argv)
3610 truecmd(int argc, char **argv)
3617 execcmd(int argc, char **argv)
3620 iflag = 0; /* exit on error */
3623 shellexec(argv + 1, pathval(), 0);
3632 * When commands are first encountered, they are entered in a hash table.
3633 * This ensures that a full path search will not have to be done for them
3634 * on each invocation.
3636 * We should investigate converting to a linear search, even though that
3637 * would make the command name "hash" a misnomer.
3640 #define CMDTABLESIZE 31 /* should be prime */
3641 #define ARB 1 /* actual size determined at run time */
3646 struct tblentry *next; /* next entry in hash chain */
3647 union param param; /* definition of builtin function */
3648 short cmdtype; /* index identifying command */
3649 char rehash; /* if set, cd done since entry created */
3650 char cmdname[ARB]; /* name of command */
3654 static struct tblentry *cmdtable[CMDTABLESIZE];
3655 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3658 static void tryexec(char *, char **, char **);
3659 static void clearcmdentry(int);
3660 static struct tblentry *cmdlookup(const char *, int);
3661 static void delete_cmd_entry(void);
3665 * Exec a program. Never returns. If you change this routine, you may
3666 * have to change the find_command routine as well.
3670 shellexec(char **argv, const char *path, int idx)
3678 envp = environment();
3679 if (strchr(argv[0], '/') != NULL
3680 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3681 || find_applet_by_name(argv[0])
3684 tryexec(argv[0], argv, envp);
3688 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3689 if (--idx < 0 && pathopt == NULL) {
3690 tryexec(cmdname, argv, envp);
3691 if (errno != ENOENT && errno != ENOTDIR)
3698 /* Map to POSIX errors */
3710 exitstatus = exerrno;
3711 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3712 argv[0], e, suppressint ));
3713 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3719 tryexec(char *cmd, char **argv, char **envp)
3722 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3723 if(find_applet_by_name(cmd) != NULL) {
3724 /* re-exec ourselves with the new arguments */
3725 execve("/proc/self/exe",argv,envp);
3726 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3727 execve("/bin/busybox",argv,envp);
3728 /* If they called chroot or otherwise made the binary no longer
3729 * executable, fall through */
3736 execve(cmd, argv, envp);
3737 } while (errno == EINTR);
3739 execve(cmd, argv, envp);
3743 } else if (errno == ENOEXEC) {
3747 for (ap = argv; *ap; ap++)
3749 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3751 *ap = cmd = (char *)DEFAULT_SHELL;
3754 while ((*ap++ = *argv++))
3764 * Do a path search. The variable path (passed by reference) should be
3765 * set to the start of the path before the first call; padvance will update
3766 * this value as it proceeds. Successive calls to padvance will return
3767 * the possible path expansions in sequence. If an option (indicated by
3768 * a percent sign) appears in the path entry then the global variable
3769 * pathopt will be set to point to it; otherwise pathopt will be set to
3774 padvance(const char **path, const char *name)
3784 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3785 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3786 while (stackblocksize() < len)
3790 memcpy(q, start, p - start);
3798 while (*p && *p != ':') p++;
3804 return stalloc(len);
3808 /*** Command hashing code ***/
3811 printentry(struct tblentry *cmdp)
3817 idx = cmdp->param.index;
3820 name = padvance(&path, cmdp->cmdname);
3822 } while (--idx >= 0);
3823 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3828 hashcmd(int argc, char **argv)
3830 struct tblentry **pp;
3831 struct tblentry *cmdp;
3833 struct cmdentry entry;
3836 while ((c = nextopt("r")) != '\0') {
3840 if (*argptr == NULL) {
3841 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3842 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3843 if (cmdp->cmdtype == CMDNORMAL)
3850 while ((name = *argptr) != NULL) {
3851 if ((cmdp = cmdlookup(name, 0)) != NULL
3852 && (cmdp->cmdtype == CMDNORMAL
3853 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3855 find_command(name, &entry, DO_ERR, pathval());
3856 if (entry.cmdtype == CMDUNKNOWN)
3865 * Resolve a command name. If you change this routine, you may have to
3866 * change the shellexec routine as well.
3870 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3872 struct tblentry *cmdp;
3879 struct builtincmd *bcmd;
3881 /* If name contains a slash, don't use PATH or hash table */
3882 if (strchr(name, '/') != NULL) {
3883 entry->u.index = -1;
3885 while (stat(name, &statb) < 0) {
3890 entry->cmdtype = CMDUNKNOWN;
3894 entry->cmdtype = CMDNORMAL;
3898 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3899 if (find_applet_by_name(name)) {
3900 entry->cmdtype = CMDNORMAL;
3901 entry->u.index = -1;
3906 updatetbl = (path == pathval());
3909 if (strstr(path, "%builtin") != NULL)
3913 /* If name is in the table, check answer will be ok */
3914 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3917 switch (cmdp->cmdtype) {
3935 } else if (cmdp->rehash == 0)
3936 /* if not invalidated by cd, we're done */
3940 /* If %builtin not in path, check for builtin next */
3941 bcmd = find_builtin(name);
3942 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3943 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3945 goto builtin_success;
3947 /* We have to search path. */
3948 prev = -1; /* where to start */
3949 if (cmdp && cmdp->rehash) { /* doing a rehash */
3950 if (cmdp->cmdtype == CMDBUILTIN)
3953 prev = cmdp->param.index;
3959 while ((fullname = padvance(&path, name)) != NULL) {
3960 stunalloc(fullname);
3963 if (prefix(pathopt, "builtin")) {
3965 goto builtin_success;
3967 } else if (!(act & DO_NOFUNC) &&
3968 prefix(pathopt, "func")) {
3971 /* ignore unimplemented options */
3975 /* if rehash, don't redo absolute path names */
3976 if (fullname[0] == '/' && idx <= prev) {
3979 TRACE(("searchexec \"%s\": no change\n", name));
3982 while (stat(fullname, &statb) < 0) {
3987 if (errno != ENOENT && errno != ENOTDIR)
3991 e = EACCES; /* if we fail, this will be the error */
3992 if (!S_ISREG(statb.st_mode))
3994 if (pathopt) { /* this is a %func directory */
3995 stalloc(strlen(fullname) + 1);
3996 readcmdfile(fullname);
3997 if ((cmdp = cmdlookup(name, 0)) == NULL ||
3998 cmdp->cmdtype != CMDFUNCTION)
3999 sh_error("%s not defined in %s", name, fullname);
4000 stunalloc(fullname);
4003 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4005 entry->cmdtype = CMDNORMAL;
4006 entry->u.index = idx;
4010 cmdp = cmdlookup(name, 1);
4011 cmdp->cmdtype = CMDNORMAL;
4012 cmdp->param.index = idx;
4017 /* We failed. If there was an entry for this command, delete it */
4018 if (cmdp && updatetbl)
4021 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4022 entry->cmdtype = CMDUNKNOWN;
4027 entry->cmdtype = CMDBUILTIN;
4028 entry->u.cmd = bcmd;
4032 cmdp = cmdlookup(name, 1);
4033 cmdp->cmdtype = CMDBUILTIN;
4034 cmdp->param.cmd = bcmd;
4038 entry->cmdtype = cmdp->cmdtype;
4039 entry->u = cmdp->param;
4044 * Wrapper around strcmp for qsort/bsearch/...
4046 static int pstrcmp(const void *a, const void *b)
4048 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4052 * Search the table of builtin commands.
4055 static struct builtincmd *
4056 find_builtin(const char *name)
4058 struct builtincmd *bp;
4061 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4070 * Called when a cd is done. Marks all commands so the next time they
4071 * are executed they will be rehashed.
4077 struct tblentry **pp;
4078 struct tblentry *cmdp;
4080 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4081 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4082 if (cmdp->cmdtype == CMDNORMAL || (
4083 cmdp->cmdtype == CMDBUILTIN &&
4084 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4095 * Fix command hash table when PATH changed.
4096 * Called before PATH is changed. The argument is the new value of PATH;
4097 * pathval() still returns the old value at this point.
4098 * Called with interrupts off.
4102 changepath(const char *newval)
4104 const char *old, *new;
4111 firstchange = 9999; /* assume no change */
4117 if ((*old == '\0' && *new == ':')
4118 || (*old == ':' && *new == '\0'))
4120 old = new; /* ignore subsequent differences */
4124 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4131 if (builtinloc < 0 && idx_bltin >= 0)
4132 builtinloc = idx_bltin; /* zap builtins */
4133 if (builtinloc >= 0 && idx_bltin < 0)
4135 clearcmdentry(firstchange);
4136 builtinloc = idx_bltin;
4141 * Clear out command entries. The argument specifies the first entry in
4142 * PATH which has changed.
4146 clearcmdentry(int firstchange)
4148 struct tblentry **tblp;
4149 struct tblentry **pp;
4150 struct tblentry *cmdp;
4153 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4155 while ((cmdp = *pp) != NULL) {
4156 if ((cmdp->cmdtype == CMDNORMAL &&
4157 cmdp->param.index >= firstchange)
4158 || (cmdp->cmdtype == CMDBUILTIN &&
4159 builtinloc >= firstchange)) {
4173 * Locate a command in the command hash table. If "add" is nonzero,
4174 * add the command to the table if it is not already present. The
4175 * variable "lastcmdentry" is set to point to the address of the link
4176 * pointing to the entry, so that delete_cmd_entry can delete the
4179 * Interrupts must be off if called with add != 0.
4182 static struct tblentry **lastcmdentry;
4185 static struct tblentry *
4186 cmdlookup(const char *name, int add)
4188 unsigned int hashval;
4190 struct tblentry *cmdp;
4191 struct tblentry **pp;
4194 hashval = (unsigned char)*p << 4;
4196 hashval += (unsigned char)*p++;
4198 pp = &cmdtable[hashval % CMDTABLESIZE];
4199 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4200 if (equal(cmdp->cmdname, name))
4204 if (add && cmdp == NULL) {
4205 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4206 + strlen(name) + 1);
4208 cmdp->cmdtype = CMDUNKNOWN;
4209 strcpy(cmdp->cmdname, name);
4216 * Delete the command entry returned on the last lookup.
4220 delete_cmd_entry(void)
4222 struct tblentry *cmdp;
4225 cmdp = *lastcmdentry;
4226 *lastcmdentry = cmdp->next;
4227 if (cmdp->cmdtype == CMDFUNCTION)
4228 freefunc(cmdp->param.func);
4235 * Add a new command entry, replacing any existing command entry for
4236 * the same name - except special builtins.
4240 addcmdentry(char *name, struct cmdentry *entry)
4242 struct tblentry *cmdp;
4244 cmdp = cmdlookup(name, 1);
4245 if (cmdp->cmdtype == CMDFUNCTION) {
4246 freefunc(cmdp->param.func);
4248 cmdp->cmdtype = entry->cmdtype;
4249 cmdp->param = entry->u;
4254 * Make a copy of a parse tree.
4257 static inline struct funcnode *
4258 copyfunc(union node *n)
4263 funcblocksize = offsetof(struct funcnode, n);
4266 blocksize = funcblocksize;
4267 f = ckmalloc(blocksize + funcstringsize);
4268 funcblock = (char *) f + offsetof(struct funcnode, n);
4269 funcstring = (char *) f + blocksize;
4276 * Define a shell function.
4280 defun(char *name, union node *func)
4282 struct cmdentry entry;
4285 entry.cmdtype = CMDFUNCTION;
4286 entry.u.func = copyfunc(func);
4287 addcmdentry(name, &entry);
4293 * Delete a function if it exists.
4297 unsetfunc(const char *name)
4299 struct tblentry *cmdp;
4301 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4302 cmdp->cmdtype == CMDFUNCTION)
4307 * Locate and print what a word is...
4311 #ifdef CONFIG_ASH_CMDCMD
4313 describe_command(char *command, int describe_command_verbose)
4315 #define describe_command_verbose 1
4317 describe_command(char *command)
4320 struct cmdentry entry;
4321 struct tblentry *cmdp;
4322 #ifdef CONFIG_ASH_ALIAS
4323 const struct alias *ap;
4325 const char *path = pathval();
4327 if (describe_command_verbose) {
4331 /* First look at the keywords */
4332 if (findkwd(command)) {
4333 out1str(describe_command_verbose ? " is a shell keyword" : command);
4337 #ifdef CONFIG_ASH_ALIAS
4338 /* Then look at the aliases */
4339 if ((ap = lookupalias(command, 0)) != NULL) {
4340 if (describe_command_verbose) {
4341 out1fmt(" is an alias for %s", ap->val);
4350 /* Then check if it is a tracked alias */
4351 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4352 entry.cmdtype = cmdp->cmdtype;
4353 entry.u = cmdp->param;
4355 /* Finally use brute force */
4356 find_command(command, &entry, DO_ABS, path);
4359 switch (entry.cmdtype) {
4361 int j = entry.u.index;
4367 p = padvance(&path, command);
4371 if (describe_command_verbose) {
4373 (cmdp ? " a tracked alias for" : nullstr), p
4382 if (describe_command_verbose) {
4383 out1str(" is a shell function");
4390 if (describe_command_verbose) {
4391 out1fmt(" is a %sshell builtin",
4392 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4393 "special " : nullstr
4401 if (describe_command_verbose) {
4402 out1str(": not found\n");
4408 outstr("\n", stdout);
4413 typecmd(int argc, char **argv)
4418 for (i = 1; i < argc; i++) {
4419 #ifdef CONFIG_ASH_CMDCMD
4420 err |= describe_command(argv[i], 1);
4422 err |= describe_command(argv[i]);
4428 #ifdef CONFIG_ASH_CMDCMD
4430 commandcmd(int argc, char **argv)
4438 while ((c = nextopt("pvV")) != '\0')
4440 verify |= VERIFY_VERBOSE;
4442 verify |= VERIFY_BRIEF;
4448 return describe_command(*argptr, verify - VERIFY_BRIEF);
4457 * Routines to expand arguments to commands. We have to deal with
4458 * backquotes, shell variables, and file metacharacters.
4464 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4465 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4466 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4467 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4468 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4471 * Structure specifying which parts of the string should be searched
4472 * for IFS characters.
4476 struct ifsregion *next; /* next region in list */
4477 int begoff; /* offset of start of region */
4478 int endoff; /* offset of end of region */
4479 int nulonly; /* search for nul bytes only */
4482 /* output of current string */
4483 static char *expdest;
4484 /* list of back quote expressions */
4485 static struct nodelist *argbackq;
4486 /* first struct in list of ifs regions */
4487 static struct ifsregion ifsfirst;
4488 /* last struct in list */
4489 static struct ifsregion *ifslastp;
4490 /* holds expanded arg list */
4491 static struct arglist exparg;
4493 static void argstr(char *, int);
4494 static char *exptilde(char *, char *, int);
4495 static void expbackq(union node *, int, int);
4496 static const char *subevalvar(char *, char *, int, int, int, int, int);
4497 static char *evalvar(char *, int);
4498 static void strtodest(const char *, int, int);
4499 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4500 static ssize_t varvalue(char *, int, int);
4501 static void recordregion(int, int, int);
4502 static void removerecordregions(int);
4503 static void ifsbreakup(char *, struct arglist *);
4504 static void ifsfree(void);
4505 static void expandmeta(struct strlist *, int);
4506 static int patmatch(char *, const char *);
4508 static int cvtnum(arith_t);
4509 static size_t esclen(const char *, const char *);
4510 static char *scanleft(char *, char *, char *, char *, int, int);
4511 static char *scanright(char *, char *, char *, char *, int, int);
4512 static void varunset(const char *, const char *, const char *, int)
4516 #define pmatch(a, b) !fnmatch((a), (b), 0)
4518 * Prepare a pattern for a expmeta (internal glob(3)) call.
4520 * Returns an stalloced string.
4523 static inline char *
4524 preglob(const char *pattern, int quoted, int flag) {
4525 flag |= RMESCAPE_GLOB;
4527 flag |= RMESCAPE_QUOTED;
4529 return _rmescapes((char *)pattern, flag);
4534 esclen(const char *start, const char *p) {
4537 while (p > start && *--p == CTLESC) {
4545 * Expand shell variables and backquotes inside a here document.
4549 expandhere(union node *arg, int fd)
4552 expandarg(arg, (struct arglist *)NULL, 0);
4553 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4558 * Perform variable substitution and command substitution on an argument,
4559 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4560 * perform splitting and file name expansion. When arglist is NULL, perform
4561 * here document expansion.
4565 expandarg(union node *arg, struct arglist *arglist, int flag)
4570 argbackq = arg->narg.backquote;
4571 STARTSTACKSTR(expdest);
4572 ifsfirst.next = NULL;
4574 argstr(arg->narg.text, flag);
4575 p = _STPUTC('\0', expdest);
4577 if (arglist == NULL) {
4578 return; /* here document expanded */
4580 p = grabstackstr(p);
4581 exparg.lastp = &exparg.list;
4585 if (flag & EXP_FULL) {
4586 ifsbreakup(p, &exparg);
4587 *exparg.lastp = NULL;
4588 exparg.lastp = &exparg.list;
4589 expandmeta(exparg.list, flag);
4591 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4593 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4596 exparg.lastp = &sp->next;
4600 *exparg.lastp = NULL;
4602 *arglist->lastp = exparg.list;
4603 arglist->lastp = exparg.lastp;
4609 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4610 * characters to allow for further processing. Otherwise treat
4611 * $@ like $* since no splitting will be performed.
4615 argstr(char *p, int flag)
4617 static const char spclchars[] = {
4625 CTLBACKQ | CTLQUOTE,
4626 #ifdef CONFIG_ASH_MATH_SUPPORT
4631 const char *reject = spclchars;
4633 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4634 int breakall = flag & EXP_WORD;
4639 if (!(flag & EXP_VARTILDE)) {
4641 } else if (flag & EXP_VARTILDE2) {
4646 if (flag & EXP_TILDE) {
4652 if (*q == CTLESC && (flag & EXP_QWORD))
4655 p = exptilde(p, q, flag);
4658 startloc = expdest - (char *)stackblock();
4660 length += strcspn(p + length, reject);
4662 if (c && (!(c & 0x80)
4663 #ifdef CONFIG_ASH_MATH_SUPPORT
4667 /* c == '=' || c == ':' || c == CTLENDARI */
4672 expdest = stnputs(p, length, expdest);
4673 newloc = expdest - (char *)stackblock();
4674 if (breakall && !inquotes && newloc > startloc) {
4675 recordregion(startloc, newloc, 0);
4686 if (flag & EXP_VARTILDE2) {
4690 flag |= EXP_VARTILDE2;
4695 * sort of a hack - expand tildes in variable
4696 * assignments (after the first '=' and after ':'s).
4705 case CTLENDVAR: /* ??? */
4708 /* "$@" syntax adherence hack */
4711 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4712 (p[4] == CTLQUOTEMARK || (
4713 p[4] == CTLENDVAR &&
4714 p[5] == CTLQUOTEMARK
4717 p = evalvar(p + 1, flag) + 1;
4720 inquotes = !inquotes;
4733 p = evalvar(p, flag);
4737 case CTLBACKQ|CTLQUOTE:
4738 expbackq(argbackq->n, c, quotes);
4739 argbackq = argbackq->next;
4741 #ifdef CONFIG_ASH_MATH_SUPPORT
4754 exptilde(char *startp, char *p, int flag)
4760 int quotes = flag & (EXP_FULL | EXP_CASE);
4765 while ((c = *++p) != '\0') {
4772 if (flag & EXP_VARTILDE)
4782 if (*name == '\0') {
4783 home = lookupvar(homestr);
4785 if ((pw = getpwnam(name)) == NULL)
4789 if (!home || !*home)
4792 startloc = expdest - (char *)stackblock();
4793 strtodest(home, SQSYNTAX, quotes);
4794 recordregion(startloc, expdest - (char *)stackblock(), 0);
4803 removerecordregions(int endoff)
4805 if (ifslastp == NULL)
4808 if (ifsfirst.endoff > endoff) {
4809 while (ifsfirst.next != NULL) {
4810 struct ifsregion *ifsp;
4812 ifsp = ifsfirst.next->next;
4813 ckfree(ifsfirst.next);
4814 ifsfirst.next = ifsp;
4817 if (ifsfirst.begoff > endoff)
4820 ifslastp = &ifsfirst;
4821 ifsfirst.endoff = endoff;
4826 ifslastp = &ifsfirst;
4827 while (ifslastp->next && ifslastp->next->begoff < endoff)
4828 ifslastp=ifslastp->next;
4829 while (ifslastp->next != NULL) {
4830 struct ifsregion *ifsp;
4832 ifsp = ifslastp->next->next;
4833 ckfree(ifslastp->next);
4834 ifslastp->next = ifsp;
4837 if (ifslastp->endoff > endoff)
4838 ifslastp->endoff = endoff;
4842 #ifdef CONFIG_ASH_MATH_SUPPORT
4844 * Expand arithmetic expression. Backup to start of expression,
4845 * evaluate, place result in (backed up) result, adjust string position.
4858 * This routine is slightly over-complicated for
4859 * efficiency. Next we scan backwards looking for the
4860 * start of arithmetic.
4862 start = stackblock();
4869 while (*p != CTLARI) {
4873 sh_error("missing CTLARI (shouldn't happen)");
4878 esc = esclen(start, p);
4888 removerecordregions(begoff);
4897 len = cvtnum(dash_arith(p + 2));
4900 recordregion(begoff, begoff + len, 0);
4905 * Expand stuff in backwards quotes.
4909 expbackq(union node *cmd, int quoted, int quotes)
4917 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4918 struct stackmark smark;
4921 setstackmark(&smark);
4923 startloc = dest - (char *)stackblock();
4925 evalbackcmd(cmd, (struct backcmd *) &in);
4926 popstackmark(&smark);
4933 memtodest(p, i, syntax, quotes);
4937 i = safe_read(in.fd, buf, sizeof buf);
4938 TRACE(("expbackq: read returns %d\n", i));
4948 back_exitstatus = waitforjob(in.jp);
4952 /* Eat all trailing newlines */
4954 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4959 recordregion(startloc, dest - (char *)stackblock(), 0);
4960 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4961 (dest - (char *)stackblock()) - startloc,
4962 (dest - (char *)stackblock()) - startloc,
4963 stackblock() + startloc));
4968 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4979 const char *s = loc2;
4985 match = pmatch(str, s);
4989 if (quotes && *loc == CTLESC)
4999 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5006 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5009 const char *s = loc2;
5014 match = pmatch(str, s);
5021 esc = esclen(startp, loc);
5033 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5037 int saveherefd = herefd;
5038 struct nodelist *saveargbackq = argbackq;
5040 char *rmesc, *rmescend;
5042 char *(*scan)(char *, char *, char *, char *, int , int);
5045 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5046 STPUTC('\0', expdest);
5047 herefd = saveherefd;
5048 argbackq = saveargbackq;
5049 startp = stackblock() + startloc;
5053 setvar(str, startp, 0);
5054 amount = startp - expdest;
5055 STADJUST(amount, expdest);
5059 varunset(p, str, startp, varflags);
5063 subtype -= VSTRIMRIGHT;
5065 if (subtype < 0 || subtype > 3)
5070 rmescend = stackblock() + strloc;
5072 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5073 if (rmesc != startp) {
5075 startp = stackblock() + startloc;
5079 str = stackblock() + strloc;
5080 preglob(str, varflags & VSQUOTE, 0);
5082 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5083 zero = subtype >> 1;
5084 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5085 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5087 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5090 memmove(startp, loc, str - loc);
5091 loc = startp + (str - loc) - 1;
5094 amount = loc - expdest;
5095 STADJUST(amount, expdest);
5102 * Expand a variable, and return a pointer to the next character in the
5106 evalvar(char *p, int flag)
5119 quotes = flag & (EXP_FULL | EXP_CASE);
5121 subtype = varflags & VSTYPE;
5122 quoted = varflags & VSQUOTE;
5124 easy = (!quoted || (*var == '@' && shellparam.nparam));
5125 startloc = expdest - (char *)stackblock();
5126 p = strchr(p, '=') + 1;
5129 varlen = varvalue(var, varflags, flag);
5130 if (varflags & VSNUL)
5133 if (subtype == VSPLUS) {
5134 varlen = -1 - varlen;
5138 if (subtype == VSMINUS) {
5142 p, flag | EXP_TILDE |
5143 (quoted ? EXP_QWORD : EXP_WORD)
5152 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5154 if (subevalvar(p, var, 0, subtype, startloc,
5158 * Remove any recorded regions beyond
5161 removerecordregions(startloc);
5171 if (varlen < 0 && uflag)
5172 varunset(p, var, 0, 0);
5174 if (subtype == VSLENGTH) {
5175 cvtnum(varlen > 0 ? varlen : 0);
5179 if (subtype == VSNORMAL) {
5183 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5192 case VSTRIMRIGHTMAX:
5201 * Terminate the string and start recording the pattern
5204 STPUTC('\0', expdest);
5205 patloc = expdest - (char *)stackblock();
5206 if (subevalvar(p, NULL, patloc, subtype,
5207 startloc, varflags, quotes) == 0) {
5208 int amount = expdest - (
5209 (char *)stackblock() + patloc - 1
5211 STADJUST(-amount, expdest);
5213 /* Remove any recorded regions beyond start of variable */
5214 removerecordregions(startloc);
5219 if (subtype != VSNORMAL) { /* skip to end of alternative */
5222 if ((c = *p++) == CTLESC)
5224 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5226 argbackq = argbackq->next;
5227 } else if (c == CTLVAR) {
5228 if ((*p++ & VSTYPE) != VSNORMAL)
5230 } else if (c == CTLENDVAR) {
5241 * Put a string on the stack.
5245 memtodest(const char *p, size_t len, int syntax, int quotes) {
5248 q = makestrspace(len * 2, q);
5251 int c = SC2INT(*p++);
5254 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5264 strtodest(const char *p, int syntax, int quotes)
5266 memtodest(p, strlen(p), syntax, quotes);
5271 * Add the value of a specialized variable to the stack string.
5275 varvalue(char *name, int varflags, int flags)
5285 int quoted = varflags & VSQUOTE;
5286 int subtype = varflags & VSTYPE;
5287 int quotes = flags & (EXP_FULL | EXP_CASE);
5289 if (quoted && (flags & EXP_FULL))
5290 sep = 1 << CHAR_BIT;
5292 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5301 num = shellparam.nparam;
5311 p = makestrspace(NOPTS, expdest);
5312 for (i = NOPTS - 1; i >= 0; i--) {
5314 USTPUTC(optletters(i), p);
5325 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5326 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5329 if (!(ap = shellparam.p))
5331 while ((p = *ap++)) {
5334 partlen = strlen(p);
5337 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5338 memtodest(p, partlen, syntax, quotes);
5344 if (subtype == VSPLUS || subtype == VSLENGTH) {
5366 if (num < 0 || num > shellparam.nparam)
5368 p = num ? shellparam.p[num - 1] : arg0;
5371 p = lookupvar(name);
5377 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5378 memtodest(p, len, syntax, quotes);
5382 if (subtype == VSPLUS || subtype == VSLENGTH)
5383 STADJUST(-len, expdest);
5389 * Record the fact that we have to scan this region of the
5390 * string for IFS characters.
5394 recordregion(int start, int end, int nulonly)
5396 struct ifsregion *ifsp;
5398 if (ifslastp == NULL) {
5402 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5404 ifslastp->next = ifsp;
5408 ifslastp->begoff = start;
5409 ifslastp->endoff = end;
5410 ifslastp->nulonly = nulonly;
5415 * Break the argument string into pieces based upon IFS and add the
5416 * strings to the argument list. The regions of the string to be
5417 * searched for IFS characters have been stored by recordregion.
5420 ifsbreakup(char *string, struct arglist *arglist)
5422 struct ifsregion *ifsp;
5427 const char *ifs, *realifs;
5433 if (ifslastp != NULL) {
5436 realifs = ifsset() ? ifsval() : defifs;
5439 p = string + ifsp->begoff;
5440 nulonly = ifsp->nulonly;
5441 ifs = nulonly ? nullstr : realifs;
5443 while (p < string + ifsp->endoff) {
5447 if (strchr(ifs, *p)) {
5449 ifsspc = (strchr(defifs, *p) != NULL);
5450 /* Ignore IFS whitespace at start */
5451 if (q == start && ifsspc) {
5457 sp = (struct strlist *)stalloc(sizeof *sp);
5459 *arglist->lastp = sp;
5460 arglist->lastp = &sp->next;
5464 if (p >= string + ifsp->endoff) {
5470 if (strchr(ifs, *p) == NULL ) {
5473 } else if (strchr(defifs, *p) == NULL) {
5489 } while ((ifsp = ifsp->next) != NULL);
5498 sp = (struct strlist *)stalloc(sizeof *sp);
5500 *arglist->lastp = sp;
5501 arglist->lastp = &sp->next;
5507 struct ifsregion *p;
5512 struct ifsregion *ifsp;
5518 ifsfirst.next = NULL;
5522 static void expmeta(char *, char *);
5523 static struct strlist *expsort(struct strlist *);
5524 static struct strlist *msort(struct strlist *, int);
5526 static char *expdir;
5530 expandmeta(struct strlist *str, int flag)
5532 static const char metachars[] = {
5535 /* TODO - EXP_REDIR */
5538 struct strlist **savelastp;
5544 if (!strpbrk(str->text, metachars))
5546 savelastp = exparg.lastp;
5549 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5551 int i = strlen(str->text);
5552 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5560 if (exparg.lastp == savelastp) {
5565 *exparg.lastp = str;
5566 rmescapes(str->text);
5567 exparg.lastp = &str->next;
5569 *exparg.lastp = NULL;
5570 *savelastp = sp = expsort(*savelastp);
5571 while (sp->next != NULL)
5573 exparg.lastp = &sp->next;
5580 * Add a file name to the list.
5584 addfname(const char *name)
5588 sp = (struct strlist *)stalloc(sizeof *sp);
5589 sp->text = sstrdup(name);
5591 exparg.lastp = &sp->next;
5596 * Do metacharacter (i.e. *, ?, [...]) expansion.
5600 expmeta(char *enddir, char *name)
5615 for (p = name; *p; p++) {
5616 if (*p == '*' || *p == '?')
5618 else if (*p == '[') {
5625 if (*q == '/' || *q == '\0')
5632 } else if (*p == '\\')
5634 else if (*p == '/') {
5641 if (metaflag == 0) { /* we've reached the end of the file name */
5642 if (enddir != expdir)
5650 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5661 } while (p < start);
5663 if (enddir == expdir) {
5665 } else if (enddir == expdir + 1 && *expdir == '/') {
5671 if ((dirp = opendir(cp)) == NULL)
5673 if (enddir != expdir)
5675 if (*endname == 0) {
5687 while (! intpending && (dp = readdir(dirp)) != NULL) {
5688 if (dp->d_name[0] == '.' && ! matchdot)
5690 if (pmatch(start, dp->d_name)) {
5692 scopy(dp->d_name, enddir);
5695 for (p = enddir, cp = dp->d_name;
5696 (*p++ = *cp++) != '\0';)
5699 expmeta(p, endname);
5709 * Sort the results of file name expansion. It calculates the number of
5710 * strings to sort and then calls msort (short for merge sort) to do the
5714 static struct strlist *
5715 expsort(struct strlist *str)
5721 for (sp = str ; sp ; sp = sp->next)
5723 return msort(str, len);
5727 static struct strlist *
5728 msort(struct strlist *list, int len)
5730 struct strlist *p, *q = NULL;
5731 struct strlist **lpp;
5739 for (n = half ; --n >= 0 ; ) {
5743 q->next = NULL; /* terminate first half of list */
5744 q = msort(list, half); /* sort first half of list */
5745 p = msort(p, len - half); /* sort second half */
5748 #ifdef CONFIG_LOCALE_SUPPORT
5749 if (strcoll(p->text, q->text) < 0)
5751 if (strcmp(p->text, q->text) < 0)
5756 if ((p = *lpp) == NULL) {
5763 if ((q = *lpp) == NULL) {
5774 * Returns true if the pattern matches the string.
5778 patmatch(char *pattern, const char *string)
5780 return pmatch(preglob(pattern, 0, 0), string);
5785 * Remove any CTLESC characters from a string.
5789 _rmescapes(char *str, int flag)
5792 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5797 p = strpbrk(str, qchars);
5803 if (flag & RMESCAPE_ALLOC) {
5804 size_t len = p - str;
5805 size_t fulllen = len + strlen(p) + 1;
5807 if (flag & RMESCAPE_GROW) {
5808 r = makestrspace(fulllen, expdest);
5809 } else if (flag & RMESCAPE_HEAP) {
5810 r = ckmalloc(fulllen);
5812 r = stalloc(fulllen);
5816 q = mempcpy(q, str, len);
5819 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5820 globbing = flag & RMESCAPE_GLOB;
5821 notescaped = globbing;
5823 if (*p == CTLQUOTEMARK) {
5824 inquotes = ~inquotes;
5826 notescaped = globbing;
5830 /* naked back slash */
5836 if (notescaped && inquotes && *p != '/') {
5840 notescaped = globbing;
5845 if (flag & RMESCAPE_GROW) {
5847 STADJUST(q - r + 1, expdest);
5854 * See if a pattern matches in a case statement.
5858 casematch(union node *pattern, char *val)
5860 struct stackmark smark;
5863 setstackmark(&smark);
5864 argbackq = pattern->narg.backquote;
5865 STARTSTACKSTR(expdest);
5867 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5868 STACKSTRNUL(expdest);
5869 result = patmatch(stackblock(), val);
5870 popstackmark(&smark);
5883 expdest = makestrspace(32, expdest);
5884 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5885 len = fmtstr(expdest, 32, "%lld", (long long) num);
5887 len = fmtstr(expdest, 32, "%ld", num);
5889 STADJUST(len, expdest);
5894 varunset(const char *end, const char *var, const char *umsg, int varflags)
5900 msg = "parameter not set";
5902 if (*end == CTLENDVAR) {
5903 if (varflags & VSNUL)
5908 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5915 * This implements the input routines used by the parser.
5918 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5920 static void pushfile(void);
5923 * Read a character from the script, returning PEOF on end of file.
5924 * Nul characters in the input are silently discarded.
5928 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5930 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5931 #define pgetc_macro() pgetc()
5935 return pgetc_as_macro();
5938 #define pgetc_macro() pgetc_as_macro()
5942 return pgetc_macro();
5948 * Same as pgetc(), but ignores PEOA.
5950 #ifdef CONFIG_ASH_ALIAS
5951 static int pgetc2(void)
5957 } while (c == PEOA);
5961 static inline int pgetc2(void)
5963 return pgetc_macro();
5968 * Read a line from the script.
5971 static inline char *
5972 pfgets(char *line, int len)
5978 while (--nleft > 0) {
5995 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5996 #ifdef CONFIG_ASH_EXPAND_PRMT
5997 static char *cmdedit_prompt;
5999 static const char *cmdedit_prompt;
6001 static inline void putprompt(const char *s)
6003 #ifdef CONFIG_ASH_EXPAND_PRMT
6004 free(cmdedit_prompt);
6005 cmdedit_prompt = bb_xstrdup(s);
6011 static inline void putprompt(const char *s)
6021 char *buf = parsefile->buf;
6025 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6026 if (!iflag || parsefile->fd)
6027 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6029 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6030 cmdedit_path_lookup = pathval();
6032 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6034 /* Ctrl+C presend */
6043 if(nr < 0 && errno == 0) {
6044 /* Ctrl+D presend */
6049 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6053 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6054 int flags = fcntl(0, F_GETFL, 0);
6055 if (flags >= 0 && flags & O_NONBLOCK) {
6056 flags &=~ O_NONBLOCK;
6057 if (fcntl(0, F_SETFL, flags) >= 0) {
6058 out2str("sh: turning off NDELAY mode\n");
6068 * Refill the input buffer and return the next input character:
6070 * 1) If a string was pushed back on the input, pop it;
6071 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6072 * from a string so we can't refill the buffer, return EOF.
6073 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6074 * 4) Process input up to the next newline, deleting nul characters.
6084 while (parsefile->strpush) {
6085 #ifdef CONFIG_ASH_ALIAS
6086 if (parsenleft == -1 && parsefile->strpush->ap &&
6087 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6092 if (--parsenleft >= 0)
6093 return SC2INT(*parsenextc++);
6095 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6102 if ((more = preadfd()) <= 0) {
6103 parselleft = parsenleft = EOF_NLEFT;
6110 /* delete nul characters */
6118 memmove(q, q + 1, more);
6122 parsenleft = q - parsenextc - 1;
6128 parsenleft = q - parsenextc - 1;
6140 out2str(parsenextc);
6145 return SC2INT(*parsenextc++);
6149 * Undo the last call to pgetc. Only one character may be pushed back.
6150 * PEOF may be pushed back.
6161 * Push a string back onto the input at this current parsefile level.
6162 * We handle aliases this way.
6165 pushstring(char *s, void *ap)
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;
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;
6184 ((struct alias *)ap)->flag |= ALIASINUSE;
6196 struct strpush *sp = parsefile->strpush;
6199 #ifdef CONFIG_ASH_ALIAS
6201 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6202 checkkwd |= CHKALIAS;
6204 if (sp->string != sp->ap->val) {
6207 sp->ap->flag &= ~ALIASINUSE;
6208 if (sp->ap->flag & ALIASDEAD) {
6209 unalias(sp->ap->name);
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))
6223 * Set the input to take input from a file. If push is set, push the
6224 * old input onto the stack first.
6228 setinputfile(const char *fname, int flags)
6234 if ((fd = open(fname, O_RDONLY)) < 0) {
6235 if (flags & INPUT_NOFILE_OK)
6237 sh_error("Can't open %s", fname);
6240 fd2 = copyfd(fd, 10);
6243 sh_error("Out of file descriptors");
6246 setinputfd(fd, flags & INPUT_PUSH_FILE);
6254 * Like setinputfile, but takes an open file descriptor. Call this with
6259 setinputfd(int fd, int push)
6261 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6267 if (parsefile->buf == NULL)
6268 parsefile->buf = ckmalloc(IBUFSIZ);
6269 parselleft = parsenleft = 0;
6275 * Like setinputfile, but takes input from a string.
6279 setinputstring(char *string)
6283 parsenextc = string;
6284 parsenleft = strlen(string);
6285 parsefile->buf = NULL;
6292 * To handle the "." command, a stack of input files is used. Pushfile
6293 * adds a new entry to the stack and popfile restores the previous level.
6299 struct parsefile *pf;
6301 parsefile->nleft = parsenleft;
6302 parsefile->lleft = parselleft;
6303 parsefile->nextc = parsenextc;
6304 parsefile->linno = plinno;
6305 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6306 pf->prev = parsefile;
6309 pf->basestrpush.prev = NULL;
6317 struct parsefile *pf = parsefile;
6326 parsefile = pf->prev;
6328 parsenleft = parsefile->nleft;
6329 parselleft = parsefile->lleft;
6330 parsenextc = parsefile->nextc;
6331 plinno = parsefile->linno;
6337 * Return to top level.
6343 while (parsefile != &basepf)
6349 * Close the file(s) that the shell is reading commands from. Called
6350 * after a fork is done.
6357 if (parsefile->fd > 0) {
6358 close(parsefile->fd);
6365 /* mode flags for set_curjob */
6366 #define CUR_DELETE 2
6367 #define CUR_RUNNING 1
6368 #define CUR_STOPPED 0
6370 /* mode flags for dowait */
6371 #define DOWAIT_NORMAL 0
6372 #define DOWAIT_BLOCK 1
6375 static struct job *jobtab;
6377 static unsigned njobs;
6379 /* pgrp of shell on invocation */
6380 static int initialpgrp;
6381 static int ttyfd = -1;
6384 static struct job *curjob;
6385 /* number of presumed living untracked jobs */
6388 static void set_curjob(struct job *, unsigned);
6390 static int restartjob(struct job *, int);
6391 static void xtcsetpgrp(int, pid_t);
6392 static char *commandtext(union node *);
6393 static void cmdlist(union node *, int);
6394 static void cmdtxt(union node *);
6395 static void cmdputs(const char *);
6396 static void showpipe(struct job *, FILE *);
6398 static int sprint_status(char *, int, int);
6399 static void freejob(struct job *);
6400 static struct job *getjob(const char *, int);
6401 static struct job *growjobtab(void);
6402 static void forkchild(struct job *, union node *, int);
6403 static void forkparent(struct job *, union node *, int, pid_t);
6404 static int dowait(int, struct job *);
6405 static int getstatus(struct job *);
6408 set_curjob(struct job *jp, unsigned mode)
6411 struct job **jpp, **curp;
6413 /* first remove from list */
6414 jpp = curp = &curjob;
6419 jpp = &jp1->prev_job;
6421 *jpp = jp1->prev_job;
6423 /* Then re-insert in correct position */
6431 /* job being deleted */
6434 /* newly created job or backgrounded job,
6435 put after all stopped jobs. */
6439 if (!jp1 || jp1->state != JOBSTOPPED)
6442 jpp = &jp1->prev_job;
6448 /* newly stopped job - becomes curjob */
6449 jp->prev_job = *jpp;
6457 * Turn job control on and off.
6459 * Note: This code assumes that the third arg to ioctl is a character
6460 * pointer, which is true on Berkeley systems but not System V. Since
6461 * System V doesn't have job control yet, this isn't a problem now.
6463 * Called with interrupts off.
6472 if (on == jobctl || rootshell == 0)
6476 ofd = fd = open(_PATH_TTY, O_RDWR);
6479 while (!isatty(fd) && --fd >= 0)
6482 fd = fcntl(fd, F_DUPFD, 10);
6486 fcntl(fd, F_SETFD, FD_CLOEXEC);
6487 do { /* while we are in the background */
6488 if ((pgrp = tcgetpgrp(fd)) < 0) {
6490 sh_warnx("can't access tty; job control turned off");
6494 if (pgrp == getpgrp())
6505 xtcsetpgrp(fd, pgrp);
6507 /* turning job control off */
6510 xtcsetpgrp(fd, pgrp);
6524 killcmd(int argc, char **argv)
6535 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6536 "kill -l [exitstatus]"
6540 if (**++argv == '-') {
6541 signo = decode_signal(*argv + 1, 1);
6545 while ((c = nextopt("ls:")) != '\0')
6555 signo = decode_signal(optionarg, 1);
6558 "invalid signal number or name: %s",
6569 if (!list && signo < 0)
6572 if ((signo < 0 || !*argv) ^ list) {
6580 for (i = 1; i < NSIG; i++) {
6581 name = u_signal_names(0, &i, 1);
6583 out1fmt(snlfmt, name);
6587 name = u_signal_names(*argptr, &signo, -1);
6589 out1fmt(snlfmt, name);
6591 sh_error("invalid signal number or exit status: %s", *argptr);
6597 if (**argv == '%') {
6598 jp = getjob(*argv, 0);
6599 pid = -jp->ps[0].pid;
6601 pid = **argv == '-' ?
6602 -number(*argv + 1) : number(*argv);
6604 if (kill(pid, signo) != 0) {
6605 sh_warnx("(%d) - %m", pid);
6614 #if defined(JOBS) || defined(DEBUG)
6616 jobno(const struct job *jp)
6618 return jp - jobtab + 1;
6624 fgcmd(int argc, char **argv)
6631 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6636 jp = getjob(*argv, 1);
6637 if (mode == FORK_BG) {
6638 set_curjob(jp, CUR_RUNNING);
6639 fprintf(out, "[%d] ", jobno(jp));
6641 outstr(jp->ps->cmd, out);
6643 retval = restartjob(jp, mode);
6644 } while (*argv && *++argv);
6648 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6652 restartjob(struct job *jp, int mode)
6654 struct procstat *ps;
6660 if (jp->state == JOBDONE)
6662 jp->state = JOBRUNNING;
6664 if (mode == FORK_FG)
6665 xtcsetpgrp(ttyfd, pgid);
6666 killpg(pgid, SIGCONT);
6670 if (WIFSTOPPED(ps->status)) {
6673 } while (ps++, --i);
6675 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6682 sprint_status(char *s, int status, int sigonly)
6688 if (!WIFEXITED(status)) {
6690 if (WIFSTOPPED(status))
6691 st = WSTOPSIG(status);
6694 st = WTERMSIG(status);
6696 if (st == SIGINT || st == SIGPIPE)
6699 if (WIFSTOPPED(status))
6704 col = fmtstr(s, 32, strsignal(st));
6705 if (WCOREDUMP(status)) {
6706 col += fmtstr(s + col, 16, " (core dumped)");
6708 } else if (!sigonly) {
6709 st = WEXITSTATUS(status);
6711 col = fmtstr(s, 16, "Done(%d)", st);
6713 col = fmtstr(s, 16, "Done");
6722 showjob(FILE *out, struct job *jp, int mode)
6724 struct procstat *ps;
6725 struct procstat *psend;
6732 if (mode & SHOW_PGID) {
6733 /* just output process (group) id of pipeline */
6734 fprintf(out, "%d\n", ps->pid);
6738 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6743 else if (curjob && jp == curjob->prev_job)
6746 if (mode & SHOW_PID)
6747 col += fmtstr(s + col, 16, "%d ", ps->pid);
6749 psend = ps + jp->nprocs;
6751 if (jp->state == JOBRUNNING) {
6752 scopy("Running", s + col);
6753 col += strlen("Running");
6755 int status = psend[-1].status;
6757 if (jp->state == JOBSTOPPED)
6758 status = jp->stopstatus;
6760 col += sprint_status(s + col, status, 0);
6766 /* for each process */
6767 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6770 fprintf(out, "%s%*c%s",
6771 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6773 if (!(mode & SHOW_PID)) {
6777 if (++ps == psend) {
6778 outcslow('\n', out);
6785 if (jp->state == JOBDONE) {
6786 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6793 jobscmd(int argc, char **argv)
6799 while ((m = nextopt("lp")))
6809 showjob(out, getjob(*argv,0), mode);
6812 showjobs(out, mode);
6819 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6820 * statuses have changed since the last call to showjobs.
6824 showjobs(FILE *out, int mode)
6828 TRACE(("showjobs(%x) called\n", mode));
6830 /* If not even one one job changed, there is nothing to do */
6831 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6834 for (jp = curjob; jp; jp = jp->prev_job) {
6835 if (!(mode & SHOW_CHANGED) || jp->changed)
6836 showjob(out, jp, mode);
6842 * Mark a job structure as unused.
6846 freejob(struct job *jp)
6848 struct procstat *ps;
6852 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6853 if (ps->cmd != nullstr)
6856 if (jp->ps != &jp->ps0)
6859 set_curjob(jp, CUR_DELETE);
6865 waitcmd(int argc, char **argv)
6878 /* wait for all jobs */
6883 /* no running procs */
6886 if (jp->state == JOBRUNNING)
6891 dowait(DOWAIT_BLOCK, 0);
6897 if (**argv != '%') {
6898 pid_t pid = number(*argv);
6902 if (job->ps[job->nprocs - 1].pid == pid)
6904 job = job->prev_job;
6910 job = getjob(*argv, 0);
6911 /* loop until process terminated or stopped */
6912 while (job->state == JOBRUNNING)
6913 dowait(DOWAIT_BLOCK, 0);
6915 retval = getstatus(job);
6926 * Convert a job name to a job structure.
6930 getjob(const char *name, int getctl)
6934 const char *err_msg = "No such job: %s";
6938 char *(*match)(const char *, const char *);
6953 if (c == '+' || c == '%') {
6955 err_msg = "No current job";
6957 } else if (c == '-') {
6960 err_msg = "No previous job";
6971 jp = jobtab + num - 1;
6988 if (match(jp->ps[0].cmd, p)) {
6992 err_msg = "%s: ambiguous";
6999 err_msg = "job %s not created under job control";
7000 if (getctl && jp->jobctl == 0)
7005 sh_error(err_msg, name);
7010 * Return a new job structure.
7011 * Called with interrupts off.
7015 makejob(union node *node, int nprocs)
7020 for (i = njobs, jp = jobtab ; ; jp++) {
7027 if (jp->state != JOBDONE || !jp->waited)
7036 memset(jp, 0, sizeof(*jp));
7041 jp->prev_job = curjob;
7046 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7048 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7058 struct job *jp, *jq;
7060 len = njobs * sizeof(*jp);
7062 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7064 offset = (char *)jp - (char *)jq;
7066 /* Relocate pointers */
7069 jq = (struct job *)((char *)jq + l);
7073 #define joff(p) ((struct job *)((char *)(p) + l))
7074 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7075 if (xlikely(joff(jp)->ps == &jq->ps0))
7076 jmove(joff(jp)->ps);
7077 if (joff(jp)->prev_job)
7078 jmove(joff(jp)->prev_job);
7088 jp = (struct job *)((char *)jp + len);
7092 } while (--jq >= jp);
7098 * Fork off a subshell. If we are doing job control, give the subshell its
7099 * own process group. Jp is a job structure that the job is to be added to.
7100 * N is the command that will be evaluated by the child. Both jp and n may
7101 * be NULL. The mode parameter can be one of the following:
7102 * FORK_FG - Fork off a foreground process.
7103 * FORK_BG - Fork off a background process.
7104 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7105 * process group even if job control is on.
7107 * When job control is turned off, background processes have their standard
7108 * input redirected to /dev/null (except for the second and later processes
7111 * Called with interrupts off.
7115 forkchild(struct job *jp, union node *n, int mode)
7119 TRACE(("Child shell %d\n", getpid()));
7126 /* do job control only in root shell */
7128 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7131 if (jp->nprocs == 0)
7134 pgrp = jp->ps[0].pid;
7135 /* This can fail because we are doing it in the parent also */
7136 (void)setpgid(0, pgrp);
7137 if (mode == FORK_FG)
7138 xtcsetpgrp(ttyfd, pgrp);
7143 if (mode == FORK_BG) {
7146 if (jp->nprocs == 0) {
7148 if (open(bb_dev_null, O_RDONLY) != 0)
7149 sh_error("Can't open %s", bb_dev_null);
7152 if (!oldlvl && iflag) {
7157 for (jp = curjob; jp; jp = jp->prev_job)
7163 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7165 TRACE(("In parent shell: child = %d\n", pid));
7167 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7172 if (mode != FORK_NOJOB && jp->jobctl) {
7175 if (jp->nprocs == 0)
7178 pgrp = jp->ps[0].pid;
7179 /* This can fail because we are doing it in the child also */
7180 (void)setpgid(pid, pgrp);
7183 if (mode == FORK_BG) {
7184 backgndpid = pid; /* set $! */
7185 set_curjob(jp, CUR_RUNNING);
7188 struct procstat *ps = &jp->ps[jp->nprocs++];
7194 ps->cmd = commandtext(n);
7200 forkshell(struct job *jp, union node *n, int mode)
7204 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7207 TRACE(("Fork failed, errno=%d", errno));
7210 sh_error("Cannot fork");
7213 forkchild(jp, n, mode);
7215 forkparent(jp, n, mode, pid);
7220 * Wait for job to finish.
7222 * Under job control we have the problem that while a child process is
7223 * running interrupts generated by the user are sent to the child but not
7224 * to the shell. This means that an infinite loop started by an inter-
7225 * active user may be hard to kill. With job control turned off, an
7226 * interactive user may place an interactive program inside a loop. If
7227 * the interactive program catches interrupts, the user doesn't want
7228 * these interrupts to also abort the loop. The approach we take here
7229 * is to have the shell ignore interrupt signals while waiting for a
7230 * foreground process to terminate, and then send itself an interrupt
7231 * signal if the child process was terminated by an interrupt signal.
7232 * Unfortunately, some programs want to do a bit of cleanup and then
7233 * exit on interrupt; unless these processes terminate themselves by
7234 * sending a signal to themselves (instead of calling exit) they will
7235 * confuse this approach.
7237 * Called with interrupts off.
7241 waitforjob(struct job *jp)
7245 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7246 while (jp->state == JOBRUNNING) {
7247 dowait(DOWAIT_BLOCK, jp);
7252 xtcsetpgrp(ttyfd, rootpid);
7254 * This is truly gross.
7255 * If we're doing job control, then we did a TIOCSPGRP which
7256 * caused us (the shell) to no longer be in the controlling
7257 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7258 * intuit from the subprocess exit status whether a SIGINT
7259 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7264 if (jp->state == JOBDONE)
7272 * Do a wait system call. If job control is compiled in, we accept
7273 * stopped processes. If block is zero, we return a value of zero
7274 * rather than blocking.
7276 * System V doesn't have a non-blocking wait system call. It does
7277 * have a SIGCLD signal that is sent to a process when one of it's
7278 * children dies. The obvious way to use SIGCLD would be to install
7279 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7280 * was received, and have waitproc bump another counter when it got
7281 * the status of a process. Waitproc would then know that a wait
7282 * system call would not block if the two counters were different.
7283 * This approach doesn't work because if a process has children that
7284 * have not been waited for, System V will send it a SIGCLD when it
7285 * installs a signal handler for SIGCLD. What this means is that when
7286 * a child exits, the shell will be sent SIGCLD signals continuously
7287 * until is runs out of stack space, unless it does a wait call before
7288 * restoring the signal handler. The code below takes advantage of
7289 * this (mis)feature by installing a signal handler for SIGCLD and
7290 * then checking to see whether it was called. If there are any
7291 * children to be waited for, it will be.
7293 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7294 * waits at all. In this case, the user will not be informed when
7295 * a background process until the next time she runs a real program
7296 * (as opposed to running a builtin command or just typing return),
7297 * and the jobs command may give out of date information.
7301 waitproc(int block, int *status)
7311 return wait3(status, flags, (struct rusage *)NULL);
7315 * Wait for a process to terminate.
7319 dowait(int block, struct job *job)
7324 struct job *thisjob;
7327 TRACE(("dowait(%d) called\n", block));
7328 pid = waitproc(block, &status);
7329 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7334 for (jp = curjob; jp; jp = jp->prev_job) {
7335 struct procstat *sp;
7336 struct procstat *spend;
7337 if (jp->state == JOBDONE)
7340 spend = jp->ps + jp->nprocs;
7343 if (sp->pid == pid) {
7344 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7345 sp->status = status;
7348 if (sp->status == -1)
7351 if (state == JOBRUNNING)
7353 if (WIFSTOPPED(sp->status)) {
7354 jp->stopstatus = sp->status;
7358 } while (++sp < spend);
7363 if (!WIFSTOPPED(status))
7370 if (state != JOBRUNNING) {
7371 thisjob->changed = 1;
7373 if (thisjob->state != state) {
7374 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7375 thisjob->state = state;
7377 if (state == JOBSTOPPED) {
7378 set_curjob(thisjob, CUR_STOPPED);
7387 if (thisjob && thisjob == job) {
7391 len = sprint_status(s, status, 1);
7403 * return 1 if there are stopped jobs, otherwise 0
7416 if (jp && jp->state == JOBSTOPPED) {
7417 out2str("You have stopped jobs.\n");
7427 * Return a string identifying a command (to be printed by the
7432 static char *cmdnextc;
7435 commandtext(union node *n)
7439 STARTSTACKSTR(cmdnextc);
7441 name = stackblock();
7442 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7443 name, cmdnextc, cmdnextc));
7444 return savestr(name);
7448 cmdtxt(union node *n)
7451 struct nodelist *lp;
7463 lp = n->npipe.cmdlist;
7481 cmdtxt(n->nbinary.ch1);
7497 cmdtxt(n->nif.test);
7500 if (n->nif.elsepart) {
7503 n = n->nif.elsepart;
7519 cmdtxt(n->nbinary.ch1);
7529 cmdputs(n->nfor.var);
7531 cmdlist(n->nfor.args, 1);
7536 cmdputs(n->narg.text);
7540 cmdlist(n->ncmd.args, 1);
7541 cmdlist(n->ncmd.redirect, 0);
7554 cmdputs(n->ncase.expr->narg.text);
7556 for (np = n->ncase.cases; np; np = np->nclist.next) {
7557 cmdtxt(np->nclist.pattern);
7559 cmdtxt(np->nclist.body);
7585 s[0] = n->nfile.fd + '0';
7589 if (n->type == NTOFD || n->type == NFROMFD) {
7590 s[0] = n->ndup.dupfd + '0';
7601 cmdlist(union node *np, int sep)
7603 for (; np; np = np->narg.next) {
7607 if (sep && np->narg.next)
7613 cmdputs(const char *s)
7615 const char *p, *str;
7616 char c, cc[2] = " ";
7620 static const char vstype[VSTYPE + 1][4] = {
7621 "", "}", "-", "+", "?", "=",
7622 "%", "%%", "#", "##"
7624 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7626 while ((c = *p++) != 0) {
7634 if ((subtype & VSTYPE) == VSLENGTH)
7638 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7645 str = "\"}" + !(quoted & 1);
7652 case CTLBACKQ+CTLQUOTE:
7655 #ifdef CONFIG_ASH_MATH_SUPPORT
7670 if ((subtype & VSTYPE) != VSNORMAL)
7672 str = vstype[subtype & VSTYPE];
7673 if (subtype & VSNUL)
7682 /* These can only happen inside quotes */
7695 while ((c = *str++)) {
7700 USTPUTC('"', nextc);
7708 showpipe(struct job *jp, FILE *out)
7710 struct procstat *sp;
7711 struct procstat *spend;
7713 spend = jp->ps + jp->nprocs;
7714 for (sp = jp->ps + 1; sp < spend; sp++)
7715 fprintf(out, " | %s", sp->cmd);
7716 outcslow('\n', out);
7721 xtcsetpgrp(int fd, pid_t pgrp)
7723 if (tcsetpgrp(fd, pgrp))
7724 sh_error("Cannot set tty process group (%m)");
7729 getstatus(struct job *job) {
7733 status = job->ps[job->nprocs - 1].status;
7734 retval = WEXITSTATUS(status);
7735 if (!WIFEXITED(status)) {
7737 retval = WSTOPSIG(status);
7738 if (!WIFSTOPPED(status))
7741 /* XXX: limits number of signals */
7742 retval = WTERMSIG(status);
7744 if (retval == SIGINT)
7750 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7751 jobno(job), job->nprocs, status, retval));
7755 #ifdef CONFIG_ASH_MAIL
7759 * Routines to check for mail. (Perhaps make part of main.c?)
7762 #define MAXMBOXES 10
7764 /* times of mailboxes */
7765 static time_t mailtime[MAXMBOXES];
7766 /* Set if MAIL or MAILPATH is changed. */
7767 static int mail_var_path_changed;
7772 * Print appropriate message(s) if mail has arrived.
7773 * If mail_var_path_changed is set,
7774 * then the value of MAIL has mail_var_path_changed,
7775 * so we just update the values.
7785 struct stackmark smark;
7788 setstackmark(&smark);
7789 mpath = mpathset() ? mpathval() : mailval();
7790 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7791 p = padvance(&mpath, nullstr);
7796 for (q = p ; *q ; q++);
7801 q[-1] = '\0'; /* delete trailing '/' */
7802 if (stat(p, &statb) < 0) {
7806 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7809 pathopt ? pathopt : "you have mail"
7812 *mtp = statb.st_mtime;
7814 mail_var_path_changed = 0;
7815 popstackmark(&smark);
7820 changemail(const char *val)
7822 mail_var_path_changed++;
7825 #endif /* CONFIG_ASH_MAIL */
7831 static short profile_buf[16384];
7835 static int isloginsh;
7837 static void read_profile(const char *);
7840 * Main routine. We initialize things, parse the arguments, execute
7841 * profiles if we're a login shell, and then call cmdloop to execute
7842 * commands. The setjmp call sets up the location to jump to when an
7843 * exception occurs. When an exception occurs the variable "state"
7844 * is used to figure out how far we had gotten.
7848 ash_main(int argc, char **argv)
7852 struct jmploc jmploc;
7853 struct stackmark smark;
7856 dash_errno = __errno_location();
7860 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7863 if (setjmp(jmploc.loc)) {
7873 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7877 outcslow('\n', stderr);
7879 popstackmark(&smark);
7880 FORCEINTON; /* enable interrupts */
7893 trputs("Shell args: "); trargs(argv);
7897 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7898 rseed = rootpid + ((time_t)time((time_t *)0));
7901 setstackmark(&smark);
7902 procargs(argc, argv);
7903 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7905 const char *hp = lookupvar("HISTFILE");
7908 hp = lookupvar("HOME");
7910 char *defhp = concat_path_file(hp, ".ash_history");
7911 setvar("HISTFILE", defhp, 0);
7917 if (argv[0] && argv[0][0] == '-')
7921 read_profile("/etc/profile");
7924 read_profile(".profile");
7930 getuid() == geteuid() && getgid() == getegid() &&
7934 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7935 read_profile(shinit);
7941 evalstring(minusc, 0);
7943 if (sflag || minusc == NULL) {
7944 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7946 const char *hp = lookupvar("HISTFILE");
7949 load_history ( hp );
7952 state4: /* XXX ??? - why isn't this before the "if" statement */
7960 extern void _mcleanup(void);
7970 * Read and execute commands. "Top" is nonzero for the top level command
7971 * loop; it turns on prompting if the shell is interactive.
7978 struct stackmark smark;
7982 TRACE(("cmdloop(%d) called\n", top));
7986 setstackmark(&smark);
7989 showjobs(stderr, SHOW_CHANGED);
7994 #ifdef CONFIG_ASH_MAIL
7998 n = parsecmd(inter);
7999 /* showtree(n); DEBUG */
8001 if (!top || numeof >= 50)
8003 if (!stoppedjobs()) {
8006 out2str("\nUse \"exit\" to leave shell.\n");
8009 } else if (nflag == 0) {
8010 job_warning = (job_warning == 2) ? 1 : 0;
8014 popstackmark(&smark);
8019 return skip & SKIPEVAL;
8028 * Read /etc/profile or .profile. Return on error.
8032 read_profile(const char *name)
8036 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8048 * Read a file containing shell functions.
8052 readcmdfile(char *name)
8054 setinputfile(name, INPUT_PUSH_FILE);
8061 * Take commands from a file. To be compatible we should do a path
8062 * search for the file, which is necessary to find sub-commands.
8065 static inline char *
8066 find_dot_file(char *name)
8069 const char *path = pathval();
8072 /* don't try this for absolute or relative paths */
8073 if (strchr(name, '/'))
8076 while ((fullname = padvance(&path, name)) != NULL) {
8077 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8079 * Don't bother freeing here, since it will
8080 * be freed by the caller.
8084 stunalloc(fullname);
8087 /* not found in the PATH */
8088 sh_error(not_found_msg, name);
8092 static int dotcmd(int argc, char **argv)
8095 volatile struct shparam saveparam;
8098 for (sp = cmdenviron; sp; sp = sp->next)
8099 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8101 if (argc >= 2) { /* That's what SVR2 does */
8104 fullname = find_dot_file(argv[1]);
8107 saveparam = shellparam;
8108 shellparam.malloc = 0;
8109 shellparam.nparam = argc - 2;
8110 shellparam.p = argv + 2;
8113 setinputfile(fullname, INPUT_PUSH_FILE);
8114 commandname = fullname;
8119 freeparam(&shellparam);
8120 shellparam = saveparam;
8122 status = exitstatus;
8129 exitcmd(int argc, char **argv)
8134 exitstatus = number(argv[1]);
8139 #ifdef CONFIG_ASH_BUILTIN_ECHO
8141 echocmd(int argc, char **argv)
8143 return bb_echo(argc, argv);
8149 * Same for malloc, realloc, but returns an error when out of space.
8153 ckrealloc(pointer p, size_t nbytes)
8155 p = realloc(p, nbytes);
8157 sh_error(bb_msg_memory_exhausted);
8162 ckmalloc(size_t nbytes)
8164 return ckrealloc(NULL, nbytes);
8168 * Make a copy of a string in safe storage.
8172 savestr(const char *s)
8174 char *p = strdup(s);
8176 sh_error(bb_msg_memory_exhausted);
8182 * Parse trees for commands are allocated in lifo order, so we use a stack
8183 * to make this more efficient, and also to avoid all sorts of exception
8184 * handling code to handle interrupts in the middle of a parse.
8186 * The size 504 was chosen because the Ultrix malloc handles that size
8192 stalloc(size_t nbytes)
8197 aligned = SHELL_ALIGN(nbytes);
8198 if (aligned > stacknleft) {
8201 struct stack_block *sp;
8203 blocksize = aligned;
8204 if (blocksize < MINSIZE)
8205 blocksize = MINSIZE;
8206 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8207 if (len < blocksize)
8208 sh_error(bb_msg_memory_exhausted);
8212 stacknxt = sp->space;
8213 stacknleft = blocksize;
8214 sstrend = stacknxt + blocksize;
8219 stacknxt += aligned;
8220 stacknleft -= aligned;
8226 stunalloc(pointer p)
8229 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8230 write(2, "stunalloc\n", 10);
8234 stacknleft += stacknxt - (char *)p;
8240 setstackmark(struct stackmark *mark)
8242 mark->stackp = stackp;
8243 mark->stacknxt = stacknxt;
8244 mark->stacknleft = stacknleft;
8245 mark->marknext = markp;
8251 popstackmark(struct stackmark *mark)
8253 struct stack_block *sp;
8256 markp = mark->marknext;
8257 while (stackp != mark->stackp) {
8262 stacknxt = mark->stacknxt;
8263 stacknleft = mark->stacknleft;
8264 sstrend = mark->stacknxt + mark->stacknleft;
8270 * When the parser reads in a string, it wants to stick the string on the
8271 * stack and only adjust the stack pointer when it knows how big the
8272 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8273 * of space on top of the stack and stackblocklen returns the length of
8274 * this block. Growstackblock will grow this space by at least one byte,
8275 * possibly moving it (like realloc). Grabstackblock actually allocates the
8276 * part of the block that has been used.
8280 growstackblock(void)
8284 newlen = stacknleft * 2;
8285 if (newlen < stacknleft)
8286 sh_error(bb_msg_memory_exhausted);
8290 if (stacknxt == stackp->space && stackp != &stackbase) {
8291 struct stack_block *oldstackp;
8292 struct stackmark *xmark;
8293 struct stack_block *sp;
8294 struct stack_block *prevstackp;
8300 prevstackp = sp->prev;
8301 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8302 sp = ckrealloc((pointer)sp, grosslen);
8303 sp->prev = prevstackp;
8305 stacknxt = sp->space;
8306 stacknleft = newlen;
8307 sstrend = sp->space + newlen;
8310 * Stack marks pointing to the start of the old block
8311 * must be relocated to point to the new block
8314 while (xmark != NULL && xmark->stackp == oldstackp) {
8315 xmark->stackp = stackp;
8316 xmark->stacknxt = stacknxt;
8317 xmark->stacknleft = stacknleft;
8318 xmark = xmark->marknext;
8322 char *oldspace = stacknxt;
8323 int oldlen = stacknleft;
8324 char *p = stalloc(newlen);
8326 /* free the space we just allocated */
8327 stacknxt = memcpy(p, oldspace, oldlen);
8328 stacknleft += newlen;
8333 grabstackblock(size_t len)
8335 len = SHELL_ALIGN(len);
8341 * The following routines are somewhat easier to use than the above.
8342 * The user declares a variable of type STACKSTR, which may be declared
8343 * to be a register. The macro STARTSTACKSTR initializes things. Then
8344 * the user uses the macro STPUTC to add characters to the string. In
8345 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8346 * grown as necessary. When the user is done, she can just leave the
8347 * string there and refer to it using stackblock(). Or she can allocate
8348 * the space for it using grabstackstr(). If it is necessary to allow
8349 * someone else to use the stack temporarily and then continue to grow
8350 * the string, the user should use grabstack to allocate the space, and
8351 * then call ungrabstr(p) to return to the previous mode of operation.
8353 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8354 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8355 * is space for at least one character.
8361 size_t len = stackblocksize();
8362 if (herefd >= 0 && len >= 1024) {
8363 bb_full_write(herefd, stackblock(), len);
8364 return stackblock();
8367 return stackblock() + len;
8371 * Called from CHECKSTRSPACE.
8375 makestrspace(size_t newlen, char *p)
8377 size_t len = p - stacknxt;
8378 size_t size = stackblocksize();
8383 size = stackblocksize();
8385 if (nleft >= newlen)
8389 return stackblock() + len;
8393 stnputs(const char *s, size_t n, char *p)
8395 p = makestrspace(n, p);
8396 p = mempcpy(p, s, n);
8401 stputs(const char *s, char *p)
8403 return stnputs(s, strlen(s), p);
8411 * number(s) Convert a string of digits to an integer.
8412 * is_number(s) Return true if s is a string of digits.
8416 * prefix -- see if pfx is a prefix of string.
8420 prefix(const char *string, const char *pfx)
8423 if (*pfx++ != *string++)
8426 return (char *) string;
8431 * Convert a string of digits to an integer, printing an error message on
8436 number(const char *s)
8440 sh_error(illnum, s);
8446 * Check for a valid number. This should be elsewhere.
8450 is_number(const char *p)
8455 } while (*++p != '\0');
8461 * Produce a possibly single quoted string suitable as input to the shell.
8462 * The return string is allocated on the stack.
8466 single_quote(const char *s) {
8475 len = strchrnul(s, '\'') - s;
8477 q = p = makestrspace(len + 3, p);
8480 q = mempcpy(q, s, len);
8486 len = strspn(s, "'");
8490 q = p = makestrspace(len + 3, p);
8493 q = mempcpy(q, s, len);
8502 return stackblock();
8506 * Like strdup but works with the ash stack.
8510 sstrdup(const char *p)
8512 size_t len = strlen(p) + 1;
8513 return memcpy(stalloc(len), p, len);
8518 calcsize(union node *n)
8522 funcblocksize += nodesize[n->type];
8525 calcsize(n->ncmd.redirect);
8526 calcsize(n->ncmd.args);
8527 calcsize(n->ncmd.assign);
8530 sizenodelist(n->npipe.cmdlist);
8535 calcsize(n->nredir.redirect);
8536 calcsize(n->nredir.n);
8543 calcsize(n->nbinary.ch2);
8544 calcsize(n->nbinary.ch1);
8547 calcsize(n->nif.elsepart);
8548 calcsize(n->nif.ifpart);
8549 calcsize(n->nif.test);
8552 funcstringsize += strlen(n->nfor.var) + 1;
8553 calcsize(n->nfor.body);
8554 calcsize(n->nfor.args);
8557 calcsize(n->ncase.cases);
8558 calcsize(n->ncase.expr);
8561 calcsize(n->nclist.body);
8562 calcsize(n->nclist.pattern);
8563 calcsize(n->nclist.next);
8567 sizenodelist(n->narg.backquote);
8568 funcstringsize += strlen(n->narg.text) + 1;
8569 calcsize(n->narg.next);
8576 calcsize(n->nfile.fname);
8577 calcsize(n->nfile.next);
8581 calcsize(n->ndup.vname);
8582 calcsize(n->ndup.next);
8586 calcsize(n->nhere.doc);
8587 calcsize(n->nhere.next);
8590 calcsize(n->nnot.com);
8597 sizenodelist(struct nodelist *lp)
8600 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8608 copynode(union node *n)
8615 funcblock = (char *) funcblock + nodesize[n->type];
8618 new->ncmd.redirect = copynode(n->ncmd.redirect);
8619 new->ncmd.args = copynode(n->ncmd.args);
8620 new->ncmd.assign = copynode(n->ncmd.assign);
8623 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8624 new->npipe.backgnd = n->npipe.backgnd;
8629 new->nredir.redirect = copynode(n->nredir.redirect);
8630 new->nredir.n = copynode(n->nredir.n);
8637 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8638 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8641 new->nif.elsepart = copynode(n->nif.elsepart);
8642 new->nif.ifpart = copynode(n->nif.ifpart);
8643 new->nif.test = copynode(n->nif.test);
8646 new->nfor.var = nodesavestr(n->nfor.var);
8647 new->nfor.body = copynode(n->nfor.body);
8648 new->nfor.args = copynode(n->nfor.args);
8651 new->ncase.cases = copynode(n->ncase.cases);
8652 new->ncase.expr = copynode(n->ncase.expr);
8655 new->nclist.body = copynode(n->nclist.body);
8656 new->nclist.pattern = copynode(n->nclist.pattern);
8657 new->nclist.next = copynode(n->nclist.next);
8661 new->narg.backquote = copynodelist(n->narg.backquote);
8662 new->narg.text = nodesavestr(n->narg.text);
8663 new->narg.next = copynode(n->narg.next);
8670 new->nfile.fname = copynode(n->nfile.fname);
8671 new->nfile.fd = n->nfile.fd;
8672 new->nfile.next = copynode(n->nfile.next);
8676 new->ndup.vname = copynode(n->ndup.vname);
8677 new->ndup.dupfd = n->ndup.dupfd;
8678 new->ndup.fd = n->ndup.fd;
8679 new->ndup.next = copynode(n->ndup.next);
8683 new->nhere.doc = copynode(n->nhere.doc);
8684 new->nhere.fd = n->nhere.fd;
8685 new->nhere.next = copynode(n->nhere.next);
8688 new->nnot.com = copynode(n->nnot.com);
8691 new->type = n->type;
8696 static struct nodelist *
8697 copynodelist(struct nodelist *lp)
8699 struct nodelist *start;
8700 struct nodelist **lpp;
8705 funcblock = (char *) funcblock +
8706 SHELL_ALIGN(sizeof(struct nodelist));
8707 (*lpp)->n = copynode(lp->n);
8709 lpp = &(*lpp)->next;
8717 nodesavestr(char *s)
8719 char *rtn = funcstring;
8721 funcstring = stpcpy(funcstring, s) + 1;
8727 * Free a parse tree.
8731 freefunc(struct funcnode *f)
8733 if (f && --f->count < 0)
8738 static void options(int);
8739 static void setoption(int, int);
8743 * Process the shell command line arguments.
8747 procargs(int argc, char **argv)
8750 const char *xminusc;
8757 for (i = 0; i < NOPTS; i++)
8763 if (*xargv == NULL) {
8765 sh_error("-c requires an argument");
8768 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8772 for (i = 0; i < NOPTS; i++)
8773 if (optlist[i] == 2)
8778 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8783 } else if (!sflag) {
8784 setinputfile(*xargv, 0);
8790 shellparam.p = xargv;
8791 #ifdef CONFIG_ASH_GETOPTS
8792 shellparam.optind = 1;
8793 shellparam.optoff = -1;
8795 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8797 shellparam.nparam++;
8810 setinteractive(iflag);
8816 minus_o(char *name, int val)
8821 out1str("Current option settings\n");
8822 for (i = 0; i < NOPTS; i++)
8823 out1fmt("%-16s%s\n", optnames(i),
8824 optlist[i] ? "on" : "off");
8826 for (i = 0; i < NOPTS; i++)
8827 if (equal(name, optnames(i))) {
8831 sh_error("Illegal option -o %s", name);
8836 * Process shell options. The global variable argptr contains a pointer
8837 * to the argument list; we advance it past the options.
8841 options(int cmdline)
8849 while ((p = *argptr) != NULL) {
8851 if ((c = *p++) == '-') {
8853 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8855 /* "-" means turn off -x and -v */
8858 /* "--" means reset params */
8859 else if (*argptr == NULL)
8862 break; /* "-" or "--" terminates options */
8864 } else if (c == '+') {
8870 while ((c = *p++) != '\0') {
8871 if (c == 'c' && cmdline) {
8872 minusc = p; /* command is after shell args*/
8873 } else if (c == 'o') {
8874 minus_o(*argptr, val);
8877 } else if (cmdline && (c == '-')) { // long options
8878 if (strcmp(p, "login") == 0)
8890 setoption(int flag, int val)
8894 for (i = 0; i < NOPTS; i++)
8895 if (optletters(i) == flag) {
8899 sh_error("Illegal option -%c", flag);
8906 * Set the shell parameters.
8910 setparam(char **argv)
8916 for (nparam = 0 ; argv[nparam] ; nparam++);
8917 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8919 *ap++ = savestr(*argv++);
8922 freeparam(&shellparam);
8923 shellparam.malloc = 1;
8924 shellparam.nparam = nparam;
8925 shellparam.p = newparam;
8926 #ifdef CONFIG_ASH_GETOPTS
8927 shellparam.optind = 1;
8928 shellparam.optoff = -1;
8934 * Free the list of positional parameters.
8938 freeparam(volatile struct shparam *param)
8942 if (param->malloc) {
8943 for (ap = param->p ; *ap ; ap++)
8952 * The shift builtin command.
8956 shiftcmd(int argc, char **argv)
8963 n = number(argv[1]);
8964 if (n > shellparam.nparam)
8965 sh_error("can't shift that many");
8967 shellparam.nparam -= n;
8968 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8969 if (shellparam.malloc)
8973 while ((*ap2++ = *ap1++) != NULL);
8974 #ifdef CONFIG_ASH_GETOPTS
8975 shellparam.optind = 1;
8976 shellparam.optoff = -1;
8985 * The set command builtin.
8989 setcmd(int argc, char **argv)
8992 return showvars(nullstr, 0, VUNSET);
8996 if (*argptr != NULL) {
9004 #ifdef CONFIG_ASH_GETOPTS
9009 shellparam.optind = number(value);
9010 shellparam.optoff = -1;
9014 #ifdef CONFIG_LOCALE_SUPPORT
9015 static void change_lc_all(const char *value)
9017 if (value != 0 && *value != 0)
9018 setlocale(LC_ALL, value);
9021 static void change_lc_ctype(const char *value)
9023 if (value != 0 && *value != 0)
9024 setlocale(LC_CTYPE, value);
9029 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9030 /* Roughly copied from bash.. */
9031 static void change_random(const char *value)
9034 /* "get", generate */
9037 rseed = rseed * 1103515245 + 12345;
9038 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9039 /* set without recursion */
9040 setvar(vrandom.text, buf, VNOFUNC);
9041 vrandom.flags &= ~VNOFUNC;
9044 rseed = strtoul(value, (char **)NULL, 10);
9050 #ifdef CONFIG_ASH_GETOPTS
9052 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9061 if(*param_optind < 1)
9063 optnext = optfirst + *param_optind - 1;
9065 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9068 p = optnext[-1] + *optoff;
9069 if (p == NULL || *p == '\0') {
9070 /* Current word is done, advance */
9072 if (p == NULL || *p != '-' || *++p == '\0') {
9079 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9084 for (q = optstr; *q != c; ) {
9086 if (optstr[0] == ':') {
9089 err |= setvarsafe("OPTARG", s, 0);
9091 fprintf(stderr, "Illegal option -%c\n", c);
9092 (void) unsetvar("OPTARG");
9102 if (*p == '\0' && (p = *optnext) == NULL) {
9103 if (optstr[0] == ':') {
9106 err |= setvarsafe("OPTARG", s, 0);
9109 fprintf(stderr, "No arg for -%c option\n", c);
9110 (void) unsetvar("OPTARG");
9118 err |= setvarsafe("OPTARG", p, 0);
9121 err |= setvarsafe("OPTARG", nullstr, 0);
9124 *optoff = p ? p - *(optnext - 1) : -1;
9125 *param_optind = optnext - optfirst + 1;
9126 fmtstr(s, sizeof(s), "%d", *param_optind);
9127 err |= setvarsafe("OPTIND", s, VNOFUNC);
9130 err |= setvarsafe(optvar, s, 0);
9141 * The getopts builtin. Shellparam.optnext points to the next argument
9142 * to be processed. Shellparam.optptr points to the next character to
9143 * be processed in the current argument. If shellparam.optnext is NULL,
9144 * then it's the first time getopts has been called.
9148 getoptscmd(int argc, char **argv)
9153 sh_error("Usage: getopts optstring var [arg]");
9154 else if (argc == 3) {
9155 optbase = shellparam.p;
9156 if (shellparam.optind > shellparam.nparam + 1) {
9157 shellparam.optind = 1;
9158 shellparam.optoff = -1;
9163 if (shellparam.optind > argc - 2) {
9164 shellparam.optind = 1;
9165 shellparam.optoff = -1;
9169 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9170 &shellparam.optoff);
9172 #endif /* CONFIG_ASH_GETOPTS */
9175 * XXX - should get rid of. have all builtins use getopt(3). the
9176 * library getopt must have the BSD extension static variable "optreset"
9177 * otherwise it can't be used within the shell safely.
9179 * Standard option processing (a la getopt) for builtin routines. The
9180 * only argument that is passed to nextopt is the option string; the
9181 * other arguments are unnecessary. It return the character, or '\0' on
9186 nextopt(const char *optstring)
9192 if ((p = optptr) == NULL || *p == '\0') {
9194 if (p == NULL || *p != '-' || *++p == '\0')
9197 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9201 for (q = optstring ; *q != c ; ) {
9203 sh_error("Illegal option -%c", c);
9208 if (*p == '\0' && (p = *argptr++) == NULL)
9209 sh_error("No arg for -%c option", c);
9221 outstr(const char *p, FILE *file)
9246 outcslow(int c, FILE *dest)
9256 out1fmt(const char *fmt, ...)
9263 r = vprintf(fmt, ap);
9271 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9278 ret = vsnprintf(outbuf, length, fmt, ap);
9290 * Shell command parser.
9293 #define EOFMARKLEN 79
9297 struct heredoc *next; /* next here document in list */
9298 union node *here; /* redirection node */
9299 char *eofmark; /* string indicating end of input */
9300 int striptabs; /* if set, strip leading tabs */
9305 static struct heredoc *heredoclist; /* list of here documents to read */
9308 static union node *list(int);
9309 static union node *andor(void);
9310 static union node *pipeline(void);
9311 static union node *command(void);
9312 static union node *simplecmd(void);
9313 static union node *makename(void);
9314 static void parsefname(void);
9315 static void parseheredoc(void);
9316 static char peektoken(void);
9317 static int readtoken(void);
9318 static int xxreadtoken(void);
9319 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9320 static int noexpand(char *);
9321 static void synexpect(int) ATTRIBUTE_NORETURN;
9322 static void synerror(const char *) ATTRIBUTE_NORETURN;
9323 static void setprompt(int);
9329 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9330 * valid parse tree indicating a blank line.)
9334 parsecmd(int interact)
9339 doprompt = interact;
9341 setprompt(doprompt);
9356 union node *n1, *n2, *n3;
9359 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9360 if (nlflag == 2 && peektoken())
9366 if (tok == TBACKGND) {
9367 if (n2->type == NPIPE) {
9368 n2->npipe.backgnd = 1;
9370 if (n2->type != NREDIR) {
9371 n3 = stalloc(sizeof(struct nredir));
9373 n3->nredir.redirect = NULL;
9376 n2->type = NBACKGND;
9383 n3 = (union node *)stalloc(sizeof (struct nbinary));
9385 n3->nbinary.ch1 = n1;
9386 n3->nbinary.ch2 = n2;
9402 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9410 pungetc(); /* push back EOF on input */
9426 union node *n1, *n2, *n3;
9431 if ((t = readtoken()) == TAND) {
9433 } else if (t == TOR) {
9439 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9441 n3 = (union node *)stalloc(sizeof (struct nbinary));
9443 n3->nbinary.ch1 = n1;
9444 n3->nbinary.ch2 = n2;
9454 union node *n1, *n2, *pipenode;
9455 struct nodelist *lp, *prev;
9459 TRACE(("pipeline: entered\n"));
9460 if (readtoken() == TNOT) {
9462 checkkwd = CHKKWD | CHKALIAS;
9466 if (readtoken() == TPIPE) {
9467 pipenode = (union node *)stalloc(sizeof (struct npipe));
9468 pipenode->type = NPIPE;
9469 pipenode->npipe.backgnd = 0;
9470 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9471 pipenode->npipe.cmdlist = lp;
9475 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9476 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9479 } while (readtoken() == TPIPE);
9485 n2 = (union node *)stalloc(sizeof (struct nnot));
9498 union node *n1, *n2;
9499 union node *ap, **app;
9500 union node *cp, **cpp;
9501 union node *redir, **rpp;
9508 switch (readtoken()) {
9513 n1 = (union node *)stalloc(sizeof (struct nif));
9515 n1->nif.test = list(0);
9516 if (readtoken() != TTHEN)
9518 n1->nif.ifpart = list(0);
9520 while (readtoken() == TELIF) {
9521 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9522 n2 = n2->nif.elsepart;
9524 n2->nif.test = list(0);
9525 if (readtoken() != TTHEN)
9527 n2->nif.ifpart = list(0);
9529 if (lasttoken == TELSE)
9530 n2->nif.elsepart = list(0);
9532 n2->nif.elsepart = NULL;
9540 n1 = (union node *)stalloc(sizeof (struct nbinary));
9541 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9542 n1->nbinary.ch1 = list(0);
9543 if ((got=readtoken()) != TDO) {
9544 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9547 n1->nbinary.ch2 = list(0);
9552 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9553 synerror("Bad for loop variable");
9554 n1 = (union node *)stalloc(sizeof (struct nfor));
9556 n1->nfor.var = wordtext;
9557 checkkwd = CHKKWD | CHKALIAS;
9558 if (readtoken() == TIN) {
9560 while (readtoken() == TWORD) {
9561 n2 = (union node *)stalloc(sizeof (struct narg));
9563 n2->narg.text = wordtext;
9564 n2->narg.backquote = backquotelist;
9566 app = &n2->narg.next;
9570 if (lasttoken != TNL && lasttoken != TSEMI)
9573 n2 = (union node *)stalloc(sizeof (struct narg));
9575 n2->narg.text = (char *)dolatstr;
9576 n2->narg.backquote = NULL;
9577 n2->narg.next = NULL;
9580 * Newline or semicolon here is optional (but note
9581 * that the original Bourne shell only allowed NL).
9583 if (lasttoken != TNL && lasttoken != TSEMI)
9586 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9587 if (readtoken() != TDO)
9589 n1->nfor.body = list(0);
9593 n1 = (union node *)stalloc(sizeof (struct ncase));
9595 if (readtoken() != TWORD)
9597 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9599 n2->narg.text = wordtext;
9600 n2->narg.backquote = backquotelist;
9601 n2->narg.next = NULL;
9603 checkkwd = CHKKWD | CHKALIAS;
9604 } while (readtoken() == TNL);
9605 if (lasttoken != TIN)
9607 cpp = &n1->ncase.cases;
9609 checkkwd = CHKNL | CHKKWD;
9612 if (lasttoken == TLP)
9614 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9616 app = &cp->nclist.pattern;
9618 *app = ap = (union node *)stalloc(sizeof (struct narg));
9620 ap->narg.text = wordtext;
9621 ap->narg.backquote = backquotelist;
9622 if (readtoken() != TPIPE)
9624 app = &ap->narg.next;
9627 ap->narg.next = NULL;
9628 if (lasttoken != TRP)
9630 cp->nclist.body = list(2);
9632 cpp = &cp->nclist.next;
9634 checkkwd = CHKNL | CHKKWD;
9635 if ((t = readtoken()) != TESAC) {
9637 synexpect(TENDCASE);
9645 n1 = (union node *)stalloc(sizeof (struct nredir));
9646 n1->type = NSUBSHELL;
9647 n1->nredir.n = list(0);
9648 n1->nredir.redirect = NULL;
9661 if (readtoken() != t)
9665 /* Now check for redirection which may follow command */
9666 checkkwd = CHKKWD | CHKALIAS;
9668 while (readtoken() == TREDIR) {
9669 *rpp = n2 = redirnode;
9670 rpp = &n2->nfile.next;
9676 if (n1->type != NSUBSHELL) {
9677 n2 = (union node *)stalloc(sizeof (struct nredir));
9682 n1->nredir.redirect = redir;
9691 union node *args, **app;
9692 union node *n = NULL;
9693 union node *vars, **vpp;
9694 union node **rpp, *redir;
9704 savecheckkwd = CHKALIAS;
9706 checkkwd = savecheckkwd;
9707 switch (readtoken()) {
9709 n = (union node *)stalloc(sizeof (struct narg));
9711 n->narg.text = wordtext;
9712 n->narg.backquote = backquotelist;
9713 if (savecheckkwd && isassignment(wordtext)) {
9715 vpp = &n->narg.next;
9718 app = &n->narg.next;
9723 *rpp = n = redirnode;
9724 rpp = &n->nfile.next;
9725 parsefname(); /* read name of redirection file */
9729 args && app == &args->narg.next &&
9732 struct builtincmd *bcmd;
9735 /* We have a function */
9736 if (readtoken() != TRP)
9738 name = n->narg.text;
9740 !goodname(name) || (
9741 (bcmd = find_builtin(name)) &&
9742 IS_BUILTIN_SPECIAL(bcmd)
9745 synerror("Bad function name");
9747 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9748 n->narg.next = command();
9761 n = (union node *)stalloc(sizeof (struct ncmd));
9763 n->ncmd.args = args;
9764 n->ncmd.assign = vars;
9765 n->ncmd.redirect = redir;
9774 n = (union node *)stalloc(sizeof (struct narg));
9776 n->narg.next = NULL;
9777 n->narg.text = wordtext;
9778 n->narg.backquote = backquotelist;
9782 void fixredir(union node *n, const char *text, int err)
9784 TRACE(("Fix redir %s %d\n", text, err));
9786 n->ndup.vname = NULL;
9788 if (is_digit(text[0]) && text[1] == '\0')
9789 n->ndup.dupfd = digit_val(text[0]);
9790 else if (text[0] == '-' && text[1] == '\0')
9795 synerror("Bad fd number");
9797 n->ndup.vname = makename();
9805 union node *n = redirnode;
9807 if (readtoken() != TWORD)
9809 if (n->type == NHERE) {
9810 struct heredoc *here = heredoc;
9816 TRACE(("Here document %d\n", n->type));
9817 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9818 synerror("Illegal eof marker for << redirection");
9819 rmescapes(wordtext);
9820 here->eofmark = wordtext;
9822 if (heredoclist == NULL)
9825 for (p = heredoclist ; p->next ; p = p->next);
9828 } else if (n->type == NTOFD || n->type == NFROMFD) {
9829 fixredir(n, wordtext, 0);
9831 n->nfile.fname = makename();
9837 * Input any here documents.
9843 struct heredoc *here;
9853 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9854 here->eofmark, here->striptabs);
9855 n = (union node *)stalloc(sizeof (struct narg));
9856 n->narg.type = NARG;
9857 n->narg.next = NULL;
9858 n->narg.text = wordtext;
9859 n->narg.backquote = backquotelist;
9860 here->here->nhere.doc = n;
9865 static char peektoken(void)
9871 return tokname_array[t][0];
9879 int alreadyseen = tokpushback;
9882 #ifdef CONFIG_ASH_ALIAS
9891 if (checkkwd & CHKNL) {
9898 if (t != TWORD || quoteflag) {
9903 * check for keywords
9905 if (checkkwd & CHKKWD) {
9906 const char *const *pp;
9908 if ((pp = findkwd(wordtext))) {
9909 lasttoken = t = pp - tokname_array;
9910 TRACE(("keyword %s recognized\n", tokname(t)));
9915 if (checkkwd & CHKALIAS) {
9916 #ifdef CONFIG_ASH_ALIAS
9918 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9920 pushstring(ap->val, ap);
9930 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9932 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9939 * Read the next input token.
9940 * If the token is a word, we set backquotelist to the list of cmds in
9941 * backquotes. We set quoteflag to true if any part of the word was
9943 * If the token is TREDIR, then we set redirnode to a structure containing
9945 * In all cases, the variable startlinno is set to the number of the line
9946 * on which the token starts.
9948 * [Change comment: here documents and internal procedures]
9949 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9950 * word parsing code into a separate routine. In this case, readtoken
9951 * doesn't need to have any internal procedures, but parseword does.
9952 * We could also make parseoperator in essence the main routine, and
9953 * have parseword (readtoken1?) handle both words and redirection.]
9956 #define NEW_xxreadtoken
9957 #ifdef NEW_xxreadtoken
9959 /* singles must be first! */
9960 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9962 static const char xxreadtoken_tokens[] = {
9963 TNL, TLP, TRP, /* only single occurrence allowed */
9964 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9965 TEOF, /* corresponds to trailing nul */
9966 TAND, TOR, TENDCASE, /* if double occurrence */
9969 #define xxreadtoken_doubles \
9970 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9971 #define xxreadtoken_singles \
9972 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9974 static int xxreadtoken()
9985 startlinno = plinno;
9986 for (;;) { /* until token or start of word found */
9989 if ((c != ' ') && (c != '\t')
9990 #ifdef CONFIG_ASH_ALIAS
9995 while ((c = pgetc()) != '\n' && c != PEOF);
9997 } else if (c == '\\') {
9998 if (pgetc() != '\n') {
10002 startlinno = ++plinno;
10007 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10012 needprompt = doprompt;
10015 p = strchr(xxreadtoken_chars, c);
10018 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10021 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10022 if (pgetc() == *p) { /* double occurrence? */
10023 p += xxreadtoken_doubles + 1;
10030 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10038 #define RETURN(token) return lasttoken = token
10052 startlinno = plinno;
10053 for (;;) { /* until token or start of word found */
10056 case ' ': case '\t':
10057 #ifdef CONFIG_ASH_ALIAS
10062 while ((c = pgetc()) != '\n' && c != PEOF);
10066 if (pgetc() == '\n') {
10067 startlinno = ++plinno;
10076 needprompt = doprompt;
10081 if (pgetc() == '&')
10086 if (pgetc() == '|')
10091 if (pgetc() == ';')
10104 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10107 #endif /* NEW_xxreadtoken */
10111 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10112 * is not NULL, read a here document. In the latter case, eofmark is the
10113 * word which marks the end of the document and striptabs is true if
10114 * leading tabs should be stripped from the document. The argument firstc
10115 * is the first character of the input token or document.
10117 * Because C does not have internal subroutines, I have simulated them
10118 * using goto's to implement the subroutine linkage. The following macros
10119 * will run code that appears at the end of readtoken1.
10122 #define CHECKEND() {goto checkend; checkend_return:;}
10123 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10124 #define PARSESUB() {goto parsesub; parsesub_return:;}
10125 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10126 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10127 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10130 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10135 char line[EOFMARKLEN + 1];
10136 struct nodelist *bqlist = 0;
10139 int varnest = 0; /* levels of variables expansion */
10140 int arinest = 0; /* levels of arithmetic expansion */
10141 int parenlevel = 0; /* levels of parens in arithmetic */
10142 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10144 int prevsyntax = 0; /* syntax before arithmetic */
10146 /* Avoid longjmp clobbering */
10152 (void) &parenlevel;
10155 (void) &prevsyntax;
10159 startlinno = plinno;
10161 if (syntax == DQSYNTAX)
10170 STARTSTACKSTR(out);
10171 loop: { /* for each line, until end of word */
10172 CHECKEND(); /* set c to PEOF if at end of here document */
10173 for (;;) { /* until end of line or end of word */
10174 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10175 switch(SIT(c, syntax)) {
10176 case CNL: /* '\n' */
10177 if (syntax == BASESYNTAX)
10178 goto endword; /* exit outer loop */
10184 goto loop; /* continue outer loop */
10189 if (eofmark == NULL || dblquote)
10190 USTPUTC(CTLESC, out);
10193 case CBACK: /* backslash */
10196 USTPUTC(CTLESC, out);
10197 USTPUTC('\\', out);
10199 } else if (c == '\n') {
10204 c != '\\' && c != '`' &&
10209 USTPUTC(CTLESC, out);
10210 USTPUTC('\\', out);
10212 if (SIT(c, SQSYNTAX) == CCTL)
10213 USTPUTC(CTLESC, out);
10221 if (eofmark == NULL) {
10222 USTPUTC(CTLQUOTEMARK, out);
10230 if (eofmark != NULL && arinest == 0 &&
10234 if (dqvarnest == 0) {
10235 syntax = BASESYNTAX;
10242 case CVAR: /* '$' */
10243 PARSESUB(); /* parse substitution */
10245 case CENDVAR: /* '}' */
10248 if (dqvarnest > 0) {
10251 USTPUTC(CTLENDVAR, out);
10256 #ifdef CONFIG_ASH_MATH_SUPPORT
10257 case CLP: /* '(' in arithmetic */
10261 case CRP: /* ')' in arithmetic */
10262 if (parenlevel > 0) {
10266 if (pgetc() == ')') {
10267 if (--arinest == 0) {
10268 USTPUTC(CTLENDARI, out);
10269 syntax = prevsyntax;
10270 if (syntax == DQSYNTAX)
10278 * unbalanced parens
10279 * (don't 2nd guess - no error)
10287 case CBQUOTE: /* '`' */
10291 goto endword; /* exit outer loop */
10296 goto endword; /* exit outer loop */
10297 #ifdef CONFIG_ASH_ALIAS
10307 #ifdef CONFIG_ASH_MATH_SUPPORT
10308 if (syntax == ARISYNTAX)
10309 synerror("Missing '))'");
10311 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10312 synerror("Unterminated quoted string");
10313 if (varnest != 0) {
10314 startlinno = plinno;
10316 synerror("Missing '}'");
10318 USTPUTC('\0', out);
10319 len = out - (char *)stackblock();
10320 out = stackblock();
10321 if (eofmark == NULL) {
10322 if ((c == '>' || c == '<')
10325 && (*out == '\0' || is_digit(*out))) {
10327 return lasttoken = TREDIR;
10332 quoteflag = quotef;
10333 backquotelist = bqlist;
10334 grabstackblock(len);
10336 return lasttoken = TWORD;
10337 /* end of readtoken routine */
10342 * Check to see whether we are at the end of the here document. When this
10343 * is called, c is set to the first character of the next input line. If
10344 * we are at the end of the here document, this routine sets the c to PEOF.
10349 #ifdef CONFIG_ASH_ALIAS
10355 while (c == '\t') {
10359 if (c == *eofmark) {
10360 if (pfgets(line, sizeof line) != NULL) {
10364 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10365 if (*p == '\n' && *q == '\0') {
10368 needprompt = doprompt;
10370 pushstring(line, NULL);
10375 goto checkend_return;
10380 * Parse a redirection operator. The variable "out" points to a string
10381 * specifying the fd to be redirected. The variable "c" contains the
10382 * first character of the redirection operator.
10389 np = (union node *)stalloc(sizeof (struct nfile));
10394 np->type = NAPPEND;
10396 np->type = NCLOBBER;
10403 } else { /* c == '<' */
10405 switch (c = pgetc()) {
10407 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10408 np = (union node *)stalloc(sizeof (struct nhere));
10412 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10413 heredoc->here = np;
10414 if ((c = pgetc()) == '-') {
10415 heredoc->striptabs = 1;
10417 heredoc->striptabs = 0;
10423 np->type = NFROMFD;
10427 np->type = NFROMTO;
10437 np->nfile.fd = digit_val(fd);
10439 goto parseredir_return;
10444 * Parse a substitution. At this point, we have read the dollar sign
10445 * and nothing else.
10453 static const char types[] = "}-+?=";
10457 c <= PEOA_OR_PEOF ||
10458 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10462 } else if (c == '(') { /* $(command) or $((arith)) */
10463 if (pgetc() == '(') {
10464 #ifdef CONFIG_ASH_MATH_SUPPORT
10467 synerror("We unsupport $((arith))");
10474 USTPUTC(CTLVAR, out);
10475 typeloc = out - (char *)stackblock();
10476 USTPUTC(VSNORMAL, out);
10477 subtype = VSNORMAL;
10481 if ((c = pgetc()) == '}')
10484 subtype = VSLENGTH;
10489 if (c > PEOA_OR_PEOF && is_name(c)) {
10493 } while (c > PEOA_OR_PEOF && is_in_name(c));
10494 } else if (is_digit(c)) {
10498 } while (is_digit(c));
10500 else if (is_special(c)) {
10505 badsub: synerror("Bad substitution");
10509 if (subtype == 0) {
10516 p = strchr(types, c);
10519 subtype = p - types + VSNORMAL;
10525 subtype = c == '#' ? VSTRIMLEFT :
10538 if (dblquote || arinest)
10540 *((char *)stackblock() + typeloc) = subtype | flags;
10541 if (subtype != VSNORMAL) {
10543 if (dblquote || arinest) {
10548 goto parsesub_return;
10553 * Called to parse command substitutions. Newstyle is set if the command
10554 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10555 * list of commands (passed by reference), and savelen is the number of
10556 * characters on the top of the stack which must be preserved.
10560 struct nodelist **nlpp;
10563 char *volatile str;
10564 struct jmploc jmploc;
10565 struct jmploc *volatile savehandler;
10567 int saveprompt = 0;
10569 (void) &saveprompt;
10572 savepbq = parsebackquote;
10573 if (setjmp(jmploc.loc)) {
10576 parsebackquote = 0;
10577 handler = savehandler;
10578 longjmp(handler->loc, 1);
10582 savelen = out - (char *)stackblock();
10584 str = ckmalloc(savelen);
10585 memcpy(str, stackblock(), savelen);
10587 savehandler = handler;
10591 /* We must read until the closing backquote, giving special
10592 treatment to some slashes, and then push the string and
10593 reread it as input, interpreting it normally. */
10600 STARTSTACKSTR(pout);
10605 switch (pc = pgetc()) {
10610 if ((pc = pgetc()) == '\n') {
10615 * If eating a newline, avoid putting
10616 * the newline into the new character
10617 * stream (via the STPUTC after the
10622 if (pc != '\\' && pc != '`' && pc != '$'
10623 && (!dblquote || pc != '"'))
10624 STPUTC('\\', pout);
10625 if (pc > PEOA_OR_PEOF) {
10631 #ifdef CONFIG_ASH_ALIAS
10634 startlinno = plinno;
10635 synerror("EOF in backquote substitution");
10639 needprompt = doprompt;
10648 STPUTC('\0', pout);
10649 psavelen = pout - (char *)stackblock();
10650 if (psavelen > 0) {
10651 pstr = grabstackstr(pout);
10652 setinputstring(pstr);
10657 nlpp = &(*nlpp)->next;
10658 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10659 (*nlpp)->next = NULL;
10660 parsebackquote = oldstyle;
10663 saveprompt = doprompt;
10670 doprompt = saveprompt;
10672 if (readtoken() != TRP)
10679 * Start reading from old file again, ignoring any pushed back
10680 * tokens left from the backquote parsing
10685 while (stackblocksize() <= savelen)
10687 STARTSTACKSTR(out);
10689 memcpy(out, str, savelen);
10690 STADJUST(savelen, out);
10696 parsebackquote = savepbq;
10697 handler = savehandler;
10698 if (arinest || dblquote)
10699 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10701 USTPUTC(CTLBACKQ, out);
10703 goto parsebackq_oldreturn;
10705 goto parsebackq_newreturn;
10708 #ifdef CONFIG_ASH_MATH_SUPPORT
10710 * Parse an arithmetic expansion (indicate start of one and set state)
10714 if (++arinest == 1) {
10715 prevsyntax = syntax;
10716 syntax = ARISYNTAX;
10717 USTPUTC(CTLARI, out);
10724 * we collapse embedded arithmetic expansion to
10725 * parenthesis, which should be equivalent
10729 goto parsearith_return;
10733 } /* end of readtoken */
10738 * Returns true if the text contains nothing to expand (no dollar signs
10743 noexpand(char *text)
10749 while ((c = *p++) != '\0') {
10750 if (c == CTLQUOTEMARK)
10754 else if (SIT(c, BASESYNTAX) == CCTL)
10762 * Return of a legal variable name (a letter or underscore followed by zero or
10763 * more letters, underscores, and digits).
10767 endofname(const char *name)
10775 if (! is_in_name(*p))
10783 * Called when an unexpected token is read during the parse. The argument
10784 * is the token that is expected, or -1 if more than one type of token can
10785 * occur at this point.
10788 static void synexpect(int token)
10793 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10795 sprintf(msg + l, " (expecting %s)", tokname(token));
10801 synerror(const char *msg)
10803 sh_error("Syntax error: %s", msg);
10809 * called by editline -- any expansions to the prompt
10810 * should be added here.
10813 #ifdef CONFIG_ASH_EXPAND_PRMT
10814 static const char *
10815 expandstr(const char *ps)
10819 /* XXX Fix (char *) cast. */
10820 setinputstring((char *)ps);
10821 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10824 n.narg.type = NARG;
10825 n.narg.next = NULL;
10826 n.narg.text = wordtext;
10827 n.narg.backquote = backquotelist;
10829 expandarg(&n, NULL, 0);
10830 return stackblock();
10834 static void setprompt(int whichprompt)
10836 const char *prompt;
10837 #ifdef CONFIG_ASH_EXPAND_PRMT
10838 struct stackmark smark;
10843 switch (whichprompt) {
10853 #ifdef CONFIG_ASH_EXPAND_PRMT
10854 setstackmark(&smark);
10855 stalloc(stackblocksize());
10857 putprompt(expandstr(prompt));
10858 #ifdef CONFIG_ASH_EXPAND_PRMT
10859 popstackmark(&smark);
10864 static const char *const *findkwd(const char *s)
10866 return bsearch(s, tokname_array + KWDOFFSET,
10867 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10868 sizeof(const char *), pstrcmp);
10874 * Code for dealing with input/output redirection.
10877 #define EMPTY -2 /* marks an unused slot in redirtab */
10879 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10881 # define PIPESIZE PIPE_BUF
10885 * Open a file in noclobber mode.
10886 * The code was copied from bash.
10889 noclobberopen(const char *fname)
10892 struct stat finfo, finfo2;
10895 * If the file exists and is a regular file, return an error
10898 r = stat(fname, &finfo);
10899 if (r == 0 && S_ISREG(finfo.st_mode)) {
10905 * If the file was not present (r != 0), make sure we open it
10906 * exclusively so that if it is created before we open it, our open
10907 * will fail. Make sure that we do not truncate an existing file.
10908 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10909 * file was not a regular file, we leave O_EXCL off.
10912 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10913 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10915 /* If the open failed, return the file descriptor right away. */
10920 * OK, the open succeeded, but the file may have been changed from a
10921 * non-regular file to a regular file between the stat and the open.
10922 * We are assuming that the O_EXCL open handles the case where FILENAME
10923 * did not exist and is symlinked to an existing file between the stat
10928 * If we can open it and fstat the file descriptor, and neither check
10929 * revealed that it was a regular file, and the file has not been
10930 * replaced, return the file descriptor.
10932 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10933 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10936 /* The file has been replaced. badness. */
10943 * Handle here documents. Normally we fork off a process to write the
10944 * data to a pipe. If the document is short, we can stuff the data in
10945 * the pipe without forking.
10949 openhere(union node *redir)
10955 sh_error("Pipe call failed");
10956 if (redir->type == NHERE) {
10957 len = strlen(redir->nhere.doc->narg.text);
10958 if (len <= PIPESIZE) {
10959 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10963 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10965 signal(SIGINT, SIG_IGN);
10966 signal(SIGQUIT, SIG_IGN);
10967 signal(SIGHUP, SIG_IGN);
10969 signal(SIGTSTP, SIG_IGN);
10971 signal(SIGPIPE, SIG_DFL);
10972 if (redir->type == NHERE)
10973 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10975 expandhere(redir->nhere.doc, pip[1]);
10984 openredirect(union node *redir)
10989 switch (redir->nfile.type) {
10991 fname = redir->nfile.expfname;
10992 if ((f = open(fname, O_RDONLY)) < 0)
10996 fname = redir->nfile.expfname;
10997 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11001 /* Take care of noclobber mode. */
11003 fname = redir->nfile.expfname;
11004 if ((f = noclobberopen(fname)) < 0)
11010 fname = redir->nfile.expfname;
11011 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11015 fname = redir->nfile.expfname;
11016 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11023 /* Fall through to eliminate warning. */
11030 f = openhere(redir);
11036 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11038 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11042 dupredirect(union node *redir, int f)
11044 int fd = redir->nfile.fd;
11046 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11047 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11048 copyfd(redir->ndup.dupfd, fd);
11061 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11062 * old file descriptors are stashed away so that the redirection can be
11063 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11064 * standard output, and the standard error if it becomes a duplicate of
11065 * stdout, is saved in memory.
11069 redirect(union node *redir, int flags)
11072 struct redirtab *sv;
11083 if (flags & REDIR_PUSH) {
11084 struct redirtab *q;
11085 q = ckmalloc(sizeof (struct redirtab));
11086 q->next = redirlist;
11088 q->nullredirs = nullredirs - 1;
11089 for (i = 0 ; i < 10 ; i++)
11090 q->renamed[i] = EMPTY;
11097 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11098 n->ndup.dupfd == fd)
11099 continue; /* redirect from/to same file descriptor */
11101 newfd = openredirect(n);
11104 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11105 i = fcntl(fd, F_DUPFD, 10);
11112 sh_error("%d: %m", fd);
11122 dupredirect(n, newfd);
11123 } while ((n = n->nfile.next));
11125 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11126 preverrout_fd = sv->renamed[2];
11131 * Undo the effects of the last redirection.
11137 struct redirtab *rp;
11140 if (--nullredirs >= 0)
11144 for (i = 0 ; i < 10 ; i++) {
11145 if (rp->renamed[i] != EMPTY) {
11148 copyfd(rp->renamed[i], i);
11150 close(rp->renamed[i]);
11153 redirlist = rp->next;
11154 nullredirs = rp->nullredirs;
11160 * Undo all redirections. Called on error or interrupt.
11164 * Discard all saved file descriptors.
11168 clearredir(int drop)
11180 * Copy a file descriptor to be >= to. Returns -1
11181 * if the source file descriptor is closed, EMPTY if there are no unused
11182 * file descriptors left.
11186 copyfd(int from, int to)
11190 newfd = fcntl(from, F_DUPFD, to);
11192 if (errno == EMFILE)
11195 sh_error("%d: %m", from);
11202 redirectsafe(union node *redir, int flags)
11205 volatile int saveint;
11206 struct jmploc *volatile savehandler = handler;
11207 struct jmploc jmploc;
11210 if (!(err = setjmp(jmploc.loc) * 2)) {
11212 redirect(redir, flags);
11214 handler = savehandler;
11215 if (err && exception != EXERROR)
11216 longjmp(handler->loc, 1);
11217 RESTOREINT(saveint);
11224 static void shtree(union node *, int, char *, FILE*);
11225 static void shcmd(union node *, FILE *);
11226 static void sharg(union node *, FILE *);
11227 static void indent(int, char *, FILE *);
11228 static void trstring(char *);
11232 showtree(union node *n)
11234 trputs("showtree called\n");
11235 shtree(n, 1, NULL, stdout);
11240 shtree(union node *n, int ind, char *pfx, FILE *fp)
11242 struct nodelist *lp;
11248 indent(ind, pfx, fp);
11259 shtree(n->nbinary.ch1, ind, NULL, fp);
11262 shtree(n->nbinary.ch2, ind, NULL, fp);
11270 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11275 if (n->npipe.backgnd)
11281 fprintf(fp, "<node type %d>", n->type);
11290 shcmd(union node *cmd, FILE *fp)
11298 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11304 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11307 switch (np->nfile.type) {
11308 case NTO: s = ">"; dftfd = 1; break;
11309 case NCLOBBER: s = ">|"; dftfd = 1; break;
11310 case NAPPEND: s = ">>"; dftfd = 1; break;
11311 case NTOFD: s = ">&"; dftfd = 1; break;
11312 case NFROM: s = "<"; dftfd = 0; break;
11313 case NFROMFD: s = "<&"; dftfd = 0; break;
11314 case NFROMTO: s = "<>"; dftfd = 0; break;
11315 default: s = "*error*"; dftfd = 0; break;
11317 if (np->nfile.fd != dftfd)
11318 fprintf(fp, "%d", np->nfile.fd);
11320 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11321 fprintf(fp, "%d", np->ndup.dupfd);
11323 sharg(np->nfile.fname, fp);
11332 sharg(union node *arg, FILE *fp)
11335 struct nodelist *bqlist;
11338 if (arg->type != NARG) {
11339 out1fmt("<node type %d>\n", arg->type);
11342 bqlist = arg->narg.backquote;
11343 for (p = arg->narg.text ; *p ; p++) {
11352 if (subtype == VSLENGTH)
11358 if (subtype & VSNUL)
11361 switch (subtype & VSTYPE) {
11380 case VSTRIMLEFTMAX:
11387 case VSTRIMRIGHTMAX:
11394 out1fmt("<subtype %d>", subtype);
11401 case CTLBACKQ|CTLQUOTE:
11404 shtree(bqlist->n, -1, NULL, fp);
11416 indent(int amount, char *pfx, FILE *fp)
11420 for (i = 0 ; i < amount ; i++) {
11421 if (pfx && i == amount - 1)
11442 putc(c, tracefile);
11446 trace(const char *fmt, ...)
11453 (void) vfprintf(tracefile, fmt, va);
11458 tracev(const char *fmt, va_list va)
11462 (void) vfprintf(tracefile, fmt, va);
11467 trputs(const char *s)
11471 fputs(s, tracefile);
11483 putc('"', tracefile);
11484 for (p = s ; *p ; p++) {
11486 case '\n': c = 'n'; goto backslash;
11487 case '\t': c = 't'; goto backslash;
11488 case '\r': c = 'r'; goto backslash;
11489 case '"': c = '"'; goto backslash;
11490 case '\\': c = '\\'; goto backslash;
11491 case CTLESC: c = 'e'; goto backslash;
11492 case CTLVAR: c = 'v'; goto backslash;
11493 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11494 case CTLBACKQ: c = 'q'; goto backslash;
11495 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11496 backslash: putc('\\', tracefile);
11497 putc(c, tracefile);
11500 if (*p >= ' ' && *p <= '~')
11501 putc(*p, tracefile);
11503 putc('\\', tracefile);
11504 putc(*p >> 6 & 03, tracefile);
11505 putc(*p >> 3 & 07, tracefile);
11506 putc(*p & 07, tracefile);
11511 putc('"', tracefile);
11523 putc(' ', tracefile);
11525 putc('\n', tracefile);
11541 /* leave open because libedit might be using it */
11544 scopy("./trace", s);
11546 if (!freopen(s, "a", tracefile)) {
11547 fprintf(stderr, "Can't re-open %s\n", s);
11552 if ((tracefile = fopen(s, "a")) == NULL) {
11553 fprintf(stderr, "Can't open %s\n", s);
11559 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11560 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11562 setlinebuf(tracefile);
11563 fputs("\nTracing started.\n", tracefile);
11571 * Sigmode records the current value of the signal handlers for the various
11572 * modes. A value of zero means that the current handler is not known.
11573 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11576 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11577 #define S_CATCH 2 /* signal is caught */
11578 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11579 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11580 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11585 * The trap builtin.
11589 trapcmd(int argc, char **argv)
11598 for (signo = 0 ; signo < NSIG ; signo++) {
11599 if (trap[signo] != NULL) {
11602 sn = u_signal_names(0, &signo, 0);
11605 out1fmt("trap -- %s %s\n",
11606 single_quote(trap[signo]), sn);
11616 if ((signo = decode_signal(*ap, 0)) < 0)
11617 sh_error("%s: bad trap", *ap);
11620 if (action[0] == '-' && action[1] == '\0')
11623 action = savestr(action);
11626 ckfree(trap[signo]);
11627 trap[signo] = action;
11638 * Clear traps on a fork.
11646 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11647 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11651 if (tp != &trap[0])
11652 setsignal(tp - trap);
11660 * Set the signal handler for the specified signal. The routine figures
11661 * out what it should be set to.
11665 setsignal(int signo)
11669 struct sigaction act;
11671 if ((t = trap[signo]) == NULL)
11673 else if (*t != '\0')
11677 if (rootshell && action == S_DFL) {
11680 if (iflag || minusc || sflag == 0)
11703 t = &sigmode[signo - 1];
11707 * current setting unknown
11709 if (sigaction(signo, 0, &act) == -1) {
11711 * Pretend it worked; maybe we should give a warning
11712 * here, but other shells don't. We don't alter
11713 * sigmode, so that we retry every time.
11717 if (act.sa_handler == SIG_IGN) {
11718 if (mflag && (signo == SIGTSTP ||
11719 signo == SIGTTIN || signo == SIGTTOU)) {
11720 tsig = S_IGN; /* don't hard ignore these */
11724 tsig = S_RESET; /* force to be set */
11727 if (tsig == S_HARD_IGN || tsig == action)
11731 act.sa_handler = onsig;
11734 act.sa_handler = SIG_IGN;
11737 act.sa_handler = SIG_DFL;
11741 sigfillset(&act.sa_mask);
11742 sigaction(signo, &act, 0);
11750 ignoresig(int signo)
11752 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11753 signal(signo, SIG_IGN);
11755 sigmode[signo - 1] = S_HARD_IGN;
11766 gotsig[signo - 1] = 1;
11767 pendingsigs = signo;
11769 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11778 * Called to execute a trap. Perhaps we should avoid entering new trap
11779 * handlers while we are executing a trap handler.
11791 savestatus = exitstatus;
11795 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11803 skip = evalstring(p, SKIPEVAL);
11804 exitstatus = savestatus;
11814 * Controls whether the shell is interactive or not.
11818 setinteractive(int on)
11820 static int is_interactive;
11822 if (++on == is_interactive)
11824 is_interactive = on;
11826 setsignal(SIGQUIT);
11827 setsignal(SIGTERM);
11828 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11829 if(is_interactive > 1) {
11830 /* Looks like they want an interactive shell */
11831 static int do_banner;
11835 "\n\n%s Built-in shell (ash)\n"
11836 "Enter 'help' for a list of built-in commands.\n\n",
11845 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11846 /*** List the available builtins ***/
11848 static int helpcmd(int argc, char **argv)
11852 out1fmt("\nBuilt-in commands:\n-------------------\n");
11853 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11854 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11855 builtincmd[i].name + 1);
11861 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11863 extern const struct BB_applet applets[];
11864 extern const size_t NUM_APPLETS;
11866 for (i = 0; i < NUM_APPLETS; i++) {
11868 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11877 return EXIT_SUCCESS;
11879 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11882 * Called to exit the shell.
11892 status = exitstatus;
11893 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11894 if (setjmp(loc.loc)) {
11895 if (exception == EXEXIT)
11900 if ((p = trap[0])) {
11906 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11907 if (iflag && rootshell) {
11908 const char *hp = lookupvar("HISTFILE");
11911 save_history ( hp );
11919 static int decode_signal(const char *string, int minsig)
11922 const char *name = u_signal_names(string, &signo, minsig);
11924 return name ? signo : -1;
11929 static struct var *vartab[VTABSIZE];
11931 static int vpcmp(const void *, const void *);
11932 static struct var **findvar(struct var **, const char *);
11935 * Initialize the variable symbol tables and import the environment
11939 #ifdef CONFIG_ASH_GETOPTS
11941 * Safe version of setvar, returns 1 on success 0 on failure.
11945 setvarsafe(const char *name, const char *val, int flags)
11948 volatile int saveint;
11949 struct jmploc *volatile savehandler = handler;
11950 struct jmploc jmploc;
11953 if (setjmp(jmploc.loc))
11957 setvar(name, val, flags);
11960 handler = savehandler;
11961 RESTOREINT(saveint);
11967 * Set the value of a variable. The flags argument is ored with the
11968 * flags of the variable. If val is NULL, the variable is unset.
11972 setvar(const char *name, const char *val, int flags)
11979 q = endofname(name);
11980 p = strchrnul(q, '=');
11981 namelen = p - name;
11982 if (!namelen || p != q)
11983 sh_error("%.*s: bad variable name", namelen, name);
11988 vallen = strlen(val);
11991 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
11994 p = mempcpy(p, val, vallen);
11997 setvareq(nameeq, flags | VNOSAVE);
12003 * Same as setvar except that the variable and value are passed in
12004 * the first argument as name=value. Since the first argument will
12005 * be actually stored in the table, it should not be a string that
12007 * Called with interrupts off.
12011 setvareq(char *s, int flags)
12013 struct var *vp, **vpp;
12016 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12017 vp = *findvar(vpp, s);
12019 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12022 if (flags & VNOSAVE)
12025 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12028 if (flags & VNOSET)
12031 if (vp->func && (flags & VNOFUNC) == 0)
12032 (*vp->func)(strchrnul(s, '=') + 1);
12034 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12037 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12039 if (flags & VNOSET)
12042 vp = ckmalloc(sizeof (*vp));
12047 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12055 * Process a linked list of variable assignments.
12059 listsetvar(struct strlist *list_set_var, int flags)
12061 struct strlist *lp = list_set_var;
12067 setvareq(lp->text, flags);
12068 } while ((lp = lp->next));
12074 * Find the value of a variable. Returns NULL if not set.
12078 lookupvar(const char *name)
12082 if ((v = *findvar(hashvar(name), name))) {
12085 * Dynamic variables are implemented roughly the same way they are
12086 * in bash. Namely, they're "special" so long as they aren't unset.
12087 * As soon as they're unset, they're no longer dynamic, and dynamic
12088 * lookup will no longer happen at that point. -- PFM.
12090 if((v->flags & VDYNAMIC))
12093 if(!(v->flags & VUNSET))
12094 return strchrnul(v->text, '=') + 1;
12102 * Search the environment of a builtin command.
12106 bltinlookup(const char *name)
12108 struct strlist *sp;
12110 for (sp = cmdenviron ; sp ; sp = sp->next) {
12111 if (varequal(sp->text, name))
12112 return strchrnul(sp->text, '=') + 1;
12114 return lookupvar(name);
12119 * Generate a list of variables satisfying the given conditions.
12123 listvars(int on, int off, char ***end)
12134 for (vp = *vpp ; vp ; vp = vp->next)
12135 if ((vp->flags & mask) == on) {
12136 if (ep == stackstrend())
12137 ep = growstackstr();
12138 *ep++ = (char *) vp->text;
12140 } while (++vpp < vartab + VTABSIZE);
12141 if (ep == stackstrend())
12142 ep = growstackstr();
12146 return grabstackstr(ep);
12151 * POSIX requires that 'set' (but not export or readonly) output the
12152 * variables in lexicographic order - by the locale's collating order (sigh).
12153 * Maybe we could keep them in an ordered balanced binary tree
12154 * instead of hashed lists.
12155 * For now just roll 'em through qsort for printing...
12159 showvars(const char *sep_prefix, int on, int off)
12162 char **ep, **epend;
12164 ep = listvars(on, off, &epend);
12165 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12167 sep = *sep_prefix ? spcstr : sep_prefix;
12169 for (; ep < epend; ep++) {
12173 p = strchrnul(*ep, '=');
12176 q = single_quote(++p);
12178 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12187 * The export and readonly commands.
12191 exportcmd(int argc, char **argv)
12197 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12200 notp = nextopt("p") - 'p';
12201 if (notp && ((name = *(aptr = argptr)))) {
12203 if ((p = strchr(name, '=')) != NULL) {
12206 if ((vp = *findvar(hashvar(name), name))) {
12211 setvar(name, p, flag);
12212 } while ((name = *++aptr) != NULL);
12214 showvars(argv[0], flag, 0);
12221 * Make a variable a local variable. When a variable is made local, it's
12222 * value and flags are saved in a localvar structure. The saved values
12223 * will be restored when the shell function returns. We handle the name
12224 * "-" as a special case.
12228 mklocal(char *name)
12230 struct localvar *lvp;
12235 lvp = ckmalloc(sizeof (struct localvar));
12236 if (name[0] == '-' && name[1] == '\0') {
12238 p = ckmalloc(sizeof(optlist));
12239 lvp->text = memcpy(p, optlist, sizeof(optlist));
12244 vpp = hashvar(name);
12245 vp = *findvar(vpp, name);
12246 eq = strchr(name, '=');
12249 setvareq(name, VSTRFIXED);
12251 setvar(name, NULL, VSTRFIXED);
12252 vp = *vpp; /* the new variable */
12253 lvp->flags = VUNSET;
12255 lvp->text = vp->text;
12256 lvp->flags = vp->flags;
12257 vp->flags |= VSTRFIXED|VTEXTFIXED;
12263 lvp->next = localvars;
12269 * The "local" command.
12273 localcmd(int argc, char **argv)
12278 while ((name = *argv++) != NULL) {
12286 * Called after a function returns.
12287 * Interrupts must be off.
12293 struct localvar *lvp;
12296 while ((lvp = localvars) != NULL) {
12297 localvars = lvp->next;
12299 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12300 if (vp == NULL) { /* $- saved */
12301 memcpy(optlist, lvp->text, sizeof(optlist));
12304 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12305 unsetvar(vp->text);
12308 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12309 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12311 vp->flags = lvp->flags;
12312 vp->text = lvp->text;
12320 * The unset builtin command. We unset the function before we unset the
12321 * variable to allow a function to be unset when there is a readonly variable
12322 * with the same name.
12326 unsetcmd(int argc, char **argv)
12333 while ((i = nextopt("vf")) != '\0') {
12337 for (ap = argptr; *ap ; ap++) {
12352 * Unset the specified variable.
12356 unsetvar(const char *s)
12362 vpp = findvar(hashvar(s), s);
12366 int flags = vp->flags;
12369 if (flags & VREADONLY)
12372 vp->flags &= ~VDYNAMIC;
12374 if (flags & VUNSET)
12376 if ((flags & VSTRFIXED) == 0) {
12378 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12385 vp->flags &= ~VEXPORT;
12398 * Find the appropriate entry in the hash table from the name.
12401 static struct var **
12402 hashvar(const char *p)
12404 unsigned int hashval;
12406 hashval = ((unsigned char) *p) << 4;
12407 while (*p && *p != '=')
12408 hashval += (unsigned char) *p++;
12409 return &vartab[hashval % VTABSIZE];
12415 * Compares two strings up to the first = or '\0'. The first
12416 * string must be terminated by '='; the second may be terminated by
12417 * either '=' or '\0'.
12421 varcmp(const char *p, const char *q)
12425 while ((c = *p) == (d = *q)) {
12426 if (!c || c == '=')
12440 vpcmp(const void *a, const void *b)
12442 return varcmp(*(const char **)a, *(const char **)b);
12445 static struct var **
12446 findvar(struct var **vpp, const char *name)
12448 for (; *vpp; vpp = &(*vpp)->next) {
12449 if (varequal((*vpp)->text, name)) {
12457 #include <sys/times.h>
12459 static const unsigned char timescmd_str[] = {
12460 ' ', offsetof(struct tms, tms_utime),
12461 '\n', offsetof(struct tms, tms_stime),
12462 ' ', offsetof(struct tms, tms_cutime),
12463 '\n', offsetof(struct tms, tms_cstime),
12467 static int timescmd(int ac, char **av)
12469 long int clk_tck, s, t;
12470 const unsigned char *p;
12473 clk_tck = sysconf(_SC_CLK_TCK);
12478 t = *(clock_t *)(((char *) &buf) + p[1]);
12480 out1fmt("%ldm%ld.%.3lds%c",
12482 ((t - s * clk_tck) * 1000) / clk_tck,
12484 } while (*(p += 2));
12489 #ifdef CONFIG_ASH_MATH_SUPPORT
12491 dash_arith(const char *s)
12497 result = arith(s, &errcode);
12500 sh_error("exponent less than 0");
12501 else if (errcode == -2)
12502 sh_error("divide by zero");
12503 else if (errcode == -5)
12504 sh_error("expression recursion loop detected");
12515 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12516 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12518 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12522 letcmd(int argc, char **argv)
12529 sh_error("expression expected");
12530 for (ap = argv + 1; *ap; ap++) {
12531 i = dash_arith(*ap);
12536 #endif /* CONFIG_ASH_MATH_SUPPORT */
12541 * Miscellaneous builtins.
12547 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12548 typedef enum __rlimit_resource rlim_t;
12554 * The read builtin. The -e option causes backslashes to escape the
12555 * following character.
12557 * This uses unbuffered input, which may be avoidable in some cases.
12561 readcmd(int argc, char **argv)
12573 #if defined(CONFIG_ASH_READ_NCHARS)
12577 struct termios tty, old_tty;
12579 #if defined(CONFIG_ASH_READ_TIMEOUT)
12583 ts.tv_sec = ts.tv_usec = 0;
12588 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12589 while ((i = nextopt("p:rt:n:s")) != '\0')
12590 #elif defined(CONFIG_ASH_READ_NCHARS)
12591 while ((i = nextopt("p:rn:s")) != '\0')
12592 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12593 while ((i = nextopt("p:rt:")) != '\0')
12595 while ((i = nextopt("p:r")) != '\0')
12600 prompt = optionarg;
12602 #if defined(CONFIG_ASH_READ_NCHARS)
12604 nchars = strtol(optionarg, &p, 10);
12606 sh_error("invalid count");
12607 nch_flag = (nchars > 0);
12613 #if defined(CONFIG_ASH_READ_TIMEOUT)
12615 ts.tv_sec = strtol(optionarg, &p, 10);
12621 ts.tv_usec = strtol(p, &p2, 10);
12623 sh_error("invalid timeout");
12625 /* normalize to usec */
12627 sh_error("invalid timeout");
12628 while (scale++ < 6)
12632 sh_error("invalid timeout");
12634 if ( ! ts.tv_sec && ! ts.tv_usec)
12635 sh_error("invalid timeout");
12645 if (prompt && isatty(0)) {
12648 if (*(ap = argptr) == NULL)
12649 sh_error("arg count");
12650 if ((ifs = bltinlookup("IFS")) == NULL)
12652 #if defined(CONFIG_ASH_READ_NCHARS)
12653 if (nch_flag || silent) {
12654 tcgetattr(0, &tty);
12657 tty.c_lflag &= ~ICANON;
12658 tty.c_cc[VMIN] = nchars;
12661 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12664 tcsetattr(0, TCSANOW, &tty);
12667 #if defined(CONFIG_ASH_READ_TIMEOUT)
12668 if (ts.tv_sec || ts.tv_usec) {
12672 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12674 #if defined(CONFIG_ASH_READ_NCHARS)
12676 tcsetattr(0, TCSANOW, &old_tty);
12686 #if defined(CONFIG_ASH_READ_NCHARS)
12687 while (!nch_flag || nchars--)
12692 if (read(0, &c, 1) != 1) {
12704 if (!rflag && c == '\\') {
12710 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12714 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12716 setvar(*ap, stackblock(), 0);
12725 #if defined(CONFIG_ASH_READ_NCHARS)
12726 if (nch_flag || silent)
12727 tcsetattr(0, TCSANOW, &old_tty);
12731 /* Remove trailing blanks */
12732 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12734 setvar(*ap, stackblock(), 0);
12735 while (*++ap != NULL)
12736 setvar(*ap, nullstr, 0);
12741 static int umaskcmd(int argc, char **argv)
12743 static const char permuser[3] = "ugo";
12744 static const char permmode[3] = "rwx";
12745 static const short int permmask[] = {
12746 S_IRUSR, S_IWUSR, S_IXUSR,
12747 S_IRGRP, S_IWGRP, S_IXGRP,
12748 S_IROTH, S_IWOTH, S_IXOTH
12754 int symbolic_mode = 0;
12756 while (nextopt("S") != '\0') {
12765 if ((ap = *argptr) == NULL) {
12766 if (symbolic_mode) {
12770 for (i = 0; i < 3; i++) {
12773 *p++ = permuser[i];
12775 for (j = 0; j < 3; j++) {
12776 if ((mask & permmask[3 * i + j]) == 0) {
12777 *p++ = permmode[j];
12785 out1fmt("%.4o\n", mask);
12788 if (is_digit((unsigned char) *ap)) {
12791 if (*ap >= '8' || *ap < '0')
12792 sh_error(illnum, argv[1]);
12793 mask = (mask << 3) + (*ap - '0');
12794 } while (*++ap != '\0');
12797 mask = ~mask & 0777;
12798 if (!bb_parse_mode(ap, &mask)) {
12799 sh_error("Illegal mode: %s", ap);
12801 umask(~mask & 0777);
12810 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12811 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12812 * ash by J.T. Conklin.
12820 int factor; /* multiply by to get rlim_{cur,max} values */
12824 static const struct limits limits[] = {
12826 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12828 #ifdef RLIMIT_FSIZE
12829 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12832 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12834 #ifdef RLIMIT_STACK
12835 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12838 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12841 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12843 #ifdef RLIMIT_MEMLOCK
12844 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12846 #ifdef RLIMIT_NPROC
12847 { "process", RLIMIT_NPROC, 1, 'p' },
12849 #ifdef RLIMIT_NOFILE
12850 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12853 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12855 #ifdef RLIMIT_LOCKS
12856 { "locks", RLIMIT_LOCKS, 1, 'w' },
12858 { (char *) 0, 0, 0, '\0' }
12861 enum limtype { SOFT = 0x1, HARD = 0x2 };
12863 static void printlim(enum limtype how, const struct rlimit *limit,
12864 const struct limits *l)
12868 val = limit->rlim_max;
12870 val = limit->rlim_cur;
12872 if (val == RLIM_INFINITY)
12873 out1fmt("unlimited\n");
12876 out1fmt("%lld\n", (long long) val);
12881 ulimitcmd(int argc, char **argv)
12885 enum limtype how = SOFT | HARD;
12886 const struct limits *l;
12889 struct rlimit limit;
12892 while ((optc = nextopt("HSa"
12896 #ifdef RLIMIT_FSIZE
12902 #ifdef RLIMIT_STACK
12911 #ifdef RLIMIT_MEMLOCK
12914 #ifdef RLIMIT_NPROC
12917 #ifdef RLIMIT_NOFILE
12923 #ifdef RLIMIT_LOCKS
12941 for (l = limits; l->option != what; l++)
12944 set = *argptr ? 1 : 0;
12948 if (all || argptr[1])
12949 sh_error("too many arguments");
12950 if (strncmp(p, "unlimited\n", 9) == 0)
12951 val = RLIM_INFINITY;
12955 while ((c = *p++) >= '0' && c <= '9')
12957 val = (val * 10) + (long)(c - '0');
12958 if (val < (rlim_t) 0)
12962 sh_error("bad number");
12967 for (l = limits; l->name; l++) {
12968 getrlimit(l->cmd, &limit);
12969 out1fmt("%-20s ", l->name);
12970 printlim(how, &limit, l);
12975 getrlimit(l->cmd, &limit);
12978 limit.rlim_max = val;
12980 limit.rlim_cur = val;
12981 if (setrlimit(l->cmd, &limit) < 0)
12982 sh_error("error setting limit (%m)");
12984 printlim(how, &limit, l);
12990 #ifdef CONFIG_ASH_MATH_SUPPORT
12992 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12994 Permission is hereby granted, free of charge, to any person obtaining
12995 a copy of this software and associated documentation files (the
12996 "Software"), to deal in the Software without restriction, including
12997 without limitation the rights to use, copy, modify, merge, publish,
12998 distribute, sublicense, and/or sell copies of the Software, and to
12999 permit persons to whom the Software is furnished to do so, subject to
13000 the following conditions:
13002 The above copyright notice and this permission notice shall be
13003 included in all copies or substantial portions of the Software.
13005 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13006 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13007 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13008 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13009 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13010 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13011 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13014 /* This is my infix parser/evaluator. It is optimized for size, intended
13015 * as a replacement for yacc-based parsers. However, it may well be faster
13016 * than a comparable parser written in yacc. The supported operators are
13017 * listed in #defines below. Parens, order of operations, and error handling
13018 * are supported. This code is thread safe. The exact expression format should
13019 * be that which POSIX specifies for shells. */
13021 /* The code uses a simple two-stack algorithm. See
13022 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13023 * for a detailed explanation of the infix-to-postfix algorithm on which
13024 * this is based (this code differs in that it applies operators immediately
13025 * to the stack instead of adding them to a queue to end up with an
13028 /* To use the routine, call it with an expression string and error return
13032 * Aug 24, 2001 Manuel Novoa III
13034 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13036 * 1) In arith_apply():
13037 * a) Cached values of *numptr and &(numptr[-1]).
13038 * b) Removed redundant test for zero denominator.
13041 * a) Eliminated redundant code for processing operator tokens by moving
13042 * to a table-based implementation. Also folded handling of parens
13044 * b) Combined all 3 loops which called arith_apply to reduce generated
13045 * code size at the cost of speed.
13047 * 3) The following expressions were treated as valid by the original code:
13048 * 1() , 0! , 1 ( *3 ) .
13049 * These bugs have been fixed by internally enclosing the expression in
13050 * parens and then checking that all binary ops and right parens are
13051 * preceded by a valid expression (NUM_TOKEN).
13053 * Note: It may be desirable to replace Aaron's test for whitespace with
13054 * ctype's isspace() if it is used by another busybox applet or if additional
13055 * whitespace chars should be considered. Look below the "#include"s for a
13056 * precompiler test.
13060 * Aug 26, 2001 Manuel Novoa III
13062 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13064 * Merge in Aaron's comments previously posted to the busybox list,
13065 * modified slightly to take account of my changes to the code.
13070 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13072 * - allow access to variable,
13073 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13074 * - realize assign syntax (VAR=expr, +=, *= etc)
13075 * - realize exponentiation (** operator)
13076 * - realize comma separated - expr, expr
13077 * - realise ++expr --expr expr++ expr--
13078 * - realise expr ? expr : expr (but, second expr calculate always)
13079 * - allow hexadecimal and octal numbers
13080 * - was restored loses XOR operator
13081 * - remove one goto label, added three ;-)
13082 * - protect $((num num)) as true zero expr (Manuel`s error)
13083 * - always use special isspace(), see comment from bash ;-)
13087 #define arith_isspace(arithval) \
13088 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13091 typedef unsigned char operator;
13093 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13094 * precedence, and 3 high bits are an ID unique across operators of that
13095 * precedence. The ID portion is so that multiple operators can have the
13096 * same precedence, ensuring that the leftmost one is evaluated first.
13097 * Consider * and /. */
13099 #define tok_decl(prec,id) (((id)<<5)|(prec))
13100 #define PREC(op) ((op) & 0x1F)
13102 #define TOK_LPAREN tok_decl(0,0)
13104 #define TOK_COMMA tok_decl(1,0)
13106 #define TOK_ASSIGN tok_decl(2,0)
13107 #define TOK_AND_ASSIGN tok_decl(2,1)
13108 #define TOK_OR_ASSIGN tok_decl(2,2)
13109 #define TOK_XOR_ASSIGN tok_decl(2,3)
13110 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13111 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13112 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13113 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13115 #define TOK_MUL_ASSIGN tok_decl(3,0)
13116 #define TOK_DIV_ASSIGN tok_decl(3,1)
13117 #define TOK_REM_ASSIGN tok_decl(3,2)
13119 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13120 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13122 /* conditional is right associativity too */
13123 #define TOK_CONDITIONAL tok_decl(4,0)
13124 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13126 #define TOK_OR tok_decl(5,0)
13128 #define TOK_AND tok_decl(6,0)
13130 #define TOK_BOR tok_decl(7,0)
13132 #define TOK_BXOR tok_decl(8,0)
13134 #define TOK_BAND tok_decl(9,0)
13136 #define TOK_EQ tok_decl(10,0)
13137 #define TOK_NE tok_decl(10,1)
13139 #define TOK_LT tok_decl(11,0)
13140 #define TOK_GT tok_decl(11,1)
13141 #define TOK_GE tok_decl(11,2)
13142 #define TOK_LE tok_decl(11,3)
13144 #define TOK_LSHIFT tok_decl(12,0)
13145 #define TOK_RSHIFT tok_decl(12,1)
13147 #define TOK_ADD tok_decl(13,0)
13148 #define TOK_SUB tok_decl(13,1)
13150 #define TOK_MUL tok_decl(14,0)
13151 #define TOK_DIV tok_decl(14,1)
13152 #define TOK_REM tok_decl(14,2)
13154 /* exponent is right associativity */
13155 #define TOK_EXPONENT tok_decl(15,1)
13157 /* For now unary operators. */
13158 #define UNARYPREC 16
13159 #define TOK_BNOT tok_decl(UNARYPREC,0)
13160 #define TOK_NOT tok_decl(UNARYPREC,1)
13162 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13163 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13165 #define PREC_PRE (UNARYPREC+2)
13167 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13168 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13170 #define PREC_POST (UNARYPREC+3)
13172 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13173 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13175 #define SPEC_PREC (UNARYPREC+4)
13177 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13178 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13180 #define NUMPTR (*numstackptr)
13182 static inline int tok_have_assign(operator op)
13184 operator prec = PREC(op);
13186 convert_prec_is_assing(prec);
13187 return (prec == PREC(TOK_ASSIGN) ||
13188 prec == PREC_PRE || prec == PREC_POST);
13191 static inline int is_right_associativity(operator prec)
13193 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13194 prec == PREC(TOK_CONDITIONAL));
13198 typedef struct ARITCH_VAR_NUM {
13200 arith_t contidional_second_val;
13201 char contidional_second_val_initialized;
13202 char *var; /* if NULL then is regular number,
13203 else is variable name */
13207 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13209 struct CHK_VAR_RECURSIVE_LOOPED *next;
13210 } chk_var_recursive_looped_t;
13212 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13215 static int arith_lookup_val(v_n_t *t)
13218 const char * p = lookupvar(t->var);
13223 /* recursive try as expression */
13224 chk_var_recursive_looped_t *cur;
13225 chk_var_recursive_looped_t cur_save;
13227 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13228 if(strcmp(cur->var, t->var) == 0) {
13229 /* expression recursion loop detected */
13233 /* save current lookuped var name */
13234 cur = prev_chk_var_recursive;
13235 cur_save.var = t->var;
13236 cur_save.next = cur;
13237 prev_chk_var_recursive = &cur_save;
13239 t->val = arith (p, &errcode);
13240 /* restore previous ptr after recursiving */
13241 prev_chk_var_recursive = cur;
13244 /* allow undefined var as 0 */
13251 /* "applying" a token means performing it on the top elements on the integer
13252 * stack. For a unary operator it will only change the top element, but a
13253 * binary operator will pop two arguments and push a result */
13255 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13258 arith_t numptr_val, rez;
13259 int ret_arith_lookup_val;
13261 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13262 without arguments */
13263 numptr_m1 = NUMPTR - 1;
13265 /* check operand is var with noninteger value */
13266 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13267 if(ret_arith_lookup_val)
13268 return ret_arith_lookup_val;
13270 rez = numptr_m1->val;
13271 if (op == TOK_UMINUS)
13273 else if (op == TOK_NOT)
13275 else if (op == TOK_BNOT)
13277 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13279 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13281 else if (op != TOK_UPLUS) {
13282 /* Binary operators */
13284 /* check and binary operators need two arguments */
13285 if (numptr_m1 == numstack) goto err;
13287 /* ... and they pop one */
13290 if (op == TOK_CONDITIONAL) {
13291 if(! numptr_m1->contidional_second_val_initialized) {
13292 /* protect $((expr1 ? expr2)) without ": expr" */
13295 rez = numptr_m1->contidional_second_val;
13296 } else if(numptr_m1->contidional_second_val_initialized) {
13297 /* protect $((expr1 : expr2)) without "expr ? " */
13300 numptr_m1 = NUMPTR - 1;
13301 if(op != TOK_ASSIGN) {
13302 /* check operand is var with noninteger value for not '=' */
13303 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13304 if(ret_arith_lookup_val)
13305 return ret_arith_lookup_val;
13307 if (op == TOK_CONDITIONAL) {
13308 numptr_m1->contidional_second_val = rez;
13310 rez = numptr_m1->val;
13311 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13313 else if (op == TOK_OR)
13314 rez = numptr_val || rez;
13315 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13317 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13319 else if (op == TOK_AND)
13320 rez = rez && numptr_val;
13321 else if (op == TOK_EQ)
13322 rez = (rez == numptr_val);
13323 else if (op == TOK_NE)
13324 rez = (rez != numptr_val);
13325 else if (op == TOK_GE)
13326 rez = (rez >= numptr_val);
13327 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13328 rez >>= numptr_val;
13329 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13330 rez <<= numptr_val;
13331 else if (op == TOK_GT)
13332 rez = (rez > numptr_val);
13333 else if (op == TOK_LT)
13334 rez = (rez < numptr_val);
13335 else if (op == TOK_LE)
13336 rez = (rez <= numptr_val);
13337 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13339 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13341 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13343 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13345 else if (op == TOK_CONDITIONAL_SEP) {
13346 if (numptr_m1 == numstack) {
13347 /* protect $((expr : expr)) without "expr ? " */
13350 numptr_m1->contidional_second_val_initialized = op;
13351 numptr_m1->contidional_second_val = numptr_val;
13353 else if (op == TOK_CONDITIONAL) {
13355 numptr_val : numptr_m1->contidional_second_val;
13357 else if(op == TOK_EXPONENT) {
13359 return -3; /* exponent less than 0 */
13364 while(numptr_val--)
13369 else if(numptr_val==0) /* zero divisor check */
13371 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13373 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13376 if(tok_have_assign(op)) {
13379 if(numptr_m1->var == NULL) {
13383 /* save to shell variable */
13384 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13385 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13387 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13389 setvar(numptr_m1->var, buf, 0);
13390 /* after saving, make previous value for v++ or v-- */
13391 if(op == TOK_POST_INC)
13393 else if(op == TOK_POST_DEC)
13396 numptr_m1->val = rez;
13397 /* protect geting var value, is number now */
13398 numptr_m1->var = NULL;
13403 /* longest must first */
13404 static const char op_tokens[] = {
13405 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13406 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13407 '<','<', 0, TOK_LSHIFT,
13408 '>','>', 0, TOK_RSHIFT,
13409 '|','|', 0, TOK_OR,
13410 '&','&', 0, TOK_AND,
13411 '!','=', 0, TOK_NE,
13412 '<','=', 0, TOK_LE,
13413 '>','=', 0, TOK_GE,
13414 '=','=', 0, TOK_EQ,
13415 '|','=', 0, TOK_OR_ASSIGN,
13416 '&','=', 0, TOK_AND_ASSIGN,
13417 '*','=', 0, TOK_MUL_ASSIGN,
13418 '/','=', 0, TOK_DIV_ASSIGN,
13419 '%','=', 0, TOK_REM_ASSIGN,
13420 '+','=', 0, TOK_PLUS_ASSIGN,
13421 '-','=', 0, TOK_MINUS_ASSIGN,
13422 '-','-', 0, TOK_POST_DEC,
13423 '^','=', 0, TOK_XOR_ASSIGN,
13424 '+','+', 0, TOK_POST_INC,
13425 '*','*', 0, TOK_EXPONENT,
13429 '=', 0, TOK_ASSIGN,
13441 '?', 0, TOK_CONDITIONAL,
13442 ':', 0, TOK_CONDITIONAL_SEP,
13443 ')', 0, TOK_RPAREN,
13444 '(', 0, TOK_LPAREN,
13448 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13451 static arith_t arith (const char *expr, int *perrcode)
13453 register char arithval; /* Current character under analysis */
13454 operator lasttok, op;
13457 const char *p = endexpression;
13460 size_t datasizes = strlen(expr) + 2;
13462 /* Stack of integers */
13463 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13464 * in any given correct or incorrect expression is left as an exercise to
13466 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13467 *numstackptr = numstack;
13468 /* Stack of operator tokens */
13469 operator *stack = alloca((datasizes) * sizeof(operator)),
13472 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13473 *perrcode = errcode = 0;
13476 if ((arithval = *expr) == 0) {
13477 if (p == endexpression) {
13478 /* Null expression. */
13482 /* This is only reached after all tokens have been extracted from the
13483 * input stream. If there are still tokens on the operator stack, they
13484 * are to be applied in order. At the end, there should be a final
13485 * result on the integer stack */
13487 if (expr != endexpression + 1) {
13488 /* If we haven't done so already, */
13489 /* append a closing right paren */
13490 expr = endexpression;
13491 /* and let the loop process it. */
13494 /* At this point, we're done with the expression. */
13495 if (numstackptr != numstack+1) {
13496 /* ... but if there isn't, it's bad */
13498 return (*perrcode = -1);
13500 if(numstack->var) {
13501 /* expression is $((var)) only, lookup now */
13502 errcode = arith_lookup_val(numstack);
13505 *perrcode = errcode;
13506 return numstack->val;
13508 /* Continue processing the expression. */
13509 if (arith_isspace(arithval)) {
13510 /* Skip whitespace */
13513 if((p = endofname(expr)) != expr) {
13514 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13516 numstackptr->var = alloca(var_name_size);
13517 safe_strncpy(numstackptr->var, expr, var_name_size);
13520 numstackptr->contidional_second_val_initialized = 0;
13524 } else if (is_digit(arithval)) {
13525 numstackptr->var = NULL;
13526 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13527 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13529 numstackptr->val = strtol(expr, (char **) &expr, 0);
13533 for(p = op_tokens; ; p++) {
13537 /* strange operator not found */
13540 for(o = expr; *p && *o == *p; p++)
13547 /* skip tail uncompared token */
13550 /* skip zero delim */
13555 /* post grammar: a++ reduce to num */
13556 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13559 /* Plus and minus are binary (not unary) _only_ if the last
13560 * token was as number, or a right paren (which pretends to be
13561 * a number, since it evaluates to one). Think about it.
13562 * It makes sense. */
13563 if (lasttok != TOK_NUM) {
13579 /* We don't want a unary operator to cause recursive descent on the
13580 * stack, because there can be many in a row and it could cause an
13581 * operator to be evaluated before its argument is pushed onto the
13582 * integer stack. */
13583 /* But for binary operators, "apply" everything on the operator
13584 * stack until we find an operator with a lesser priority than the
13585 * one we have just extracted. */
13586 /* Left paren is given the lowest priority so it will never be
13587 * "applied" in this way.
13588 * if associativity is right and priority eq, applied also skip
13591 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13592 /* not left paren or unary */
13593 if (lasttok != TOK_NUM) {
13594 /* binary op must be preceded by a num */
13597 while (stackptr != stack) {
13598 if (op == TOK_RPAREN) {
13599 /* The algorithm employed here is simple: while we don't
13600 * hit an open paren nor the bottom of the stack, pop
13601 * tokens and apply them */
13602 if (stackptr[-1] == TOK_LPAREN) {
13604 /* Any operator directly after a */
13606 /* close paren should consider itself binary */
13610 operator prev_prec = PREC(stackptr[-1]);
13612 convert_prec_is_assing(prec);
13613 convert_prec_is_assing(prev_prec);
13614 if (prev_prec < prec)
13616 /* check right assoc */
13617 if(prev_prec == prec && is_right_associativity(prec))
13620 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13621 if(errcode) goto ret;
13623 if (op == TOK_RPAREN) {
13628 /* Push this operator to the stack and remember it. */
13629 *stackptr++ = lasttok = op;
13636 #endif /* CONFIG_ASH_MATH_SUPPORT */
13640 const char *bb_applet_name = "debug stuff usage";
13641 int main(int argc, char **argv)
13643 return ash_main(argc, argv);
13648 * Copyright (c) 1989, 1991, 1993, 1994
13649 * The Regents of the University of California. All rights reserved.
13651 * This code is derived from software contributed to Berkeley by
13652 * Kenneth Almquist.
13654 * Redistribution and use in source and binary forms, with or without
13655 * modification, are permitted provided that the following conditions
13657 * 1. Redistributions of source code must retain the above copyright
13658 * notice, this list of conditions and the following disclaimer.
13659 * 2. Redistributions in binary form must reproduce the above copyright
13660 * notice, this list of conditions and the following disclaimer in the
13661 * documentation and/or other materials provided with the distribution.
13662 * 3. Neither the name of the University nor the names of its contributors
13663 * may be used to endorse or promote products derived from this software
13664 * without specific prior written permission.
13666 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13667 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13668 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13669 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13670 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13671 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13672 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13673 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13674 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13675 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF