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 /* make sure to keep these in proper order since it is searched via bsearch() */
1316 static const struct builtincmd builtincmd[] = {
1317 { BUILTIN_SPEC_REG ".", dotcmd },
1318 { BUILTIN_SPEC_REG ":", truecmd },
1319 #ifdef CONFIG_ASH_BUILTIN_TEST
1320 { BUILTIN_REGULAR "[", testcmd },
1321 { BUILTIN_REGULAR "[[", testcmd },
1323 #ifdef CONFIG_ASH_ALIAS
1324 { BUILTIN_REG_ASSG "alias", aliascmd },
1327 { BUILTIN_REGULAR "bg", bgcmd },
1329 { BUILTIN_SPEC_REG "break", breakcmd },
1330 { BUILTIN_REGULAR "cd", cdcmd },
1331 { BUILTIN_NOSPEC "chdir", cdcmd },
1332 #ifdef CONFIG_ASH_CMDCMD
1333 { BUILTIN_REGULAR "command", commandcmd },
1335 { BUILTIN_SPEC_REG "continue", breakcmd },
1336 #ifdef CONFIG_ASH_BUILTIN_ECHO
1337 { BUILTIN_REGULAR "echo", echocmd },
1339 { BUILTIN_SPEC_REG "eval", evalcmd },
1340 { BUILTIN_SPEC_REG "exec", execcmd },
1341 { BUILTIN_SPEC_REG "exit", exitcmd },
1342 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1343 { BUILTIN_REGULAR "false", falsecmd },
1345 { BUILTIN_REGULAR "fg", fgcmd },
1347 #ifdef CONFIG_ASH_GETOPTS
1348 { BUILTIN_REGULAR "getopts", getoptscmd },
1350 { BUILTIN_NOSPEC "hash", hashcmd },
1351 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1352 { BUILTIN_NOSPEC "help", helpcmd },
1355 { BUILTIN_REGULAR "jobs", jobscmd },
1356 { BUILTIN_REGULAR "kill", killcmd },
1358 #ifdef CONFIG_ASH_MATH_SUPPORT
1359 { BUILTIN_NOSPEC "let", letcmd },
1361 { BUILTIN_ASSIGN "local", localcmd },
1362 { BUILTIN_NOSPEC "pwd", pwdcmd },
1363 { BUILTIN_REGULAR "read", readcmd },
1364 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1365 { BUILTIN_SPEC_REG "return", returncmd },
1366 { BUILTIN_SPEC_REG "set", setcmd },
1367 { BUILTIN_SPEC_REG "shift", shiftcmd },
1368 { BUILTIN_SPEC_REG "source", dotcmd },
1369 #ifdef CONFIG_ASH_BUILTIN_TEST
1370 { BUILTIN_REGULAR "test", testcmd },
1372 { BUILTIN_SPEC_REG "times", timescmd },
1373 { BUILTIN_SPEC_REG "trap", trapcmd },
1374 { BUILTIN_REGULAR "true", truecmd },
1375 { BUILTIN_NOSPEC "type", typecmd },
1376 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1377 { BUILTIN_REGULAR "umask", umaskcmd },
1378 #ifdef CONFIG_ASH_ALIAS
1379 { BUILTIN_REGULAR "unalias", unaliascmd },
1381 { BUILTIN_SPEC_REG "unset", unsetcmd },
1382 { BUILTIN_REGULAR "wait", waitcmd },
1385 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1393 const struct builtincmd *cmd;
1394 struct funcnode *func;
1399 /* action to find_command() */
1400 #define DO_ERR 0x01 /* prints errors */
1401 #define DO_ABS 0x02 /* checks absolute paths */
1402 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1403 #define DO_ALTPATH 0x08 /* using alternate path */
1404 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1406 static const char *pathopt; /* set by padvance */
1408 static void shellexec(char **, const char *, int)
1410 static char *padvance(const char **, const char *);
1411 static void find_command(char *, struct cmdentry *, int, const char *);
1412 static struct builtincmd *find_builtin(const char *);
1413 static void hashcd(void);
1414 static void changepath(const char *);
1415 static void defun(char *, union node *);
1416 static void unsetfunc(const char *);
1418 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1419 typedef int64_t arith_t;
1420 #define arith_t_type (long long)
1422 typedef long arith_t;
1423 #define arith_t_type (long)
1426 #ifdef CONFIG_ASH_MATH_SUPPORT
1427 static arith_t dash_arith(const char *);
1428 static arith_t arith(const char *expr, int *perrcode);
1431 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1432 static unsigned long rseed;
1433 static void change_random(const char *);
1434 # ifndef DYNAMIC_VAR
1435 # define DYNAMIC_VAR
1441 static void reset(void);
1450 #define VEXPORT 0x01 /* variable is exported */
1451 #define VREADONLY 0x02 /* variable cannot be modified */
1452 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1453 #define VTEXTFIXED 0x08 /* text is statically allocated */
1454 #define VSTACK 0x10 /* text is allocated on the stack */
1455 #define VUNSET 0x20 /* the variable is not set */
1456 #define VNOFUNC 0x40 /* don't call the callback function */
1457 #define VNOSET 0x80 /* do not set variable - just readonly test */
1458 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1460 # define VDYNAMIC 0x200 /* dynamic variable */
1466 struct var *next; /* next entry in hash list */
1467 int flags; /* flags are defined above */
1468 const char *text; /* name=value */
1469 void (*func)(const char *); /* function to be called when */
1470 /* the variable gets set/unset */
1474 struct localvar *next; /* next local variable in list */
1475 struct var *vp; /* the variable that was made local */
1476 int flags; /* saved flags */
1477 const char *text; /* saved text */
1481 static struct localvar *localvars;
1487 #ifdef CONFIG_ASH_GETOPTS
1488 static void getoptsreset(const char *);
1491 #ifdef CONFIG_LOCALE_SUPPORT
1493 static void change_lc_all(const char *value);
1494 static void change_lc_ctype(const char *value);
1500 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1502 static const char defifsvar[] = "IFS= \t\n";
1503 #define defifs (defifsvar + 4)
1505 static const char defifs[] = " \t\n";
1509 static struct var varinit[] = {
1511 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1513 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1516 #ifdef CONFIG_ASH_MAIL
1517 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1518 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1521 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1522 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1523 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1524 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1525 #ifdef CONFIG_ASH_GETOPTS
1526 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1528 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1529 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1531 #ifdef CONFIG_LOCALE_SUPPORT
1532 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1533 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1535 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1536 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1540 #define vifs varinit[0]
1541 #ifdef CONFIG_ASH_MAIL
1542 #define vmail (&vifs)[1]
1543 #define vmpath (&vmail)[1]
1547 #define vpath (&vmpath)[1]
1548 #define vps1 (&vpath)[1]
1549 #define vps2 (&vps1)[1]
1550 #define vps4 (&vps2)[1]
1551 #define voptind (&vps4)[1]
1552 #ifdef CONFIG_ASH_GETOPTS
1553 #define vrandom (&voptind)[1]
1555 #define vrandom (&vps4)[1]
1557 #define defpath (defpathvar + 5)
1560 * The following macros access the values of the above variables.
1561 * They have to skip over the name. They return the null string
1562 * for unset variables.
1565 #define ifsval() (vifs.text + 4)
1566 #define ifsset() ((vifs.flags & VUNSET) == 0)
1567 #define mailval() (vmail.text + 5)
1568 #define mpathval() (vmpath.text + 9)
1569 #define pathval() (vpath.text + 5)
1570 #define ps1val() (vps1.text + 4)
1571 #define ps2val() (vps2.text + 4)
1572 #define ps4val() (vps4.text + 4)
1573 #define optindval() (voptind.text + 7)
1575 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1577 static void setvar(const char *, const char *, int);
1578 static void setvareq(char *, int);
1579 static void listsetvar(struct strlist *, int);
1580 static char *lookupvar(const char *);
1581 static char *bltinlookup(const char *);
1582 static char **listvars(int, int, char ***);
1583 #define environment() listvars(VEXPORT, VUNSET, 0)
1584 static int showvars(const char *, int, int);
1585 static void poplocalvars(void);
1586 static int unsetvar(const char *);
1587 #ifdef CONFIG_ASH_GETOPTS
1588 static int setvarsafe(const char *, const char *, int);
1590 static int varcmp(const char *, const char *);
1591 static struct var **hashvar(const char *);
1594 static inline int varequal(const char *a, const char *b) {
1595 return !varcmp(a, b);
1599 static int loopnest; /* current loop nesting level */
1602 * The parsefile structure pointed to by the global variable parsefile
1603 * contains information about the current file being read.
1608 struct redirtab *next;
1613 static struct redirtab *redirlist;
1614 static int nullredirs;
1616 extern char **environ;
1621 static void outstr(const char *, FILE *);
1622 static void outcslow(int, FILE *);
1623 static void flushall(void);
1624 static void flusherr(void);
1625 static int out1fmt(const char *, ...)
1626 __attribute__((__format__(__printf__,1,2)));
1627 static int fmtstr(char *, size_t, const char *, ...)
1628 __attribute__((__format__(__printf__,3,4)));
1630 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1633 static void out1str(const char *p)
1638 static void out2str(const char *p)
1645 * Initialization code.
1649 * This routine initializes the builtin variables.
1660 * PS1 depends on uid
1662 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1663 vps1.text = "PS1=\\w \\$ ";
1666 vps1.text = "PS1=# ";
1669 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1671 vpp = hashvar(vp->text);
1674 } while (++vp < end);
1683 basepf.nextc = basepf.buf = basebuf;
1688 signal(SIGCHLD, SIG_DFL);
1696 struct stat st1, st2;
1699 for (envp = environ ; envp && *envp ; envp++) {
1700 if (strchr(*envp, '=')) {
1701 setvareq(*envp, VEXPORT|VTEXTFIXED);
1705 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1706 setvar("PPID", ppid, 0);
1708 p = lookupvar("PWD");
1710 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1711 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1717 /* PEOF (the end of file marker) */
1720 INPUT_PUSH_FILE = 1,
1721 INPUT_NOFILE_OK = 2,
1725 * The input line number. Input.c just defines this variable, and saves
1726 * and restores it when files are pushed and popped. The user of this
1727 * package must set its value.
1730 static int pgetc(void);
1731 static int pgetc2(void);
1732 static int preadbuffer(void);
1733 static void pungetc(void);
1734 static void pushstring(char *, void *);
1735 static void popstring(void);
1736 static void setinputfd(int, int);
1737 static void setinputstring(char *);
1738 static void popfile(void);
1739 static void popallfiles(void);
1740 static void closescript(void);
1746 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1749 #define FORK_NOJOB 2
1751 /* mode flags for showjob(s) */
1752 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1753 #define SHOW_PID 0x04 /* include process pid */
1754 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1758 * A job structure contains information about a job. A job is either a
1759 * single process or a set of processes contained in a pipeline. In the
1760 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1765 pid_t pid; /* process id */
1766 int status; /* last process status from wait() */
1767 char *cmd; /* text of command being run */
1771 struct procstat ps0; /* status of process */
1772 struct procstat *ps; /* status or processes when more than one */
1774 int stopstatus; /* status of a stopped job */
1777 nprocs: 16, /* number of processes */
1779 #define JOBRUNNING 0 /* at least one proc running */
1780 #define JOBSTOPPED 1 /* all procs are stopped */
1781 #define JOBDONE 2 /* all procs are completed */
1783 sigint: 1, /* job was killed by SIGINT */
1784 jobctl: 1, /* job running under job control */
1786 waited: 1, /* true if this entry has been waited for */
1787 used: 1, /* true if this entry is in used */
1788 changed: 1; /* true if status has changed */
1789 struct job *prev_job; /* previous job */
1792 static pid_t backgndpid; /* pid of last background process */
1793 static int job_warning; /* user was warned about stopped jobs */
1795 static int jobctl; /* true if doing job control */
1798 static struct job *makejob(union node *, int);
1799 static int forkshell(struct job *, union node *, int);
1800 static int waitforjob(struct job *);
1801 static int stoppedjobs(void);
1804 #define setjobctl(on) /* do nothing */
1806 static void setjobctl(int);
1807 static void showjobs(FILE *, int);
1813 /* pid of main shell */
1815 /* shell level: 0 for the main shell, 1 for its children, and so on */
1817 #define rootshell (!shlvl)
1819 static void readcmdfile(char *);
1820 static int cmdloop(int);
1826 struct stack_block *stackp;
1829 struct stackmark *marknext;
1832 /* minimum size of a block */
1833 #define MINSIZE SHELL_ALIGN(504)
1835 struct stack_block {
1836 struct stack_block *prev;
1837 char space[MINSIZE];
1840 static struct stack_block stackbase;
1841 static struct stack_block *stackp = &stackbase;
1842 static struct stackmark *markp;
1843 static char *stacknxt = stackbase.space;
1844 static size_t stacknleft = MINSIZE;
1845 static char *sstrend = stackbase.space + MINSIZE;
1846 static int herefd = -1;
1849 static pointer ckmalloc(size_t);
1850 static pointer ckrealloc(pointer, size_t);
1851 static char *savestr(const char *);
1852 static pointer stalloc(size_t);
1853 static void stunalloc(pointer);
1854 static void setstackmark(struct stackmark *);
1855 static void popstackmark(struct stackmark *);
1856 static void growstackblock(void);
1857 static void *growstackstr(void);
1858 static char *makestrspace(size_t, char *);
1859 static char *stnputs(const char *, size_t, char *);
1860 static char *stputs(const char *, char *);
1863 static inline char *_STPUTC(int c, char *p) {
1870 #define stackblock() ((void *)stacknxt)
1871 #define stackblocksize() stacknleft
1872 #define STARTSTACKSTR(p) ((p) = stackblock())
1873 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1874 #define CHECKSTRSPACE(n, p) \
1878 size_t m = sstrend - q; \
1880 (p) = makestrspace(l, q); \
1883 #define USTPUTC(c, p) (*p++ = (c))
1884 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1885 #define STUNPUTC(p) (--p)
1886 #define STTOPC(p) p[-1]
1887 #define STADJUST(amount, p) (p += (amount))
1889 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1890 #define ungrabstackstr(s, p) stunalloc((s))
1891 #define stackstrend() ((void *)sstrend)
1893 #define ckfree(p) free((pointer)(p))
1898 #define DOLATSTRLEN 4
1900 static char *prefix(const char *, const char *);
1901 static int number(const char *);
1902 static int is_number(const char *);
1903 static char *single_quote(const char *);
1904 static char *sstrdup(const char *);
1906 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1907 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1912 int nparam; /* # of positional parameters (without $0) */
1913 unsigned char malloc; /* if parameter list dynamically allocated */
1914 char **p; /* parameter list */
1915 #ifdef CONFIG_ASH_GETOPTS
1916 int optind; /* next parameter to be processed by getopts */
1917 int optoff; /* used by getopts */
1922 #define eflag optlist[0]
1923 #define fflag optlist[1]
1924 #define Iflag optlist[2]
1925 #define iflag optlist[3]
1926 #define mflag optlist[4]
1927 #define nflag optlist[5]
1928 #define sflag optlist[6]
1929 #define xflag optlist[7]
1930 #define vflag optlist[8]
1931 #define Cflag optlist[9]
1932 #define aflag optlist[10]
1933 #define bflag optlist[11]
1934 #define uflag optlist[12]
1935 #define viflag optlist[13]
1938 #define nolog optlist[14]
1939 #define debug optlist[15]
1942 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1943 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1949 static const char *const optletters_optnames[] = {
1970 #define optletters(n) optletters_optnames[(n)][0]
1971 #define optnames(n) (&optletters_optnames[(n)][1])
1973 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1975 static char optlist[NOPTS];
1978 static char *arg0; /* value of $0 */
1979 static struct shparam shellparam; /* $@ current positional parameters */
1980 static char **argptr; /* argument list for builtin commands */
1981 static char *optionarg; /* set by nextopt (like getopt) */
1982 static char *optptr; /* used by nextopt */
1984 static char *minusc; /* argument to -c option */
1987 static void procargs(int, char **);
1988 static void optschanged(void);
1989 static void setparam(char **);
1990 static void freeparam(volatile struct shparam *);
1991 static int shiftcmd(int, char **);
1992 static int setcmd(int, char **);
1993 static int nextopt(const char *);
1997 /* flags passed to redirect */
1998 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1999 #define REDIR_SAVEFD2 03 /* set preverrout */
2002 static void redirect(union node *, int);
2003 static void popredir(int);
2004 static void clearredir(int);
2005 static int copyfd(int, int);
2006 static int redirectsafe(union node *, int);
2012 static void showtree(union node *);
2013 static void trace(const char *, ...);
2014 static void tracev(const char *, va_list);
2015 static void trargs(char **);
2016 static void trputc(int);
2017 static void trputs(const char *);
2018 static void opentrace(void);
2024 /* trap handler commands */
2025 static char *trap[NSIG];
2026 /* current value of signal */
2027 static char sigmode[NSIG - 1];
2028 /* indicates specified signal received */
2029 static char gotsig[NSIG - 1];
2031 static void clear_traps(void);
2032 static void setsignal(int);
2033 static void ignoresig(int);
2034 static void onsig(int);
2035 static int dotrap(void);
2036 static void setinteractive(int);
2037 static void exitshell(void) ATTRIBUTE_NORETURN;
2038 static int decode_signal(const char *, int);
2041 * This routine is called when an error or an interrupt occurs in an
2042 * interactive shell and control is returned to the main command loop.
2056 parselleft = parsenleft = 0; /* clear input buffer */
2060 /* from parser.c: */
2073 #ifdef CONFIG_ASH_ALIAS
2074 static struct alias *atab[ATABSIZE];
2076 static void setalias(const char *, const char *);
2077 static struct alias *freealias(struct alias *);
2078 static struct alias **__lookupalias(const char *);
2081 setalias(const char *name, const char *val)
2083 struct alias *ap, **app;
2085 app = __lookupalias(name);
2089 if (!(ap->flag & ALIASINUSE)) {
2092 ap->val = savestr(val);
2093 ap->flag &= ~ALIASDEAD;
2096 ap = ckmalloc(sizeof (struct alias));
2097 ap->name = savestr(name);
2098 ap->val = savestr(val);
2107 unalias(const char *name)
2111 app = __lookupalias(name);
2115 *app = freealias(*app);
2126 struct alias *ap, **app;
2130 for (i = 0; i < ATABSIZE; i++) {
2132 for (ap = *app; ap; ap = *app) {
2133 *app = freealias(*app);
2142 static struct alias *
2143 lookupalias(const char *name, int check)
2145 struct alias *ap = *__lookupalias(name);
2147 if (check && ap && (ap->flag & ALIASINUSE))
2153 * TODO - sort output
2156 aliascmd(int argc, char **argv)
2165 for (i = 0; i < ATABSIZE; i++)
2166 for (ap = atab[i]; ap; ap = ap->next) {
2171 while ((n = *++argv) != NULL) {
2172 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2173 if ((ap = *__lookupalias(n)) == NULL) {
2174 fprintf(stderr, "%s: %s not found\n", "alias", n);
2188 unaliascmd(int argc, char **argv)
2192 while ((i = nextopt("a")) != '\0') {
2198 for (i = 0; *argptr; argptr++) {
2199 if (unalias(*argptr)) {
2200 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2208 static struct alias *
2209 freealias(struct alias *ap) {
2212 if (ap->flag & ALIASINUSE) {
2213 ap->flag |= ALIASDEAD;
2225 printalias(const struct alias *ap) {
2226 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2229 static struct alias **
2230 __lookupalias(const char *name) {
2231 unsigned int hashval;
2238 ch = (unsigned char)*p;
2242 ch = (unsigned char)*++p;
2244 app = &atab[hashval % ATABSIZE];
2246 for (; *app; app = &(*app)->next) {
2247 if (equal(name, (*app)->name)) {
2254 #endif /* CONFIG_ASH_ALIAS */
2260 * The cd and pwd commands.
2263 #define CD_PHYSICAL 1
2266 static int docd(const char *, int);
2267 static int cdopt(void);
2269 static char *curdir = nullstr; /* current working directory */
2270 static char *physdir = nullstr; /* physical working directory */
2279 while ((i = nextopt("LP"))) {
2281 flags ^= CD_PHYSICAL;
2290 cdcmd(int argc, char **argv)
2302 dest = bltinlookup(homestr);
2303 else if (dest[0] == '-' && dest[1] == '\0') {
2304 dest = bltinlookup("OLDPWD");
2326 if (!(path = bltinlookup("CDPATH"))) {
2334 p = padvance(&path, dest);
2335 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2339 if (!docd(p, flags))
2344 sh_error("can't cd to %s", dest);
2347 if (flags & CD_PRINT)
2348 out1fmt(snlfmt, curdir);
2354 * Update curdir (the name of the current directory) in response to a
2358 static inline const char *
2359 updatepwd(const char *dir)
2366 cdcomppath = sstrdup(dir);
2369 if (curdir == nullstr)
2371 new = stputs(curdir, new);
2373 new = makestrspace(strlen(dir) + 2, new);
2374 lim = stackblock() + 1;
2378 if (new > lim && *lim == '/')
2383 if (dir[1] == '/' && dir[2] != '/') {
2389 p = strtok(cdcomppath, "/");
2393 if (p[1] == '.' && p[2] == '\0') {
2400 } else if (p[1] == '\0')
2404 new = stputs(p, new);
2412 return stackblock();
2416 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2417 * know that the current directory has changed.
2421 docd(const char *dest, int flags)
2423 const char *dir = 0;
2426 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2429 if (!(flags & CD_PHYSICAL)) {
2430 dir = updatepwd(dest);
2445 * Find out what the current directory is. If we already know the current
2446 * directory, this routine returns immediately.
2448 static inline char *
2451 char *dir = getcwd(0, 0);
2452 return dir ? dir : nullstr;
2456 pwdcmd(int argc, char **argv)
2459 const char *dir = curdir;
2463 if (physdir == nullstr)
2467 out1fmt(snlfmt, dir);
2472 setpwd(const char *val, int setold)
2476 oldcur = dir = curdir;
2479 setvar("OLDPWD", oldcur, VEXPORT);
2482 if (physdir != nullstr) {
2483 if (physdir != oldcur)
2487 if (oldcur == val || !val) {
2494 if (oldcur != dir && oldcur != nullstr) {
2499 setvar("PWD", dir, VEXPORT);
2505 * Errors and exceptions.
2509 * Code to handle exceptions in C.
2514 static void exverror(int, const char *, va_list)
2518 * Called to raise an exception. Since C doesn't include exceptions, we
2519 * just do a longjmp to the exception handler. The type of exception is
2520 * stored in the global variable "exception".
2527 if (handler == NULL)
2533 longjmp(handler->loc, 1);
2538 * Called from trap.c when a SIGINT is received. (If the user specifies
2539 * that SIGINT is to be trapped or ignored using the trap builtin, then
2540 * this routine is not called.) Suppressint is nonzero when interrupts
2541 * are held using the INTOFF macro. (The test for iflag is just
2542 * defensive programming.)
2551 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2552 if (!(rootshell && iflag)) {
2553 signal(SIGINT, SIG_DFL);
2563 exvwarning(const char *msg, va_list ap)
2568 fprintf(errs, "%s: ", arg0);
2570 const char *fmt = (!iflag || parsefile->fd) ?
2571 "%s: %d: " : "%s: ";
2572 fprintf(errs, fmt, commandname, startlinno);
2574 vfprintf(errs, msg, ap);
2575 outcslow('\n', errs);
2579 * Exverror is called to raise the error exception. If the second argument
2580 * is not NULL then error prints an error message using printf style
2581 * formatting. It then raises the error exception.
2584 exverror(int cond, const char *msg, va_list ap)
2588 TRACE(("exverror(%d, \"", cond));
2590 TRACE(("\") pid=%d\n", getpid()));
2592 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2595 exvwarning(msg, ap);
2604 sh_error(const char *msg, ...)
2609 exverror(EXERROR, msg, ap);
2616 exerror(int cond, const char *msg, ...)
2621 exverror(cond, msg, ap);
2627 * error/warning routines for external builtins
2631 sh_warnx(const char *fmt, ...)
2636 exvwarning(fmt, ap);
2642 * Return a string describing an error. The returned string may be a
2643 * pointer to a static buffer that will be overwritten on the next call.
2644 * Action describes the operation that got the error.
2648 errmsg(int e, const char *em)
2650 if(e == ENOENT || e == ENOTDIR) {
2661 * Evaluate a command.
2664 /* flags in argument to evaltree */
2665 #define EV_EXIT 01 /* exit after evaluating tree */
2666 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2667 #define EV_BACKCMD 04 /* command executing within back quotes */
2670 static void evalloop(union node *, int);
2671 static void evalfor(union node *, int);
2672 static void evalcase(union node *, int);
2673 static void evalsubshell(union node *, int);
2674 static void expredir(union node *);
2675 static void evalpipe(union node *, int);
2676 static void evalcommand(union node *, int);
2677 static int evalbltin(const struct builtincmd *, int, char **);
2678 static int evalfun(struct funcnode *, int, char **, int);
2679 static void prehash(union node *);
2680 static int bltincmd(int, char **);
2683 static const struct builtincmd bltin = {
2689 * Called to reset things after an exception.
2697 evalcmd(int argc, char **argv)
2706 STARTSTACKSTR(concat);
2709 concat = stputs(p, concat);
2710 if ((p = *ap++) == NULL)
2712 STPUTC(' ', concat);
2714 STPUTC('\0', concat);
2715 p = grabstackstr(concat);
2717 evalstring(p, ~SKIPEVAL);
2725 * Execute a command or commands contained in a string.
2729 evalstring(char *s, int mask)
2732 struct stackmark smark;
2736 setstackmark(&smark);
2739 while ((n = parsecmd(0)) != NEOF) {
2741 popstackmark(&smark);
2756 * Evaluate a parse tree. The value is left in the global variable
2761 evaltree(union node *n, int flags)
2764 void (*evalfn)(union node *, int);
2768 TRACE(("evaltree(NULL) called\n"));
2771 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2772 getpid(), n, n->type, flags));
2776 out1fmt("Node type = %d\n", n->type);
2781 evaltree(n->nnot.com, EV_TESTED);
2782 status = !exitstatus;
2785 expredir(n->nredir.redirect);
2786 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2788 evaltree(n->nredir.n, flags & EV_TESTED);
2789 status = exitstatus;
2794 evalfn = evalcommand;
2796 if (eflag && !(flags & EV_TESTED))
2808 evalfn = evalsubshell;
2820 #error NAND + 1 != NOR
2822 #if NOR + 1 != NSEMI
2823 #error NOR + 1 != NSEMI
2825 isor = n->type - NAND;
2828 (flags | ((isor >> 1) - 1)) & EV_TESTED
2830 if (!exitstatus == isor)
2842 evaltree(n->nif.test, EV_TESTED);
2845 if (exitstatus == 0) {
2848 } else if (n->nif.elsepart) {
2849 n = n->nif.elsepart;
2854 defun(n->narg.text, n->narg.next);
2858 exitstatus = status;
2862 if ((checkexit & exitstatus))
2863 evalskip |= SKIPEVAL;
2864 else if (pendingsigs && dotrap())
2867 if (flags & EV_EXIT) {
2874 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2877 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2881 evalloop(union node *n, int flags)
2891 evaltree(n->nbinary.ch1, EV_TESTED);
2893 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2897 if (evalskip == SKIPBREAK && --skipcount <= 0)
2902 if (n->type != NWHILE)
2906 evaltree(n->nbinary.ch2, flags);
2907 status = exitstatus;
2912 exitstatus = status;
2918 evalfor(union node *n, int flags)
2920 struct arglist arglist;
2923 struct stackmark smark;
2925 setstackmark(&smark);
2926 arglist.lastp = &arglist.list;
2927 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2928 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2933 *arglist.lastp = NULL;
2938 for (sp = arglist.list ; sp ; sp = sp->next) {
2939 setvar(n->nfor.var, sp->text, 0);
2940 evaltree(n->nfor.body, flags);
2942 if (evalskip == SKIPCONT && --skipcount <= 0) {
2946 if (evalskip == SKIPBREAK && --skipcount <= 0)
2953 popstackmark(&smark);
2959 evalcase(union node *n, int flags)
2963 struct arglist arglist;
2964 struct stackmark smark;
2966 setstackmark(&smark);
2967 arglist.lastp = &arglist.list;
2968 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2970 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2971 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2972 if (casematch(patp, arglist.list->text)) {
2973 if (evalskip == 0) {
2974 evaltree(cp->nclist.body, flags);
2981 popstackmark(&smark);
2987 * Kick off a subshell to evaluate a tree.
2991 evalsubshell(union node *n, int flags)
2994 int backgnd = (n->type == NBACKGND);
2997 expredir(n->nredir.redirect);
2998 if (!backgnd && flags & EV_EXIT && !trap[0])
3002 if (forkshell(jp, n, backgnd) == 0) {
3006 flags &=~ EV_TESTED;
3008 redirect(n->nredir.redirect, 0);
3009 evaltreenr(n->nredir.n, flags);
3014 status = waitforjob(jp);
3015 exitstatus = status;
3022 * Compute the names of the files in a redirection list.
3026 expredir(union node *n)
3030 for (redir = n ; redir ; redir = redir->nfile.next) {
3032 fn.lastp = &fn.list;
3033 switch (redir->type) {
3039 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3040 redir->nfile.expfname = fn.list->text;
3044 if (redir->ndup.vname) {
3045 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3046 fixredir(redir, fn.list->text, 1);
3056 * Evaluate a pipeline. All the processes in the pipeline are children
3057 * of the process creating the pipeline. (This differs from some versions
3058 * of the shell, which make the last process in a pipeline the parent
3063 evalpipe(union node *n, int flags)
3066 struct nodelist *lp;
3071 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3073 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3077 jp = makejob(n, pipelen);
3079 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3083 if (pipe(pip) < 0) {
3085 sh_error("Pipe call failed");
3088 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3101 evaltreenr(lp->n, flags);
3109 if (n->npipe.backgnd == 0) {
3110 exitstatus = waitforjob(jp);
3111 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3119 * Execute a command inside back quotes. If it's a builtin command, we
3120 * want to save its output in a block obtained from malloc. Otherwise
3121 * we fork off a subprocess and get the output of the command via a pipe.
3122 * Should be called with interrupts off.
3126 evalbackcmd(union node *n, struct backcmd *result)
3138 saveherefd = herefd;
3146 sh_error("Pipe call failed");
3148 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3157 evaltreenr(n, EV_EXIT);
3161 result->fd = pip[0];
3164 herefd = saveherefd;
3166 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3167 result->fd, result->buf, result->nleft, result->jp));
3170 #ifdef CONFIG_ASH_CMDCMD
3171 static inline char **
3172 parse_command_args(char **argv, const char **path)
3184 if (c == '-' && !*cp) {
3194 /* run 'typecmd' for other options */
3197 } while ((c = *cp++));
3204 isassignment(const char *p)
3206 const char *q = endofname(p);
3212 #ifdef CONFIG_ASH_EXPAND_PRMT
3213 static const char *expandstr(const char *ps);
3215 #define expandstr(s) s
3219 * Execute a simple command.
3223 evalcommand(union node *cmd, int flags)
3225 struct stackmark smark;
3227 struct arglist arglist;
3228 struct arglist varlist;
3231 const struct strlist *sp;
3232 struct cmdentry cmdentry;
3240 struct builtincmd *bcmd;
3241 int pseudovarflag = 0;
3243 /* First expand the arguments. */
3244 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3245 setstackmark(&smark);
3246 back_exitstatus = 0;
3248 cmdentry.cmdtype = CMDBUILTIN;
3249 cmdentry.u.cmd = &bltin;
3250 varlist.lastp = &varlist.list;
3251 *varlist.lastp = NULL;
3252 arglist.lastp = &arglist.list;
3253 *arglist.lastp = NULL;
3258 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3259 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3262 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3263 struct strlist **spp;
3265 spp = arglist.lastp;
3266 if (pseudovarflag && isassignment(argp->narg.text))
3267 expandarg(argp, &arglist, EXP_VARTILDE);
3269 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3271 for (sp = *spp; sp; sp = sp->next)
3275 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3276 for (sp = arglist.list ; sp ; sp = sp->next) {
3277 TRACE(("evalcommand arg: %s\n", sp->text));
3278 *nargv++ = sp->text;
3283 if (iflag && funcnest == 0 && argc > 0)
3284 lastarg = nargv[-1];
3287 expredir(cmd->ncmd.redirect);
3288 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3291 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3292 struct strlist **spp;
3295 spp = varlist.lastp;
3296 expandarg(argp, &varlist, EXP_VARTILDE);
3299 * Modify the command lookup path, if a PATH= assignment
3303 if (varequal(p, path))
3307 /* Print the command if xflag is set. */
3310 const char *p = " %s";
3313 dprintf(preverrout_fd, p, expandstr(ps4val()));
3316 for(n = 0; n < 2; n++) {
3318 dprintf(preverrout_fd, p, sp->text);
3326 bb_full_write(preverrout_fd, "\n", 1);
3332 /* Now locate the command. */
3334 const char *oldpath;
3335 int cmd_flag = DO_ERR;
3340 find_command(argv[0], &cmdentry, cmd_flag, path);
3341 if (cmdentry.cmdtype == CMDUNKNOWN) {
3347 /* implement bltin and command here */
3348 if (cmdentry.cmdtype != CMDBUILTIN)
3351 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3352 if (cmdentry.u.cmd == EXECCMD)
3354 #ifdef CONFIG_ASH_CMDCMD
3355 if (cmdentry.u.cmd == COMMANDCMD) {
3358 nargv = parse_command_args(argv, &path);
3361 argc -= nargv - argv;
3363 cmd_flag |= DO_NOFUNC;
3371 /* We have a redirection error. */
3375 exitstatus = status;
3379 /* Execute the command. */
3380 switch (cmdentry.cmdtype) {
3382 /* Fork off a child process if necessary. */
3383 if (!(flags & EV_EXIT) || trap[0]) {
3385 jp = makejob(cmd, 1);
3386 if (forkshell(jp, cmd, FORK_FG) != 0) {
3387 exitstatus = waitforjob(jp);
3393 listsetvar(varlist.list, VEXPORT|VSTACK);
3394 shellexec(argv, path, cmdentry.u.index);
3398 cmdenviron = varlist.list;
3400 struct strlist *list = cmdenviron;
3402 if (spclbltin > 0 || argc == 0) {
3404 if (cmd_is_exec && argc > 1)
3407 listsetvar(list, i);
3409 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3424 exit_status = j + 128;
3425 exitstatus = exit_status;
3427 if (i == EXINT || spclbltin > 0) {
3429 longjmp(handler->loc, 1);
3436 listsetvar(varlist.list, 0);
3437 if (evalfun(cmdentry.u.func, argc, argv, flags))
3443 popredir(cmd_is_exec);
3445 /* dsl: I think this is intended to be used to support
3446 * '_' in 'vi' command mode during line editing...
3447 * However I implemented that within libedit itself.
3449 setvar("_", lastarg, 0);
3450 popstackmark(&smark);
3454 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3455 char *volatile savecmdname;
3456 struct jmploc *volatile savehandler;
3457 struct jmploc jmploc;
3460 savecmdname = commandname;
3461 if ((i = setjmp(jmploc.loc)))
3463 savehandler = handler;
3465 commandname = argv[0];
3467 optptr = NULL; /* initialize nextopt */
3468 exitstatus = (*cmd->builtin)(argc, argv);
3471 exitstatus |= ferror(stdout);
3473 commandname = savecmdname;
3475 handler = savehandler;
3481 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3483 volatile struct shparam saveparam;
3484 struct localvar *volatile savelocalvars;
3485 struct jmploc *volatile savehandler;
3486 struct jmploc jmploc;
3489 saveparam = shellparam;
3490 savelocalvars = localvars;
3491 if ((e = setjmp(jmploc.loc))) {
3495 savehandler = handler;
3498 shellparam.malloc = 0;
3502 shellparam.nparam = argc - 1;
3503 shellparam.p = argv + 1;
3504 #ifdef CONFIG_ASH_GETOPTS
3505 shellparam.optind = 1;
3506 shellparam.optoff = -1;
3508 evaltree(&func->n, flags & EV_TESTED);
3514 localvars = savelocalvars;
3515 freeparam(&shellparam);
3516 shellparam = saveparam;
3517 handler = savehandler;
3519 evalskip &= ~SKIPFUNC;
3525 goodname(const char *p)
3527 return !*endofname(p);
3531 * Search for a command. This is called before we fork so that the
3532 * location of the command will be available in the parent as well as
3533 * the child. The check for "goodname" is an overly conservative
3534 * check that the name will not be subject to expansion.
3538 prehash(union node *n)
3540 struct cmdentry entry;
3542 if (n->type == NCMD && n->ncmd.args)
3543 if (goodname(n->ncmd.args->narg.text))
3544 find_command(n->ncmd.args->narg.text, &entry, 0,
3551 * Builtin commands. Builtin commands whose functions are closely
3552 * tied to evaluation are implemented here.
3560 bltincmd(int argc, char **argv)
3563 * Preserve exitstatus of a previous possible redirection
3566 return back_exitstatus;
3571 * Handle break and continue commands. Break, continue, and return are
3572 * all handled by setting the evalskip flag. The evaluation routines
3573 * above all check this flag, and if it is set they start skipping
3574 * commands rather than executing them. The variable skipcount is
3575 * the number of loops to break/continue, or the number of function
3576 * levels to return. (The latter is always 1.) It should probably
3577 * be an error to break out of more loops than exist, but it isn't
3578 * in the standard shell so we don't make it one here.
3582 breakcmd(int argc, char **argv)
3584 int n = argc > 1 ? number(argv[1]) : 1;
3587 sh_error(illnum, argv[1]);
3591 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3599 * The return command.
3603 returncmd(int argc, char **argv)
3606 * If called outside a function, do what ksh does;
3607 * skip the rest of the file.
3609 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3610 return argv[1] ? number(argv[1]) : exitstatus;
3615 falsecmd(int argc, char **argv)
3622 truecmd(int argc, char **argv)
3629 execcmd(int argc, char **argv)
3632 iflag = 0; /* exit on error */
3635 shellexec(argv + 1, pathval(), 0);
3644 * When commands are first encountered, they are entered in a hash table.
3645 * This ensures that a full path search will not have to be done for them
3646 * on each invocation.
3648 * We should investigate converting to a linear search, even though that
3649 * would make the command name "hash" a misnomer.
3652 #define CMDTABLESIZE 31 /* should be prime */
3653 #define ARB 1 /* actual size determined at run time */
3658 struct tblentry *next; /* next entry in hash chain */
3659 union param param; /* definition of builtin function */
3660 short cmdtype; /* index identifying command */
3661 char rehash; /* if set, cd done since entry created */
3662 char cmdname[ARB]; /* name of command */
3666 static struct tblentry *cmdtable[CMDTABLESIZE];
3667 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3670 static void tryexec(char *, char **, char **);
3671 static void clearcmdentry(int);
3672 static struct tblentry *cmdlookup(const char *, int);
3673 static void delete_cmd_entry(void);
3677 * Exec a program. Never returns. If you change this routine, you may
3678 * have to change the find_command routine as well.
3682 shellexec(char **argv, const char *path, int idx)
3690 envp = environment();
3691 if (strchr(argv[0], '/') != NULL
3692 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3693 || find_applet_by_name(argv[0])
3696 tryexec(argv[0], argv, envp);
3700 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3701 if (--idx < 0 && pathopt == NULL) {
3702 tryexec(cmdname, argv, envp);
3703 if (errno != ENOENT && errno != ENOTDIR)
3710 /* Map to POSIX errors */
3722 exitstatus = exerrno;
3723 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3724 argv[0], e, suppressint ));
3725 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3731 tryexec(char *cmd, char **argv, char **envp)
3734 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3735 if(find_applet_by_name(cmd) != NULL) {
3736 /* re-exec ourselves with the new arguments */
3737 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3738 /* If they called chroot or otherwise made the binary no longer
3739 * executable, fall through */
3746 execve(cmd, argv, envp);
3747 } while (errno == EINTR);
3749 execve(cmd, argv, envp);
3753 } else if (errno == ENOEXEC) {
3757 for (ap = argv; *ap; ap++)
3759 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3761 *ap = cmd = (char *)DEFAULT_SHELL;
3764 while ((*ap++ = *argv++))
3774 * Do a path search. The variable path (passed by reference) should be
3775 * set to the start of the path before the first call; padvance will update
3776 * this value as it proceeds. Successive calls to padvance will return
3777 * the possible path expansions in sequence. If an option (indicated by
3778 * a percent sign) appears in the path entry then the global variable
3779 * pathopt will be set to point to it; otherwise pathopt will be set to
3784 padvance(const char **path, const char *name)
3794 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3795 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3796 while (stackblocksize() < len)
3800 memcpy(q, start, p - start);
3808 while (*p && *p != ':') p++;
3814 return stalloc(len);
3818 /*** Command hashing code ***/
3821 printentry(struct tblentry *cmdp)
3827 idx = cmdp->param.index;
3830 name = padvance(&path, cmdp->cmdname);
3832 } while (--idx >= 0);
3833 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3838 hashcmd(int argc, char **argv)
3840 struct tblentry **pp;
3841 struct tblentry *cmdp;
3843 struct cmdentry entry;
3846 while ((c = nextopt("r")) != '\0') {
3850 if (*argptr == NULL) {
3851 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3852 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3853 if (cmdp->cmdtype == CMDNORMAL)
3860 while ((name = *argptr) != NULL) {
3861 if ((cmdp = cmdlookup(name, 0)) != NULL
3862 && (cmdp->cmdtype == CMDNORMAL
3863 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3865 find_command(name, &entry, DO_ERR, pathval());
3866 if (entry.cmdtype == CMDUNKNOWN)
3875 * Resolve a command name. If you change this routine, you may have to
3876 * change the shellexec routine as well.
3880 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3882 struct tblentry *cmdp;
3889 struct builtincmd *bcmd;
3891 /* If name contains a slash, don't use PATH or hash table */
3892 if (strchr(name, '/') != NULL) {
3893 entry->u.index = -1;
3895 while (stat(name, &statb) < 0) {
3900 entry->cmdtype = CMDUNKNOWN;
3904 entry->cmdtype = CMDNORMAL;
3908 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3909 if (find_applet_by_name(name)) {
3910 entry->cmdtype = CMDNORMAL;
3911 entry->u.index = -1;
3916 updatetbl = (path == pathval());
3919 if (strstr(path, "%builtin") != NULL)
3923 /* If name is in the table, check answer will be ok */
3924 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3927 switch (cmdp->cmdtype) {
3945 } else if (cmdp->rehash == 0)
3946 /* if not invalidated by cd, we're done */
3950 /* If %builtin not in path, check for builtin next */
3951 bcmd = find_builtin(name);
3952 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3953 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3955 goto builtin_success;
3957 /* We have to search path. */
3958 prev = -1; /* where to start */
3959 if (cmdp && cmdp->rehash) { /* doing a rehash */
3960 if (cmdp->cmdtype == CMDBUILTIN)
3963 prev = cmdp->param.index;
3969 while ((fullname = padvance(&path, name)) != NULL) {
3970 stunalloc(fullname);
3973 if (prefix(pathopt, "builtin")) {
3975 goto builtin_success;
3977 } else if (!(act & DO_NOFUNC) &&
3978 prefix(pathopt, "func")) {
3981 /* ignore unimplemented options */
3985 /* if rehash, don't redo absolute path names */
3986 if (fullname[0] == '/' && idx <= prev) {
3989 TRACE(("searchexec \"%s\": no change\n", name));
3992 while (stat(fullname, &statb) < 0) {
3997 if (errno != ENOENT && errno != ENOTDIR)
4001 e = EACCES; /* if we fail, this will be the error */
4002 if (!S_ISREG(statb.st_mode))
4004 if (pathopt) { /* this is a %func directory */
4005 stalloc(strlen(fullname) + 1);
4006 readcmdfile(fullname);
4007 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4008 cmdp->cmdtype != CMDFUNCTION)
4009 sh_error("%s not defined in %s", name, fullname);
4010 stunalloc(fullname);
4013 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4015 entry->cmdtype = CMDNORMAL;
4016 entry->u.index = idx;
4020 cmdp = cmdlookup(name, 1);
4021 cmdp->cmdtype = CMDNORMAL;
4022 cmdp->param.index = idx;
4027 /* We failed. If there was an entry for this command, delete it */
4028 if (cmdp && updatetbl)
4031 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4032 entry->cmdtype = CMDUNKNOWN;
4037 entry->cmdtype = CMDBUILTIN;
4038 entry->u.cmd = bcmd;
4042 cmdp = cmdlookup(name, 1);
4043 cmdp->cmdtype = CMDBUILTIN;
4044 cmdp->param.cmd = bcmd;
4048 entry->cmdtype = cmdp->cmdtype;
4049 entry->u = cmdp->param;
4054 * Wrapper around strcmp for qsort/bsearch/...
4056 static int pstrcmp(const void *a, const void *b)
4058 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4062 * Search the table of builtin commands.
4065 static struct builtincmd *
4066 find_builtin(const char *name)
4068 struct builtincmd *bp;
4071 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4080 * Called when a cd is done. Marks all commands so the next time they
4081 * are executed they will be rehashed.
4087 struct tblentry **pp;
4088 struct tblentry *cmdp;
4090 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4091 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4092 if (cmdp->cmdtype == CMDNORMAL || (
4093 cmdp->cmdtype == CMDBUILTIN &&
4094 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4105 * Fix command hash table when PATH changed.
4106 * Called before PATH is changed. The argument is the new value of PATH;
4107 * pathval() still returns the old value at this point.
4108 * Called with interrupts off.
4112 changepath(const char *newval)
4114 const char *old, *new;
4121 firstchange = 9999; /* assume no change */
4127 if ((*old == '\0' && *new == ':')
4128 || (*old == ':' && *new == '\0'))
4130 old = new; /* ignore subsequent differences */
4134 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4141 if (builtinloc < 0 && idx_bltin >= 0)
4142 builtinloc = idx_bltin; /* zap builtins */
4143 if (builtinloc >= 0 && idx_bltin < 0)
4145 clearcmdentry(firstchange);
4146 builtinloc = idx_bltin;
4151 * Clear out command entries. The argument specifies the first entry in
4152 * PATH which has changed.
4156 clearcmdentry(int firstchange)
4158 struct tblentry **tblp;
4159 struct tblentry **pp;
4160 struct tblentry *cmdp;
4163 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4165 while ((cmdp = *pp) != NULL) {
4166 if ((cmdp->cmdtype == CMDNORMAL &&
4167 cmdp->param.index >= firstchange)
4168 || (cmdp->cmdtype == CMDBUILTIN &&
4169 builtinloc >= firstchange)) {
4183 * Locate a command in the command hash table. If "add" is nonzero,
4184 * add the command to the table if it is not already present. The
4185 * variable "lastcmdentry" is set to point to the address of the link
4186 * pointing to the entry, so that delete_cmd_entry can delete the
4189 * Interrupts must be off if called with add != 0.
4192 static struct tblentry **lastcmdentry;
4195 static struct tblentry *
4196 cmdlookup(const char *name, int add)
4198 unsigned int hashval;
4200 struct tblentry *cmdp;
4201 struct tblentry **pp;
4204 hashval = (unsigned char)*p << 4;
4206 hashval += (unsigned char)*p++;
4208 pp = &cmdtable[hashval % CMDTABLESIZE];
4209 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4210 if (equal(cmdp->cmdname, name))
4214 if (add && cmdp == NULL) {
4215 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4216 + strlen(name) + 1);
4218 cmdp->cmdtype = CMDUNKNOWN;
4219 strcpy(cmdp->cmdname, name);
4226 * Delete the command entry returned on the last lookup.
4230 delete_cmd_entry(void)
4232 struct tblentry *cmdp;
4235 cmdp = *lastcmdentry;
4236 *lastcmdentry = cmdp->next;
4237 if (cmdp->cmdtype == CMDFUNCTION)
4238 freefunc(cmdp->param.func);
4245 * Add a new command entry, replacing any existing command entry for
4246 * the same name - except special builtins.
4250 addcmdentry(char *name, struct cmdentry *entry)
4252 struct tblentry *cmdp;
4254 cmdp = cmdlookup(name, 1);
4255 if (cmdp->cmdtype == CMDFUNCTION) {
4256 freefunc(cmdp->param.func);
4258 cmdp->cmdtype = entry->cmdtype;
4259 cmdp->param = entry->u;
4264 * Make a copy of a parse tree.
4267 static inline struct funcnode *
4268 copyfunc(union node *n)
4273 funcblocksize = offsetof(struct funcnode, n);
4276 blocksize = funcblocksize;
4277 f = ckmalloc(blocksize + funcstringsize);
4278 funcblock = (char *) f + offsetof(struct funcnode, n);
4279 funcstring = (char *) f + blocksize;
4286 * Define a shell function.
4290 defun(char *name, union node *func)
4292 struct cmdentry entry;
4295 entry.cmdtype = CMDFUNCTION;
4296 entry.u.func = copyfunc(func);
4297 addcmdentry(name, &entry);
4303 * Delete a function if it exists.
4307 unsetfunc(const char *name)
4309 struct tblentry *cmdp;
4311 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4312 cmdp->cmdtype == CMDFUNCTION)
4317 * Locate and print what a word is...
4321 #ifdef CONFIG_ASH_CMDCMD
4323 describe_command(char *command, int describe_command_verbose)
4325 #define describe_command_verbose 1
4327 describe_command(char *command)
4330 struct cmdentry entry;
4331 struct tblentry *cmdp;
4332 #ifdef CONFIG_ASH_ALIAS
4333 const struct alias *ap;
4335 const char *path = pathval();
4337 if (describe_command_verbose) {
4341 /* First look at the keywords */
4342 if (findkwd(command)) {
4343 out1str(describe_command_verbose ? " is a shell keyword" : command);
4347 #ifdef CONFIG_ASH_ALIAS
4348 /* Then look at the aliases */
4349 if ((ap = lookupalias(command, 0)) != NULL) {
4350 if (describe_command_verbose) {
4351 out1fmt(" is an alias for %s", ap->val);
4360 /* Then check if it is a tracked alias */
4361 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4362 entry.cmdtype = cmdp->cmdtype;
4363 entry.u = cmdp->param;
4365 /* Finally use brute force */
4366 find_command(command, &entry, DO_ABS, path);
4369 switch (entry.cmdtype) {
4371 int j = entry.u.index;
4377 p = padvance(&path, command);
4381 if (describe_command_verbose) {
4383 (cmdp ? " a tracked alias for" : nullstr), p
4392 if (describe_command_verbose) {
4393 out1str(" is a shell function");
4400 if (describe_command_verbose) {
4401 out1fmt(" is a %sshell builtin",
4402 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4403 "special " : nullstr
4411 if (describe_command_verbose) {
4412 out1str(": not found\n");
4418 outstr("\n", stdout);
4423 typecmd(int argc, char **argv)
4428 for (i = 1; i < argc; i++) {
4429 #ifdef CONFIG_ASH_CMDCMD
4430 err |= describe_command(argv[i], 1);
4432 err |= describe_command(argv[i]);
4438 #ifdef CONFIG_ASH_CMDCMD
4440 commandcmd(int argc, char **argv)
4448 while ((c = nextopt("pvV")) != '\0')
4450 verify |= VERIFY_VERBOSE;
4452 verify |= VERIFY_BRIEF;
4458 return describe_command(*argptr, verify - VERIFY_BRIEF);
4467 * Routines to expand arguments to commands. We have to deal with
4468 * backquotes, shell variables, and file metacharacters.
4474 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4475 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4476 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4477 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4478 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4481 * Structure specifying which parts of the string should be searched
4482 * for IFS characters.
4486 struct ifsregion *next; /* next region in list */
4487 int begoff; /* offset of start of region */
4488 int endoff; /* offset of end of region */
4489 int nulonly; /* search for nul bytes only */
4492 /* output of current string */
4493 static char *expdest;
4494 /* list of back quote expressions */
4495 static struct nodelist *argbackq;
4496 /* first struct in list of ifs regions */
4497 static struct ifsregion ifsfirst;
4498 /* last struct in list */
4499 static struct ifsregion *ifslastp;
4500 /* holds expanded arg list */
4501 static struct arglist exparg;
4503 static void argstr(char *, int);
4504 static char *exptilde(char *, char *, int);
4505 static void expbackq(union node *, int, int);
4506 static const char *subevalvar(char *, char *, int, int, int, int, int);
4507 static char *evalvar(char *, int);
4508 static void strtodest(const char *, int, int);
4509 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4510 static ssize_t varvalue(char *, int, int);
4511 static void recordregion(int, int, int);
4512 static void removerecordregions(int);
4513 static void ifsbreakup(char *, struct arglist *);
4514 static void ifsfree(void);
4515 static void expandmeta(struct strlist *, int);
4516 static int patmatch(char *, const char *);
4518 static int cvtnum(arith_t);
4519 static size_t esclen(const char *, const char *);
4520 static char *scanleft(char *, char *, char *, char *, int, int);
4521 static char *scanright(char *, char *, char *, char *, int, int);
4522 static void varunset(const char *, const char *, const char *, int)
4526 #define pmatch(a, b) !fnmatch((a), (b), 0)
4528 * Prepare a pattern for a expmeta (internal glob(3)) call.
4530 * Returns an stalloced string.
4533 static inline char *
4534 preglob(const char *pattern, int quoted, int flag) {
4535 flag |= RMESCAPE_GLOB;
4537 flag |= RMESCAPE_QUOTED;
4539 return _rmescapes((char *)pattern, flag);
4544 esclen(const char *start, const char *p) {
4547 while (p > start && *--p == CTLESC) {
4555 * Expand shell variables and backquotes inside a here document.
4559 expandhere(union node *arg, int fd)
4562 expandarg(arg, (struct arglist *)NULL, 0);
4563 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4568 * Perform variable substitution and command substitution on an argument,
4569 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4570 * perform splitting and file name expansion. When arglist is NULL, perform
4571 * here document expansion.
4575 expandarg(union node *arg, struct arglist *arglist, int flag)
4580 argbackq = arg->narg.backquote;
4581 STARTSTACKSTR(expdest);
4582 ifsfirst.next = NULL;
4584 argstr(arg->narg.text, flag);
4585 p = _STPUTC('\0', expdest);
4587 if (arglist == NULL) {
4588 return; /* here document expanded */
4590 p = grabstackstr(p);
4591 exparg.lastp = &exparg.list;
4595 if (flag & EXP_FULL) {
4596 ifsbreakup(p, &exparg);
4597 *exparg.lastp = NULL;
4598 exparg.lastp = &exparg.list;
4599 expandmeta(exparg.list, flag);
4601 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4603 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4606 exparg.lastp = &sp->next;
4610 *exparg.lastp = NULL;
4612 *arglist->lastp = exparg.list;
4613 arglist->lastp = exparg.lastp;
4619 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4620 * characters to allow for further processing. Otherwise treat
4621 * $@ like $* since no splitting will be performed.
4625 argstr(char *p, int flag)
4627 static const char spclchars[] = {
4635 CTLBACKQ | CTLQUOTE,
4636 #ifdef CONFIG_ASH_MATH_SUPPORT
4641 const char *reject = spclchars;
4643 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4644 int breakall = flag & EXP_WORD;
4649 if (!(flag & EXP_VARTILDE)) {
4651 } else if (flag & EXP_VARTILDE2) {
4656 if (flag & EXP_TILDE) {
4662 if (*q == CTLESC && (flag & EXP_QWORD))
4665 p = exptilde(p, q, flag);
4668 startloc = expdest - (char *)stackblock();
4670 length += strcspn(p + length, reject);
4672 if (c && (!(c & 0x80)
4673 #ifdef CONFIG_ASH_MATH_SUPPORT
4677 /* c == '=' || c == ':' || c == CTLENDARI */
4682 expdest = stnputs(p, length, expdest);
4683 newloc = expdest - (char *)stackblock();
4684 if (breakall && !inquotes && newloc > startloc) {
4685 recordregion(startloc, newloc, 0);
4696 if (flag & EXP_VARTILDE2) {
4700 flag |= EXP_VARTILDE2;
4705 * sort of a hack - expand tildes in variable
4706 * assignments (after the first '=' and after ':'s).
4715 case CTLENDVAR: /* ??? */
4718 /* "$@" syntax adherence hack */
4721 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4722 (p[4] == CTLQUOTEMARK || (
4723 p[4] == CTLENDVAR &&
4724 p[5] == CTLQUOTEMARK
4727 p = evalvar(p + 1, flag) + 1;
4730 inquotes = !inquotes;
4743 p = evalvar(p, flag);
4747 case CTLBACKQ|CTLQUOTE:
4748 expbackq(argbackq->n, c, quotes);
4749 argbackq = argbackq->next;
4751 #ifdef CONFIG_ASH_MATH_SUPPORT
4764 exptilde(char *startp, char *p, int flag)
4770 int quotes = flag & (EXP_FULL | EXP_CASE);
4775 while ((c = *++p) != '\0') {
4782 if (flag & EXP_VARTILDE)
4792 if (*name == '\0') {
4793 home = lookupvar(homestr);
4795 if ((pw = getpwnam(name)) == NULL)
4799 if (!home || !*home)
4802 startloc = expdest - (char *)stackblock();
4803 strtodest(home, SQSYNTAX, quotes);
4804 recordregion(startloc, expdest - (char *)stackblock(), 0);
4813 removerecordregions(int endoff)
4815 if (ifslastp == NULL)
4818 if (ifsfirst.endoff > endoff) {
4819 while (ifsfirst.next != NULL) {
4820 struct ifsregion *ifsp;
4822 ifsp = ifsfirst.next->next;
4823 ckfree(ifsfirst.next);
4824 ifsfirst.next = ifsp;
4827 if (ifsfirst.begoff > endoff)
4830 ifslastp = &ifsfirst;
4831 ifsfirst.endoff = endoff;
4836 ifslastp = &ifsfirst;
4837 while (ifslastp->next && ifslastp->next->begoff < endoff)
4838 ifslastp=ifslastp->next;
4839 while (ifslastp->next != NULL) {
4840 struct ifsregion *ifsp;
4842 ifsp = ifslastp->next->next;
4843 ckfree(ifslastp->next);
4844 ifslastp->next = ifsp;
4847 if (ifslastp->endoff > endoff)
4848 ifslastp->endoff = endoff;
4852 #ifdef CONFIG_ASH_MATH_SUPPORT
4854 * Expand arithmetic expression. Backup to start of expression,
4855 * evaluate, place result in (backed up) result, adjust string position.
4868 * This routine is slightly over-complicated for
4869 * efficiency. Next we scan backwards looking for the
4870 * start of arithmetic.
4872 start = stackblock();
4879 while (*p != CTLARI) {
4883 sh_error("missing CTLARI (shouldn't happen)");
4888 esc = esclen(start, p);
4898 removerecordregions(begoff);
4907 len = cvtnum(dash_arith(p + 2));
4910 recordregion(begoff, begoff + len, 0);
4915 * Expand stuff in backwards quotes.
4919 expbackq(union node *cmd, int quoted, int quotes)
4927 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4928 struct stackmark smark;
4931 setstackmark(&smark);
4933 startloc = dest - (char *)stackblock();
4935 evalbackcmd(cmd, (struct backcmd *) &in);
4936 popstackmark(&smark);
4943 memtodest(p, i, syntax, quotes);
4947 i = safe_read(in.fd, buf, sizeof buf);
4948 TRACE(("expbackq: read returns %d\n", i));
4958 back_exitstatus = waitforjob(in.jp);
4962 /* Eat all trailing newlines */
4964 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4969 recordregion(startloc, dest - (char *)stackblock(), 0);
4970 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4971 (dest - (char *)stackblock()) - startloc,
4972 (dest - (char *)stackblock()) - startloc,
4973 stackblock() + startloc));
4978 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4989 const char *s = loc2;
4995 match = pmatch(str, s);
4999 if (quotes && *loc == CTLESC)
5009 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5016 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5019 const char *s = loc2;
5024 match = pmatch(str, s);
5031 esc = esclen(startp, loc);
5043 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5047 int saveherefd = herefd;
5048 struct nodelist *saveargbackq = argbackq;
5050 char *rmesc, *rmescend;
5052 char *(*scan)(char *, char *, char *, char *, int , int);
5055 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5056 STPUTC('\0', expdest);
5057 herefd = saveherefd;
5058 argbackq = saveargbackq;
5059 startp = stackblock() + startloc;
5063 setvar(str, startp, 0);
5064 amount = startp - expdest;
5065 STADJUST(amount, expdest);
5069 varunset(p, str, startp, varflags);
5073 subtype -= VSTRIMRIGHT;
5075 if (subtype < 0 || subtype > 3)
5080 rmescend = stackblock() + strloc;
5082 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5083 if (rmesc != startp) {
5085 startp = stackblock() + startloc;
5089 str = stackblock() + strloc;
5090 preglob(str, varflags & VSQUOTE, 0);
5092 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5093 zero = subtype >> 1;
5094 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5095 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5097 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5100 memmove(startp, loc, str - loc);
5101 loc = startp + (str - loc) - 1;
5104 amount = loc - expdest;
5105 STADJUST(amount, expdest);
5112 * Expand a variable, and return a pointer to the next character in the
5116 evalvar(char *p, int flag)
5129 quotes = flag & (EXP_FULL | EXP_CASE);
5131 subtype = varflags & VSTYPE;
5132 quoted = varflags & VSQUOTE;
5134 easy = (!quoted || (*var == '@' && shellparam.nparam));
5135 startloc = expdest - (char *)stackblock();
5136 p = strchr(p, '=') + 1;
5139 varlen = varvalue(var, varflags, flag);
5140 if (varflags & VSNUL)
5143 if (subtype == VSPLUS) {
5144 varlen = -1 - varlen;
5148 if (subtype == VSMINUS) {
5152 p, flag | EXP_TILDE |
5153 (quoted ? EXP_QWORD : EXP_WORD)
5162 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5164 if (subevalvar(p, var, 0, subtype, startloc,
5168 * Remove any recorded regions beyond
5171 removerecordregions(startloc);
5181 if (varlen < 0 && uflag)
5182 varunset(p, var, 0, 0);
5184 if (subtype == VSLENGTH) {
5185 cvtnum(varlen > 0 ? varlen : 0);
5189 if (subtype == VSNORMAL) {
5193 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5202 case VSTRIMRIGHTMAX:
5211 * Terminate the string and start recording the pattern
5214 STPUTC('\0', expdest);
5215 patloc = expdest - (char *)stackblock();
5216 if (subevalvar(p, NULL, patloc, subtype,
5217 startloc, varflags, quotes) == 0) {
5218 int amount = expdest - (
5219 (char *)stackblock() + patloc - 1
5221 STADJUST(-amount, expdest);
5223 /* Remove any recorded regions beyond start of variable */
5224 removerecordregions(startloc);
5229 if (subtype != VSNORMAL) { /* skip to end of alternative */
5232 if ((c = *p++) == CTLESC)
5234 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5236 argbackq = argbackq->next;
5237 } else if (c == CTLVAR) {
5238 if ((*p++ & VSTYPE) != VSNORMAL)
5240 } else if (c == CTLENDVAR) {
5251 * Put a string on the stack.
5255 memtodest(const char *p, size_t len, int syntax, int quotes) {
5258 q = makestrspace(len * 2, q);
5261 int c = SC2INT(*p++);
5264 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5274 strtodest(const char *p, int syntax, int quotes)
5276 memtodest(p, strlen(p), syntax, quotes);
5281 * Add the value of a specialized variable to the stack string.
5285 varvalue(char *name, int varflags, int flags)
5295 int quoted = varflags & VSQUOTE;
5296 int subtype = varflags & VSTYPE;
5297 int quotes = flags & (EXP_FULL | EXP_CASE);
5299 if (quoted && (flags & EXP_FULL))
5300 sep = 1 << CHAR_BIT;
5302 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5311 num = shellparam.nparam;
5321 p = makestrspace(NOPTS, expdest);
5322 for (i = NOPTS - 1; i >= 0; i--) {
5324 USTPUTC(optletters(i), p);
5335 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5336 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5339 if (!(ap = shellparam.p))
5341 while ((p = *ap++)) {
5344 partlen = strlen(p);
5347 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5348 memtodest(p, partlen, syntax, quotes);
5354 if (subtype == VSPLUS || subtype == VSLENGTH) {
5376 if (num < 0 || num > shellparam.nparam)
5378 p = num ? shellparam.p[num - 1] : arg0;
5381 p = lookupvar(name);
5387 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5388 memtodest(p, len, syntax, quotes);
5392 if (subtype == VSPLUS || subtype == VSLENGTH)
5393 STADJUST(-len, expdest);
5399 * Record the fact that we have to scan this region of the
5400 * string for IFS characters.
5404 recordregion(int start, int end, int nulonly)
5406 struct ifsregion *ifsp;
5408 if (ifslastp == NULL) {
5412 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5414 ifslastp->next = ifsp;
5418 ifslastp->begoff = start;
5419 ifslastp->endoff = end;
5420 ifslastp->nulonly = nulonly;
5425 * Break the argument string into pieces based upon IFS and add the
5426 * strings to the argument list. The regions of the string to be
5427 * searched for IFS characters have been stored by recordregion.
5430 ifsbreakup(char *string, struct arglist *arglist)
5432 struct ifsregion *ifsp;
5437 const char *ifs, *realifs;
5443 if (ifslastp != NULL) {
5446 realifs = ifsset() ? ifsval() : defifs;
5449 p = string + ifsp->begoff;
5450 nulonly = ifsp->nulonly;
5451 ifs = nulonly ? nullstr : realifs;
5453 while (p < string + ifsp->endoff) {
5457 if (strchr(ifs, *p)) {
5459 ifsspc = (strchr(defifs, *p) != NULL);
5460 /* Ignore IFS whitespace at start */
5461 if (q == start && ifsspc) {
5467 sp = (struct strlist *)stalloc(sizeof *sp);
5469 *arglist->lastp = sp;
5470 arglist->lastp = &sp->next;
5474 if (p >= string + ifsp->endoff) {
5480 if (strchr(ifs, *p) == NULL ) {
5483 } else if (strchr(defifs, *p) == NULL) {
5499 } while ((ifsp = ifsp->next) != NULL);
5508 sp = (struct strlist *)stalloc(sizeof *sp);
5510 *arglist->lastp = sp;
5511 arglist->lastp = &sp->next;
5517 struct ifsregion *p;
5522 struct ifsregion *ifsp;
5528 ifsfirst.next = NULL;
5532 static void expmeta(char *, char *);
5533 static struct strlist *expsort(struct strlist *);
5534 static struct strlist *msort(struct strlist *, int);
5536 static char *expdir;
5540 expandmeta(struct strlist *str, int flag)
5542 static const char metachars[] = {
5545 /* TODO - EXP_REDIR */
5548 struct strlist **savelastp;
5554 if (!strpbrk(str->text, metachars))
5556 savelastp = exparg.lastp;
5559 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5561 int i = strlen(str->text);
5562 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5570 if (exparg.lastp == savelastp) {
5575 *exparg.lastp = str;
5576 rmescapes(str->text);
5577 exparg.lastp = &str->next;
5579 *exparg.lastp = NULL;
5580 *savelastp = sp = expsort(*savelastp);
5581 while (sp->next != NULL)
5583 exparg.lastp = &sp->next;
5590 * Add a file name to the list.
5594 addfname(const char *name)
5598 sp = (struct strlist *)stalloc(sizeof *sp);
5599 sp->text = sstrdup(name);
5601 exparg.lastp = &sp->next;
5606 * Do metacharacter (i.e. *, ?, [...]) expansion.
5610 expmeta(char *enddir, char *name)
5625 for (p = name; *p; p++) {
5626 if (*p == '*' || *p == '?')
5628 else if (*p == '[') {
5635 if (*q == '/' || *q == '\0')
5642 } else if (*p == '\\')
5644 else if (*p == '/') {
5651 if (metaflag == 0) { /* we've reached the end of the file name */
5652 if (enddir != expdir)
5660 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5671 } while (p < start);
5673 if (enddir == expdir) {
5675 } else if (enddir == expdir + 1 && *expdir == '/') {
5681 if ((dirp = opendir(cp)) == NULL)
5683 if (enddir != expdir)
5685 if (*endname == 0) {
5697 while (! intpending && (dp = readdir(dirp)) != NULL) {
5698 if (dp->d_name[0] == '.' && ! matchdot)
5700 if (pmatch(start, dp->d_name)) {
5702 scopy(dp->d_name, enddir);
5705 for (p = enddir, cp = dp->d_name;
5706 (*p++ = *cp++) != '\0';)
5709 expmeta(p, endname);
5719 * Sort the results of file name expansion. It calculates the number of
5720 * strings to sort and then calls msort (short for merge sort) to do the
5724 static struct strlist *
5725 expsort(struct strlist *str)
5731 for (sp = str ; sp ; sp = sp->next)
5733 return msort(str, len);
5737 static struct strlist *
5738 msort(struct strlist *list, int len)
5740 struct strlist *p, *q = NULL;
5741 struct strlist **lpp;
5749 for (n = half ; --n >= 0 ; ) {
5753 q->next = NULL; /* terminate first half of list */
5754 q = msort(list, half); /* sort first half of list */
5755 p = msort(p, len - half); /* sort second half */
5758 #ifdef CONFIG_LOCALE_SUPPORT
5759 if (strcoll(p->text, q->text) < 0)
5761 if (strcmp(p->text, q->text) < 0)
5766 if ((p = *lpp) == NULL) {
5773 if ((q = *lpp) == NULL) {
5784 * Returns true if the pattern matches the string.
5788 patmatch(char *pattern, const char *string)
5790 return pmatch(preglob(pattern, 0, 0), string);
5795 * Remove any CTLESC characters from a string.
5799 _rmescapes(char *str, int flag)
5802 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5807 p = strpbrk(str, qchars);
5813 if (flag & RMESCAPE_ALLOC) {
5814 size_t len = p - str;
5815 size_t fulllen = len + strlen(p) + 1;
5817 if (flag & RMESCAPE_GROW) {
5818 r = makestrspace(fulllen, expdest);
5819 } else if (flag & RMESCAPE_HEAP) {
5820 r = ckmalloc(fulllen);
5822 r = stalloc(fulllen);
5826 q = mempcpy(q, str, len);
5829 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5830 globbing = flag & RMESCAPE_GLOB;
5831 notescaped = globbing;
5833 if (*p == CTLQUOTEMARK) {
5834 inquotes = ~inquotes;
5836 notescaped = globbing;
5840 /* naked back slash */
5846 if (notescaped && inquotes && *p != '/') {
5850 notescaped = globbing;
5855 if (flag & RMESCAPE_GROW) {
5857 STADJUST(q - r + 1, expdest);
5864 * See if a pattern matches in a case statement.
5868 casematch(union node *pattern, char *val)
5870 struct stackmark smark;
5873 setstackmark(&smark);
5874 argbackq = pattern->narg.backquote;
5875 STARTSTACKSTR(expdest);
5877 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5878 STACKSTRNUL(expdest);
5879 result = patmatch(stackblock(), val);
5880 popstackmark(&smark);
5893 expdest = makestrspace(32, expdest);
5894 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5895 len = fmtstr(expdest, 32, "%lld", (long long) num);
5897 len = fmtstr(expdest, 32, "%ld", num);
5899 STADJUST(len, expdest);
5904 varunset(const char *end, const char *var, const char *umsg, int varflags)
5910 msg = "parameter not set";
5912 if (*end == CTLENDVAR) {
5913 if (varflags & VSNUL)
5918 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5925 * This implements the input routines used by the parser.
5928 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5930 static void pushfile(void);
5933 * Read a character from the script, returning PEOF on end of file.
5934 * Nul characters in the input are silently discarded.
5938 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5940 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5941 #define pgetc_macro() pgetc()
5945 return pgetc_as_macro();
5948 #define pgetc_macro() pgetc_as_macro()
5952 return pgetc_macro();
5958 * Same as pgetc(), but ignores PEOA.
5960 #ifdef CONFIG_ASH_ALIAS
5961 static int pgetc2(void)
5967 } while (c == PEOA);
5971 static inline int pgetc2(void)
5973 return pgetc_macro();
5978 * Read a line from the script.
5981 static inline char *
5982 pfgets(char *line, int len)
5988 while (--nleft > 0) {
6005 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6006 #ifdef CONFIG_ASH_EXPAND_PRMT
6007 static char *cmdedit_prompt;
6009 static const char *cmdedit_prompt;
6011 static inline void putprompt(const char *s)
6013 #ifdef CONFIG_ASH_EXPAND_PRMT
6014 free(cmdedit_prompt);
6015 cmdedit_prompt = bb_xstrdup(s);
6021 static inline void putprompt(const char *s)
6031 char *buf = parsefile->buf;
6035 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6036 if (!iflag || parsefile->fd)
6037 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6039 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6040 cmdedit_path_lookup = pathval();
6042 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6044 /* Ctrl+C presend */
6053 if(nr < 0 && errno == 0) {
6054 /* Ctrl+D presend */
6059 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6063 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6064 int flags = fcntl(0, F_GETFL, 0);
6065 if (flags >= 0 && flags & O_NONBLOCK) {
6066 flags &=~ O_NONBLOCK;
6067 if (fcntl(0, F_SETFL, flags) >= 0) {
6068 out2str("sh: turning off NDELAY mode\n");
6078 * Refill the input buffer and return the next input character:
6080 * 1) If a string was pushed back on the input, pop it;
6081 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6082 * from a string so we can't refill the buffer, return EOF.
6083 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6084 * 4) Process input up to the next newline, deleting nul characters.
6094 while (parsefile->strpush) {
6095 #ifdef CONFIG_ASH_ALIAS
6096 if (parsenleft == -1 && parsefile->strpush->ap &&
6097 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6102 if (--parsenleft >= 0)
6103 return SC2INT(*parsenextc++);
6105 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6112 if ((more = preadfd()) <= 0) {
6113 parselleft = parsenleft = EOF_NLEFT;
6120 /* delete nul characters */
6128 memmove(q, q + 1, more);
6132 parsenleft = q - parsenextc - 1;
6138 parsenleft = q - parsenextc - 1;
6150 out2str(parsenextc);
6155 return SC2INT(*parsenextc++);
6159 * Undo the last call to pgetc. Only one character may be pushed back.
6160 * PEOF may be pushed back.
6171 * Push a string back onto the input at this current parsefile level.
6172 * We handle aliases this way.
6175 pushstring(char *s, void *ap)
6182 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6183 if (parsefile->strpush) {
6184 sp = ckmalloc(sizeof (struct strpush));
6185 sp->prev = parsefile->strpush;
6186 parsefile->strpush = sp;
6188 sp = parsefile->strpush = &(parsefile->basestrpush);
6189 sp->prevstring = parsenextc;
6190 sp->prevnleft = parsenleft;
6191 #ifdef CONFIG_ASH_ALIAS
6192 sp->ap = (struct alias *)ap;
6194 ((struct alias *)ap)->flag |= ALIASINUSE;
6206 struct strpush *sp = parsefile->strpush;
6209 #ifdef CONFIG_ASH_ALIAS
6211 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6212 checkkwd |= CHKALIAS;
6214 if (sp->string != sp->ap->val) {
6217 sp->ap->flag &= ~ALIASINUSE;
6218 if (sp->ap->flag & ALIASDEAD) {
6219 unalias(sp->ap->name);
6223 parsenextc = sp->prevstring;
6224 parsenleft = sp->prevnleft;
6225 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6226 parsefile->strpush = sp->prev;
6227 if (sp != &(parsefile->basestrpush))
6233 * Set the input to take input from a file. If push is set, push the
6234 * old input onto the stack first.
6238 setinputfile(const char *fname, int flags)
6244 if ((fd = open(fname, O_RDONLY)) < 0) {
6245 if (flags & INPUT_NOFILE_OK)
6247 sh_error("Can't open %s", fname);
6250 fd2 = copyfd(fd, 10);
6253 sh_error("Out of file descriptors");
6256 setinputfd(fd, flags & INPUT_PUSH_FILE);
6264 * Like setinputfile, but takes an open file descriptor. Call this with
6269 setinputfd(int fd, int push)
6271 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6277 if (parsefile->buf == NULL)
6278 parsefile->buf = ckmalloc(IBUFSIZ);
6279 parselleft = parsenleft = 0;
6285 * Like setinputfile, but takes input from a string.
6289 setinputstring(char *string)
6293 parsenextc = string;
6294 parsenleft = strlen(string);
6295 parsefile->buf = NULL;
6302 * To handle the "." command, a stack of input files is used. Pushfile
6303 * adds a new entry to the stack and popfile restores the previous level.
6309 struct parsefile *pf;
6311 parsefile->nleft = parsenleft;
6312 parsefile->lleft = parselleft;
6313 parsefile->nextc = parsenextc;
6314 parsefile->linno = plinno;
6315 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6316 pf->prev = parsefile;
6319 pf->basestrpush.prev = NULL;
6327 struct parsefile *pf = parsefile;
6336 parsefile = pf->prev;
6338 parsenleft = parsefile->nleft;
6339 parselleft = parsefile->lleft;
6340 parsenextc = parsefile->nextc;
6341 plinno = parsefile->linno;
6347 * Return to top level.
6353 while (parsefile != &basepf)
6359 * Close the file(s) that the shell is reading commands from. Called
6360 * after a fork is done.
6367 if (parsefile->fd > 0) {
6368 close(parsefile->fd);
6375 /* mode flags for set_curjob */
6376 #define CUR_DELETE 2
6377 #define CUR_RUNNING 1
6378 #define CUR_STOPPED 0
6380 /* mode flags for dowait */
6381 #define DOWAIT_NORMAL 0
6382 #define DOWAIT_BLOCK 1
6385 static struct job *jobtab;
6387 static unsigned njobs;
6389 /* pgrp of shell on invocation */
6390 static int initialpgrp;
6391 static int ttyfd = -1;
6394 static struct job *curjob;
6395 /* number of presumed living untracked jobs */
6398 static void set_curjob(struct job *, unsigned);
6400 static int restartjob(struct job *, int);
6401 static void xtcsetpgrp(int, pid_t);
6402 static char *commandtext(union node *);
6403 static void cmdlist(union node *, int);
6404 static void cmdtxt(union node *);
6405 static void cmdputs(const char *);
6406 static void showpipe(struct job *, FILE *);
6408 static int sprint_status(char *, int, int);
6409 static void freejob(struct job *);
6410 static struct job *getjob(const char *, int);
6411 static struct job *growjobtab(void);
6412 static void forkchild(struct job *, union node *, int);
6413 static void forkparent(struct job *, union node *, int, pid_t);
6414 static int dowait(int, struct job *);
6415 static int getstatus(struct job *);
6418 set_curjob(struct job *jp, unsigned mode)
6421 struct job **jpp, **curp;
6423 /* first remove from list */
6424 jpp = curp = &curjob;
6429 jpp = &jp1->prev_job;
6431 *jpp = jp1->prev_job;
6433 /* Then re-insert in correct position */
6441 /* job being deleted */
6444 /* newly created job or backgrounded job,
6445 put after all stopped jobs. */
6449 if (!jp1 || jp1->state != JOBSTOPPED)
6452 jpp = &jp1->prev_job;
6458 /* newly stopped job - becomes curjob */
6459 jp->prev_job = *jpp;
6467 * Turn job control on and off.
6469 * Note: This code assumes that the third arg to ioctl is a character
6470 * pointer, which is true on Berkeley systems but not System V. Since
6471 * System V doesn't have job control yet, this isn't a problem now.
6473 * Called with interrupts off.
6482 if (on == jobctl || rootshell == 0)
6486 ofd = fd = open(_PATH_TTY, O_RDWR);
6489 while (!isatty(fd) && --fd >= 0)
6492 fd = fcntl(fd, F_DUPFD, 10);
6496 fcntl(fd, F_SETFD, FD_CLOEXEC);
6497 do { /* while we are in the background */
6498 if ((pgrp = tcgetpgrp(fd)) < 0) {
6500 sh_warnx("can't access tty; job control turned off");
6504 if (pgrp == getpgrp())
6515 xtcsetpgrp(fd, pgrp);
6517 /* turning job control off */
6520 xtcsetpgrp(fd, pgrp);
6534 killcmd(int argc, char **argv)
6545 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6546 "kill -l [exitstatus]"
6550 if (**++argv == '-') {
6551 signo = decode_signal(*argv + 1, 1);
6555 while ((c = nextopt("ls:")) != '\0')
6565 signo = decode_signal(optionarg, 1);
6568 "invalid signal number or name: %s",
6579 if (!list && signo < 0)
6582 if ((signo < 0 || !*argv) ^ list) {
6590 for (i = 1; i < NSIG; i++) {
6591 name = u_signal_names(0, &i, 1);
6593 out1fmt(snlfmt, name);
6597 name = u_signal_names(*argptr, &signo, -1);
6599 out1fmt(snlfmt, name);
6601 sh_error("invalid signal number or exit status: %s", *argptr);
6607 if (**argv == '%') {
6608 jp = getjob(*argv, 0);
6609 pid = -jp->ps[0].pid;
6611 pid = **argv == '-' ?
6612 -number(*argv + 1) : number(*argv);
6614 if (kill(pid, signo) != 0) {
6615 sh_warnx("(%d) - %m", pid);
6624 #if defined(JOBS) || defined(DEBUG)
6626 jobno(const struct job *jp)
6628 return jp - jobtab + 1;
6634 fgcmd(int argc, char **argv)
6641 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6646 jp = getjob(*argv, 1);
6647 if (mode == FORK_BG) {
6648 set_curjob(jp, CUR_RUNNING);
6649 fprintf(out, "[%d] ", jobno(jp));
6651 outstr(jp->ps->cmd, out);
6653 retval = restartjob(jp, mode);
6654 } while (*argv && *++argv);
6658 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6662 restartjob(struct job *jp, int mode)
6664 struct procstat *ps;
6670 if (jp->state == JOBDONE)
6672 jp->state = JOBRUNNING;
6674 if (mode == FORK_FG)
6675 xtcsetpgrp(ttyfd, pgid);
6676 killpg(pgid, SIGCONT);
6680 if (WIFSTOPPED(ps->status)) {
6683 } while (ps++, --i);
6685 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6692 sprint_status(char *s, int status, int sigonly)
6698 if (!WIFEXITED(status)) {
6700 if (WIFSTOPPED(status))
6701 st = WSTOPSIG(status);
6704 st = WTERMSIG(status);
6706 if (st == SIGINT || st == SIGPIPE)
6709 if (WIFSTOPPED(status))
6714 col = fmtstr(s, 32, strsignal(st));
6715 if (WCOREDUMP(status)) {
6716 col += fmtstr(s + col, 16, " (core dumped)");
6718 } else if (!sigonly) {
6719 st = WEXITSTATUS(status);
6721 col = fmtstr(s, 16, "Done(%d)", st);
6723 col = fmtstr(s, 16, "Done");
6732 showjob(FILE *out, struct job *jp, int mode)
6734 struct procstat *ps;
6735 struct procstat *psend;
6742 if (mode & SHOW_PGID) {
6743 /* just output process (group) id of pipeline */
6744 fprintf(out, "%d\n", ps->pid);
6748 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6753 else if (curjob && jp == curjob->prev_job)
6756 if (mode & SHOW_PID)
6757 col += fmtstr(s + col, 16, "%d ", ps->pid);
6759 psend = ps + jp->nprocs;
6761 if (jp->state == JOBRUNNING) {
6762 scopy("Running", s + col);
6763 col += strlen("Running");
6765 int status = psend[-1].status;
6767 if (jp->state == JOBSTOPPED)
6768 status = jp->stopstatus;
6770 col += sprint_status(s + col, status, 0);
6776 /* for each process */
6777 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6780 fprintf(out, "%s%*c%s",
6781 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6783 if (!(mode & SHOW_PID)) {
6787 if (++ps == psend) {
6788 outcslow('\n', out);
6795 if (jp->state == JOBDONE) {
6796 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6803 jobscmd(int argc, char **argv)
6809 while ((m = nextopt("lp")))
6819 showjob(out, getjob(*argv,0), mode);
6822 showjobs(out, mode);
6829 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6830 * statuses have changed since the last call to showjobs.
6834 showjobs(FILE *out, int mode)
6838 TRACE(("showjobs(%x) called\n", mode));
6840 /* If not even one one job changed, there is nothing to do */
6841 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6844 for (jp = curjob; jp; jp = jp->prev_job) {
6845 if (!(mode & SHOW_CHANGED) || jp->changed)
6846 showjob(out, jp, mode);
6852 * Mark a job structure as unused.
6856 freejob(struct job *jp)
6858 struct procstat *ps;
6862 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6863 if (ps->cmd != nullstr)
6866 if (jp->ps != &jp->ps0)
6869 set_curjob(jp, CUR_DELETE);
6875 waitcmd(int argc, char **argv)
6888 /* wait for all jobs */
6893 /* no running procs */
6896 if (jp->state == JOBRUNNING)
6901 dowait(DOWAIT_BLOCK, 0);
6907 if (**argv != '%') {
6908 pid_t pid = number(*argv);
6912 if (job->ps[job->nprocs - 1].pid == pid)
6914 job = job->prev_job;
6920 job = getjob(*argv, 0);
6921 /* loop until process terminated or stopped */
6922 while (job->state == JOBRUNNING)
6923 dowait(DOWAIT_BLOCK, 0);
6925 retval = getstatus(job);
6936 * Convert a job name to a job structure.
6940 getjob(const char *name, int getctl)
6944 const char *err_msg = "No such job: %s";
6948 char *(*match)(const char *, const char *);
6963 if (c == '+' || c == '%') {
6965 err_msg = "No current job";
6967 } else if (c == '-') {
6970 err_msg = "No previous job";
6981 jp = jobtab + num - 1;
6998 if (match(jp->ps[0].cmd, p)) {
7002 err_msg = "%s: ambiguous";
7009 err_msg = "job %s not created under job control";
7010 if (getctl && jp->jobctl == 0)
7015 sh_error(err_msg, name);
7020 * Return a new job structure.
7021 * Called with interrupts off.
7025 makejob(union node *node, int nprocs)
7030 for (i = njobs, jp = jobtab ; ; jp++) {
7037 if (jp->state != JOBDONE || !jp->waited)
7046 memset(jp, 0, sizeof(*jp));
7051 jp->prev_job = curjob;
7056 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7058 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7068 struct job *jp, *jq;
7070 len = njobs * sizeof(*jp);
7072 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7074 offset = (char *)jp - (char *)jq;
7076 /* Relocate pointers */
7079 jq = (struct job *)((char *)jq + l);
7083 #define joff(p) ((struct job *)((char *)(p) + l))
7084 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7085 if (xlikely(joff(jp)->ps == &jq->ps0))
7086 jmove(joff(jp)->ps);
7087 if (joff(jp)->prev_job)
7088 jmove(joff(jp)->prev_job);
7098 jp = (struct job *)((char *)jp + len);
7102 } while (--jq >= jp);
7108 * Fork off a subshell. If we are doing job control, give the subshell its
7109 * own process group. Jp is a job structure that the job is to be added to.
7110 * N is the command that will be evaluated by the child. Both jp and n may
7111 * be NULL. The mode parameter can be one of the following:
7112 * FORK_FG - Fork off a foreground process.
7113 * FORK_BG - Fork off a background process.
7114 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7115 * process group even if job control is on.
7117 * When job control is turned off, background processes have their standard
7118 * input redirected to /dev/null (except for the second and later processes
7121 * Called with interrupts off.
7125 forkchild(struct job *jp, union node *n, int mode)
7129 TRACE(("Child shell %d\n", getpid()));
7136 /* do job control only in root shell */
7138 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7141 if (jp->nprocs == 0)
7144 pgrp = jp->ps[0].pid;
7145 /* This can fail because we are doing it in the parent also */
7146 (void)setpgid(0, pgrp);
7147 if (mode == FORK_FG)
7148 xtcsetpgrp(ttyfd, pgrp);
7153 if (mode == FORK_BG) {
7156 if (jp->nprocs == 0) {
7158 if (open(bb_dev_null, O_RDONLY) != 0)
7159 sh_error("Can't open %s", bb_dev_null);
7162 if (!oldlvl && iflag) {
7167 for (jp = curjob; jp; jp = jp->prev_job)
7173 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7175 TRACE(("In parent shell: child = %d\n", pid));
7177 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7182 if (mode != FORK_NOJOB && jp->jobctl) {
7185 if (jp->nprocs == 0)
7188 pgrp = jp->ps[0].pid;
7189 /* This can fail because we are doing it in the child also */
7190 (void)setpgid(pid, pgrp);
7193 if (mode == FORK_BG) {
7194 backgndpid = pid; /* set $! */
7195 set_curjob(jp, CUR_RUNNING);
7198 struct procstat *ps = &jp->ps[jp->nprocs++];
7204 ps->cmd = commandtext(n);
7210 forkshell(struct job *jp, union node *n, int mode)
7214 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7217 TRACE(("Fork failed, errno=%d", errno));
7220 sh_error("Cannot fork");
7223 forkchild(jp, n, mode);
7225 forkparent(jp, n, mode, pid);
7230 * Wait for job to finish.
7232 * Under job control we have the problem that while a child process is
7233 * running interrupts generated by the user are sent to the child but not
7234 * to the shell. This means that an infinite loop started by an inter-
7235 * active user may be hard to kill. With job control turned off, an
7236 * interactive user may place an interactive program inside a loop. If
7237 * the interactive program catches interrupts, the user doesn't want
7238 * these interrupts to also abort the loop. The approach we take here
7239 * is to have the shell ignore interrupt signals while waiting for a
7240 * foreground process to terminate, and then send itself an interrupt
7241 * signal if the child process was terminated by an interrupt signal.
7242 * Unfortunately, some programs want to do a bit of cleanup and then
7243 * exit on interrupt; unless these processes terminate themselves by
7244 * sending a signal to themselves (instead of calling exit) they will
7245 * confuse this approach.
7247 * Called with interrupts off.
7251 waitforjob(struct job *jp)
7255 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7256 while (jp->state == JOBRUNNING) {
7257 dowait(DOWAIT_BLOCK, jp);
7262 xtcsetpgrp(ttyfd, rootpid);
7264 * This is truly gross.
7265 * If we're doing job control, then we did a TIOCSPGRP which
7266 * caused us (the shell) to no longer be in the controlling
7267 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7268 * intuit from the subprocess exit status whether a SIGINT
7269 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7274 if (jp->state == JOBDONE)
7282 * Do a wait system call. If job control is compiled in, we accept
7283 * stopped processes. If block is zero, we return a value of zero
7284 * rather than blocking.
7286 * System V doesn't have a non-blocking wait system call. It does
7287 * have a SIGCLD signal that is sent to a process when one of it's
7288 * children dies. The obvious way to use SIGCLD would be to install
7289 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7290 * was received, and have waitproc bump another counter when it got
7291 * the status of a process. Waitproc would then know that a wait
7292 * system call would not block if the two counters were different.
7293 * This approach doesn't work because if a process has children that
7294 * have not been waited for, System V will send it a SIGCLD when it
7295 * installs a signal handler for SIGCLD. What this means is that when
7296 * a child exits, the shell will be sent SIGCLD signals continuously
7297 * until is runs out of stack space, unless it does a wait call before
7298 * restoring the signal handler. The code below takes advantage of
7299 * this (mis)feature by installing a signal handler for SIGCLD and
7300 * then checking to see whether it was called. If there are any
7301 * children to be waited for, it will be.
7303 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7304 * waits at all. In this case, the user will not be informed when
7305 * a background process until the next time she runs a real program
7306 * (as opposed to running a builtin command or just typing return),
7307 * and the jobs command may give out of date information.
7311 waitproc(int block, int *status)
7321 return wait3(status, flags, (struct rusage *)NULL);
7325 * Wait for a process to terminate.
7329 dowait(int block, struct job *job)
7334 struct job *thisjob;
7337 TRACE(("dowait(%d) called\n", block));
7338 pid = waitproc(block, &status);
7339 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7344 for (jp = curjob; jp; jp = jp->prev_job) {
7345 struct procstat *sp;
7346 struct procstat *spend;
7347 if (jp->state == JOBDONE)
7350 spend = jp->ps + jp->nprocs;
7353 if (sp->pid == pid) {
7354 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7355 sp->status = status;
7358 if (sp->status == -1)
7361 if (state == JOBRUNNING)
7363 if (WIFSTOPPED(sp->status)) {
7364 jp->stopstatus = sp->status;
7368 } while (++sp < spend);
7373 if (!WIFSTOPPED(status))
7380 if (state != JOBRUNNING) {
7381 thisjob->changed = 1;
7383 if (thisjob->state != state) {
7384 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7385 thisjob->state = state;
7387 if (state == JOBSTOPPED) {
7388 set_curjob(thisjob, CUR_STOPPED);
7397 if (thisjob && thisjob == job) {
7401 len = sprint_status(s, status, 1);
7413 * return 1 if there are stopped jobs, otherwise 0
7426 if (jp && jp->state == JOBSTOPPED) {
7427 out2str("You have stopped jobs.\n");
7437 * Return a string identifying a command (to be printed by the
7442 static char *cmdnextc;
7445 commandtext(union node *n)
7449 STARTSTACKSTR(cmdnextc);
7451 name = stackblock();
7452 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7453 name, cmdnextc, cmdnextc));
7454 return savestr(name);
7458 cmdtxt(union node *n)
7461 struct nodelist *lp;
7473 lp = n->npipe.cmdlist;
7491 cmdtxt(n->nbinary.ch1);
7507 cmdtxt(n->nif.test);
7510 if (n->nif.elsepart) {
7513 n = n->nif.elsepart;
7529 cmdtxt(n->nbinary.ch1);
7539 cmdputs(n->nfor.var);
7541 cmdlist(n->nfor.args, 1);
7546 cmdputs(n->narg.text);
7550 cmdlist(n->ncmd.args, 1);
7551 cmdlist(n->ncmd.redirect, 0);
7564 cmdputs(n->ncase.expr->narg.text);
7566 for (np = n->ncase.cases; np; np = np->nclist.next) {
7567 cmdtxt(np->nclist.pattern);
7569 cmdtxt(np->nclist.body);
7595 s[0] = n->nfile.fd + '0';
7599 if (n->type == NTOFD || n->type == NFROMFD) {
7600 s[0] = n->ndup.dupfd + '0';
7611 cmdlist(union node *np, int sep)
7613 for (; np; np = np->narg.next) {
7617 if (sep && np->narg.next)
7623 cmdputs(const char *s)
7625 const char *p, *str;
7626 char c, cc[2] = " ";
7630 static const char vstype[VSTYPE + 1][4] = {
7631 "", "}", "-", "+", "?", "=",
7632 "%", "%%", "#", "##"
7634 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7636 while ((c = *p++) != 0) {
7644 if ((subtype & VSTYPE) == VSLENGTH)
7648 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7655 str = "\"}" + !(quoted & 1);
7662 case CTLBACKQ+CTLQUOTE:
7665 #ifdef CONFIG_ASH_MATH_SUPPORT
7680 if ((subtype & VSTYPE) != VSNORMAL)
7682 str = vstype[subtype & VSTYPE];
7683 if (subtype & VSNUL)
7692 /* These can only happen inside quotes */
7705 while ((c = *str++)) {
7710 USTPUTC('"', nextc);
7718 showpipe(struct job *jp, FILE *out)
7720 struct procstat *sp;
7721 struct procstat *spend;
7723 spend = jp->ps + jp->nprocs;
7724 for (sp = jp->ps + 1; sp < spend; sp++)
7725 fprintf(out, " | %s", sp->cmd);
7726 outcslow('\n', out);
7731 xtcsetpgrp(int fd, pid_t pgrp)
7733 if (tcsetpgrp(fd, pgrp))
7734 sh_error("Cannot set tty process group (%m)");
7739 getstatus(struct job *job) {
7743 status = job->ps[job->nprocs - 1].status;
7744 retval = WEXITSTATUS(status);
7745 if (!WIFEXITED(status)) {
7747 retval = WSTOPSIG(status);
7748 if (!WIFSTOPPED(status))
7751 /* XXX: limits number of signals */
7752 retval = WTERMSIG(status);
7754 if (retval == SIGINT)
7760 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7761 jobno(job), job->nprocs, status, retval));
7765 #ifdef CONFIG_ASH_MAIL
7769 * Routines to check for mail. (Perhaps make part of main.c?)
7772 #define MAXMBOXES 10
7774 /* times of mailboxes */
7775 static time_t mailtime[MAXMBOXES];
7776 /* Set if MAIL or MAILPATH is changed. */
7777 static int mail_var_path_changed;
7782 * Print appropriate message(s) if mail has arrived.
7783 * If mail_var_path_changed is set,
7784 * then the value of MAIL has mail_var_path_changed,
7785 * so we just update the values.
7795 struct stackmark smark;
7798 setstackmark(&smark);
7799 mpath = mpathset() ? mpathval() : mailval();
7800 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7801 p = padvance(&mpath, nullstr);
7806 for (q = p ; *q ; q++);
7811 q[-1] = '\0'; /* delete trailing '/' */
7812 if (stat(p, &statb) < 0) {
7816 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7819 pathopt ? pathopt : "you have mail"
7822 *mtp = statb.st_mtime;
7824 mail_var_path_changed = 0;
7825 popstackmark(&smark);
7830 changemail(const char *val)
7832 mail_var_path_changed++;
7835 #endif /* CONFIG_ASH_MAIL */
7841 static short profile_buf[16384];
7845 static int isloginsh;
7847 static void read_profile(const char *);
7850 * Main routine. We initialize things, parse the arguments, execute
7851 * profiles if we're a login shell, and then call cmdloop to execute
7852 * commands. The setjmp call sets up the location to jump to when an
7853 * exception occurs. When an exception occurs the variable "state"
7854 * is used to figure out how far we had gotten.
7858 ash_main(int argc, char **argv)
7862 struct jmploc jmploc;
7863 struct stackmark smark;
7866 dash_errno = __errno_location();
7870 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7873 if (setjmp(jmploc.loc)) {
7883 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7887 outcslow('\n', stderr);
7889 popstackmark(&smark);
7890 FORCEINTON; /* enable interrupts */
7903 trputs("Shell args: "); trargs(argv);
7907 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7908 rseed = rootpid + ((time_t)time((time_t *)0));
7911 setstackmark(&smark);
7912 procargs(argc, argv);
7913 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7915 const char *hp = lookupvar("HISTFILE");
7918 hp = lookupvar("HOME");
7920 char *defhp = concat_path_file(hp, ".ash_history");
7921 setvar("HISTFILE", defhp, 0);
7927 if (argv[0] && argv[0][0] == '-')
7931 read_profile("/etc/profile");
7934 read_profile(".profile");
7940 getuid() == geteuid() && getgid() == getegid() &&
7944 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7945 read_profile(shinit);
7951 evalstring(minusc, 0);
7953 if (sflag || minusc == NULL) {
7954 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7956 const char *hp = lookupvar("HISTFILE");
7959 load_history ( hp );
7962 state4: /* XXX ??? - why isn't this before the "if" statement */
7970 extern void _mcleanup(void);
7980 * Read and execute commands. "Top" is nonzero for the top level command
7981 * loop; it turns on prompting if the shell is interactive.
7988 struct stackmark smark;
7992 TRACE(("cmdloop(%d) called\n", top));
7996 setstackmark(&smark);
7999 showjobs(stderr, SHOW_CHANGED);
8004 #ifdef CONFIG_ASH_MAIL
8008 n = parsecmd(inter);
8009 /* showtree(n); DEBUG */
8011 if (!top || numeof >= 50)
8013 if (!stoppedjobs()) {
8016 out2str("\nUse \"exit\" to leave shell.\n");
8019 } else if (nflag == 0) {
8020 job_warning = (job_warning == 2) ? 1 : 0;
8024 popstackmark(&smark);
8029 return skip & SKIPEVAL;
8038 * Read /etc/profile or .profile. Return on error.
8042 read_profile(const char *name)
8046 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8058 * Read a file containing shell functions.
8062 readcmdfile(char *name)
8064 setinputfile(name, INPUT_PUSH_FILE);
8071 * Take commands from a file. To be compatible we should do a path
8072 * search for the file, which is necessary to find sub-commands.
8075 static inline char *
8076 find_dot_file(char *name)
8079 const char *path = pathval();
8082 /* don't try this for absolute or relative paths */
8083 if (strchr(name, '/'))
8086 while ((fullname = padvance(&path, name)) != NULL) {
8087 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8089 * Don't bother freeing here, since it will
8090 * be freed by the caller.
8094 stunalloc(fullname);
8097 /* not found in the PATH */
8098 sh_error(not_found_msg, name);
8102 static int dotcmd(int argc, char **argv)
8105 volatile struct shparam saveparam;
8108 for (sp = cmdenviron; sp; sp = sp->next)
8109 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8111 if (argc >= 2) { /* That's what SVR2 does */
8114 fullname = find_dot_file(argv[1]);
8117 saveparam = shellparam;
8118 shellparam.malloc = 0;
8119 shellparam.nparam = argc - 2;
8120 shellparam.p = argv + 2;
8123 setinputfile(fullname, INPUT_PUSH_FILE);
8124 commandname = fullname;
8129 freeparam(&shellparam);
8130 shellparam = saveparam;
8132 status = exitstatus;
8139 exitcmd(int argc, char **argv)
8144 exitstatus = number(argv[1]);
8149 #ifdef CONFIG_ASH_BUILTIN_ECHO
8151 echocmd(int argc, char **argv)
8153 return bb_echo(argc, argv);
8157 #ifdef CONFIG_ASH_BUILTIN_TEST
8159 testcmd(int argc, char **argv)
8161 return bb_test(argc, argv);
8168 * Same for malloc, realloc, but returns an error when out of space.
8172 ckrealloc(pointer p, size_t nbytes)
8174 p = realloc(p, nbytes);
8176 sh_error(bb_msg_memory_exhausted);
8181 ckmalloc(size_t nbytes)
8183 return ckrealloc(NULL, nbytes);
8187 * Make a copy of a string in safe storage.
8191 savestr(const char *s)
8193 char *p = strdup(s);
8195 sh_error(bb_msg_memory_exhausted);
8201 * Parse trees for commands are allocated in lifo order, so we use a stack
8202 * to make this more efficient, and also to avoid all sorts of exception
8203 * handling code to handle interrupts in the middle of a parse.
8205 * The size 504 was chosen because the Ultrix malloc handles that size
8211 stalloc(size_t nbytes)
8216 aligned = SHELL_ALIGN(nbytes);
8217 if (aligned > stacknleft) {
8220 struct stack_block *sp;
8222 blocksize = aligned;
8223 if (blocksize < MINSIZE)
8224 blocksize = MINSIZE;
8225 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8226 if (len < blocksize)
8227 sh_error(bb_msg_memory_exhausted);
8231 stacknxt = sp->space;
8232 stacknleft = blocksize;
8233 sstrend = stacknxt + blocksize;
8238 stacknxt += aligned;
8239 stacknleft -= aligned;
8245 stunalloc(pointer p)
8248 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8249 write(2, "stunalloc\n", 10);
8253 stacknleft += stacknxt - (char *)p;
8259 setstackmark(struct stackmark *mark)
8261 mark->stackp = stackp;
8262 mark->stacknxt = stacknxt;
8263 mark->stacknleft = stacknleft;
8264 mark->marknext = markp;
8270 popstackmark(struct stackmark *mark)
8272 struct stack_block *sp;
8275 markp = mark->marknext;
8276 while (stackp != mark->stackp) {
8281 stacknxt = mark->stacknxt;
8282 stacknleft = mark->stacknleft;
8283 sstrend = mark->stacknxt + mark->stacknleft;
8289 * When the parser reads in a string, it wants to stick the string on the
8290 * stack and only adjust the stack pointer when it knows how big the
8291 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8292 * of space on top of the stack and stackblocklen returns the length of
8293 * this block. Growstackblock will grow this space by at least one byte,
8294 * possibly moving it (like realloc). Grabstackblock actually allocates the
8295 * part of the block that has been used.
8299 growstackblock(void)
8303 newlen = stacknleft * 2;
8304 if (newlen < stacknleft)
8305 sh_error(bb_msg_memory_exhausted);
8309 if (stacknxt == stackp->space && stackp != &stackbase) {
8310 struct stack_block *oldstackp;
8311 struct stackmark *xmark;
8312 struct stack_block *sp;
8313 struct stack_block *prevstackp;
8319 prevstackp = sp->prev;
8320 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8321 sp = ckrealloc((pointer)sp, grosslen);
8322 sp->prev = prevstackp;
8324 stacknxt = sp->space;
8325 stacknleft = newlen;
8326 sstrend = sp->space + newlen;
8329 * Stack marks pointing to the start of the old block
8330 * must be relocated to point to the new block
8333 while (xmark != NULL && xmark->stackp == oldstackp) {
8334 xmark->stackp = stackp;
8335 xmark->stacknxt = stacknxt;
8336 xmark->stacknleft = stacknleft;
8337 xmark = xmark->marknext;
8341 char *oldspace = stacknxt;
8342 int oldlen = stacknleft;
8343 char *p = stalloc(newlen);
8345 /* free the space we just allocated */
8346 stacknxt = memcpy(p, oldspace, oldlen);
8347 stacknleft += newlen;
8352 grabstackblock(size_t len)
8354 len = SHELL_ALIGN(len);
8360 * The following routines are somewhat easier to use than the above.
8361 * The user declares a variable of type STACKSTR, which may be declared
8362 * to be a register. The macro STARTSTACKSTR initializes things. Then
8363 * the user uses the macro STPUTC to add characters to the string. In
8364 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8365 * grown as necessary. When the user is done, she can just leave the
8366 * string there and refer to it using stackblock(). Or she can allocate
8367 * the space for it using grabstackstr(). If it is necessary to allow
8368 * someone else to use the stack temporarily and then continue to grow
8369 * the string, the user should use grabstack to allocate the space, and
8370 * then call ungrabstr(p) to return to the previous mode of operation.
8372 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8373 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8374 * is space for at least one character.
8380 size_t len = stackblocksize();
8381 if (herefd >= 0 && len >= 1024) {
8382 bb_full_write(herefd, stackblock(), len);
8383 return stackblock();
8386 return stackblock() + len;
8390 * Called from CHECKSTRSPACE.
8394 makestrspace(size_t newlen, char *p)
8396 size_t len = p - stacknxt;
8397 size_t size = stackblocksize();
8402 size = stackblocksize();
8404 if (nleft >= newlen)
8408 return stackblock() + len;
8412 stnputs(const char *s, size_t n, char *p)
8414 p = makestrspace(n, p);
8415 p = mempcpy(p, s, n);
8420 stputs(const char *s, char *p)
8422 return stnputs(s, strlen(s), p);
8430 * number(s) Convert a string of digits to an integer.
8431 * is_number(s) Return true if s is a string of digits.
8435 * prefix -- see if pfx is a prefix of string.
8439 prefix(const char *string, const char *pfx)
8442 if (*pfx++ != *string++)
8445 return (char *) string;
8450 * Convert a string of digits to an integer, printing an error message on
8455 number(const char *s)
8459 sh_error(illnum, s);
8465 * Check for a valid number. This should be elsewhere.
8469 is_number(const char *p)
8474 } while (*++p != '\0');
8480 * Produce a possibly single quoted string suitable as input to the shell.
8481 * The return string is allocated on the stack.
8485 single_quote(const char *s) {
8494 len = strchrnul(s, '\'') - s;
8496 q = p = makestrspace(len + 3, p);
8499 q = mempcpy(q, s, len);
8505 len = strspn(s, "'");
8509 q = p = makestrspace(len + 3, p);
8512 q = mempcpy(q, s, len);
8521 return stackblock();
8525 * Like strdup but works with the ash stack.
8529 sstrdup(const char *p)
8531 size_t len = strlen(p) + 1;
8532 return memcpy(stalloc(len), p, len);
8537 calcsize(union node *n)
8541 funcblocksize += nodesize[n->type];
8544 calcsize(n->ncmd.redirect);
8545 calcsize(n->ncmd.args);
8546 calcsize(n->ncmd.assign);
8549 sizenodelist(n->npipe.cmdlist);
8554 calcsize(n->nredir.redirect);
8555 calcsize(n->nredir.n);
8562 calcsize(n->nbinary.ch2);
8563 calcsize(n->nbinary.ch1);
8566 calcsize(n->nif.elsepart);
8567 calcsize(n->nif.ifpart);
8568 calcsize(n->nif.test);
8571 funcstringsize += strlen(n->nfor.var) + 1;
8572 calcsize(n->nfor.body);
8573 calcsize(n->nfor.args);
8576 calcsize(n->ncase.cases);
8577 calcsize(n->ncase.expr);
8580 calcsize(n->nclist.body);
8581 calcsize(n->nclist.pattern);
8582 calcsize(n->nclist.next);
8586 sizenodelist(n->narg.backquote);
8587 funcstringsize += strlen(n->narg.text) + 1;
8588 calcsize(n->narg.next);
8595 calcsize(n->nfile.fname);
8596 calcsize(n->nfile.next);
8600 calcsize(n->ndup.vname);
8601 calcsize(n->ndup.next);
8605 calcsize(n->nhere.doc);
8606 calcsize(n->nhere.next);
8609 calcsize(n->nnot.com);
8616 sizenodelist(struct nodelist *lp)
8619 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8627 copynode(union node *n)
8634 funcblock = (char *) funcblock + nodesize[n->type];
8637 new->ncmd.redirect = copynode(n->ncmd.redirect);
8638 new->ncmd.args = copynode(n->ncmd.args);
8639 new->ncmd.assign = copynode(n->ncmd.assign);
8642 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8643 new->npipe.backgnd = n->npipe.backgnd;
8648 new->nredir.redirect = copynode(n->nredir.redirect);
8649 new->nredir.n = copynode(n->nredir.n);
8656 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8657 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8660 new->nif.elsepart = copynode(n->nif.elsepart);
8661 new->nif.ifpart = copynode(n->nif.ifpart);
8662 new->nif.test = copynode(n->nif.test);
8665 new->nfor.var = nodesavestr(n->nfor.var);
8666 new->nfor.body = copynode(n->nfor.body);
8667 new->nfor.args = copynode(n->nfor.args);
8670 new->ncase.cases = copynode(n->ncase.cases);
8671 new->ncase.expr = copynode(n->ncase.expr);
8674 new->nclist.body = copynode(n->nclist.body);
8675 new->nclist.pattern = copynode(n->nclist.pattern);
8676 new->nclist.next = copynode(n->nclist.next);
8680 new->narg.backquote = copynodelist(n->narg.backquote);
8681 new->narg.text = nodesavestr(n->narg.text);
8682 new->narg.next = copynode(n->narg.next);
8689 new->nfile.fname = copynode(n->nfile.fname);
8690 new->nfile.fd = n->nfile.fd;
8691 new->nfile.next = copynode(n->nfile.next);
8695 new->ndup.vname = copynode(n->ndup.vname);
8696 new->ndup.dupfd = n->ndup.dupfd;
8697 new->ndup.fd = n->ndup.fd;
8698 new->ndup.next = copynode(n->ndup.next);
8702 new->nhere.doc = copynode(n->nhere.doc);
8703 new->nhere.fd = n->nhere.fd;
8704 new->nhere.next = copynode(n->nhere.next);
8707 new->nnot.com = copynode(n->nnot.com);
8710 new->type = n->type;
8715 static struct nodelist *
8716 copynodelist(struct nodelist *lp)
8718 struct nodelist *start;
8719 struct nodelist **lpp;
8724 funcblock = (char *) funcblock +
8725 SHELL_ALIGN(sizeof(struct nodelist));
8726 (*lpp)->n = copynode(lp->n);
8728 lpp = &(*lpp)->next;
8736 nodesavestr(char *s)
8738 char *rtn = funcstring;
8740 funcstring = stpcpy(funcstring, s) + 1;
8746 * Free a parse tree.
8750 freefunc(struct funcnode *f)
8752 if (f && --f->count < 0)
8757 static void options(int);
8758 static void setoption(int, int);
8762 * Process the shell command line arguments.
8766 procargs(int argc, char **argv)
8769 const char *xminusc;
8776 for (i = 0; i < NOPTS; i++)
8782 if (*xargv == NULL) {
8784 sh_error(bb_msg_requires_arg, "-c");
8787 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8791 for (i = 0; i < NOPTS; i++)
8792 if (optlist[i] == 2)
8797 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8802 } else if (!sflag) {
8803 setinputfile(*xargv, 0);
8809 shellparam.p = xargv;
8810 #ifdef CONFIG_ASH_GETOPTS
8811 shellparam.optind = 1;
8812 shellparam.optoff = -1;
8814 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8816 shellparam.nparam++;
8829 setinteractive(iflag);
8835 minus_o(char *name, int val)
8840 out1str("Current option settings\n");
8841 for (i = 0; i < NOPTS; i++)
8842 out1fmt("%-16s%s\n", optnames(i),
8843 optlist[i] ? "on" : "off");
8845 for (i = 0; i < NOPTS; i++)
8846 if (equal(name, optnames(i))) {
8850 sh_error("Illegal option -o %s", name);
8855 * Process shell options. The global variable argptr contains a pointer
8856 * to the argument list; we advance it past the options.
8860 options(int cmdline)
8868 while ((p = *argptr) != NULL) {
8870 if ((c = *p++) == '-') {
8872 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8874 /* "-" means turn off -x and -v */
8877 /* "--" means reset params */
8878 else if (*argptr == NULL)
8881 break; /* "-" or "--" terminates options */
8883 } else if (c == '+') {
8889 while ((c = *p++) != '\0') {
8890 if (c == 'c' && cmdline) {
8891 minusc = p; /* command is after shell args*/
8892 } else if (c == 'o') {
8893 minus_o(*argptr, val);
8896 } else if (cmdline && (c == '-')) { // long options
8897 if (strcmp(p, "login") == 0)
8909 setoption(int flag, int val)
8913 for (i = 0; i < NOPTS; i++)
8914 if (optletters(i) == flag) {
8918 sh_error("Illegal option -%c", flag);
8925 * Set the shell parameters.
8929 setparam(char **argv)
8935 for (nparam = 0 ; argv[nparam] ; nparam++);
8936 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8938 *ap++ = savestr(*argv++);
8941 freeparam(&shellparam);
8942 shellparam.malloc = 1;
8943 shellparam.nparam = nparam;
8944 shellparam.p = newparam;
8945 #ifdef CONFIG_ASH_GETOPTS
8946 shellparam.optind = 1;
8947 shellparam.optoff = -1;
8953 * Free the list of positional parameters.
8957 freeparam(volatile struct shparam *param)
8961 if (param->malloc) {
8962 for (ap = param->p ; *ap ; ap++)
8971 * The shift builtin command.
8975 shiftcmd(int argc, char **argv)
8982 n = number(argv[1]);
8983 if (n > shellparam.nparam)
8984 sh_error("can't shift that many");
8986 shellparam.nparam -= n;
8987 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8988 if (shellparam.malloc)
8992 while ((*ap2++ = *ap1++) != NULL);
8993 #ifdef CONFIG_ASH_GETOPTS
8994 shellparam.optind = 1;
8995 shellparam.optoff = -1;
9004 * The set command builtin.
9008 setcmd(int argc, char **argv)
9011 return showvars(nullstr, 0, VUNSET);
9015 if (*argptr != NULL) {
9023 #ifdef CONFIG_ASH_GETOPTS
9025 getoptsreset(const char *value)
9027 shellparam.optind = number(value);
9028 shellparam.optoff = -1;
9032 #ifdef CONFIG_LOCALE_SUPPORT
9033 static void change_lc_all(const char *value)
9035 if (value != 0 && *value != 0)
9036 setlocale(LC_ALL, value);
9039 static void change_lc_ctype(const char *value)
9041 if (value != 0 && *value != 0)
9042 setlocale(LC_CTYPE, value);
9047 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9048 /* Roughly copied from bash.. */
9049 static void change_random(const char *value)
9052 /* "get", generate */
9055 rseed = rseed * 1103515245 + 12345;
9056 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9057 /* set without recursion */
9058 setvar(vrandom.text, buf, VNOFUNC);
9059 vrandom.flags &= ~VNOFUNC;
9062 rseed = strtoul(value, (char **)NULL, 10);
9068 #ifdef CONFIG_ASH_GETOPTS
9070 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9079 if(*param_optind < 1)
9081 optnext = optfirst + *param_optind - 1;
9083 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9086 p = optnext[-1] + *optoff;
9087 if (p == NULL || *p == '\0') {
9088 /* Current word is done, advance */
9090 if (p == NULL || *p != '-' || *++p == '\0') {
9097 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9102 for (q = optstr; *q != c; ) {
9104 if (optstr[0] == ':') {
9107 err |= setvarsafe("OPTARG", s, 0);
9109 fprintf(stderr, "Illegal option -%c\n", c);
9110 (void) unsetvar("OPTARG");
9120 if (*p == '\0' && (p = *optnext) == NULL) {
9121 if (optstr[0] == ':') {
9124 err |= setvarsafe("OPTARG", s, 0);
9127 fprintf(stderr, "No arg for -%c option\n", c);
9128 (void) unsetvar("OPTARG");
9136 err |= setvarsafe("OPTARG", p, 0);
9139 err |= setvarsafe("OPTARG", nullstr, 0);
9142 *optoff = p ? p - *(optnext - 1) : -1;
9143 *param_optind = optnext - optfirst + 1;
9144 fmtstr(s, sizeof(s), "%d", *param_optind);
9145 err |= setvarsafe("OPTIND", s, VNOFUNC);
9148 err |= setvarsafe(optvar, s, 0);
9159 * The getopts builtin. Shellparam.optnext points to the next argument
9160 * to be processed. Shellparam.optptr points to the next character to
9161 * be processed in the current argument. If shellparam.optnext is NULL,
9162 * then it's the first time getopts has been called.
9166 getoptscmd(int argc, char **argv)
9171 sh_error("Usage: getopts optstring var [arg]");
9172 else if (argc == 3) {
9173 optbase = shellparam.p;
9174 if (shellparam.optind > shellparam.nparam + 1) {
9175 shellparam.optind = 1;
9176 shellparam.optoff = -1;
9181 if (shellparam.optind > argc - 2) {
9182 shellparam.optind = 1;
9183 shellparam.optoff = -1;
9187 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9188 &shellparam.optoff);
9190 #endif /* CONFIG_ASH_GETOPTS */
9193 * XXX - should get rid of. have all builtins use getopt(3). the
9194 * library getopt must have the BSD extension static variable "optreset"
9195 * otherwise it can't be used within the shell safely.
9197 * Standard option processing (a la getopt) for builtin routines. The
9198 * only argument that is passed to nextopt is the option string; the
9199 * other arguments are unnecessary. It return the character, or '\0' on
9204 nextopt(const char *optstring)
9210 if ((p = optptr) == NULL || *p == '\0') {
9212 if (p == NULL || *p != '-' || *++p == '\0')
9215 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9219 for (q = optstring ; *q != c ; ) {
9221 sh_error("Illegal option -%c", c);
9226 if (*p == '\0' && (p = *argptr++) == NULL)
9227 sh_error("No arg for -%c option", c);
9239 outstr(const char *p, FILE *file)
9264 outcslow(int c, FILE *dest)
9274 out1fmt(const char *fmt, ...)
9281 r = vprintf(fmt, ap);
9289 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9296 ret = vsnprintf(outbuf, length, fmt, ap);
9308 * Shell command parser.
9311 #define EOFMARKLEN 79
9315 struct heredoc *next; /* next here document in list */
9316 union node *here; /* redirection node */
9317 char *eofmark; /* string indicating end of input */
9318 int striptabs; /* if set, strip leading tabs */
9323 static struct heredoc *heredoclist; /* list of here documents to read */
9326 static union node *list(int);
9327 static union node *andor(void);
9328 static union node *pipeline(void);
9329 static union node *command(void);
9330 static union node *simplecmd(void);
9331 static union node *makename(void);
9332 static void parsefname(void);
9333 static void parseheredoc(void);
9334 static char peektoken(void);
9335 static int readtoken(void);
9336 static int xxreadtoken(void);
9337 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9338 static int noexpand(char *);
9339 static void synexpect(int) ATTRIBUTE_NORETURN;
9340 static void synerror(const char *) ATTRIBUTE_NORETURN;
9341 static void setprompt(int);
9347 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9348 * valid parse tree indicating a blank line.)
9352 parsecmd(int interact)
9357 doprompt = interact;
9359 setprompt(doprompt);
9374 union node *n1, *n2, *n3;
9377 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9378 if (nlflag == 2 && peektoken())
9384 if (tok == TBACKGND) {
9385 if (n2->type == NPIPE) {
9386 n2->npipe.backgnd = 1;
9388 if (n2->type != NREDIR) {
9389 n3 = stalloc(sizeof(struct nredir));
9391 n3->nredir.redirect = NULL;
9394 n2->type = NBACKGND;
9401 n3 = (union node *)stalloc(sizeof (struct nbinary));
9403 n3->nbinary.ch1 = n1;
9404 n3->nbinary.ch2 = n2;
9420 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9428 pungetc(); /* push back EOF on input */
9444 union node *n1, *n2, *n3;
9449 if ((t = readtoken()) == TAND) {
9451 } else if (t == TOR) {
9457 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9459 n3 = (union node *)stalloc(sizeof (struct nbinary));
9461 n3->nbinary.ch1 = n1;
9462 n3->nbinary.ch2 = n2;
9472 union node *n1, *n2, *pipenode;
9473 struct nodelist *lp, *prev;
9477 TRACE(("pipeline: entered\n"));
9478 if (readtoken() == TNOT) {
9480 checkkwd = CHKKWD | CHKALIAS;
9484 if (readtoken() == TPIPE) {
9485 pipenode = (union node *)stalloc(sizeof (struct npipe));
9486 pipenode->type = NPIPE;
9487 pipenode->npipe.backgnd = 0;
9488 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9489 pipenode->npipe.cmdlist = lp;
9493 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9494 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9497 } while (readtoken() == TPIPE);
9503 n2 = (union node *)stalloc(sizeof (struct nnot));
9516 union node *n1, *n2;
9517 union node *ap, **app;
9518 union node *cp, **cpp;
9519 union node *redir, **rpp;
9526 switch (readtoken()) {
9531 n1 = (union node *)stalloc(sizeof (struct nif));
9533 n1->nif.test = list(0);
9534 if (readtoken() != TTHEN)
9536 n1->nif.ifpart = list(0);
9538 while (readtoken() == TELIF) {
9539 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9540 n2 = n2->nif.elsepart;
9542 n2->nif.test = list(0);
9543 if (readtoken() != TTHEN)
9545 n2->nif.ifpart = list(0);
9547 if (lasttoken == TELSE)
9548 n2->nif.elsepart = list(0);
9550 n2->nif.elsepart = NULL;
9558 n1 = (union node *)stalloc(sizeof (struct nbinary));
9559 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9560 n1->nbinary.ch1 = list(0);
9561 if ((got=readtoken()) != TDO) {
9562 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9565 n1->nbinary.ch2 = list(0);
9570 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9571 synerror("Bad for loop variable");
9572 n1 = (union node *)stalloc(sizeof (struct nfor));
9574 n1->nfor.var = wordtext;
9575 checkkwd = CHKKWD | CHKALIAS;
9576 if (readtoken() == TIN) {
9578 while (readtoken() == TWORD) {
9579 n2 = (union node *)stalloc(sizeof (struct narg));
9581 n2->narg.text = wordtext;
9582 n2->narg.backquote = backquotelist;
9584 app = &n2->narg.next;
9588 if (lasttoken != TNL && lasttoken != TSEMI)
9591 n2 = (union node *)stalloc(sizeof (struct narg));
9593 n2->narg.text = (char *)dolatstr;
9594 n2->narg.backquote = NULL;
9595 n2->narg.next = NULL;
9598 * Newline or semicolon here is optional (but note
9599 * that the original Bourne shell only allowed NL).
9601 if (lasttoken != TNL && lasttoken != TSEMI)
9604 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9605 if (readtoken() != TDO)
9607 n1->nfor.body = list(0);
9611 n1 = (union node *)stalloc(sizeof (struct ncase));
9613 if (readtoken() != TWORD)
9615 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9617 n2->narg.text = wordtext;
9618 n2->narg.backquote = backquotelist;
9619 n2->narg.next = NULL;
9621 checkkwd = CHKKWD | CHKALIAS;
9622 } while (readtoken() == TNL);
9623 if (lasttoken != TIN)
9625 cpp = &n1->ncase.cases;
9627 checkkwd = CHKNL | CHKKWD;
9630 if (lasttoken == TLP)
9632 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9634 app = &cp->nclist.pattern;
9636 *app = ap = (union node *)stalloc(sizeof (struct narg));
9638 ap->narg.text = wordtext;
9639 ap->narg.backquote = backquotelist;
9640 if (readtoken() != TPIPE)
9642 app = &ap->narg.next;
9645 ap->narg.next = NULL;
9646 if (lasttoken != TRP)
9648 cp->nclist.body = list(2);
9650 cpp = &cp->nclist.next;
9652 checkkwd = CHKNL | CHKKWD;
9653 if ((t = readtoken()) != TESAC) {
9655 synexpect(TENDCASE);
9663 n1 = (union node *)stalloc(sizeof (struct nredir));
9664 n1->type = NSUBSHELL;
9665 n1->nredir.n = list(0);
9666 n1->nredir.redirect = NULL;
9679 if (readtoken() != t)
9683 /* Now check for redirection which may follow command */
9684 checkkwd = CHKKWD | CHKALIAS;
9686 while (readtoken() == TREDIR) {
9687 *rpp = n2 = redirnode;
9688 rpp = &n2->nfile.next;
9694 if (n1->type != NSUBSHELL) {
9695 n2 = (union node *)stalloc(sizeof (struct nredir));
9700 n1->nredir.redirect = redir;
9709 union node *args, **app;
9710 union node *n = NULL;
9711 union node *vars, **vpp;
9712 union node **rpp, *redir;
9722 savecheckkwd = CHKALIAS;
9724 checkkwd = savecheckkwd;
9725 switch (readtoken()) {
9727 n = (union node *)stalloc(sizeof (struct narg));
9729 n->narg.text = wordtext;
9730 n->narg.backquote = backquotelist;
9731 if (savecheckkwd && isassignment(wordtext)) {
9733 vpp = &n->narg.next;
9736 app = &n->narg.next;
9741 *rpp = n = redirnode;
9742 rpp = &n->nfile.next;
9743 parsefname(); /* read name of redirection file */
9747 args && app == &args->narg.next &&
9750 struct builtincmd *bcmd;
9753 /* We have a function */
9754 if (readtoken() != TRP)
9756 name = n->narg.text;
9758 !goodname(name) || (
9759 (bcmd = find_builtin(name)) &&
9760 IS_BUILTIN_SPECIAL(bcmd)
9763 synerror("Bad function name");
9765 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9766 n->narg.next = command();
9779 n = (union node *)stalloc(sizeof (struct ncmd));
9781 n->ncmd.args = args;
9782 n->ncmd.assign = vars;
9783 n->ncmd.redirect = redir;
9792 n = (union node *)stalloc(sizeof (struct narg));
9794 n->narg.next = NULL;
9795 n->narg.text = wordtext;
9796 n->narg.backquote = backquotelist;
9800 void fixredir(union node *n, const char *text, int err)
9802 TRACE(("Fix redir %s %d\n", text, err));
9804 n->ndup.vname = NULL;
9806 if (is_digit(text[0]) && text[1] == '\0')
9807 n->ndup.dupfd = digit_val(text[0]);
9808 else if (text[0] == '-' && text[1] == '\0')
9813 synerror("Bad fd number");
9815 n->ndup.vname = makename();
9823 union node *n = redirnode;
9825 if (readtoken() != TWORD)
9827 if (n->type == NHERE) {
9828 struct heredoc *here = heredoc;
9834 TRACE(("Here document %d\n", n->type));
9835 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9836 synerror("Illegal eof marker for << redirection");
9837 rmescapes(wordtext);
9838 here->eofmark = wordtext;
9840 if (heredoclist == NULL)
9843 for (p = heredoclist ; p->next ; p = p->next);
9846 } else if (n->type == NTOFD || n->type == NFROMFD) {
9847 fixredir(n, wordtext, 0);
9849 n->nfile.fname = makename();
9855 * Input any here documents.
9861 struct heredoc *here;
9871 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9872 here->eofmark, here->striptabs);
9873 n = (union node *)stalloc(sizeof (struct narg));
9874 n->narg.type = NARG;
9875 n->narg.next = NULL;
9876 n->narg.text = wordtext;
9877 n->narg.backquote = backquotelist;
9878 here->here->nhere.doc = n;
9883 static char peektoken(void)
9889 return tokname_array[t][0];
9897 int alreadyseen = tokpushback;
9900 #ifdef CONFIG_ASH_ALIAS
9909 if (checkkwd & CHKNL) {
9916 if (t != TWORD || quoteflag) {
9921 * check for keywords
9923 if (checkkwd & CHKKWD) {
9924 const char *const *pp;
9926 if ((pp = findkwd(wordtext))) {
9927 lasttoken = t = pp - tokname_array;
9928 TRACE(("keyword %s recognized\n", tokname(t)));
9933 if (checkkwd & CHKALIAS) {
9934 #ifdef CONFIG_ASH_ALIAS
9936 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9938 pushstring(ap->val, ap);
9948 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9950 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9957 * Read the next input token.
9958 * If the token is a word, we set backquotelist to the list of cmds in
9959 * backquotes. We set quoteflag to true if any part of the word was
9961 * If the token is TREDIR, then we set redirnode to a structure containing
9963 * In all cases, the variable startlinno is set to the number of the line
9964 * on which the token starts.
9966 * [Change comment: here documents and internal procedures]
9967 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9968 * word parsing code into a separate routine. In this case, readtoken
9969 * doesn't need to have any internal procedures, but parseword does.
9970 * We could also make parseoperator in essence the main routine, and
9971 * have parseword (readtoken1?) handle both words and redirection.]
9974 #define NEW_xxreadtoken
9975 #ifdef NEW_xxreadtoken
9977 /* singles must be first! */
9978 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9980 static const char xxreadtoken_tokens[] = {
9981 TNL, TLP, TRP, /* only single occurrence allowed */
9982 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9983 TEOF, /* corresponds to trailing nul */
9984 TAND, TOR, TENDCASE, /* if double occurrence */
9987 #define xxreadtoken_doubles \
9988 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9989 #define xxreadtoken_singles \
9990 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9992 static int xxreadtoken(void)
10003 startlinno = plinno;
10004 for (;;) { /* until token or start of word found */
10007 if ((c != ' ') && (c != '\t')
10008 #ifdef CONFIG_ASH_ALIAS
10013 while ((c = pgetc()) != '\n' && c != PEOF);
10015 } else if (c == '\\') {
10016 if (pgetc() != '\n') {
10020 startlinno = ++plinno;
10025 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10030 needprompt = doprompt;
10033 p = strchr(xxreadtoken_chars, c);
10036 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10039 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10040 if (pgetc() == *p) { /* double occurrence? */
10041 p += xxreadtoken_doubles + 1;
10048 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10056 #define RETURN(token) return lasttoken = token
10070 startlinno = plinno;
10071 for (;;) { /* until token or start of word found */
10074 case ' ': case '\t':
10075 #ifdef CONFIG_ASH_ALIAS
10080 while ((c = pgetc()) != '\n' && c != PEOF);
10084 if (pgetc() == '\n') {
10085 startlinno = ++plinno;
10094 needprompt = doprompt;
10099 if (pgetc() == '&')
10104 if (pgetc() == '|')
10109 if (pgetc() == ';')
10122 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10125 #endif /* NEW_xxreadtoken */
10129 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10130 * is not NULL, read a here document. In the latter case, eofmark is the
10131 * word which marks the end of the document and striptabs is true if
10132 * leading tabs should be stripped from the document. The argument firstc
10133 * is the first character of the input token or document.
10135 * Because C does not have internal subroutines, I have simulated them
10136 * using goto's to implement the subroutine linkage. The following macros
10137 * will run code that appears at the end of readtoken1.
10140 #define CHECKEND() {goto checkend; checkend_return:;}
10141 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10142 #define PARSESUB() {goto parsesub; parsesub_return:;}
10143 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10144 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10145 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10148 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10153 char line[EOFMARKLEN + 1];
10154 struct nodelist *bqlist = 0;
10157 int varnest = 0; /* levels of variables expansion */
10158 int arinest = 0; /* levels of arithmetic expansion */
10159 int parenlevel = 0; /* levels of parens in arithmetic */
10160 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10162 int prevsyntax = 0; /* syntax before arithmetic */
10164 /* Avoid longjmp clobbering */
10170 (void) &parenlevel;
10173 (void) &prevsyntax;
10177 startlinno = plinno;
10179 if (syntax == DQSYNTAX)
10188 STARTSTACKSTR(out);
10189 loop: { /* for each line, until end of word */
10190 CHECKEND(); /* set c to PEOF if at end of here document */
10191 for (;;) { /* until end of line or end of word */
10192 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10193 switch(SIT(c, syntax)) {
10194 case CNL: /* '\n' */
10195 if (syntax == BASESYNTAX)
10196 goto endword; /* exit outer loop */
10202 goto loop; /* continue outer loop */
10207 if (eofmark == NULL || dblquote)
10208 USTPUTC(CTLESC, out);
10211 case CBACK: /* backslash */
10214 USTPUTC(CTLESC, out);
10215 USTPUTC('\\', out);
10217 } else if (c == '\n') {
10222 c != '\\' && c != '`' &&
10227 USTPUTC(CTLESC, out);
10228 USTPUTC('\\', out);
10230 if (SIT(c, SQSYNTAX) == CCTL)
10231 USTPUTC(CTLESC, out);
10239 if (eofmark == NULL) {
10240 USTPUTC(CTLQUOTEMARK, out);
10248 if (eofmark != NULL && arinest == 0 &&
10252 if (dqvarnest == 0) {
10253 syntax = BASESYNTAX;
10260 case CVAR: /* '$' */
10261 PARSESUB(); /* parse substitution */
10263 case CENDVAR: /* '}' */
10266 if (dqvarnest > 0) {
10269 USTPUTC(CTLENDVAR, out);
10274 #ifdef CONFIG_ASH_MATH_SUPPORT
10275 case CLP: /* '(' in arithmetic */
10279 case CRP: /* ')' in arithmetic */
10280 if (parenlevel > 0) {
10284 if (pgetc() == ')') {
10285 if (--arinest == 0) {
10286 USTPUTC(CTLENDARI, out);
10287 syntax = prevsyntax;
10288 if (syntax == DQSYNTAX)
10296 * unbalanced parens
10297 * (don't 2nd guess - no error)
10305 case CBQUOTE: /* '`' */
10309 goto endword; /* exit outer loop */
10314 goto endword; /* exit outer loop */
10315 #ifdef CONFIG_ASH_ALIAS
10325 #ifdef CONFIG_ASH_MATH_SUPPORT
10326 if (syntax == ARISYNTAX)
10327 synerror("Missing '))'");
10329 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10330 synerror("Unterminated quoted string");
10331 if (varnest != 0) {
10332 startlinno = plinno;
10334 synerror("Missing '}'");
10336 USTPUTC('\0', out);
10337 len = out - (char *)stackblock();
10338 out = stackblock();
10339 if (eofmark == NULL) {
10340 if ((c == '>' || c == '<')
10343 && (*out == '\0' || is_digit(*out))) {
10345 return lasttoken = TREDIR;
10350 quoteflag = quotef;
10351 backquotelist = bqlist;
10352 grabstackblock(len);
10354 return lasttoken = TWORD;
10355 /* end of readtoken routine */
10360 * Check to see whether we are at the end of the here document. When this
10361 * is called, c is set to the first character of the next input line. If
10362 * we are at the end of the here document, this routine sets the c to PEOF.
10367 #ifdef CONFIG_ASH_ALIAS
10373 while (c == '\t') {
10377 if (c == *eofmark) {
10378 if (pfgets(line, sizeof line) != NULL) {
10382 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10383 if (*p == '\n' && *q == '\0') {
10386 needprompt = doprompt;
10388 pushstring(line, NULL);
10393 goto checkend_return;
10398 * Parse a redirection operator. The variable "out" points to a string
10399 * specifying the fd to be redirected. The variable "c" contains the
10400 * first character of the redirection operator.
10407 np = (union node *)stalloc(sizeof (struct nfile));
10412 np->type = NAPPEND;
10414 np->type = NCLOBBER;
10421 } else { /* c == '<' */
10423 switch (c = pgetc()) {
10425 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10426 np = (union node *)stalloc(sizeof (struct nhere));
10430 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10431 heredoc->here = np;
10432 if ((c = pgetc()) == '-') {
10433 heredoc->striptabs = 1;
10435 heredoc->striptabs = 0;
10441 np->type = NFROMFD;
10445 np->type = NFROMTO;
10455 np->nfile.fd = digit_val(fd);
10457 goto parseredir_return;
10462 * Parse a substitution. At this point, we have read the dollar sign
10463 * and nothing else.
10471 static const char types[] = "}-+?=";
10475 c <= PEOA_OR_PEOF ||
10476 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10480 } else if (c == '(') { /* $(command) or $((arith)) */
10481 if (pgetc() == '(') {
10482 #ifdef CONFIG_ASH_MATH_SUPPORT
10485 synerror("We unsupport $((arith))");
10492 USTPUTC(CTLVAR, out);
10493 typeloc = out - (char *)stackblock();
10494 USTPUTC(VSNORMAL, out);
10495 subtype = VSNORMAL;
10499 if ((c = pgetc()) == '}')
10502 subtype = VSLENGTH;
10507 if (c > PEOA_OR_PEOF && is_name(c)) {
10511 } while (c > PEOA_OR_PEOF && is_in_name(c));
10512 } else if (is_digit(c)) {
10516 } while (is_digit(c));
10518 else if (is_special(c)) {
10523 badsub: synerror("Bad substitution");
10527 if (subtype == 0) {
10534 p = strchr(types, c);
10537 subtype = p - types + VSNORMAL;
10543 subtype = c == '#' ? VSTRIMLEFT :
10556 if (dblquote || arinest)
10558 *((char *)stackblock() + typeloc) = subtype | flags;
10559 if (subtype != VSNORMAL) {
10561 if (dblquote || arinest) {
10566 goto parsesub_return;
10571 * Called to parse command substitutions. Newstyle is set if the command
10572 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10573 * list of commands (passed by reference), and savelen is the number of
10574 * characters on the top of the stack which must be preserved.
10578 struct nodelist **nlpp;
10581 char *volatile str;
10582 struct jmploc jmploc;
10583 struct jmploc *volatile savehandler;
10585 int saveprompt = 0;
10587 (void) &saveprompt;
10590 savepbq = parsebackquote;
10591 if (setjmp(jmploc.loc)) {
10594 parsebackquote = 0;
10595 handler = savehandler;
10596 longjmp(handler->loc, 1);
10600 savelen = out - (char *)stackblock();
10602 str = ckmalloc(savelen);
10603 memcpy(str, stackblock(), savelen);
10605 savehandler = handler;
10609 /* We must read until the closing backquote, giving special
10610 treatment to some slashes, and then push the string and
10611 reread it as input, interpreting it normally. */
10618 STARTSTACKSTR(pout);
10623 switch (pc = pgetc()) {
10628 if ((pc = pgetc()) == '\n') {
10633 * If eating a newline, avoid putting
10634 * the newline into the new character
10635 * stream (via the STPUTC after the
10640 if (pc != '\\' && pc != '`' && pc != '$'
10641 && (!dblquote || pc != '"'))
10642 STPUTC('\\', pout);
10643 if (pc > PEOA_OR_PEOF) {
10649 #ifdef CONFIG_ASH_ALIAS
10652 startlinno = plinno;
10653 synerror("EOF in backquote substitution");
10657 needprompt = doprompt;
10666 STPUTC('\0', pout);
10667 psavelen = pout - (char *)stackblock();
10668 if (psavelen > 0) {
10669 pstr = grabstackstr(pout);
10670 setinputstring(pstr);
10675 nlpp = &(*nlpp)->next;
10676 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10677 (*nlpp)->next = NULL;
10678 parsebackquote = oldstyle;
10681 saveprompt = doprompt;
10688 doprompt = saveprompt;
10690 if (readtoken() != TRP)
10697 * Start reading from old file again, ignoring any pushed back
10698 * tokens left from the backquote parsing
10703 while (stackblocksize() <= savelen)
10705 STARTSTACKSTR(out);
10707 memcpy(out, str, savelen);
10708 STADJUST(savelen, out);
10714 parsebackquote = savepbq;
10715 handler = savehandler;
10716 if (arinest || dblquote)
10717 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10719 USTPUTC(CTLBACKQ, out);
10721 goto parsebackq_oldreturn;
10723 goto parsebackq_newreturn;
10726 #ifdef CONFIG_ASH_MATH_SUPPORT
10728 * Parse an arithmetic expansion (indicate start of one and set state)
10732 if (++arinest == 1) {
10733 prevsyntax = syntax;
10734 syntax = ARISYNTAX;
10735 USTPUTC(CTLARI, out);
10742 * we collapse embedded arithmetic expansion to
10743 * parenthesis, which should be equivalent
10747 goto parsearith_return;
10751 } /* end of readtoken */
10756 * Returns true if the text contains nothing to expand (no dollar signs
10761 noexpand(char *text)
10767 while ((c = *p++) != '\0') {
10768 if (c == CTLQUOTEMARK)
10772 else if (SIT(c, BASESYNTAX) == CCTL)
10780 * Return of a legal variable name (a letter or underscore followed by zero or
10781 * more letters, underscores, and digits).
10785 endofname(const char *name)
10793 if (! is_in_name(*p))
10801 * Called when an unexpected token is read during the parse. The argument
10802 * is the token that is expected, or -1 if more than one type of token can
10803 * occur at this point.
10806 static void synexpect(int token)
10811 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10813 sprintf(msg + l, " (expecting %s)", tokname(token));
10819 synerror(const char *msg)
10821 sh_error("Syntax error: %s", msg);
10827 * called by editline -- any expansions to the prompt
10828 * should be added here.
10831 #ifdef CONFIG_ASH_EXPAND_PRMT
10832 static const char *
10833 expandstr(const char *ps)
10837 /* XXX Fix (char *) cast. */
10838 setinputstring((char *)ps);
10839 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10842 n.narg.type = NARG;
10843 n.narg.next = NULL;
10844 n.narg.text = wordtext;
10845 n.narg.backquote = backquotelist;
10847 expandarg(&n, NULL, 0);
10848 return stackblock();
10852 static void setprompt(int whichprompt)
10854 const char *prompt;
10855 #ifdef CONFIG_ASH_EXPAND_PRMT
10856 struct stackmark smark;
10861 switch (whichprompt) {
10871 #ifdef CONFIG_ASH_EXPAND_PRMT
10872 setstackmark(&smark);
10873 stalloc(stackblocksize());
10875 putprompt(expandstr(prompt));
10876 #ifdef CONFIG_ASH_EXPAND_PRMT
10877 popstackmark(&smark);
10882 static const char *const *findkwd(const char *s)
10884 return bsearch(s, tokname_array + KWDOFFSET,
10885 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10886 sizeof(const char *), pstrcmp);
10892 * Code for dealing with input/output redirection.
10895 #define EMPTY -2 /* marks an unused slot in redirtab */
10897 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10899 # define PIPESIZE PIPE_BUF
10903 * Open a file in noclobber mode.
10904 * The code was copied from bash.
10907 noclobberopen(const char *fname)
10910 struct stat finfo, finfo2;
10913 * If the file exists and is a regular file, return an error
10916 r = stat(fname, &finfo);
10917 if (r == 0 && S_ISREG(finfo.st_mode)) {
10923 * If the file was not present (r != 0), make sure we open it
10924 * exclusively so that if it is created before we open it, our open
10925 * will fail. Make sure that we do not truncate an existing file.
10926 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10927 * file was not a regular file, we leave O_EXCL off.
10930 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10931 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10933 /* If the open failed, return the file descriptor right away. */
10938 * OK, the open succeeded, but the file may have been changed from a
10939 * non-regular file to a regular file between the stat and the open.
10940 * We are assuming that the O_EXCL open handles the case where FILENAME
10941 * did not exist and is symlinked to an existing file between the stat
10946 * If we can open it and fstat the file descriptor, and neither check
10947 * revealed that it was a regular file, and the file has not been
10948 * replaced, return the file descriptor.
10950 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10951 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10954 /* The file has been replaced. badness. */
10961 * Handle here documents. Normally we fork off a process to write the
10962 * data to a pipe. If the document is short, we can stuff the data in
10963 * the pipe without forking.
10967 openhere(union node *redir)
10973 sh_error("Pipe call failed");
10974 if (redir->type == NHERE) {
10975 len = strlen(redir->nhere.doc->narg.text);
10976 if (len <= PIPESIZE) {
10977 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10981 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10983 signal(SIGINT, SIG_IGN);
10984 signal(SIGQUIT, SIG_IGN);
10985 signal(SIGHUP, SIG_IGN);
10987 signal(SIGTSTP, SIG_IGN);
10989 signal(SIGPIPE, SIG_DFL);
10990 if (redir->type == NHERE)
10991 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10993 expandhere(redir->nhere.doc, pip[1]);
11002 openredirect(union node *redir)
11007 switch (redir->nfile.type) {
11009 fname = redir->nfile.expfname;
11010 if ((f = open(fname, O_RDONLY)) < 0)
11014 fname = redir->nfile.expfname;
11015 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11019 /* Take care of noclobber mode. */
11021 fname = redir->nfile.expfname;
11022 if ((f = noclobberopen(fname)) < 0)
11028 fname = redir->nfile.expfname;
11029 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11033 fname = redir->nfile.expfname;
11034 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11041 /* Fall through to eliminate warning. */
11048 f = openhere(redir);
11054 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11056 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11060 dupredirect(union node *redir, int f)
11062 int fd = redir->nfile.fd;
11064 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11065 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11066 copyfd(redir->ndup.dupfd, fd);
11079 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11080 * old file descriptors are stashed away so that the redirection can be
11081 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11082 * standard output, and the standard error if it becomes a duplicate of
11083 * stdout, is saved in memory.
11087 redirect(union node *redir, int flags)
11090 struct redirtab *sv;
11101 if (flags & REDIR_PUSH) {
11102 struct redirtab *q;
11103 q = ckmalloc(sizeof (struct redirtab));
11104 q->next = redirlist;
11106 q->nullredirs = nullredirs - 1;
11107 for (i = 0 ; i < 10 ; i++)
11108 q->renamed[i] = EMPTY;
11115 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11116 n->ndup.dupfd == fd)
11117 continue; /* redirect from/to same file descriptor */
11119 newfd = openredirect(n);
11122 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11123 i = fcntl(fd, F_DUPFD, 10);
11130 sh_error("%d: %m", fd);
11140 dupredirect(n, newfd);
11141 } while ((n = n->nfile.next));
11143 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11144 preverrout_fd = sv->renamed[2];
11149 * Undo the effects of the last redirection.
11155 struct redirtab *rp;
11158 if (--nullredirs >= 0)
11162 for (i = 0 ; i < 10 ; i++) {
11163 if (rp->renamed[i] != EMPTY) {
11166 copyfd(rp->renamed[i], i);
11168 close(rp->renamed[i]);
11171 redirlist = rp->next;
11172 nullredirs = rp->nullredirs;
11178 * Undo all redirections. Called on error or interrupt.
11182 * Discard all saved file descriptors.
11186 clearredir(int drop)
11198 * Copy a file descriptor to be >= to. Returns -1
11199 * if the source file descriptor is closed, EMPTY if there are no unused
11200 * file descriptors left.
11204 copyfd(int from, int to)
11208 newfd = fcntl(from, F_DUPFD, to);
11210 if (errno == EMFILE)
11213 sh_error("%d: %m", from);
11220 redirectsafe(union node *redir, int flags)
11223 volatile int saveint;
11224 struct jmploc *volatile savehandler = handler;
11225 struct jmploc jmploc;
11228 if (!(err = setjmp(jmploc.loc) * 2)) {
11230 redirect(redir, flags);
11232 handler = savehandler;
11233 if (err && exception != EXERROR)
11234 longjmp(handler->loc, 1);
11235 RESTOREINT(saveint);
11242 static void shtree(union node *, int, char *, FILE*);
11243 static void shcmd(union node *, FILE *);
11244 static void sharg(union node *, FILE *);
11245 static void indent(int, char *, FILE *);
11246 static void trstring(char *);
11250 showtree(union node *n)
11252 trputs("showtree called\n");
11253 shtree(n, 1, NULL, stdout);
11258 shtree(union node *n, int ind, char *pfx, FILE *fp)
11260 struct nodelist *lp;
11266 indent(ind, pfx, fp);
11277 shtree(n->nbinary.ch1, ind, NULL, fp);
11280 shtree(n->nbinary.ch2, ind, NULL, fp);
11288 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11293 if (n->npipe.backgnd)
11299 fprintf(fp, "<node type %d>", n->type);
11308 shcmd(union node *cmd, FILE *fp)
11316 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11322 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11325 switch (np->nfile.type) {
11326 case NTO: s = ">"; dftfd = 1; break;
11327 case NCLOBBER: s = ">|"; dftfd = 1; break;
11328 case NAPPEND: s = ">>"; dftfd = 1; break;
11329 case NTOFD: s = ">&"; dftfd = 1; break;
11330 case NFROM: s = "<"; dftfd = 0; break;
11331 case NFROMFD: s = "<&"; dftfd = 0; break;
11332 case NFROMTO: s = "<>"; dftfd = 0; break;
11333 default: s = "*error*"; dftfd = 0; break;
11335 if (np->nfile.fd != dftfd)
11336 fprintf(fp, "%d", np->nfile.fd);
11338 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11339 fprintf(fp, "%d", np->ndup.dupfd);
11341 sharg(np->nfile.fname, fp);
11350 sharg(union node *arg, FILE *fp)
11353 struct nodelist *bqlist;
11356 if (arg->type != NARG) {
11357 out1fmt("<node type %d>\n", arg->type);
11360 bqlist = arg->narg.backquote;
11361 for (p = arg->narg.text ; *p ; p++) {
11370 if (subtype == VSLENGTH)
11376 if (subtype & VSNUL)
11379 switch (subtype & VSTYPE) {
11398 case VSTRIMLEFTMAX:
11405 case VSTRIMRIGHTMAX:
11412 out1fmt("<subtype %d>", subtype);
11419 case CTLBACKQ|CTLQUOTE:
11422 shtree(bqlist->n, -1, NULL, fp);
11434 indent(int amount, char *pfx, FILE *fp)
11438 for (i = 0 ; i < amount ; i++) {
11439 if (pfx && i == amount - 1)
11460 putc(c, tracefile);
11464 trace(const char *fmt, ...)
11471 (void) vfprintf(tracefile, fmt, va);
11476 tracev(const char *fmt, va_list va)
11480 (void) vfprintf(tracefile, fmt, va);
11485 trputs(const char *s)
11489 fputs(s, tracefile);
11501 putc('"', tracefile);
11502 for (p = s ; *p ; p++) {
11504 case '\n': c = 'n'; goto backslash;
11505 case '\t': c = 't'; goto backslash;
11506 case '\r': c = 'r'; goto backslash;
11507 case '"': c = '"'; goto backslash;
11508 case '\\': c = '\\'; goto backslash;
11509 case CTLESC: c = 'e'; goto backslash;
11510 case CTLVAR: c = 'v'; goto backslash;
11511 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11512 case CTLBACKQ: c = 'q'; goto backslash;
11513 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11514 backslash: putc('\\', tracefile);
11515 putc(c, tracefile);
11518 if (*p >= ' ' && *p <= '~')
11519 putc(*p, tracefile);
11521 putc('\\', tracefile);
11522 putc(*p >> 6 & 03, tracefile);
11523 putc(*p >> 3 & 07, tracefile);
11524 putc(*p & 07, tracefile);
11529 putc('"', tracefile);
11541 putc(' ', tracefile);
11543 putc('\n', tracefile);
11559 /* leave open because libedit might be using it */
11562 scopy("./trace", s);
11564 if (!freopen(s, "a", tracefile)) {
11565 fprintf(stderr, "Can't re-open %s\n", s);
11570 if ((tracefile = fopen(s, "a")) == NULL) {
11571 fprintf(stderr, "Can't open %s\n", s);
11577 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11578 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11580 setlinebuf(tracefile);
11581 fputs("\nTracing started.\n", tracefile);
11589 * Sigmode records the current value of the signal handlers for the various
11590 * modes. A value of zero means that the current handler is not known.
11591 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11594 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11595 #define S_CATCH 2 /* signal is caught */
11596 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11597 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11598 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11603 * The trap builtin.
11607 trapcmd(int argc, char **argv)
11616 for (signo = 0 ; signo < NSIG ; signo++) {
11617 if (trap[signo] != NULL) {
11620 sn = u_signal_names(0, &signo, 0);
11623 out1fmt("trap -- %s %s\n",
11624 single_quote(trap[signo]), sn);
11634 if ((signo = decode_signal(*ap, 0)) < 0)
11635 sh_error("%s: bad trap", *ap);
11638 if (action[0] == '-' && action[1] == '\0')
11641 action = savestr(action);
11644 ckfree(trap[signo]);
11645 trap[signo] = action;
11656 * Clear traps on a fork.
11664 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11665 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11669 if (tp != &trap[0])
11670 setsignal(tp - trap);
11678 * Set the signal handler for the specified signal. The routine figures
11679 * out what it should be set to.
11683 setsignal(int signo)
11687 struct sigaction act;
11689 if ((t = trap[signo]) == NULL)
11691 else if (*t != '\0')
11695 if (rootshell && action == S_DFL) {
11698 if (iflag || minusc || sflag == 0)
11721 t = &sigmode[signo - 1];
11725 * current setting unknown
11727 if (sigaction(signo, 0, &act) == -1) {
11729 * Pretend it worked; maybe we should give a warning
11730 * here, but other shells don't. We don't alter
11731 * sigmode, so that we retry every time.
11735 if (act.sa_handler == SIG_IGN) {
11736 if (mflag && (signo == SIGTSTP ||
11737 signo == SIGTTIN || signo == SIGTTOU)) {
11738 tsig = S_IGN; /* don't hard ignore these */
11742 tsig = S_RESET; /* force to be set */
11745 if (tsig == S_HARD_IGN || tsig == action)
11749 act.sa_handler = onsig;
11752 act.sa_handler = SIG_IGN;
11755 act.sa_handler = SIG_DFL;
11759 sigfillset(&act.sa_mask);
11760 sigaction(signo, &act, 0);
11768 ignoresig(int signo)
11770 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11771 signal(signo, SIG_IGN);
11773 sigmode[signo - 1] = S_HARD_IGN;
11784 gotsig[signo - 1] = 1;
11785 pendingsigs = signo;
11787 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11796 * Called to execute a trap. Perhaps we should avoid entering new trap
11797 * handlers while we are executing a trap handler.
11809 savestatus = exitstatus;
11813 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11821 skip = evalstring(p, SKIPEVAL);
11822 exitstatus = savestatus;
11832 * Controls whether the shell is interactive or not.
11836 setinteractive(int on)
11838 static int is_interactive;
11840 if (++on == is_interactive)
11842 is_interactive = on;
11844 setsignal(SIGQUIT);
11845 setsignal(SIGTERM);
11846 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11847 if(is_interactive > 1) {
11848 /* Looks like they want an interactive shell */
11849 static int do_banner;
11853 "\n\n%s Built-in shell (ash)\n"
11854 "Enter 'help' for a list of built-in commands.\n\n",
11863 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11864 /*** List the available builtins ***/
11866 static int helpcmd(int argc, char **argv)
11870 out1fmt("\nBuilt-in commands:\n-------------------\n");
11871 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11872 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11873 builtincmd[i].name + 1);
11879 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11881 extern const struct BB_applet applets[];
11882 extern const size_t NUM_APPLETS;
11884 for (i = 0; i < NUM_APPLETS; i++) {
11886 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11895 return EXIT_SUCCESS;
11897 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11900 * Called to exit the shell.
11910 status = exitstatus;
11911 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11912 if (setjmp(loc.loc)) {
11913 if (exception == EXEXIT)
11918 if ((p = trap[0])) {
11924 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11925 if (iflag && rootshell) {
11926 const char *hp = lookupvar("HISTFILE");
11929 save_history ( hp );
11937 static int decode_signal(const char *string, int minsig)
11940 const char *name = u_signal_names(string, &signo, minsig);
11942 return name ? signo : -1;
11947 static struct var *vartab[VTABSIZE];
11949 static int vpcmp(const void *, const void *);
11950 static struct var **findvar(struct var **, const char *);
11953 * Initialize the variable symbol tables and import the environment
11957 #ifdef CONFIG_ASH_GETOPTS
11959 * Safe version of setvar, returns 1 on success 0 on failure.
11963 setvarsafe(const char *name, const char *val, int flags)
11966 volatile int saveint;
11967 struct jmploc *volatile savehandler = handler;
11968 struct jmploc jmploc;
11971 if (setjmp(jmploc.loc))
11975 setvar(name, val, flags);
11978 handler = savehandler;
11979 RESTOREINT(saveint);
11985 * Set the value of a variable. The flags argument is ored with the
11986 * flags of the variable. If val is NULL, the variable is unset.
11990 setvar(const char *name, const char *val, int flags)
11997 q = endofname(name);
11998 p = strchrnul(q, '=');
11999 namelen = p - name;
12000 if (!namelen || p != q)
12001 sh_error("%.*s: bad variable name", namelen, name);
12006 vallen = strlen(val);
12009 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12012 p = mempcpy(p, val, vallen);
12015 setvareq(nameeq, flags | VNOSAVE);
12021 * Same as setvar except that the variable and value are passed in
12022 * the first argument as name=value. Since the first argument will
12023 * be actually stored in the table, it should not be a string that
12025 * Called with interrupts off.
12029 setvareq(char *s, int flags)
12031 struct var *vp, **vpp;
12034 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12035 vp = *findvar(vpp, s);
12037 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12040 if (flags & VNOSAVE)
12043 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12046 if (flags & VNOSET)
12049 if (vp->func && (flags & VNOFUNC) == 0)
12050 (*vp->func)(strchrnul(s, '=') + 1);
12052 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12055 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12057 if (flags & VNOSET)
12060 vp = ckmalloc(sizeof (*vp));
12065 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12073 * Process a linked list of variable assignments.
12077 listsetvar(struct strlist *list_set_var, int flags)
12079 struct strlist *lp = list_set_var;
12085 setvareq(lp->text, flags);
12086 } while ((lp = lp->next));
12092 * Find the value of a variable. Returns NULL if not set.
12096 lookupvar(const char *name)
12100 if ((v = *findvar(hashvar(name), name))) {
12103 * Dynamic variables are implemented roughly the same way they are
12104 * in bash. Namely, they're "special" so long as they aren't unset.
12105 * As soon as they're unset, they're no longer dynamic, and dynamic
12106 * lookup will no longer happen at that point. -- PFM.
12108 if((v->flags & VDYNAMIC))
12111 if(!(v->flags & VUNSET))
12112 return strchrnul(v->text, '=') + 1;
12120 * Search the environment of a builtin command.
12124 bltinlookup(const char *name)
12126 struct strlist *sp;
12128 for (sp = cmdenviron ; sp ; sp = sp->next) {
12129 if (varequal(sp->text, name))
12130 return strchrnul(sp->text, '=') + 1;
12132 return lookupvar(name);
12137 * Generate a list of variables satisfying the given conditions.
12141 listvars(int on, int off, char ***end)
12152 for (vp = *vpp ; vp ; vp = vp->next)
12153 if ((vp->flags & mask) == on) {
12154 if (ep == stackstrend())
12155 ep = growstackstr();
12156 *ep++ = (char *) vp->text;
12158 } while (++vpp < vartab + VTABSIZE);
12159 if (ep == stackstrend())
12160 ep = growstackstr();
12164 return grabstackstr(ep);
12169 * POSIX requires that 'set' (but not export or readonly) output the
12170 * variables in lexicographic order - by the locale's collating order (sigh).
12171 * Maybe we could keep them in an ordered balanced binary tree
12172 * instead of hashed lists.
12173 * For now just roll 'em through qsort for printing...
12177 showvars(const char *sep_prefix, int on, int off)
12180 char **ep, **epend;
12182 ep = listvars(on, off, &epend);
12183 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12185 sep = *sep_prefix ? spcstr : sep_prefix;
12187 for (; ep < epend; ep++) {
12191 p = strchrnul(*ep, '=');
12194 q = single_quote(++p);
12196 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12205 * The export and readonly commands.
12209 exportcmd(int argc, char **argv)
12215 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12218 notp = nextopt("p") - 'p';
12219 if (notp && ((name = *(aptr = argptr)))) {
12221 if ((p = strchr(name, '=')) != NULL) {
12224 if ((vp = *findvar(hashvar(name), name))) {
12229 setvar(name, p, flag);
12230 } while ((name = *++aptr) != NULL);
12232 showvars(argv[0], flag, 0);
12239 * Make a variable a local variable. When a variable is made local, it's
12240 * value and flags are saved in a localvar structure. The saved values
12241 * will be restored when the shell function returns. We handle the name
12242 * "-" as a special case.
12246 mklocal(char *name)
12248 struct localvar *lvp;
12253 lvp = ckmalloc(sizeof (struct localvar));
12254 if (name[0] == '-' && name[1] == '\0') {
12256 p = ckmalloc(sizeof(optlist));
12257 lvp->text = memcpy(p, optlist, sizeof(optlist));
12262 vpp = hashvar(name);
12263 vp = *findvar(vpp, name);
12264 eq = strchr(name, '=');
12267 setvareq(name, VSTRFIXED);
12269 setvar(name, NULL, VSTRFIXED);
12270 vp = *vpp; /* the new variable */
12271 lvp->flags = VUNSET;
12273 lvp->text = vp->text;
12274 lvp->flags = vp->flags;
12275 vp->flags |= VSTRFIXED|VTEXTFIXED;
12281 lvp->next = localvars;
12287 * The "local" command.
12291 localcmd(int argc, char **argv)
12296 while ((name = *argv++) != NULL) {
12304 * Called after a function returns.
12305 * Interrupts must be off.
12311 struct localvar *lvp;
12314 while ((lvp = localvars) != NULL) {
12315 localvars = lvp->next;
12317 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12318 if (vp == NULL) { /* $- saved */
12319 memcpy(optlist, lvp->text, sizeof(optlist));
12322 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12323 unsetvar(vp->text);
12326 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12327 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12329 vp->flags = lvp->flags;
12330 vp->text = lvp->text;
12338 * The unset builtin command. We unset the function before we unset the
12339 * variable to allow a function to be unset when there is a readonly variable
12340 * with the same name.
12344 unsetcmd(int argc, char **argv)
12351 while ((i = nextopt("vf")) != '\0') {
12355 for (ap = argptr; *ap ; ap++) {
12370 * Unset the specified variable.
12374 unsetvar(const char *s)
12380 vpp = findvar(hashvar(s), s);
12384 int flags = vp->flags;
12387 if (flags & VREADONLY)
12390 vp->flags &= ~VDYNAMIC;
12392 if (flags & VUNSET)
12394 if ((flags & VSTRFIXED) == 0) {
12396 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12403 vp->flags &= ~VEXPORT;
12416 * Find the appropriate entry in the hash table from the name.
12419 static struct var **
12420 hashvar(const char *p)
12422 unsigned int hashval;
12424 hashval = ((unsigned char) *p) << 4;
12425 while (*p && *p != '=')
12426 hashval += (unsigned char) *p++;
12427 return &vartab[hashval % VTABSIZE];
12433 * Compares two strings up to the first = or '\0'. The first
12434 * string must be terminated by '='; the second may be terminated by
12435 * either '=' or '\0'.
12439 varcmp(const char *p, const char *q)
12443 while ((c = *p) == (d = *q)) {
12444 if (!c || c == '=')
12458 vpcmp(const void *a, const void *b)
12460 return varcmp(*(const char **)a, *(const char **)b);
12463 static struct var **
12464 findvar(struct var **vpp, const char *name)
12466 for (; *vpp; vpp = &(*vpp)->next) {
12467 if (varequal((*vpp)->text, name)) {
12475 #include <sys/times.h>
12477 static const unsigned char timescmd_str[] = {
12478 ' ', offsetof(struct tms, tms_utime),
12479 '\n', offsetof(struct tms, tms_stime),
12480 ' ', offsetof(struct tms, tms_cutime),
12481 '\n', offsetof(struct tms, tms_cstime),
12485 static int timescmd(int ac, char **av)
12487 long int clk_tck, s, t;
12488 const unsigned char *p;
12491 clk_tck = sysconf(_SC_CLK_TCK);
12496 t = *(clock_t *)(((char *) &buf) + p[1]);
12498 out1fmt("%ldm%ld.%.3lds%c",
12500 ((t - s * clk_tck) * 1000) / clk_tck,
12502 } while (*(p += 2));
12507 #ifdef CONFIG_ASH_MATH_SUPPORT
12509 dash_arith(const char *s)
12515 result = arith(s, &errcode);
12518 sh_error("exponent less than 0");
12519 else if (errcode == -2)
12520 sh_error("divide by zero");
12521 else if (errcode == -5)
12522 sh_error("expression recursion loop detected");
12533 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12534 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12536 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12540 letcmd(int argc, char **argv)
12547 sh_error("expression expected");
12548 for (ap = argv + 1; *ap; ap++) {
12549 i = dash_arith(*ap);
12554 #endif /* CONFIG_ASH_MATH_SUPPORT */
12559 * Miscellaneous builtins.
12565 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12566 typedef enum __rlimit_resource rlim_t;
12572 * The read builtin. The -e option causes backslashes to escape the
12573 * following character.
12575 * This uses unbuffered input, which may be avoidable in some cases.
12579 readcmd(int argc, char **argv)
12591 #if defined(CONFIG_ASH_READ_NCHARS)
12595 struct termios tty, old_tty;
12597 #if defined(CONFIG_ASH_READ_TIMEOUT)
12601 ts.tv_sec = ts.tv_usec = 0;
12606 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12607 while ((i = nextopt("p:rt:n:s")) != '\0')
12608 #elif defined(CONFIG_ASH_READ_NCHARS)
12609 while ((i = nextopt("p:rn:s")) != '\0')
12610 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12611 while ((i = nextopt("p:rt:")) != '\0')
12613 while ((i = nextopt("p:r")) != '\0')
12618 prompt = optionarg;
12620 #if defined(CONFIG_ASH_READ_NCHARS)
12622 nchars = strtol(optionarg, &p, 10);
12624 sh_error("invalid count");
12625 nch_flag = (nchars > 0);
12631 #if defined(CONFIG_ASH_READ_TIMEOUT)
12633 ts.tv_sec = strtol(optionarg, &p, 10);
12639 ts.tv_usec = strtol(p, &p2, 10);
12641 sh_error("invalid timeout");
12643 /* normalize to usec */
12645 sh_error("invalid timeout");
12646 while (scale++ < 6)
12650 sh_error("invalid timeout");
12652 if ( ! ts.tv_sec && ! ts.tv_usec)
12653 sh_error("invalid timeout");
12663 if (prompt && isatty(0)) {
12666 if (*(ap = argptr) == NULL)
12667 sh_error("arg count");
12668 if ((ifs = bltinlookup("IFS")) == NULL)
12670 #if defined(CONFIG_ASH_READ_NCHARS)
12671 if (nch_flag || silent) {
12672 tcgetattr(0, &tty);
12675 tty.c_lflag &= ~ICANON;
12676 tty.c_cc[VMIN] = nchars;
12679 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12682 tcsetattr(0, TCSANOW, &tty);
12685 #if defined(CONFIG_ASH_READ_TIMEOUT)
12686 if (ts.tv_sec || ts.tv_usec) {
12690 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12692 #if defined(CONFIG_ASH_READ_NCHARS)
12694 tcsetattr(0, TCSANOW, &old_tty);
12704 #if defined(CONFIG_ASH_READ_NCHARS)
12705 while (!nch_flag || nchars--)
12710 if (read(0, &c, 1) != 1) {
12722 if (!rflag && c == '\\') {
12728 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12732 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12734 setvar(*ap, stackblock(), 0);
12743 #if defined(CONFIG_ASH_READ_NCHARS)
12744 if (nch_flag || silent)
12745 tcsetattr(0, TCSANOW, &old_tty);
12749 /* Remove trailing blanks */
12750 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12752 setvar(*ap, stackblock(), 0);
12753 while (*++ap != NULL)
12754 setvar(*ap, nullstr, 0);
12759 static int umaskcmd(int argc, char **argv)
12761 static const char permuser[3] = "ugo";
12762 static const char permmode[3] = "rwx";
12763 static const short int permmask[] = {
12764 S_IRUSR, S_IWUSR, S_IXUSR,
12765 S_IRGRP, S_IWGRP, S_IXGRP,
12766 S_IROTH, S_IWOTH, S_IXOTH
12772 int symbolic_mode = 0;
12774 while (nextopt("S") != '\0') {
12783 if ((ap = *argptr) == NULL) {
12784 if (symbolic_mode) {
12788 for (i = 0; i < 3; i++) {
12791 *p++ = permuser[i];
12793 for (j = 0; j < 3; j++) {
12794 if ((mask & permmask[3 * i + j]) == 0) {
12795 *p++ = permmode[j];
12803 out1fmt("%.4o\n", mask);
12806 if (is_digit((unsigned char) *ap)) {
12809 if (*ap >= '8' || *ap < '0')
12810 sh_error(illnum, argv[1]);
12811 mask = (mask << 3) + (*ap - '0');
12812 } while (*++ap != '\0');
12815 mask = ~mask & 0777;
12816 if (!bb_parse_mode(ap, &mask)) {
12817 sh_error("Illegal mode: %s", ap);
12819 umask(~mask & 0777);
12828 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12829 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12830 * ash by J.T. Conklin.
12838 int factor; /* multiply by to get rlim_{cur,max} values */
12842 static const struct limits limits[] = {
12844 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12846 #ifdef RLIMIT_FSIZE
12847 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12850 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12852 #ifdef RLIMIT_STACK
12853 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12856 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12859 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12861 #ifdef RLIMIT_MEMLOCK
12862 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12864 #ifdef RLIMIT_NPROC
12865 { "process", RLIMIT_NPROC, 1, 'p' },
12867 #ifdef RLIMIT_NOFILE
12868 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12871 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12873 #ifdef RLIMIT_LOCKS
12874 { "locks", RLIMIT_LOCKS, 1, 'w' },
12876 { (char *) 0, 0, 0, '\0' }
12879 enum limtype { SOFT = 0x1, HARD = 0x2 };
12881 static void printlim(enum limtype how, const struct rlimit *limit,
12882 const struct limits *l)
12886 val = limit->rlim_max;
12888 val = limit->rlim_cur;
12890 if (val == RLIM_INFINITY)
12891 out1fmt("unlimited\n");
12894 out1fmt("%lld\n", (long long) val);
12899 ulimitcmd(int argc, char **argv)
12903 enum limtype how = SOFT | HARD;
12904 const struct limits *l;
12907 struct rlimit limit;
12910 while ((optc = nextopt("HSa"
12914 #ifdef RLIMIT_FSIZE
12920 #ifdef RLIMIT_STACK
12929 #ifdef RLIMIT_MEMLOCK
12932 #ifdef RLIMIT_NPROC
12935 #ifdef RLIMIT_NOFILE
12941 #ifdef RLIMIT_LOCKS
12959 for (l = limits; l->option != what; l++)
12962 set = *argptr ? 1 : 0;
12966 if (all || argptr[1])
12967 sh_error("too many arguments");
12968 if (strncmp(p, "unlimited\n", 9) == 0)
12969 val = RLIM_INFINITY;
12973 while ((c = *p++) >= '0' && c <= '9')
12975 val = (val * 10) + (long)(c - '0');
12976 if (val < (rlim_t) 0)
12980 sh_error("bad number");
12985 for (l = limits; l->name; l++) {
12986 getrlimit(l->cmd, &limit);
12987 out1fmt("%-20s ", l->name);
12988 printlim(how, &limit, l);
12993 getrlimit(l->cmd, &limit);
12996 limit.rlim_max = val;
12998 limit.rlim_cur = val;
12999 if (setrlimit(l->cmd, &limit) < 0)
13000 sh_error("error setting limit (%m)");
13002 printlim(how, &limit, l);
13008 #ifdef CONFIG_ASH_MATH_SUPPORT
13010 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13012 Permission is hereby granted, free of charge, to any person obtaining
13013 a copy of this software and associated documentation files (the
13014 "Software"), to deal in the Software without restriction, including
13015 without limitation the rights to use, copy, modify, merge, publish,
13016 distribute, sublicense, and/or sell copies of the Software, and to
13017 permit persons to whom the Software is furnished to do so, subject to
13018 the following conditions:
13020 The above copyright notice and this permission notice shall be
13021 included in all copies or substantial portions of the Software.
13023 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13024 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13025 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13026 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13027 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13028 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13029 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13032 /* This is my infix parser/evaluator. It is optimized for size, intended
13033 * as a replacement for yacc-based parsers. However, it may well be faster
13034 * than a comparable parser written in yacc. The supported operators are
13035 * listed in #defines below. Parens, order of operations, and error handling
13036 * are supported. This code is thread safe. The exact expression format should
13037 * be that which POSIX specifies for shells. */
13039 /* The code uses a simple two-stack algorithm. See
13040 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13041 * for a detailed explanation of the infix-to-postfix algorithm on which
13042 * this is based (this code differs in that it applies operators immediately
13043 * to the stack instead of adding them to a queue to end up with an
13046 /* To use the routine, call it with an expression string and error return
13050 * Aug 24, 2001 Manuel Novoa III
13052 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13054 * 1) In arith_apply():
13055 * a) Cached values of *numptr and &(numptr[-1]).
13056 * b) Removed redundant test for zero denominator.
13059 * a) Eliminated redundant code for processing operator tokens by moving
13060 * to a table-based implementation. Also folded handling of parens
13062 * b) Combined all 3 loops which called arith_apply to reduce generated
13063 * code size at the cost of speed.
13065 * 3) The following expressions were treated as valid by the original code:
13066 * 1() , 0! , 1 ( *3 ) .
13067 * These bugs have been fixed by internally enclosing the expression in
13068 * parens and then checking that all binary ops and right parens are
13069 * preceded by a valid expression (NUM_TOKEN).
13071 * Note: It may be desirable to replace Aaron's test for whitespace with
13072 * ctype's isspace() if it is used by another busybox applet or if additional
13073 * whitespace chars should be considered. Look below the "#include"s for a
13074 * precompiler test.
13078 * Aug 26, 2001 Manuel Novoa III
13080 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13082 * Merge in Aaron's comments previously posted to the busybox list,
13083 * modified slightly to take account of my changes to the code.
13088 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13090 * - allow access to variable,
13091 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13092 * - realize assign syntax (VAR=expr, +=, *= etc)
13093 * - realize exponentiation (** operator)
13094 * - realize comma separated - expr, expr
13095 * - realise ++expr --expr expr++ expr--
13096 * - realise expr ? expr : expr (but, second expr calculate always)
13097 * - allow hexadecimal and octal numbers
13098 * - was restored loses XOR operator
13099 * - remove one goto label, added three ;-)
13100 * - protect $((num num)) as true zero expr (Manuel`s error)
13101 * - always use special isspace(), see comment from bash ;-)
13105 #define arith_isspace(arithval) \
13106 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13109 typedef unsigned char operator;
13111 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13112 * precedence, and 3 high bits are an ID unique across operators of that
13113 * precedence. The ID portion is so that multiple operators can have the
13114 * same precedence, ensuring that the leftmost one is evaluated first.
13115 * Consider * and /. */
13117 #define tok_decl(prec,id) (((id)<<5)|(prec))
13118 #define PREC(op) ((op) & 0x1F)
13120 #define TOK_LPAREN tok_decl(0,0)
13122 #define TOK_COMMA tok_decl(1,0)
13124 #define TOK_ASSIGN tok_decl(2,0)
13125 #define TOK_AND_ASSIGN tok_decl(2,1)
13126 #define TOK_OR_ASSIGN tok_decl(2,2)
13127 #define TOK_XOR_ASSIGN tok_decl(2,3)
13128 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13129 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13130 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13131 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13133 #define TOK_MUL_ASSIGN tok_decl(3,0)
13134 #define TOK_DIV_ASSIGN tok_decl(3,1)
13135 #define TOK_REM_ASSIGN tok_decl(3,2)
13137 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13138 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13140 /* conditional is right associativity too */
13141 #define TOK_CONDITIONAL tok_decl(4,0)
13142 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13144 #define TOK_OR tok_decl(5,0)
13146 #define TOK_AND tok_decl(6,0)
13148 #define TOK_BOR tok_decl(7,0)
13150 #define TOK_BXOR tok_decl(8,0)
13152 #define TOK_BAND tok_decl(9,0)
13154 #define TOK_EQ tok_decl(10,0)
13155 #define TOK_NE tok_decl(10,1)
13157 #define TOK_LT tok_decl(11,0)
13158 #define TOK_GT tok_decl(11,1)
13159 #define TOK_GE tok_decl(11,2)
13160 #define TOK_LE tok_decl(11,3)
13162 #define TOK_LSHIFT tok_decl(12,0)
13163 #define TOK_RSHIFT tok_decl(12,1)
13165 #define TOK_ADD tok_decl(13,0)
13166 #define TOK_SUB tok_decl(13,1)
13168 #define TOK_MUL tok_decl(14,0)
13169 #define TOK_DIV tok_decl(14,1)
13170 #define TOK_REM tok_decl(14,2)
13172 /* exponent is right associativity */
13173 #define TOK_EXPONENT tok_decl(15,1)
13175 /* For now unary operators. */
13176 #define UNARYPREC 16
13177 #define TOK_BNOT tok_decl(UNARYPREC,0)
13178 #define TOK_NOT tok_decl(UNARYPREC,1)
13180 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13181 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13183 #define PREC_PRE (UNARYPREC+2)
13185 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13186 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13188 #define PREC_POST (UNARYPREC+3)
13190 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13191 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13193 #define SPEC_PREC (UNARYPREC+4)
13195 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13196 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13198 #define NUMPTR (*numstackptr)
13200 static inline int tok_have_assign(operator op)
13202 operator prec = PREC(op);
13204 convert_prec_is_assing(prec);
13205 return (prec == PREC(TOK_ASSIGN) ||
13206 prec == PREC_PRE || prec == PREC_POST);
13209 static inline int is_right_associativity(operator prec)
13211 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13212 prec == PREC(TOK_CONDITIONAL));
13216 typedef struct ARITCH_VAR_NUM {
13218 arith_t contidional_second_val;
13219 char contidional_second_val_initialized;
13220 char *var; /* if NULL then is regular number,
13221 else is variable name */
13225 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13227 struct CHK_VAR_RECURSIVE_LOOPED *next;
13228 } chk_var_recursive_looped_t;
13230 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13233 static int arith_lookup_val(v_n_t *t)
13236 const char * p = lookupvar(t->var);
13241 /* recursive try as expression */
13242 chk_var_recursive_looped_t *cur;
13243 chk_var_recursive_looped_t cur_save;
13245 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13246 if(strcmp(cur->var, t->var) == 0) {
13247 /* expression recursion loop detected */
13251 /* save current lookuped var name */
13252 cur = prev_chk_var_recursive;
13253 cur_save.var = t->var;
13254 cur_save.next = cur;
13255 prev_chk_var_recursive = &cur_save;
13257 t->val = arith (p, &errcode);
13258 /* restore previous ptr after recursiving */
13259 prev_chk_var_recursive = cur;
13262 /* allow undefined var as 0 */
13269 /* "applying" a token means performing it on the top elements on the integer
13270 * stack. For a unary operator it will only change the top element, but a
13271 * binary operator will pop two arguments and push a result */
13273 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13276 arith_t numptr_val, rez;
13277 int ret_arith_lookup_val;
13279 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13280 without arguments */
13281 numptr_m1 = NUMPTR - 1;
13283 /* check operand is var with noninteger value */
13284 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13285 if(ret_arith_lookup_val)
13286 return ret_arith_lookup_val;
13288 rez = numptr_m1->val;
13289 if (op == TOK_UMINUS)
13291 else if (op == TOK_NOT)
13293 else if (op == TOK_BNOT)
13295 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13297 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13299 else if (op != TOK_UPLUS) {
13300 /* Binary operators */
13302 /* check and binary operators need two arguments */
13303 if (numptr_m1 == numstack) goto err;
13305 /* ... and they pop one */
13308 if (op == TOK_CONDITIONAL) {
13309 if(! numptr_m1->contidional_second_val_initialized) {
13310 /* protect $((expr1 ? expr2)) without ": expr" */
13313 rez = numptr_m1->contidional_second_val;
13314 } else if(numptr_m1->contidional_second_val_initialized) {
13315 /* protect $((expr1 : expr2)) without "expr ? " */
13318 numptr_m1 = NUMPTR - 1;
13319 if(op != TOK_ASSIGN) {
13320 /* check operand is var with noninteger value for not '=' */
13321 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13322 if(ret_arith_lookup_val)
13323 return ret_arith_lookup_val;
13325 if (op == TOK_CONDITIONAL) {
13326 numptr_m1->contidional_second_val = rez;
13328 rez = numptr_m1->val;
13329 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13331 else if (op == TOK_OR)
13332 rez = numptr_val || rez;
13333 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13335 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13337 else if (op == TOK_AND)
13338 rez = rez && numptr_val;
13339 else if (op == TOK_EQ)
13340 rez = (rez == numptr_val);
13341 else if (op == TOK_NE)
13342 rez = (rez != numptr_val);
13343 else if (op == TOK_GE)
13344 rez = (rez >= numptr_val);
13345 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13346 rez >>= numptr_val;
13347 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13348 rez <<= numptr_val;
13349 else if (op == TOK_GT)
13350 rez = (rez > numptr_val);
13351 else if (op == TOK_LT)
13352 rez = (rez < numptr_val);
13353 else if (op == TOK_LE)
13354 rez = (rez <= numptr_val);
13355 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13357 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13359 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13361 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13363 else if (op == TOK_CONDITIONAL_SEP) {
13364 if (numptr_m1 == numstack) {
13365 /* protect $((expr : expr)) without "expr ? " */
13368 numptr_m1->contidional_second_val_initialized = op;
13369 numptr_m1->contidional_second_val = numptr_val;
13371 else if (op == TOK_CONDITIONAL) {
13373 numptr_val : numptr_m1->contidional_second_val;
13375 else if(op == TOK_EXPONENT) {
13377 return -3; /* exponent less than 0 */
13382 while(numptr_val--)
13387 else if(numptr_val==0) /* zero divisor check */
13389 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13391 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13394 if(tok_have_assign(op)) {
13397 if(numptr_m1->var == NULL) {
13401 /* save to shell variable */
13402 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13403 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13405 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13407 setvar(numptr_m1->var, buf, 0);
13408 /* after saving, make previous value for v++ or v-- */
13409 if(op == TOK_POST_INC)
13411 else if(op == TOK_POST_DEC)
13414 numptr_m1->val = rez;
13415 /* protect geting var value, is number now */
13416 numptr_m1->var = NULL;
13421 /* longest must first */
13422 static const char op_tokens[] = {
13423 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13424 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13425 '<','<', 0, TOK_LSHIFT,
13426 '>','>', 0, TOK_RSHIFT,
13427 '|','|', 0, TOK_OR,
13428 '&','&', 0, TOK_AND,
13429 '!','=', 0, TOK_NE,
13430 '<','=', 0, TOK_LE,
13431 '>','=', 0, TOK_GE,
13432 '=','=', 0, TOK_EQ,
13433 '|','=', 0, TOK_OR_ASSIGN,
13434 '&','=', 0, TOK_AND_ASSIGN,
13435 '*','=', 0, TOK_MUL_ASSIGN,
13436 '/','=', 0, TOK_DIV_ASSIGN,
13437 '%','=', 0, TOK_REM_ASSIGN,
13438 '+','=', 0, TOK_PLUS_ASSIGN,
13439 '-','=', 0, TOK_MINUS_ASSIGN,
13440 '-','-', 0, TOK_POST_DEC,
13441 '^','=', 0, TOK_XOR_ASSIGN,
13442 '+','+', 0, TOK_POST_INC,
13443 '*','*', 0, TOK_EXPONENT,
13447 '=', 0, TOK_ASSIGN,
13459 '?', 0, TOK_CONDITIONAL,
13460 ':', 0, TOK_CONDITIONAL_SEP,
13461 ')', 0, TOK_RPAREN,
13462 '(', 0, TOK_LPAREN,
13466 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13469 static arith_t arith (const char *expr, int *perrcode)
13471 char arithval; /* Current character under analysis */
13472 operator lasttok, op;
13475 const char *p = endexpression;
13478 size_t datasizes = strlen(expr) + 2;
13480 /* Stack of integers */
13481 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13482 * in any given correct or incorrect expression is left as an exercise to
13484 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13485 *numstackptr = numstack;
13486 /* Stack of operator tokens */
13487 operator *stack = alloca((datasizes) * sizeof(operator)),
13490 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13491 *perrcode = errcode = 0;
13494 if ((arithval = *expr) == 0) {
13495 if (p == endexpression) {
13496 /* Null expression. */
13500 /* This is only reached after all tokens have been extracted from the
13501 * input stream. If there are still tokens on the operator stack, they
13502 * are to be applied in order. At the end, there should be a final
13503 * result on the integer stack */
13505 if (expr != endexpression + 1) {
13506 /* If we haven't done so already, */
13507 /* append a closing right paren */
13508 expr = endexpression;
13509 /* and let the loop process it. */
13512 /* At this point, we're done with the expression. */
13513 if (numstackptr != numstack+1) {
13514 /* ... but if there isn't, it's bad */
13516 return (*perrcode = -1);
13518 if(numstack->var) {
13519 /* expression is $((var)) only, lookup now */
13520 errcode = arith_lookup_val(numstack);
13523 *perrcode = errcode;
13524 return numstack->val;
13526 /* Continue processing the expression. */
13527 if (arith_isspace(arithval)) {
13528 /* Skip whitespace */
13531 if((p = endofname(expr)) != expr) {
13532 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13534 numstackptr->var = alloca(var_name_size);
13535 safe_strncpy(numstackptr->var, expr, var_name_size);
13538 numstackptr->contidional_second_val_initialized = 0;
13542 } else if (is_digit(arithval)) {
13543 numstackptr->var = NULL;
13544 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13545 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13547 numstackptr->val = strtol(expr, (char **) &expr, 0);
13551 for(p = op_tokens; ; p++) {
13555 /* strange operator not found */
13558 for(o = expr; *p && *o == *p; p++)
13565 /* skip tail uncompared token */
13568 /* skip zero delim */
13573 /* post grammar: a++ reduce to num */
13574 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13577 /* Plus and minus are binary (not unary) _only_ if the last
13578 * token was as number, or a right paren (which pretends to be
13579 * a number, since it evaluates to one). Think about it.
13580 * It makes sense. */
13581 if (lasttok != TOK_NUM) {
13597 /* We don't want a unary operator to cause recursive descent on the
13598 * stack, because there can be many in a row and it could cause an
13599 * operator to be evaluated before its argument is pushed onto the
13600 * integer stack. */
13601 /* But for binary operators, "apply" everything on the operator
13602 * stack until we find an operator with a lesser priority than the
13603 * one we have just extracted. */
13604 /* Left paren is given the lowest priority so it will never be
13605 * "applied" in this way.
13606 * if associativity is right and priority eq, applied also skip
13609 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13610 /* not left paren or unary */
13611 if (lasttok != TOK_NUM) {
13612 /* binary op must be preceded by a num */
13615 while (stackptr != stack) {
13616 if (op == TOK_RPAREN) {
13617 /* The algorithm employed here is simple: while we don't
13618 * hit an open paren nor the bottom of the stack, pop
13619 * tokens and apply them */
13620 if (stackptr[-1] == TOK_LPAREN) {
13622 /* Any operator directly after a */
13624 /* close paren should consider itself binary */
13628 operator prev_prec = PREC(stackptr[-1]);
13630 convert_prec_is_assing(prec);
13631 convert_prec_is_assing(prev_prec);
13632 if (prev_prec < prec)
13634 /* check right assoc */
13635 if(prev_prec == prec && is_right_associativity(prec))
13638 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13639 if(errcode) goto ret;
13641 if (op == TOK_RPAREN) {
13646 /* Push this operator to the stack and remember it. */
13647 *stackptr++ = lasttok = op;
13654 #endif /* CONFIG_ASH_MATH_SUPPORT */
13658 const char *bb_applet_name = "debug stuff usage";
13659 int main(int argc, char **argv)
13661 return ash_main(argc, argv);
13666 * Copyright (c) 1989, 1991, 1993, 1994
13667 * The Regents of the University of California. All rights reserved.
13669 * This code is derived from software contributed to Berkeley by
13670 * Kenneth Almquist.
13672 * Redistribution and use in source and binary forms, with or without
13673 * modification, are permitted provided that the following conditions
13675 * 1. Redistributions of source code must retain the above copyright
13676 * notice, this list of conditions and the following disclaimer.
13677 * 2. Redistributions in binary form must reproduce the above copyright
13678 * notice, this list of conditions and the following disclaimer in the
13679 * documentation and/or other materials provided with the distribution.
13680 * 3. Neither the name of the University nor the names of its contributors
13681 * may be used to endorse or promote products derived from this software
13682 * without specific prior written permission.
13684 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13685 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13686 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13687 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13688 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13689 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13690 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13691 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13692 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13693 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF