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 /* comment by vodz: its strange for me, this programm don`t use other
2556 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2557 if (!(rootshell && iflag)) {
2558 signal(SIGINT, SIG_DFL);
2568 exvwarning(const char *msg, va_list ap)
2573 fprintf(errs, "%s: ", arg0);
2575 const char *fmt = (!iflag || parsefile->fd) ?
2576 "%s: %d: " : "%s: ";
2577 fprintf(errs, fmt, commandname, startlinno);
2579 vfprintf(errs, msg, ap);
2580 outcslow('\n', errs);
2584 * Exverror is called to raise the error exception. If the second argument
2585 * is not NULL then error prints an error message using printf style
2586 * formatting. It then raises the error exception.
2589 exverror(int cond, const char *msg, va_list ap)
2593 TRACE(("exverror(%d, \"", cond));
2595 TRACE(("\") pid=%d\n", getpid()));
2597 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2600 exvwarning(msg, ap);
2609 sh_error(const char *msg, ...)
2614 exverror(EXERROR, msg, ap);
2621 exerror(int cond, const char *msg, ...)
2626 exverror(cond, msg, ap);
2632 * error/warning routines for external builtins
2636 sh_warnx(const char *fmt, ...)
2641 exvwarning(fmt, ap);
2647 * Return a string describing an error. The returned string may be a
2648 * pointer to a static buffer that will be overwritten on the next call.
2649 * Action describes the operation that got the error.
2653 errmsg(int e, const char *em)
2655 if(e == ENOENT || e == ENOTDIR) {
2666 * Evaluate a command.
2669 /* flags in argument to evaltree */
2670 #define EV_EXIT 01 /* exit after evaluating tree */
2671 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2672 #define EV_BACKCMD 04 /* command executing within back quotes */
2675 static void evalloop(union node *, int);
2676 static void evalfor(union node *, int);
2677 static void evalcase(union node *, int);
2678 static void evalsubshell(union node *, int);
2679 static void expredir(union node *);
2680 static void evalpipe(union node *, int);
2681 static void evalcommand(union node *, int);
2682 static int evalbltin(const struct builtincmd *, int, char **);
2683 static int evalfun(struct funcnode *, int, char **, int);
2684 static void prehash(union node *);
2685 static int bltincmd(int, char **);
2688 static const struct builtincmd bltin = {
2694 * Called to reset things after an exception.
2702 evalcmd(int argc, char **argv)
2711 STARTSTACKSTR(concat);
2714 concat = stputs(p, concat);
2715 if ((p = *ap++) == NULL)
2717 STPUTC(' ', concat);
2719 STPUTC('\0', concat);
2720 p = grabstackstr(concat);
2722 evalstring(p, ~SKIPEVAL);
2730 * Execute a command or commands contained in a string.
2734 evalstring(char *s, int mask)
2737 struct stackmark smark;
2741 setstackmark(&smark);
2744 while ((n = parsecmd(0)) != NEOF) {
2746 popstackmark(&smark);
2761 * Evaluate a parse tree. The value is left in the global variable
2766 evaltree(union node *n, int flags)
2769 void (*evalfn)(union node *, int);
2773 TRACE(("evaltree(NULL) called\n"));
2776 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2777 getpid(), n, n->type, flags));
2781 out1fmt("Node type = %d\n", n->type);
2786 evaltree(n->nnot.com, EV_TESTED);
2787 status = !exitstatus;
2790 expredir(n->nredir.redirect);
2791 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2793 evaltree(n->nredir.n, flags & EV_TESTED);
2794 status = exitstatus;
2799 evalfn = evalcommand;
2801 if (eflag && !(flags & EV_TESTED))
2813 evalfn = evalsubshell;
2825 #error NAND + 1 != NOR
2827 #if NOR + 1 != NSEMI
2828 #error NOR + 1 != NSEMI
2830 isor = n->type - NAND;
2833 (flags | ((isor >> 1) - 1)) & EV_TESTED
2835 if (!exitstatus == isor)
2847 evaltree(n->nif.test, EV_TESTED);
2850 if (exitstatus == 0) {
2853 } else if (n->nif.elsepart) {
2854 n = n->nif.elsepart;
2859 defun(n->narg.text, n->narg.next);
2863 exitstatus = status;
2867 if ((checkexit & exitstatus))
2868 evalskip |= SKIPEVAL;
2869 else if (pendingsigs && dotrap())
2872 if (flags & EV_EXIT) {
2879 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2882 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2886 evalloop(union node *n, int flags)
2896 evaltree(n->nbinary.ch1, EV_TESTED);
2898 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2902 if (evalskip == SKIPBREAK && --skipcount <= 0)
2907 if (n->type != NWHILE)
2911 evaltree(n->nbinary.ch2, flags);
2912 status = exitstatus;
2917 exitstatus = status;
2923 evalfor(union node *n, int flags)
2925 struct arglist arglist;
2928 struct stackmark smark;
2930 setstackmark(&smark);
2931 arglist.lastp = &arglist.list;
2932 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2933 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2938 *arglist.lastp = NULL;
2943 for (sp = arglist.list ; sp ; sp = sp->next) {
2944 setvar(n->nfor.var, sp->text, 0);
2945 evaltree(n->nfor.body, flags);
2947 if (evalskip == SKIPCONT && --skipcount <= 0) {
2951 if (evalskip == SKIPBREAK && --skipcount <= 0)
2958 popstackmark(&smark);
2964 evalcase(union node *n, int flags)
2968 struct arglist arglist;
2969 struct stackmark smark;
2971 setstackmark(&smark);
2972 arglist.lastp = &arglist.list;
2973 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2975 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2976 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2977 if (casematch(patp, arglist.list->text)) {
2978 if (evalskip == 0) {
2979 evaltree(cp->nclist.body, flags);
2986 popstackmark(&smark);
2992 * Kick off a subshell to evaluate a tree.
2996 evalsubshell(union node *n, int flags)
2999 int backgnd = (n->type == NBACKGND);
3002 expredir(n->nredir.redirect);
3003 if (!backgnd && flags & EV_EXIT && !trap[0])
3007 if (forkshell(jp, n, backgnd) == 0) {
3011 flags &=~ EV_TESTED;
3013 redirect(n->nredir.redirect, 0);
3014 evaltreenr(n->nredir.n, flags);
3019 status = waitforjob(jp);
3020 exitstatus = status;
3027 * Compute the names of the files in a redirection list.
3031 expredir(union node *n)
3035 for (redir = n ; redir ; redir = redir->nfile.next) {
3037 fn.lastp = &fn.list;
3038 switch (redir->type) {
3044 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3045 redir->nfile.expfname = fn.list->text;
3049 if (redir->ndup.vname) {
3050 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3051 fixredir(redir, fn.list->text, 1);
3061 * Evaluate a pipeline. All the processes in the pipeline are children
3062 * of the process creating the pipeline. (This differs from some versions
3063 * of the shell, which make the last process in a pipeline the parent
3068 evalpipe(union node *n, int flags)
3071 struct nodelist *lp;
3076 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3078 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3082 jp = makejob(n, pipelen);
3084 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3088 if (pipe(pip) < 0) {
3090 sh_error("Pipe call failed");
3093 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3106 evaltreenr(lp->n, flags);
3114 if (n->npipe.backgnd == 0) {
3115 exitstatus = waitforjob(jp);
3116 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3124 * Execute a command inside back quotes. If it's a builtin command, we
3125 * want to save its output in a block obtained from malloc. Otherwise
3126 * we fork off a subprocess and get the output of the command via a pipe.
3127 * Should be called with interrupts off.
3131 evalbackcmd(union node *n, struct backcmd *result)
3143 saveherefd = herefd;
3151 sh_error("Pipe call failed");
3153 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3162 evaltreenr(n, EV_EXIT);
3166 result->fd = pip[0];
3169 herefd = saveherefd;
3171 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3172 result->fd, result->buf, result->nleft, result->jp));
3175 #ifdef CONFIG_ASH_CMDCMD
3176 static inline char **
3177 parse_command_args(char **argv, const char **path)
3189 if (c == '-' && !*cp) {
3199 /* run 'typecmd' for other options */
3202 } while ((c = *cp++));
3209 isassignment(const char *p)
3211 const char *q = endofname(p);
3217 #ifdef CONFIG_ASH_EXPAND_PRMT
3218 static const char *expandstr(const char *ps);
3220 #define expandstr(s) s
3224 * Execute a simple command.
3228 evalcommand(union node *cmd, int flags)
3230 struct stackmark smark;
3232 struct arglist arglist;
3233 struct arglist varlist;
3236 const struct strlist *sp;
3237 struct cmdentry cmdentry;
3245 struct builtincmd *bcmd;
3246 int pseudovarflag = 0;
3248 /* First expand the arguments. */
3249 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3250 setstackmark(&smark);
3251 back_exitstatus = 0;
3253 cmdentry.cmdtype = CMDBUILTIN;
3254 cmdentry.u.cmd = &bltin;
3255 varlist.lastp = &varlist.list;
3256 *varlist.lastp = NULL;
3257 arglist.lastp = &arglist.list;
3258 *arglist.lastp = NULL;
3263 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3264 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3267 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3268 struct strlist **spp;
3270 spp = arglist.lastp;
3271 if (pseudovarflag && isassignment(argp->narg.text))
3272 expandarg(argp, &arglist, EXP_VARTILDE);
3274 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3276 for (sp = *spp; sp; sp = sp->next)
3280 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3281 for (sp = arglist.list ; sp ; sp = sp->next) {
3282 TRACE(("evalcommand arg: %s\n", sp->text));
3283 *nargv++ = sp->text;
3288 if (iflag && funcnest == 0 && argc > 0)
3289 lastarg = nargv[-1];
3292 expredir(cmd->ncmd.redirect);
3293 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3296 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3297 struct strlist **spp;
3300 spp = varlist.lastp;
3301 expandarg(argp, &varlist, EXP_VARTILDE);
3304 * Modify the command lookup path, if a PATH= assignment
3308 if (varequal(p, path))
3312 /* Print the command if xflag is set. */
3315 const char *p = " %s";
3318 dprintf(preverrout_fd, p, expandstr(ps4val()));
3321 for(n = 0; n < 2; n++) {
3323 dprintf(preverrout_fd, p, sp->text);
3331 bb_full_write(preverrout_fd, "\n", 1);
3337 /* Now locate the command. */
3339 const char *oldpath;
3340 int cmd_flag = DO_ERR;
3345 find_command(argv[0], &cmdentry, cmd_flag, path);
3346 if (cmdentry.cmdtype == CMDUNKNOWN) {
3352 /* implement bltin and command here */
3353 if (cmdentry.cmdtype != CMDBUILTIN)
3356 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3357 if (cmdentry.u.cmd == EXECCMD)
3359 #ifdef CONFIG_ASH_CMDCMD
3360 if (cmdentry.u.cmd == COMMANDCMD) {
3363 nargv = parse_command_args(argv, &path);
3366 argc -= nargv - argv;
3368 cmd_flag |= DO_NOFUNC;
3376 /* We have a redirection error. */
3380 exitstatus = status;
3384 /* Execute the command. */
3385 switch (cmdentry.cmdtype) {
3387 /* Fork off a child process if necessary. */
3388 if (!(flags & EV_EXIT) || trap[0]) {
3390 jp = makejob(cmd, 1);
3391 if (forkshell(jp, cmd, FORK_FG) != 0) {
3392 exitstatus = waitforjob(jp);
3398 listsetvar(varlist.list, VEXPORT|VSTACK);
3399 shellexec(argv, path, cmdentry.u.index);
3403 cmdenviron = varlist.list;
3405 struct strlist *list = cmdenviron;
3407 if (spclbltin > 0 || argc == 0) {
3409 if (cmd_is_exec && argc > 1)
3412 listsetvar(list, i);
3414 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3429 exit_status = j + 128;
3430 exitstatus = exit_status;
3432 if (i == EXINT || spclbltin > 0) {
3434 longjmp(handler->loc, 1);
3441 listsetvar(varlist.list, 0);
3442 if (evalfun(cmdentry.u.func, argc, argv, flags))
3448 popredir(cmd_is_exec);
3450 /* dsl: I think this is intended to be used to support
3451 * '_' in 'vi' command mode during line editing...
3452 * However I implemented that within libedit itself.
3454 setvar("_", lastarg, 0);
3455 popstackmark(&smark);
3459 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3460 char *volatile savecmdname;
3461 struct jmploc *volatile savehandler;
3462 struct jmploc jmploc;
3465 savecmdname = commandname;
3466 if ((i = setjmp(jmploc.loc)))
3468 savehandler = handler;
3470 commandname = argv[0];
3472 optptr = NULL; /* initialize nextopt */
3473 exitstatus = (*cmd->builtin)(argc, argv);
3476 exitstatus |= ferror(stdout);
3477 commandname = savecmdname;
3479 handler = savehandler;
3485 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3487 volatile struct shparam saveparam;
3488 struct localvar *volatile savelocalvars;
3489 struct jmploc *volatile savehandler;
3490 struct jmploc jmploc;
3493 saveparam = shellparam;
3494 savelocalvars = localvars;
3495 if ((e = setjmp(jmploc.loc))) {
3499 savehandler = handler;
3502 shellparam.malloc = 0;
3506 shellparam.nparam = argc - 1;
3507 shellparam.p = argv + 1;
3508 #ifdef CONFIG_ASH_GETOPTS
3509 shellparam.optind = 1;
3510 shellparam.optoff = -1;
3512 evaltree(&func->n, flags & EV_TESTED);
3518 localvars = savelocalvars;
3519 freeparam(&shellparam);
3520 shellparam = saveparam;
3521 handler = savehandler;
3523 evalskip &= ~SKIPFUNC;
3529 goodname(const char *p)
3531 return !*endofname(p);
3535 * Search for a command. This is called before we fork so that the
3536 * location of the command will be available in the parent as well as
3537 * the child. The check for "goodname" is an overly conservative
3538 * check that the name will not be subject to expansion.
3542 prehash(union node *n)
3544 struct cmdentry entry;
3546 if (n->type == NCMD && n->ncmd.args)
3547 if (goodname(n->ncmd.args->narg.text))
3548 find_command(n->ncmd.args->narg.text, &entry, 0,
3555 * Builtin commands. Builtin commands whose functions are closely
3556 * tied to evaluation are implemented here.
3564 bltincmd(int argc, char **argv)
3567 * Preserve exitstatus of a previous possible redirection
3570 return back_exitstatus;
3575 * Handle break and continue commands. Break, continue, and return are
3576 * all handled by setting the evalskip flag. The evaluation routines
3577 * above all check this flag, and if it is set they start skipping
3578 * commands rather than executing them. The variable skipcount is
3579 * the number of loops to break/continue, or the number of function
3580 * levels to return. (The latter is always 1.) It should probably
3581 * be an error to break out of more loops than exist, but it isn't
3582 * in the standard shell so we don't make it one here.
3586 breakcmd(int argc, char **argv)
3588 int n = argc > 1 ? number(argv[1]) : 1;
3591 sh_error(illnum, argv[1]);
3595 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3603 * The return command.
3607 returncmd(int argc, char **argv)
3610 * If called outside a function, do what ksh does;
3611 * skip the rest of the file.
3613 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3614 return argv[1] ? number(argv[1]) : exitstatus;
3619 falsecmd(int argc, char **argv)
3626 truecmd(int argc, char **argv)
3633 execcmd(int argc, char **argv)
3636 iflag = 0; /* exit on error */
3639 shellexec(argv + 1, pathval(), 0);
3648 * When commands are first encountered, they are entered in a hash table.
3649 * This ensures that a full path search will not have to be done for them
3650 * on each invocation.
3652 * We should investigate converting to a linear search, even though that
3653 * would make the command name "hash" a misnomer.
3656 #define CMDTABLESIZE 31 /* should be prime */
3657 #define ARB 1 /* actual size determined at run time */
3662 struct tblentry *next; /* next entry in hash chain */
3663 union param param; /* definition of builtin function */
3664 short cmdtype; /* index identifying command */
3665 char rehash; /* if set, cd done since entry created */
3666 char cmdname[ARB]; /* name of command */
3670 static struct tblentry *cmdtable[CMDTABLESIZE];
3671 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3674 static void tryexec(char *, char **, char **);
3675 static void clearcmdentry(int);
3676 static struct tblentry *cmdlookup(const char *, int);
3677 static void delete_cmd_entry(void);
3681 * Exec a program. Never returns. If you change this routine, you may
3682 * have to change the find_command routine as well.
3686 shellexec(char **argv, const char *path, int idx)
3694 envp = environment();
3695 if (strchr(argv[0], '/') != NULL
3696 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3697 || find_applet_by_name(argv[0])
3700 tryexec(argv[0], argv, envp);
3704 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3705 if (--idx < 0 && pathopt == NULL) {
3706 tryexec(cmdname, argv, envp);
3707 if (errno != ENOENT && errno != ENOTDIR)
3714 /* Map to POSIX errors */
3726 exitstatus = exerrno;
3727 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3728 argv[0], e, suppressint ));
3729 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3735 tryexec(char *cmd, char **argv, char **envp)
3738 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3739 if(find_applet_by_name(cmd) != NULL) {
3740 /* re-exec ourselves with the new arguments */
3741 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3742 /* If they called chroot or otherwise made the binary no longer
3743 * executable, fall through */
3750 execve(cmd, argv, envp);
3751 } while (errno == EINTR);
3753 execve(cmd, argv, envp);
3757 } else if (errno == ENOEXEC) {
3761 for (ap = argv; *ap; ap++)
3763 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3765 *ap = cmd = (char *)DEFAULT_SHELL;
3768 while ((*ap++ = *argv++))
3778 * Do a path search. The variable path (passed by reference) should be
3779 * set to the start of the path before the first call; padvance will update
3780 * this value as it proceeds. Successive calls to padvance will return
3781 * the possible path expansions in sequence. If an option (indicated by
3782 * a percent sign) appears in the path entry then the global variable
3783 * pathopt will be set to point to it; otherwise pathopt will be set to
3788 padvance(const char **path, const char *name)
3798 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3799 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3800 while (stackblocksize() < len)
3804 memcpy(q, start, p - start);
3812 while (*p && *p != ':') p++;
3818 return stalloc(len);
3822 /*** Command hashing code ***/
3825 printentry(struct tblentry *cmdp)
3831 idx = cmdp->param.index;
3834 name = padvance(&path, cmdp->cmdname);
3836 } while (--idx >= 0);
3837 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3842 hashcmd(int argc, char **argv)
3844 struct tblentry **pp;
3845 struct tblentry *cmdp;
3847 struct cmdentry entry;
3850 while ((c = nextopt("r")) != '\0') {
3854 if (*argptr == NULL) {
3855 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3856 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3857 if (cmdp->cmdtype == CMDNORMAL)
3864 while ((name = *argptr) != NULL) {
3865 if ((cmdp = cmdlookup(name, 0)) != NULL
3866 && (cmdp->cmdtype == CMDNORMAL
3867 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3869 find_command(name, &entry, DO_ERR, pathval());
3870 if (entry.cmdtype == CMDUNKNOWN)
3879 * Resolve a command name. If you change this routine, you may have to
3880 * change the shellexec routine as well.
3884 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3886 struct tblentry *cmdp;
3893 struct builtincmd *bcmd;
3895 /* If name contains a slash, don't use PATH or hash table */
3896 if (strchr(name, '/') != NULL) {
3897 entry->u.index = -1;
3899 while (stat(name, &statb) < 0) {
3904 entry->cmdtype = CMDUNKNOWN;
3908 entry->cmdtype = CMDNORMAL;
3912 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3913 if (find_applet_by_name(name)) {
3914 entry->cmdtype = CMDNORMAL;
3915 entry->u.index = -1;
3920 updatetbl = (path == pathval());
3923 if (strstr(path, "%builtin") != NULL)
3927 /* If name is in the table, check answer will be ok */
3928 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3931 switch (cmdp->cmdtype) {
3949 } else if (cmdp->rehash == 0)
3950 /* if not invalidated by cd, we're done */
3954 /* If %builtin not in path, check for builtin next */
3955 bcmd = find_builtin(name);
3956 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3957 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3959 goto builtin_success;
3961 /* We have to search path. */
3962 prev = -1; /* where to start */
3963 if (cmdp && cmdp->rehash) { /* doing a rehash */
3964 if (cmdp->cmdtype == CMDBUILTIN)
3967 prev = cmdp->param.index;
3973 while ((fullname = padvance(&path, name)) != NULL) {
3974 stunalloc(fullname);
3977 if (prefix(pathopt, "builtin")) {
3979 goto builtin_success;
3981 } else if (!(act & DO_NOFUNC) &&
3982 prefix(pathopt, "func")) {
3985 /* ignore unimplemented options */
3989 /* if rehash, don't redo absolute path names */
3990 if (fullname[0] == '/' && idx <= prev) {
3993 TRACE(("searchexec \"%s\": no change\n", name));
3996 while (stat(fullname, &statb) < 0) {
4001 if (errno != ENOENT && errno != ENOTDIR)
4005 e = EACCES; /* if we fail, this will be the error */
4006 if (!S_ISREG(statb.st_mode))
4008 if (pathopt) { /* this is a %func directory */
4009 stalloc(strlen(fullname) + 1);
4010 readcmdfile(fullname);
4011 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4012 cmdp->cmdtype != CMDFUNCTION)
4013 sh_error("%s not defined in %s", name, fullname);
4014 stunalloc(fullname);
4017 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4019 entry->cmdtype = CMDNORMAL;
4020 entry->u.index = idx;
4024 cmdp = cmdlookup(name, 1);
4025 cmdp->cmdtype = CMDNORMAL;
4026 cmdp->param.index = idx;
4031 /* We failed. If there was an entry for this command, delete it */
4032 if (cmdp && updatetbl)
4035 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4036 entry->cmdtype = CMDUNKNOWN;
4041 entry->cmdtype = CMDBUILTIN;
4042 entry->u.cmd = bcmd;
4046 cmdp = cmdlookup(name, 1);
4047 cmdp->cmdtype = CMDBUILTIN;
4048 cmdp->param.cmd = bcmd;
4052 entry->cmdtype = cmdp->cmdtype;
4053 entry->u = cmdp->param;
4058 * Wrapper around strcmp for qsort/bsearch/...
4060 static int pstrcmp(const void *a, const void *b)
4062 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4066 * Search the table of builtin commands.
4069 static struct builtincmd *
4070 find_builtin(const char *name)
4072 struct builtincmd *bp;
4075 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4084 * Called when a cd is done. Marks all commands so the next time they
4085 * are executed they will be rehashed.
4091 struct tblentry **pp;
4092 struct tblentry *cmdp;
4094 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4095 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4096 if (cmdp->cmdtype == CMDNORMAL || (
4097 cmdp->cmdtype == CMDBUILTIN &&
4098 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4109 * Fix command hash table when PATH changed.
4110 * Called before PATH is changed. The argument is the new value of PATH;
4111 * pathval() still returns the old value at this point.
4112 * Called with interrupts off.
4116 changepath(const char *newval)
4118 const char *old, *new;
4125 firstchange = 9999; /* assume no change */
4131 if ((*old == '\0' && *new == ':')
4132 || (*old == ':' && *new == '\0'))
4134 old = new; /* ignore subsequent differences */
4138 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4145 if (builtinloc < 0 && idx_bltin >= 0)
4146 builtinloc = idx_bltin; /* zap builtins */
4147 if (builtinloc >= 0 && idx_bltin < 0)
4149 clearcmdentry(firstchange);
4150 builtinloc = idx_bltin;
4155 * Clear out command entries. The argument specifies the first entry in
4156 * PATH which has changed.
4160 clearcmdentry(int firstchange)
4162 struct tblentry **tblp;
4163 struct tblentry **pp;
4164 struct tblentry *cmdp;
4167 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4169 while ((cmdp = *pp) != NULL) {
4170 if ((cmdp->cmdtype == CMDNORMAL &&
4171 cmdp->param.index >= firstchange)
4172 || (cmdp->cmdtype == CMDBUILTIN &&
4173 builtinloc >= firstchange)) {
4187 * Locate a command in the command hash table. If "add" is nonzero,
4188 * add the command to the table if it is not already present. The
4189 * variable "lastcmdentry" is set to point to the address of the link
4190 * pointing to the entry, so that delete_cmd_entry can delete the
4193 * Interrupts must be off if called with add != 0.
4196 static struct tblentry **lastcmdentry;
4199 static struct tblentry *
4200 cmdlookup(const char *name, int add)
4202 unsigned int hashval;
4204 struct tblentry *cmdp;
4205 struct tblentry **pp;
4208 hashval = (unsigned char)*p << 4;
4210 hashval += (unsigned char)*p++;
4212 pp = &cmdtable[hashval % CMDTABLESIZE];
4213 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4214 if (equal(cmdp->cmdname, name))
4218 if (add && cmdp == NULL) {
4219 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4220 + strlen(name) + 1);
4222 cmdp->cmdtype = CMDUNKNOWN;
4223 strcpy(cmdp->cmdname, name);
4230 * Delete the command entry returned on the last lookup.
4234 delete_cmd_entry(void)
4236 struct tblentry *cmdp;
4239 cmdp = *lastcmdentry;
4240 *lastcmdentry = cmdp->next;
4241 if (cmdp->cmdtype == CMDFUNCTION)
4242 freefunc(cmdp->param.func);
4249 * Add a new command entry, replacing any existing command entry for
4250 * the same name - except special builtins.
4254 addcmdentry(char *name, struct cmdentry *entry)
4256 struct tblentry *cmdp;
4258 cmdp = cmdlookup(name, 1);
4259 if (cmdp->cmdtype == CMDFUNCTION) {
4260 freefunc(cmdp->param.func);
4262 cmdp->cmdtype = entry->cmdtype;
4263 cmdp->param = entry->u;
4268 * Make a copy of a parse tree.
4271 static inline struct funcnode *
4272 copyfunc(union node *n)
4277 funcblocksize = offsetof(struct funcnode, n);
4280 blocksize = funcblocksize;
4281 f = ckmalloc(blocksize + funcstringsize);
4282 funcblock = (char *) f + offsetof(struct funcnode, n);
4283 funcstring = (char *) f + blocksize;
4290 * Define a shell function.
4294 defun(char *name, union node *func)
4296 struct cmdentry entry;
4299 entry.cmdtype = CMDFUNCTION;
4300 entry.u.func = copyfunc(func);
4301 addcmdentry(name, &entry);
4307 * Delete a function if it exists.
4311 unsetfunc(const char *name)
4313 struct tblentry *cmdp;
4315 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4316 cmdp->cmdtype == CMDFUNCTION)
4321 * Locate and print what a word is...
4325 #ifdef CONFIG_ASH_CMDCMD
4327 describe_command(char *command, int describe_command_verbose)
4329 #define describe_command_verbose 1
4331 describe_command(char *command)
4334 struct cmdentry entry;
4335 struct tblentry *cmdp;
4336 #ifdef CONFIG_ASH_ALIAS
4337 const struct alias *ap;
4339 const char *path = pathval();
4341 if (describe_command_verbose) {
4345 /* First look at the keywords */
4346 if (findkwd(command)) {
4347 out1str(describe_command_verbose ? " is a shell keyword" : command);
4351 #ifdef CONFIG_ASH_ALIAS
4352 /* Then look at the aliases */
4353 if ((ap = lookupalias(command, 0)) != NULL) {
4354 if (describe_command_verbose) {
4355 out1fmt(" is an alias for %s", ap->val);
4364 /* Then check if it is a tracked alias */
4365 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4366 entry.cmdtype = cmdp->cmdtype;
4367 entry.u = cmdp->param;
4369 /* Finally use brute force */
4370 find_command(command, &entry, DO_ABS, path);
4373 switch (entry.cmdtype) {
4375 int j = entry.u.index;
4381 p = padvance(&path, command);
4385 if (describe_command_verbose) {
4387 (cmdp ? " a tracked alias for" : nullstr), p
4396 if (describe_command_verbose) {
4397 out1str(" is a shell function");
4404 if (describe_command_verbose) {
4405 out1fmt(" is a %sshell builtin",
4406 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4407 "special " : nullstr
4415 if (describe_command_verbose) {
4416 out1str(": not found\n");
4422 outstr("\n", stdout);
4427 typecmd(int argc, char **argv)
4432 for (i = 1; i < argc; i++) {
4433 #ifdef CONFIG_ASH_CMDCMD
4434 err |= describe_command(argv[i], 1);
4436 err |= describe_command(argv[i]);
4442 #ifdef CONFIG_ASH_CMDCMD
4444 commandcmd(int argc, char **argv)
4452 while ((c = nextopt("pvV")) != '\0')
4454 verify |= VERIFY_VERBOSE;
4456 verify |= VERIFY_BRIEF;
4462 return describe_command(*argptr, verify - VERIFY_BRIEF);
4471 * Routines to expand arguments to commands. We have to deal with
4472 * backquotes, shell variables, and file metacharacters.
4478 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4479 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4480 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4481 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4482 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4485 * Structure specifying which parts of the string should be searched
4486 * for IFS characters.
4490 struct ifsregion *next; /* next region in list */
4491 int begoff; /* offset of start of region */
4492 int endoff; /* offset of end of region */
4493 int nulonly; /* search for nul bytes only */
4496 /* output of current string */
4497 static char *expdest;
4498 /* list of back quote expressions */
4499 static struct nodelist *argbackq;
4500 /* first struct in list of ifs regions */
4501 static struct ifsregion ifsfirst;
4502 /* last struct in list */
4503 static struct ifsregion *ifslastp;
4504 /* holds expanded arg list */
4505 static struct arglist exparg;
4507 static void argstr(char *, int);
4508 static char *exptilde(char *, char *, int);
4509 static void expbackq(union node *, int, int);
4510 static const char *subevalvar(char *, char *, int, int, int, int, int);
4511 static char *evalvar(char *, int);
4512 static void strtodest(const char *, int, int);
4513 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4514 static ssize_t varvalue(char *, int, int);
4515 static void recordregion(int, int, int);
4516 static void removerecordregions(int);
4517 static void ifsbreakup(char *, struct arglist *);
4518 static void ifsfree(void);
4519 static void expandmeta(struct strlist *, int);
4520 static int patmatch(char *, const char *);
4522 static int cvtnum(arith_t);
4523 static size_t esclen(const char *, const char *);
4524 static char *scanleft(char *, char *, char *, char *, int, int);
4525 static char *scanright(char *, char *, char *, char *, int, int);
4526 static void varunset(const char *, const char *, const char *, int)
4530 #define pmatch(a, b) !fnmatch((a), (b), 0)
4532 * Prepare a pattern for a expmeta (internal glob(3)) call.
4534 * Returns an stalloced string.
4537 static inline char *
4538 preglob(const char *pattern, int quoted, int flag) {
4539 flag |= RMESCAPE_GLOB;
4541 flag |= RMESCAPE_QUOTED;
4543 return _rmescapes((char *)pattern, flag);
4548 esclen(const char *start, const char *p) {
4551 while (p > start && *--p == CTLESC) {
4559 * Expand shell variables and backquotes inside a here document.
4563 expandhere(union node *arg, int fd)
4566 expandarg(arg, (struct arglist *)NULL, 0);
4567 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4572 * Perform variable substitution and command substitution on an argument,
4573 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4574 * perform splitting and file name expansion. When arglist is NULL, perform
4575 * here document expansion.
4579 expandarg(union node *arg, struct arglist *arglist, int flag)
4584 argbackq = arg->narg.backquote;
4585 STARTSTACKSTR(expdest);
4586 ifsfirst.next = NULL;
4588 argstr(arg->narg.text, flag);
4589 p = _STPUTC('\0', expdest);
4591 if (arglist == NULL) {
4592 return; /* here document expanded */
4594 p = grabstackstr(p);
4595 exparg.lastp = &exparg.list;
4599 if (flag & EXP_FULL) {
4600 ifsbreakup(p, &exparg);
4601 *exparg.lastp = NULL;
4602 exparg.lastp = &exparg.list;
4603 expandmeta(exparg.list, flag);
4605 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4607 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4610 exparg.lastp = &sp->next;
4614 *exparg.lastp = NULL;
4616 *arglist->lastp = exparg.list;
4617 arglist->lastp = exparg.lastp;
4623 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4624 * characters to allow for further processing. Otherwise treat
4625 * $@ like $* since no splitting will be performed.
4629 argstr(char *p, int flag)
4631 static const char spclchars[] = {
4639 CTLBACKQ | CTLQUOTE,
4640 #ifdef CONFIG_ASH_MATH_SUPPORT
4645 const char *reject = spclchars;
4647 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4648 int breakall = flag & EXP_WORD;
4653 if (!(flag & EXP_VARTILDE)) {
4655 } else if (flag & EXP_VARTILDE2) {
4660 if (flag & EXP_TILDE) {
4666 if (*q == CTLESC && (flag & EXP_QWORD))
4669 p = exptilde(p, q, flag);
4672 startloc = expdest - (char *)stackblock();
4674 length += strcspn(p + length, reject);
4676 if (c && (!(c & 0x80)
4677 #ifdef CONFIG_ASH_MATH_SUPPORT
4681 /* c == '=' || c == ':' || c == CTLENDARI */
4686 expdest = stnputs(p, length, expdest);
4687 newloc = expdest - (char *)stackblock();
4688 if (breakall && !inquotes && newloc > startloc) {
4689 recordregion(startloc, newloc, 0);
4700 if (flag & EXP_VARTILDE2) {
4704 flag |= EXP_VARTILDE2;
4709 * sort of a hack - expand tildes in variable
4710 * assignments (after the first '=' and after ':'s).
4719 case CTLENDVAR: /* ??? */
4722 /* "$@" syntax adherence hack */
4725 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4726 (p[4] == CTLQUOTEMARK || (
4727 p[4] == CTLENDVAR &&
4728 p[5] == CTLQUOTEMARK
4731 p = evalvar(p + 1, flag) + 1;
4734 inquotes = !inquotes;
4747 p = evalvar(p, flag);
4751 case CTLBACKQ|CTLQUOTE:
4752 expbackq(argbackq->n, c, quotes);
4753 argbackq = argbackq->next;
4755 #ifdef CONFIG_ASH_MATH_SUPPORT
4768 exptilde(char *startp, char *p, int flag)
4774 int quotes = flag & (EXP_FULL | EXP_CASE);
4779 while ((c = *++p) != '\0') {
4786 if (flag & EXP_VARTILDE)
4796 if (*name == '\0') {
4797 home = lookupvar(homestr);
4799 if ((pw = getpwnam(name)) == NULL)
4803 if (!home || !*home)
4806 startloc = expdest - (char *)stackblock();
4807 strtodest(home, SQSYNTAX, quotes);
4808 recordregion(startloc, expdest - (char *)stackblock(), 0);
4817 removerecordregions(int endoff)
4819 if (ifslastp == NULL)
4822 if (ifsfirst.endoff > endoff) {
4823 while (ifsfirst.next != NULL) {
4824 struct ifsregion *ifsp;
4826 ifsp = ifsfirst.next->next;
4827 ckfree(ifsfirst.next);
4828 ifsfirst.next = ifsp;
4831 if (ifsfirst.begoff > endoff)
4834 ifslastp = &ifsfirst;
4835 ifsfirst.endoff = endoff;
4840 ifslastp = &ifsfirst;
4841 while (ifslastp->next && ifslastp->next->begoff < endoff)
4842 ifslastp=ifslastp->next;
4843 while (ifslastp->next != NULL) {
4844 struct ifsregion *ifsp;
4846 ifsp = ifslastp->next->next;
4847 ckfree(ifslastp->next);
4848 ifslastp->next = ifsp;
4851 if (ifslastp->endoff > endoff)
4852 ifslastp->endoff = endoff;
4856 #ifdef CONFIG_ASH_MATH_SUPPORT
4858 * Expand arithmetic expression. Backup to start of expression,
4859 * evaluate, place result in (backed up) result, adjust string position.
4872 * This routine is slightly over-complicated for
4873 * efficiency. Next we scan backwards looking for the
4874 * start of arithmetic.
4876 start = stackblock();
4883 while (*p != CTLARI) {
4887 sh_error("missing CTLARI (shouldn't happen)");
4892 esc = esclen(start, p);
4902 removerecordregions(begoff);
4911 len = cvtnum(dash_arith(p + 2));
4914 recordregion(begoff, begoff + len, 0);
4919 * Expand stuff in backwards quotes.
4923 expbackq(union node *cmd, int quoted, int quotes)
4931 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4932 struct stackmark smark;
4935 setstackmark(&smark);
4937 startloc = dest - (char *)stackblock();
4939 evalbackcmd(cmd, (struct backcmd *) &in);
4940 popstackmark(&smark);
4947 memtodest(p, i, syntax, quotes);
4951 i = safe_read(in.fd, buf, sizeof buf);
4952 TRACE(("expbackq: read returns %d\n", i));
4962 back_exitstatus = waitforjob(in.jp);
4966 /* Eat all trailing newlines */
4968 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4973 recordregion(startloc, dest - (char *)stackblock(), 0);
4974 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4975 (dest - (char *)stackblock()) - startloc,
4976 (dest - (char *)stackblock()) - startloc,
4977 stackblock() + startloc));
4982 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4993 const char *s = loc2;
4999 match = pmatch(str, s);
5003 if (quotes && *loc == CTLESC)
5013 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5020 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5023 const char *s = loc2;
5028 match = pmatch(str, s);
5035 esc = esclen(startp, loc);
5047 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5051 int saveherefd = herefd;
5052 struct nodelist *saveargbackq = argbackq;
5054 char *rmesc, *rmescend;
5056 char *(*scan)(char *, char *, char *, char *, int , int);
5059 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5060 STPUTC('\0', expdest);
5061 herefd = saveherefd;
5062 argbackq = saveargbackq;
5063 startp = stackblock() + startloc;
5067 setvar(str, startp, 0);
5068 amount = startp - expdest;
5069 STADJUST(amount, expdest);
5073 varunset(p, str, startp, varflags);
5077 subtype -= VSTRIMRIGHT;
5079 if (subtype < 0 || subtype > 3)
5084 rmescend = stackblock() + strloc;
5086 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5087 if (rmesc != startp) {
5089 startp = stackblock() + startloc;
5093 str = stackblock() + strloc;
5094 preglob(str, varflags & VSQUOTE, 0);
5096 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5097 zero = subtype >> 1;
5098 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5099 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5101 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5104 memmove(startp, loc, str - loc);
5105 loc = startp + (str - loc) - 1;
5108 amount = loc - expdest;
5109 STADJUST(amount, expdest);
5116 * Expand a variable, and return a pointer to the next character in the
5120 evalvar(char *p, int flag)
5133 quotes = flag & (EXP_FULL | EXP_CASE);
5135 subtype = varflags & VSTYPE;
5136 quoted = varflags & VSQUOTE;
5138 easy = (!quoted || (*var == '@' && shellparam.nparam));
5139 startloc = expdest - (char *)stackblock();
5140 p = strchr(p, '=') + 1;
5143 varlen = varvalue(var, varflags, flag);
5144 if (varflags & VSNUL)
5147 if (subtype == VSPLUS) {
5148 varlen = -1 - varlen;
5152 if (subtype == VSMINUS) {
5156 p, flag | EXP_TILDE |
5157 (quoted ? EXP_QWORD : EXP_WORD)
5166 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5168 if (subevalvar(p, var, 0, subtype, startloc,
5172 * Remove any recorded regions beyond
5175 removerecordregions(startloc);
5185 if (varlen < 0 && uflag)
5186 varunset(p, var, 0, 0);
5188 if (subtype == VSLENGTH) {
5189 cvtnum(varlen > 0 ? varlen : 0);
5193 if (subtype == VSNORMAL) {
5197 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5206 case VSTRIMRIGHTMAX:
5215 * Terminate the string and start recording the pattern
5218 STPUTC('\0', expdest);
5219 patloc = expdest - (char *)stackblock();
5220 if (subevalvar(p, NULL, patloc, subtype,
5221 startloc, varflags, quotes) == 0) {
5222 int amount = expdest - (
5223 (char *)stackblock() + patloc - 1
5225 STADJUST(-amount, expdest);
5227 /* Remove any recorded regions beyond start of variable */
5228 removerecordregions(startloc);
5233 if (subtype != VSNORMAL) { /* skip to end of alternative */
5236 if ((c = *p++) == CTLESC)
5238 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5240 argbackq = argbackq->next;
5241 } else if (c == CTLVAR) {
5242 if ((*p++ & VSTYPE) != VSNORMAL)
5244 } else if (c == CTLENDVAR) {
5255 * Put a string on the stack.
5259 memtodest(const char *p, size_t len, int syntax, int quotes) {
5262 q = makestrspace(len * 2, q);
5265 int c = SC2INT(*p++);
5268 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5278 strtodest(const char *p, int syntax, int quotes)
5280 memtodest(p, strlen(p), syntax, quotes);
5285 * Add the value of a specialized variable to the stack string.
5289 varvalue(char *name, int varflags, int flags)
5299 int quoted = varflags & VSQUOTE;
5300 int subtype = varflags & VSTYPE;
5301 int quotes = flags & (EXP_FULL | EXP_CASE);
5303 if (quoted && (flags & EXP_FULL))
5304 sep = 1 << CHAR_BIT;
5306 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5315 num = shellparam.nparam;
5325 p = makestrspace(NOPTS, expdest);
5326 for (i = NOPTS - 1; i >= 0; i--) {
5328 USTPUTC(optletters(i), p);
5339 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5340 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5343 if (!(ap = shellparam.p))
5345 while ((p = *ap++)) {
5348 partlen = strlen(p);
5351 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5352 memtodest(p, partlen, syntax, quotes);
5358 if (subtype == VSPLUS || subtype == VSLENGTH) {
5380 if (num < 0 || num > shellparam.nparam)
5382 p = num ? shellparam.p[num - 1] : arg0;
5385 p = lookupvar(name);
5391 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5392 memtodest(p, len, syntax, quotes);
5396 if (subtype == VSPLUS || subtype == VSLENGTH)
5397 STADJUST(-len, expdest);
5403 * Record the fact that we have to scan this region of the
5404 * string for IFS characters.
5408 recordregion(int start, int end, int nulonly)
5410 struct ifsregion *ifsp;
5412 if (ifslastp == NULL) {
5416 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5418 ifslastp->next = ifsp;
5422 ifslastp->begoff = start;
5423 ifslastp->endoff = end;
5424 ifslastp->nulonly = nulonly;
5429 * Break the argument string into pieces based upon IFS and add the
5430 * strings to the argument list. The regions of the string to be
5431 * searched for IFS characters have been stored by recordregion.
5434 ifsbreakup(char *string, struct arglist *arglist)
5436 struct ifsregion *ifsp;
5441 const char *ifs, *realifs;
5447 if (ifslastp != NULL) {
5450 realifs = ifsset() ? ifsval() : defifs;
5453 p = string + ifsp->begoff;
5454 nulonly = ifsp->nulonly;
5455 ifs = nulonly ? nullstr : realifs;
5457 while (p < string + ifsp->endoff) {
5461 if (strchr(ifs, *p)) {
5463 ifsspc = (strchr(defifs, *p) != NULL);
5464 /* Ignore IFS whitespace at start */
5465 if (q == start && ifsspc) {
5471 sp = (struct strlist *)stalloc(sizeof *sp);
5473 *arglist->lastp = sp;
5474 arglist->lastp = &sp->next;
5478 if (p >= string + ifsp->endoff) {
5484 if (strchr(ifs, *p) == NULL ) {
5487 } else if (strchr(defifs, *p) == NULL) {
5503 } while ((ifsp = ifsp->next) != NULL);
5512 sp = (struct strlist *)stalloc(sizeof *sp);
5514 *arglist->lastp = sp;
5515 arglist->lastp = &sp->next;
5521 struct ifsregion *p;
5526 struct ifsregion *ifsp;
5532 ifsfirst.next = NULL;
5536 static void expmeta(char *, char *);
5537 static struct strlist *expsort(struct strlist *);
5538 static struct strlist *msort(struct strlist *, int);
5540 static char *expdir;
5544 expandmeta(struct strlist *str, int flag)
5546 static const char metachars[] = {
5549 /* TODO - EXP_REDIR */
5552 struct strlist **savelastp;
5558 if (!strpbrk(str->text, metachars))
5560 savelastp = exparg.lastp;
5563 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5565 int i = strlen(str->text);
5566 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5574 if (exparg.lastp == savelastp) {
5579 *exparg.lastp = str;
5580 rmescapes(str->text);
5581 exparg.lastp = &str->next;
5583 *exparg.lastp = NULL;
5584 *savelastp = sp = expsort(*savelastp);
5585 while (sp->next != NULL)
5587 exparg.lastp = &sp->next;
5594 * Add a file name to the list.
5598 addfname(const char *name)
5602 sp = (struct strlist *)stalloc(sizeof *sp);
5603 sp->text = sstrdup(name);
5605 exparg.lastp = &sp->next;
5610 * Do metacharacter (i.e. *, ?, [...]) expansion.
5614 expmeta(char *enddir, char *name)
5629 for (p = name; *p; p++) {
5630 if (*p == '*' || *p == '?')
5632 else if (*p == '[') {
5639 if (*q == '/' || *q == '\0')
5646 } else if (*p == '\\')
5648 else if (*p == '/') {
5655 if (metaflag == 0) { /* we've reached the end of the file name */
5656 if (enddir != expdir)
5664 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5675 } while (p < start);
5677 if (enddir == expdir) {
5679 } else if (enddir == expdir + 1 && *expdir == '/') {
5685 if ((dirp = opendir(cp)) == NULL)
5687 if (enddir != expdir)
5689 if (*endname == 0) {
5701 while (! intpending && (dp = readdir(dirp)) != NULL) {
5702 if (dp->d_name[0] == '.' && ! matchdot)
5704 if (pmatch(start, dp->d_name)) {
5706 scopy(dp->d_name, enddir);
5709 for (p = enddir, cp = dp->d_name;
5710 (*p++ = *cp++) != '\0';)
5713 expmeta(p, endname);
5723 * Sort the results of file name expansion. It calculates the number of
5724 * strings to sort and then calls msort (short for merge sort) to do the
5728 static struct strlist *
5729 expsort(struct strlist *str)
5735 for (sp = str ; sp ; sp = sp->next)
5737 return msort(str, len);
5741 static struct strlist *
5742 msort(struct strlist *list, int len)
5744 struct strlist *p, *q = NULL;
5745 struct strlist **lpp;
5753 for (n = half ; --n >= 0 ; ) {
5757 q->next = NULL; /* terminate first half of list */
5758 q = msort(list, half); /* sort first half of list */
5759 p = msort(p, len - half); /* sort second half */
5762 #ifdef CONFIG_LOCALE_SUPPORT
5763 if (strcoll(p->text, q->text) < 0)
5765 if (strcmp(p->text, q->text) < 0)
5770 if ((p = *lpp) == NULL) {
5777 if ((q = *lpp) == NULL) {
5788 * Returns true if the pattern matches the string.
5792 patmatch(char *pattern, const char *string)
5794 return pmatch(preglob(pattern, 0, 0), string);
5799 * Remove any CTLESC characters from a string.
5803 _rmescapes(char *str, int flag)
5806 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5811 p = strpbrk(str, qchars);
5817 if (flag & RMESCAPE_ALLOC) {
5818 size_t len = p - str;
5819 size_t fulllen = len + strlen(p) + 1;
5821 if (flag & RMESCAPE_GROW) {
5822 r = makestrspace(fulllen, expdest);
5823 } else if (flag & RMESCAPE_HEAP) {
5824 r = ckmalloc(fulllen);
5826 r = stalloc(fulllen);
5830 q = mempcpy(q, str, len);
5833 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5834 globbing = flag & RMESCAPE_GLOB;
5835 notescaped = globbing;
5837 if (*p == CTLQUOTEMARK) {
5838 inquotes = ~inquotes;
5840 notescaped = globbing;
5844 /* naked back slash */
5850 if (notescaped && inquotes && *p != '/') {
5854 notescaped = globbing;
5859 if (flag & RMESCAPE_GROW) {
5861 STADJUST(q - r + 1, expdest);
5868 * See if a pattern matches in a case statement.
5872 casematch(union node *pattern, char *val)
5874 struct stackmark smark;
5877 setstackmark(&smark);
5878 argbackq = pattern->narg.backquote;
5879 STARTSTACKSTR(expdest);
5881 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5882 STACKSTRNUL(expdest);
5883 result = patmatch(stackblock(), val);
5884 popstackmark(&smark);
5897 expdest = makestrspace(32, expdest);
5898 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5899 len = fmtstr(expdest, 32, "%lld", (long long) num);
5901 len = fmtstr(expdest, 32, "%ld", num);
5903 STADJUST(len, expdest);
5908 varunset(const char *end, const char *var, const char *umsg, int varflags)
5914 msg = "parameter not set";
5916 if (*end == CTLENDVAR) {
5917 if (varflags & VSNUL)
5922 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5929 * This implements the input routines used by the parser.
5932 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5934 static void pushfile(void);
5937 * Read a character from the script, returning PEOF on end of file.
5938 * Nul characters in the input are silently discarded.
5942 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5944 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5945 #define pgetc_macro() pgetc()
5949 return pgetc_as_macro();
5952 #define pgetc_macro() pgetc_as_macro()
5956 return pgetc_macro();
5962 * Same as pgetc(), but ignores PEOA.
5964 #ifdef CONFIG_ASH_ALIAS
5965 static int pgetc2(void)
5971 } while (c == PEOA);
5975 static inline int pgetc2(void)
5977 return pgetc_macro();
5982 * Read a line from the script.
5985 static inline char *
5986 pfgets(char *line, int len)
5992 while (--nleft > 0) {
6009 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6010 #ifdef CONFIG_ASH_EXPAND_PRMT
6011 static char *cmdedit_prompt;
6013 static const char *cmdedit_prompt;
6015 static inline void putprompt(const char *s)
6017 #ifdef CONFIG_ASH_EXPAND_PRMT
6018 free(cmdedit_prompt);
6019 cmdedit_prompt = bb_xstrdup(s);
6025 static inline void putprompt(const char *s)
6035 char *buf = parsefile->buf;
6039 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6040 if (!iflag || parsefile->fd)
6041 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6043 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6044 cmdedit_path_lookup = pathval();
6046 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6048 /* Ctrl+C presend */
6057 if(nr < 0 && errno == 0) {
6058 /* Ctrl+D presend */
6063 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6067 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6068 int flags = fcntl(0, F_GETFL, 0);
6069 if (flags >= 0 && flags & O_NONBLOCK) {
6070 flags &=~ O_NONBLOCK;
6071 if (fcntl(0, F_SETFL, flags) >= 0) {
6072 out2str("sh: turning off NDELAY mode\n");
6082 * Refill the input buffer and return the next input character:
6084 * 1) If a string was pushed back on the input, pop it;
6085 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6086 * from a string so we can't refill the buffer, return EOF.
6087 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6088 * 4) Process input up to the next newline, deleting nul characters.
6098 while (parsefile->strpush) {
6099 #ifdef CONFIG_ASH_ALIAS
6100 if (parsenleft == -1 && parsefile->strpush->ap &&
6101 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6106 if (--parsenleft >= 0)
6107 return SC2INT(*parsenextc++);
6109 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6116 if ((more = preadfd()) <= 0) {
6117 parselleft = parsenleft = EOF_NLEFT;
6124 /* delete nul characters */
6132 memmove(q, q + 1, more);
6136 parsenleft = q - parsenextc - 1;
6142 parsenleft = q - parsenextc - 1;
6154 out2str(parsenextc);
6159 return SC2INT(*parsenextc++);
6163 * Undo the last call to pgetc. Only one character may be pushed back.
6164 * PEOF may be pushed back.
6175 * Push a string back onto the input at this current parsefile level.
6176 * We handle aliases this way.
6179 pushstring(char *s, void *ap)
6186 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6187 if (parsefile->strpush) {
6188 sp = ckmalloc(sizeof (struct strpush));
6189 sp->prev = parsefile->strpush;
6190 parsefile->strpush = sp;
6192 sp = parsefile->strpush = &(parsefile->basestrpush);
6193 sp->prevstring = parsenextc;
6194 sp->prevnleft = parsenleft;
6195 #ifdef CONFIG_ASH_ALIAS
6196 sp->ap = (struct alias *)ap;
6198 ((struct alias *)ap)->flag |= ALIASINUSE;
6210 struct strpush *sp = parsefile->strpush;
6213 #ifdef CONFIG_ASH_ALIAS
6215 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6216 checkkwd |= CHKALIAS;
6218 if (sp->string != sp->ap->val) {
6221 sp->ap->flag &= ~ALIASINUSE;
6222 if (sp->ap->flag & ALIASDEAD) {
6223 unalias(sp->ap->name);
6227 parsenextc = sp->prevstring;
6228 parsenleft = sp->prevnleft;
6229 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6230 parsefile->strpush = sp->prev;
6231 if (sp != &(parsefile->basestrpush))
6237 * Set the input to take input from a file. If push is set, push the
6238 * old input onto the stack first.
6242 setinputfile(const char *fname, int flags)
6248 if ((fd = open(fname, O_RDONLY)) < 0) {
6249 if (flags & INPUT_NOFILE_OK)
6251 sh_error("Can't open %s", fname);
6254 fd2 = copyfd(fd, 10);
6257 sh_error("Out of file descriptors");
6260 setinputfd(fd, flags & INPUT_PUSH_FILE);
6268 * Like setinputfile, but takes an open file descriptor. Call this with
6273 setinputfd(int fd, int push)
6275 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6281 if (parsefile->buf == NULL)
6282 parsefile->buf = ckmalloc(IBUFSIZ);
6283 parselleft = parsenleft = 0;
6289 * Like setinputfile, but takes input from a string.
6293 setinputstring(char *string)
6297 parsenextc = string;
6298 parsenleft = strlen(string);
6299 parsefile->buf = NULL;
6306 * To handle the "." command, a stack of input files is used. Pushfile
6307 * adds a new entry to the stack and popfile restores the previous level.
6313 struct parsefile *pf;
6315 parsefile->nleft = parsenleft;
6316 parsefile->lleft = parselleft;
6317 parsefile->nextc = parsenextc;
6318 parsefile->linno = plinno;
6319 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6320 pf->prev = parsefile;
6323 pf->basestrpush.prev = NULL;
6331 struct parsefile *pf = parsefile;
6340 parsefile = pf->prev;
6342 parsenleft = parsefile->nleft;
6343 parselleft = parsefile->lleft;
6344 parsenextc = parsefile->nextc;
6345 plinno = parsefile->linno;
6351 * Return to top level.
6357 while (parsefile != &basepf)
6363 * Close the file(s) that the shell is reading commands from. Called
6364 * after a fork is done.
6371 if (parsefile->fd > 0) {
6372 close(parsefile->fd);
6379 /* mode flags for set_curjob */
6380 #define CUR_DELETE 2
6381 #define CUR_RUNNING 1
6382 #define CUR_STOPPED 0
6384 /* mode flags for dowait */
6385 #define DOWAIT_NORMAL 0
6386 #define DOWAIT_BLOCK 1
6389 static struct job *jobtab;
6391 static unsigned njobs;
6393 /* pgrp of shell on invocation */
6394 static int initialpgrp;
6395 static int ttyfd = -1;
6398 static struct job *curjob;
6399 /* number of presumed living untracked jobs */
6402 static void set_curjob(struct job *, unsigned);
6404 static int restartjob(struct job *, int);
6405 static void xtcsetpgrp(int, pid_t);
6406 static char *commandtext(union node *);
6407 static void cmdlist(union node *, int);
6408 static void cmdtxt(union node *);
6409 static void cmdputs(const char *);
6410 static void showpipe(struct job *, FILE *);
6412 static int sprint_status(char *, int, int);
6413 static void freejob(struct job *);
6414 static struct job *getjob(const char *, int);
6415 static struct job *growjobtab(void);
6416 static void forkchild(struct job *, union node *, int);
6417 static void forkparent(struct job *, union node *, int, pid_t);
6418 static int dowait(int, struct job *);
6419 static int getstatus(struct job *);
6422 set_curjob(struct job *jp, unsigned mode)
6425 struct job **jpp, **curp;
6427 /* first remove from list */
6428 jpp = curp = &curjob;
6433 jpp = &jp1->prev_job;
6435 *jpp = jp1->prev_job;
6437 /* Then re-insert in correct position */
6445 /* job being deleted */
6448 /* newly created job or backgrounded job,
6449 put after all stopped jobs. */
6453 if (!jp1 || jp1->state != JOBSTOPPED)
6456 jpp = &jp1->prev_job;
6462 /* newly stopped job - becomes curjob */
6463 jp->prev_job = *jpp;
6471 * Turn job control on and off.
6473 * Note: This code assumes that the third arg to ioctl is a character
6474 * pointer, which is true on Berkeley systems but not System V. Since
6475 * System V doesn't have job control yet, this isn't a problem now.
6477 * Called with interrupts off.
6486 if (on == jobctl || rootshell == 0)
6490 ofd = fd = open(_PATH_TTY, O_RDWR);
6493 while (!isatty(fd) && --fd >= 0)
6496 fd = fcntl(fd, F_DUPFD, 10);
6500 fcntl(fd, F_SETFD, FD_CLOEXEC);
6501 do { /* while we are in the background */
6502 if ((pgrp = tcgetpgrp(fd)) < 0) {
6504 sh_warnx("can't access tty; job control turned off");
6508 if (pgrp == getpgrp())
6519 xtcsetpgrp(fd, pgrp);
6521 /* turning job control off */
6524 xtcsetpgrp(fd, pgrp);
6538 killcmd(int argc, char **argv)
6549 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6550 "kill -l [exitstatus]"
6554 if (**++argv == '-') {
6555 signo = decode_signal(*argv + 1, 1);
6559 while ((c = nextopt("ls:")) != '\0')
6569 signo = decode_signal(optionarg, 1);
6572 "invalid signal number or name: %s",
6583 if (!list && signo < 0)
6586 if ((signo < 0 || !*argv) ^ list) {
6594 for (i = 1; i < NSIG; i++) {
6595 name = u_signal_names(0, &i, 1);
6597 out1fmt(snlfmt, name);
6601 name = u_signal_names(*argptr, &signo, -1);
6603 out1fmt(snlfmt, name);
6605 sh_error("invalid signal number or exit status: %s", *argptr);
6611 if (**argv == '%') {
6612 jp = getjob(*argv, 0);
6613 pid = -jp->ps[0].pid;
6615 pid = **argv == '-' ?
6616 -number(*argv + 1) : number(*argv);
6618 if (kill(pid, signo) != 0) {
6619 sh_warnx("(%d) - %m", pid);
6628 #if defined(JOBS) || defined(DEBUG)
6630 jobno(const struct job *jp)
6632 return jp - jobtab + 1;
6638 fgcmd(int argc, char **argv)
6645 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6650 jp = getjob(*argv, 1);
6651 if (mode == FORK_BG) {
6652 set_curjob(jp, CUR_RUNNING);
6653 fprintf(out, "[%d] ", jobno(jp));
6655 outstr(jp->ps->cmd, out);
6657 retval = restartjob(jp, mode);
6658 } while (*argv && *++argv);
6662 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6666 restartjob(struct job *jp, int mode)
6668 struct procstat *ps;
6674 if (jp->state == JOBDONE)
6676 jp->state = JOBRUNNING;
6678 if (mode == FORK_FG)
6679 xtcsetpgrp(ttyfd, pgid);
6680 killpg(pgid, SIGCONT);
6684 if (WIFSTOPPED(ps->status)) {
6687 } while (ps++, --i);
6689 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6696 sprint_status(char *s, int status, int sigonly)
6702 if (!WIFEXITED(status)) {
6704 if (WIFSTOPPED(status))
6705 st = WSTOPSIG(status);
6708 st = WTERMSIG(status);
6710 if (st == SIGINT || st == SIGPIPE)
6713 if (WIFSTOPPED(status))
6718 col = fmtstr(s, 32, strsignal(st));
6719 if (WCOREDUMP(status)) {
6720 col += fmtstr(s + col, 16, " (core dumped)");
6722 } else if (!sigonly) {
6723 st = WEXITSTATUS(status);
6725 col = fmtstr(s, 16, "Done(%d)", st);
6727 col = fmtstr(s, 16, "Done");
6736 showjob(FILE *out, struct job *jp, int mode)
6738 struct procstat *ps;
6739 struct procstat *psend;
6746 if (mode & SHOW_PGID) {
6747 /* just output process (group) id of pipeline */
6748 fprintf(out, "%d\n", ps->pid);
6752 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6757 else if (curjob && jp == curjob->prev_job)
6760 if (mode & SHOW_PID)
6761 col += fmtstr(s + col, 16, "%d ", ps->pid);
6763 psend = ps + jp->nprocs;
6765 if (jp->state == JOBRUNNING) {
6766 scopy("Running", s + col);
6767 col += strlen("Running");
6769 int status = psend[-1].status;
6771 if (jp->state == JOBSTOPPED)
6772 status = jp->stopstatus;
6774 col += sprint_status(s + col, status, 0);
6780 /* for each process */
6781 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6784 fprintf(out, "%s%*c%s",
6785 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6787 if (!(mode & SHOW_PID)) {
6791 if (++ps == psend) {
6792 outcslow('\n', out);
6799 if (jp->state == JOBDONE) {
6800 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6807 jobscmd(int argc, char **argv)
6813 while ((m = nextopt("lp")))
6823 showjob(out, getjob(*argv,0), mode);
6826 showjobs(out, mode);
6833 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6834 * statuses have changed since the last call to showjobs.
6838 showjobs(FILE *out, int mode)
6842 TRACE(("showjobs(%x) called\n", mode));
6844 /* If not even one one job changed, there is nothing to do */
6845 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6848 for (jp = curjob; jp; jp = jp->prev_job) {
6849 if (!(mode & SHOW_CHANGED) || jp->changed)
6850 showjob(out, jp, mode);
6856 * Mark a job structure as unused.
6860 freejob(struct job *jp)
6862 struct procstat *ps;
6866 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6867 if (ps->cmd != nullstr)
6870 if (jp->ps != &jp->ps0)
6873 set_curjob(jp, CUR_DELETE);
6879 waitcmd(int argc, char **argv)
6892 /* wait for all jobs */
6897 /* no running procs */
6900 if (jp->state == JOBRUNNING)
6905 dowait(DOWAIT_BLOCK, 0);
6911 if (**argv != '%') {
6912 pid_t pid = number(*argv);
6916 if (job->ps[job->nprocs - 1].pid == pid)
6918 job = job->prev_job;
6924 job = getjob(*argv, 0);
6925 /* loop until process terminated or stopped */
6926 while (job->state == JOBRUNNING)
6927 dowait(DOWAIT_BLOCK, 0);
6929 retval = getstatus(job);
6940 * Convert a job name to a job structure.
6944 getjob(const char *name, int getctl)
6948 const char *err_msg = "No such job: %s";
6952 char *(*match)(const char *, const char *);
6967 if (c == '+' || c == '%') {
6969 err_msg = "No current job";
6971 } else if (c == '-') {
6974 err_msg = "No previous job";
6985 jp = jobtab + num - 1;
7002 if (match(jp->ps[0].cmd, p)) {
7006 err_msg = "%s: ambiguous";
7013 err_msg = "job %s not created under job control";
7014 if (getctl && jp->jobctl == 0)
7019 sh_error(err_msg, name);
7024 * Return a new job structure.
7025 * Called with interrupts off.
7029 makejob(union node *node, int nprocs)
7034 for (i = njobs, jp = jobtab ; ; jp++) {
7041 if (jp->state != JOBDONE || !jp->waited)
7050 memset(jp, 0, sizeof(*jp));
7055 jp->prev_job = curjob;
7060 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7062 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7072 struct job *jp, *jq;
7074 len = njobs * sizeof(*jp);
7076 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7078 offset = (char *)jp - (char *)jq;
7080 /* Relocate pointers */
7083 jq = (struct job *)((char *)jq + l);
7087 #define joff(p) ((struct job *)((char *)(p) + l))
7088 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7089 if (xlikely(joff(jp)->ps == &jq->ps0))
7090 jmove(joff(jp)->ps);
7091 if (joff(jp)->prev_job)
7092 jmove(joff(jp)->prev_job);
7102 jp = (struct job *)((char *)jp + len);
7106 } while (--jq >= jp);
7112 * Fork off a subshell. If we are doing job control, give the subshell its
7113 * own process group. Jp is a job structure that the job is to be added to.
7114 * N is the command that will be evaluated by the child. Both jp and n may
7115 * be NULL. The mode parameter can be one of the following:
7116 * FORK_FG - Fork off a foreground process.
7117 * FORK_BG - Fork off a background process.
7118 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7119 * process group even if job control is on.
7121 * When job control is turned off, background processes have their standard
7122 * input redirected to /dev/null (except for the second and later processes
7125 * Called with interrupts off.
7129 forkchild(struct job *jp, union node *n, int mode)
7133 TRACE(("Child shell %d\n", getpid()));
7140 /* do job control only in root shell */
7142 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7145 if (jp->nprocs == 0)
7148 pgrp = jp->ps[0].pid;
7149 /* This can fail because we are doing it in the parent also */
7150 (void)setpgid(0, pgrp);
7151 if (mode == FORK_FG)
7152 xtcsetpgrp(ttyfd, pgrp);
7157 if (mode == FORK_BG) {
7160 if (jp->nprocs == 0) {
7162 if (open(bb_dev_null, O_RDONLY) != 0)
7163 sh_error("Can't open %s", bb_dev_null);
7166 if (!oldlvl && iflag) {
7171 for (jp = curjob; jp; jp = jp->prev_job)
7177 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7179 TRACE(("In parent shell: child = %d\n", pid));
7181 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7186 if (mode != FORK_NOJOB && jp->jobctl) {
7189 if (jp->nprocs == 0)
7192 pgrp = jp->ps[0].pid;
7193 /* This can fail because we are doing it in the child also */
7194 (void)setpgid(pid, pgrp);
7197 if (mode == FORK_BG) {
7198 backgndpid = pid; /* set $! */
7199 set_curjob(jp, CUR_RUNNING);
7202 struct procstat *ps = &jp->ps[jp->nprocs++];
7208 ps->cmd = commandtext(n);
7214 forkshell(struct job *jp, union node *n, int mode)
7218 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7221 TRACE(("Fork failed, errno=%d", errno));
7224 sh_error("Cannot fork");
7227 forkchild(jp, n, mode);
7229 forkparent(jp, n, mode, pid);
7234 * Wait for job to finish.
7236 * Under job control we have the problem that while a child process is
7237 * running interrupts generated by the user are sent to the child but not
7238 * to the shell. This means that an infinite loop started by an inter-
7239 * active user may be hard to kill. With job control turned off, an
7240 * interactive user may place an interactive program inside a loop. If
7241 * the interactive program catches interrupts, the user doesn't want
7242 * these interrupts to also abort the loop. The approach we take here
7243 * is to have the shell ignore interrupt signals while waiting for a
7244 * foreground process to terminate, and then send itself an interrupt
7245 * signal if the child process was terminated by an interrupt signal.
7246 * Unfortunately, some programs want to do a bit of cleanup and then
7247 * exit on interrupt; unless these processes terminate themselves by
7248 * sending a signal to themselves (instead of calling exit) they will
7249 * confuse this approach.
7251 * Called with interrupts off.
7255 waitforjob(struct job *jp)
7259 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7260 while (jp->state == JOBRUNNING) {
7261 dowait(DOWAIT_BLOCK, jp);
7266 xtcsetpgrp(ttyfd, rootpid);
7268 * This is truly gross.
7269 * If we're doing job control, then we did a TIOCSPGRP which
7270 * caused us (the shell) to no longer be in the controlling
7271 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7272 * intuit from the subprocess exit status whether a SIGINT
7273 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7278 if (jp->state == JOBDONE)
7286 * Do a wait system call. If job control is compiled in, we accept
7287 * stopped processes. If block is zero, we return a value of zero
7288 * rather than blocking.
7290 * System V doesn't have a non-blocking wait system call. It does
7291 * have a SIGCLD signal that is sent to a process when one of it's
7292 * children dies. The obvious way to use SIGCLD would be to install
7293 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7294 * was received, and have waitproc bump another counter when it got
7295 * the status of a process. Waitproc would then know that a wait
7296 * system call would not block if the two counters were different.
7297 * This approach doesn't work because if a process has children that
7298 * have not been waited for, System V will send it a SIGCLD when it
7299 * installs a signal handler for SIGCLD. What this means is that when
7300 * a child exits, the shell will be sent SIGCLD signals continuously
7301 * until is runs out of stack space, unless it does a wait call before
7302 * restoring the signal handler. The code below takes advantage of
7303 * this (mis)feature by installing a signal handler for SIGCLD and
7304 * then checking to see whether it was called. If there are any
7305 * children to be waited for, it will be.
7307 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7308 * waits at all. In this case, the user will not be informed when
7309 * a background process until the next time she runs a real program
7310 * (as opposed to running a builtin command or just typing return),
7311 * and the jobs command may give out of date information.
7315 waitproc(int block, int *status)
7325 return wait3(status, flags, (struct rusage *)NULL);
7329 * Wait for a process to terminate.
7333 dowait(int block, struct job *job)
7338 struct job *thisjob;
7341 TRACE(("dowait(%d) called\n", block));
7342 pid = waitproc(block, &status);
7343 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7348 for (jp = curjob; jp; jp = jp->prev_job) {
7349 struct procstat *sp;
7350 struct procstat *spend;
7351 if (jp->state == JOBDONE)
7354 spend = jp->ps + jp->nprocs;
7357 if (sp->pid == pid) {
7358 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7359 sp->status = status;
7362 if (sp->status == -1)
7365 if (state == JOBRUNNING)
7367 if (WIFSTOPPED(sp->status)) {
7368 jp->stopstatus = sp->status;
7372 } while (++sp < spend);
7377 if (!WIFSTOPPED(status))
7384 if (state != JOBRUNNING) {
7385 thisjob->changed = 1;
7387 if (thisjob->state != state) {
7388 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7389 thisjob->state = state;
7391 if (state == JOBSTOPPED) {
7392 set_curjob(thisjob, CUR_STOPPED);
7401 if (thisjob && thisjob == job) {
7405 len = sprint_status(s, status, 1);
7417 * return 1 if there are stopped jobs, otherwise 0
7430 if (jp && jp->state == JOBSTOPPED) {
7431 out2str("You have stopped jobs.\n");
7441 * Return a string identifying a command (to be printed by the
7446 static char *cmdnextc;
7449 commandtext(union node *n)
7453 STARTSTACKSTR(cmdnextc);
7455 name = stackblock();
7456 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7457 name, cmdnextc, cmdnextc));
7458 return savestr(name);
7462 cmdtxt(union node *n)
7465 struct nodelist *lp;
7477 lp = n->npipe.cmdlist;
7495 cmdtxt(n->nbinary.ch1);
7511 cmdtxt(n->nif.test);
7514 if (n->nif.elsepart) {
7517 n = n->nif.elsepart;
7533 cmdtxt(n->nbinary.ch1);
7543 cmdputs(n->nfor.var);
7545 cmdlist(n->nfor.args, 1);
7550 cmdputs(n->narg.text);
7554 cmdlist(n->ncmd.args, 1);
7555 cmdlist(n->ncmd.redirect, 0);
7568 cmdputs(n->ncase.expr->narg.text);
7570 for (np = n->ncase.cases; np; np = np->nclist.next) {
7571 cmdtxt(np->nclist.pattern);
7573 cmdtxt(np->nclist.body);
7599 s[0] = n->nfile.fd + '0';
7603 if (n->type == NTOFD || n->type == NFROMFD) {
7604 s[0] = n->ndup.dupfd + '0';
7615 cmdlist(union node *np, int sep)
7617 for (; np; np = np->narg.next) {
7621 if (sep && np->narg.next)
7627 cmdputs(const char *s)
7629 const char *p, *str;
7630 char c, cc[2] = " ";
7634 static const char vstype[VSTYPE + 1][4] = {
7635 "", "}", "-", "+", "?", "=",
7636 "%", "%%", "#", "##"
7638 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7640 while ((c = *p++) != 0) {
7648 if ((subtype & VSTYPE) == VSLENGTH)
7652 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7659 str = "\"}" + !(quoted & 1);
7666 case CTLBACKQ+CTLQUOTE:
7669 #ifdef CONFIG_ASH_MATH_SUPPORT
7684 if ((subtype & VSTYPE) != VSNORMAL)
7686 str = vstype[subtype & VSTYPE];
7687 if (subtype & VSNUL)
7696 /* These can only happen inside quotes */
7709 while ((c = *str++)) {
7714 USTPUTC('"', nextc);
7722 showpipe(struct job *jp, FILE *out)
7724 struct procstat *sp;
7725 struct procstat *spend;
7727 spend = jp->ps + jp->nprocs;
7728 for (sp = jp->ps + 1; sp < spend; sp++)
7729 fprintf(out, " | %s", sp->cmd);
7730 outcslow('\n', out);
7735 xtcsetpgrp(int fd, pid_t pgrp)
7737 if (tcsetpgrp(fd, pgrp))
7738 sh_error("Cannot set tty process group (%m)");
7743 getstatus(struct job *job) {
7747 status = job->ps[job->nprocs - 1].status;
7748 retval = WEXITSTATUS(status);
7749 if (!WIFEXITED(status)) {
7751 retval = WSTOPSIG(status);
7752 if (!WIFSTOPPED(status))
7755 /* XXX: limits number of signals */
7756 retval = WTERMSIG(status);
7758 if (retval == SIGINT)
7764 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7765 jobno(job), job->nprocs, status, retval));
7769 #ifdef CONFIG_ASH_MAIL
7773 * Routines to check for mail. (Perhaps make part of main.c?)
7776 #define MAXMBOXES 10
7778 /* times of mailboxes */
7779 static time_t mailtime[MAXMBOXES];
7780 /* Set if MAIL or MAILPATH is changed. */
7781 static int mail_var_path_changed;
7786 * Print appropriate message(s) if mail has arrived.
7787 * If mail_var_path_changed is set,
7788 * then the value of MAIL has mail_var_path_changed,
7789 * so we just update the values.
7799 struct stackmark smark;
7802 setstackmark(&smark);
7803 mpath = mpathset() ? mpathval() : mailval();
7804 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7805 p = padvance(&mpath, nullstr);
7810 for (q = p ; *q ; q++);
7815 q[-1] = '\0'; /* delete trailing '/' */
7816 if (stat(p, &statb) < 0) {
7820 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7823 pathopt ? pathopt : "you have mail"
7826 *mtp = statb.st_mtime;
7828 mail_var_path_changed = 0;
7829 popstackmark(&smark);
7834 changemail(const char *val)
7836 mail_var_path_changed++;
7839 #endif /* CONFIG_ASH_MAIL */
7845 static short profile_buf[16384];
7849 static int isloginsh;
7851 static void read_profile(const char *);
7854 * Main routine. We initialize things, parse the arguments, execute
7855 * profiles if we're a login shell, and then call cmdloop to execute
7856 * commands. The setjmp call sets up the location to jump to when an
7857 * exception occurs. When an exception occurs the variable "state"
7858 * is used to figure out how far we had gotten.
7862 ash_main(int argc, char **argv)
7866 struct jmploc jmploc;
7867 struct stackmark smark;
7870 dash_errno = __errno_location();
7874 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7877 if (setjmp(jmploc.loc)) {
7887 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7891 outcslow('\n', stderr);
7893 popstackmark(&smark);
7894 FORCEINTON; /* enable interrupts */
7907 trputs("Shell args: "); trargs(argv);
7911 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7912 rseed = rootpid + ((time_t)time((time_t *)0));
7915 setstackmark(&smark);
7916 procargs(argc, argv);
7917 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7919 const char *hp = lookupvar("HISTFILE");
7922 hp = lookupvar("HOME");
7924 char *defhp = concat_path_file(hp, ".ash_history");
7925 setvar("HISTFILE", defhp, 0);
7931 if (argv[0] && argv[0][0] == '-')
7935 read_profile("/etc/profile");
7938 read_profile(".profile");
7944 getuid() == geteuid() && getgid() == getegid() &&
7948 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7949 read_profile(shinit);
7955 evalstring(minusc, 0);
7957 if (sflag || minusc == NULL) {
7958 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7960 const char *hp = lookupvar("HISTFILE");
7963 load_history ( hp );
7966 state4: /* XXX ??? - why isn't this before the "if" statement */
7974 extern void _mcleanup(void);
7984 * Read and execute commands. "Top" is nonzero for the top level command
7985 * loop; it turns on prompting if the shell is interactive.
7992 struct stackmark smark;
7996 TRACE(("cmdloop(%d) called\n", top));
8000 setstackmark(&smark);
8003 showjobs(stderr, SHOW_CHANGED);
8008 #ifdef CONFIG_ASH_MAIL
8012 n = parsecmd(inter);
8013 /* showtree(n); DEBUG */
8015 if (!top || numeof >= 50)
8017 if (!stoppedjobs()) {
8020 out2str("\nUse \"exit\" to leave shell.\n");
8023 } else if (nflag == 0) {
8024 job_warning = (job_warning == 2) ? 1 : 0;
8028 popstackmark(&smark);
8033 return skip & SKIPEVAL;
8042 * Read /etc/profile or .profile. Return on error.
8046 read_profile(const char *name)
8050 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8062 * Read a file containing shell functions.
8066 readcmdfile(char *name)
8068 setinputfile(name, INPUT_PUSH_FILE);
8075 * Take commands from a file. To be compatible we should do a path
8076 * search for the file, which is necessary to find sub-commands.
8079 static inline char *
8080 find_dot_file(char *name)
8083 const char *path = pathval();
8086 /* don't try this for absolute or relative paths */
8087 if (strchr(name, '/'))
8090 while ((fullname = padvance(&path, name)) != NULL) {
8091 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8093 * Don't bother freeing here, since it will
8094 * be freed by the caller.
8098 stunalloc(fullname);
8101 /* not found in the PATH */
8102 sh_error(not_found_msg, name);
8106 static int dotcmd(int argc, char **argv)
8109 volatile struct shparam saveparam;
8112 for (sp = cmdenviron; sp; sp = sp->next)
8113 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8115 if (argc >= 2) { /* That's what SVR2 does */
8118 fullname = find_dot_file(argv[1]);
8121 saveparam = shellparam;
8122 shellparam.malloc = 0;
8123 shellparam.nparam = argc - 2;
8124 shellparam.p = argv + 2;
8127 setinputfile(fullname, INPUT_PUSH_FILE);
8128 commandname = fullname;
8133 freeparam(&shellparam);
8134 shellparam = saveparam;
8136 status = exitstatus;
8143 exitcmd(int argc, char **argv)
8148 exitstatus = number(argv[1]);
8153 #ifdef CONFIG_ASH_BUILTIN_ECHO
8155 echocmd(int argc, char **argv)
8157 return bb_echo(argc, argv);
8161 #ifdef CONFIG_ASH_BUILTIN_TEST
8163 testcmd(int argc, char **argv)
8165 return bb_test(argc, argv);
8172 * Same for malloc, realloc, but returns an error when out of space.
8176 ckrealloc(pointer p, size_t nbytes)
8178 p = realloc(p, nbytes);
8180 sh_error(bb_msg_memory_exhausted);
8185 ckmalloc(size_t nbytes)
8187 return ckrealloc(NULL, nbytes);
8191 * Make a copy of a string in safe storage.
8195 savestr(const char *s)
8197 char *p = strdup(s);
8199 sh_error(bb_msg_memory_exhausted);
8205 * Parse trees for commands are allocated in lifo order, so we use a stack
8206 * to make this more efficient, and also to avoid all sorts of exception
8207 * handling code to handle interrupts in the middle of a parse.
8209 * The size 504 was chosen because the Ultrix malloc handles that size
8215 stalloc(size_t nbytes)
8220 aligned = SHELL_ALIGN(nbytes);
8221 if (aligned > stacknleft) {
8224 struct stack_block *sp;
8226 blocksize = aligned;
8227 if (blocksize < MINSIZE)
8228 blocksize = MINSIZE;
8229 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8230 if (len < blocksize)
8231 sh_error(bb_msg_memory_exhausted);
8235 stacknxt = sp->space;
8236 stacknleft = blocksize;
8237 sstrend = stacknxt + blocksize;
8242 stacknxt += aligned;
8243 stacknleft -= aligned;
8249 stunalloc(pointer p)
8252 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8253 write(2, "stunalloc\n", 10);
8257 stacknleft += stacknxt - (char *)p;
8263 setstackmark(struct stackmark *mark)
8265 mark->stackp = stackp;
8266 mark->stacknxt = stacknxt;
8267 mark->stacknleft = stacknleft;
8268 mark->marknext = markp;
8274 popstackmark(struct stackmark *mark)
8276 struct stack_block *sp;
8279 markp = mark->marknext;
8280 while (stackp != mark->stackp) {
8285 stacknxt = mark->stacknxt;
8286 stacknleft = mark->stacknleft;
8287 sstrend = mark->stacknxt + mark->stacknleft;
8293 * When the parser reads in a string, it wants to stick the string on the
8294 * stack and only adjust the stack pointer when it knows how big the
8295 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8296 * of space on top of the stack and stackblocklen returns the length of
8297 * this block. Growstackblock will grow this space by at least one byte,
8298 * possibly moving it (like realloc). Grabstackblock actually allocates the
8299 * part of the block that has been used.
8303 growstackblock(void)
8307 newlen = stacknleft * 2;
8308 if (newlen < stacknleft)
8309 sh_error(bb_msg_memory_exhausted);
8313 if (stacknxt == stackp->space && stackp != &stackbase) {
8314 struct stack_block *oldstackp;
8315 struct stackmark *xmark;
8316 struct stack_block *sp;
8317 struct stack_block *prevstackp;
8323 prevstackp = sp->prev;
8324 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8325 sp = ckrealloc((pointer)sp, grosslen);
8326 sp->prev = prevstackp;
8328 stacknxt = sp->space;
8329 stacknleft = newlen;
8330 sstrend = sp->space + newlen;
8333 * Stack marks pointing to the start of the old block
8334 * must be relocated to point to the new block
8337 while (xmark != NULL && xmark->stackp == oldstackp) {
8338 xmark->stackp = stackp;
8339 xmark->stacknxt = stacknxt;
8340 xmark->stacknleft = stacknleft;
8341 xmark = xmark->marknext;
8345 char *oldspace = stacknxt;
8346 int oldlen = stacknleft;
8347 char *p = stalloc(newlen);
8349 /* free the space we just allocated */
8350 stacknxt = memcpy(p, oldspace, oldlen);
8351 stacknleft += newlen;
8356 grabstackblock(size_t len)
8358 len = SHELL_ALIGN(len);
8364 * The following routines are somewhat easier to use than the above.
8365 * The user declares a variable of type STACKSTR, which may be declared
8366 * to be a register. The macro STARTSTACKSTR initializes things. Then
8367 * the user uses the macro STPUTC to add characters to the string. In
8368 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8369 * grown as necessary. When the user is done, she can just leave the
8370 * string there and refer to it using stackblock(). Or she can allocate
8371 * the space for it using grabstackstr(). If it is necessary to allow
8372 * someone else to use the stack temporarily and then continue to grow
8373 * the string, the user should use grabstack to allocate the space, and
8374 * then call ungrabstr(p) to return to the previous mode of operation.
8376 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8377 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8378 * is space for at least one character.
8384 size_t len = stackblocksize();
8385 if (herefd >= 0 && len >= 1024) {
8386 bb_full_write(herefd, stackblock(), len);
8387 return stackblock();
8390 return stackblock() + len;
8394 * Called from CHECKSTRSPACE.
8398 makestrspace(size_t newlen, char *p)
8400 size_t len = p - stacknxt;
8401 size_t size = stackblocksize();
8406 size = stackblocksize();
8408 if (nleft >= newlen)
8412 return stackblock() + len;
8416 stnputs(const char *s, size_t n, char *p)
8418 p = makestrspace(n, p);
8419 p = mempcpy(p, s, n);
8424 stputs(const char *s, char *p)
8426 return stnputs(s, strlen(s), p);
8434 * number(s) Convert a string of digits to an integer.
8435 * is_number(s) Return true if s is a string of digits.
8439 * prefix -- see if pfx is a prefix of string.
8443 prefix(const char *string, const char *pfx)
8446 if (*pfx++ != *string++)
8449 return (char *) string;
8454 * Convert a string of digits to an integer, printing an error message on
8459 number(const char *s)
8463 sh_error(illnum, s);
8469 * Check for a valid number. This should be elsewhere.
8473 is_number(const char *p)
8478 } while (*++p != '\0');
8484 * Produce a possibly single quoted string suitable as input to the shell.
8485 * The return string is allocated on the stack.
8489 single_quote(const char *s) {
8498 len = strchrnul(s, '\'') - s;
8500 q = p = makestrspace(len + 3, p);
8503 q = mempcpy(q, s, len);
8509 len = strspn(s, "'");
8513 q = p = makestrspace(len + 3, p);
8516 q = mempcpy(q, s, len);
8525 return stackblock();
8529 * Like strdup but works with the ash stack.
8533 sstrdup(const char *p)
8535 size_t len = strlen(p) + 1;
8536 return memcpy(stalloc(len), p, len);
8541 calcsize(union node *n)
8545 funcblocksize += nodesize[n->type];
8548 calcsize(n->ncmd.redirect);
8549 calcsize(n->ncmd.args);
8550 calcsize(n->ncmd.assign);
8553 sizenodelist(n->npipe.cmdlist);
8558 calcsize(n->nredir.redirect);
8559 calcsize(n->nredir.n);
8566 calcsize(n->nbinary.ch2);
8567 calcsize(n->nbinary.ch1);
8570 calcsize(n->nif.elsepart);
8571 calcsize(n->nif.ifpart);
8572 calcsize(n->nif.test);
8575 funcstringsize += strlen(n->nfor.var) + 1;
8576 calcsize(n->nfor.body);
8577 calcsize(n->nfor.args);
8580 calcsize(n->ncase.cases);
8581 calcsize(n->ncase.expr);
8584 calcsize(n->nclist.body);
8585 calcsize(n->nclist.pattern);
8586 calcsize(n->nclist.next);
8590 sizenodelist(n->narg.backquote);
8591 funcstringsize += strlen(n->narg.text) + 1;
8592 calcsize(n->narg.next);
8599 calcsize(n->nfile.fname);
8600 calcsize(n->nfile.next);
8604 calcsize(n->ndup.vname);
8605 calcsize(n->ndup.next);
8609 calcsize(n->nhere.doc);
8610 calcsize(n->nhere.next);
8613 calcsize(n->nnot.com);
8620 sizenodelist(struct nodelist *lp)
8623 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8631 copynode(union node *n)
8638 funcblock = (char *) funcblock + nodesize[n->type];
8641 new->ncmd.redirect = copynode(n->ncmd.redirect);
8642 new->ncmd.args = copynode(n->ncmd.args);
8643 new->ncmd.assign = copynode(n->ncmd.assign);
8646 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8647 new->npipe.backgnd = n->npipe.backgnd;
8652 new->nredir.redirect = copynode(n->nredir.redirect);
8653 new->nredir.n = copynode(n->nredir.n);
8660 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8661 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8664 new->nif.elsepart = copynode(n->nif.elsepart);
8665 new->nif.ifpart = copynode(n->nif.ifpart);
8666 new->nif.test = copynode(n->nif.test);
8669 new->nfor.var = nodesavestr(n->nfor.var);
8670 new->nfor.body = copynode(n->nfor.body);
8671 new->nfor.args = copynode(n->nfor.args);
8674 new->ncase.cases = copynode(n->ncase.cases);
8675 new->ncase.expr = copynode(n->ncase.expr);
8678 new->nclist.body = copynode(n->nclist.body);
8679 new->nclist.pattern = copynode(n->nclist.pattern);
8680 new->nclist.next = copynode(n->nclist.next);
8684 new->narg.backquote = copynodelist(n->narg.backquote);
8685 new->narg.text = nodesavestr(n->narg.text);
8686 new->narg.next = copynode(n->narg.next);
8693 new->nfile.fname = copynode(n->nfile.fname);
8694 new->nfile.fd = n->nfile.fd;
8695 new->nfile.next = copynode(n->nfile.next);
8699 new->ndup.vname = copynode(n->ndup.vname);
8700 new->ndup.dupfd = n->ndup.dupfd;
8701 new->ndup.fd = n->ndup.fd;
8702 new->ndup.next = copynode(n->ndup.next);
8706 new->nhere.doc = copynode(n->nhere.doc);
8707 new->nhere.fd = n->nhere.fd;
8708 new->nhere.next = copynode(n->nhere.next);
8711 new->nnot.com = copynode(n->nnot.com);
8714 new->type = n->type;
8719 static struct nodelist *
8720 copynodelist(struct nodelist *lp)
8722 struct nodelist *start;
8723 struct nodelist **lpp;
8728 funcblock = (char *) funcblock +
8729 SHELL_ALIGN(sizeof(struct nodelist));
8730 (*lpp)->n = copynode(lp->n);
8732 lpp = &(*lpp)->next;
8740 nodesavestr(char *s)
8742 char *rtn = funcstring;
8744 funcstring = stpcpy(funcstring, s) + 1;
8750 * Free a parse tree.
8754 freefunc(struct funcnode *f)
8756 if (f && --f->count < 0)
8761 static void options(int);
8762 static void setoption(int, int);
8766 * Process the shell command line arguments.
8770 procargs(int argc, char **argv)
8773 const char *xminusc;
8780 for (i = 0; i < NOPTS; i++)
8786 if (*xargv == NULL) {
8788 sh_error(bb_msg_requires_arg, "-c");
8791 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8795 for (i = 0; i < NOPTS; i++)
8796 if (optlist[i] == 2)
8801 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8806 } else if (!sflag) {
8807 setinputfile(*xargv, 0);
8813 shellparam.p = xargv;
8814 #ifdef CONFIG_ASH_GETOPTS
8815 shellparam.optind = 1;
8816 shellparam.optoff = -1;
8818 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8820 shellparam.nparam++;
8833 setinteractive(iflag);
8839 minus_o(char *name, int val)
8844 out1str("Current option settings\n");
8845 for (i = 0; i < NOPTS; i++)
8846 out1fmt("%-16s%s\n", optnames(i),
8847 optlist[i] ? "on" : "off");
8849 for (i = 0; i < NOPTS; i++)
8850 if (equal(name, optnames(i))) {
8854 sh_error("Illegal option -o %s", name);
8859 * Process shell options. The global variable argptr contains a pointer
8860 * to the argument list; we advance it past the options.
8864 options(int cmdline)
8872 while ((p = *argptr) != NULL) {
8874 if ((c = *p++) == '-') {
8876 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8878 /* "-" means turn off -x and -v */
8881 /* "--" means reset params */
8882 else if (*argptr == NULL)
8885 break; /* "-" or "--" terminates options */
8887 } else if (c == '+') {
8893 while ((c = *p++) != '\0') {
8894 if (c == 'c' && cmdline) {
8895 minusc = p; /* command is after shell args*/
8896 } else if (c == 'o') {
8897 minus_o(*argptr, val);
8900 } else if (cmdline && (c == '-')) { // long options
8901 if (strcmp(p, "login") == 0)
8913 setoption(int flag, int val)
8917 for (i = 0; i < NOPTS; i++)
8918 if (optletters(i) == flag) {
8922 sh_error("Illegal option -%c", flag);
8929 * Set the shell parameters.
8933 setparam(char **argv)
8939 for (nparam = 0 ; argv[nparam] ; nparam++);
8940 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8942 *ap++ = savestr(*argv++);
8945 freeparam(&shellparam);
8946 shellparam.malloc = 1;
8947 shellparam.nparam = nparam;
8948 shellparam.p = newparam;
8949 #ifdef CONFIG_ASH_GETOPTS
8950 shellparam.optind = 1;
8951 shellparam.optoff = -1;
8957 * Free the list of positional parameters.
8961 freeparam(volatile struct shparam *param)
8965 if (param->malloc) {
8966 for (ap = param->p ; *ap ; ap++)
8975 * The shift builtin command.
8979 shiftcmd(int argc, char **argv)
8986 n = number(argv[1]);
8987 if (n > shellparam.nparam)
8988 sh_error("can't shift that many");
8990 shellparam.nparam -= n;
8991 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8992 if (shellparam.malloc)
8996 while ((*ap2++ = *ap1++) != NULL);
8997 #ifdef CONFIG_ASH_GETOPTS
8998 shellparam.optind = 1;
8999 shellparam.optoff = -1;
9008 * The set command builtin.
9012 setcmd(int argc, char **argv)
9015 return showvars(nullstr, 0, VUNSET);
9019 if (*argptr != NULL) {
9027 #ifdef CONFIG_ASH_GETOPTS
9029 getoptsreset(const char *value)
9031 shellparam.optind = number(value);
9032 shellparam.optoff = -1;
9036 #ifdef CONFIG_LOCALE_SUPPORT
9037 static void change_lc_all(const char *value)
9039 if (value != 0 && *value != 0)
9040 setlocale(LC_ALL, value);
9043 static void change_lc_ctype(const char *value)
9045 if (value != 0 && *value != 0)
9046 setlocale(LC_CTYPE, value);
9051 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9052 /* Roughly copied from bash.. */
9053 static void change_random(const char *value)
9056 /* "get", generate */
9059 rseed = rseed * 1103515245 + 12345;
9060 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9061 /* set without recursion */
9062 setvar(vrandom.text, buf, VNOFUNC);
9063 vrandom.flags &= ~VNOFUNC;
9066 rseed = strtoul(value, (char **)NULL, 10);
9072 #ifdef CONFIG_ASH_GETOPTS
9074 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9083 if(*param_optind < 1)
9085 optnext = optfirst + *param_optind - 1;
9087 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9090 p = optnext[-1] + *optoff;
9091 if (p == NULL || *p == '\0') {
9092 /* Current word is done, advance */
9094 if (p == NULL || *p != '-' || *++p == '\0') {
9101 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9106 for (q = optstr; *q != c; ) {
9108 if (optstr[0] == ':') {
9111 err |= setvarsafe("OPTARG", s, 0);
9113 fprintf(stderr, "Illegal option -%c\n", c);
9114 (void) unsetvar("OPTARG");
9124 if (*p == '\0' && (p = *optnext) == NULL) {
9125 if (optstr[0] == ':') {
9128 err |= setvarsafe("OPTARG", s, 0);
9131 fprintf(stderr, "No arg for -%c option\n", c);
9132 (void) unsetvar("OPTARG");
9140 err |= setvarsafe("OPTARG", p, 0);
9143 err |= setvarsafe("OPTARG", nullstr, 0);
9146 *optoff = p ? p - *(optnext - 1) : -1;
9147 *param_optind = optnext - optfirst + 1;
9148 fmtstr(s, sizeof(s), "%d", *param_optind);
9149 err |= setvarsafe("OPTIND", s, VNOFUNC);
9152 err |= setvarsafe(optvar, s, 0);
9163 * The getopts builtin. Shellparam.optnext points to the next argument
9164 * to be processed. Shellparam.optptr points to the next character to
9165 * be processed in the current argument. If shellparam.optnext is NULL,
9166 * then it's the first time getopts has been called.
9170 getoptscmd(int argc, char **argv)
9175 sh_error("Usage: getopts optstring var [arg]");
9176 else if (argc == 3) {
9177 optbase = shellparam.p;
9178 if (shellparam.optind > shellparam.nparam + 1) {
9179 shellparam.optind = 1;
9180 shellparam.optoff = -1;
9185 if (shellparam.optind > argc - 2) {
9186 shellparam.optind = 1;
9187 shellparam.optoff = -1;
9191 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9192 &shellparam.optoff);
9194 #endif /* CONFIG_ASH_GETOPTS */
9197 * XXX - should get rid of. have all builtins use getopt(3). the
9198 * library getopt must have the BSD extension static variable "optreset"
9199 * otherwise it can't be used within the shell safely.
9201 * Standard option processing (a la getopt) for builtin routines. The
9202 * only argument that is passed to nextopt is the option string; the
9203 * other arguments are unnecessary. It return the character, or '\0' on
9208 nextopt(const char *optstring)
9214 if ((p = optptr) == NULL || *p == '\0') {
9216 if (p == NULL || *p != '-' || *++p == '\0')
9219 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9223 for (q = optstring ; *q != c ; ) {
9225 sh_error("Illegal option -%c", c);
9230 if (*p == '\0' && (p = *argptr++) == NULL)
9231 sh_error("No arg for -%c option", c);
9243 outstr(const char *p, FILE *file)
9268 outcslow(int c, FILE *dest)
9278 out1fmt(const char *fmt, ...)
9285 r = vprintf(fmt, ap);
9293 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9300 ret = vsnprintf(outbuf, length, fmt, ap);
9312 * Shell command parser.
9315 #define EOFMARKLEN 79
9319 struct heredoc *next; /* next here document in list */
9320 union node *here; /* redirection node */
9321 char *eofmark; /* string indicating end of input */
9322 int striptabs; /* if set, strip leading tabs */
9327 static struct heredoc *heredoclist; /* list of here documents to read */
9330 static union node *list(int);
9331 static union node *andor(void);
9332 static union node *pipeline(void);
9333 static union node *command(void);
9334 static union node *simplecmd(void);
9335 static union node *makename(void);
9336 static void parsefname(void);
9337 static void parseheredoc(void);
9338 static char peektoken(void);
9339 static int readtoken(void);
9340 static int xxreadtoken(void);
9341 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9342 static int noexpand(char *);
9343 static void synexpect(int) ATTRIBUTE_NORETURN;
9344 static void synerror(const char *) ATTRIBUTE_NORETURN;
9345 static void setprompt(int);
9351 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9352 * valid parse tree indicating a blank line.)
9356 parsecmd(int interact)
9361 doprompt = interact;
9363 setprompt(doprompt);
9378 union node *n1, *n2, *n3;
9381 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9382 if (nlflag == 2 && peektoken())
9388 if (tok == TBACKGND) {
9389 if (n2->type == NPIPE) {
9390 n2->npipe.backgnd = 1;
9392 if (n2->type != NREDIR) {
9393 n3 = stalloc(sizeof(struct nredir));
9395 n3->nredir.redirect = NULL;
9398 n2->type = NBACKGND;
9405 n3 = (union node *)stalloc(sizeof (struct nbinary));
9407 n3->nbinary.ch1 = n1;
9408 n3->nbinary.ch2 = n2;
9424 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9432 pungetc(); /* push back EOF on input */
9448 union node *n1, *n2, *n3;
9453 if ((t = readtoken()) == TAND) {
9455 } else if (t == TOR) {
9461 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9463 n3 = (union node *)stalloc(sizeof (struct nbinary));
9465 n3->nbinary.ch1 = n1;
9466 n3->nbinary.ch2 = n2;
9476 union node *n1, *n2, *pipenode;
9477 struct nodelist *lp, *prev;
9481 TRACE(("pipeline: entered\n"));
9482 if (readtoken() == TNOT) {
9484 checkkwd = CHKKWD | CHKALIAS;
9488 if (readtoken() == TPIPE) {
9489 pipenode = (union node *)stalloc(sizeof (struct npipe));
9490 pipenode->type = NPIPE;
9491 pipenode->npipe.backgnd = 0;
9492 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9493 pipenode->npipe.cmdlist = lp;
9497 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9498 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9501 } while (readtoken() == TPIPE);
9507 n2 = (union node *)stalloc(sizeof (struct nnot));
9520 union node *n1, *n2;
9521 union node *ap, **app;
9522 union node *cp, **cpp;
9523 union node *redir, **rpp;
9530 switch (readtoken()) {
9535 n1 = (union node *)stalloc(sizeof (struct nif));
9537 n1->nif.test = list(0);
9538 if (readtoken() != TTHEN)
9540 n1->nif.ifpart = list(0);
9542 while (readtoken() == TELIF) {
9543 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9544 n2 = n2->nif.elsepart;
9546 n2->nif.test = list(0);
9547 if (readtoken() != TTHEN)
9549 n2->nif.ifpart = list(0);
9551 if (lasttoken == TELSE)
9552 n2->nif.elsepart = list(0);
9554 n2->nif.elsepart = NULL;
9562 n1 = (union node *)stalloc(sizeof (struct nbinary));
9563 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9564 n1->nbinary.ch1 = list(0);
9565 if ((got=readtoken()) != TDO) {
9566 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9569 n1->nbinary.ch2 = list(0);
9574 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9575 synerror("Bad for loop variable");
9576 n1 = (union node *)stalloc(sizeof (struct nfor));
9578 n1->nfor.var = wordtext;
9579 checkkwd = CHKKWD | CHKALIAS;
9580 if (readtoken() == TIN) {
9582 while (readtoken() == TWORD) {
9583 n2 = (union node *)stalloc(sizeof (struct narg));
9585 n2->narg.text = wordtext;
9586 n2->narg.backquote = backquotelist;
9588 app = &n2->narg.next;
9592 if (lasttoken != TNL && lasttoken != TSEMI)
9595 n2 = (union node *)stalloc(sizeof (struct narg));
9597 n2->narg.text = (char *)dolatstr;
9598 n2->narg.backquote = NULL;
9599 n2->narg.next = NULL;
9602 * Newline or semicolon here is optional (but note
9603 * that the original Bourne shell only allowed NL).
9605 if (lasttoken != TNL && lasttoken != TSEMI)
9608 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9609 if (readtoken() != TDO)
9611 n1->nfor.body = list(0);
9615 n1 = (union node *)stalloc(sizeof (struct ncase));
9617 if (readtoken() != TWORD)
9619 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9621 n2->narg.text = wordtext;
9622 n2->narg.backquote = backquotelist;
9623 n2->narg.next = NULL;
9625 checkkwd = CHKKWD | CHKALIAS;
9626 } while (readtoken() == TNL);
9627 if (lasttoken != TIN)
9629 cpp = &n1->ncase.cases;
9631 checkkwd = CHKNL | CHKKWD;
9634 if (lasttoken == TLP)
9636 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9638 app = &cp->nclist.pattern;
9640 *app = ap = (union node *)stalloc(sizeof (struct narg));
9642 ap->narg.text = wordtext;
9643 ap->narg.backquote = backquotelist;
9644 if (readtoken() != TPIPE)
9646 app = &ap->narg.next;
9649 ap->narg.next = NULL;
9650 if (lasttoken != TRP)
9652 cp->nclist.body = list(2);
9654 cpp = &cp->nclist.next;
9656 checkkwd = CHKNL | CHKKWD;
9657 if ((t = readtoken()) != TESAC) {
9659 synexpect(TENDCASE);
9667 n1 = (union node *)stalloc(sizeof (struct nredir));
9668 n1->type = NSUBSHELL;
9669 n1->nredir.n = list(0);
9670 n1->nredir.redirect = NULL;
9683 if (readtoken() != t)
9687 /* Now check for redirection which may follow command */
9688 checkkwd = CHKKWD | CHKALIAS;
9690 while (readtoken() == TREDIR) {
9691 *rpp = n2 = redirnode;
9692 rpp = &n2->nfile.next;
9698 if (n1->type != NSUBSHELL) {
9699 n2 = (union node *)stalloc(sizeof (struct nredir));
9704 n1->nredir.redirect = redir;
9713 union node *args, **app;
9714 union node *n = NULL;
9715 union node *vars, **vpp;
9716 union node **rpp, *redir;
9726 savecheckkwd = CHKALIAS;
9728 checkkwd = savecheckkwd;
9729 switch (readtoken()) {
9731 n = (union node *)stalloc(sizeof (struct narg));
9733 n->narg.text = wordtext;
9734 n->narg.backquote = backquotelist;
9735 if (savecheckkwd && isassignment(wordtext)) {
9737 vpp = &n->narg.next;
9740 app = &n->narg.next;
9745 *rpp = n = redirnode;
9746 rpp = &n->nfile.next;
9747 parsefname(); /* read name of redirection file */
9751 args && app == &args->narg.next &&
9754 struct builtincmd *bcmd;
9757 /* We have a function */
9758 if (readtoken() != TRP)
9760 name = n->narg.text;
9762 !goodname(name) || (
9763 (bcmd = find_builtin(name)) &&
9764 IS_BUILTIN_SPECIAL(bcmd)
9767 synerror("Bad function name");
9769 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9770 n->narg.next = command();
9783 n = (union node *)stalloc(sizeof (struct ncmd));
9785 n->ncmd.args = args;
9786 n->ncmd.assign = vars;
9787 n->ncmd.redirect = redir;
9796 n = (union node *)stalloc(sizeof (struct narg));
9798 n->narg.next = NULL;
9799 n->narg.text = wordtext;
9800 n->narg.backquote = backquotelist;
9804 void fixredir(union node *n, const char *text, int err)
9806 TRACE(("Fix redir %s %d\n", text, err));
9808 n->ndup.vname = NULL;
9810 if (is_digit(text[0]) && text[1] == '\0')
9811 n->ndup.dupfd = digit_val(text[0]);
9812 else if (text[0] == '-' && text[1] == '\0')
9817 synerror("Bad fd number");
9819 n->ndup.vname = makename();
9827 union node *n = redirnode;
9829 if (readtoken() != TWORD)
9831 if (n->type == NHERE) {
9832 struct heredoc *here = heredoc;
9838 TRACE(("Here document %d\n", n->type));
9839 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9840 synerror("Illegal eof marker for << redirection");
9841 rmescapes(wordtext);
9842 here->eofmark = wordtext;
9844 if (heredoclist == NULL)
9847 for (p = heredoclist ; p->next ; p = p->next);
9850 } else if (n->type == NTOFD || n->type == NFROMFD) {
9851 fixredir(n, wordtext, 0);
9853 n->nfile.fname = makename();
9859 * Input any here documents.
9865 struct heredoc *here;
9875 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9876 here->eofmark, here->striptabs);
9877 n = (union node *)stalloc(sizeof (struct narg));
9878 n->narg.type = NARG;
9879 n->narg.next = NULL;
9880 n->narg.text = wordtext;
9881 n->narg.backquote = backquotelist;
9882 here->here->nhere.doc = n;
9887 static char peektoken(void)
9893 return tokname_array[t][0];
9901 int alreadyseen = tokpushback;
9904 #ifdef CONFIG_ASH_ALIAS
9913 if (checkkwd & CHKNL) {
9920 if (t != TWORD || quoteflag) {
9925 * check for keywords
9927 if (checkkwd & CHKKWD) {
9928 const char *const *pp;
9930 if ((pp = findkwd(wordtext))) {
9931 lasttoken = t = pp - tokname_array;
9932 TRACE(("keyword %s recognized\n", tokname(t)));
9937 if (checkkwd & CHKALIAS) {
9938 #ifdef CONFIG_ASH_ALIAS
9940 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9942 pushstring(ap->val, ap);
9952 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9954 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9961 * Read the next input token.
9962 * If the token is a word, we set backquotelist to the list of cmds in
9963 * backquotes. We set quoteflag to true if any part of the word was
9965 * If the token is TREDIR, then we set redirnode to a structure containing
9967 * In all cases, the variable startlinno is set to the number of the line
9968 * on which the token starts.
9970 * [Change comment: here documents and internal procedures]
9971 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9972 * word parsing code into a separate routine. In this case, readtoken
9973 * doesn't need to have any internal procedures, but parseword does.
9974 * We could also make parseoperator in essence the main routine, and
9975 * have parseword (readtoken1?) handle both words and redirection.]
9978 #define NEW_xxreadtoken
9979 #ifdef NEW_xxreadtoken
9981 /* singles must be first! */
9982 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9984 static const char xxreadtoken_tokens[] = {
9985 TNL, TLP, TRP, /* only single occurrence allowed */
9986 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9987 TEOF, /* corresponds to trailing nul */
9988 TAND, TOR, TENDCASE, /* if double occurrence */
9991 #define xxreadtoken_doubles \
9992 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9993 #define xxreadtoken_singles \
9994 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9996 static int xxreadtoken(void)
10007 startlinno = plinno;
10008 for (;;) { /* until token or start of word found */
10011 if ((c != ' ') && (c != '\t')
10012 #ifdef CONFIG_ASH_ALIAS
10017 while ((c = pgetc()) != '\n' && c != PEOF);
10019 } else if (c == '\\') {
10020 if (pgetc() != '\n') {
10024 startlinno = ++plinno;
10029 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10034 needprompt = doprompt;
10037 p = strchr(xxreadtoken_chars, c);
10040 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10043 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10044 if (pgetc() == *p) { /* double occurrence? */
10045 p += xxreadtoken_doubles + 1;
10052 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10060 #define RETURN(token) return lasttoken = token
10074 startlinno = plinno;
10075 for (;;) { /* until token or start of word found */
10078 case ' ': case '\t':
10079 #ifdef CONFIG_ASH_ALIAS
10084 while ((c = pgetc()) != '\n' && c != PEOF);
10088 if (pgetc() == '\n') {
10089 startlinno = ++plinno;
10098 needprompt = doprompt;
10103 if (pgetc() == '&')
10108 if (pgetc() == '|')
10113 if (pgetc() == ';')
10126 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10129 #endif /* NEW_xxreadtoken */
10133 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10134 * is not NULL, read a here document. In the latter case, eofmark is the
10135 * word which marks the end of the document and striptabs is true if
10136 * leading tabs should be stripped from the document. The argument firstc
10137 * is the first character of the input token or document.
10139 * Because C does not have internal subroutines, I have simulated them
10140 * using goto's to implement the subroutine linkage. The following macros
10141 * will run code that appears at the end of readtoken1.
10144 #define CHECKEND() {goto checkend; checkend_return:;}
10145 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10146 #define PARSESUB() {goto parsesub; parsesub_return:;}
10147 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10148 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10149 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10152 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10157 char line[EOFMARKLEN + 1];
10158 struct nodelist *bqlist = 0;
10161 int varnest = 0; /* levels of variables expansion */
10162 int arinest = 0; /* levels of arithmetic expansion */
10163 int parenlevel = 0; /* levels of parens in arithmetic */
10164 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10166 int prevsyntax = 0; /* syntax before arithmetic */
10168 /* Avoid longjmp clobbering */
10174 (void) &parenlevel;
10177 (void) &prevsyntax;
10181 startlinno = plinno;
10183 if (syntax == DQSYNTAX)
10192 STARTSTACKSTR(out);
10193 loop: { /* for each line, until end of word */
10194 CHECKEND(); /* set c to PEOF if at end of here document */
10195 for (;;) { /* until end of line or end of word */
10196 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10197 switch(SIT(c, syntax)) {
10198 case CNL: /* '\n' */
10199 if (syntax == BASESYNTAX)
10200 goto endword; /* exit outer loop */
10206 goto loop; /* continue outer loop */
10211 if (eofmark == NULL || dblquote)
10212 USTPUTC(CTLESC, out);
10215 case CBACK: /* backslash */
10218 USTPUTC(CTLESC, out);
10219 USTPUTC('\\', out);
10221 } else if (c == '\n') {
10226 c != '\\' && c != '`' &&
10231 USTPUTC(CTLESC, out);
10232 USTPUTC('\\', out);
10234 if (SIT(c, SQSYNTAX) == CCTL)
10235 USTPUTC(CTLESC, out);
10243 if (eofmark == NULL) {
10244 USTPUTC(CTLQUOTEMARK, out);
10252 if (eofmark != NULL && arinest == 0 &&
10256 if (dqvarnest == 0) {
10257 syntax = BASESYNTAX;
10264 case CVAR: /* '$' */
10265 PARSESUB(); /* parse substitution */
10267 case CENDVAR: /* '}' */
10270 if (dqvarnest > 0) {
10273 USTPUTC(CTLENDVAR, out);
10278 #ifdef CONFIG_ASH_MATH_SUPPORT
10279 case CLP: /* '(' in arithmetic */
10283 case CRP: /* ')' in arithmetic */
10284 if (parenlevel > 0) {
10288 if (pgetc() == ')') {
10289 if (--arinest == 0) {
10290 USTPUTC(CTLENDARI, out);
10291 syntax = prevsyntax;
10292 if (syntax == DQSYNTAX)
10300 * unbalanced parens
10301 * (don't 2nd guess - no error)
10309 case CBQUOTE: /* '`' */
10313 goto endword; /* exit outer loop */
10318 goto endword; /* exit outer loop */
10319 #ifdef CONFIG_ASH_ALIAS
10329 #ifdef CONFIG_ASH_MATH_SUPPORT
10330 if (syntax == ARISYNTAX)
10331 synerror("Missing '))'");
10333 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10334 synerror("Unterminated quoted string");
10335 if (varnest != 0) {
10336 startlinno = plinno;
10338 synerror("Missing '}'");
10340 USTPUTC('\0', out);
10341 len = out - (char *)stackblock();
10342 out = stackblock();
10343 if (eofmark == NULL) {
10344 if ((c == '>' || c == '<')
10347 && (*out == '\0' || is_digit(*out))) {
10349 return lasttoken = TREDIR;
10354 quoteflag = quotef;
10355 backquotelist = bqlist;
10356 grabstackblock(len);
10358 return lasttoken = TWORD;
10359 /* end of readtoken routine */
10364 * Check to see whether we are at the end of the here document. When this
10365 * is called, c is set to the first character of the next input line. If
10366 * we are at the end of the here document, this routine sets the c to PEOF.
10371 #ifdef CONFIG_ASH_ALIAS
10377 while (c == '\t') {
10381 if (c == *eofmark) {
10382 if (pfgets(line, sizeof line) != NULL) {
10386 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10387 if (*p == '\n' && *q == '\0') {
10390 needprompt = doprompt;
10392 pushstring(line, NULL);
10397 goto checkend_return;
10402 * Parse a redirection operator. The variable "out" points to a string
10403 * specifying the fd to be redirected. The variable "c" contains the
10404 * first character of the redirection operator.
10411 np = (union node *)stalloc(sizeof (struct nfile));
10416 np->type = NAPPEND;
10418 np->type = NCLOBBER;
10425 } else { /* c == '<' */
10427 switch (c = pgetc()) {
10429 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10430 np = (union node *)stalloc(sizeof (struct nhere));
10434 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10435 heredoc->here = np;
10436 if ((c = pgetc()) == '-') {
10437 heredoc->striptabs = 1;
10439 heredoc->striptabs = 0;
10445 np->type = NFROMFD;
10449 np->type = NFROMTO;
10459 np->nfile.fd = digit_val(fd);
10461 goto parseredir_return;
10466 * Parse a substitution. At this point, we have read the dollar sign
10467 * and nothing else.
10475 static const char types[] = "}-+?=";
10479 c <= PEOA_OR_PEOF ||
10480 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10484 } else if (c == '(') { /* $(command) or $((arith)) */
10485 if (pgetc() == '(') {
10486 #ifdef CONFIG_ASH_MATH_SUPPORT
10489 synerror("We unsupport $((arith))");
10496 USTPUTC(CTLVAR, out);
10497 typeloc = out - (char *)stackblock();
10498 USTPUTC(VSNORMAL, out);
10499 subtype = VSNORMAL;
10503 if ((c = pgetc()) == '}')
10506 subtype = VSLENGTH;
10511 if (c > PEOA_OR_PEOF && is_name(c)) {
10515 } while (c > PEOA_OR_PEOF && is_in_name(c));
10516 } else if (is_digit(c)) {
10520 } while (is_digit(c));
10522 else if (is_special(c)) {
10527 badsub: synerror("Bad substitution");
10531 if (subtype == 0) {
10538 p = strchr(types, c);
10541 subtype = p - types + VSNORMAL;
10547 subtype = c == '#' ? VSTRIMLEFT :
10560 if (dblquote || arinest)
10562 *((char *)stackblock() + typeloc) = subtype | flags;
10563 if (subtype != VSNORMAL) {
10565 if (dblquote || arinest) {
10570 goto parsesub_return;
10575 * Called to parse command substitutions. Newstyle is set if the command
10576 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10577 * list of commands (passed by reference), and savelen is the number of
10578 * characters on the top of the stack which must be preserved.
10582 struct nodelist **nlpp;
10585 char *volatile str;
10586 struct jmploc jmploc;
10587 struct jmploc *volatile savehandler;
10589 int saveprompt = 0;
10591 (void) &saveprompt;
10594 savepbq = parsebackquote;
10595 if (setjmp(jmploc.loc)) {
10598 parsebackquote = 0;
10599 handler = savehandler;
10600 longjmp(handler->loc, 1);
10604 savelen = out - (char *)stackblock();
10606 str = ckmalloc(savelen);
10607 memcpy(str, stackblock(), savelen);
10609 savehandler = handler;
10613 /* We must read until the closing backquote, giving special
10614 treatment to some slashes, and then push the string and
10615 reread it as input, interpreting it normally. */
10622 STARTSTACKSTR(pout);
10627 switch (pc = pgetc()) {
10632 if ((pc = pgetc()) == '\n') {
10637 * If eating a newline, avoid putting
10638 * the newline into the new character
10639 * stream (via the STPUTC after the
10644 if (pc != '\\' && pc != '`' && pc != '$'
10645 && (!dblquote || pc != '"'))
10646 STPUTC('\\', pout);
10647 if (pc > PEOA_OR_PEOF) {
10653 #ifdef CONFIG_ASH_ALIAS
10656 startlinno = plinno;
10657 synerror("EOF in backquote substitution");
10661 needprompt = doprompt;
10670 STPUTC('\0', pout);
10671 psavelen = pout - (char *)stackblock();
10672 if (psavelen > 0) {
10673 pstr = grabstackstr(pout);
10674 setinputstring(pstr);
10679 nlpp = &(*nlpp)->next;
10680 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10681 (*nlpp)->next = NULL;
10682 parsebackquote = oldstyle;
10685 saveprompt = doprompt;
10692 doprompt = saveprompt;
10694 if (readtoken() != TRP)
10701 * Start reading from old file again, ignoring any pushed back
10702 * tokens left from the backquote parsing
10707 while (stackblocksize() <= savelen)
10709 STARTSTACKSTR(out);
10711 memcpy(out, str, savelen);
10712 STADJUST(savelen, out);
10718 parsebackquote = savepbq;
10719 handler = savehandler;
10720 if (arinest || dblquote)
10721 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10723 USTPUTC(CTLBACKQ, out);
10725 goto parsebackq_oldreturn;
10727 goto parsebackq_newreturn;
10730 #ifdef CONFIG_ASH_MATH_SUPPORT
10732 * Parse an arithmetic expansion (indicate start of one and set state)
10736 if (++arinest == 1) {
10737 prevsyntax = syntax;
10738 syntax = ARISYNTAX;
10739 USTPUTC(CTLARI, out);
10746 * we collapse embedded arithmetic expansion to
10747 * parenthesis, which should be equivalent
10751 goto parsearith_return;
10755 } /* end of readtoken */
10760 * Returns true if the text contains nothing to expand (no dollar signs
10765 noexpand(char *text)
10771 while ((c = *p++) != '\0') {
10772 if (c == CTLQUOTEMARK)
10776 else if (SIT(c, BASESYNTAX) == CCTL)
10784 * Return of a legal variable name (a letter or underscore followed by zero or
10785 * more letters, underscores, and digits).
10789 endofname(const char *name)
10797 if (! is_in_name(*p))
10805 * Called when an unexpected token is read during the parse. The argument
10806 * is the token that is expected, or -1 if more than one type of token can
10807 * occur at this point.
10810 static void synexpect(int token)
10815 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10817 sprintf(msg + l, " (expecting %s)", tokname(token));
10823 synerror(const char *msg)
10825 sh_error("Syntax error: %s", msg);
10831 * called by editline -- any expansions to the prompt
10832 * should be added here.
10835 #ifdef CONFIG_ASH_EXPAND_PRMT
10836 static const char *
10837 expandstr(const char *ps)
10841 /* XXX Fix (char *) cast. */
10842 setinputstring((char *)ps);
10843 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10846 n.narg.type = NARG;
10847 n.narg.next = NULL;
10848 n.narg.text = wordtext;
10849 n.narg.backquote = backquotelist;
10851 expandarg(&n, NULL, 0);
10852 return stackblock();
10856 static void setprompt(int whichprompt)
10858 const char *prompt;
10859 #ifdef CONFIG_ASH_EXPAND_PRMT
10860 struct stackmark smark;
10865 switch (whichprompt) {
10875 #ifdef CONFIG_ASH_EXPAND_PRMT
10876 setstackmark(&smark);
10877 stalloc(stackblocksize());
10879 putprompt(expandstr(prompt));
10880 #ifdef CONFIG_ASH_EXPAND_PRMT
10881 popstackmark(&smark);
10886 static const char *const *findkwd(const char *s)
10888 return bsearch(s, tokname_array + KWDOFFSET,
10889 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10890 sizeof(const char *), pstrcmp);
10896 * Code for dealing with input/output redirection.
10899 #define EMPTY -2 /* marks an unused slot in redirtab */
10901 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10903 # define PIPESIZE PIPE_BUF
10907 * Open a file in noclobber mode.
10908 * The code was copied from bash.
10911 noclobberopen(const char *fname)
10914 struct stat finfo, finfo2;
10917 * If the file exists and is a regular file, return an error
10920 r = stat(fname, &finfo);
10921 if (r == 0 && S_ISREG(finfo.st_mode)) {
10927 * If the file was not present (r != 0), make sure we open it
10928 * exclusively so that if it is created before we open it, our open
10929 * will fail. Make sure that we do not truncate an existing file.
10930 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10931 * file was not a regular file, we leave O_EXCL off.
10934 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10935 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10937 /* If the open failed, return the file descriptor right away. */
10942 * OK, the open succeeded, but the file may have been changed from a
10943 * non-regular file to a regular file between the stat and the open.
10944 * We are assuming that the O_EXCL open handles the case where FILENAME
10945 * did not exist and is symlinked to an existing file between the stat
10950 * If we can open it and fstat the file descriptor, and neither check
10951 * revealed that it was a regular file, and the file has not been
10952 * replaced, return the file descriptor.
10954 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10955 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10958 /* The file has been replaced. badness. */
10965 * Handle here documents. Normally we fork off a process to write the
10966 * data to a pipe. If the document is short, we can stuff the data in
10967 * the pipe without forking.
10971 openhere(union node *redir)
10977 sh_error("Pipe call failed");
10978 if (redir->type == NHERE) {
10979 len = strlen(redir->nhere.doc->narg.text);
10980 if (len <= PIPESIZE) {
10981 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10985 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10987 signal(SIGINT, SIG_IGN);
10988 signal(SIGQUIT, SIG_IGN);
10989 signal(SIGHUP, SIG_IGN);
10991 signal(SIGTSTP, SIG_IGN);
10993 signal(SIGPIPE, SIG_DFL);
10994 if (redir->type == NHERE)
10995 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10997 expandhere(redir->nhere.doc, pip[1]);
11006 openredirect(union node *redir)
11011 switch (redir->nfile.type) {
11013 fname = redir->nfile.expfname;
11014 if ((f = open(fname, O_RDONLY)) < 0)
11018 fname = redir->nfile.expfname;
11019 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11023 /* Take care of noclobber mode. */
11025 fname = redir->nfile.expfname;
11026 if ((f = noclobberopen(fname)) < 0)
11032 fname = redir->nfile.expfname;
11033 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11037 fname = redir->nfile.expfname;
11038 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11045 /* Fall through to eliminate warning. */
11052 f = openhere(redir);
11058 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11060 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11064 dupredirect(union node *redir, int f)
11066 int fd = redir->nfile.fd;
11068 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11069 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11070 copyfd(redir->ndup.dupfd, fd);
11083 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11084 * old file descriptors are stashed away so that the redirection can be
11085 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11086 * standard output, and the standard error if it becomes a duplicate of
11087 * stdout, is saved in memory.
11091 redirect(union node *redir, int flags)
11094 struct redirtab *sv;
11105 if (flags & REDIR_PUSH) {
11106 struct redirtab *q;
11107 q = ckmalloc(sizeof (struct redirtab));
11108 q->next = redirlist;
11110 q->nullredirs = nullredirs - 1;
11111 for (i = 0 ; i < 10 ; i++)
11112 q->renamed[i] = EMPTY;
11119 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11120 n->ndup.dupfd == fd)
11121 continue; /* redirect from/to same file descriptor */
11123 newfd = openredirect(n);
11126 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11127 i = fcntl(fd, F_DUPFD, 10);
11134 sh_error("%d: %m", fd);
11144 dupredirect(n, newfd);
11145 } while ((n = n->nfile.next));
11147 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11148 preverrout_fd = sv->renamed[2];
11153 * Undo the effects of the last redirection.
11159 struct redirtab *rp;
11162 if (--nullredirs >= 0)
11166 for (i = 0 ; i < 10 ; i++) {
11167 if (rp->renamed[i] != EMPTY) {
11170 copyfd(rp->renamed[i], i);
11172 close(rp->renamed[i]);
11175 redirlist = rp->next;
11176 nullredirs = rp->nullredirs;
11182 * Undo all redirections. Called on error or interrupt.
11186 * Discard all saved file descriptors.
11190 clearredir(int drop)
11202 * Copy a file descriptor to be >= to. Returns -1
11203 * if the source file descriptor is closed, EMPTY if there are no unused
11204 * file descriptors left.
11208 copyfd(int from, int to)
11212 newfd = fcntl(from, F_DUPFD, to);
11214 if (errno == EMFILE)
11217 sh_error("%d: %m", from);
11224 redirectsafe(union node *redir, int flags)
11227 volatile int saveint;
11228 struct jmploc *volatile savehandler = handler;
11229 struct jmploc jmploc;
11232 if (!(err = setjmp(jmploc.loc) * 2)) {
11234 redirect(redir, flags);
11236 handler = savehandler;
11237 if (err && exception != EXERROR)
11238 longjmp(handler->loc, 1);
11239 RESTOREINT(saveint);
11246 static void shtree(union node *, int, char *, FILE*);
11247 static void shcmd(union node *, FILE *);
11248 static void sharg(union node *, FILE *);
11249 static void indent(int, char *, FILE *);
11250 static void trstring(char *);
11254 showtree(union node *n)
11256 trputs("showtree called\n");
11257 shtree(n, 1, NULL, stdout);
11262 shtree(union node *n, int ind, char *pfx, FILE *fp)
11264 struct nodelist *lp;
11270 indent(ind, pfx, fp);
11281 shtree(n->nbinary.ch1, ind, NULL, fp);
11284 shtree(n->nbinary.ch2, ind, NULL, fp);
11292 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11297 if (n->npipe.backgnd)
11303 fprintf(fp, "<node type %d>", n->type);
11312 shcmd(union node *cmd, FILE *fp)
11320 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11326 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11329 switch (np->nfile.type) {
11330 case NTO: s = ">"; dftfd = 1; break;
11331 case NCLOBBER: s = ">|"; dftfd = 1; break;
11332 case NAPPEND: s = ">>"; dftfd = 1; break;
11333 case NTOFD: s = ">&"; dftfd = 1; break;
11334 case NFROM: s = "<"; dftfd = 0; break;
11335 case NFROMFD: s = "<&"; dftfd = 0; break;
11336 case NFROMTO: s = "<>"; dftfd = 0; break;
11337 default: s = "*error*"; dftfd = 0; break;
11339 if (np->nfile.fd != dftfd)
11340 fprintf(fp, "%d", np->nfile.fd);
11342 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11343 fprintf(fp, "%d", np->ndup.dupfd);
11345 sharg(np->nfile.fname, fp);
11354 sharg(union node *arg, FILE *fp)
11357 struct nodelist *bqlist;
11360 if (arg->type != NARG) {
11361 out1fmt("<node type %d>\n", arg->type);
11364 bqlist = arg->narg.backquote;
11365 for (p = arg->narg.text ; *p ; p++) {
11374 if (subtype == VSLENGTH)
11380 if (subtype & VSNUL)
11383 switch (subtype & VSTYPE) {
11402 case VSTRIMLEFTMAX:
11409 case VSTRIMRIGHTMAX:
11416 out1fmt("<subtype %d>", subtype);
11423 case CTLBACKQ|CTLQUOTE:
11426 shtree(bqlist->n, -1, NULL, fp);
11438 indent(int amount, char *pfx, FILE *fp)
11442 for (i = 0 ; i < amount ; i++) {
11443 if (pfx && i == amount - 1)
11464 putc(c, tracefile);
11468 trace(const char *fmt, ...)
11475 (void) vfprintf(tracefile, fmt, va);
11480 tracev(const char *fmt, va_list va)
11484 (void) vfprintf(tracefile, fmt, va);
11489 trputs(const char *s)
11493 fputs(s, tracefile);
11505 putc('"', tracefile);
11506 for (p = s ; *p ; p++) {
11508 case '\n': c = 'n'; goto backslash;
11509 case '\t': c = 't'; goto backslash;
11510 case '\r': c = 'r'; goto backslash;
11511 case '"': c = '"'; goto backslash;
11512 case '\\': c = '\\'; goto backslash;
11513 case CTLESC: c = 'e'; goto backslash;
11514 case CTLVAR: c = 'v'; goto backslash;
11515 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11516 case CTLBACKQ: c = 'q'; goto backslash;
11517 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11518 backslash: putc('\\', tracefile);
11519 putc(c, tracefile);
11522 if (*p >= ' ' && *p <= '~')
11523 putc(*p, tracefile);
11525 putc('\\', tracefile);
11526 putc(*p >> 6 & 03, tracefile);
11527 putc(*p >> 3 & 07, tracefile);
11528 putc(*p & 07, tracefile);
11533 putc('"', tracefile);
11545 putc(' ', tracefile);
11547 putc('\n', tracefile);
11563 /* leave open because libedit might be using it */
11566 scopy("./trace", s);
11568 if (!freopen(s, "a", tracefile)) {
11569 fprintf(stderr, "Can't re-open %s\n", s);
11574 if ((tracefile = fopen(s, "a")) == NULL) {
11575 fprintf(stderr, "Can't open %s\n", s);
11581 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11582 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11584 setlinebuf(tracefile);
11585 fputs("\nTracing started.\n", tracefile);
11593 * Sigmode records the current value of the signal handlers for the various
11594 * modes. A value of zero means that the current handler is not known.
11595 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11598 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11599 #define S_CATCH 2 /* signal is caught */
11600 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11601 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11602 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11607 * The trap builtin.
11611 trapcmd(int argc, char **argv)
11620 for (signo = 0 ; signo < NSIG ; signo++) {
11621 if (trap[signo] != NULL) {
11624 sn = u_signal_names(0, &signo, 0);
11627 out1fmt("trap -- %s %s\n",
11628 single_quote(trap[signo]), sn);
11638 if ((signo = decode_signal(*ap, 0)) < 0)
11639 sh_error("%s: bad trap", *ap);
11642 if (action[0] == '-' && action[1] == '\0')
11645 action = savestr(action);
11648 ckfree(trap[signo]);
11649 trap[signo] = action;
11660 * Clear traps on a fork.
11668 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11669 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11673 if (tp != &trap[0])
11674 setsignal(tp - trap);
11682 * Set the signal handler for the specified signal. The routine figures
11683 * out what it should be set to.
11687 setsignal(int signo)
11691 struct sigaction act;
11693 if ((t = trap[signo]) == NULL)
11695 else if (*t != '\0')
11699 if (rootshell && action == S_DFL) {
11702 if (iflag || minusc || sflag == 0)
11725 t = &sigmode[signo - 1];
11729 * current setting unknown
11731 if (sigaction(signo, 0, &act) == -1) {
11733 * Pretend it worked; maybe we should give a warning
11734 * here, but other shells don't. We don't alter
11735 * sigmode, so that we retry every time.
11739 if (act.sa_handler == SIG_IGN) {
11740 if (mflag && (signo == SIGTSTP ||
11741 signo == SIGTTIN || signo == SIGTTOU)) {
11742 tsig = S_IGN; /* don't hard ignore these */
11746 tsig = S_RESET; /* force to be set */
11749 if (tsig == S_HARD_IGN || tsig == action)
11753 act.sa_handler = onsig;
11756 act.sa_handler = SIG_IGN;
11759 act.sa_handler = SIG_DFL;
11763 sigfillset(&act.sa_mask);
11764 sigaction(signo, &act, 0);
11772 ignoresig(int signo)
11774 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11775 signal(signo, SIG_IGN);
11777 sigmode[signo - 1] = S_HARD_IGN;
11788 gotsig[signo - 1] = 1;
11789 pendingsigs = signo;
11791 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11800 * Called to execute a trap. Perhaps we should avoid entering new trap
11801 * handlers while we are executing a trap handler.
11813 savestatus = exitstatus;
11817 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11825 skip = evalstring(p, SKIPEVAL);
11826 exitstatus = savestatus;
11836 * Controls whether the shell is interactive or not.
11840 setinteractive(int on)
11842 static int is_interactive;
11844 if (++on == is_interactive)
11846 is_interactive = on;
11848 setsignal(SIGQUIT);
11849 setsignal(SIGTERM);
11850 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11851 if(is_interactive > 1) {
11852 /* Looks like they want an interactive shell */
11853 static int do_banner;
11857 "\n\n%s Built-in shell (ash)\n"
11858 "Enter 'help' for a list of built-in commands.\n\n",
11867 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11868 /*** List the available builtins ***/
11870 static int helpcmd(int argc, char **argv)
11874 out1fmt("\nBuilt-in commands:\n-------------------\n");
11875 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11876 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11877 builtincmd[i].name + 1);
11883 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11885 extern const struct BB_applet applets[];
11886 extern const size_t NUM_APPLETS;
11888 for (i = 0; i < NUM_APPLETS; i++) {
11890 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11899 return EXIT_SUCCESS;
11901 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11904 * Called to exit the shell.
11914 status = exitstatus;
11915 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11916 if (setjmp(loc.loc)) {
11917 if (exception == EXEXIT)
11922 if ((p = trap[0])) {
11928 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11929 if (iflag && rootshell) {
11930 const char *hp = lookupvar("HISTFILE");
11933 save_history ( hp );
11941 static int decode_signal(const char *string, int minsig)
11944 const char *name = u_signal_names(string, &signo, minsig);
11946 return name ? signo : -1;
11951 static struct var *vartab[VTABSIZE];
11953 static int vpcmp(const void *, const void *);
11954 static struct var **findvar(struct var **, const char *);
11957 * Initialize the variable symbol tables and import the environment
11961 #ifdef CONFIG_ASH_GETOPTS
11963 * Safe version of setvar, returns 1 on success 0 on failure.
11967 setvarsafe(const char *name, const char *val, int flags)
11970 volatile int saveint;
11971 struct jmploc *volatile savehandler = handler;
11972 struct jmploc jmploc;
11975 if (setjmp(jmploc.loc))
11979 setvar(name, val, flags);
11982 handler = savehandler;
11983 RESTOREINT(saveint);
11989 * Set the value of a variable. The flags argument is ored with the
11990 * flags of the variable. If val is NULL, the variable is unset.
11994 setvar(const char *name, const char *val, int flags)
12001 q = endofname(name);
12002 p = strchrnul(q, '=');
12003 namelen = p - name;
12004 if (!namelen || p != q)
12005 sh_error("%.*s: bad variable name", namelen, name);
12010 vallen = strlen(val);
12013 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12016 p = mempcpy(p, val, vallen);
12019 setvareq(nameeq, flags | VNOSAVE);
12025 * Same as setvar except that the variable and value are passed in
12026 * the first argument as name=value. Since the first argument will
12027 * be actually stored in the table, it should not be a string that
12029 * Called with interrupts off.
12033 setvareq(char *s, int flags)
12035 struct var *vp, **vpp;
12038 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12039 vp = *findvar(vpp, s);
12041 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12044 if (flags & VNOSAVE)
12047 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12050 if (flags & VNOSET)
12053 if (vp->func && (flags & VNOFUNC) == 0)
12054 (*vp->func)(strchrnul(s, '=') + 1);
12056 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12059 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12061 if (flags & VNOSET)
12064 vp = ckmalloc(sizeof (*vp));
12069 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12077 * Process a linked list of variable assignments.
12081 listsetvar(struct strlist *list_set_var, int flags)
12083 struct strlist *lp = list_set_var;
12089 setvareq(lp->text, flags);
12090 } while ((lp = lp->next));
12096 * Find the value of a variable. Returns NULL if not set.
12100 lookupvar(const char *name)
12104 if ((v = *findvar(hashvar(name), name))) {
12107 * Dynamic variables are implemented roughly the same way they are
12108 * in bash. Namely, they're "special" so long as they aren't unset.
12109 * As soon as they're unset, they're no longer dynamic, and dynamic
12110 * lookup will no longer happen at that point. -- PFM.
12112 if((v->flags & VDYNAMIC))
12115 if(!(v->flags & VUNSET))
12116 return strchrnul(v->text, '=') + 1;
12124 * Search the environment of a builtin command.
12128 bltinlookup(const char *name)
12130 struct strlist *sp;
12132 for (sp = cmdenviron ; sp ; sp = sp->next) {
12133 if (varequal(sp->text, name))
12134 return strchrnul(sp->text, '=') + 1;
12136 return lookupvar(name);
12141 * Generate a list of variables satisfying the given conditions.
12145 listvars(int on, int off, char ***end)
12156 for (vp = *vpp ; vp ; vp = vp->next)
12157 if ((vp->flags & mask) == on) {
12158 if (ep == stackstrend())
12159 ep = growstackstr();
12160 *ep++ = (char *) vp->text;
12162 } while (++vpp < vartab + VTABSIZE);
12163 if (ep == stackstrend())
12164 ep = growstackstr();
12168 return grabstackstr(ep);
12173 * POSIX requires that 'set' (but not export or readonly) output the
12174 * variables in lexicographic order - by the locale's collating order (sigh).
12175 * Maybe we could keep them in an ordered balanced binary tree
12176 * instead of hashed lists.
12177 * For now just roll 'em through qsort for printing...
12181 showvars(const char *sep_prefix, int on, int off)
12184 char **ep, **epend;
12186 ep = listvars(on, off, &epend);
12187 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12189 sep = *sep_prefix ? spcstr : sep_prefix;
12191 for (; ep < epend; ep++) {
12195 p = strchrnul(*ep, '=');
12198 q = single_quote(++p);
12200 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12209 * The export and readonly commands.
12213 exportcmd(int argc, char **argv)
12219 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12222 notp = nextopt("p") - 'p';
12223 if (notp && ((name = *(aptr = argptr)))) {
12225 if ((p = strchr(name, '=')) != NULL) {
12228 if ((vp = *findvar(hashvar(name), name))) {
12233 setvar(name, p, flag);
12234 } while ((name = *++aptr) != NULL);
12236 showvars(argv[0], flag, 0);
12243 * Make a variable a local variable. When a variable is made local, it's
12244 * value and flags are saved in a localvar structure. The saved values
12245 * will be restored when the shell function returns. We handle the name
12246 * "-" as a special case.
12250 mklocal(char *name)
12252 struct localvar *lvp;
12257 lvp = ckmalloc(sizeof (struct localvar));
12258 if (name[0] == '-' && name[1] == '\0') {
12260 p = ckmalloc(sizeof(optlist));
12261 lvp->text = memcpy(p, optlist, sizeof(optlist));
12266 vpp = hashvar(name);
12267 vp = *findvar(vpp, name);
12268 eq = strchr(name, '=');
12271 setvareq(name, VSTRFIXED);
12273 setvar(name, NULL, VSTRFIXED);
12274 vp = *vpp; /* the new variable */
12275 lvp->flags = VUNSET;
12277 lvp->text = vp->text;
12278 lvp->flags = vp->flags;
12279 vp->flags |= VSTRFIXED|VTEXTFIXED;
12285 lvp->next = localvars;
12291 * The "local" command.
12295 localcmd(int argc, char **argv)
12300 while ((name = *argv++) != NULL) {
12308 * Called after a function returns.
12309 * Interrupts must be off.
12315 struct localvar *lvp;
12318 while ((lvp = localvars) != NULL) {
12319 localvars = lvp->next;
12321 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12322 if (vp == NULL) { /* $- saved */
12323 memcpy(optlist, lvp->text, sizeof(optlist));
12326 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12327 unsetvar(vp->text);
12330 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12331 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12333 vp->flags = lvp->flags;
12334 vp->text = lvp->text;
12342 * The unset builtin command. We unset the function before we unset the
12343 * variable to allow a function to be unset when there is a readonly variable
12344 * with the same name.
12348 unsetcmd(int argc, char **argv)
12355 while ((i = nextopt("vf")) != '\0') {
12359 for (ap = argptr; *ap ; ap++) {
12374 * Unset the specified variable.
12378 unsetvar(const char *s)
12384 vpp = findvar(hashvar(s), s);
12388 int flags = vp->flags;
12391 if (flags & VREADONLY)
12394 vp->flags &= ~VDYNAMIC;
12396 if (flags & VUNSET)
12398 if ((flags & VSTRFIXED) == 0) {
12400 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12407 vp->flags &= ~VEXPORT;
12420 * Find the appropriate entry in the hash table from the name.
12423 static struct var **
12424 hashvar(const char *p)
12426 unsigned int hashval;
12428 hashval = ((unsigned char) *p) << 4;
12429 while (*p && *p != '=')
12430 hashval += (unsigned char) *p++;
12431 return &vartab[hashval % VTABSIZE];
12437 * Compares two strings up to the first = or '\0'. The first
12438 * string must be terminated by '='; the second may be terminated by
12439 * either '=' or '\0'.
12443 varcmp(const char *p, const char *q)
12447 while ((c = *p) == (d = *q)) {
12448 if (!c || c == '=')
12462 vpcmp(const void *a, const void *b)
12464 return varcmp(*(const char **)a, *(const char **)b);
12467 static struct var **
12468 findvar(struct var **vpp, const char *name)
12470 for (; *vpp; vpp = &(*vpp)->next) {
12471 if (varequal((*vpp)->text, name)) {
12479 #include <sys/times.h>
12481 static const unsigned char timescmd_str[] = {
12482 ' ', offsetof(struct tms, tms_utime),
12483 '\n', offsetof(struct tms, tms_stime),
12484 ' ', offsetof(struct tms, tms_cutime),
12485 '\n', offsetof(struct tms, tms_cstime),
12489 static int timescmd(int ac, char **av)
12491 long int clk_tck, s, t;
12492 const unsigned char *p;
12495 clk_tck = sysconf(_SC_CLK_TCK);
12500 t = *(clock_t *)(((char *) &buf) + p[1]);
12502 out1fmt("%ldm%ld.%.3lds%c",
12504 ((t - s * clk_tck) * 1000) / clk_tck,
12506 } while (*(p += 2));
12511 #ifdef CONFIG_ASH_MATH_SUPPORT
12513 dash_arith(const char *s)
12519 result = arith(s, &errcode);
12522 sh_error("exponent less than 0");
12523 else if (errcode == -2)
12524 sh_error("divide by zero");
12525 else if (errcode == -5)
12526 sh_error("expression recursion loop detected");
12537 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12538 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12540 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12544 letcmd(int argc, char **argv)
12551 sh_error("expression expected");
12552 for (ap = argv + 1; *ap; ap++) {
12553 i = dash_arith(*ap);
12558 #endif /* CONFIG_ASH_MATH_SUPPORT */
12563 * Miscellaneous builtins.
12569 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12570 typedef enum __rlimit_resource rlim_t;
12576 * The read builtin. The -e option causes backslashes to escape the
12577 * following character.
12579 * This uses unbuffered input, which may be avoidable in some cases.
12583 readcmd(int argc, char **argv)
12595 #if defined(CONFIG_ASH_READ_NCHARS)
12599 struct termios tty, old_tty;
12601 #if defined(CONFIG_ASH_READ_TIMEOUT)
12605 ts.tv_sec = ts.tv_usec = 0;
12610 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12611 while ((i = nextopt("p:rt:n:s")) != '\0')
12612 #elif defined(CONFIG_ASH_READ_NCHARS)
12613 while ((i = nextopt("p:rn:s")) != '\0')
12614 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12615 while ((i = nextopt("p:rt:")) != '\0')
12617 while ((i = nextopt("p:r")) != '\0')
12622 prompt = optionarg;
12624 #if defined(CONFIG_ASH_READ_NCHARS)
12626 nchars = strtol(optionarg, &p, 10);
12628 sh_error("invalid count");
12629 nch_flag = (nchars > 0);
12635 #if defined(CONFIG_ASH_READ_TIMEOUT)
12637 ts.tv_sec = strtol(optionarg, &p, 10);
12643 ts.tv_usec = strtol(p, &p2, 10);
12645 sh_error("invalid timeout");
12647 /* normalize to usec */
12649 sh_error("invalid timeout");
12650 while (scale++ < 6)
12654 sh_error("invalid timeout");
12656 if ( ! ts.tv_sec && ! ts.tv_usec)
12657 sh_error("invalid timeout");
12667 if (prompt && isatty(0)) {
12670 if (*(ap = argptr) == NULL)
12671 sh_error("arg count");
12672 if ((ifs = bltinlookup("IFS")) == NULL)
12674 #if defined(CONFIG_ASH_READ_NCHARS)
12675 if (nch_flag || silent) {
12676 tcgetattr(0, &tty);
12679 tty.c_lflag &= ~ICANON;
12680 tty.c_cc[VMIN] = nchars;
12683 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12686 tcsetattr(0, TCSANOW, &tty);
12689 #if defined(CONFIG_ASH_READ_TIMEOUT)
12690 if (ts.tv_sec || ts.tv_usec) {
12694 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12696 #if defined(CONFIG_ASH_READ_NCHARS)
12698 tcsetattr(0, TCSANOW, &old_tty);
12708 #if defined(CONFIG_ASH_READ_NCHARS)
12709 while (!nch_flag || nchars--)
12714 if (read(0, &c, 1) != 1) {
12726 if (!rflag && c == '\\') {
12732 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12736 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12738 setvar(*ap, stackblock(), 0);
12747 #if defined(CONFIG_ASH_READ_NCHARS)
12748 if (nch_flag || silent)
12749 tcsetattr(0, TCSANOW, &old_tty);
12753 /* Remove trailing blanks */
12754 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12756 setvar(*ap, stackblock(), 0);
12757 while (*++ap != NULL)
12758 setvar(*ap, nullstr, 0);
12763 static int umaskcmd(int argc, char **argv)
12765 static const char permuser[3] = "ugo";
12766 static const char permmode[3] = "rwx";
12767 static const short int permmask[] = {
12768 S_IRUSR, S_IWUSR, S_IXUSR,
12769 S_IRGRP, S_IWGRP, S_IXGRP,
12770 S_IROTH, S_IWOTH, S_IXOTH
12776 int symbolic_mode = 0;
12778 while (nextopt("S") != '\0') {
12787 if ((ap = *argptr) == NULL) {
12788 if (symbolic_mode) {
12792 for (i = 0; i < 3; i++) {
12795 *p++ = permuser[i];
12797 for (j = 0; j < 3; j++) {
12798 if ((mask & permmask[3 * i + j]) == 0) {
12799 *p++ = permmode[j];
12807 out1fmt("%.4o\n", mask);
12810 if (is_digit((unsigned char) *ap)) {
12813 if (*ap >= '8' || *ap < '0')
12814 sh_error(illnum, argv[1]);
12815 mask = (mask << 3) + (*ap - '0');
12816 } while (*++ap != '\0');
12819 mask = ~mask & 0777;
12820 if (!bb_parse_mode(ap, &mask)) {
12821 sh_error("Illegal mode: %s", ap);
12823 umask(~mask & 0777);
12832 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12833 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12834 * ash by J.T. Conklin.
12842 int factor; /* multiply by to get rlim_{cur,max} values */
12846 static const struct limits limits[] = {
12848 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12850 #ifdef RLIMIT_FSIZE
12851 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12854 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12856 #ifdef RLIMIT_STACK
12857 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12860 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12863 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12865 #ifdef RLIMIT_MEMLOCK
12866 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12868 #ifdef RLIMIT_NPROC
12869 { "process", RLIMIT_NPROC, 1, 'p' },
12871 #ifdef RLIMIT_NOFILE
12872 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12875 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12877 #ifdef RLIMIT_LOCKS
12878 { "locks", RLIMIT_LOCKS, 1, 'w' },
12880 { (char *) 0, 0, 0, '\0' }
12883 enum limtype { SOFT = 0x1, HARD = 0x2 };
12885 static void printlim(enum limtype how, const struct rlimit *limit,
12886 const struct limits *l)
12890 val = limit->rlim_max;
12892 val = limit->rlim_cur;
12894 if (val == RLIM_INFINITY)
12895 out1fmt("unlimited\n");
12898 out1fmt("%lld\n", (long long) val);
12903 ulimitcmd(int argc, char **argv)
12907 enum limtype how = SOFT | HARD;
12908 const struct limits *l;
12911 struct rlimit limit;
12914 while ((optc = nextopt("HSa"
12918 #ifdef RLIMIT_FSIZE
12924 #ifdef RLIMIT_STACK
12933 #ifdef RLIMIT_MEMLOCK
12936 #ifdef RLIMIT_NPROC
12939 #ifdef RLIMIT_NOFILE
12945 #ifdef RLIMIT_LOCKS
12963 for (l = limits; l->option != what; l++)
12966 set = *argptr ? 1 : 0;
12970 if (all || argptr[1])
12971 sh_error("too many arguments");
12972 if (strncmp(p, "unlimited\n", 9) == 0)
12973 val = RLIM_INFINITY;
12977 while ((c = *p++) >= '0' && c <= '9')
12979 val = (val * 10) + (long)(c - '0');
12980 if (val < (rlim_t) 0)
12984 sh_error("bad number");
12989 for (l = limits; l->name; l++) {
12990 getrlimit(l->cmd, &limit);
12991 out1fmt("%-20s ", l->name);
12992 printlim(how, &limit, l);
12997 getrlimit(l->cmd, &limit);
13000 limit.rlim_max = val;
13002 limit.rlim_cur = val;
13003 if (setrlimit(l->cmd, &limit) < 0)
13004 sh_error("error setting limit (%m)");
13006 printlim(how, &limit, l);
13012 #ifdef CONFIG_ASH_MATH_SUPPORT
13014 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13016 Permission is hereby granted, free of charge, to any person obtaining
13017 a copy of this software and associated documentation files (the
13018 "Software"), to deal in the Software without restriction, including
13019 without limitation the rights to use, copy, modify, merge, publish,
13020 distribute, sublicense, and/or sell copies of the Software, and to
13021 permit persons to whom the Software is furnished to do so, subject to
13022 the following conditions:
13024 The above copyright notice and this permission notice shall be
13025 included in all copies or substantial portions of the Software.
13027 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13028 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13029 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13030 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13031 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13032 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13033 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13036 /* This is my infix parser/evaluator. It is optimized for size, intended
13037 * as a replacement for yacc-based parsers. However, it may well be faster
13038 * than a comparable parser written in yacc. The supported operators are
13039 * listed in #defines below. Parens, order of operations, and error handling
13040 * are supported. This code is thread safe. The exact expression format should
13041 * be that which POSIX specifies for shells. */
13043 /* The code uses a simple two-stack algorithm. See
13044 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13045 * for a detailed explanation of the infix-to-postfix algorithm on which
13046 * this is based (this code differs in that it applies operators immediately
13047 * to the stack instead of adding them to a queue to end up with an
13050 /* To use the routine, call it with an expression string and error return
13054 * Aug 24, 2001 Manuel Novoa III
13056 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13058 * 1) In arith_apply():
13059 * a) Cached values of *numptr and &(numptr[-1]).
13060 * b) Removed redundant test for zero denominator.
13063 * a) Eliminated redundant code for processing operator tokens by moving
13064 * to a table-based implementation. Also folded handling of parens
13066 * b) Combined all 3 loops which called arith_apply to reduce generated
13067 * code size at the cost of speed.
13069 * 3) The following expressions were treated as valid by the original code:
13070 * 1() , 0! , 1 ( *3 ) .
13071 * These bugs have been fixed by internally enclosing the expression in
13072 * parens and then checking that all binary ops and right parens are
13073 * preceded by a valid expression (NUM_TOKEN).
13075 * Note: It may be desirable to replace Aaron's test for whitespace with
13076 * ctype's isspace() if it is used by another busybox applet or if additional
13077 * whitespace chars should be considered. Look below the "#include"s for a
13078 * precompiler test.
13082 * Aug 26, 2001 Manuel Novoa III
13084 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13086 * Merge in Aaron's comments previously posted to the busybox list,
13087 * modified slightly to take account of my changes to the code.
13092 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13094 * - allow access to variable,
13095 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13096 * - realize assign syntax (VAR=expr, +=, *= etc)
13097 * - realize exponentiation (** operator)
13098 * - realize comma separated - expr, expr
13099 * - realise ++expr --expr expr++ expr--
13100 * - realise expr ? expr : expr (but, second expr calculate always)
13101 * - allow hexadecimal and octal numbers
13102 * - was restored loses XOR operator
13103 * - remove one goto label, added three ;-)
13104 * - protect $((num num)) as true zero expr (Manuel`s error)
13105 * - always use special isspace(), see comment from bash ;-)
13109 #define arith_isspace(arithval) \
13110 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13113 typedef unsigned char operator;
13115 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13116 * precedence, and 3 high bits are an ID unique across operators of that
13117 * precedence. The ID portion is so that multiple operators can have the
13118 * same precedence, ensuring that the leftmost one is evaluated first.
13119 * Consider * and /. */
13121 #define tok_decl(prec,id) (((id)<<5)|(prec))
13122 #define PREC(op) ((op) & 0x1F)
13124 #define TOK_LPAREN tok_decl(0,0)
13126 #define TOK_COMMA tok_decl(1,0)
13128 #define TOK_ASSIGN tok_decl(2,0)
13129 #define TOK_AND_ASSIGN tok_decl(2,1)
13130 #define TOK_OR_ASSIGN tok_decl(2,2)
13131 #define TOK_XOR_ASSIGN tok_decl(2,3)
13132 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13133 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13134 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13135 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13137 #define TOK_MUL_ASSIGN tok_decl(3,0)
13138 #define TOK_DIV_ASSIGN tok_decl(3,1)
13139 #define TOK_REM_ASSIGN tok_decl(3,2)
13141 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13142 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13144 /* conditional is right associativity too */
13145 #define TOK_CONDITIONAL tok_decl(4,0)
13146 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13148 #define TOK_OR tok_decl(5,0)
13150 #define TOK_AND tok_decl(6,0)
13152 #define TOK_BOR tok_decl(7,0)
13154 #define TOK_BXOR tok_decl(8,0)
13156 #define TOK_BAND tok_decl(9,0)
13158 #define TOK_EQ tok_decl(10,0)
13159 #define TOK_NE tok_decl(10,1)
13161 #define TOK_LT tok_decl(11,0)
13162 #define TOK_GT tok_decl(11,1)
13163 #define TOK_GE tok_decl(11,2)
13164 #define TOK_LE tok_decl(11,3)
13166 #define TOK_LSHIFT tok_decl(12,0)
13167 #define TOK_RSHIFT tok_decl(12,1)
13169 #define TOK_ADD tok_decl(13,0)
13170 #define TOK_SUB tok_decl(13,1)
13172 #define TOK_MUL tok_decl(14,0)
13173 #define TOK_DIV tok_decl(14,1)
13174 #define TOK_REM tok_decl(14,2)
13176 /* exponent is right associativity */
13177 #define TOK_EXPONENT tok_decl(15,1)
13179 /* For now unary operators. */
13180 #define UNARYPREC 16
13181 #define TOK_BNOT tok_decl(UNARYPREC,0)
13182 #define TOK_NOT tok_decl(UNARYPREC,1)
13184 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13185 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13187 #define PREC_PRE (UNARYPREC+2)
13189 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13190 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13192 #define PREC_POST (UNARYPREC+3)
13194 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13195 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13197 #define SPEC_PREC (UNARYPREC+4)
13199 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13200 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13202 #define NUMPTR (*numstackptr)
13204 static inline int tok_have_assign(operator op)
13206 operator prec = PREC(op);
13208 convert_prec_is_assing(prec);
13209 return (prec == PREC(TOK_ASSIGN) ||
13210 prec == PREC_PRE || prec == PREC_POST);
13213 static inline int is_right_associativity(operator prec)
13215 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13216 prec == PREC(TOK_CONDITIONAL));
13220 typedef struct ARITCH_VAR_NUM {
13222 arith_t contidional_second_val;
13223 char contidional_second_val_initialized;
13224 char *var; /* if NULL then is regular number,
13225 else is variable name */
13229 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13231 struct CHK_VAR_RECURSIVE_LOOPED *next;
13232 } chk_var_recursive_looped_t;
13234 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13237 static int arith_lookup_val(v_n_t *t)
13240 const char * p = lookupvar(t->var);
13245 /* recursive try as expression */
13246 chk_var_recursive_looped_t *cur;
13247 chk_var_recursive_looped_t cur_save;
13249 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13250 if(strcmp(cur->var, t->var) == 0) {
13251 /* expression recursion loop detected */
13255 /* save current lookuped var name */
13256 cur = prev_chk_var_recursive;
13257 cur_save.var = t->var;
13258 cur_save.next = cur;
13259 prev_chk_var_recursive = &cur_save;
13261 t->val = arith (p, &errcode);
13262 /* restore previous ptr after recursiving */
13263 prev_chk_var_recursive = cur;
13266 /* allow undefined var as 0 */
13273 /* "applying" a token means performing it on the top elements on the integer
13274 * stack. For a unary operator it will only change the top element, but a
13275 * binary operator will pop two arguments and push a result */
13277 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13280 arith_t numptr_val, rez;
13281 int ret_arith_lookup_val;
13283 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13284 without arguments */
13285 numptr_m1 = NUMPTR - 1;
13287 /* check operand is var with noninteger value */
13288 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13289 if(ret_arith_lookup_val)
13290 return ret_arith_lookup_val;
13292 rez = numptr_m1->val;
13293 if (op == TOK_UMINUS)
13295 else if (op == TOK_NOT)
13297 else if (op == TOK_BNOT)
13299 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13301 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13303 else if (op != TOK_UPLUS) {
13304 /* Binary operators */
13306 /* check and binary operators need two arguments */
13307 if (numptr_m1 == numstack) goto err;
13309 /* ... and they pop one */
13312 if (op == TOK_CONDITIONAL) {
13313 if(! numptr_m1->contidional_second_val_initialized) {
13314 /* protect $((expr1 ? expr2)) without ": expr" */
13317 rez = numptr_m1->contidional_second_val;
13318 } else if(numptr_m1->contidional_second_val_initialized) {
13319 /* protect $((expr1 : expr2)) without "expr ? " */
13322 numptr_m1 = NUMPTR - 1;
13323 if(op != TOK_ASSIGN) {
13324 /* check operand is var with noninteger value for not '=' */
13325 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13326 if(ret_arith_lookup_val)
13327 return ret_arith_lookup_val;
13329 if (op == TOK_CONDITIONAL) {
13330 numptr_m1->contidional_second_val = rez;
13332 rez = numptr_m1->val;
13333 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13335 else if (op == TOK_OR)
13336 rez = numptr_val || rez;
13337 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13339 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13341 else if (op == TOK_AND)
13342 rez = rez && numptr_val;
13343 else if (op == TOK_EQ)
13344 rez = (rez == numptr_val);
13345 else if (op == TOK_NE)
13346 rez = (rez != numptr_val);
13347 else if (op == TOK_GE)
13348 rez = (rez >= numptr_val);
13349 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13350 rez >>= numptr_val;
13351 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13352 rez <<= numptr_val;
13353 else if (op == TOK_GT)
13354 rez = (rez > numptr_val);
13355 else if (op == TOK_LT)
13356 rez = (rez < numptr_val);
13357 else if (op == TOK_LE)
13358 rez = (rez <= numptr_val);
13359 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13361 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13363 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13365 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13367 else if (op == TOK_CONDITIONAL_SEP) {
13368 if (numptr_m1 == numstack) {
13369 /* protect $((expr : expr)) without "expr ? " */
13372 numptr_m1->contidional_second_val_initialized = op;
13373 numptr_m1->contidional_second_val = numptr_val;
13375 else if (op == TOK_CONDITIONAL) {
13377 numptr_val : numptr_m1->contidional_second_val;
13379 else if(op == TOK_EXPONENT) {
13381 return -3; /* exponent less than 0 */
13386 while(numptr_val--)
13391 else if(numptr_val==0) /* zero divisor check */
13393 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13395 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13398 if(tok_have_assign(op)) {
13401 if(numptr_m1->var == NULL) {
13405 /* save to shell variable */
13406 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13407 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13409 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13411 setvar(numptr_m1->var, buf, 0);
13412 /* after saving, make previous value for v++ or v-- */
13413 if(op == TOK_POST_INC)
13415 else if(op == TOK_POST_DEC)
13418 numptr_m1->val = rez;
13419 /* protect geting var value, is number now */
13420 numptr_m1->var = NULL;
13425 /* longest must first */
13426 static const char op_tokens[] = {
13427 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13428 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13429 '<','<', 0, TOK_LSHIFT,
13430 '>','>', 0, TOK_RSHIFT,
13431 '|','|', 0, TOK_OR,
13432 '&','&', 0, TOK_AND,
13433 '!','=', 0, TOK_NE,
13434 '<','=', 0, TOK_LE,
13435 '>','=', 0, TOK_GE,
13436 '=','=', 0, TOK_EQ,
13437 '|','=', 0, TOK_OR_ASSIGN,
13438 '&','=', 0, TOK_AND_ASSIGN,
13439 '*','=', 0, TOK_MUL_ASSIGN,
13440 '/','=', 0, TOK_DIV_ASSIGN,
13441 '%','=', 0, TOK_REM_ASSIGN,
13442 '+','=', 0, TOK_PLUS_ASSIGN,
13443 '-','=', 0, TOK_MINUS_ASSIGN,
13444 '-','-', 0, TOK_POST_DEC,
13445 '^','=', 0, TOK_XOR_ASSIGN,
13446 '+','+', 0, TOK_POST_INC,
13447 '*','*', 0, TOK_EXPONENT,
13451 '=', 0, TOK_ASSIGN,
13463 '?', 0, TOK_CONDITIONAL,
13464 ':', 0, TOK_CONDITIONAL_SEP,
13465 ')', 0, TOK_RPAREN,
13466 '(', 0, TOK_LPAREN,
13470 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13473 static arith_t arith (const char *expr, int *perrcode)
13475 char arithval; /* Current character under analysis */
13476 operator lasttok, op;
13479 const char *p = endexpression;
13482 size_t datasizes = strlen(expr) + 2;
13484 /* Stack of integers */
13485 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13486 * in any given correct or incorrect expression is left as an exercise to
13488 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13489 *numstackptr = numstack;
13490 /* Stack of operator tokens */
13491 operator *stack = alloca((datasizes) * sizeof(operator)),
13494 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13495 *perrcode = errcode = 0;
13498 if ((arithval = *expr) == 0) {
13499 if (p == endexpression) {
13500 /* Null expression. */
13504 /* This is only reached after all tokens have been extracted from the
13505 * input stream. If there are still tokens on the operator stack, they
13506 * are to be applied in order. At the end, there should be a final
13507 * result on the integer stack */
13509 if (expr != endexpression + 1) {
13510 /* If we haven't done so already, */
13511 /* append a closing right paren */
13512 expr = endexpression;
13513 /* and let the loop process it. */
13516 /* At this point, we're done with the expression. */
13517 if (numstackptr != numstack+1) {
13518 /* ... but if there isn't, it's bad */
13520 return (*perrcode = -1);
13522 if(numstack->var) {
13523 /* expression is $((var)) only, lookup now */
13524 errcode = arith_lookup_val(numstack);
13527 *perrcode = errcode;
13528 return numstack->val;
13530 /* Continue processing the expression. */
13531 if (arith_isspace(arithval)) {
13532 /* Skip whitespace */
13535 if((p = endofname(expr)) != expr) {
13536 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13538 numstackptr->var = alloca(var_name_size);
13539 safe_strncpy(numstackptr->var, expr, var_name_size);
13542 numstackptr->contidional_second_val_initialized = 0;
13546 } else if (is_digit(arithval)) {
13547 numstackptr->var = NULL;
13548 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13549 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13551 numstackptr->val = strtol(expr, (char **) &expr, 0);
13555 for(p = op_tokens; ; p++) {
13559 /* strange operator not found */
13562 for(o = expr; *p && *o == *p; p++)
13569 /* skip tail uncompared token */
13572 /* skip zero delim */
13577 /* post grammar: a++ reduce to num */
13578 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13581 /* Plus and minus are binary (not unary) _only_ if the last
13582 * token was as number, or a right paren (which pretends to be
13583 * a number, since it evaluates to one). Think about it.
13584 * It makes sense. */
13585 if (lasttok != TOK_NUM) {
13601 /* We don't want a unary operator to cause recursive descent on the
13602 * stack, because there can be many in a row and it could cause an
13603 * operator to be evaluated before its argument is pushed onto the
13604 * integer stack. */
13605 /* But for binary operators, "apply" everything on the operator
13606 * stack until we find an operator with a lesser priority than the
13607 * one we have just extracted. */
13608 /* Left paren is given the lowest priority so it will never be
13609 * "applied" in this way.
13610 * if associativity is right and priority eq, applied also skip
13613 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13614 /* not left paren or unary */
13615 if (lasttok != TOK_NUM) {
13616 /* binary op must be preceded by a num */
13619 while (stackptr != stack) {
13620 if (op == TOK_RPAREN) {
13621 /* The algorithm employed here is simple: while we don't
13622 * hit an open paren nor the bottom of the stack, pop
13623 * tokens and apply them */
13624 if (stackptr[-1] == TOK_LPAREN) {
13626 /* Any operator directly after a */
13628 /* close paren should consider itself binary */
13632 operator prev_prec = PREC(stackptr[-1]);
13634 convert_prec_is_assing(prec);
13635 convert_prec_is_assing(prev_prec);
13636 if (prev_prec < prec)
13638 /* check right assoc */
13639 if(prev_prec == prec && is_right_associativity(prec))
13642 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13643 if(errcode) goto ret;
13645 if (op == TOK_RPAREN) {
13650 /* Push this operator to the stack and remember it. */
13651 *stackptr++ = lasttok = op;
13658 #endif /* CONFIG_ASH_MATH_SUPPORT */
13662 const char *bb_applet_name = "debug stuff usage";
13663 int main(int argc, char **argv)
13665 return ash_main(argc, argv);
13670 * Copyright (c) 1989, 1991, 1993, 1994
13671 * The Regents of the University of California. All rights reserved.
13673 * This code is derived from software contributed to Berkeley by
13674 * Kenneth Almquist.
13676 * Redistribution and use in source and binary forms, with or without
13677 * modification, are permitted provided that the following conditions
13679 * 1. Redistributions of source code must retain the above copyright
13680 * notice, this list of conditions and the following disclaimer.
13681 * 2. Redistributions in binary form must reproduce the above copyright
13682 * notice, this list of conditions and the following disclaimer in the
13683 * documentation and/or other materials provided with the distribution.
13684 * 3. Neither the name of the University nor the names of its contributors
13685 * may be used to endorse or promote products derived from this software
13686 * without specific prior written permission.
13688 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13689 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13690 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13691 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13692 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13693 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13694 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13695 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13696 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13697 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF