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 #ifdef CONFIG_ASH_BUILTIN_TEST
1229 static int testcmd(int, char **);
1231 static int execcmd(int, char **);
1232 static int exitcmd(int, char **);
1233 static int exportcmd(int, char **);
1234 static int falsecmd(int, char **);
1236 static int fgcmd(int, char **);
1238 #ifdef CONFIG_ASH_GETOPTS
1239 static int getoptscmd(int, char **);
1241 static int hashcmd(int, char **);
1242 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1243 static int helpcmd(int argc, char **argv);
1246 static int jobscmd(int, char **);
1248 #ifdef CONFIG_ASH_MATH_SUPPORT
1249 static int letcmd(int, char **);
1251 static int localcmd(int, char **);
1252 static int pwdcmd(int, char **);
1253 static int readcmd(int, char **);
1254 static int returncmd(int, char **);
1255 static int setcmd(int, char **);
1256 static int shiftcmd(int, char **);
1257 static int timescmd(int, char **);
1258 static int trapcmd(int, char **);
1259 static int truecmd(int, char **);
1260 static int typecmd(int, char **);
1261 static int umaskcmd(int, char **);
1262 static int unsetcmd(int, char **);
1263 static int waitcmd(int, char **);
1264 static int ulimitcmd(int, char **);
1266 static int killcmd(int, char **);
1271 #ifdef CONFIG_ASH_MAIL
1272 static void chkmail(void);
1273 static void changemail(const char *);
1278 /* values of cmdtype */
1279 #define CMDUNKNOWN -1 /* no entry in table for command */
1280 #define CMDNORMAL 0 /* command is an executable program */
1281 #define CMDFUNCTION 1 /* command is a shell function */
1282 #define CMDBUILTIN 2 /* command is a shell builtin */
1286 int (*builtin)(int, char **);
1287 /* unsigned flags; */
1291 #define COMMANDCMD (builtincmd + 5 + \
1292 2 * ENABLE_ASH_BUILTIN_TEST + \
1293 ENABLE_ASH_ALIAS + \
1294 ENABLE_ASH_JOB_CONTROL)
1295 #define EXECCMD (builtincmd + 7 + \
1296 2 * ENABLE_ASH_BUILTIN_TEST + \
1297 ENABLE_ASH_ALIAS + \
1298 ENABLE_ASH_JOB_CONTROL + \
1299 ENABLE_ASH_CMDCMD + \
1300 ENABLE_ASH_BUILTIN_ECHO)
1302 #define BUILTIN_NOSPEC "0"
1303 #define BUILTIN_SPECIAL "1"
1304 #define BUILTIN_REGULAR "2"
1305 #define BUILTIN_SPEC_REG "3"
1306 #define BUILTIN_ASSIGN "4"
1307 #define BUILTIN_SPEC_ASSG "5"
1308 #define BUILTIN_REG_ASSG "6"
1309 #define BUILTIN_SPEC_REG_ASSG "7"
1311 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1312 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1313 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1315 static const struct builtincmd builtincmd[] = {
1316 { BUILTIN_SPEC_REG ".", dotcmd },
1317 { BUILTIN_SPEC_REG ":", truecmd },
1318 #ifdef CONFIG_ASH_BUILTIN_TEST
1319 { BUILTIN_REGULAR "[", testcmd },
1320 { BUILTIN_REGULAR "[[", testcmd },
1322 #ifdef CONFIG_ASH_ALIAS
1323 { BUILTIN_REG_ASSG "alias", aliascmd },
1326 { BUILTIN_REGULAR "bg", bgcmd },
1328 { BUILTIN_SPEC_REG "break", breakcmd },
1329 { BUILTIN_REGULAR "cd", cdcmd },
1330 { BUILTIN_NOSPEC "chdir", cdcmd },
1331 #ifdef CONFIG_ASH_CMDCMD
1332 { BUILTIN_REGULAR "command", commandcmd },
1334 { BUILTIN_SPEC_REG "continue", breakcmd },
1335 #ifdef CONFIG_ASH_BUILTIN_ECHO
1336 { BUILTIN_REGULAR "echo", echocmd },
1338 { BUILTIN_SPEC_REG "eval", evalcmd },
1339 { BUILTIN_SPEC_REG "exec", execcmd },
1340 { BUILTIN_SPEC_REG "exit", exitcmd },
1341 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1342 { BUILTIN_REGULAR "false", falsecmd },
1344 { BUILTIN_REGULAR "fg", fgcmd },
1346 #ifdef CONFIG_ASH_GETOPTS
1347 { BUILTIN_REGULAR "getopts", getoptscmd },
1349 { BUILTIN_NOSPEC "hash", hashcmd },
1350 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1351 { BUILTIN_NOSPEC "help", helpcmd },
1354 { BUILTIN_REGULAR "jobs", jobscmd },
1355 { BUILTIN_REGULAR "kill", killcmd },
1357 #ifdef CONFIG_ASH_MATH_SUPPORT
1358 { BUILTIN_NOSPEC "let", letcmd },
1360 { BUILTIN_ASSIGN "local", localcmd },
1361 { BUILTIN_NOSPEC "pwd", pwdcmd },
1362 { BUILTIN_REGULAR "read", readcmd },
1363 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1364 { BUILTIN_SPEC_REG "return", returncmd },
1365 { BUILTIN_SPEC_REG "set", setcmd },
1366 { BUILTIN_SPEC_REG "source", dotcmd },
1367 { BUILTIN_SPEC_REG "shift", shiftcmd },
1368 #ifdef CONFIG_ASH_BUILTIN_TEST
1369 { BUILTIN_REGULAR "test", testcmd },
1371 { BUILTIN_SPEC_REG "times", timescmd },
1372 { BUILTIN_SPEC_REG "trap", trapcmd },
1373 { BUILTIN_REGULAR "true", truecmd },
1374 { BUILTIN_NOSPEC "type", typecmd },
1375 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1376 { BUILTIN_REGULAR "umask", umaskcmd },
1377 #ifdef CONFIG_ASH_ALIAS
1378 { BUILTIN_REGULAR "unalias", unaliascmd },
1380 { BUILTIN_SPEC_REG "unset", unsetcmd },
1381 { BUILTIN_REGULAR "wait", waitcmd },
1384 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1392 const struct builtincmd *cmd;
1393 struct funcnode *func;
1398 /* action to find_command() */
1399 #define DO_ERR 0x01 /* prints errors */
1400 #define DO_ABS 0x02 /* checks absolute paths */
1401 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1402 #define DO_ALTPATH 0x08 /* using alternate path */
1403 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1405 static const char *pathopt; /* set by padvance */
1407 static void shellexec(char **, const char *, int)
1409 static char *padvance(const char **, const char *);
1410 static void find_command(char *, struct cmdentry *, int, const char *);
1411 static struct builtincmd *find_builtin(const char *);
1412 static void hashcd(void);
1413 static void changepath(const char *);
1414 static void defun(char *, union node *);
1415 static void unsetfunc(const char *);
1417 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1418 typedef int64_t arith_t;
1419 #define arith_t_type (long long)
1421 typedef long arith_t;
1422 #define arith_t_type (long)
1425 #ifdef CONFIG_ASH_MATH_SUPPORT
1426 static arith_t dash_arith(const char *);
1427 static arith_t arith(const char *expr, int *perrcode);
1430 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1431 static unsigned long rseed;
1432 static void change_random(const char *);
1433 # ifndef DYNAMIC_VAR
1434 # define DYNAMIC_VAR
1440 static void reset(void);
1449 #define VEXPORT 0x01 /* variable is exported */
1450 #define VREADONLY 0x02 /* variable cannot be modified */
1451 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1452 #define VTEXTFIXED 0x08 /* text is statically allocated */
1453 #define VSTACK 0x10 /* text is allocated on the stack */
1454 #define VUNSET 0x20 /* the variable is not set */
1455 #define VNOFUNC 0x40 /* don't call the callback function */
1456 #define VNOSET 0x80 /* do not set variable - just readonly test */
1457 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1459 # define VDYNAMIC 0x200 /* dynamic variable */
1465 struct var *next; /* next entry in hash list */
1466 int flags; /* flags are defined above */
1467 const char *text; /* name=value */
1468 void (*func)(const char *); /* function to be called when */
1469 /* the variable gets set/unset */
1473 struct localvar *next; /* next local variable in list */
1474 struct var *vp; /* the variable that was made local */
1475 int flags; /* saved flags */
1476 const char *text; /* saved text */
1480 static struct localvar *localvars;
1486 #ifdef CONFIG_ASH_GETOPTS
1487 static void getoptsreset(const char *);
1490 #ifdef CONFIG_LOCALE_SUPPORT
1492 static void change_lc_all(const char *value);
1493 static void change_lc_ctype(const char *value);
1499 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1501 static const char defifsvar[] = "IFS= \t\n";
1502 #define defifs (defifsvar + 4)
1504 static const char defifs[] = " \t\n";
1508 static struct var varinit[] = {
1510 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1512 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1515 #ifdef CONFIG_ASH_MAIL
1516 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1517 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1520 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1521 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1522 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1523 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1524 #ifdef CONFIG_ASH_GETOPTS
1525 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1527 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1528 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1530 #ifdef CONFIG_LOCALE_SUPPORT
1531 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1532 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1534 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1535 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1539 #define vifs varinit[0]
1540 #ifdef CONFIG_ASH_MAIL
1541 #define vmail (&vifs)[1]
1542 #define vmpath (&vmail)[1]
1546 #define vpath (&vmpath)[1]
1547 #define vps1 (&vpath)[1]
1548 #define vps2 (&vps1)[1]
1549 #define vps4 (&vps2)[1]
1550 #define voptind (&vps4)[1]
1551 #ifdef CONFIG_ASH_GETOPTS
1552 #define vrandom (&voptind)[1]
1554 #define vrandom (&vps4)[1]
1556 #define defpath (defpathvar + 5)
1559 * The following macros access the values of the above variables.
1560 * They have to skip over the name. They return the null string
1561 * for unset variables.
1564 #define ifsval() (vifs.text + 4)
1565 #define ifsset() ((vifs.flags & VUNSET) == 0)
1566 #define mailval() (vmail.text + 5)
1567 #define mpathval() (vmpath.text + 9)
1568 #define pathval() (vpath.text + 5)
1569 #define ps1val() (vps1.text + 4)
1570 #define ps2val() (vps2.text + 4)
1571 #define ps4val() (vps4.text + 4)
1572 #define optindval() (voptind.text + 7)
1574 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1576 static void setvar(const char *, const char *, int);
1577 static void setvareq(char *, int);
1578 static void listsetvar(struct strlist *, int);
1579 static char *lookupvar(const char *);
1580 static char *bltinlookup(const char *);
1581 static char **listvars(int, int, char ***);
1582 #define environment() listvars(VEXPORT, VUNSET, 0)
1583 static int showvars(const char *, int, int);
1584 static void poplocalvars(void);
1585 static int unsetvar(const char *);
1586 #ifdef CONFIG_ASH_GETOPTS
1587 static int setvarsafe(const char *, const char *, int);
1589 static int varcmp(const char *, const char *);
1590 static struct var **hashvar(const char *);
1593 static inline int varequal(const char *a, const char *b) {
1594 return !varcmp(a, b);
1598 static int loopnest; /* current loop nesting level */
1601 * The parsefile structure pointed to by the global variable parsefile
1602 * contains information about the current file being read.
1607 struct redirtab *next;
1612 static struct redirtab *redirlist;
1613 static int nullredirs;
1615 extern char **environ;
1620 static void outstr(const char *, FILE *);
1621 static void outcslow(int, FILE *);
1622 static void flushall(void);
1623 static void flusherr(void);
1624 static int out1fmt(const char *, ...)
1625 __attribute__((__format__(__printf__,1,2)));
1626 static int fmtstr(char *, size_t, const char *, ...)
1627 __attribute__((__format__(__printf__,3,4)));
1629 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1632 static void out1str(const char *p)
1637 static void out2str(const char *p)
1644 * Initialization code.
1648 * This routine initializes the builtin variables.
1659 * PS1 depends on uid
1661 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1662 vps1.text = "PS1=\\w \\$ ";
1665 vps1.text = "PS1=# ";
1668 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1670 vpp = hashvar(vp->text);
1673 } while (++vp < end);
1682 basepf.nextc = basepf.buf = basebuf;
1687 signal(SIGCHLD, SIG_DFL);
1695 struct stat st1, st2;
1698 for (envp = environ ; envp && *envp ; envp++) {
1699 if (strchr(*envp, '=')) {
1700 setvareq(*envp, VEXPORT|VTEXTFIXED);
1704 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1705 setvar("PPID", ppid, 0);
1707 p = lookupvar("PWD");
1709 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1710 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1716 /* PEOF (the end of file marker) */
1719 INPUT_PUSH_FILE = 1,
1720 INPUT_NOFILE_OK = 2,
1724 * The input line number. Input.c just defines this variable, and saves
1725 * and restores it when files are pushed and popped. The user of this
1726 * package must set its value.
1729 static int pgetc(void);
1730 static int pgetc2(void);
1731 static int preadbuffer(void);
1732 static void pungetc(void);
1733 static void pushstring(char *, void *);
1734 static void popstring(void);
1735 static void setinputfd(int, int);
1736 static void setinputstring(char *);
1737 static void popfile(void);
1738 static void popallfiles(void);
1739 static void closescript(void);
1745 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1748 #define FORK_NOJOB 2
1750 /* mode flags for showjob(s) */
1751 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1752 #define SHOW_PID 0x04 /* include process pid */
1753 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1757 * A job structure contains information about a job. A job is either a
1758 * single process or a set of processes contained in a pipeline. In the
1759 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1764 pid_t pid; /* process id */
1765 int status; /* last process status from wait() */
1766 char *cmd; /* text of command being run */
1770 struct procstat ps0; /* status of process */
1771 struct procstat *ps; /* status or processes when more than one */
1773 int stopstatus; /* status of a stopped job */
1776 nprocs: 16, /* number of processes */
1778 #define JOBRUNNING 0 /* at least one proc running */
1779 #define JOBSTOPPED 1 /* all procs are stopped */
1780 #define JOBDONE 2 /* all procs are completed */
1782 sigint: 1, /* job was killed by SIGINT */
1783 jobctl: 1, /* job running under job control */
1785 waited: 1, /* true if this entry has been waited for */
1786 used: 1, /* true if this entry is in used */
1787 changed: 1; /* true if status has changed */
1788 struct job *prev_job; /* previous job */
1791 static pid_t backgndpid; /* pid of last background process */
1792 static int job_warning; /* user was warned about stopped jobs */
1794 static int jobctl; /* true if doing job control */
1797 static struct job *makejob(union node *, int);
1798 static int forkshell(struct job *, union node *, int);
1799 static int waitforjob(struct job *);
1800 static int stoppedjobs(void);
1803 #define setjobctl(on) /* do nothing */
1805 static void setjobctl(int);
1806 static void showjobs(FILE *, int);
1812 /* pid of main shell */
1814 /* shell level: 0 for the main shell, 1 for its children, and so on */
1816 #define rootshell (!shlvl)
1818 static void readcmdfile(char *);
1819 static int cmdloop(int);
1825 struct stack_block *stackp;
1828 struct stackmark *marknext;
1831 /* minimum size of a block */
1832 #define MINSIZE SHELL_ALIGN(504)
1834 struct stack_block {
1835 struct stack_block *prev;
1836 char space[MINSIZE];
1839 static struct stack_block stackbase;
1840 static struct stack_block *stackp = &stackbase;
1841 static struct stackmark *markp;
1842 static char *stacknxt = stackbase.space;
1843 static size_t stacknleft = MINSIZE;
1844 static char *sstrend = stackbase.space + MINSIZE;
1845 static int herefd = -1;
1848 static pointer ckmalloc(size_t);
1849 static pointer ckrealloc(pointer, size_t);
1850 static char *savestr(const char *);
1851 static pointer stalloc(size_t);
1852 static void stunalloc(pointer);
1853 static void setstackmark(struct stackmark *);
1854 static void popstackmark(struct stackmark *);
1855 static void growstackblock(void);
1856 static void *growstackstr(void);
1857 static char *makestrspace(size_t, char *);
1858 static char *stnputs(const char *, size_t, char *);
1859 static char *stputs(const char *, char *);
1862 static inline char *_STPUTC(int c, char *p) {
1869 #define stackblock() ((void *)stacknxt)
1870 #define stackblocksize() stacknleft
1871 #define STARTSTACKSTR(p) ((p) = stackblock())
1872 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1873 #define CHECKSTRSPACE(n, p) \
1877 size_t m = sstrend - q; \
1879 (p) = makestrspace(l, q); \
1882 #define USTPUTC(c, p) (*p++ = (c))
1883 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1884 #define STUNPUTC(p) (--p)
1885 #define STTOPC(p) p[-1]
1886 #define STADJUST(amount, p) (p += (amount))
1888 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1889 #define ungrabstackstr(s, p) stunalloc((s))
1890 #define stackstrend() ((void *)sstrend)
1892 #define ckfree(p) free((pointer)(p))
1897 #define DOLATSTRLEN 4
1899 static char *prefix(const char *, const char *);
1900 static int number(const char *);
1901 static int is_number(const char *);
1902 static char *single_quote(const char *);
1903 static char *sstrdup(const char *);
1905 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1906 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1911 int nparam; /* # of positional parameters (without $0) */
1912 unsigned char malloc; /* if parameter list dynamically allocated */
1913 char **p; /* parameter list */
1914 #ifdef CONFIG_ASH_GETOPTS
1915 int optind; /* next parameter to be processed by getopts */
1916 int optoff; /* used by getopts */
1921 #define eflag optlist[0]
1922 #define fflag optlist[1]
1923 #define Iflag optlist[2]
1924 #define iflag optlist[3]
1925 #define mflag optlist[4]
1926 #define nflag optlist[5]
1927 #define sflag optlist[6]
1928 #define xflag optlist[7]
1929 #define vflag optlist[8]
1930 #define Cflag optlist[9]
1931 #define aflag optlist[10]
1932 #define bflag optlist[11]
1933 #define uflag optlist[12]
1934 #define viflag optlist[13]
1937 #define nolog optlist[14]
1938 #define debug optlist[15]
1941 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1942 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1948 static const char *const optletters_optnames[] = {
1969 #define optletters(n) optletters_optnames[(n)][0]
1970 #define optnames(n) (&optletters_optnames[(n)][1])
1972 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1974 static char optlist[NOPTS];
1977 static char *arg0; /* value of $0 */
1978 static struct shparam shellparam; /* $@ current positional parameters */
1979 static char **argptr; /* argument list for builtin commands */
1980 static char *optionarg; /* set by nextopt (like getopt) */
1981 static char *optptr; /* used by nextopt */
1983 static char *minusc; /* argument to -c option */
1986 static void procargs(int, char **);
1987 static void optschanged(void);
1988 static void setparam(char **);
1989 static void freeparam(volatile struct shparam *);
1990 static int shiftcmd(int, char **);
1991 static int setcmd(int, char **);
1992 static int nextopt(const char *);
1996 /* flags passed to redirect */
1997 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1998 #define REDIR_SAVEFD2 03 /* set preverrout */
2001 static void redirect(union node *, int);
2002 static void popredir(int);
2003 static void clearredir(int);
2004 static int copyfd(int, int);
2005 static int redirectsafe(union node *, int);
2011 static void showtree(union node *);
2012 static void trace(const char *, ...);
2013 static void tracev(const char *, va_list);
2014 static void trargs(char **);
2015 static void trputc(int);
2016 static void trputs(const char *);
2017 static void opentrace(void);
2023 /* trap handler commands */
2024 static char *trap[NSIG];
2025 /* current value of signal */
2026 static char sigmode[NSIG - 1];
2027 /* indicates specified signal received */
2028 static char gotsig[NSIG - 1];
2030 static void clear_traps(void);
2031 static void setsignal(int);
2032 static void ignoresig(int);
2033 static void onsig(int);
2034 static int dotrap(void);
2035 static void setinteractive(int);
2036 static void exitshell(void) ATTRIBUTE_NORETURN;
2037 static int decode_signal(const char *, int);
2040 * This routine is called when an error or an interrupt occurs in an
2041 * interactive shell and control is returned to the main command loop.
2055 parselleft = parsenleft = 0; /* clear input buffer */
2059 /* from parser.c: */
2072 #ifdef CONFIG_ASH_ALIAS
2073 static struct alias *atab[ATABSIZE];
2075 static void setalias(const char *, const char *);
2076 static struct alias *freealias(struct alias *);
2077 static struct alias **__lookupalias(const char *);
2080 setalias(const char *name, const char *val)
2082 struct alias *ap, **app;
2084 app = __lookupalias(name);
2088 if (!(ap->flag & ALIASINUSE)) {
2091 ap->val = savestr(val);
2092 ap->flag &= ~ALIASDEAD;
2095 ap = ckmalloc(sizeof (struct alias));
2096 ap->name = savestr(name);
2097 ap->val = savestr(val);
2106 unalias(const char *name)
2110 app = __lookupalias(name);
2114 *app = freealias(*app);
2125 struct alias *ap, **app;
2129 for (i = 0; i < ATABSIZE; i++) {
2131 for (ap = *app; ap; ap = *app) {
2132 *app = freealias(*app);
2141 static struct alias *
2142 lookupalias(const char *name, int check)
2144 struct alias *ap = *__lookupalias(name);
2146 if (check && ap && (ap->flag & ALIASINUSE))
2152 * TODO - sort output
2155 aliascmd(int argc, char **argv)
2164 for (i = 0; i < ATABSIZE; i++)
2165 for (ap = atab[i]; ap; ap = ap->next) {
2170 while ((n = *++argv) != NULL) {
2171 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2172 if ((ap = *__lookupalias(n)) == NULL) {
2173 fprintf(stderr, "%s: %s not found\n", "alias", n);
2187 unaliascmd(int argc, char **argv)
2191 while ((i = nextopt("a")) != '\0') {
2197 for (i = 0; *argptr; argptr++) {
2198 if (unalias(*argptr)) {
2199 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2207 static struct alias *
2208 freealias(struct alias *ap) {
2211 if (ap->flag & ALIASINUSE) {
2212 ap->flag |= ALIASDEAD;
2224 printalias(const struct alias *ap) {
2225 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2228 static struct alias **
2229 __lookupalias(const char *name) {
2230 unsigned int hashval;
2237 ch = (unsigned char)*p;
2241 ch = (unsigned char)*++p;
2243 app = &atab[hashval % ATABSIZE];
2245 for (; *app; app = &(*app)->next) {
2246 if (equal(name, (*app)->name)) {
2253 #endif /* CONFIG_ASH_ALIAS */
2259 * The cd and pwd commands.
2262 #define CD_PHYSICAL 1
2265 static int docd(const char *, int);
2266 static int cdopt(void);
2268 static char *curdir = nullstr; /* current working directory */
2269 static char *physdir = nullstr; /* physical working directory */
2278 while ((i = nextopt("LP"))) {
2280 flags ^= CD_PHYSICAL;
2289 cdcmd(int argc, char **argv)
2301 dest = bltinlookup(homestr);
2302 else if (dest[0] == '-' && dest[1] == '\0') {
2303 dest = bltinlookup("OLDPWD");
2325 if (!(path = bltinlookup("CDPATH"))) {
2333 p = padvance(&path, dest);
2334 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2338 if (!docd(p, flags))
2343 sh_error("can't cd to %s", dest);
2346 if (flags & CD_PRINT)
2347 out1fmt(snlfmt, curdir);
2353 * Update curdir (the name of the current directory) in response to a
2357 static inline const char *
2358 updatepwd(const char *dir)
2365 cdcomppath = sstrdup(dir);
2368 if (curdir == nullstr)
2370 new = stputs(curdir, new);
2372 new = makestrspace(strlen(dir) + 2, new);
2373 lim = stackblock() + 1;
2377 if (new > lim && *lim == '/')
2382 if (dir[1] == '/' && dir[2] != '/') {
2388 p = strtok(cdcomppath, "/");
2392 if (p[1] == '.' && p[2] == '\0') {
2399 } else if (p[1] == '\0')
2403 new = stputs(p, new);
2411 return stackblock();
2415 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2416 * know that the current directory has changed.
2420 docd(const char *dest, int flags)
2422 const char *dir = 0;
2425 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2428 if (!(flags & CD_PHYSICAL)) {
2429 dir = updatepwd(dest);
2444 * Find out what the current directory is. If we already know the current
2445 * directory, this routine returns immediately.
2447 static inline char *
2450 char *dir = getcwd(0, 0);
2451 return dir ? dir : nullstr;
2455 pwdcmd(int argc, char **argv)
2458 const char *dir = curdir;
2462 if (physdir == nullstr)
2466 out1fmt(snlfmt, dir);
2471 setpwd(const char *val, int setold)
2475 oldcur = dir = curdir;
2478 setvar("OLDPWD", oldcur, VEXPORT);
2481 if (physdir != nullstr) {
2482 if (physdir != oldcur)
2486 if (oldcur == val || !val) {
2493 if (oldcur != dir && oldcur != nullstr) {
2498 setvar("PWD", dir, VEXPORT);
2504 * Errors and exceptions.
2508 * Code to handle exceptions in C.
2513 static void exverror(int, const char *, va_list)
2517 * Called to raise an exception. Since C doesn't include exceptions, we
2518 * just do a longjmp to the exception handler. The type of exception is
2519 * stored in the global variable "exception".
2526 if (handler == NULL)
2532 longjmp(handler->loc, 1);
2537 * Called from trap.c when a SIGINT is received. (If the user specifies
2538 * that SIGINT is to be trapped or ignored using the trap builtin, then
2539 * this routine is not called.) Suppressint is nonzero when interrupts
2540 * are held using the INTOFF macro. (The test for iflag is just
2541 * defensive programming.)
2550 /* comment by vodz: its strange for me, this programm don`t use other
2555 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2556 if (!(rootshell && iflag)) {
2557 signal(SIGINT, SIG_DFL);
2567 exvwarning(const char *msg, va_list ap)
2572 fprintf(errs, "%s: ", arg0);
2574 const char *fmt = (!iflag || parsefile->fd) ?
2575 "%s: %d: " : "%s: ";
2576 fprintf(errs, fmt, commandname, startlinno);
2578 vfprintf(errs, msg, ap);
2579 outcslow('\n', errs);
2583 * Exverror is called to raise the error exception. If the second argument
2584 * is not NULL then error prints an error message using printf style
2585 * formatting. It then raises the error exception.
2588 exverror(int cond, const char *msg, va_list ap)
2592 TRACE(("exverror(%d, \"", cond));
2594 TRACE(("\") pid=%d\n", getpid()));
2596 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2599 exvwarning(msg, ap);
2608 sh_error(const char *msg, ...)
2613 exverror(EXERROR, msg, ap);
2620 exerror(int cond, const char *msg, ...)
2625 exverror(cond, msg, ap);
2631 * error/warning routines for external builtins
2635 sh_warnx(const char *fmt, ...)
2640 exvwarning(fmt, ap);
2646 * Return a string describing an error. The returned string may be a
2647 * pointer to a static buffer that will be overwritten on the next call.
2648 * Action describes the operation that got the error.
2652 errmsg(int e, const char *em)
2654 if(e == ENOENT || e == ENOTDIR) {
2665 * Evaluate a command.
2668 /* flags in argument to evaltree */
2669 #define EV_EXIT 01 /* exit after evaluating tree */
2670 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2671 #define EV_BACKCMD 04 /* command executing within back quotes */
2674 static void evalloop(union node *, int);
2675 static void evalfor(union node *, int);
2676 static void evalcase(union node *, int);
2677 static void evalsubshell(union node *, int);
2678 static void expredir(union node *);
2679 static void evalpipe(union node *, int);
2680 static void evalcommand(union node *, int);
2681 static int evalbltin(const struct builtincmd *, int, char **);
2682 static int evalfun(struct funcnode *, int, char **, int);
2683 static void prehash(union node *);
2684 static int bltincmd(int, char **);
2687 static const struct builtincmd bltin = {
2693 * Called to reset things after an exception.
2701 evalcmd(int argc, char **argv)
2710 STARTSTACKSTR(concat);
2713 concat = stputs(p, concat);
2714 if ((p = *ap++) == NULL)
2716 STPUTC(' ', concat);
2718 STPUTC('\0', concat);
2719 p = grabstackstr(concat);
2721 evalstring(p, ~SKIPEVAL);
2729 * Execute a command or commands contained in a string.
2733 evalstring(char *s, int mask)
2736 struct stackmark smark;
2740 setstackmark(&smark);
2743 while ((n = parsecmd(0)) != NEOF) {
2745 popstackmark(&smark);
2760 * Evaluate a parse tree. The value is left in the global variable
2765 evaltree(union node *n, int flags)
2768 void (*evalfn)(union node *, int);
2772 TRACE(("evaltree(NULL) called\n"));
2775 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2776 getpid(), n, n->type, flags));
2780 out1fmt("Node type = %d\n", n->type);
2785 evaltree(n->nnot.com, EV_TESTED);
2786 status = !exitstatus;
2789 expredir(n->nredir.redirect);
2790 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2792 evaltree(n->nredir.n, flags & EV_TESTED);
2793 status = exitstatus;
2798 evalfn = evalcommand;
2800 if (eflag && !(flags & EV_TESTED))
2812 evalfn = evalsubshell;
2824 #error NAND + 1 != NOR
2826 #if NOR + 1 != NSEMI
2827 #error NOR + 1 != NSEMI
2829 isor = n->type - NAND;
2832 (flags | ((isor >> 1) - 1)) & EV_TESTED
2834 if (!exitstatus == isor)
2846 evaltree(n->nif.test, EV_TESTED);
2849 if (exitstatus == 0) {
2852 } else if (n->nif.elsepart) {
2853 n = n->nif.elsepart;
2858 defun(n->narg.text, n->narg.next);
2862 exitstatus = status;
2866 if ((checkexit & exitstatus))
2867 evalskip |= SKIPEVAL;
2868 else if (pendingsigs && dotrap())
2871 if (flags & EV_EXIT) {
2878 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2881 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2885 evalloop(union node *n, int flags)
2895 evaltree(n->nbinary.ch1, EV_TESTED);
2897 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2901 if (evalskip == SKIPBREAK && --skipcount <= 0)
2906 if (n->type != NWHILE)
2910 evaltree(n->nbinary.ch2, flags);
2911 status = exitstatus;
2916 exitstatus = status;
2922 evalfor(union node *n, int flags)
2924 struct arglist arglist;
2927 struct stackmark smark;
2929 setstackmark(&smark);
2930 arglist.lastp = &arglist.list;
2931 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2932 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2937 *arglist.lastp = NULL;
2942 for (sp = arglist.list ; sp ; sp = sp->next) {
2943 setvar(n->nfor.var, sp->text, 0);
2944 evaltree(n->nfor.body, flags);
2946 if (evalskip == SKIPCONT && --skipcount <= 0) {
2950 if (evalskip == SKIPBREAK && --skipcount <= 0)
2957 popstackmark(&smark);
2963 evalcase(union node *n, int flags)
2967 struct arglist arglist;
2968 struct stackmark smark;
2970 setstackmark(&smark);
2971 arglist.lastp = &arglist.list;
2972 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2974 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2975 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2976 if (casematch(patp, arglist.list->text)) {
2977 if (evalskip == 0) {
2978 evaltree(cp->nclist.body, flags);
2985 popstackmark(&smark);
2991 * Kick off a subshell to evaluate a tree.
2995 evalsubshell(union node *n, int flags)
2998 int backgnd = (n->type == NBACKGND);
3001 expredir(n->nredir.redirect);
3002 if (!backgnd && flags & EV_EXIT && !trap[0])
3006 if (forkshell(jp, n, backgnd) == 0) {
3010 flags &=~ EV_TESTED;
3012 redirect(n->nredir.redirect, 0);
3013 evaltreenr(n->nredir.n, flags);
3018 status = waitforjob(jp);
3019 exitstatus = status;
3026 * Compute the names of the files in a redirection list.
3030 expredir(union node *n)
3034 for (redir = n ; redir ; redir = redir->nfile.next) {
3036 fn.lastp = &fn.list;
3037 switch (redir->type) {
3043 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3044 redir->nfile.expfname = fn.list->text;
3048 if (redir->ndup.vname) {
3049 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3050 fixredir(redir, fn.list->text, 1);
3060 * Evaluate a pipeline. All the processes in the pipeline are children
3061 * of the process creating the pipeline. (This differs from some versions
3062 * of the shell, which make the last process in a pipeline the parent
3067 evalpipe(union node *n, int flags)
3070 struct nodelist *lp;
3075 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3077 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3081 jp = makejob(n, pipelen);
3083 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3087 if (pipe(pip) < 0) {
3089 sh_error("Pipe call failed");
3092 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3105 evaltreenr(lp->n, flags);
3113 if (n->npipe.backgnd == 0) {
3114 exitstatus = waitforjob(jp);
3115 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3123 * Execute a command inside back quotes. If it's a builtin command, we
3124 * want to save its output in a block obtained from malloc. Otherwise
3125 * we fork off a subprocess and get the output of the command via a pipe.
3126 * Should be called with interrupts off.
3130 evalbackcmd(union node *n, struct backcmd *result)
3142 saveherefd = herefd;
3150 sh_error("Pipe call failed");
3152 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3161 evaltreenr(n, EV_EXIT);
3165 result->fd = pip[0];
3168 herefd = saveherefd;
3170 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3171 result->fd, result->buf, result->nleft, result->jp));
3174 #ifdef CONFIG_ASH_CMDCMD
3175 static inline char **
3176 parse_command_args(char **argv, const char **path)
3188 if (c == '-' && !*cp) {
3198 /* run 'typecmd' for other options */
3201 } while ((c = *cp++));
3208 isassignment(const char *p)
3210 const char *q = endofname(p);
3216 #ifdef CONFIG_ASH_EXPAND_PRMT
3217 static const char *expandstr(const char *ps);
3219 #define expandstr(s) s
3223 * Execute a simple command.
3227 evalcommand(union node *cmd, int flags)
3229 struct stackmark smark;
3231 struct arglist arglist;
3232 struct arglist varlist;
3235 const struct strlist *sp;
3236 struct cmdentry cmdentry;
3244 struct builtincmd *bcmd;
3245 int pseudovarflag = 0;
3247 /* First expand the arguments. */
3248 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3249 setstackmark(&smark);
3250 back_exitstatus = 0;
3252 cmdentry.cmdtype = CMDBUILTIN;
3253 cmdentry.u.cmd = &bltin;
3254 varlist.lastp = &varlist.list;
3255 *varlist.lastp = NULL;
3256 arglist.lastp = &arglist.list;
3257 *arglist.lastp = NULL;
3262 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3263 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3266 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3267 struct strlist **spp;
3269 spp = arglist.lastp;
3270 if (pseudovarflag && isassignment(argp->narg.text))
3271 expandarg(argp, &arglist, EXP_VARTILDE);
3273 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3275 for (sp = *spp; sp; sp = sp->next)
3279 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3280 for (sp = arglist.list ; sp ; sp = sp->next) {
3281 TRACE(("evalcommand arg: %s\n", sp->text));
3282 *nargv++ = sp->text;
3287 if (iflag && funcnest == 0 && argc > 0)
3288 lastarg = nargv[-1];
3291 expredir(cmd->ncmd.redirect);
3292 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3295 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3296 struct strlist **spp;
3299 spp = varlist.lastp;
3300 expandarg(argp, &varlist, EXP_VARTILDE);
3303 * Modify the command lookup path, if a PATH= assignment
3307 if (varequal(p, path))
3311 /* Print the command if xflag is set. */
3314 const char *p = " %s";
3317 dprintf(preverrout_fd, p, expandstr(ps4val()));
3320 for(n = 0; n < 2; n++) {
3322 dprintf(preverrout_fd, p, sp->text);
3330 bb_full_write(preverrout_fd, "\n", 1);
3336 /* Now locate the command. */
3338 const char *oldpath;
3339 int cmd_flag = DO_ERR;
3344 find_command(argv[0], &cmdentry, cmd_flag, path);
3345 if (cmdentry.cmdtype == CMDUNKNOWN) {
3351 /* implement bltin and command here */
3352 if (cmdentry.cmdtype != CMDBUILTIN)
3355 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3356 if (cmdentry.u.cmd == EXECCMD)
3358 #ifdef CONFIG_ASH_CMDCMD
3359 if (cmdentry.u.cmd == COMMANDCMD) {
3362 nargv = parse_command_args(argv, &path);
3365 argc -= nargv - argv;
3367 cmd_flag |= DO_NOFUNC;
3375 /* We have a redirection error. */
3379 exitstatus = status;
3383 /* Execute the command. */
3384 switch (cmdentry.cmdtype) {
3386 /* Fork off a child process if necessary. */
3387 if (!(flags & EV_EXIT) || trap[0]) {
3389 jp = makejob(cmd, 1);
3390 if (forkshell(jp, cmd, FORK_FG) != 0) {
3391 exitstatus = waitforjob(jp);
3397 listsetvar(varlist.list, VEXPORT|VSTACK);
3398 shellexec(argv, path, cmdentry.u.index);
3402 cmdenviron = varlist.list;
3404 struct strlist *list = cmdenviron;
3406 if (spclbltin > 0 || argc == 0) {
3408 if (cmd_is_exec && argc > 1)
3411 listsetvar(list, i);
3413 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3428 exit_status = j + 128;
3429 exitstatus = exit_status;
3431 if (i == EXINT || spclbltin > 0) {
3433 longjmp(handler->loc, 1);
3440 listsetvar(varlist.list, 0);
3441 if (evalfun(cmdentry.u.func, argc, argv, flags))
3447 popredir(cmd_is_exec);
3449 /* dsl: I think this is intended to be used to support
3450 * '_' in 'vi' command mode during line editing...
3451 * However I implemented that within libedit itself.
3453 setvar("_", lastarg, 0);
3454 popstackmark(&smark);
3458 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3459 char *volatile savecmdname;
3460 struct jmploc *volatile savehandler;
3461 struct jmploc jmploc;
3464 savecmdname = commandname;
3465 if ((i = setjmp(jmploc.loc)))
3467 savehandler = handler;
3469 commandname = argv[0];
3471 optptr = NULL; /* initialize nextopt */
3472 exitstatus = (*cmd->builtin)(argc, argv);
3475 exitstatus |= ferror(stdout);
3476 commandname = savecmdname;
3478 handler = savehandler;
3484 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3486 volatile struct shparam saveparam;
3487 struct localvar *volatile savelocalvars;
3488 struct jmploc *volatile savehandler;
3489 struct jmploc jmploc;
3492 saveparam = shellparam;
3493 savelocalvars = localvars;
3494 if ((e = setjmp(jmploc.loc))) {
3498 savehandler = handler;
3501 shellparam.malloc = 0;
3505 shellparam.nparam = argc - 1;
3506 shellparam.p = argv + 1;
3507 #ifdef CONFIG_ASH_GETOPTS
3508 shellparam.optind = 1;
3509 shellparam.optoff = -1;
3511 evaltree(&func->n, flags & EV_TESTED);
3517 localvars = savelocalvars;
3518 freeparam(&shellparam);
3519 shellparam = saveparam;
3520 handler = savehandler;
3522 evalskip &= ~SKIPFUNC;
3528 goodname(const char *p)
3530 return !*endofname(p);
3534 * Search for a command. This is called before we fork so that the
3535 * location of the command will be available in the parent as well as
3536 * the child. The check for "goodname" is an overly conservative
3537 * check that the name will not be subject to expansion.
3541 prehash(union node *n)
3543 struct cmdentry entry;
3545 if (n->type == NCMD && n->ncmd.args)
3546 if (goodname(n->ncmd.args->narg.text))
3547 find_command(n->ncmd.args->narg.text, &entry, 0,
3554 * Builtin commands. Builtin commands whose functions are closely
3555 * tied to evaluation are implemented here.
3563 bltincmd(int argc, char **argv)
3566 * Preserve exitstatus of a previous possible redirection
3569 return back_exitstatus;
3574 * Handle break and continue commands. Break, continue, and return are
3575 * all handled by setting the evalskip flag. The evaluation routines
3576 * above all check this flag, and if it is set they start skipping
3577 * commands rather than executing them. The variable skipcount is
3578 * the number of loops to break/continue, or the number of function
3579 * levels to return. (The latter is always 1.) It should probably
3580 * be an error to break out of more loops than exist, but it isn't
3581 * in the standard shell so we don't make it one here.
3585 breakcmd(int argc, char **argv)
3587 int n = argc > 1 ? number(argv[1]) : 1;
3590 sh_error(illnum, argv[1]);
3594 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3602 * The return command.
3606 returncmd(int argc, char **argv)
3609 * If called outside a function, do what ksh does;
3610 * skip the rest of the file.
3612 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3613 return argv[1] ? number(argv[1]) : exitstatus;
3618 falsecmd(int argc, char **argv)
3625 truecmd(int argc, char **argv)
3632 execcmd(int argc, char **argv)
3635 iflag = 0; /* exit on error */
3638 shellexec(argv + 1, pathval(), 0);
3647 * When commands are first encountered, they are entered in a hash table.
3648 * This ensures that a full path search will not have to be done for them
3649 * on each invocation.
3651 * We should investigate converting to a linear search, even though that
3652 * would make the command name "hash" a misnomer.
3655 #define CMDTABLESIZE 31 /* should be prime */
3656 #define ARB 1 /* actual size determined at run time */
3661 struct tblentry *next; /* next entry in hash chain */
3662 union param param; /* definition of builtin function */
3663 short cmdtype; /* index identifying command */
3664 char rehash; /* if set, cd done since entry created */
3665 char cmdname[ARB]; /* name of command */
3669 static struct tblentry *cmdtable[CMDTABLESIZE];
3670 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3673 static void tryexec(char *, char **, char **);
3674 static void clearcmdentry(int);
3675 static struct tblentry *cmdlookup(const char *, int);
3676 static void delete_cmd_entry(void);
3680 * Exec a program. Never returns. If you change this routine, you may
3681 * have to change the find_command routine as well.
3685 shellexec(char **argv, const char *path, int idx)
3693 envp = environment();
3694 if (strchr(argv[0], '/') != NULL
3695 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3696 || find_applet_by_name(argv[0])
3699 tryexec(argv[0], argv, envp);
3703 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3704 if (--idx < 0 && pathopt == NULL) {
3705 tryexec(cmdname, argv, envp);
3706 if (errno != ENOENT && errno != ENOTDIR)
3713 /* Map to POSIX errors */
3725 exitstatus = exerrno;
3726 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3727 argv[0], e, suppressint ));
3728 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3734 tryexec(char *cmd, char **argv, char **envp)
3737 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3738 if(find_applet_by_name(cmd) != NULL) {
3739 /* re-exec ourselves with the new arguments */
3740 execve("/proc/self/exe",argv,envp);
3741 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3742 execve("/bin/busybox",argv,envp);
3743 /* If they called chroot or otherwise made the binary no longer
3744 * executable, fall through */
3751 execve(cmd, argv, envp);
3752 } while (errno == EINTR);
3754 execve(cmd, argv, envp);
3758 } else if (errno == ENOEXEC) {
3762 for (ap = argv; *ap; ap++)
3764 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3766 *ap = cmd = (char *)DEFAULT_SHELL;
3769 while ((*ap++ = *argv++))
3779 * Do a path search. The variable path (passed by reference) should be
3780 * set to the start of the path before the first call; padvance will update
3781 * this value as it proceeds. Successive calls to padvance will return
3782 * the possible path expansions in sequence. If an option (indicated by
3783 * a percent sign) appears in the path entry then the global variable
3784 * pathopt will be set to point to it; otherwise pathopt will be set to
3789 padvance(const char **path, const char *name)
3799 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3800 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3801 while (stackblocksize() < len)
3805 memcpy(q, start, p - start);
3813 while (*p && *p != ':') p++;
3819 return stalloc(len);
3823 /*** Command hashing code ***/
3826 printentry(struct tblentry *cmdp)
3832 idx = cmdp->param.index;
3835 name = padvance(&path, cmdp->cmdname);
3837 } while (--idx >= 0);
3838 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3843 hashcmd(int argc, char **argv)
3845 struct tblentry **pp;
3846 struct tblentry *cmdp;
3848 struct cmdentry entry;
3851 while ((c = nextopt("r")) != '\0') {
3855 if (*argptr == NULL) {
3856 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3857 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3858 if (cmdp->cmdtype == CMDNORMAL)
3865 while ((name = *argptr) != NULL) {
3866 if ((cmdp = cmdlookup(name, 0)) != NULL
3867 && (cmdp->cmdtype == CMDNORMAL
3868 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3870 find_command(name, &entry, DO_ERR, pathval());
3871 if (entry.cmdtype == CMDUNKNOWN)
3880 * Resolve a command name. If you change this routine, you may have to
3881 * change the shellexec routine as well.
3885 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3887 struct tblentry *cmdp;
3894 struct builtincmd *bcmd;
3896 /* If name contains a slash, don't use PATH or hash table */
3897 if (strchr(name, '/') != NULL) {
3898 entry->u.index = -1;
3900 while (stat(name, &statb) < 0) {
3905 entry->cmdtype = CMDUNKNOWN;
3909 entry->cmdtype = CMDNORMAL;
3913 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3914 if (find_applet_by_name(name)) {
3915 entry->cmdtype = CMDNORMAL;
3916 entry->u.index = -1;
3921 updatetbl = (path == pathval());
3924 if (strstr(path, "%builtin") != NULL)
3928 /* If name is in the table, check answer will be ok */
3929 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3932 switch (cmdp->cmdtype) {
3950 } else if (cmdp->rehash == 0)
3951 /* if not invalidated by cd, we're done */
3955 /* If %builtin not in path, check for builtin next */
3956 bcmd = find_builtin(name);
3957 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3958 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3960 goto builtin_success;
3962 /* We have to search path. */
3963 prev = -1; /* where to start */
3964 if (cmdp && cmdp->rehash) { /* doing a rehash */
3965 if (cmdp->cmdtype == CMDBUILTIN)
3968 prev = cmdp->param.index;
3974 while ((fullname = padvance(&path, name)) != NULL) {
3975 stunalloc(fullname);
3978 if (prefix(pathopt, "builtin")) {
3980 goto builtin_success;
3982 } else if (!(act & DO_NOFUNC) &&
3983 prefix(pathopt, "func")) {
3986 /* ignore unimplemented options */
3990 /* if rehash, don't redo absolute path names */
3991 if (fullname[0] == '/' && idx <= prev) {
3994 TRACE(("searchexec \"%s\": no change\n", name));
3997 while (stat(fullname, &statb) < 0) {
4002 if (errno != ENOENT && errno != ENOTDIR)
4006 e = EACCES; /* if we fail, this will be the error */
4007 if (!S_ISREG(statb.st_mode))
4009 if (pathopt) { /* this is a %func directory */
4010 stalloc(strlen(fullname) + 1);
4011 readcmdfile(fullname);
4012 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4013 cmdp->cmdtype != CMDFUNCTION)
4014 sh_error("%s not defined in %s", name, fullname);
4015 stunalloc(fullname);
4018 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4020 entry->cmdtype = CMDNORMAL;
4021 entry->u.index = idx;
4025 cmdp = cmdlookup(name, 1);
4026 cmdp->cmdtype = CMDNORMAL;
4027 cmdp->param.index = idx;
4032 /* We failed. If there was an entry for this command, delete it */
4033 if (cmdp && updatetbl)
4036 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4037 entry->cmdtype = CMDUNKNOWN;
4042 entry->cmdtype = CMDBUILTIN;
4043 entry->u.cmd = bcmd;
4047 cmdp = cmdlookup(name, 1);
4048 cmdp->cmdtype = CMDBUILTIN;
4049 cmdp->param.cmd = bcmd;
4053 entry->cmdtype = cmdp->cmdtype;
4054 entry->u = cmdp->param;
4059 * Wrapper around strcmp for qsort/bsearch/...
4061 static int pstrcmp(const void *a, const void *b)
4063 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4067 * Search the table of builtin commands.
4070 static struct builtincmd *
4071 find_builtin(const char *name)
4073 struct builtincmd *bp;
4076 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4085 * Called when a cd is done. Marks all commands so the next time they
4086 * are executed they will be rehashed.
4092 struct tblentry **pp;
4093 struct tblentry *cmdp;
4095 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4096 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4097 if (cmdp->cmdtype == CMDNORMAL || (
4098 cmdp->cmdtype == CMDBUILTIN &&
4099 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4110 * Fix command hash table when PATH changed.
4111 * Called before PATH is changed. The argument is the new value of PATH;
4112 * pathval() still returns the old value at this point.
4113 * Called with interrupts off.
4117 changepath(const char *newval)
4119 const char *old, *new;
4126 firstchange = 9999; /* assume no change */
4132 if ((*old == '\0' && *new == ':')
4133 || (*old == ':' && *new == '\0'))
4135 old = new; /* ignore subsequent differences */
4139 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4146 if (builtinloc < 0 && idx_bltin >= 0)
4147 builtinloc = idx_bltin; /* zap builtins */
4148 if (builtinloc >= 0 && idx_bltin < 0)
4150 clearcmdentry(firstchange);
4151 builtinloc = idx_bltin;
4156 * Clear out command entries. The argument specifies the first entry in
4157 * PATH which has changed.
4161 clearcmdentry(int firstchange)
4163 struct tblentry **tblp;
4164 struct tblentry **pp;
4165 struct tblentry *cmdp;
4168 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4170 while ((cmdp = *pp) != NULL) {
4171 if ((cmdp->cmdtype == CMDNORMAL &&
4172 cmdp->param.index >= firstchange)
4173 || (cmdp->cmdtype == CMDBUILTIN &&
4174 builtinloc >= firstchange)) {
4188 * Locate a command in the command hash table. If "add" is nonzero,
4189 * add the command to the table if it is not already present. The
4190 * variable "lastcmdentry" is set to point to the address of the link
4191 * pointing to the entry, so that delete_cmd_entry can delete the
4194 * Interrupts must be off if called with add != 0.
4197 static struct tblentry **lastcmdentry;
4200 static struct tblentry *
4201 cmdlookup(const char *name, int add)
4203 unsigned int hashval;
4205 struct tblentry *cmdp;
4206 struct tblentry **pp;
4209 hashval = (unsigned char)*p << 4;
4211 hashval += (unsigned char)*p++;
4213 pp = &cmdtable[hashval % CMDTABLESIZE];
4214 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4215 if (equal(cmdp->cmdname, name))
4219 if (add && cmdp == NULL) {
4220 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4221 + strlen(name) + 1);
4223 cmdp->cmdtype = CMDUNKNOWN;
4224 strcpy(cmdp->cmdname, name);
4231 * Delete the command entry returned on the last lookup.
4235 delete_cmd_entry(void)
4237 struct tblentry *cmdp;
4240 cmdp = *lastcmdentry;
4241 *lastcmdentry = cmdp->next;
4242 if (cmdp->cmdtype == CMDFUNCTION)
4243 freefunc(cmdp->param.func);
4250 * Add a new command entry, replacing any existing command entry for
4251 * the same name - except special builtins.
4255 addcmdentry(char *name, struct cmdentry *entry)
4257 struct tblentry *cmdp;
4259 cmdp = cmdlookup(name, 1);
4260 if (cmdp->cmdtype == CMDFUNCTION) {
4261 freefunc(cmdp->param.func);
4263 cmdp->cmdtype = entry->cmdtype;
4264 cmdp->param = entry->u;
4269 * Make a copy of a parse tree.
4272 static inline struct funcnode *
4273 copyfunc(union node *n)
4278 funcblocksize = offsetof(struct funcnode, n);
4281 blocksize = funcblocksize;
4282 f = ckmalloc(blocksize + funcstringsize);
4283 funcblock = (char *) f + offsetof(struct funcnode, n);
4284 funcstring = (char *) f + blocksize;
4291 * Define a shell function.
4295 defun(char *name, union node *func)
4297 struct cmdentry entry;
4300 entry.cmdtype = CMDFUNCTION;
4301 entry.u.func = copyfunc(func);
4302 addcmdentry(name, &entry);
4308 * Delete a function if it exists.
4312 unsetfunc(const char *name)
4314 struct tblentry *cmdp;
4316 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4317 cmdp->cmdtype == CMDFUNCTION)
4322 * Locate and print what a word is...
4326 #ifdef CONFIG_ASH_CMDCMD
4328 describe_command(char *command, int describe_command_verbose)
4330 #define describe_command_verbose 1
4332 describe_command(char *command)
4335 struct cmdentry entry;
4336 struct tblentry *cmdp;
4337 #ifdef CONFIG_ASH_ALIAS
4338 const struct alias *ap;
4340 const char *path = pathval();
4342 if (describe_command_verbose) {
4346 /* First look at the keywords */
4347 if (findkwd(command)) {
4348 out1str(describe_command_verbose ? " is a shell keyword" : command);
4352 #ifdef CONFIG_ASH_ALIAS
4353 /* Then look at the aliases */
4354 if ((ap = lookupalias(command, 0)) != NULL) {
4355 if (describe_command_verbose) {
4356 out1fmt(" is an alias for %s", ap->val);
4365 /* Then check if it is a tracked alias */
4366 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4367 entry.cmdtype = cmdp->cmdtype;
4368 entry.u = cmdp->param;
4370 /* Finally use brute force */
4371 find_command(command, &entry, DO_ABS, path);
4374 switch (entry.cmdtype) {
4376 int j = entry.u.index;
4382 p = padvance(&path, command);
4386 if (describe_command_verbose) {
4388 (cmdp ? " a tracked alias for" : nullstr), p
4397 if (describe_command_verbose) {
4398 out1str(" is a shell function");
4405 if (describe_command_verbose) {
4406 out1fmt(" is a %sshell builtin",
4407 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4408 "special " : nullstr
4416 if (describe_command_verbose) {
4417 out1str(": not found\n");
4423 outstr("\n", stdout);
4428 typecmd(int argc, char **argv)
4433 for (i = 1; i < argc; i++) {
4434 #ifdef CONFIG_ASH_CMDCMD
4435 err |= describe_command(argv[i], 1);
4437 err |= describe_command(argv[i]);
4443 #ifdef CONFIG_ASH_CMDCMD
4445 commandcmd(int argc, char **argv)
4453 while ((c = nextopt("pvV")) != '\0')
4455 verify |= VERIFY_VERBOSE;
4457 verify |= VERIFY_BRIEF;
4463 return describe_command(*argptr, verify - VERIFY_BRIEF);
4472 * Routines to expand arguments to commands. We have to deal with
4473 * backquotes, shell variables, and file metacharacters.
4479 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4480 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4481 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4482 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4483 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4486 * Structure specifying which parts of the string should be searched
4487 * for IFS characters.
4491 struct ifsregion *next; /* next region in list */
4492 int begoff; /* offset of start of region */
4493 int endoff; /* offset of end of region */
4494 int nulonly; /* search for nul bytes only */
4497 /* output of current string */
4498 static char *expdest;
4499 /* list of back quote expressions */
4500 static struct nodelist *argbackq;
4501 /* first struct in list of ifs regions */
4502 static struct ifsregion ifsfirst;
4503 /* last struct in list */
4504 static struct ifsregion *ifslastp;
4505 /* holds expanded arg list */
4506 static struct arglist exparg;
4508 static void argstr(char *, int);
4509 static char *exptilde(char *, char *, int);
4510 static void expbackq(union node *, int, int);
4511 static const char *subevalvar(char *, char *, int, int, int, int, int);
4512 static char *evalvar(char *, int);
4513 static void strtodest(const char *, int, int);
4514 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4515 static ssize_t varvalue(char *, int, int);
4516 static void recordregion(int, int, int);
4517 static void removerecordregions(int);
4518 static void ifsbreakup(char *, struct arglist *);
4519 static void ifsfree(void);
4520 static void expandmeta(struct strlist *, int);
4521 static int patmatch(char *, const char *);
4523 static int cvtnum(arith_t);
4524 static size_t esclen(const char *, const char *);
4525 static char *scanleft(char *, char *, char *, char *, int, int);
4526 static char *scanright(char *, char *, char *, char *, int, int);
4527 static void varunset(const char *, const char *, const char *, int)
4531 #define pmatch(a, b) !fnmatch((a), (b), 0)
4533 * Prepare a pattern for a expmeta (internal glob(3)) call.
4535 * Returns an stalloced string.
4538 static inline char *
4539 preglob(const char *pattern, int quoted, int flag) {
4540 flag |= RMESCAPE_GLOB;
4542 flag |= RMESCAPE_QUOTED;
4544 return _rmescapes((char *)pattern, flag);
4549 esclen(const char *start, const char *p) {
4552 while (p > start && *--p == CTLESC) {
4560 * Expand shell variables and backquotes inside a here document.
4564 expandhere(union node *arg, int fd)
4567 expandarg(arg, (struct arglist *)NULL, 0);
4568 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4573 * Perform variable substitution and command substitution on an argument,
4574 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4575 * perform splitting and file name expansion. When arglist is NULL, perform
4576 * here document expansion.
4580 expandarg(union node *arg, struct arglist *arglist, int flag)
4585 argbackq = arg->narg.backquote;
4586 STARTSTACKSTR(expdest);
4587 ifsfirst.next = NULL;
4589 argstr(arg->narg.text, flag);
4590 p = _STPUTC('\0', expdest);
4592 if (arglist == NULL) {
4593 return; /* here document expanded */
4595 p = grabstackstr(p);
4596 exparg.lastp = &exparg.list;
4600 if (flag & EXP_FULL) {
4601 ifsbreakup(p, &exparg);
4602 *exparg.lastp = NULL;
4603 exparg.lastp = &exparg.list;
4604 expandmeta(exparg.list, flag);
4606 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4608 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4611 exparg.lastp = &sp->next;
4615 *exparg.lastp = NULL;
4617 *arglist->lastp = exparg.list;
4618 arglist->lastp = exparg.lastp;
4624 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4625 * characters to allow for further processing. Otherwise treat
4626 * $@ like $* since no splitting will be performed.
4630 argstr(char *p, int flag)
4632 static const char spclchars[] = {
4640 CTLBACKQ | CTLQUOTE,
4641 #ifdef CONFIG_ASH_MATH_SUPPORT
4646 const char *reject = spclchars;
4648 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4649 int breakall = flag & EXP_WORD;
4654 if (!(flag & EXP_VARTILDE)) {
4656 } else if (flag & EXP_VARTILDE2) {
4661 if (flag & EXP_TILDE) {
4667 if (*q == CTLESC && (flag & EXP_QWORD))
4670 p = exptilde(p, q, flag);
4673 startloc = expdest - (char *)stackblock();
4675 length += strcspn(p + length, reject);
4677 if (c && (!(c & 0x80)
4678 #ifdef CONFIG_ASH_MATH_SUPPORT
4682 /* c == '=' || c == ':' || c == CTLENDARI */
4687 expdest = stnputs(p, length, expdest);
4688 newloc = expdest - (char *)stackblock();
4689 if (breakall && !inquotes && newloc > startloc) {
4690 recordregion(startloc, newloc, 0);
4701 if (flag & EXP_VARTILDE2) {
4705 flag |= EXP_VARTILDE2;
4710 * sort of a hack - expand tildes in variable
4711 * assignments (after the first '=' and after ':'s).
4720 case CTLENDVAR: /* ??? */
4723 /* "$@" syntax adherence hack */
4726 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4727 (p[4] == CTLQUOTEMARK || (
4728 p[4] == CTLENDVAR &&
4729 p[5] == CTLQUOTEMARK
4732 p = evalvar(p + 1, flag) + 1;
4735 inquotes = !inquotes;
4748 p = evalvar(p, flag);
4752 case CTLBACKQ|CTLQUOTE:
4753 expbackq(argbackq->n, c, quotes);
4754 argbackq = argbackq->next;
4756 #ifdef CONFIG_ASH_MATH_SUPPORT
4769 exptilde(char *startp, char *p, int flag)
4775 int quotes = flag & (EXP_FULL | EXP_CASE);
4780 while ((c = *++p) != '\0') {
4787 if (flag & EXP_VARTILDE)
4797 if (*name == '\0') {
4798 home = lookupvar(homestr);
4800 if ((pw = getpwnam(name)) == NULL)
4804 if (!home || !*home)
4807 startloc = expdest - (char *)stackblock();
4808 strtodest(home, SQSYNTAX, quotes);
4809 recordregion(startloc, expdest - (char *)stackblock(), 0);
4818 removerecordregions(int endoff)
4820 if (ifslastp == NULL)
4823 if (ifsfirst.endoff > endoff) {
4824 while (ifsfirst.next != NULL) {
4825 struct ifsregion *ifsp;
4827 ifsp = ifsfirst.next->next;
4828 ckfree(ifsfirst.next);
4829 ifsfirst.next = ifsp;
4832 if (ifsfirst.begoff > endoff)
4835 ifslastp = &ifsfirst;
4836 ifsfirst.endoff = endoff;
4841 ifslastp = &ifsfirst;
4842 while (ifslastp->next && ifslastp->next->begoff < endoff)
4843 ifslastp=ifslastp->next;
4844 while (ifslastp->next != NULL) {
4845 struct ifsregion *ifsp;
4847 ifsp = ifslastp->next->next;
4848 ckfree(ifslastp->next);
4849 ifslastp->next = ifsp;
4852 if (ifslastp->endoff > endoff)
4853 ifslastp->endoff = endoff;
4857 #ifdef CONFIG_ASH_MATH_SUPPORT
4859 * Expand arithmetic expression. Backup to start of expression,
4860 * evaluate, place result in (backed up) result, adjust string position.
4873 * This routine is slightly over-complicated for
4874 * efficiency. Next we scan backwards looking for the
4875 * start of arithmetic.
4877 start = stackblock();
4884 while (*p != CTLARI) {
4888 sh_error("missing CTLARI (shouldn't happen)");
4893 esc = esclen(start, p);
4903 removerecordregions(begoff);
4912 len = cvtnum(dash_arith(p + 2));
4915 recordregion(begoff, begoff + len, 0);
4920 * Expand stuff in backwards quotes.
4924 expbackq(union node *cmd, int quoted, int quotes)
4932 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4933 struct stackmark smark;
4936 setstackmark(&smark);
4938 startloc = dest - (char *)stackblock();
4940 evalbackcmd(cmd, (struct backcmd *) &in);
4941 popstackmark(&smark);
4948 memtodest(p, i, syntax, quotes);
4952 i = safe_read(in.fd, buf, sizeof buf);
4953 TRACE(("expbackq: read returns %d\n", i));
4963 back_exitstatus = waitforjob(in.jp);
4967 /* Eat all trailing newlines */
4969 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4974 recordregion(startloc, dest - (char *)stackblock(), 0);
4975 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4976 (dest - (char *)stackblock()) - startloc,
4977 (dest - (char *)stackblock()) - startloc,
4978 stackblock() + startloc));
4983 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4994 const char *s = loc2;
5000 match = pmatch(str, s);
5004 if (quotes && *loc == CTLESC)
5014 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5021 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5024 const char *s = loc2;
5029 match = pmatch(str, s);
5036 esc = esclen(startp, loc);
5048 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5052 int saveherefd = herefd;
5053 struct nodelist *saveargbackq = argbackq;
5055 char *rmesc, *rmescend;
5057 char *(*scan)(char *, char *, char *, char *, int , int);
5060 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5061 STPUTC('\0', expdest);
5062 herefd = saveherefd;
5063 argbackq = saveargbackq;
5064 startp = stackblock() + startloc;
5068 setvar(str, startp, 0);
5069 amount = startp - expdest;
5070 STADJUST(amount, expdest);
5074 varunset(p, str, startp, varflags);
5078 subtype -= VSTRIMRIGHT;
5080 if (subtype < 0 || subtype > 3)
5085 rmescend = stackblock() + strloc;
5087 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5088 if (rmesc != startp) {
5090 startp = stackblock() + startloc;
5094 str = stackblock() + strloc;
5095 preglob(str, varflags & VSQUOTE, 0);
5097 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5098 zero = subtype >> 1;
5099 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5100 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5102 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5105 memmove(startp, loc, str - loc);
5106 loc = startp + (str - loc) - 1;
5109 amount = loc - expdest;
5110 STADJUST(amount, expdest);
5117 * Expand a variable, and return a pointer to the next character in the
5121 evalvar(char *p, int flag)
5134 quotes = flag & (EXP_FULL | EXP_CASE);
5136 subtype = varflags & VSTYPE;
5137 quoted = varflags & VSQUOTE;
5139 easy = (!quoted || (*var == '@' && shellparam.nparam));
5140 startloc = expdest - (char *)stackblock();
5141 p = strchr(p, '=') + 1;
5144 varlen = varvalue(var, varflags, flag);
5145 if (varflags & VSNUL)
5148 if (subtype == VSPLUS) {
5149 varlen = -1 - varlen;
5153 if (subtype == VSMINUS) {
5157 p, flag | EXP_TILDE |
5158 (quoted ? EXP_QWORD : EXP_WORD)
5167 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5169 if (subevalvar(p, var, 0, subtype, startloc,
5173 * Remove any recorded regions beyond
5176 removerecordregions(startloc);
5186 if (varlen < 0 && uflag)
5187 varunset(p, var, 0, 0);
5189 if (subtype == VSLENGTH) {
5190 cvtnum(varlen > 0 ? varlen : 0);
5194 if (subtype == VSNORMAL) {
5198 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5207 case VSTRIMRIGHTMAX:
5216 * Terminate the string and start recording the pattern
5219 STPUTC('\0', expdest);
5220 patloc = expdest - (char *)stackblock();
5221 if (subevalvar(p, NULL, patloc, subtype,
5222 startloc, varflags, quotes) == 0) {
5223 int amount = expdest - (
5224 (char *)stackblock() + patloc - 1
5226 STADJUST(-amount, expdest);
5228 /* Remove any recorded regions beyond start of variable */
5229 removerecordregions(startloc);
5234 if (subtype != VSNORMAL) { /* skip to end of alternative */
5237 if ((c = *p++) == CTLESC)
5239 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5241 argbackq = argbackq->next;
5242 } else if (c == CTLVAR) {
5243 if ((*p++ & VSTYPE) != VSNORMAL)
5245 } else if (c == CTLENDVAR) {
5256 * Put a string on the stack.
5260 memtodest(const char *p, size_t len, int syntax, int quotes) {
5263 q = makestrspace(len * 2, q);
5266 int c = SC2INT(*p++);
5269 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5279 strtodest(const char *p, int syntax, int quotes)
5281 memtodest(p, strlen(p), syntax, quotes);
5286 * Add the value of a specialized variable to the stack string.
5290 varvalue(char *name, int varflags, int flags)
5300 int quoted = varflags & VSQUOTE;
5301 int subtype = varflags & VSTYPE;
5302 int quotes = flags & (EXP_FULL | EXP_CASE);
5304 if (quoted && (flags & EXP_FULL))
5305 sep = 1 << CHAR_BIT;
5307 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5316 num = shellparam.nparam;
5326 p = makestrspace(NOPTS, expdest);
5327 for (i = NOPTS - 1; i >= 0; i--) {
5329 USTPUTC(optletters(i), p);
5340 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5341 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5344 if (!(ap = shellparam.p))
5346 while ((p = *ap++)) {
5349 partlen = strlen(p);
5352 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5353 memtodest(p, partlen, syntax, quotes);
5359 if (subtype == VSPLUS || subtype == VSLENGTH) {
5381 if (num < 0 || num > shellparam.nparam)
5383 p = num ? shellparam.p[num - 1] : arg0;
5386 p = lookupvar(name);
5392 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5393 memtodest(p, len, syntax, quotes);
5397 if (subtype == VSPLUS || subtype == VSLENGTH)
5398 STADJUST(-len, expdest);
5404 * Record the fact that we have to scan this region of the
5405 * string for IFS characters.
5409 recordregion(int start, int end, int nulonly)
5411 struct ifsregion *ifsp;
5413 if (ifslastp == NULL) {
5417 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5419 ifslastp->next = ifsp;
5423 ifslastp->begoff = start;
5424 ifslastp->endoff = end;
5425 ifslastp->nulonly = nulonly;
5430 * Break the argument string into pieces based upon IFS and add the
5431 * strings to the argument list. The regions of the string to be
5432 * searched for IFS characters have been stored by recordregion.
5435 ifsbreakup(char *string, struct arglist *arglist)
5437 struct ifsregion *ifsp;
5442 const char *ifs, *realifs;
5448 if (ifslastp != NULL) {
5451 realifs = ifsset() ? ifsval() : defifs;
5454 p = string + ifsp->begoff;
5455 nulonly = ifsp->nulonly;
5456 ifs = nulonly ? nullstr : realifs;
5458 while (p < string + ifsp->endoff) {
5462 if (strchr(ifs, *p)) {
5464 ifsspc = (strchr(defifs, *p) != NULL);
5465 /* Ignore IFS whitespace at start */
5466 if (q == start && ifsspc) {
5472 sp = (struct strlist *)stalloc(sizeof *sp);
5474 *arglist->lastp = sp;
5475 arglist->lastp = &sp->next;
5479 if (p >= string + ifsp->endoff) {
5485 if (strchr(ifs, *p) == NULL ) {
5488 } else if (strchr(defifs, *p) == NULL) {
5504 } while ((ifsp = ifsp->next) != NULL);
5513 sp = (struct strlist *)stalloc(sizeof *sp);
5515 *arglist->lastp = sp;
5516 arglist->lastp = &sp->next;
5522 struct ifsregion *p;
5527 struct ifsregion *ifsp;
5533 ifsfirst.next = NULL;
5537 static void expmeta(char *, char *);
5538 static struct strlist *expsort(struct strlist *);
5539 static struct strlist *msort(struct strlist *, int);
5541 static char *expdir;
5545 expandmeta(struct strlist *str, int flag)
5547 static const char metachars[] = {
5550 /* TODO - EXP_REDIR */
5553 struct strlist **savelastp;
5559 if (!strpbrk(str->text, metachars))
5561 savelastp = exparg.lastp;
5564 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5566 int i = strlen(str->text);
5567 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5575 if (exparg.lastp == savelastp) {
5580 *exparg.lastp = str;
5581 rmescapes(str->text);
5582 exparg.lastp = &str->next;
5584 *exparg.lastp = NULL;
5585 *savelastp = sp = expsort(*savelastp);
5586 while (sp->next != NULL)
5588 exparg.lastp = &sp->next;
5595 * Add a file name to the list.
5599 addfname(const char *name)
5603 sp = (struct strlist *)stalloc(sizeof *sp);
5604 sp->text = sstrdup(name);
5606 exparg.lastp = &sp->next;
5611 * Do metacharacter (i.e. *, ?, [...]) expansion.
5615 expmeta(char *enddir, char *name)
5630 for (p = name; *p; p++) {
5631 if (*p == '*' || *p == '?')
5633 else if (*p == '[') {
5640 if (*q == '/' || *q == '\0')
5647 } else if (*p == '\\')
5649 else if (*p == '/') {
5656 if (metaflag == 0) { /* we've reached the end of the file name */
5657 if (enddir != expdir)
5665 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5676 } while (p < start);
5678 if (enddir == expdir) {
5680 } else if (enddir == expdir + 1 && *expdir == '/') {
5686 if ((dirp = opendir(cp)) == NULL)
5688 if (enddir != expdir)
5690 if (*endname == 0) {
5702 while (! intpending && (dp = readdir(dirp)) != NULL) {
5703 if (dp->d_name[0] == '.' && ! matchdot)
5705 if (pmatch(start, dp->d_name)) {
5707 scopy(dp->d_name, enddir);
5710 for (p = enddir, cp = dp->d_name;
5711 (*p++ = *cp++) != '\0';)
5714 expmeta(p, endname);
5724 * Sort the results of file name expansion. It calculates the number of
5725 * strings to sort and then calls msort (short for merge sort) to do the
5729 static struct strlist *
5730 expsort(struct strlist *str)
5736 for (sp = str ; sp ; sp = sp->next)
5738 return msort(str, len);
5742 static struct strlist *
5743 msort(struct strlist *list, int len)
5745 struct strlist *p, *q = NULL;
5746 struct strlist **lpp;
5754 for (n = half ; --n >= 0 ; ) {
5758 q->next = NULL; /* terminate first half of list */
5759 q = msort(list, half); /* sort first half of list */
5760 p = msort(p, len - half); /* sort second half */
5763 #ifdef CONFIG_LOCALE_SUPPORT
5764 if (strcoll(p->text, q->text) < 0)
5766 if (strcmp(p->text, q->text) < 0)
5771 if ((p = *lpp) == NULL) {
5778 if ((q = *lpp) == NULL) {
5789 * Returns true if the pattern matches the string.
5793 patmatch(char *pattern, const char *string)
5795 return pmatch(preglob(pattern, 0, 0), string);
5800 * Remove any CTLESC characters from a string.
5804 _rmescapes(char *str, int flag)
5807 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5812 p = strpbrk(str, qchars);
5818 if (flag & RMESCAPE_ALLOC) {
5819 size_t len = p - str;
5820 size_t fulllen = len + strlen(p) + 1;
5822 if (flag & RMESCAPE_GROW) {
5823 r = makestrspace(fulllen, expdest);
5824 } else if (flag & RMESCAPE_HEAP) {
5825 r = ckmalloc(fulllen);
5827 r = stalloc(fulllen);
5831 q = mempcpy(q, str, len);
5834 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5835 globbing = flag & RMESCAPE_GLOB;
5836 notescaped = globbing;
5838 if (*p == CTLQUOTEMARK) {
5839 inquotes = ~inquotes;
5841 notescaped = globbing;
5845 /* naked back slash */
5851 if (notescaped && inquotes && *p != '/') {
5855 notescaped = globbing;
5860 if (flag & RMESCAPE_GROW) {
5862 STADJUST(q - r + 1, expdest);
5869 * See if a pattern matches in a case statement.
5873 casematch(union node *pattern, char *val)
5875 struct stackmark smark;
5878 setstackmark(&smark);
5879 argbackq = pattern->narg.backquote;
5880 STARTSTACKSTR(expdest);
5882 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5883 STACKSTRNUL(expdest);
5884 result = patmatch(stackblock(), val);
5885 popstackmark(&smark);
5898 expdest = makestrspace(32, expdest);
5899 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5900 len = fmtstr(expdest, 32, "%lld", (long long) num);
5902 len = fmtstr(expdest, 32, "%ld", num);
5904 STADJUST(len, expdest);
5909 varunset(const char *end, const char *var, const char *umsg, int varflags)
5915 msg = "parameter not set";
5917 if (*end == CTLENDVAR) {
5918 if (varflags & VSNUL)
5923 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5930 * This implements the input routines used by the parser.
5933 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5935 static void pushfile(void);
5938 * Read a character from the script, returning PEOF on end of file.
5939 * Nul characters in the input are silently discarded.
5943 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5945 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5946 #define pgetc_macro() pgetc()
5950 return pgetc_as_macro();
5953 #define pgetc_macro() pgetc_as_macro()
5957 return pgetc_macro();
5963 * Same as pgetc(), but ignores PEOA.
5965 #ifdef CONFIG_ASH_ALIAS
5966 static int pgetc2(void)
5972 } while (c == PEOA);
5976 static inline int pgetc2(void)
5978 return pgetc_macro();
5983 * Read a line from the script.
5986 static inline char *
5987 pfgets(char *line, int len)
5993 while (--nleft > 0) {
6010 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6011 #ifdef CONFIG_ASH_EXPAND_PRMT
6012 static char *cmdedit_prompt;
6014 static const char *cmdedit_prompt;
6016 static inline void putprompt(const char *s)
6018 #ifdef CONFIG_ASH_EXPAND_PRMT
6019 free(cmdedit_prompt);
6020 cmdedit_prompt = bb_xstrdup(s);
6026 static inline void putprompt(const char *s)
6036 char *buf = parsefile->buf;
6040 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6041 if (!iflag || parsefile->fd)
6042 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6044 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6045 cmdedit_path_lookup = pathval();
6047 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6049 /* Ctrl+C presend */
6058 if(nr < 0 && errno == 0) {
6059 /* Ctrl+D presend */
6064 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6068 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6069 int flags = fcntl(0, F_GETFL, 0);
6070 if (flags >= 0 && flags & O_NONBLOCK) {
6071 flags &=~ O_NONBLOCK;
6072 if (fcntl(0, F_SETFL, flags) >= 0) {
6073 out2str("sh: turning off NDELAY mode\n");
6083 * Refill the input buffer and return the next input character:
6085 * 1) If a string was pushed back on the input, pop it;
6086 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6087 * from a string so we can't refill the buffer, return EOF.
6088 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6089 * 4) Process input up to the next newline, deleting nul characters.
6099 while (parsefile->strpush) {
6100 #ifdef CONFIG_ASH_ALIAS
6101 if (parsenleft == -1 && parsefile->strpush->ap &&
6102 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6107 if (--parsenleft >= 0)
6108 return SC2INT(*parsenextc++);
6110 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6117 if ((more = preadfd()) <= 0) {
6118 parselleft = parsenleft = EOF_NLEFT;
6125 /* delete nul characters */
6133 memmove(q, q + 1, more);
6137 parsenleft = q - parsenextc - 1;
6143 parsenleft = q - parsenextc - 1;
6155 out2str(parsenextc);
6160 return SC2INT(*parsenextc++);
6164 * Undo the last call to pgetc. Only one character may be pushed back.
6165 * PEOF may be pushed back.
6176 * Push a string back onto the input at this current parsefile level.
6177 * We handle aliases this way.
6180 pushstring(char *s, void *ap)
6187 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6188 if (parsefile->strpush) {
6189 sp = ckmalloc(sizeof (struct strpush));
6190 sp->prev = parsefile->strpush;
6191 parsefile->strpush = sp;
6193 sp = parsefile->strpush = &(parsefile->basestrpush);
6194 sp->prevstring = parsenextc;
6195 sp->prevnleft = parsenleft;
6196 #ifdef CONFIG_ASH_ALIAS
6197 sp->ap = (struct alias *)ap;
6199 ((struct alias *)ap)->flag |= ALIASINUSE;
6211 struct strpush *sp = parsefile->strpush;
6214 #ifdef CONFIG_ASH_ALIAS
6216 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6217 checkkwd |= CHKALIAS;
6219 if (sp->string != sp->ap->val) {
6222 sp->ap->flag &= ~ALIASINUSE;
6223 if (sp->ap->flag & ALIASDEAD) {
6224 unalias(sp->ap->name);
6228 parsenextc = sp->prevstring;
6229 parsenleft = sp->prevnleft;
6230 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6231 parsefile->strpush = sp->prev;
6232 if (sp != &(parsefile->basestrpush))
6238 * Set the input to take input from a file. If push is set, push the
6239 * old input onto the stack first.
6243 setinputfile(const char *fname, int flags)
6249 if ((fd = open(fname, O_RDONLY)) < 0) {
6250 if (flags & INPUT_NOFILE_OK)
6252 sh_error("Can't open %s", fname);
6255 fd2 = copyfd(fd, 10);
6258 sh_error("Out of file descriptors");
6261 setinputfd(fd, flags & INPUT_PUSH_FILE);
6269 * Like setinputfile, but takes an open file descriptor. Call this with
6274 setinputfd(int fd, int push)
6276 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6282 if (parsefile->buf == NULL)
6283 parsefile->buf = ckmalloc(IBUFSIZ);
6284 parselleft = parsenleft = 0;
6290 * Like setinputfile, but takes input from a string.
6294 setinputstring(char *string)
6298 parsenextc = string;
6299 parsenleft = strlen(string);
6300 parsefile->buf = NULL;
6307 * To handle the "." command, a stack of input files is used. Pushfile
6308 * adds a new entry to the stack and popfile restores the previous level.
6314 struct parsefile *pf;
6316 parsefile->nleft = parsenleft;
6317 parsefile->lleft = parselleft;
6318 parsefile->nextc = parsenextc;
6319 parsefile->linno = plinno;
6320 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6321 pf->prev = parsefile;
6324 pf->basestrpush.prev = NULL;
6332 struct parsefile *pf = parsefile;
6341 parsefile = pf->prev;
6343 parsenleft = parsefile->nleft;
6344 parselleft = parsefile->lleft;
6345 parsenextc = parsefile->nextc;
6346 plinno = parsefile->linno;
6352 * Return to top level.
6358 while (parsefile != &basepf)
6364 * Close the file(s) that the shell is reading commands from. Called
6365 * after a fork is done.
6372 if (parsefile->fd > 0) {
6373 close(parsefile->fd);
6380 /* mode flags for set_curjob */
6381 #define CUR_DELETE 2
6382 #define CUR_RUNNING 1
6383 #define CUR_STOPPED 0
6385 /* mode flags for dowait */
6386 #define DOWAIT_NORMAL 0
6387 #define DOWAIT_BLOCK 1
6390 static struct job *jobtab;
6392 static unsigned njobs;
6394 /* pgrp of shell on invocation */
6395 static int initialpgrp;
6396 static int ttyfd = -1;
6399 static struct job *curjob;
6400 /* number of presumed living untracked jobs */
6403 static void set_curjob(struct job *, unsigned);
6405 static int restartjob(struct job *, int);
6406 static void xtcsetpgrp(int, pid_t);
6407 static char *commandtext(union node *);
6408 static void cmdlist(union node *, int);
6409 static void cmdtxt(union node *);
6410 static void cmdputs(const char *);
6411 static void showpipe(struct job *, FILE *);
6413 static int sprint_status(char *, int, int);
6414 static void freejob(struct job *);
6415 static struct job *getjob(const char *, int);
6416 static struct job *growjobtab(void);
6417 static void forkchild(struct job *, union node *, int);
6418 static void forkparent(struct job *, union node *, int, pid_t);
6419 static int dowait(int, struct job *);
6420 static int getstatus(struct job *);
6423 set_curjob(struct job *jp, unsigned mode)
6426 struct job **jpp, **curp;
6428 /* first remove from list */
6429 jpp = curp = &curjob;
6434 jpp = &jp1->prev_job;
6436 *jpp = jp1->prev_job;
6438 /* Then re-insert in correct position */
6446 /* job being deleted */
6449 /* newly created job or backgrounded job,
6450 put after all stopped jobs. */
6454 if (!jp1 || jp1->state != JOBSTOPPED)
6457 jpp = &jp1->prev_job;
6463 /* newly stopped job - becomes curjob */
6464 jp->prev_job = *jpp;
6472 * Turn job control on and off.
6474 * Note: This code assumes that the third arg to ioctl is a character
6475 * pointer, which is true on Berkeley systems but not System V. Since
6476 * System V doesn't have job control yet, this isn't a problem now.
6478 * Called with interrupts off.
6487 if (on == jobctl || rootshell == 0)
6491 ofd = fd = open(_PATH_TTY, O_RDWR);
6494 while (!isatty(fd) && --fd >= 0)
6497 fd = fcntl(fd, F_DUPFD, 10);
6501 fcntl(fd, F_SETFD, FD_CLOEXEC);
6502 do { /* while we are in the background */
6503 if ((pgrp = tcgetpgrp(fd)) < 0) {
6505 sh_warnx("can't access tty; job control turned off");
6509 if (pgrp == getpgrp())
6520 xtcsetpgrp(fd, pgrp);
6522 /* turning job control off */
6525 xtcsetpgrp(fd, pgrp);
6539 killcmd(int argc, char **argv)
6550 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6551 "kill -l [exitstatus]"
6555 if (**++argv == '-') {
6556 signo = decode_signal(*argv + 1, 1);
6560 while ((c = nextopt("ls:")) != '\0')
6570 signo = decode_signal(optionarg, 1);
6573 "invalid signal number or name: %s",
6584 if (!list && signo < 0)
6587 if ((signo < 0 || !*argv) ^ list) {
6595 for (i = 1; i < NSIG; i++) {
6596 name = u_signal_names(0, &i, 1);
6598 out1fmt(snlfmt, name);
6602 name = u_signal_names(*argptr, &signo, -1);
6604 out1fmt(snlfmt, name);
6606 sh_error("invalid signal number or exit status: %s", *argptr);
6612 if (**argv == '%') {
6613 jp = getjob(*argv, 0);
6614 pid = -jp->ps[0].pid;
6616 pid = **argv == '-' ?
6617 -number(*argv + 1) : number(*argv);
6619 if (kill(pid, signo) != 0) {
6620 sh_warnx("(%d) - %m", pid);
6629 #if defined(JOBS) || defined(DEBUG)
6631 jobno(const struct job *jp)
6633 return jp - jobtab + 1;
6639 fgcmd(int argc, char **argv)
6646 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6651 jp = getjob(*argv, 1);
6652 if (mode == FORK_BG) {
6653 set_curjob(jp, CUR_RUNNING);
6654 fprintf(out, "[%d] ", jobno(jp));
6656 outstr(jp->ps->cmd, out);
6658 retval = restartjob(jp, mode);
6659 } while (*argv && *++argv);
6663 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6667 restartjob(struct job *jp, int mode)
6669 struct procstat *ps;
6675 if (jp->state == JOBDONE)
6677 jp->state = JOBRUNNING;
6679 if (mode == FORK_FG)
6680 xtcsetpgrp(ttyfd, pgid);
6681 killpg(pgid, SIGCONT);
6685 if (WIFSTOPPED(ps->status)) {
6688 } while (ps++, --i);
6690 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6697 sprint_status(char *s, int status, int sigonly)
6703 if (!WIFEXITED(status)) {
6705 if (WIFSTOPPED(status))
6706 st = WSTOPSIG(status);
6709 st = WTERMSIG(status);
6711 if (st == SIGINT || st == SIGPIPE)
6714 if (WIFSTOPPED(status))
6719 col = fmtstr(s, 32, strsignal(st));
6720 if (WCOREDUMP(status)) {
6721 col += fmtstr(s + col, 16, " (core dumped)");
6723 } else if (!sigonly) {
6724 st = WEXITSTATUS(status);
6726 col = fmtstr(s, 16, "Done(%d)", st);
6728 col = fmtstr(s, 16, "Done");
6737 showjob(FILE *out, struct job *jp, int mode)
6739 struct procstat *ps;
6740 struct procstat *psend;
6747 if (mode & SHOW_PGID) {
6748 /* just output process (group) id of pipeline */
6749 fprintf(out, "%d\n", ps->pid);
6753 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6758 else if (curjob && jp == curjob->prev_job)
6761 if (mode & SHOW_PID)
6762 col += fmtstr(s + col, 16, "%d ", ps->pid);
6764 psend = ps + jp->nprocs;
6766 if (jp->state == JOBRUNNING) {
6767 scopy("Running", s + col);
6768 col += strlen("Running");
6770 int status = psend[-1].status;
6772 if (jp->state == JOBSTOPPED)
6773 status = jp->stopstatus;
6775 col += sprint_status(s + col, status, 0);
6781 /* for each process */
6782 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6785 fprintf(out, "%s%*c%s",
6786 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6788 if (!(mode & SHOW_PID)) {
6792 if (++ps == psend) {
6793 outcslow('\n', out);
6800 if (jp->state == JOBDONE) {
6801 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6808 jobscmd(int argc, char **argv)
6814 while ((m = nextopt("lp")))
6824 showjob(out, getjob(*argv,0), mode);
6827 showjobs(out, mode);
6834 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6835 * statuses have changed since the last call to showjobs.
6839 showjobs(FILE *out, int mode)
6843 TRACE(("showjobs(%x) called\n", mode));
6845 /* If not even one one job changed, there is nothing to do */
6846 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6849 for (jp = curjob; jp; jp = jp->prev_job) {
6850 if (!(mode & SHOW_CHANGED) || jp->changed)
6851 showjob(out, jp, mode);
6857 * Mark a job structure as unused.
6861 freejob(struct job *jp)
6863 struct procstat *ps;
6867 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6868 if (ps->cmd != nullstr)
6871 if (jp->ps != &jp->ps0)
6874 set_curjob(jp, CUR_DELETE);
6880 waitcmd(int argc, char **argv)
6893 /* wait for all jobs */
6898 /* no running procs */
6901 if (jp->state == JOBRUNNING)
6906 dowait(DOWAIT_BLOCK, 0);
6912 if (**argv != '%') {
6913 pid_t pid = number(*argv);
6917 if (job->ps[job->nprocs - 1].pid == pid)
6919 job = job->prev_job;
6925 job = getjob(*argv, 0);
6926 /* loop until process terminated or stopped */
6927 while (job->state == JOBRUNNING)
6928 dowait(DOWAIT_BLOCK, 0);
6930 retval = getstatus(job);
6941 * Convert a job name to a job structure.
6945 getjob(const char *name, int getctl)
6949 const char *err_msg = "No such job: %s";
6953 char *(*match)(const char *, const char *);
6968 if (c == '+' || c == '%') {
6970 err_msg = "No current job";
6972 } else if (c == '-') {
6975 err_msg = "No previous job";
6986 jp = jobtab + num - 1;
7003 if (match(jp->ps[0].cmd, p)) {
7007 err_msg = "%s: ambiguous";
7014 err_msg = "job %s not created under job control";
7015 if (getctl && jp->jobctl == 0)
7020 sh_error(err_msg, name);
7025 * Return a new job structure.
7026 * Called with interrupts off.
7030 makejob(union node *node, int nprocs)
7035 for (i = njobs, jp = jobtab ; ; jp++) {
7042 if (jp->state != JOBDONE || !jp->waited)
7051 memset(jp, 0, sizeof(*jp));
7056 jp->prev_job = curjob;
7061 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7063 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7073 struct job *jp, *jq;
7075 len = njobs * sizeof(*jp);
7077 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7079 offset = (char *)jp - (char *)jq;
7081 /* Relocate pointers */
7084 jq = (struct job *)((char *)jq + l);
7088 #define joff(p) ((struct job *)((char *)(p) + l))
7089 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7090 if (xlikely(joff(jp)->ps == &jq->ps0))
7091 jmove(joff(jp)->ps);
7092 if (joff(jp)->prev_job)
7093 jmove(joff(jp)->prev_job);
7103 jp = (struct job *)((char *)jp + len);
7107 } while (--jq >= jp);
7113 * Fork off a subshell. If we are doing job control, give the subshell its
7114 * own process group. Jp is a job structure that the job is to be added to.
7115 * N is the command that will be evaluated by the child. Both jp and n may
7116 * be NULL. The mode parameter can be one of the following:
7117 * FORK_FG - Fork off a foreground process.
7118 * FORK_BG - Fork off a background process.
7119 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7120 * process group even if job control is on.
7122 * When job control is turned off, background processes have their standard
7123 * input redirected to /dev/null (except for the second and later processes
7126 * Called with interrupts off.
7130 forkchild(struct job *jp, union node *n, int mode)
7134 TRACE(("Child shell %d\n", getpid()));
7141 /* do job control only in root shell */
7143 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7146 if (jp->nprocs == 0)
7149 pgrp = jp->ps[0].pid;
7150 /* This can fail because we are doing it in the parent also */
7151 (void)setpgid(0, pgrp);
7152 if (mode == FORK_FG)
7153 xtcsetpgrp(ttyfd, pgrp);
7158 if (mode == FORK_BG) {
7161 if (jp->nprocs == 0) {
7163 if (open(bb_dev_null, O_RDONLY) != 0)
7164 sh_error("Can't open %s", bb_dev_null);
7167 if (!oldlvl && iflag) {
7172 for (jp = curjob; jp; jp = jp->prev_job)
7178 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7180 TRACE(("In parent shell: child = %d\n", pid));
7182 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7187 if (mode != FORK_NOJOB && jp->jobctl) {
7190 if (jp->nprocs == 0)
7193 pgrp = jp->ps[0].pid;
7194 /* This can fail because we are doing it in the child also */
7195 (void)setpgid(pid, pgrp);
7198 if (mode == FORK_BG) {
7199 backgndpid = pid; /* set $! */
7200 set_curjob(jp, CUR_RUNNING);
7203 struct procstat *ps = &jp->ps[jp->nprocs++];
7209 ps->cmd = commandtext(n);
7215 forkshell(struct job *jp, union node *n, int mode)
7219 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7222 TRACE(("Fork failed, errno=%d", errno));
7225 sh_error("Cannot fork");
7228 forkchild(jp, n, mode);
7230 forkparent(jp, n, mode, pid);
7235 * Wait for job to finish.
7237 * Under job control we have the problem that while a child process is
7238 * running interrupts generated by the user are sent to the child but not
7239 * to the shell. This means that an infinite loop started by an inter-
7240 * active user may be hard to kill. With job control turned off, an
7241 * interactive user may place an interactive program inside a loop. If
7242 * the interactive program catches interrupts, the user doesn't want
7243 * these interrupts to also abort the loop. The approach we take here
7244 * is to have the shell ignore interrupt signals while waiting for a
7245 * foreground process to terminate, and then send itself an interrupt
7246 * signal if the child process was terminated by an interrupt signal.
7247 * Unfortunately, some programs want to do a bit of cleanup and then
7248 * exit on interrupt; unless these processes terminate themselves by
7249 * sending a signal to themselves (instead of calling exit) they will
7250 * confuse this approach.
7252 * Called with interrupts off.
7256 waitforjob(struct job *jp)
7260 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7261 while (jp->state == JOBRUNNING) {
7262 dowait(DOWAIT_BLOCK, jp);
7267 xtcsetpgrp(ttyfd, rootpid);
7269 * This is truly gross.
7270 * If we're doing job control, then we did a TIOCSPGRP which
7271 * caused us (the shell) to no longer be in the controlling
7272 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7273 * intuit from the subprocess exit status whether a SIGINT
7274 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7279 if (jp->state == JOBDONE)
7287 * Do a wait system call. If job control is compiled in, we accept
7288 * stopped processes. If block is zero, we return a value of zero
7289 * rather than blocking.
7291 * System V doesn't have a non-blocking wait system call. It does
7292 * have a SIGCLD signal that is sent to a process when one of it's
7293 * children dies. The obvious way to use SIGCLD would be to install
7294 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7295 * was received, and have waitproc bump another counter when it got
7296 * the status of a process. Waitproc would then know that a wait
7297 * system call would not block if the two counters were different.
7298 * This approach doesn't work because if a process has children that
7299 * have not been waited for, System V will send it a SIGCLD when it
7300 * installs a signal handler for SIGCLD. What this means is that when
7301 * a child exits, the shell will be sent SIGCLD signals continuously
7302 * until is runs out of stack space, unless it does a wait call before
7303 * restoring the signal handler. The code below takes advantage of
7304 * this (mis)feature by installing a signal handler for SIGCLD and
7305 * then checking to see whether it was called. If there are any
7306 * children to be waited for, it will be.
7308 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7309 * waits at all. In this case, the user will not be informed when
7310 * a background process until the next time she runs a real program
7311 * (as opposed to running a builtin command or just typing return),
7312 * and the jobs command may give out of date information.
7316 waitproc(int block, int *status)
7326 return wait3(status, flags, (struct rusage *)NULL);
7330 * Wait for a process to terminate.
7334 dowait(int block, struct job *job)
7339 struct job *thisjob;
7342 TRACE(("dowait(%d) called\n", block));
7343 pid = waitproc(block, &status);
7344 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7349 for (jp = curjob; jp; jp = jp->prev_job) {
7350 struct procstat *sp;
7351 struct procstat *spend;
7352 if (jp->state == JOBDONE)
7355 spend = jp->ps + jp->nprocs;
7358 if (sp->pid == pid) {
7359 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7360 sp->status = status;
7363 if (sp->status == -1)
7366 if (state == JOBRUNNING)
7368 if (WIFSTOPPED(sp->status)) {
7369 jp->stopstatus = sp->status;
7373 } while (++sp < spend);
7378 if (!WIFSTOPPED(status))
7385 if (state != JOBRUNNING) {
7386 thisjob->changed = 1;
7388 if (thisjob->state != state) {
7389 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7390 thisjob->state = state;
7392 if (state == JOBSTOPPED) {
7393 set_curjob(thisjob, CUR_STOPPED);
7402 if (thisjob && thisjob == job) {
7406 len = sprint_status(s, status, 1);
7418 * return 1 if there are stopped jobs, otherwise 0
7431 if (jp && jp->state == JOBSTOPPED) {
7432 out2str("You have stopped jobs.\n");
7442 * Return a string identifying a command (to be printed by the
7447 static char *cmdnextc;
7450 commandtext(union node *n)
7454 STARTSTACKSTR(cmdnextc);
7456 name = stackblock();
7457 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7458 name, cmdnextc, cmdnextc));
7459 return savestr(name);
7463 cmdtxt(union node *n)
7466 struct nodelist *lp;
7478 lp = n->npipe.cmdlist;
7496 cmdtxt(n->nbinary.ch1);
7512 cmdtxt(n->nif.test);
7515 if (n->nif.elsepart) {
7518 n = n->nif.elsepart;
7534 cmdtxt(n->nbinary.ch1);
7544 cmdputs(n->nfor.var);
7546 cmdlist(n->nfor.args, 1);
7551 cmdputs(n->narg.text);
7555 cmdlist(n->ncmd.args, 1);
7556 cmdlist(n->ncmd.redirect, 0);
7569 cmdputs(n->ncase.expr->narg.text);
7571 for (np = n->ncase.cases; np; np = np->nclist.next) {
7572 cmdtxt(np->nclist.pattern);
7574 cmdtxt(np->nclist.body);
7600 s[0] = n->nfile.fd + '0';
7604 if (n->type == NTOFD || n->type == NFROMFD) {
7605 s[0] = n->ndup.dupfd + '0';
7616 cmdlist(union node *np, int sep)
7618 for (; np; np = np->narg.next) {
7622 if (sep && np->narg.next)
7628 cmdputs(const char *s)
7630 const char *p, *str;
7631 char c, cc[2] = " ";
7635 static const char vstype[VSTYPE + 1][4] = {
7636 "", "}", "-", "+", "?", "=",
7637 "%", "%%", "#", "##"
7639 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7641 while ((c = *p++) != 0) {
7649 if ((subtype & VSTYPE) == VSLENGTH)
7653 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7660 str = "\"}" + !(quoted & 1);
7667 case CTLBACKQ+CTLQUOTE:
7670 #ifdef CONFIG_ASH_MATH_SUPPORT
7685 if ((subtype & VSTYPE) != VSNORMAL)
7687 str = vstype[subtype & VSTYPE];
7688 if (subtype & VSNUL)
7697 /* These can only happen inside quotes */
7710 while ((c = *str++)) {
7715 USTPUTC('"', nextc);
7723 showpipe(struct job *jp, FILE *out)
7725 struct procstat *sp;
7726 struct procstat *spend;
7728 spend = jp->ps + jp->nprocs;
7729 for (sp = jp->ps + 1; sp < spend; sp++)
7730 fprintf(out, " | %s", sp->cmd);
7731 outcslow('\n', out);
7736 xtcsetpgrp(int fd, pid_t pgrp)
7738 if (tcsetpgrp(fd, pgrp))
7739 sh_error("Cannot set tty process group (%m)");
7744 getstatus(struct job *job) {
7748 status = job->ps[job->nprocs - 1].status;
7749 retval = WEXITSTATUS(status);
7750 if (!WIFEXITED(status)) {
7752 retval = WSTOPSIG(status);
7753 if (!WIFSTOPPED(status))
7756 /* XXX: limits number of signals */
7757 retval = WTERMSIG(status);
7759 if (retval == SIGINT)
7765 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7766 jobno(job), job->nprocs, status, retval));
7770 #ifdef CONFIG_ASH_MAIL
7774 * Routines to check for mail. (Perhaps make part of main.c?)
7777 #define MAXMBOXES 10
7779 /* times of mailboxes */
7780 static time_t mailtime[MAXMBOXES];
7781 /* Set if MAIL or MAILPATH is changed. */
7782 static int mail_var_path_changed;
7787 * Print appropriate message(s) if mail has arrived.
7788 * If mail_var_path_changed is set,
7789 * then the value of MAIL has mail_var_path_changed,
7790 * so we just update the values.
7800 struct stackmark smark;
7803 setstackmark(&smark);
7804 mpath = mpathset() ? mpathval() : mailval();
7805 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7806 p = padvance(&mpath, nullstr);
7811 for (q = p ; *q ; q++);
7816 q[-1] = '\0'; /* delete trailing '/' */
7817 if (stat(p, &statb) < 0) {
7821 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7824 pathopt ? pathopt : "you have mail"
7827 *mtp = statb.st_mtime;
7829 mail_var_path_changed = 0;
7830 popstackmark(&smark);
7835 changemail(const char *val)
7837 mail_var_path_changed++;
7840 #endif /* CONFIG_ASH_MAIL */
7846 static short profile_buf[16384];
7850 static int isloginsh;
7852 static void read_profile(const char *);
7855 * Main routine. We initialize things, parse the arguments, execute
7856 * profiles if we're a login shell, and then call cmdloop to execute
7857 * commands. The setjmp call sets up the location to jump to when an
7858 * exception occurs. When an exception occurs the variable "state"
7859 * is used to figure out how far we had gotten.
7863 ash_main(int argc, char **argv)
7867 struct jmploc jmploc;
7868 struct stackmark smark;
7871 dash_errno = __errno_location();
7875 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7878 if (setjmp(jmploc.loc)) {
7888 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7892 outcslow('\n', stderr);
7894 popstackmark(&smark);
7895 FORCEINTON; /* enable interrupts */
7908 trputs("Shell args: "); trargs(argv);
7912 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7913 rseed = rootpid + ((time_t)time((time_t *)0));
7916 setstackmark(&smark);
7917 procargs(argc, argv);
7918 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7920 const char *hp = lookupvar("HISTFILE");
7923 hp = lookupvar("HOME");
7925 char *defhp = concat_path_file(hp, ".ash_history");
7926 setvar("HISTFILE", defhp, 0);
7932 if (argv[0] && argv[0][0] == '-')
7936 read_profile("/etc/profile");
7939 read_profile(".profile");
7945 getuid() == geteuid() && getgid() == getegid() &&
7949 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7950 read_profile(shinit);
7956 evalstring(minusc, 0);
7958 if (sflag || minusc == NULL) {
7959 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7961 const char *hp = lookupvar("HISTFILE");
7964 load_history ( hp );
7967 state4: /* XXX ??? - why isn't this before the "if" statement */
7975 extern void _mcleanup(void);
7985 * Read and execute commands. "Top" is nonzero for the top level command
7986 * loop; it turns on prompting if the shell is interactive.
7993 struct stackmark smark;
7997 TRACE(("cmdloop(%d) called\n", top));
8001 setstackmark(&smark);
8004 showjobs(stderr, SHOW_CHANGED);
8009 #ifdef CONFIG_ASH_MAIL
8013 n = parsecmd(inter);
8014 /* showtree(n); DEBUG */
8016 if (!top || numeof >= 50)
8018 if (!stoppedjobs()) {
8021 out2str("\nUse \"exit\" to leave shell.\n");
8024 } else if (nflag == 0) {
8025 job_warning = (job_warning == 2) ? 1 : 0;
8029 popstackmark(&smark);
8034 return skip & SKIPEVAL;
8043 * Read /etc/profile or .profile. Return on error.
8047 read_profile(const char *name)
8051 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8063 * Read a file containing shell functions.
8067 readcmdfile(char *name)
8069 setinputfile(name, INPUT_PUSH_FILE);
8076 * Take commands from a file. To be compatible we should do a path
8077 * search for the file, which is necessary to find sub-commands.
8080 static inline char *
8081 find_dot_file(char *name)
8084 const char *path = pathval();
8087 /* don't try this for absolute or relative paths */
8088 if (strchr(name, '/'))
8091 while ((fullname = padvance(&path, name)) != NULL) {
8092 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8094 * Don't bother freeing here, since it will
8095 * be freed by the caller.
8099 stunalloc(fullname);
8102 /* not found in the PATH */
8103 sh_error(not_found_msg, name);
8107 static int dotcmd(int argc, char **argv)
8110 volatile struct shparam saveparam;
8113 for (sp = cmdenviron; sp; sp = sp->next)
8114 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8116 if (argc >= 2) { /* That's what SVR2 does */
8119 fullname = find_dot_file(argv[1]);
8122 saveparam = shellparam;
8123 shellparam.malloc = 0;
8124 shellparam.nparam = argc - 2;
8125 shellparam.p = argv + 2;
8128 setinputfile(fullname, INPUT_PUSH_FILE);
8129 commandname = fullname;
8134 freeparam(&shellparam);
8135 shellparam = saveparam;
8137 status = exitstatus;
8144 exitcmd(int argc, char **argv)
8149 exitstatus = number(argv[1]);
8154 #ifdef CONFIG_ASH_BUILTIN_ECHO
8156 echocmd(int argc, char **argv)
8158 return bb_echo(argc, argv);
8162 #ifdef CONFIG_ASH_BUILTIN_TEST
8164 testcmd(int argc, char **argv)
8166 return bb_test(argc, argv);
8173 * Same for malloc, realloc, but returns an error when out of space.
8177 ckrealloc(pointer p, size_t nbytes)
8179 p = realloc(p, nbytes);
8181 sh_error(bb_msg_memory_exhausted);
8186 ckmalloc(size_t nbytes)
8188 return ckrealloc(NULL, nbytes);
8192 * Make a copy of a string in safe storage.
8196 savestr(const char *s)
8198 char *p = strdup(s);
8200 sh_error(bb_msg_memory_exhausted);
8206 * Parse trees for commands are allocated in lifo order, so we use a stack
8207 * to make this more efficient, and also to avoid all sorts of exception
8208 * handling code to handle interrupts in the middle of a parse.
8210 * The size 504 was chosen because the Ultrix malloc handles that size
8216 stalloc(size_t nbytes)
8221 aligned = SHELL_ALIGN(nbytes);
8222 if (aligned > stacknleft) {
8225 struct stack_block *sp;
8227 blocksize = aligned;
8228 if (blocksize < MINSIZE)
8229 blocksize = MINSIZE;
8230 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8231 if (len < blocksize)
8232 sh_error(bb_msg_memory_exhausted);
8236 stacknxt = sp->space;
8237 stacknleft = blocksize;
8238 sstrend = stacknxt + blocksize;
8243 stacknxt += aligned;
8244 stacknleft -= aligned;
8250 stunalloc(pointer p)
8253 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8254 write(2, "stunalloc\n", 10);
8258 stacknleft += stacknxt - (char *)p;
8264 setstackmark(struct stackmark *mark)
8266 mark->stackp = stackp;
8267 mark->stacknxt = stacknxt;
8268 mark->stacknleft = stacknleft;
8269 mark->marknext = markp;
8275 popstackmark(struct stackmark *mark)
8277 struct stack_block *sp;
8280 markp = mark->marknext;
8281 while (stackp != mark->stackp) {
8286 stacknxt = mark->stacknxt;
8287 stacknleft = mark->stacknleft;
8288 sstrend = mark->stacknxt + mark->stacknleft;
8294 * When the parser reads in a string, it wants to stick the string on the
8295 * stack and only adjust the stack pointer when it knows how big the
8296 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8297 * of space on top of the stack and stackblocklen returns the length of
8298 * this block. Growstackblock will grow this space by at least one byte,
8299 * possibly moving it (like realloc). Grabstackblock actually allocates the
8300 * part of the block that has been used.
8304 growstackblock(void)
8308 newlen = stacknleft * 2;
8309 if (newlen < stacknleft)
8310 sh_error(bb_msg_memory_exhausted);
8314 if (stacknxt == stackp->space && stackp != &stackbase) {
8315 struct stack_block *oldstackp;
8316 struct stackmark *xmark;
8317 struct stack_block *sp;
8318 struct stack_block *prevstackp;
8324 prevstackp = sp->prev;
8325 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8326 sp = ckrealloc((pointer)sp, grosslen);
8327 sp->prev = prevstackp;
8329 stacknxt = sp->space;
8330 stacknleft = newlen;
8331 sstrend = sp->space + newlen;
8334 * Stack marks pointing to the start of the old block
8335 * must be relocated to point to the new block
8338 while (xmark != NULL && xmark->stackp == oldstackp) {
8339 xmark->stackp = stackp;
8340 xmark->stacknxt = stacknxt;
8341 xmark->stacknleft = stacknleft;
8342 xmark = xmark->marknext;
8346 char *oldspace = stacknxt;
8347 int oldlen = stacknleft;
8348 char *p = stalloc(newlen);
8350 /* free the space we just allocated */
8351 stacknxt = memcpy(p, oldspace, oldlen);
8352 stacknleft += newlen;
8357 grabstackblock(size_t len)
8359 len = SHELL_ALIGN(len);
8365 * The following routines are somewhat easier to use than the above.
8366 * The user declares a variable of type STACKSTR, which may be declared
8367 * to be a register. The macro STARTSTACKSTR initializes things. Then
8368 * the user uses the macro STPUTC to add characters to the string. In
8369 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8370 * grown as necessary. When the user is done, she can just leave the
8371 * string there and refer to it using stackblock(). Or she can allocate
8372 * the space for it using grabstackstr(). If it is necessary to allow
8373 * someone else to use the stack temporarily and then continue to grow
8374 * the string, the user should use grabstack to allocate the space, and
8375 * then call ungrabstr(p) to return to the previous mode of operation.
8377 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8378 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8379 * is space for at least one character.
8385 size_t len = stackblocksize();
8386 if (herefd >= 0 && len >= 1024) {
8387 bb_full_write(herefd, stackblock(), len);
8388 return stackblock();
8391 return stackblock() + len;
8395 * Called from CHECKSTRSPACE.
8399 makestrspace(size_t newlen, char *p)
8401 size_t len = p - stacknxt;
8402 size_t size = stackblocksize();
8407 size = stackblocksize();
8409 if (nleft >= newlen)
8413 return stackblock() + len;
8417 stnputs(const char *s, size_t n, char *p)
8419 p = makestrspace(n, p);
8420 p = mempcpy(p, s, n);
8425 stputs(const char *s, char *p)
8427 return stnputs(s, strlen(s), p);
8435 * number(s) Convert a string of digits to an integer.
8436 * is_number(s) Return true if s is a string of digits.
8440 * prefix -- see if pfx is a prefix of string.
8444 prefix(const char *string, const char *pfx)
8447 if (*pfx++ != *string++)
8450 return (char *) string;
8455 * Convert a string of digits to an integer, printing an error message on
8460 number(const char *s)
8464 sh_error(illnum, s);
8470 * Check for a valid number. This should be elsewhere.
8474 is_number(const char *p)
8479 } while (*++p != '\0');
8485 * Produce a possibly single quoted string suitable as input to the shell.
8486 * The return string is allocated on the stack.
8490 single_quote(const char *s) {
8499 len = strchrnul(s, '\'') - s;
8501 q = p = makestrspace(len + 3, p);
8504 q = mempcpy(q, s, len);
8510 len = strspn(s, "'");
8514 q = p = makestrspace(len + 3, p);
8517 q = mempcpy(q, s, len);
8526 return stackblock();
8530 * Like strdup but works with the ash stack.
8534 sstrdup(const char *p)
8536 size_t len = strlen(p) + 1;
8537 return memcpy(stalloc(len), p, len);
8542 calcsize(union node *n)
8546 funcblocksize += nodesize[n->type];
8549 calcsize(n->ncmd.redirect);
8550 calcsize(n->ncmd.args);
8551 calcsize(n->ncmd.assign);
8554 sizenodelist(n->npipe.cmdlist);
8559 calcsize(n->nredir.redirect);
8560 calcsize(n->nredir.n);
8567 calcsize(n->nbinary.ch2);
8568 calcsize(n->nbinary.ch1);
8571 calcsize(n->nif.elsepart);
8572 calcsize(n->nif.ifpart);
8573 calcsize(n->nif.test);
8576 funcstringsize += strlen(n->nfor.var) + 1;
8577 calcsize(n->nfor.body);
8578 calcsize(n->nfor.args);
8581 calcsize(n->ncase.cases);
8582 calcsize(n->ncase.expr);
8585 calcsize(n->nclist.body);
8586 calcsize(n->nclist.pattern);
8587 calcsize(n->nclist.next);
8591 sizenodelist(n->narg.backquote);
8592 funcstringsize += strlen(n->narg.text) + 1;
8593 calcsize(n->narg.next);
8600 calcsize(n->nfile.fname);
8601 calcsize(n->nfile.next);
8605 calcsize(n->ndup.vname);
8606 calcsize(n->ndup.next);
8610 calcsize(n->nhere.doc);
8611 calcsize(n->nhere.next);
8614 calcsize(n->nnot.com);
8621 sizenodelist(struct nodelist *lp)
8624 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8632 copynode(union node *n)
8639 funcblock = (char *) funcblock + nodesize[n->type];
8642 new->ncmd.redirect = copynode(n->ncmd.redirect);
8643 new->ncmd.args = copynode(n->ncmd.args);
8644 new->ncmd.assign = copynode(n->ncmd.assign);
8647 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8648 new->npipe.backgnd = n->npipe.backgnd;
8653 new->nredir.redirect = copynode(n->nredir.redirect);
8654 new->nredir.n = copynode(n->nredir.n);
8661 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8662 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8665 new->nif.elsepart = copynode(n->nif.elsepart);
8666 new->nif.ifpart = copynode(n->nif.ifpart);
8667 new->nif.test = copynode(n->nif.test);
8670 new->nfor.var = nodesavestr(n->nfor.var);
8671 new->nfor.body = copynode(n->nfor.body);
8672 new->nfor.args = copynode(n->nfor.args);
8675 new->ncase.cases = copynode(n->ncase.cases);
8676 new->ncase.expr = copynode(n->ncase.expr);
8679 new->nclist.body = copynode(n->nclist.body);
8680 new->nclist.pattern = copynode(n->nclist.pattern);
8681 new->nclist.next = copynode(n->nclist.next);
8685 new->narg.backquote = copynodelist(n->narg.backquote);
8686 new->narg.text = nodesavestr(n->narg.text);
8687 new->narg.next = copynode(n->narg.next);
8694 new->nfile.fname = copynode(n->nfile.fname);
8695 new->nfile.fd = n->nfile.fd;
8696 new->nfile.next = copynode(n->nfile.next);
8700 new->ndup.vname = copynode(n->ndup.vname);
8701 new->ndup.dupfd = n->ndup.dupfd;
8702 new->ndup.fd = n->ndup.fd;
8703 new->ndup.next = copynode(n->ndup.next);
8707 new->nhere.doc = copynode(n->nhere.doc);
8708 new->nhere.fd = n->nhere.fd;
8709 new->nhere.next = copynode(n->nhere.next);
8712 new->nnot.com = copynode(n->nnot.com);
8715 new->type = n->type;
8720 static struct nodelist *
8721 copynodelist(struct nodelist *lp)
8723 struct nodelist *start;
8724 struct nodelist **lpp;
8729 funcblock = (char *) funcblock +
8730 SHELL_ALIGN(sizeof(struct nodelist));
8731 (*lpp)->n = copynode(lp->n);
8733 lpp = &(*lpp)->next;
8741 nodesavestr(char *s)
8743 char *rtn = funcstring;
8745 funcstring = stpcpy(funcstring, s) + 1;
8751 * Free a parse tree.
8755 freefunc(struct funcnode *f)
8757 if (f && --f->count < 0)
8762 static void options(int);
8763 static void setoption(int, int);
8767 * Process the shell command line arguments.
8771 procargs(int argc, char **argv)
8774 const char *xminusc;
8781 for (i = 0; i < NOPTS; i++)
8787 if (*xargv == NULL) {
8789 sh_error(bb_msg_requires_arg, "-c");
8792 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8796 for (i = 0; i < NOPTS; i++)
8797 if (optlist[i] == 2)
8802 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8807 } else if (!sflag) {
8808 setinputfile(*xargv, 0);
8814 shellparam.p = xargv;
8815 #ifdef CONFIG_ASH_GETOPTS
8816 shellparam.optind = 1;
8817 shellparam.optoff = -1;
8819 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8821 shellparam.nparam++;
8834 setinteractive(iflag);
8840 minus_o(char *name, int val)
8845 out1str("Current option settings\n");
8846 for (i = 0; i < NOPTS; i++)
8847 out1fmt("%-16s%s\n", optnames(i),
8848 optlist[i] ? "on" : "off");
8850 for (i = 0; i < NOPTS; i++)
8851 if (equal(name, optnames(i))) {
8855 sh_error("Illegal option -o %s", name);
8860 * Process shell options. The global variable argptr contains a pointer
8861 * to the argument list; we advance it past the options.
8865 options(int cmdline)
8873 while ((p = *argptr) != NULL) {
8875 if ((c = *p++) == '-') {
8877 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8879 /* "-" means turn off -x and -v */
8882 /* "--" means reset params */
8883 else if (*argptr == NULL)
8886 break; /* "-" or "--" terminates options */
8888 } else if (c == '+') {
8894 while ((c = *p++) != '\0') {
8895 if (c == 'c' && cmdline) {
8896 minusc = p; /* command is after shell args*/
8897 } else if (c == 'o') {
8898 minus_o(*argptr, val);
8901 } else if (cmdline && (c == '-')) { // long options
8902 if (strcmp(p, "login") == 0)
8914 setoption(int flag, int val)
8918 for (i = 0; i < NOPTS; i++)
8919 if (optletters(i) == flag) {
8923 sh_error("Illegal option -%c", flag);
8930 * Set the shell parameters.
8934 setparam(char **argv)
8940 for (nparam = 0 ; argv[nparam] ; nparam++);
8941 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8943 *ap++ = savestr(*argv++);
8946 freeparam(&shellparam);
8947 shellparam.malloc = 1;
8948 shellparam.nparam = nparam;
8949 shellparam.p = newparam;
8950 #ifdef CONFIG_ASH_GETOPTS
8951 shellparam.optind = 1;
8952 shellparam.optoff = -1;
8958 * Free the list of positional parameters.
8962 freeparam(volatile struct shparam *param)
8966 if (param->malloc) {
8967 for (ap = param->p ; *ap ; ap++)
8976 * The shift builtin command.
8980 shiftcmd(int argc, char **argv)
8987 n = number(argv[1]);
8988 if (n > shellparam.nparam)
8989 sh_error("can't shift that many");
8991 shellparam.nparam -= n;
8992 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8993 if (shellparam.malloc)
8997 while ((*ap2++ = *ap1++) != NULL);
8998 #ifdef CONFIG_ASH_GETOPTS
8999 shellparam.optind = 1;
9000 shellparam.optoff = -1;
9009 * The set command builtin.
9013 setcmd(int argc, char **argv)
9016 return showvars(nullstr, 0, VUNSET);
9020 if (*argptr != NULL) {
9028 #ifdef CONFIG_ASH_GETOPTS
9033 shellparam.optind = number(value);
9034 shellparam.optoff = -1;
9038 #ifdef CONFIG_LOCALE_SUPPORT
9039 static void change_lc_all(const char *value)
9041 if (value != 0 && *value != 0)
9042 setlocale(LC_ALL, value);
9045 static void change_lc_ctype(const char *value)
9047 if (value != 0 && *value != 0)
9048 setlocale(LC_CTYPE, value);
9053 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9054 /* Roughly copied from bash.. */
9055 static void change_random(const char *value)
9058 /* "get", generate */
9061 rseed = rseed * 1103515245 + 12345;
9062 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9063 /* set without recursion */
9064 setvar(vrandom.text, buf, VNOFUNC);
9065 vrandom.flags &= ~VNOFUNC;
9068 rseed = strtoul(value, (char **)NULL, 10);
9074 #ifdef CONFIG_ASH_GETOPTS
9076 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9085 if(*param_optind < 1)
9087 optnext = optfirst + *param_optind - 1;
9089 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9092 p = optnext[-1] + *optoff;
9093 if (p == NULL || *p == '\0') {
9094 /* Current word is done, advance */
9096 if (p == NULL || *p != '-' || *++p == '\0') {
9103 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9108 for (q = optstr; *q != c; ) {
9110 if (optstr[0] == ':') {
9113 err |= setvarsafe("OPTARG", s, 0);
9115 fprintf(stderr, "Illegal option -%c\n", c);
9116 (void) unsetvar("OPTARG");
9126 if (*p == '\0' && (p = *optnext) == NULL) {
9127 if (optstr[0] == ':') {
9130 err |= setvarsafe("OPTARG", s, 0);
9133 fprintf(stderr, "No arg for -%c option\n", c);
9134 (void) unsetvar("OPTARG");
9142 err |= setvarsafe("OPTARG", p, 0);
9145 err |= setvarsafe("OPTARG", nullstr, 0);
9148 *optoff = p ? p - *(optnext - 1) : -1;
9149 *param_optind = optnext - optfirst + 1;
9150 fmtstr(s, sizeof(s), "%d", *param_optind);
9151 err |= setvarsafe("OPTIND", s, VNOFUNC);
9154 err |= setvarsafe(optvar, s, 0);
9165 * The getopts builtin. Shellparam.optnext points to the next argument
9166 * to be processed. Shellparam.optptr points to the next character to
9167 * be processed in the current argument. If shellparam.optnext is NULL,
9168 * then it's the first time getopts has been called.
9172 getoptscmd(int argc, char **argv)
9177 sh_error("Usage: getopts optstring var [arg]");
9178 else if (argc == 3) {
9179 optbase = shellparam.p;
9180 if (shellparam.optind > shellparam.nparam + 1) {
9181 shellparam.optind = 1;
9182 shellparam.optoff = -1;
9187 if (shellparam.optind > argc - 2) {
9188 shellparam.optind = 1;
9189 shellparam.optoff = -1;
9193 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9194 &shellparam.optoff);
9196 #endif /* CONFIG_ASH_GETOPTS */
9199 * XXX - should get rid of. have all builtins use getopt(3). the
9200 * library getopt must have the BSD extension static variable "optreset"
9201 * otherwise it can't be used within the shell safely.
9203 * Standard option processing (a la getopt) for builtin routines. The
9204 * only argument that is passed to nextopt is the option string; the
9205 * other arguments are unnecessary. It return the character, or '\0' on
9210 nextopt(const char *optstring)
9216 if ((p = optptr) == NULL || *p == '\0') {
9218 if (p == NULL || *p != '-' || *++p == '\0')
9221 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9225 for (q = optstring ; *q != c ; ) {
9227 sh_error("Illegal option -%c", c);
9232 if (*p == '\0' && (p = *argptr++) == NULL)
9233 sh_error("No arg for -%c option", c);
9245 outstr(const char *p, FILE *file)
9270 outcslow(int c, FILE *dest)
9280 out1fmt(const char *fmt, ...)
9287 r = vprintf(fmt, ap);
9295 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9302 ret = vsnprintf(outbuf, length, fmt, ap);
9314 * Shell command parser.
9317 #define EOFMARKLEN 79
9321 struct heredoc *next; /* next here document in list */
9322 union node *here; /* redirection node */
9323 char *eofmark; /* string indicating end of input */
9324 int striptabs; /* if set, strip leading tabs */
9329 static struct heredoc *heredoclist; /* list of here documents to read */
9332 static union node *list(int);
9333 static union node *andor(void);
9334 static union node *pipeline(void);
9335 static union node *command(void);
9336 static union node *simplecmd(void);
9337 static union node *makename(void);
9338 static void parsefname(void);
9339 static void parseheredoc(void);
9340 static char peektoken(void);
9341 static int readtoken(void);
9342 static int xxreadtoken(void);
9343 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9344 static int noexpand(char *);
9345 static void synexpect(int) ATTRIBUTE_NORETURN;
9346 static void synerror(const char *) ATTRIBUTE_NORETURN;
9347 static void setprompt(int);
9353 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9354 * valid parse tree indicating a blank line.)
9358 parsecmd(int interact)
9363 doprompt = interact;
9365 setprompt(doprompt);
9380 union node *n1, *n2, *n3;
9383 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9384 if (nlflag == 2 && peektoken())
9390 if (tok == TBACKGND) {
9391 if (n2->type == NPIPE) {
9392 n2->npipe.backgnd = 1;
9394 if (n2->type != NREDIR) {
9395 n3 = stalloc(sizeof(struct nredir));
9397 n3->nredir.redirect = NULL;
9400 n2->type = NBACKGND;
9407 n3 = (union node *)stalloc(sizeof (struct nbinary));
9409 n3->nbinary.ch1 = n1;
9410 n3->nbinary.ch2 = n2;
9426 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9434 pungetc(); /* push back EOF on input */
9450 union node *n1, *n2, *n3;
9455 if ((t = readtoken()) == TAND) {
9457 } else if (t == TOR) {
9463 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9465 n3 = (union node *)stalloc(sizeof (struct nbinary));
9467 n3->nbinary.ch1 = n1;
9468 n3->nbinary.ch2 = n2;
9478 union node *n1, *n2, *pipenode;
9479 struct nodelist *lp, *prev;
9483 TRACE(("pipeline: entered\n"));
9484 if (readtoken() == TNOT) {
9486 checkkwd = CHKKWD | CHKALIAS;
9490 if (readtoken() == TPIPE) {
9491 pipenode = (union node *)stalloc(sizeof (struct npipe));
9492 pipenode->type = NPIPE;
9493 pipenode->npipe.backgnd = 0;
9494 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9495 pipenode->npipe.cmdlist = lp;
9499 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9500 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9503 } while (readtoken() == TPIPE);
9509 n2 = (union node *)stalloc(sizeof (struct nnot));
9522 union node *n1, *n2;
9523 union node *ap, **app;
9524 union node *cp, **cpp;
9525 union node *redir, **rpp;
9532 switch (readtoken()) {
9537 n1 = (union node *)stalloc(sizeof (struct nif));
9539 n1->nif.test = list(0);
9540 if (readtoken() != TTHEN)
9542 n1->nif.ifpart = list(0);
9544 while (readtoken() == TELIF) {
9545 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9546 n2 = n2->nif.elsepart;
9548 n2->nif.test = list(0);
9549 if (readtoken() != TTHEN)
9551 n2->nif.ifpart = list(0);
9553 if (lasttoken == TELSE)
9554 n2->nif.elsepart = list(0);
9556 n2->nif.elsepart = NULL;
9564 n1 = (union node *)stalloc(sizeof (struct nbinary));
9565 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9566 n1->nbinary.ch1 = list(0);
9567 if ((got=readtoken()) != TDO) {
9568 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9571 n1->nbinary.ch2 = list(0);
9576 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9577 synerror("Bad for loop variable");
9578 n1 = (union node *)stalloc(sizeof (struct nfor));
9580 n1->nfor.var = wordtext;
9581 checkkwd = CHKKWD | CHKALIAS;
9582 if (readtoken() == TIN) {
9584 while (readtoken() == TWORD) {
9585 n2 = (union node *)stalloc(sizeof (struct narg));
9587 n2->narg.text = wordtext;
9588 n2->narg.backquote = backquotelist;
9590 app = &n2->narg.next;
9594 if (lasttoken != TNL && lasttoken != TSEMI)
9597 n2 = (union node *)stalloc(sizeof (struct narg));
9599 n2->narg.text = (char *)dolatstr;
9600 n2->narg.backquote = NULL;
9601 n2->narg.next = NULL;
9604 * Newline or semicolon here is optional (but note
9605 * that the original Bourne shell only allowed NL).
9607 if (lasttoken != TNL && lasttoken != TSEMI)
9610 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9611 if (readtoken() != TDO)
9613 n1->nfor.body = list(0);
9617 n1 = (union node *)stalloc(sizeof (struct ncase));
9619 if (readtoken() != TWORD)
9621 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9623 n2->narg.text = wordtext;
9624 n2->narg.backquote = backquotelist;
9625 n2->narg.next = NULL;
9627 checkkwd = CHKKWD | CHKALIAS;
9628 } while (readtoken() == TNL);
9629 if (lasttoken != TIN)
9631 cpp = &n1->ncase.cases;
9633 checkkwd = CHKNL | CHKKWD;
9636 if (lasttoken == TLP)
9638 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9640 app = &cp->nclist.pattern;
9642 *app = ap = (union node *)stalloc(sizeof (struct narg));
9644 ap->narg.text = wordtext;
9645 ap->narg.backquote = backquotelist;
9646 if (readtoken() != TPIPE)
9648 app = &ap->narg.next;
9651 ap->narg.next = NULL;
9652 if (lasttoken != TRP)
9654 cp->nclist.body = list(2);
9656 cpp = &cp->nclist.next;
9658 checkkwd = CHKNL | CHKKWD;
9659 if ((t = readtoken()) != TESAC) {
9661 synexpect(TENDCASE);
9669 n1 = (union node *)stalloc(sizeof (struct nredir));
9670 n1->type = NSUBSHELL;
9671 n1->nredir.n = list(0);
9672 n1->nredir.redirect = NULL;
9685 if (readtoken() != t)
9689 /* Now check for redirection which may follow command */
9690 checkkwd = CHKKWD | CHKALIAS;
9692 while (readtoken() == TREDIR) {
9693 *rpp = n2 = redirnode;
9694 rpp = &n2->nfile.next;
9700 if (n1->type != NSUBSHELL) {
9701 n2 = (union node *)stalloc(sizeof (struct nredir));
9706 n1->nredir.redirect = redir;
9715 union node *args, **app;
9716 union node *n = NULL;
9717 union node *vars, **vpp;
9718 union node **rpp, *redir;
9728 savecheckkwd = CHKALIAS;
9730 checkkwd = savecheckkwd;
9731 switch (readtoken()) {
9733 n = (union node *)stalloc(sizeof (struct narg));
9735 n->narg.text = wordtext;
9736 n->narg.backquote = backquotelist;
9737 if (savecheckkwd && isassignment(wordtext)) {
9739 vpp = &n->narg.next;
9742 app = &n->narg.next;
9747 *rpp = n = redirnode;
9748 rpp = &n->nfile.next;
9749 parsefname(); /* read name of redirection file */
9753 args && app == &args->narg.next &&
9756 struct builtincmd *bcmd;
9759 /* We have a function */
9760 if (readtoken() != TRP)
9762 name = n->narg.text;
9764 !goodname(name) || (
9765 (bcmd = find_builtin(name)) &&
9766 IS_BUILTIN_SPECIAL(bcmd)
9769 synerror("Bad function name");
9771 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9772 n->narg.next = command();
9785 n = (union node *)stalloc(sizeof (struct ncmd));
9787 n->ncmd.args = args;
9788 n->ncmd.assign = vars;
9789 n->ncmd.redirect = redir;
9798 n = (union node *)stalloc(sizeof (struct narg));
9800 n->narg.next = NULL;
9801 n->narg.text = wordtext;
9802 n->narg.backquote = backquotelist;
9806 void fixredir(union node *n, const char *text, int err)
9808 TRACE(("Fix redir %s %d\n", text, err));
9810 n->ndup.vname = NULL;
9812 if (is_digit(text[0]) && text[1] == '\0')
9813 n->ndup.dupfd = digit_val(text[0]);
9814 else if (text[0] == '-' && text[1] == '\0')
9819 synerror("Bad fd number");
9821 n->ndup.vname = makename();
9829 union node *n = redirnode;
9831 if (readtoken() != TWORD)
9833 if (n->type == NHERE) {
9834 struct heredoc *here = heredoc;
9840 TRACE(("Here document %d\n", n->type));
9841 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9842 synerror("Illegal eof marker for << redirection");
9843 rmescapes(wordtext);
9844 here->eofmark = wordtext;
9846 if (heredoclist == NULL)
9849 for (p = heredoclist ; p->next ; p = p->next);
9852 } else if (n->type == NTOFD || n->type == NFROMFD) {
9853 fixredir(n, wordtext, 0);
9855 n->nfile.fname = makename();
9861 * Input any here documents.
9867 struct heredoc *here;
9877 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9878 here->eofmark, here->striptabs);
9879 n = (union node *)stalloc(sizeof (struct narg));
9880 n->narg.type = NARG;
9881 n->narg.next = NULL;
9882 n->narg.text = wordtext;
9883 n->narg.backquote = backquotelist;
9884 here->here->nhere.doc = n;
9889 static char peektoken(void)
9895 return tokname_array[t][0];
9903 int alreadyseen = tokpushback;
9906 #ifdef CONFIG_ASH_ALIAS
9915 if (checkkwd & CHKNL) {
9922 if (t != TWORD || quoteflag) {
9927 * check for keywords
9929 if (checkkwd & CHKKWD) {
9930 const char *const *pp;
9932 if ((pp = findkwd(wordtext))) {
9933 lasttoken = t = pp - tokname_array;
9934 TRACE(("keyword %s recognized\n", tokname(t)));
9939 if (checkkwd & CHKALIAS) {
9940 #ifdef CONFIG_ASH_ALIAS
9942 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9944 pushstring(ap->val, ap);
9954 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9956 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9963 * Read the next input token.
9964 * If the token is a word, we set backquotelist to the list of cmds in
9965 * backquotes. We set quoteflag to true if any part of the word was
9967 * If the token is TREDIR, then we set redirnode to a structure containing
9969 * In all cases, the variable startlinno is set to the number of the line
9970 * on which the token starts.
9972 * [Change comment: here documents and internal procedures]
9973 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9974 * word parsing code into a separate routine. In this case, readtoken
9975 * doesn't need to have any internal procedures, but parseword does.
9976 * We could also make parseoperator in essence the main routine, and
9977 * have parseword (readtoken1?) handle both words and redirection.]
9980 #define NEW_xxreadtoken
9981 #ifdef NEW_xxreadtoken
9983 /* singles must be first! */
9984 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9986 static const char xxreadtoken_tokens[] = {
9987 TNL, TLP, TRP, /* only single occurrence allowed */
9988 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9989 TEOF, /* corresponds to trailing nul */
9990 TAND, TOR, TENDCASE, /* if double occurrence */
9993 #define xxreadtoken_doubles \
9994 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9995 #define xxreadtoken_singles \
9996 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9998 static int xxreadtoken()
10009 startlinno = plinno;
10010 for (;;) { /* until token or start of word found */
10013 if ((c != ' ') && (c != '\t')
10014 #ifdef CONFIG_ASH_ALIAS
10019 while ((c = pgetc()) != '\n' && c != PEOF);
10021 } else if (c == '\\') {
10022 if (pgetc() != '\n') {
10026 startlinno = ++plinno;
10031 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10036 needprompt = doprompt;
10039 p = strchr(xxreadtoken_chars, c);
10042 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10045 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10046 if (pgetc() == *p) { /* double occurrence? */
10047 p += xxreadtoken_doubles + 1;
10054 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10062 #define RETURN(token) return lasttoken = token
10076 startlinno = plinno;
10077 for (;;) { /* until token or start of word found */
10080 case ' ': case '\t':
10081 #ifdef CONFIG_ASH_ALIAS
10086 while ((c = pgetc()) != '\n' && c != PEOF);
10090 if (pgetc() == '\n') {
10091 startlinno = ++plinno;
10100 needprompt = doprompt;
10105 if (pgetc() == '&')
10110 if (pgetc() == '|')
10115 if (pgetc() == ';')
10128 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10131 #endif /* NEW_xxreadtoken */
10135 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10136 * is not NULL, read a here document. In the latter case, eofmark is the
10137 * word which marks the end of the document and striptabs is true if
10138 * leading tabs should be stripped from the document. The argument firstc
10139 * is the first character of the input token or document.
10141 * Because C does not have internal subroutines, I have simulated them
10142 * using goto's to implement the subroutine linkage. The following macros
10143 * will run code that appears at the end of readtoken1.
10146 #define CHECKEND() {goto checkend; checkend_return:;}
10147 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10148 #define PARSESUB() {goto parsesub; parsesub_return:;}
10149 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10150 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10151 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10154 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10159 char line[EOFMARKLEN + 1];
10160 struct nodelist *bqlist = 0;
10163 int varnest = 0; /* levels of variables expansion */
10164 int arinest = 0; /* levels of arithmetic expansion */
10165 int parenlevel = 0; /* levels of parens in arithmetic */
10166 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10168 int prevsyntax = 0; /* syntax before arithmetic */
10170 /* Avoid longjmp clobbering */
10176 (void) &parenlevel;
10179 (void) &prevsyntax;
10183 startlinno = plinno;
10185 if (syntax == DQSYNTAX)
10194 STARTSTACKSTR(out);
10195 loop: { /* for each line, until end of word */
10196 CHECKEND(); /* set c to PEOF if at end of here document */
10197 for (;;) { /* until end of line or end of word */
10198 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10199 switch(SIT(c, syntax)) {
10200 case CNL: /* '\n' */
10201 if (syntax == BASESYNTAX)
10202 goto endword; /* exit outer loop */
10208 goto loop; /* continue outer loop */
10213 if (eofmark == NULL || dblquote)
10214 USTPUTC(CTLESC, out);
10217 case CBACK: /* backslash */
10220 USTPUTC(CTLESC, out);
10221 USTPUTC('\\', out);
10223 } else if (c == '\n') {
10228 c != '\\' && c != '`' &&
10233 USTPUTC(CTLESC, out);
10234 USTPUTC('\\', out);
10236 if (SIT(c, SQSYNTAX) == CCTL)
10237 USTPUTC(CTLESC, out);
10245 if (eofmark == NULL) {
10246 USTPUTC(CTLQUOTEMARK, out);
10254 if (eofmark != NULL && arinest == 0 &&
10258 if (dqvarnest == 0) {
10259 syntax = BASESYNTAX;
10266 case CVAR: /* '$' */
10267 PARSESUB(); /* parse substitution */
10269 case CENDVAR: /* '}' */
10272 if (dqvarnest > 0) {
10275 USTPUTC(CTLENDVAR, out);
10280 #ifdef CONFIG_ASH_MATH_SUPPORT
10281 case CLP: /* '(' in arithmetic */
10285 case CRP: /* ')' in arithmetic */
10286 if (parenlevel > 0) {
10290 if (pgetc() == ')') {
10291 if (--arinest == 0) {
10292 USTPUTC(CTLENDARI, out);
10293 syntax = prevsyntax;
10294 if (syntax == DQSYNTAX)
10302 * unbalanced parens
10303 * (don't 2nd guess - no error)
10311 case CBQUOTE: /* '`' */
10315 goto endword; /* exit outer loop */
10320 goto endword; /* exit outer loop */
10321 #ifdef CONFIG_ASH_ALIAS
10331 #ifdef CONFIG_ASH_MATH_SUPPORT
10332 if (syntax == ARISYNTAX)
10333 synerror("Missing '))'");
10335 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10336 synerror("Unterminated quoted string");
10337 if (varnest != 0) {
10338 startlinno = plinno;
10340 synerror("Missing '}'");
10342 USTPUTC('\0', out);
10343 len = out - (char *)stackblock();
10344 out = stackblock();
10345 if (eofmark == NULL) {
10346 if ((c == '>' || c == '<')
10349 && (*out == '\0' || is_digit(*out))) {
10351 return lasttoken = TREDIR;
10356 quoteflag = quotef;
10357 backquotelist = bqlist;
10358 grabstackblock(len);
10360 return lasttoken = TWORD;
10361 /* end of readtoken routine */
10366 * Check to see whether we are at the end of the here document. When this
10367 * is called, c is set to the first character of the next input line. If
10368 * we are at the end of the here document, this routine sets the c to PEOF.
10373 #ifdef CONFIG_ASH_ALIAS
10379 while (c == '\t') {
10383 if (c == *eofmark) {
10384 if (pfgets(line, sizeof line) != NULL) {
10388 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10389 if (*p == '\n' && *q == '\0') {
10392 needprompt = doprompt;
10394 pushstring(line, NULL);
10399 goto checkend_return;
10404 * Parse a redirection operator. The variable "out" points to a string
10405 * specifying the fd to be redirected. The variable "c" contains the
10406 * first character of the redirection operator.
10413 np = (union node *)stalloc(sizeof (struct nfile));
10418 np->type = NAPPEND;
10420 np->type = NCLOBBER;
10427 } else { /* c == '<' */
10429 switch (c = pgetc()) {
10431 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10432 np = (union node *)stalloc(sizeof (struct nhere));
10436 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10437 heredoc->here = np;
10438 if ((c = pgetc()) == '-') {
10439 heredoc->striptabs = 1;
10441 heredoc->striptabs = 0;
10447 np->type = NFROMFD;
10451 np->type = NFROMTO;
10461 np->nfile.fd = digit_val(fd);
10463 goto parseredir_return;
10468 * Parse a substitution. At this point, we have read the dollar sign
10469 * and nothing else.
10477 static const char types[] = "}-+?=";
10481 c <= PEOA_OR_PEOF ||
10482 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10486 } else if (c == '(') { /* $(command) or $((arith)) */
10487 if (pgetc() == '(') {
10488 #ifdef CONFIG_ASH_MATH_SUPPORT
10491 synerror("We unsupport $((arith))");
10498 USTPUTC(CTLVAR, out);
10499 typeloc = out - (char *)stackblock();
10500 USTPUTC(VSNORMAL, out);
10501 subtype = VSNORMAL;
10505 if ((c = pgetc()) == '}')
10508 subtype = VSLENGTH;
10513 if (c > PEOA_OR_PEOF && is_name(c)) {
10517 } while (c > PEOA_OR_PEOF && is_in_name(c));
10518 } else if (is_digit(c)) {
10522 } while (is_digit(c));
10524 else if (is_special(c)) {
10529 badsub: synerror("Bad substitution");
10533 if (subtype == 0) {
10540 p = strchr(types, c);
10543 subtype = p - types + VSNORMAL;
10549 subtype = c == '#' ? VSTRIMLEFT :
10562 if (dblquote || arinest)
10564 *((char *)stackblock() + typeloc) = subtype | flags;
10565 if (subtype != VSNORMAL) {
10567 if (dblquote || arinest) {
10572 goto parsesub_return;
10577 * Called to parse command substitutions. Newstyle is set if the command
10578 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10579 * list of commands (passed by reference), and savelen is the number of
10580 * characters on the top of the stack which must be preserved.
10584 struct nodelist **nlpp;
10587 char *volatile str;
10588 struct jmploc jmploc;
10589 struct jmploc *volatile savehandler;
10591 int saveprompt = 0;
10593 (void) &saveprompt;
10596 savepbq = parsebackquote;
10597 if (setjmp(jmploc.loc)) {
10600 parsebackquote = 0;
10601 handler = savehandler;
10602 longjmp(handler->loc, 1);
10606 savelen = out - (char *)stackblock();
10608 str = ckmalloc(savelen);
10609 memcpy(str, stackblock(), savelen);
10611 savehandler = handler;
10615 /* We must read until the closing backquote, giving special
10616 treatment to some slashes, and then push the string and
10617 reread it as input, interpreting it normally. */
10624 STARTSTACKSTR(pout);
10629 switch (pc = pgetc()) {
10634 if ((pc = pgetc()) == '\n') {
10639 * If eating a newline, avoid putting
10640 * the newline into the new character
10641 * stream (via the STPUTC after the
10646 if (pc != '\\' && pc != '`' && pc != '$'
10647 && (!dblquote || pc != '"'))
10648 STPUTC('\\', pout);
10649 if (pc > PEOA_OR_PEOF) {
10655 #ifdef CONFIG_ASH_ALIAS
10658 startlinno = plinno;
10659 synerror("EOF in backquote substitution");
10663 needprompt = doprompt;
10672 STPUTC('\0', pout);
10673 psavelen = pout - (char *)stackblock();
10674 if (psavelen > 0) {
10675 pstr = grabstackstr(pout);
10676 setinputstring(pstr);
10681 nlpp = &(*nlpp)->next;
10682 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10683 (*nlpp)->next = NULL;
10684 parsebackquote = oldstyle;
10687 saveprompt = doprompt;
10694 doprompt = saveprompt;
10696 if (readtoken() != TRP)
10703 * Start reading from old file again, ignoring any pushed back
10704 * tokens left from the backquote parsing
10709 while (stackblocksize() <= savelen)
10711 STARTSTACKSTR(out);
10713 memcpy(out, str, savelen);
10714 STADJUST(savelen, out);
10720 parsebackquote = savepbq;
10721 handler = savehandler;
10722 if (arinest || dblquote)
10723 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10725 USTPUTC(CTLBACKQ, out);
10727 goto parsebackq_oldreturn;
10729 goto parsebackq_newreturn;
10732 #ifdef CONFIG_ASH_MATH_SUPPORT
10734 * Parse an arithmetic expansion (indicate start of one and set state)
10738 if (++arinest == 1) {
10739 prevsyntax = syntax;
10740 syntax = ARISYNTAX;
10741 USTPUTC(CTLARI, out);
10748 * we collapse embedded arithmetic expansion to
10749 * parenthesis, which should be equivalent
10753 goto parsearith_return;
10757 } /* end of readtoken */
10762 * Returns true if the text contains nothing to expand (no dollar signs
10767 noexpand(char *text)
10773 while ((c = *p++) != '\0') {
10774 if (c == CTLQUOTEMARK)
10778 else if (SIT(c, BASESYNTAX) == CCTL)
10786 * Return of a legal variable name (a letter or underscore followed by zero or
10787 * more letters, underscores, and digits).
10791 endofname(const char *name)
10799 if (! is_in_name(*p))
10807 * Called when an unexpected token is read during the parse. The argument
10808 * is the token that is expected, or -1 if more than one type of token can
10809 * occur at this point.
10812 static void synexpect(int token)
10817 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10819 sprintf(msg + l, " (expecting %s)", tokname(token));
10825 synerror(const char *msg)
10827 sh_error("Syntax error: %s", msg);
10833 * called by editline -- any expansions to the prompt
10834 * should be added here.
10837 #ifdef CONFIG_ASH_EXPAND_PRMT
10838 static const char *
10839 expandstr(const char *ps)
10843 /* XXX Fix (char *) cast. */
10844 setinputstring((char *)ps);
10845 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10848 n.narg.type = NARG;
10849 n.narg.next = NULL;
10850 n.narg.text = wordtext;
10851 n.narg.backquote = backquotelist;
10853 expandarg(&n, NULL, 0);
10854 return stackblock();
10858 static void setprompt(int whichprompt)
10860 const char *prompt;
10861 #ifdef CONFIG_ASH_EXPAND_PRMT
10862 struct stackmark smark;
10867 switch (whichprompt) {
10877 #ifdef CONFIG_ASH_EXPAND_PRMT
10878 setstackmark(&smark);
10879 stalloc(stackblocksize());
10881 putprompt(expandstr(prompt));
10882 #ifdef CONFIG_ASH_EXPAND_PRMT
10883 popstackmark(&smark);
10888 static const char *const *findkwd(const char *s)
10890 return bsearch(s, tokname_array + KWDOFFSET,
10891 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10892 sizeof(const char *), pstrcmp);
10898 * Code for dealing with input/output redirection.
10901 #define EMPTY -2 /* marks an unused slot in redirtab */
10903 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10905 # define PIPESIZE PIPE_BUF
10909 * Open a file in noclobber mode.
10910 * The code was copied from bash.
10913 noclobberopen(const char *fname)
10916 struct stat finfo, finfo2;
10919 * If the file exists and is a regular file, return an error
10922 r = stat(fname, &finfo);
10923 if (r == 0 && S_ISREG(finfo.st_mode)) {
10929 * If the file was not present (r != 0), make sure we open it
10930 * exclusively so that if it is created before we open it, our open
10931 * will fail. Make sure that we do not truncate an existing file.
10932 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10933 * file was not a regular file, we leave O_EXCL off.
10936 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10937 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10939 /* If the open failed, return the file descriptor right away. */
10944 * OK, the open succeeded, but the file may have been changed from a
10945 * non-regular file to a regular file between the stat and the open.
10946 * We are assuming that the O_EXCL open handles the case where FILENAME
10947 * did not exist and is symlinked to an existing file between the stat
10952 * If we can open it and fstat the file descriptor, and neither check
10953 * revealed that it was a regular file, and the file has not been
10954 * replaced, return the file descriptor.
10956 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10957 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10960 /* The file has been replaced. badness. */
10967 * Handle here documents. Normally we fork off a process to write the
10968 * data to a pipe. If the document is short, we can stuff the data in
10969 * the pipe without forking.
10973 openhere(union node *redir)
10979 sh_error("Pipe call failed");
10980 if (redir->type == NHERE) {
10981 len = strlen(redir->nhere.doc->narg.text);
10982 if (len <= PIPESIZE) {
10983 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10987 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10989 signal(SIGINT, SIG_IGN);
10990 signal(SIGQUIT, SIG_IGN);
10991 signal(SIGHUP, SIG_IGN);
10993 signal(SIGTSTP, SIG_IGN);
10995 signal(SIGPIPE, SIG_DFL);
10996 if (redir->type == NHERE)
10997 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10999 expandhere(redir->nhere.doc, pip[1]);
11008 openredirect(union node *redir)
11013 switch (redir->nfile.type) {
11015 fname = redir->nfile.expfname;
11016 if ((f = open(fname, O_RDONLY)) < 0)
11020 fname = redir->nfile.expfname;
11021 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11025 /* Take care of noclobber mode. */
11027 fname = redir->nfile.expfname;
11028 if ((f = noclobberopen(fname)) < 0)
11034 fname = redir->nfile.expfname;
11035 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11039 fname = redir->nfile.expfname;
11040 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11047 /* Fall through to eliminate warning. */
11054 f = openhere(redir);
11060 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11062 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11066 dupredirect(union node *redir, int f)
11068 int fd = redir->nfile.fd;
11070 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11071 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11072 copyfd(redir->ndup.dupfd, fd);
11085 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11086 * old file descriptors are stashed away so that the redirection can be
11087 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11088 * standard output, and the standard error if it becomes a duplicate of
11089 * stdout, is saved in memory.
11093 redirect(union node *redir, int flags)
11096 struct redirtab *sv;
11107 if (flags & REDIR_PUSH) {
11108 struct redirtab *q;
11109 q = ckmalloc(sizeof (struct redirtab));
11110 q->next = redirlist;
11112 q->nullredirs = nullredirs - 1;
11113 for (i = 0 ; i < 10 ; i++)
11114 q->renamed[i] = EMPTY;
11121 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11122 n->ndup.dupfd == fd)
11123 continue; /* redirect from/to same file descriptor */
11125 newfd = openredirect(n);
11128 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11129 i = fcntl(fd, F_DUPFD, 10);
11136 sh_error("%d: %m", fd);
11146 dupredirect(n, newfd);
11147 } while ((n = n->nfile.next));
11149 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11150 preverrout_fd = sv->renamed[2];
11155 * Undo the effects of the last redirection.
11161 struct redirtab *rp;
11164 if (--nullredirs >= 0)
11168 for (i = 0 ; i < 10 ; i++) {
11169 if (rp->renamed[i] != EMPTY) {
11172 copyfd(rp->renamed[i], i);
11174 close(rp->renamed[i]);
11177 redirlist = rp->next;
11178 nullredirs = rp->nullredirs;
11184 * Undo all redirections. Called on error or interrupt.
11188 * Discard all saved file descriptors.
11192 clearredir(int drop)
11204 * Copy a file descriptor to be >= to. Returns -1
11205 * if the source file descriptor is closed, EMPTY if there are no unused
11206 * file descriptors left.
11210 copyfd(int from, int to)
11214 newfd = fcntl(from, F_DUPFD, to);
11216 if (errno == EMFILE)
11219 sh_error("%d: %m", from);
11226 redirectsafe(union node *redir, int flags)
11229 volatile int saveint;
11230 struct jmploc *volatile savehandler = handler;
11231 struct jmploc jmploc;
11234 if (!(err = setjmp(jmploc.loc) * 2)) {
11236 redirect(redir, flags);
11238 handler = savehandler;
11239 if (err && exception != EXERROR)
11240 longjmp(handler->loc, 1);
11241 RESTOREINT(saveint);
11248 static void shtree(union node *, int, char *, FILE*);
11249 static void shcmd(union node *, FILE *);
11250 static void sharg(union node *, FILE *);
11251 static void indent(int, char *, FILE *);
11252 static void trstring(char *);
11256 showtree(union node *n)
11258 trputs("showtree called\n");
11259 shtree(n, 1, NULL, stdout);
11264 shtree(union node *n, int ind, char *pfx, FILE *fp)
11266 struct nodelist *lp;
11272 indent(ind, pfx, fp);
11283 shtree(n->nbinary.ch1, ind, NULL, fp);
11286 shtree(n->nbinary.ch2, ind, NULL, fp);
11294 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11299 if (n->npipe.backgnd)
11305 fprintf(fp, "<node type %d>", n->type);
11314 shcmd(union node *cmd, FILE *fp)
11322 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11328 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11331 switch (np->nfile.type) {
11332 case NTO: s = ">"; dftfd = 1; break;
11333 case NCLOBBER: s = ">|"; dftfd = 1; break;
11334 case NAPPEND: s = ">>"; dftfd = 1; break;
11335 case NTOFD: s = ">&"; dftfd = 1; break;
11336 case NFROM: s = "<"; dftfd = 0; break;
11337 case NFROMFD: s = "<&"; dftfd = 0; break;
11338 case NFROMTO: s = "<>"; dftfd = 0; break;
11339 default: s = "*error*"; dftfd = 0; break;
11341 if (np->nfile.fd != dftfd)
11342 fprintf(fp, "%d", np->nfile.fd);
11344 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11345 fprintf(fp, "%d", np->ndup.dupfd);
11347 sharg(np->nfile.fname, fp);
11356 sharg(union node *arg, FILE *fp)
11359 struct nodelist *bqlist;
11362 if (arg->type != NARG) {
11363 out1fmt("<node type %d>\n", arg->type);
11366 bqlist = arg->narg.backquote;
11367 for (p = arg->narg.text ; *p ; p++) {
11376 if (subtype == VSLENGTH)
11382 if (subtype & VSNUL)
11385 switch (subtype & VSTYPE) {
11404 case VSTRIMLEFTMAX:
11411 case VSTRIMRIGHTMAX:
11418 out1fmt("<subtype %d>", subtype);
11425 case CTLBACKQ|CTLQUOTE:
11428 shtree(bqlist->n, -1, NULL, fp);
11440 indent(int amount, char *pfx, FILE *fp)
11444 for (i = 0 ; i < amount ; i++) {
11445 if (pfx && i == amount - 1)
11466 putc(c, tracefile);
11470 trace(const char *fmt, ...)
11477 (void) vfprintf(tracefile, fmt, va);
11482 tracev(const char *fmt, va_list va)
11486 (void) vfprintf(tracefile, fmt, va);
11491 trputs(const char *s)
11495 fputs(s, tracefile);
11507 putc('"', tracefile);
11508 for (p = s ; *p ; p++) {
11510 case '\n': c = 'n'; goto backslash;
11511 case '\t': c = 't'; goto backslash;
11512 case '\r': c = 'r'; goto backslash;
11513 case '"': c = '"'; goto backslash;
11514 case '\\': c = '\\'; goto backslash;
11515 case CTLESC: c = 'e'; goto backslash;
11516 case CTLVAR: c = 'v'; goto backslash;
11517 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11518 case CTLBACKQ: c = 'q'; goto backslash;
11519 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11520 backslash: putc('\\', tracefile);
11521 putc(c, tracefile);
11524 if (*p >= ' ' && *p <= '~')
11525 putc(*p, tracefile);
11527 putc('\\', tracefile);
11528 putc(*p >> 6 & 03, tracefile);
11529 putc(*p >> 3 & 07, tracefile);
11530 putc(*p & 07, tracefile);
11535 putc('"', tracefile);
11547 putc(' ', tracefile);
11549 putc('\n', tracefile);
11565 /* leave open because libedit might be using it */
11568 scopy("./trace", s);
11570 if (!freopen(s, "a", tracefile)) {
11571 fprintf(stderr, "Can't re-open %s\n", s);
11576 if ((tracefile = fopen(s, "a")) == NULL) {
11577 fprintf(stderr, "Can't open %s\n", s);
11583 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11584 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11586 setlinebuf(tracefile);
11587 fputs("\nTracing started.\n", tracefile);
11595 * Sigmode records the current value of the signal handlers for the various
11596 * modes. A value of zero means that the current handler is not known.
11597 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11600 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11601 #define S_CATCH 2 /* signal is caught */
11602 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11603 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11604 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11609 * The trap builtin.
11613 trapcmd(int argc, char **argv)
11622 for (signo = 0 ; signo < NSIG ; signo++) {
11623 if (trap[signo] != NULL) {
11626 sn = u_signal_names(0, &signo, 0);
11629 out1fmt("trap -- %s %s\n",
11630 single_quote(trap[signo]), sn);
11640 if ((signo = decode_signal(*ap, 0)) < 0)
11641 sh_error("%s: bad trap", *ap);
11644 if (action[0] == '-' && action[1] == '\0')
11647 action = savestr(action);
11650 ckfree(trap[signo]);
11651 trap[signo] = action;
11662 * Clear traps on a fork.
11670 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11671 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11675 if (tp != &trap[0])
11676 setsignal(tp - trap);
11684 * Set the signal handler for the specified signal. The routine figures
11685 * out what it should be set to.
11689 setsignal(int signo)
11693 struct sigaction act;
11695 if ((t = trap[signo]) == NULL)
11697 else if (*t != '\0')
11701 if (rootshell && action == S_DFL) {
11704 if (iflag || minusc || sflag == 0)
11727 t = &sigmode[signo - 1];
11731 * current setting unknown
11733 if (sigaction(signo, 0, &act) == -1) {
11735 * Pretend it worked; maybe we should give a warning
11736 * here, but other shells don't. We don't alter
11737 * sigmode, so that we retry every time.
11741 if (act.sa_handler == SIG_IGN) {
11742 if (mflag && (signo == SIGTSTP ||
11743 signo == SIGTTIN || signo == SIGTTOU)) {
11744 tsig = S_IGN; /* don't hard ignore these */
11748 tsig = S_RESET; /* force to be set */
11751 if (tsig == S_HARD_IGN || tsig == action)
11755 act.sa_handler = onsig;
11758 act.sa_handler = SIG_IGN;
11761 act.sa_handler = SIG_DFL;
11765 sigfillset(&act.sa_mask);
11766 sigaction(signo, &act, 0);
11774 ignoresig(int signo)
11776 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11777 signal(signo, SIG_IGN);
11779 sigmode[signo - 1] = S_HARD_IGN;
11790 gotsig[signo - 1] = 1;
11791 pendingsigs = signo;
11793 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11802 * Called to execute a trap. Perhaps we should avoid entering new trap
11803 * handlers while we are executing a trap handler.
11815 savestatus = exitstatus;
11819 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11827 skip = evalstring(p, SKIPEVAL);
11828 exitstatus = savestatus;
11838 * Controls whether the shell is interactive or not.
11842 setinteractive(int on)
11844 static int is_interactive;
11846 if (++on == is_interactive)
11848 is_interactive = on;
11850 setsignal(SIGQUIT);
11851 setsignal(SIGTERM);
11852 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11853 if(is_interactive > 1) {
11854 /* Looks like they want an interactive shell */
11855 static int do_banner;
11859 "\n\n%s Built-in shell (ash)\n"
11860 "Enter 'help' for a list of built-in commands.\n\n",
11869 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11870 /*** List the available builtins ***/
11872 static int helpcmd(int argc, char **argv)
11876 out1fmt("\nBuilt-in commands:\n-------------------\n");
11877 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11878 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11879 builtincmd[i].name + 1);
11885 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11887 extern const struct BB_applet applets[];
11888 extern const size_t NUM_APPLETS;
11890 for (i = 0; i < NUM_APPLETS; i++) {
11892 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11901 return EXIT_SUCCESS;
11903 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11906 * Called to exit the shell.
11916 status = exitstatus;
11917 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11918 if (setjmp(loc.loc)) {
11919 if (exception == EXEXIT)
11924 if ((p = trap[0])) {
11930 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11931 if (iflag && rootshell) {
11932 const char *hp = lookupvar("HISTFILE");
11935 save_history ( hp );
11943 static int decode_signal(const char *string, int minsig)
11946 const char *name = u_signal_names(string, &signo, minsig);
11948 return name ? signo : -1;
11953 static struct var *vartab[VTABSIZE];
11955 static int vpcmp(const void *, const void *);
11956 static struct var **findvar(struct var **, const char *);
11959 * Initialize the variable symbol tables and import the environment
11963 #ifdef CONFIG_ASH_GETOPTS
11965 * Safe version of setvar, returns 1 on success 0 on failure.
11969 setvarsafe(const char *name, const char *val, int flags)
11972 volatile int saveint;
11973 struct jmploc *volatile savehandler = handler;
11974 struct jmploc jmploc;
11977 if (setjmp(jmploc.loc))
11981 setvar(name, val, flags);
11984 handler = savehandler;
11985 RESTOREINT(saveint);
11991 * Set the value of a variable. The flags argument is ored with the
11992 * flags of the variable. If val is NULL, the variable is unset.
11996 setvar(const char *name, const char *val, int flags)
12003 q = endofname(name);
12004 p = strchrnul(q, '=');
12005 namelen = p - name;
12006 if (!namelen || p != q)
12007 sh_error("%.*s: bad variable name", namelen, name);
12012 vallen = strlen(val);
12015 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12018 p = mempcpy(p, val, vallen);
12021 setvareq(nameeq, flags | VNOSAVE);
12027 * Same as setvar except that the variable and value are passed in
12028 * the first argument as name=value. Since the first argument will
12029 * be actually stored in the table, it should not be a string that
12031 * Called with interrupts off.
12035 setvareq(char *s, int flags)
12037 struct var *vp, **vpp;
12040 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12041 vp = *findvar(vpp, s);
12043 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12046 if (flags & VNOSAVE)
12049 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12052 if (flags & VNOSET)
12055 if (vp->func && (flags & VNOFUNC) == 0)
12056 (*vp->func)(strchrnul(s, '=') + 1);
12058 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12061 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12063 if (flags & VNOSET)
12066 vp = ckmalloc(sizeof (*vp));
12071 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12079 * Process a linked list of variable assignments.
12083 listsetvar(struct strlist *list_set_var, int flags)
12085 struct strlist *lp = list_set_var;
12091 setvareq(lp->text, flags);
12092 } while ((lp = lp->next));
12098 * Find the value of a variable. Returns NULL if not set.
12102 lookupvar(const char *name)
12106 if ((v = *findvar(hashvar(name), name))) {
12109 * Dynamic variables are implemented roughly the same way they are
12110 * in bash. Namely, they're "special" so long as they aren't unset.
12111 * As soon as they're unset, they're no longer dynamic, and dynamic
12112 * lookup will no longer happen at that point. -- PFM.
12114 if((v->flags & VDYNAMIC))
12117 if(!(v->flags & VUNSET))
12118 return strchrnul(v->text, '=') + 1;
12126 * Search the environment of a builtin command.
12130 bltinlookup(const char *name)
12132 struct strlist *sp;
12134 for (sp = cmdenviron ; sp ; sp = sp->next) {
12135 if (varequal(sp->text, name))
12136 return strchrnul(sp->text, '=') + 1;
12138 return lookupvar(name);
12143 * Generate a list of variables satisfying the given conditions.
12147 listvars(int on, int off, char ***end)
12158 for (vp = *vpp ; vp ; vp = vp->next)
12159 if ((vp->flags & mask) == on) {
12160 if (ep == stackstrend())
12161 ep = growstackstr();
12162 *ep++ = (char *) vp->text;
12164 } while (++vpp < vartab + VTABSIZE);
12165 if (ep == stackstrend())
12166 ep = growstackstr();
12170 return grabstackstr(ep);
12175 * POSIX requires that 'set' (but not export or readonly) output the
12176 * variables in lexicographic order - by the locale's collating order (sigh).
12177 * Maybe we could keep them in an ordered balanced binary tree
12178 * instead of hashed lists.
12179 * For now just roll 'em through qsort for printing...
12183 showvars(const char *sep_prefix, int on, int off)
12186 char **ep, **epend;
12188 ep = listvars(on, off, &epend);
12189 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12191 sep = *sep_prefix ? spcstr : sep_prefix;
12193 for (; ep < epend; ep++) {
12197 p = strchrnul(*ep, '=');
12200 q = single_quote(++p);
12202 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12211 * The export and readonly commands.
12215 exportcmd(int argc, char **argv)
12221 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12224 notp = nextopt("p") - 'p';
12225 if (notp && ((name = *(aptr = argptr)))) {
12227 if ((p = strchr(name, '=')) != NULL) {
12230 if ((vp = *findvar(hashvar(name), name))) {
12235 setvar(name, p, flag);
12236 } while ((name = *++aptr) != NULL);
12238 showvars(argv[0], flag, 0);
12245 * Make a variable a local variable. When a variable is made local, it's
12246 * value and flags are saved in a localvar structure. The saved values
12247 * will be restored when the shell function returns. We handle the name
12248 * "-" as a special case.
12252 mklocal(char *name)
12254 struct localvar *lvp;
12259 lvp = ckmalloc(sizeof (struct localvar));
12260 if (name[0] == '-' && name[1] == '\0') {
12262 p = ckmalloc(sizeof(optlist));
12263 lvp->text = memcpy(p, optlist, sizeof(optlist));
12268 vpp = hashvar(name);
12269 vp = *findvar(vpp, name);
12270 eq = strchr(name, '=');
12273 setvareq(name, VSTRFIXED);
12275 setvar(name, NULL, VSTRFIXED);
12276 vp = *vpp; /* the new variable */
12277 lvp->flags = VUNSET;
12279 lvp->text = vp->text;
12280 lvp->flags = vp->flags;
12281 vp->flags |= VSTRFIXED|VTEXTFIXED;
12287 lvp->next = localvars;
12293 * The "local" command.
12297 localcmd(int argc, char **argv)
12302 while ((name = *argv++) != NULL) {
12310 * Called after a function returns.
12311 * Interrupts must be off.
12317 struct localvar *lvp;
12320 while ((lvp = localvars) != NULL) {
12321 localvars = lvp->next;
12323 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12324 if (vp == NULL) { /* $- saved */
12325 memcpy(optlist, lvp->text, sizeof(optlist));
12328 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12329 unsetvar(vp->text);
12332 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12333 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12335 vp->flags = lvp->flags;
12336 vp->text = lvp->text;
12344 * The unset builtin command. We unset the function before we unset the
12345 * variable to allow a function to be unset when there is a readonly variable
12346 * with the same name.
12350 unsetcmd(int argc, char **argv)
12357 while ((i = nextopt("vf")) != '\0') {
12361 for (ap = argptr; *ap ; ap++) {
12376 * Unset the specified variable.
12380 unsetvar(const char *s)
12386 vpp = findvar(hashvar(s), s);
12390 int flags = vp->flags;
12393 if (flags & VREADONLY)
12396 vp->flags &= ~VDYNAMIC;
12398 if (flags & VUNSET)
12400 if ((flags & VSTRFIXED) == 0) {
12402 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12409 vp->flags &= ~VEXPORT;
12422 * Find the appropriate entry in the hash table from the name.
12425 static struct var **
12426 hashvar(const char *p)
12428 unsigned int hashval;
12430 hashval = ((unsigned char) *p) << 4;
12431 while (*p && *p != '=')
12432 hashval += (unsigned char) *p++;
12433 return &vartab[hashval % VTABSIZE];
12439 * Compares two strings up to the first = or '\0'. The first
12440 * string must be terminated by '='; the second may be terminated by
12441 * either '=' or '\0'.
12445 varcmp(const char *p, const char *q)
12449 while ((c = *p) == (d = *q)) {
12450 if (!c || c == '=')
12464 vpcmp(const void *a, const void *b)
12466 return varcmp(*(const char **)a, *(const char **)b);
12469 static struct var **
12470 findvar(struct var **vpp, const char *name)
12472 for (; *vpp; vpp = &(*vpp)->next) {
12473 if (varequal((*vpp)->text, name)) {
12481 #include <sys/times.h>
12483 static const unsigned char timescmd_str[] = {
12484 ' ', offsetof(struct tms, tms_utime),
12485 '\n', offsetof(struct tms, tms_stime),
12486 ' ', offsetof(struct tms, tms_cutime),
12487 '\n', offsetof(struct tms, tms_cstime),
12491 static int timescmd(int ac, char **av)
12493 long int clk_tck, s, t;
12494 const unsigned char *p;
12497 clk_tck = sysconf(_SC_CLK_TCK);
12502 t = *(clock_t *)(((char *) &buf) + p[1]);
12504 out1fmt("%ldm%ld.%.3lds%c",
12506 ((t - s * clk_tck) * 1000) / clk_tck,
12508 } while (*(p += 2));
12513 #ifdef CONFIG_ASH_MATH_SUPPORT
12515 dash_arith(const char *s)
12521 result = arith(s, &errcode);
12524 sh_error("exponent less than 0");
12525 else if (errcode == -2)
12526 sh_error("divide by zero");
12527 else if (errcode == -5)
12528 sh_error("expression recursion loop detected");
12539 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12540 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12542 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12546 letcmd(int argc, char **argv)
12553 sh_error("expression expected");
12554 for (ap = argv + 1; *ap; ap++) {
12555 i = dash_arith(*ap);
12560 #endif /* CONFIG_ASH_MATH_SUPPORT */
12565 * Miscellaneous builtins.
12571 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12572 typedef enum __rlimit_resource rlim_t;
12578 * The read builtin. The -e option causes backslashes to escape the
12579 * following character.
12581 * This uses unbuffered input, which may be avoidable in some cases.
12585 readcmd(int argc, char **argv)
12597 #if defined(CONFIG_ASH_READ_NCHARS)
12601 struct termios tty, old_tty;
12603 #if defined(CONFIG_ASH_READ_TIMEOUT)
12607 ts.tv_sec = ts.tv_usec = 0;
12612 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12613 while ((i = nextopt("p:rt:n:s")) != '\0')
12614 #elif defined(CONFIG_ASH_READ_NCHARS)
12615 while ((i = nextopt("p:rn:s")) != '\0')
12616 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12617 while ((i = nextopt("p:rt:")) != '\0')
12619 while ((i = nextopt("p:r")) != '\0')
12624 prompt = optionarg;
12626 #if defined(CONFIG_ASH_READ_NCHARS)
12628 nchars = strtol(optionarg, &p, 10);
12630 sh_error("invalid count");
12631 nch_flag = (nchars > 0);
12637 #if defined(CONFIG_ASH_READ_TIMEOUT)
12639 ts.tv_sec = strtol(optionarg, &p, 10);
12645 ts.tv_usec = strtol(p, &p2, 10);
12647 sh_error("invalid timeout");
12649 /* normalize to usec */
12651 sh_error("invalid timeout");
12652 while (scale++ < 6)
12656 sh_error("invalid timeout");
12658 if ( ! ts.tv_sec && ! ts.tv_usec)
12659 sh_error("invalid timeout");
12669 if (prompt && isatty(0)) {
12672 if (*(ap = argptr) == NULL)
12673 sh_error("arg count");
12674 if ((ifs = bltinlookup("IFS")) == NULL)
12676 #if defined(CONFIG_ASH_READ_NCHARS)
12677 if (nch_flag || silent) {
12678 tcgetattr(0, &tty);
12681 tty.c_lflag &= ~ICANON;
12682 tty.c_cc[VMIN] = nchars;
12685 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12688 tcsetattr(0, TCSANOW, &tty);
12691 #if defined(CONFIG_ASH_READ_TIMEOUT)
12692 if (ts.tv_sec || ts.tv_usec) {
12696 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12698 #if defined(CONFIG_ASH_READ_NCHARS)
12700 tcsetattr(0, TCSANOW, &old_tty);
12710 #if defined(CONFIG_ASH_READ_NCHARS)
12711 while (!nch_flag || nchars--)
12716 if (read(0, &c, 1) != 1) {
12728 if (!rflag && c == '\\') {
12734 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12738 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12740 setvar(*ap, stackblock(), 0);
12749 #if defined(CONFIG_ASH_READ_NCHARS)
12750 if (nch_flag || silent)
12751 tcsetattr(0, TCSANOW, &old_tty);
12755 /* Remove trailing blanks */
12756 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12758 setvar(*ap, stackblock(), 0);
12759 while (*++ap != NULL)
12760 setvar(*ap, nullstr, 0);
12765 static int umaskcmd(int argc, char **argv)
12767 static const char permuser[3] = "ugo";
12768 static const char permmode[3] = "rwx";
12769 static const short int permmask[] = {
12770 S_IRUSR, S_IWUSR, S_IXUSR,
12771 S_IRGRP, S_IWGRP, S_IXGRP,
12772 S_IROTH, S_IWOTH, S_IXOTH
12778 int symbolic_mode = 0;
12780 while (nextopt("S") != '\0') {
12789 if ((ap = *argptr) == NULL) {
12790 if (symbolic_mode) {
12794 for (i = 0; i < 3; i++) {
12797 *p++ = permuser[i];
12799 for (j = 0; j < 3; j++) {
12800 if ((mask & permmask[3 * i + j]) == 0) {
12801 *p++ = permmode[j];
12809 out1fmt("%.4o\n", mask);
12812 if (is_digit((unsigned char) *ap)) {
12815 if (*ap >= '8' || *ap < '0')
12816 sh_error(illnum, argv[1]);
12817 mask = (mask << 3) + (*ap - '0');
12818 } while (*++ap != '\0');
12821 mask = ~mask & 0777;
12822 if (!bb_parse_mode(ap, &mask)) {
12823 sh_error("Illegal mode: %s", ap);
12825 umask(~mask & 0777);
12834 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12835 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12836 * ash by J.T. Conklin.
12844 int factor; /* multiply by to get rlim_{cur,max} values */
12848 static const struct limits limits[] = {
12850 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12852 #ifdef RLIMIT_FSIZE
12853 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12856 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12858 #ifdef RLIMIT_STACK
12859 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12862 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12865 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12867 #ifdef RLIMIT_MEMLOCK
12868 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12870 #ifdef RLIMIT_NPROC
12871 { "process", RLIMIT_NPROC, 1, 'p' },
12873 #ifdef RLIMIT_NOFILE
12874 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12877 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12879 #ifdef RLIMIT_LOCKS
12880 { "locks", RLIMIT_LOCKS, 1, 'w' },
12882 { (char *) 0, 0, 0, '\0' }
12885 enum limtype { SOFT = 0x1, HARD = 0x2 };
12887 static void printlim(enum limtype how, const struct rlimit *limit,
12888 const struct limits *l)
12892 val = limit->rlim_max;
12894 val = limit->rlim_cur;
12896 if (val == RLIM_INFINITY)
12897 out1fmt("unlimited\n");
12900 out1fmt("%lld\n", (long long) val);
12905 ulimitcmd(int argc, char **argv)
12909 enum limtype how = SOFT | HARD;
12910 const struct limits *l;
12913 struct rlimit limit;
12916 while ((optc = nextopt("HSa"
12920 #ifdef RLIMIT_FSIZE
12926 #ifdef RLIMIT_STACK
12935 #ifdef RLIMIT_MEMLOCK
12938 #ifdef RLIMIT_NPROC
12941 #ifdef RLIMIT_NOFILE
12947 #ifdef RLIMIT_LOCKS
12965 for (l = limits; l->option != what; l++)
12968 set = *argptr ? 1 : 0;
12972 if (all || argptr[1])
12973 sh_error("too many arguments");
12974 if (strncmp(p, "unlimited\n", 9) == 0)
12975 val = RLIM_INFINITY;
12979 while ((c = *p++) >= '0' && c <= '9')
12981 val = (val * 10) + (long)(c - '0');
12982 if (val < (rlim_t) 0)
12986 sh_error("bad number");
12991 for (l = limits; l->name; l++) {
12992 getrlimit(l->cmd, &limit);
12993 out1fmt("%-20s ", l->name);
12994 printlim(how, &limit, l);
12999 getrlimit(l->cmd, &limit);
13002 limit.rlim_max = val;
13004 limit.rlim_cur = val;
13005 if (setrlimit(l->cmd, &limit) < 0)
13006 sh_error("error setting limit (%m)");
13008 printlim(how, &limit, l);
13014 #ifdef CONFIG_ASH_MATH_SUPPORT
13016 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13018 Permission is hereby granted, free of charge, to any person obtaining
13019 a copy of this software and associated documentation files (the
13020 "Software"), to deal in the Software without restriction, including
13021 without limitation the rights to use, copy, modify, merge, publish,
13022 distribute, sublicense, and/or sell copies of the Software, and to
13023 permit persons to whom the Software is furnished to do so, subject to
13024 the following conditions:
13026 The above copyright notice and this permission notice shall be
13027 included in all copies or substantial portions of the Software.
13029 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13030 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13031 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13032 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13033 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13034 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13035 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13038 /* This is my infix parser/evaluator. It is optimized for size, intended
13039 * as a replacement for yacc-based parsers. However, it may well be faster
13040 * than a comparable parser written in yacc. The supported operators are
13041 * listed in #defines below. Parens, order of operations, and error handling
13042 * are supported. This code is thread safe. The exact expression format should
13043 * be that which POSIX specifies for shells. */
13045 /* The code uses a simple two-stack algorithm. See
13046 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13047 * for a detailed explanation of the infix-to-postfix algorithm on which
13048 * this is based (this code differs in that it applies operators immediately
13049 * to the stack instead of adding them to a queue to end up with an
13052 /* To use the routine, call it with an expression string and error return
13056 * Aug 24, 2001 Manuel Novoa III
13058 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13060 * 1) In arith_apply():
13061 * a) Cached values of *numptr and &(numptr[-1]).
13062 * b) Removed redundant test for zero denominator.
13065 * a) Eliminated redundant code for processing operator tokens by moving
13066 * to a table-based implementation. Also folded handling of parens
13068 * b) Combined all 3 loops which called arith_apply to reduce generated
13069 * code size at the cost of speed.
13071 * 3) The following expressions were treated as valid by the original code:
13072 * 1() , 0! , 1 ( *3 ) .
13073 * These bugs have been fixed by internally enclosing the expression in
13074 * parens and then checking that all binary ops and right parens are
13075 * preceded by a valid expression (NUM_TOKEN).
13077 * Note: It may be desirable to replace Aaron's test for whitespace with
13078 * ctype's isspace() if it is used by another busybox applet or if additional
13079 * whitespace chars should be considered. Look below the "#include"s for a
13080 * precompiler test.
13084 * Aug 26, 2001 Manuel Novoa III
13086 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13088 * Merge in Aaron's comments previously posted to the busybox list,
13089 * modified slightly to take account of my changes to the code.
13094 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13096 * - allow access to variable,
13097 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13098 * - realize assign syntax (VAR=expr, +=, *= etc)
13099 * - realize exponentiation (** operator)
13100 * - realize comma separated - expr, expr
13101 * - realise ++expr --expr expr++ expr--
13102 * - realise expr ? expr : expr (but, second expr calculate always)
13103 * - allow hexadecimal and octal numbers
13104 * - was restored loses XOR operator
13105 * - remove one goto label, added three ;-)
13106 * - protect $((num num)) as true zero expr (Manuel`s error)
13107 * - always use special isspace(), see comment from bash ;-)
13111 #define arith_isspace(arithval) \
13112 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13115 typedef unsigned char operator;
13117 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13118 * precedence, and 3 high bits are an ID unique across operators of that
13119 * precedence. The ID portion is so that multiple operators can have the
13120 * same precedence, ensuring that the leftmost one is evaluated first.
13121 * Consider * and /. */
13123 #define tok_decl(prec,id) (((id)<<5)|(prec))
13124 #define PREC(op) ((op) & 0x1F)
13126 #define TOK_LPAREN tok_decl(0,0)
13128 #define TOK_COMMA tok_decl(1,0)
13130 #define TOK_ASSIGN tok_decl(2,0)
13131 #define TOK_AND_ASSIGN tok_decl(2,1)
13132 #define TOK_OR_ASSIGN tok_decl(2,2)
13133 #define TOK_XOR_ASSIGN tok_decl(2,3)
13134 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13135 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13136 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13137 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13139 #define TOK_MUL_ASSIGN tok_decl(3,0)
13140 #define TOK_DIV_ASSIGN tok_decl(3,1)
13141 #define TOK_REM_ASSIGN tok_decl(3,2)
13143 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13144 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13146 /* conditional is right associativity too */
13147 #define TOK_CONDITIONAL tok_decl(4,0)
13148 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13150 #define TOK_OR tok_decl(5,0)
13152 #define TOK_AND tok_decl(6,0)
13154 #define TOK_BOR tok_decl(7,0)
13156 #define TOK_BXOR tok_decl(8,0)
13158 #define TOK_BAND tok_decl(9,0)
13160 #define TOK_EQ tok_decl(10,0)
13161 #define TOK_NE tok_decl(10,1)
13163 #define TOK_LT tok_decl(11,0)
13164 #define TOK_GT tok_decl(11,1)
13165 #define TOK_GE tok_decl(11,2)
13166 #define TOK_LE tok_decl(11,3)
13168 #define TOK_LSHIFT tok_decl(12,0)
13169 #define TOK_RSHIFT tok_decl(12,1)
13171 #define TOK_ADD tok_decl(13,0)
13172 #define TOK_SUB tok_decl(13,1)
13174 #define TOK_MUL tok_decl(14,0)
13175 #define TOK_DIV tok_decl(14,1)
13176 #define TOK_REM tok_decl(14,2)
13178 /* exponent is right associativity */
13179 #define TOK_EXPONENT tok_decl(15,1)
13181 /* For now unary operators. */
13182 #define UNARYPREC 16
13183 #define TOK_BNOT tok_decl(UNARYPREC,0)
13184 #define TOK_NOT tok_decl(UNARYPREC,1)
13186 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13187 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13189 #define PREC_PRE (UNARYPREC+2)
13191 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13192 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13194 #define PREC_POST (UNARYPREC+3)
13196 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13197 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13199 #define SPEC_PREC (UNARYPREC+4)
13201 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13202 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13204 #define NUMPTR (*numstackptr)
13206 static inline int tok_have_assign(operator op)
13208 operator prec = PREC(op);
13210 convert_prec_is_assing(prec);
13211 return (prec == PREC(TOK_ASSIGN) ||
13212 prec == PREC_PRE || prec == PREC_POST);
13215 static inline int is_right_associativity(operator prec)
13217 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13218 prec == PREC(TOK_CONDITIONAL));
13222 typedef struct ARITCH_VAR_NUM {
13224 arith_t contidional_second_val;
13225 char contidional_second_val_initialized;
13226 char *var; /* if NULL then is regular number,
13227 else is variable name */
13231 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13233 struct CHK_VAR_RECURSIVE_LOOPED *next;
13234 } chk_var_recursive_looped_t;
13236 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13239 static int arith_lookup_val(v_n_t *t)
13242 const char * p = lookupvar(t->var);
13247 /* recursive try as expression */
13248 chk_var_recursive_looped_t *cur;
13249 chk_var_recursive_looped_t cur_save;
13251 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13252 if(strcmp(cur->var, t->var) == 0) {
13253 /* expression recursion loop detected */
13257 /* save current lookuped var name */
13258 cur = prev_chk_var_recursive;
13259 cur_save.var = t->var;
13260 cur_save.next = cur;
13261 prev_chk_var_recursive = &cur_save;
13263 t->val = arith (p, &errcode);
13264 /* restore previous ptr after recursiving */
13265 prev_chk_var_recursive = cur;
13268 /* allow undefined var as 0 */
13275 /* "applying" a token means performing it on the top elements on the integer
13276 * stack. For a unary operator it will only change the top element, but a
13277 * binary operator will pop two arguments and push a result */
13279 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13282 arith_t numptr_val, rez;
13283 int ret_arith_lookup_val;
13285 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13286 without arguments */
13287 numptr_m1 = NUMPTR - 1;
13289 /* check operand is var with noninteger value */
13290 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13291 if(ret_arith_lookup_val)
13292 return ret_arith_lookup_val;
13294 rez = numptr_m1->val;
13295 if (op == TOK_UMINUS)
13297 else if (op == TOK_NOT)
13299 else if (op == TOK_BNOT)
13301 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13303 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13305 else if (op != TOK_UPLUS) {
13306 /* Binary operators */
13308 /* check and binary operators need two arguments */
13309 if (numptr_m1 == numstack) goto err;
13311 /* ... and they pop one */
13314 if (op == TOK_CONDITIONAL) {
13315 if(! numptr_m1->contidional_second_val_initialized) {
13316 /* protect $((expr1 ? expr2)) without ": expr" */
13319 rez = numptr_m1->contidional_second_val;
13320 } else if(numptr_m1->contidional_second_val_initialized) {
13321 /* protect $((expr1 : expr2)) without "expr ? " */
13324 numptr_m1 = NUMPTR - 1;
13325 if(op != TOK_ASSIGN) {
13326 /* check operand is var with noninteger value for not '=' */
13327 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13328 if(ret_arith_lookup_val)
13329 return ret_arith_lookup_val;
13331 if (op == TOK_CONDITIONAL) {
13332 numptr_m1->contidional_second_val = rez;
13334 rez = numptr_m1->val;
13335 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13337 else if (op == TOK_OR)
13338 rez = numptr_val || rez;
13339 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13341 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13343 else if (op == TOK_AND)
13344 rez = rez && numptr_val;
13345 else if (op == TOK_EQ)
13346 rez = (rez == numptr_val);
13347 else if (op == TOK_NE)
13348 rez = (rez != numptr_val);
13349 else if (op == TOK_GE)
13350 rez = (rez >= numptr_val);
13351 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13352 rez >>= numptr_val;
13353 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13354 rez <<= numptr_val;
13355 else if (op == TOK_GT)
13356 rez = (rez > numptr_val);
13357 else if (op == TOK_LT)
13358 rez = (rez < numptr_val);
13359 else if (op == TOK_LE)
13360 rez = (rez <= numptr_val);
13361 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13363 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13365 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13367 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13369 else if (op == TOK_CONDITIONAL_SEP) {
13370 if (numptr_m1 == numstack) {
13371 /* protect $((expr : expr)) without "expr ? " */
13374 numptr_m1->contidional_second_val_initialized = op;
13375 numptr_m1->contidional_second_val = numptr_val;
13377 else if (op == TOK_CONDITIONAL) {
13379 numptr_val : numptr_m1->contidional_second_val;
13381 else if(op == TOK_EXPONENT) {
13383 return -3; /* exponent less than 0 */
13388 while(numptr_val--)
13393 else if(numptr_val==0) /* zero divisor check */
13395 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13397 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13400 if(tok_have_assign(op)) {
13403 if(numptr_m1->var == NULL) {
13407 /* save to shell variable */
13408 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13409 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13411 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13413 setvar(numptr_m1->var, buf, 0);
13414 /* after saving, make previous value for v++ or v-- */
13415 if(op == TOK_POST_INC)
13417 else if(op == TOK_POST_DEC)
13420 numptr_m1->val = rez;
13421 /* protect geting var value, is number now */
13422 numptr_m1->var = NULL;
13427 /* longest must first */
13428 static const char op_tokens[] = {
13429 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13430 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13431 '<','<', 0, TOK_LSHIFT,
13432 '>','>', 0, TOK_RSHIFT,
13433 '|','|', 0, TOK_OR,
13434 '&','&', 0, TOK_AND,
13435 '!','=', 0, TOK_NE,
13436 '<','=', 0, TOK_LE,
13437 '>','=', 0, TOK_GE,
13438 '=','=', 0, TOK_EQ,
13439 '|','=', 0, TOK_OR_ASSIGN,
13440 '&','=', 0, TOK_AND_ASSIGN,
13441 '*','=', 0, TOK_MUL_ASSIGN,
13442 '/','=', 0, TOK_DIV_ASSIGN,
13443 '%','=', 0, TOK_REM_ASSIGN,
13444 '+','=', 0, TOK_PLUS_ASSIGN,
13445 '-','=', 0, TOK_MINUS_ASSIGN,
13446 '-','-', 0, TOK_POST_DEC,
13447 '^','=', 0, TOK_XOR_ASSIGN,
13448 '+','+', 0, TOK_POST_INC,
13449 '*','*', 0, TOK_EXPONENT,
13453 '=', 0, TOK_ASSIGN,
13465 '?', 0, TOK_CONDITIONAL,
13466 ':', 0, TOK_CONDITIONAL_SEP,
13467 ')', 0, TOK_RPAREN,
13468 '(', 0, TOK_LPAREN,
13472 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13475 static arith_t arith (const char *expr, int *perrcode)
13477 register char arithval; /* Current character under analysis */
13478 operator lasttok, op;
13481 const char *p = endexpression;
13484 size_t datasizes = strlen(expr) + 2;
13486 /* Stack of integers */
13487 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13488 * in any given correct or incorrect expression is left as an exercise to
13490 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13491 *numstackptr = numstack;
13492 /* Stack of operator tokens */
13493 operator *stack = alloca((datasizes) * sizeof(operator)),
13496 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13497 *perrcode = errcode = 0;
13500 if ((arithval = *expr) == 0) {
13501 if (p == endexpression) {
13502 /* Null expression. */
13506 /* This is only reached after all tokens have been extracted from the
13507 * input stream. If there are still tokens on the operator stack, they
13508 * are to be applied in order. At the end, there should be a final
13509 * result on the integer stack */
13511 if (expr != endexpression + 1) {
13512 /* If we haven't done so already, */
13513 /* append a closing right paren */
13514 expr = endexpression;
13515 /* and let the loop process it. */
13518 /* At this point, we're done with the expression. */
13519 if (numstackptr != numstack+1) {
13520 /* ... but if there isn't, it's bad */
13522 return (*perrcode = -1);
13524 if(numstack->var) {
13525 /* expression is $((var)) only, lookup now */
13526 errcode = arith_lookup_val(numstack);
13529 *perrcode = errcode;
13530 return numstack->val;
13532 /* Continue processing the expression. */
13533 if (arith_isspace(arithval)) {
13534 /* Skip whitespace */
13537 if((p = endofname(expr)) != expr) {
13538 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13540 numstackptr->var = alloca(var_name_size);
13541 safe_strncpy(numstackptr->var, expr, var_name_size);
13544 numstackptr->contidional_second_val_initialized = 0;
13548 } else if (is_digit(arithval)) {
13549 numstackptr->var = NULL;
13550 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13551 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13553 numstackptr->val = strtol(expr, (char **) &expr, 0);
13557 for(p = op_tokens; ; p++) {
13561 /* strange operator not found */
13564 for(o = expr; *p && *o == *p; p++)
13571 /* skip tail uncompared token */
13574 /* skip zero delim */
13579 /* post grammar: a++ reduce to num */
13580 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13583 /* Plus and minus are binary (not unary) _only_ if the last
13584 * token was as number, or a right paren (which pretends to be
13585 * a number, since it evaluates to one). Think about it.
13586 * It makes sense. */
13587 if (lasttok != TOK_NUM) {
13603 /* We don't want a unary operator to cause recursive descent on the
13604 * stack, because there can be many in a row and it could cause an
13605 * operator to be evaluated before its argument is pushed onto the
13606 * integer stack. */
13607 /* But for binary operators, "apply" everything on the operator
13608 * stack until we find an operator with a lesser priority than the
13609 * one we have just extracted. */
13610 /* Left paren is given the lowest priority so it will never be
13611 * "applied" in this way.
13612 * if associativity is right and priority eq, applied also skip
13615 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13616 /* not left paren or unary */
13617 if (lasttok != TOK_NUM) {
13618 /* binary op must be preceded by a num */
13621 while (stackptr != stack) {
13622 if (op == TOK_RPAREN) {
13623 /* The algorithm employed here is simple: while we don't
13624 * hit an open paren nor the bottom of the stack, pop
13625 * tokens and apply them */
13626 if (stackptr[-1] == TOK_LPAREN) {
13628 /* Any operator directly after a */
13630 /* close paren should consider itself binary */
13634 operator prev_prec = PREC(stackptr[-1]);
13636 convert_prec_is_assing(prec);
13637 convert_prec_is_assing(prev_prec);
13638 if (prev_prec < prec)
13640 /* check right assoc */
13641 if(prev_prec == prec && is_right_associativity(prec))
13644 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13645 if(errcode) goto ret;
13647 if (op == TOK_RPAREN) {
13652 /* Push this operator to the stack and remember it. */
13653 *stackptr++ = lasttok = op;
13660 #endif /* CONFIG_ASH_MATH_SUPPORT */
13664 const char *bb_applet_name = "debug stuff usage";
13665 int main(int argc, char **argv)
13667 return ash_main(argc, argv);
13672 * Copyright (c) 1989, 1991, 1993, 1994
13673 * The Regents of the University of California. All rights reserved.
13675 * This code is derived from software contributed to Berkeley by
13676 * Kenneth Almquist.
13678 * Redistribution and use in source and binary forms, with or without
13679 * modification, are permitted provided that the following conditions
13681 * 1. Redistributions of source code must retain the above copyright
13682 * notice, this list of conditions and the following disclaimer.
13683 * 2. Redistributions in binary form must reproduce the above copyright
13684 * notice, this list of conditions and the following disclaimer in the
13685 * documentation and/or other materials provided with the distribution.
13686 * 3. Neither the name of the University nor the names of its contributors
13687 * may be used to endorse or promote products derived from this software
13688 * without specific prior written permission.
13690 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13691 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13692 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13693 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13694 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13695 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13696 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13697 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13698 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13699 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF