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.
58 #include <sys/types.h>
59 #include <sys/ioctl.h>
60 #include <sys/param.h>
61 #include <sys/resource.h>
81 /*#include <stdint.h>*/
85 #ifdef CONFIG_ASH_JOB_CONTROL
91 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
99 static int *dash_errno;
101 #define errno (*dash_errno)
104 #if defined(__uClinux__)
105 #error "Do not even bother, ash will not run on uClinux"
109 #define _DIAGASSERT(assert_expr) assert(assert_expr)
111 #define _DIAGASSERT(assert_expr)
115 #ifdef CONFIG_ASH_ALIAS
128 static struct alias *lookupalias(const char *, int);
129 static int aliascmd(int, char **);
130 static int unaliascmd(int, char **);
131 static void rmaliases(void);
132 static int unalias(const char *);
133 static void printalias(const struct alias *);
139 static void setpwd(const char *, int);
145 * Types of operations (passed to the errmsg routine).
149 static const char not_found_msg[] = "%s: not found";
152 #define E_OPEN "No such file" /* opening a file */
153 #define E_CREAT "Directory nonexistent" /* creating a file */
154 #define E_EXEC not_found_msg+4 /* executing a program */
157 * We enclose jmp_buf in a structure so that we can declare pointers to
158 * jump locations. The global variable handler contains the location to
159 * jump to when an exception occurs, and the global variable exception
160 * contains a code identifying the exception. To implement nested
161 * exception handlers, the user should save the value of handler on entry
162 * to an inner scope, set handler to point to a jmploc structure for the
163 * inner scope, and restore handler on exit from the scope.
170 static struct jmploc *handler;
171 static int exception;
172 static volatile int suppressint;
173 static volatile sig_atomic_t intpending;
176 #define EXINT 0 /* SIGINT received */
177 #define EXERROR 1 /* a generic error */
178 #define EXSHELLPROC 2 /* execute a shell procedure */
179 #define EXEXEC 3 /* command execution failed */
180 #define EXEXIT 4 /* exit the shell */
181 #define EXSIG 5 /* trapped signal in wait(1) */
184 /* do we generate EXSIG events */
186 /* last pending signal */
187 static volatile sig_atomic_t pendingsigs;
190 * These macros allow the user to suspend the handling of interrupt signals
191 * over a period of time. This is similar to SIGHOLD to or sigblock, but
192 * much more efficient and portable. (But hacking the kernel is so much
193 * more fun than worrying about efficiency and portability. :-))
196 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
203 #define SAVEINT(v) ((v) = suppressint)
204 #define RESTOREINT(v) \
207 if ((suppressint = (v)) == 0 && intpending) onint(); \
218 /* EXSIG is turned off by evalbltin(). */
221 static void exraise(int) ATTRIBUTE_NORETURN;
222 static void onint(void) ATTRIBUTE_NORETURN;
224 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
225 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
227 static void sh_warnx(const char *, ...);
229 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
232 if (--suppressint == 0 && intpending) {
236 #define INTON inton()
237 static void forceinton(void)
243 #define FORCEINTON forceinton()
248 if (--suppressint == 0 && intpending) onint(); \
255 if (intpending) onint(); \
258 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
263 struct strlist *next;
269 struct strlist *list;
270 struct strlist **lastp;
276 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
277 #define EXP_TILDE 0x2 /* do normal tilde expansion */
278 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
279 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
280 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
281 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
282 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
283 #define EXP_WORD 0x80 /* expand word in parameter expansion */
284 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
288 static void expandarg(union node *, struct arglist *, int);
289 #define rmescapes(p) _rmescapes((p), 0)
290 static char *_rmescapes(char *, int);
291 static int casematch(union node *, char *);
293 #ifdef CONFIG_ASH_MATH_SUPPORT
294 static void expari(int);
299 static char *commandname; /* currently executing command */
300 static struct strlist *cmdenviron; /* environment for builtin command */
301 static int exitstatus; /* exit status of last command */
302 static int back_exitstatus; /* exit status of backquoted command */
305 struct backcmd { /* result of evalbackcmd */
306 int fd; /* file descriptor to read from */
307 char *buf; /* buffer */
308 int nleft; /* number of chars in buffer */
309 struct job *jp; /* job structure for command */
313 * This file was generated by the mknodes program.
349 union node *redirect;
356 struct nodelist *cmdlist;
363 union node *redirect;
378 union node *elsepart;
409 struct nodelist *backquote;
449 struct nredir nredir;
450 struct nbinary nbinary;
454 struct nclist nclist;
464 struct nodelist *next;
475 static void freefunc(struct funcnode *);
478 /* control characters in argument strings */
479 #define CTL_FIRST '\201' /* first 'special' character */
480 #define CTLESC '\201' /* escape next character */
481 #define CTLVAR '\202' /* variable defn */
482 #define CTLENDVAR '\203'
483 #define CTLBACKQ '\204'
484 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
485 /* CTLBACKQ | CTLQUOTE == '\205' */
486 #define CTLARI '\206' /* arithmetic expression */
487 #define CTLENDARI '\207'
488 #define CTLQUOTEMARK '\210'
489 #define CTL_LAST '\210' /* last 'special' character */
491 /* variable substitution byte (follows CTLVAR) */
492 #define VSTYPE 0x0f /* type of variable substitution */
493 #define VSNUL 0x10 /* colon--treat the empty string as unset */
494 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
496 /* values of VSTYPE field */
497 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
498 #define VSMINUS 0x2 /* ${var-text} */
499 #define VSPLUS 0x3 /* ${var+text} */
500 #define VSQUESTION 0x4 /* ${var?message} */
501 #define VSASSIGN 0x5 /* ${var=text} */
502 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
503 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
504 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
505 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
506 #define VSLENGTH 0xa /* ${#var} */
508 /* values of checkkwd variable */
513 #define IBUFSIZ (BUFSIZ + 1)
516 * NEOF is returned by parsecmd when it encounters an end of file. It
517 * must be distinct from NULL, so we use the address of a variable that
518 * happens to be handy.
520 static int plinno = 1; /* input line number */
522 /* number of characters left in input buffer */
523 static int parsenleft; /* copy of parsefile->nleft */
524 static int parselleft; /* copy of parsefile->lleft */
526 /* next character in input buffer */
527 static char *parsenextc; /* copy of parsefile->nextc */
530 struct strpush *prev; /* preceding string on stack */
533 #ifdef CONFIG_ASH_ALIAS
534 struct alias *ap; /* if push was associated with an alias */
536 char *string; /* remember the string since it may change */
540 struct parsefile *prev; /* preceding file on stack */
541 int linno; /* current line */
542 int fd; /* file descriptor (or -1 if string) */
543 int nleft; /* number of chars left in this line */
544 int lleft; /* number of chars left in this buffer */
545 char *nextc; /* next char in buffer */
546 char *buf; /* input buffer */
547 struct strpush *strpush; /* for pushing strings at this level */
548 struct strpush basestrpush; /* so pushing one is fast */
551 static struct parsefile basepf; /* top level input file */
552 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
553 static struct parsefile *parsefile = &basepf; /* current input file */
556 static int tokpushback; /* last token pushed back */
557 #define NEOF ((union node *)&tokpushback)
558 static int parsebackquote; /* nonzero if we are inside backquotes */
559 static int doprompt; /* if set, prompt the user */
560 static int needprompt; /* true if interactive and at start of line */
561 static int lasttoken; /* last token read */
562 static char *wordtext; /* text of last word returned by readtoken */
564 static struct nodelist *backquotelist;
565 static union node *redirnode;
566 static struct heredoc *heredoc;
567 static int quoteflag; /* set if (part of) last token was quoted */
568 static int startlinno; /* line # where last token started */
570 static union node *parsecmd(int);
571 static void fixredir(union node *, const char *, int);
572 static const char *const *findkwd(const char *);
573 static char *endofname(const char *);
577 typedef void *pointer;
579 static char nullstr[1]; /* zero length string */
580 static const char spcstr[] = " ";
581 static const char snlfmt[] = "%s\n";
582 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
583 static const char illnum[] = "Illegal number: %s";
584 static const char homestr[] = "HOME";
587 #define TRACE(param) trace param
588 #define TRACEV(param) tracev param
591 #define TRACEV(param)
594 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
595 #define __builtin_expect(x, expected_value) (x)
598 #define xlikely(x) __builtin_expect((x),1)
613 #define TENDBQUOTE 12
631 /* first char is indicating which tokens mark the end of a list */
632 static const char *const tokname_array[] = {
647 /* the following are keywords */
666 static const char *tokname(int tok)
672 sprintf(buf + (tok >= TSEMI), "%s%c",
673 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
680 * Most machines require the value returned from malloc to be aligned
681 * in some way. The following macro will get this right on many machines.
684 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
686 * It appears that grabstackstr() will barf with such alignments
687 * because stalloc() will return a string allocated in a new stackblock.
689 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
692 * This file was generated by the mksyntax program.
697 #define CWORD 0 /* character is nothing special */
698 #define CNL 1 /* newline character */
699 #define CBACK 2 /* a backslash character */
700 #define CSQUOTE 3 /* single quote */
701 #define CDQUOTE 4 /* double quote */
702 #define CENDQUOTE 5 /* a terminating quote */
703 #define CBQUOTE 6 /* backwards single quote */
704 #define CVAR 7 /* a dollar sign */
705 #define CENDVAR 8 /* a '}' character */
706 #define CLP 9 /* a left paren in arithmetic */
707 #define CRP 10 /* a right paren in arithmetic */
708 #define CENDFILE 11 /* end of file */
709 #define CCTL 12 /* like CWORD, except it must be escaped */
710 #define CSPCL 13 /* these terminate a word */
711 #define CIGN 14 /* character should be ignored */
713 #ifdef CONFIG_ASH_ALIAS
717 #define PEOA_OR_PEOF PEOA
721 #define PEOA_OR_PEOF PEOF
724 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
725 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
726 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
728 /* C99 say: "char" declaration may be signed or unsigned default */
729 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
732 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
733 * (assuming ascii char codes, as the original implementation did)
735 #define is_special(c) \
736 ( (((unsigned int)c) - 33 < 32) \
737 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
739 #define digit_val(c) ((c) - '0')
742 * This file was generated by the mksyntax program.
745 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
746 #define USE_SIT_FUNCTION
749 /* number syntax index */
750 #define BASESYNTAX 0 /* not in quotes */
751 #define DQSYNTAX 1 /* in double quotes */
752 #define SQSYNTAX 2 /* in single quotes */
753 #define ARISYNTAX 3 /* in arithmetic */
755 #ifdef CONFIG_ASH_MATH_SUPPORT
756 static const char S_I_T[][4] = {
757 #ifdef CONFIG_ASH_ALIAS
758 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
760 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
761 {CNL, CNL, CNL, CNL}, /* 2, \n */
762 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
763 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
764 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
765 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
766 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
767 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
768 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
769 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
770 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
771 #ifndef USE_SIT_FUNCTION
772 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
773 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
774 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
778 static const char S_I_T[][3] = {
779 #ifdef CONFIG_ASH_ALIAS
780 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
782 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
783 {CNL, CNL, CNL}, /* 2, \n */
784 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
785 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
786 {CVAR, CVAR, CWORD}, /* 5, $ */
787 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
788 {CSPCL, CWORD, CWORD}, /* 7, ( */
789 {CSPCL, CWORD, CWORD}, /* 8, ) */
790 {CBACK, CBACK, CCTL}, /* 9, \ */
791 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
792 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
793 #ifndef USE_SIT_FUNCTION
794 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
795 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
796 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
799 #endif /* CONFIG_ASH_MATH_SUPPORT */
801 #ifdef USE_SIT_FUNCTION
803 #define U_C(c) ((unsigned char)(c))
805 static int SIT(int c, int syntax)
807 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
808 #ifdef CONFIG_ASH_ALIAS
809 static const char syntax_index_table[] = {
810 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
811 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
812 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
816 static const char syntax_index_table[] = {
817 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
818 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
819 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
826 if (c == PEOF) /* 2^8+2 */
828 #ifdef CONFIG_ASH_ALIAS
829 if (c == PEOA) /* 2^8+1 */
833 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
836 s = strchr(spec_symbls, c);
837 if (s == 0 || *s == 0)
839 indx = syntax_index_table[(s - spec_symbls)];
841 return S_I_T[indx][syntax];
844 #else /* USE_SIT_FUNCTION */
846 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
848 #ifdef CONFIG_ASH_ALIAS
849 #define CSPCL_CIGN_CIGN_CIGN 0
850 #define CSPCL_CWORD_CWORD_CWORD 1
851 #define CNL_CNL_CNL_CNL 2
852 #define CWORD_CCTL_CCTL_CWORD 3
853 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
854 #define CVAR_CVAR_CWORD_CVAR 5
855 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
856 #define CSPCL_CWORD_CWORD_CLP 7
857 #define CSPCL_CWORD_CWORD_CRP 8
858 #define CBACK_CBACK_CCTL_CBACK 9
859 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
860 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
861 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
862 #define CWORD_CWORD_CWORD_CWORD 13
863 #define CCTL_CCTL_CCTL_CCTL 14
865 #define CSPCL_CWORD_CWORD_CWORD 0
866 #define CNL_CNL_CNL_CNL 1
867 #define CWORD_CCTL_CCTL_CWORD 2
868 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
869 #define CVAR_CVAR_CWORD_CVAR 4
870 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
871 #define CSPCL_CWORD_CWORD_CLP 6
872 #define CSPCL_CWORD_CWORD_CRP 7
873 #define CBACK_CBACK_CCTL_CBACK 8
874 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
875 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
876 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
877 #define CWORD_CWORD_CWORD_CWORD 12
878 #define CCTL_CCTL_CCTL_CCTL 13
881 static const char syntax_index_table[258] = {
882 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
883 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
884 #ifdef CONFIG_ASH_ALIAS
885 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
887 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
888 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
889 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
890 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
891 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
892 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
893 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
894 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
895 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
896 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
897 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
898 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
899 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
900 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
901 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
902 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
903 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
904 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
905 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
906 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
907 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
908 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
909 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
910 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
911 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
912 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
913 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
914 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
915 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
916 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
917 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
918 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
919 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
920 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
921 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
922 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
923 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
924 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
925 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
926 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
927 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
928 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
929 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
930 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
931 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
932 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
933 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
934 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
935 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
936 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
937 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
938 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
939 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
940 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
941 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
942 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
943 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
944 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
945 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
946 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
947 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
948 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
949 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
950 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
951 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
952 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
953 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
954 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
955 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
956 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
957 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
958 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
959 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
960 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
961 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
962 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
963 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
964 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
965 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
966 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
967 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
968 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
969 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
970 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
971 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
972 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
973 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
974 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
975 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
976 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
977 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
978 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
979 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
980 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
981 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
982 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
983 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
984 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
985 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
986 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
987 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
988 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
989 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
990 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
991 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
992 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
993 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
994 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
995 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
996 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
997 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
998 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
999 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1025 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1026 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1048 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1049 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1050 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1051 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1052 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1053 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1054 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1055 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1056 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1057 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1058 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1059 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1060 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1061 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1062 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1063 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1064 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1074 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1075 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1076 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1077 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1078 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1079 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1107 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1108 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1109 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1112 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1140 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1141 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1142 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1145 #endif /* USE_SIT_FUNCTION */
1152 static int funcblocksize; /* size of structures in function */
1153 static int funcstringsize; /* size of strings in node */
1154 static pointer funcblock; /* block to allocate function from */
1155 static char *funcstring; /* block to allocate strings from */
1157 static const short nodesize[26] = {
1158 SHELL_ALIGN(sizeof (struct ncmd)),
1159 SHELL_ALIGN(sizeof (struct npipe)),
1160 SHELL_ALIGN(sizeof (struct nredir)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nredir)),
1163 SHELL_ALIGN(sizeof (struct nbinary)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nbinary)),
1166 SHELL_ALIGN(sizeof (struct nif)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nfor)),
1170 SHELL_ALIGN(sizeof (struct ncase)),
1171 SHELL_ALIGN(sizeof (struct nclist)),
1172 SHELL_ALIGN(sizeof (struct narg)),
1173 SHELL_ALIGN(sizeof (struct narg)),
1174 SHELL_ALIGN(sizeof (struct nfile)),
1175 SHELL_ALIGN(sizeof (struct nfile)),
1176 SHELL_ALIGN(sizeof (struct nfile)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct ndup)),
1180 SHELL_ALIGN(sizeof (struct ndup)),
1181 SHELL_ALIGN(sizeof (struct nhere)),
1182 SHELL_ALIGN(sizeof (struct nhere)),
1183 SHELL_ALIGN(sizeof (struct nnot)),
1187 static void calcsize(union node *);
1188 static void sizenodelist(struct nodelist *);
1189 static union node *copynode(union node *);
1190 static struct nodelist *copynodelist(struct nodelist *);
1191 static char *nodesavestr(char *);
1194 static int evalstring(char *, int mask);
1195 union node; /* BLETCH for ansi C */
1196 static void evaltree(union node *, int);
1197 static void evalbackcmd(union node *, struct backcmd *);
1199 static int evalskip; /* set if we are skipping commands */
1200 static int skipcount; /* number of levels to skip */
1201 static int funcnest; /* depth of function calls */
1203 /* reasons for skipping commands (see comment on breakcmd routine) */
1204 #define SKIPBREAK (1 << 0)
1205 #define SKIPCONT (1 << 1)
1206 #define SKIPFUNC (1 << 2)
1207 #define SKIPFILE (1 << 3)
1208 #define SKIPEVAL (1 << 4)
1211 * This file was generated by the mkbuiltins program.
1215 static int bgcmd(int, char **);
1217 static int breakcmd(int, char **);
1218 static int cdcmd(int, char **);
1219 #ifdef CONFIG_ASH_CMDCMD
1220 static int commandcmd(int, char **);
1222 static int dotcmd(int, char **);
1223 static int evalcmd(int, char **);
1224 #ifdef CONFIG_ASH_BUILTIN_ECHO
1225 static int echocmd(int, char **);
1227 #ifdef CONFIG_ASH_BUILTIN_TEST
1228 static int testcmd(int, char **);
1230 static int execcmd(int, char **);
1231 static int exitcmd(int, char **);
1232 static int exportcmd(int, char **);
1233 static int falsecmd(int, char **);
1235 static int fgcmd(int, char **);
1237 #ifdef CONFIG_ASH_GETOPTS
1238 static int getoptscmd(int, char **);
1240 static int hashcmd(int, char **);
1241 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1242 static int helpcmd(int argc, char **argv);
1245 static int jobscmd(int, char **);
1247 #ifdef CONFIG_ASH_MATH_SUPPORT
1248 static int letcmd(int, char **);
1250 static int localcmd(int, char **);
1251 static int pwdcmd(int, char **);
1252 static int readcmd(int, char **);
1253 static int returncmd(int, char **);
1254 static int setcmd(int, char **);
1255 static int shiftcmd(int, char **);
1256 static int timescmd(int, char **);
1257 static int trapcmd(int, char **);
1258 static int truecmd(int, char **);
1259 static int typecmd(int, char **);
1260 static int umaskcmd(int, char **);
1261 static int unsetcmd(int, char **);
1262 static int waitcmd(int, char **);
1263 static int ulimitcmd(int, char **);
1265 static int killcmd(int, char **);
1270 #ifdef CONFIG_ASH_MAIL
1271 static void chkmail(void);
1272 static void changemail(const char *);
1277 /* values of cmdtype */
1278 #define CMDUNKNOWN -1 /* no entry in table for command */
1279 #define CMDNORMAL 0 /* command is an executable program */
1280 #define CMDFUNCTION 1 /* command is a shell function */
1281 #define CMDBUILTIN 2 /* command is a shell builtin */
1285 int (*builtin)(int, char **);
1286 /* unsigned flags; */
1290 #define COMMANDCMD (builtincmd + 5 + \
1291 2 * ENABLE_ASH_BUILTIN_TEST + \
1292 ENABLE_ASH_ALIAS + \
1293 ENABLE_ASH_JOB_CONTROL)
1294 #define EXECCMD (builtincmd + 7 + \
1295 2 * ENABLE_ASH_BUILTIN_TEST + \
1296 ENABLE_ASH_ALIAS + \
1297 ENABLE_ASH_JOB_CONTROL + \
1298 ENABLE_ASH_CMDCMD + \
1299 ENABLE_ASH_BUILTIN_ECHO)
1301 #define BUILTIN_NOSPEC "0"
1302 #define BUILTIN_SPECIAL "1"
1303 #define BUILTIN_REGULAR "2"
1304 #define BUILTIN_SPEC_REG "3"
1305 #define BUILTIN_ASSIGN "4"
1306 #define BUILTIN_SPEC_ASSG "5"
1307 #define BUILTIN_REG_ASSG "6"
1308 #define BUILTIN_SPEC_REG_ASSG "7"
1310 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1311 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1312 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1314 /* make sure to keep these in proper order since it is searched via bsearch() */
1315 static const struct builtincmd builtincmd[] = {
1316 { BUILTIN_SPEC_REG ".", dotcmd },
1317 { BUILTIN_SPEC_REG ":", truecmd },
1318 #ifdef CONFIG_ASH_BUILTIN_TEST
1319 { BUILTIN_REGULAR "[", testcmd },
1320 { BUILTIN_REGULAR "[[", testcmd },
1322 #ifdef CONFIG_ASH_ALIAS
1323 { BUILTIN_REG_ASSG "alias", aliascmd },
1326 { BUILTIN_REGULAR "bg", bgcmd },
1328 { BUILTIN_SPEC_REG "break", breakcmd },
1329 { BUILTIN_REGULAR "cd", cdcmd },
1330 { BUILTIN_NOSPEC "chdir", cdcmd },
1331 #ifdef CONFIG_ASH_CMDCMD
1332 { BUILTIN_REGULAR "command", commandcmd },
1334 { BUILTIN_SPEC_REG "continue", breakcmd },
1335 #ifdef CONFIG_ASH_BUILTIN_ECHO
1336 { BUILTIN_REGULAR "echo", echocmd },
1338 { BUILTIN_SPEC_REG "eval", evalcmd },
1339 { BUILTIN_SPEC_REG "exec", execcmd },
1340 { BUILTIN_SPEC_REG "exit", exitcmd },
1341 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1342 { BUILTIN_REGULAR "false", falsecmd },
1344 { BUILTIN_REGULAR "fg", fgcmd },
1346 #ifdef CONFIG_ASH_GETOPTS
1347 { BUILTIN_REGULAR "getopts", getoptscmd },
1349 { BUILTIN_NOSPEC "hash", hashcmd },
1350 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1351 { BUILTIN_NOSPEC "help", helpcmd },
1354 { BUILTIN_REGULAR "jobs", jobscmd },
1355 { BUILTIN_REGULAR "kill", killcmd },
1357 #ifdef CONFIG_ASH_MATH_SUPPORT
1358 { BUILTIN_NOSPEC "let", letcmd },
1360 { BUILTIN_ASSIGN "local", localcmd },
1361 { BUILTIN_NOSPEC "pwd", pwdcmd },
1362 { BUILTIN_REGULAR "read", readcmd },
1363 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1364 { BUILTIN_SPEC_REG "return", returncmd },
1365 { BUILTIN_SPEC_REG "set", setcmd },
1366 { BUILTIN_SPEC_REG "shift", shiftcmd },
1367 { BUILTIN_SPEC_REG "source", dotcmd },
1368 #ifdef CONFIG_ASH_BUILTIN_TEST
1369 { BUILTIN_REGULAR "test", testcmd },
1371 { BUILTIN_SPEC_REG "times", timescmd },
1372 { BUILTIN_SPEC_REG "trap", trapcmd },
1373 { BUILTIN_REGULAR "true", truecmd },
1374 { BUILTIN_NOSPEC "type", typecmd },
1375 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1376 { BUILTIN_REGULAR "umask", umaskcmd },
1377 #ifdef CONFIG_ASH_ALIAS
1378 { BUILTIN_REGULAR "unalias", unaliascmd },
1380 { BUILTIN_SPEC_REG "unset", unsetcmd },
1381 { BUILTIN_REGULAR "wait", waitcmd },
1384 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1386 static const char *safe_applets[] = {
1387 "[", "test", "echo", "cat",
1388 "ln", "cp", "touch", "mkdir", "rm",
1389 "cut", "hexdump", "awk", "sort",
1390 "find", "xargs", "ls", "dd",
1399 const struct builtincmd *cmd;
1400 struct funcnode *func;
1405 /* action to find_command() */
1406 #define DO_ERR 0x01 /* prints errors */
1407 #define DO_ABS 0x02 /* checks absolute paths */
1408 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1409 #define DO_ALTPATH 0x08 /* using alternate path */
1410 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1412 static const char *pathopt; /* set by padvance */
1414 static void shellexec(char **, const char *, int)
1416 static char *padvance(const char **, const char *);
1417 static void find_command(char *, struct cmdentry *, int, const char *);
1418 static struct builtincmd *find_builtin(const char *);
1419 static void hashcd(void);
1420 static void changepath(const char *);
1421 static void defun(char *, union node *);
1422 static void unsetfunc(const char *);
1424 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1425 typedef int64_t arith_t;
1426 #define arith_t_type (long long)
1428 typedef long arith_t;
1429 #define arith_t_type (long)
1432 #ifdef CONFIG_ASH_MATH_SUPPORT
1433 static arith_t dash_arith(const char *);
1434 static arith_t arith(const char *expr, int *perrcode);
1437 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1438 static unsigned long rseed;
1439 static void change_random(const char *);
1440 # ifndef DYNAMIC_VAR
1441 # define DYNAMIC_VAR
1447 static void reset(void);
1456 #define VEXPORT 0x01 /* variable is exported */
1457 #define VREADONLY 0x02 /* variable cannot be modified */
1458 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1459 #define VTEXTFIXED 0x08 /* text is statically allocated */
1460 #define VSTACK 0x10 /* text is allocated on the stack */
1461 #define VUNSET 0x20 /* the variable is not set */
1462 #define VNOFUNC 0x40 /* don't call the callback function */
1463 #define VNOSET 0x80 /* do not set variable - just readonly test */
1464 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1466 # define VDYNAMIC 0x200 /* dynamic variable */
1472 struct var *next; /* next entry in hash list */
1473 int flags; /* flags are defined above */
1474 const char *text; /* name=value */
1475 void (*func)(const char *); /* function to be called when */
1476 /* the variable gets set/unset */
1480 struct localvar *next; /* next local variable in list */
1481 struct var *vp; /* the variable that was made local */
1482 int flags; /* saved flags */
1483 const char *text; /* saved text */
1487 static struct localvar *localvars;
1493 #ifdef CONFIG_ASH_GETOPTS
1494 static void getoptsreset(const char *);
1497 #ifdef CONFIG_LOCALE_SUPPORT
1499 static void change_lc_all(const char *value);
1500 static void change_lc_ctype(const char *value);
1506 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1508 static const char defifsvar[] = "IFS= \t\n";
1509 #define defifs (defifsvar + 4)
1511 static const char defifs[] = " \t\n";
1515 static struct var varinit[] = {
1517 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1519 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1522 #ifdef CONFIG_ASH_MAIL
1523 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1524 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1527 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1528 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1529 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1530 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1531 #ifdef CONFIG_ASH_GETOPTS
1532 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1534 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1535 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1537 #ifdef CONFIG_LOCALE_SUPPORT
1538 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1539 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1541 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1542 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1546 #define vifs varinit[0]
1547 #ifdef CONFIG_ASH_MAIL
1548 #define vmail (&vifs)[1]
1549 #define vmpath (&vmail)[1]
1553 #define vpath (&vmpath)[1]
1554 #define vps1 (&vpath)[1]
1555 #define vps2 (&vps1)[1]
1556 #define vps4 (&vps2)[1]
1557 #define voptind (&vps4)[1]
1558 #ifdef CONFIG_ASH_GETOPTS
1559 #define vrandom (&voptind)[1]
1561 #define vrandom (&vps4)[1]
1563 #define defpath (defpathvar + 5)
1566 * The following macros access the values of the above variables.
1567 * They have to skip over the name. They return the null string
1568 * for unset variables.
1571 #define ifsval() (vifs.text + 4)
1572 #define ifsset() ((vifs.flags & VUNSET) == 0)
1573 #define mailval() (vmail.text + 5)
1574 #define mpathval() (vmpath.text + 9)
1575 #define pathval() (vpath.text + 5)
1576 #define ps1val() (vps1.text + 4)
1577 #define ps2val() (vps2.text + 4)
1578 #define ps4val() (vps4.text + 4)
1579 #define optindval() (voptind.text + 7)
1581 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1583 static void setvar(const char *, const char *, int);
1584 static void setvareq(char *, int);
1585 static void listsetvar(struct strlist *, int);
1586 static char *lookupvar(const char *);
1587 static char *bltinlookup(const char *);
1588 static char **listvars(int, int, char ***);
1589 #define environment() listvars(VEXPORT, VUNSET, 0)
1590 static int showvars(const char *, int, int);
1591 static void poplocalvars(void);
1592 static int unsetvar(const char *);
1593 #ifdef CONFIG_ASH_GETOPTS
1594 static int setvarsafe(const char *, const char *, int);
1596 static int varcmp(const char *, const char *);
1597 static struct var **hashvar(const char *);
1600 static int varequal(const char *a, const char *b) {
1601 return !varcmp(a, b);
1605 static int loopnest; /* current loop nesting level */
1608 * The parsefile structure pointed to by the global variable parsefile
1609 * contains information about the current file being read.
1614 struct redirtab *next;
1619 static struct redirtab *redirlist;
1620 static int nullredirs;
1622 extern char **environ;
1627 static void outstr(const char *, FILE *);
1628 static void outcslow(int, FILE *);
1629 static void flushall(void);
1630 static void flusherr(void);
1631 static int out1fmt(const char *, ...)
1632 __attribute__((__format__(__printf__,1,2)));
1633 static int fmtstr(char *, size_t, const char *, ...)
1634 __attribute__((__format__(__printf__,3,4)));
1636 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1639 static void out1str(const char *p)
1644 static void out2str(const char *p)
1651 * Initialization code.
1655 * This routine initializes the builtin variables.
1658 static void initvar(void)
1665 * PS1 depends on uid
1667 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1668 vps1.text = "PS1=\\w \\$ ";
1671 vps1.text = "PS1=# ";
1674 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1676 vpp = hashvar(vp->text);
1679 } while (++vp < end);
1682 static void init(void)
1687 basepf.nextc = basepf.buf = basebuf;
1692 signal(SIGCHLD, SIG_DFL);
1700 struct stat st1, st2;
1703 for (envp = environ ; envp && *envp ; envp++) {
1704 if (strchr(*envp, '=')) {
1705 setvareq(*envp, VEXPORT|VTEXTFIXED);
1709 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1710 setvar("PPID", ppid, 0);
1712 p = lookupvar("PWD");
1714 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1715 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1721 /* PEOF (the end of file marker) */
1724 INPUT_PUSH_FILE = 1,
1725 INPUT_NOFILE_OK = 2,
1729 * The input line number. Input.c just defines this variable, and saves
1730 * and restores it when files are pushed and popped. The user of this
1731 * package must set its value.
1734 static int pgetc(void);
1735 static int pgetc2(void);
1736 static int preadbuffer(void);
1737 static void pungetc(void);
1738 static void pushstring(char *, void *);
1739 static void popstring(void);
1740 static void setinputfd(int, int);
1741 static void setinputstring(char *);
1742 static void popfile(void);
1743 static void popallfiles(void);
1744 static void closescript(void);
1750 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1753 #define FORK_NOJOB 2
1755 /* mode flags for showjob(s) */
1756 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1757 #define SHOW_PID 0x04 /* include process pid */
1758 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1762 * A job structure contains information about a job. A job is either a
1763 * single process or a set of processes contained in a pipeline. In the
1764 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1769 pid_t pid; /* process id */
1770 int status; /* last process status from wait() */
1771 char *cmd; /* text of command being run */
1775 struct procstat ps0; /* status of process */
1776 struct procstat *ps; /* status or processes when more than one */
1778 int stopstatus; /* status of a stopped job */
1781 nprocs: 16, /* number of processes */
1783 #define JOBRUNNING 0 /* at least one proc running */
1784 #define JOBSTOPPED 1 /* all procs are stopped */
1785 #define JOBDONE 2 /* all procs are completed */
1787 sigint: 1, /* job was killed by SIGINT */
1788 jobctl: 1, /* job running under job control */
1790 waited: 1, /* true if this entry has been waited for */
1791 used: 1, /* true if this entry is in used */
1792 changed: 1; /* true if status has changed */
1793 struct job *prev_job; /* previous job */
1796 static pid_t backgndpid; /* pid of last background process */
1797 static int job_warning; /* user was warned about stopped jobs */
1799 static int jobctl; /* true if doing job control */
1802 static struct job *makejob(union node *, int);
1803 static int forkshell(struct job *, union node *, int);
1804 static int waitforjob(struct job *);
1805 static int stoppedjobs(void);
1808 #define setjobctl(on) /* do nothing */
1810 static void setjobctl(int);
1811 static void showjobs(FILE *, int);
1817 /* pid of main shell */
1819 /* shell level: 0 for the main shell, 1 for its children, and so on */
1821 #define rootshell (!shlvl)
1823 static void readcmdfile(char *);
1824 static int cmdloop(int);
1830 struct stack_block *stackp;
1833 struct stackmark *marknext;
1836 /* minimum size of a block */
1837 #define MINSIZE SHELL_ALIGN(504)
1839 struct stack_block {
1840 struct stack_block *prev;
1841 char space[MINSIZE];
1844 static struct stack_block stackbase;
1845 static struct stack_block *stackp = &stackbase;
1846 static struct stackmark *markp;
1847 static char *stacknxt = stackbase.space;
1848 static size_t stacknleft = MINSIZE;
1849 static char *sstrend = stackbase.space + MINSIZE;
1850 static int herefd = -1;
1853 static pointer ckmalloc(size_t);
1854 static pointer ckrealloc(pointer, size_t);
1855 static char *savestr(const char *);
1856 static pointer stalloc(size_t);
1857 static void stunalloc(pointer);
1858 static void setstackmark(struct stackmark *);
1859 static void popstackmark(struct stackmark *);
1860 static void growstackblock(void);
1861 static void *growstackstr(void);
1862 static char *makestrspace(size_t, char *);
1863 static char *stnputs(const char *, size_t, char *);
1864 static char *stputs(const char *, char *);
1867 static char *_STPUTC(int c, char *p) {
1874 #define stackblock() ((void *)stacknxt)
1875 #define stackblocksize() stacknleft
1876 #define STARTSTACKSTR(p) ((p) = stackblock())
1877 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1878 #define CHECKSTRSPACE(n, p) \
1882 size_t m = sstrend - q; \
1884 (p) = makestrspace(l, q); \
1887 #define USTPUTC(c, p) (*p++ = (c))
1888 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1889 #define STUNPUTC(p) (--p)
1890 #define STTOPC(p) p[-1]
1891 #define STADJUST(amount, p) (p += (amount))
1893 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1894 #define ungrabstackstr(s, p) stunalloc((s))
1895 #define stackstrend() ((void *)sstrend)
1897 #define ckfree(p) free((pointer)(p))
1902 #define DOLATSTRLEN 4
1904 static char *prefix(const char *, const char *);
1905 static int number(const char *);
1906 static int is_number(const char *);
1907 static char *single_quote(const char *);
1908 static char *sstrdup(const char *);
1910 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1911 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1916 int nparam; /* # of positional parameters (without $0) */
1917 unsigned char malloc; /* if parameter list dynamically allocated */
1918 char **p; /* parameter list */
1919 #ifdef CONFIG_ASH_GETOPTS
1920 int optind; /* next parameter to be processed by getopts */
1921 int optoff; /* used by getopts */
1926 #define eflag optlist[0]
1927 #define fflag optlist[1]
1928 #define Iflag optlist[2]
1929 #define iflag optlist[3]
1930 #define mflag optlist[4]
1931 #define nflag optlist[5]
1932 #define sflag optlist[6]
1933 #define xflag optlist[7]
1934 #define vflag optlist[8]
1935 #define Cflag optlist[9]
1936 #define aflag optlist[10]
1937 #define bflag optlist[11]
1938 #define uflag optlist[12]
1939 #define viflag optlist[13]
1942 #define nolog optlist[14]
1943 #define debug optlist[15]
1946 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1947 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1953 static const char *const optletters_optnames[] = {
1974 #define optletters(n) optletters_optnames[(n)][0]
1975 #define optnames(n) (&optletters_optnames[(n)][1])
1977 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1979 static char optlist[NOPTS];
1982 static char *arg0; /* value of $0 */
1983 static struct shparam shellparam; /* $@ current positional parameters */
1984 static char **argptr; /* argument list for builtin commands */
1985 static char *optionarg; /* set by nextopt (like getopt) */
1986 static char *optptr; /* used by nextopt */
1988 static char *minusc; /* argument to -c option */
1991 static void procargs(int, char **);
1992 static void optschanged(void);
1993 static void setparam(char **);
1994 static void freeparam(volatile struct shparam *);
1995 static int shiftcmd(int, char **);
1996 static int setcmd(int, char **);
1997 static int nextopt(const char *);
2001 /* flags passed to redirect */
2002 #define REDIR_PUSH 01 /* save previous values of file descriptors */
2003 #define REDIR_SAVEFD2 03 /* set preverrout */
2006 static void redirect(union node *, int);
2007 static void popredir(int);
2008 static void clearredir(int);
2009 static int copyfd(int, int);
2010 static int redirectsafe(union node *, int);
2016 static void showtree(union node *);
2017 static void trace(const char *, ...);
2018 static void tracev(const char *, va_list);
2019 static void trargs(char **);
2020 static void trputc(int);
2021 static void trputs(const char *);
2022 static void opentrace(void);
2028 /* trap handler commands */
2029 static char *trap[NSIG];
2030 /* current value of signal */
2031 static char sigmode[NSIG - 1];
2032 /* indicates specified signal received */
2033 static char gotsig[NSIG - 1];
2035 static void clear_traps(void);
2036 static void setsignal(int);
2037 static void ignoresig(int);
2038 static void onsig(int);
2039 static int dotrap(void);
2040 static void setinteractive(int);
2041 static void exitshell(void) ATTRIBUTE_NORETURN;
2044 static int is_safe_applet(char *name)
2046 int n = sizeof(safe_applets) / sizeof(char *);
2048 for (i = 0; i < n; i++)
2049 if (strcmp(safe_applets[i], name) == 0)
2057 * This routine is called when an error or an interrupt occurs in an
2058 * interactive shell and control is returned to the main command loop.
2072 parselleft = parsenleft = 0; /* clear input buffer */
2076 /* from parser.c: */
2089 #ifdef CONFIG_ASH_ALIAS
2090 static struct alias *atab[ATABSIZE];
2092 static void setalias(const char *, const char *);
2093 static struct alias *freealias(struct alias *);
2094 static struct alias **__lookupalias(const char *);
2097 setalias(const char *name, const char *val)
2099 struct alias *ap, **app;
2101 app = __lookupalias(name);
2105 if (!(ap->flag & ALIASINUSE)) {
2108 ap->val = savestr(val);
2109 ap->flag &= ~ALIASDEAD;
2112 ap = ckmalloc(sizeof (struct alias));
2113 ap->name = savestr(name);
2114 ap->val = savestr(val);
2123 unalias(const char *name)
2127 app = __lookupalias(name);
2131 *app = freealias(*app);
2142 struct alias *ap, **app;
2146 for (i = 0; i < ATABSIZE; i++) {
2148 for (ap = *app; ap; ap = *app) {
2149 *app = freealias(*app);
2158 static struct alias *
2159 lookupalias(const char *name, int check)
2161 struct alias *ap = *__lookupalias(name);
2163 if (check && ap && (ap->flag & ALIASINUSE))
2169 * TODO - sort output
2172 aliascmd(int argc, char **argv)
2181 for (i = 0; i < ATABSIZE; i++)
2182 for (ap = atab[i]; ap; ap = ap->next) {
2187 while ((n = *++argv) != NULL) {
2188 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2189 if ((ap = *__lookupalias(n)) == NULL) {
2190 fprintf(stderr, "%s: %s not found\n", "alias", n);
2204 unaliascmd(int argc, char **argv)
2208 while ((i = nextopt("a")) != '\0') {
2214 for (i = 0; *argptr; argptr++) {
2215 if (unalias(*argptr)) {
2216 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2224 static struct alias *
2225 freealias(struct alias *ap) {
2228 if (ap->flag & ALIASINUSE) {
2229 ap->flag |= ALIASDEAD;
2241 printalias(const struct alias *ap) {
2242 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2245 static struct alias **
2246 __lookupalias(const char *name) {
2247 unsigned int hashval;
2254 ch = (unsigned char)*p;
2258 ch = (unsigned char)*++p;
2260 app = &atab[hashval % ATABSIZE];
2262 for (; *app; app = &(*app)->next) {
2263 if (equal(name, (*app)->name)) {
2270 #endif /* CONFIG_ASH_ALIAS */
2276 * The cd and pwd commands.
2279 #define CD_PHYSICAL 1
2282 static int docd(const char *, int);
2283 static int cdopt(void);
2285 static char *curdir = nullstr; /* current working directory */
2286 static char *physdir = nullstr; /* physical working directory */
2295 while ((i = nextopt("LP"))) {
2297 flags ^= CD_PHYSICAL;
2306 cdcmd(int argc, char **argv)
2318 dest = bltinlookup(homestr);
2319 else if (dest[0] == '-' && dest[1] == '\0') {
2320 dest = bltinlookup("OLDPWD");
2342 if (!(path = bltinlookup("CDPATH"))) {
2350 p = padvance(&path, dest);
2351 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2355 if (!docd(p, flags))
2360 sh_error("can't cd to %s", dest);
2363 if (flags & CD_PRINT)
2364 out1fmt(snlfmt, curdir);
2370 * Update curdir (the name of the current directory) in response to a
2374 static const char * updatepwd(const char *dir)
2381 cdcomppath = sstrdup(dir);
2384 if (curdir == nullstr)
2386 new = stputs(curdir, new);
2388 new = makestrspace(strlen(dir) + 2, new);
2389 lim = stackblock() + 1;
2393 if (new > lim && *lim == '/')
2398 if (dir[1] == '/' && dir[2] != '/') {
2404 p = strtok(cdcomppath, "/");
2408 if (p[1] == '.' && p[2] == '\0') {
2415 } else if (p[1] == '\0')
2419 new = stputs(p, new);
2427 return stackblock();
2431 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2432 * know that the current directory has changed.
2436 docd(const char *dest, int flags)
2438 const char *dir = 0;
2441 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2444 if (!(flags & CD_PHYSICAL)) {
2445 dir = updatepwd(dest);
2460 * Find out what the current directory is. If we already know the current
2461 * directory, this routine returns immediately.
2463 static char * getpwd(void)
2465 char *dir = getcwd(0, 0);
2466 return dir ? dir : nullstr;
2470 pwdcmd(int argc, char **argv)
2473 const char *dir = curdir;
2477 if (physdir == nullstr)
2481 out1fmt(snlfmt, dir);
2486 setpwd(const char *val, int setold)
2490 oldcur = dir = curdir;
2493 setvar("OLDPWD", oldcur, VEXPORT);
2496 if (physdir != nullstr) {
2497 if (physdir != oldcur)
2501 if (oldcur == val || !val) {
2508 if (oldcur != dir && oldcur != nullstr) {
2513 setvar("PWD", dir, VEXPORT);
2519 * Errors and exceptions.
2523 * Code to handle exceptions in C.
2528 static void exverror(int, const char *, va_list)
2532 * Called to raise an exception. Since C doesn't include exceptions, we
2533 * just do a longjmp to the exception handler. The type of exception is
2534 * stored in the global variable "exception".
2541 if (handler == NULL)
2547 longjmp(handler->loc, 1);
2552 * Called from trap.c when a SIGINT is received. (If the user specifies
2553 * that SIGINT is to be trapped or ignored using the trap builtin, then
2554 * this routine is not called.) Suppressint is nonzero when interrupts
2555 * are held using the INTOFF macro. (The test for iflag is just
2556 * defensive programming.)
2565 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2566 if (!(rootshell && iflag)) {
2567 signal(SIGINT, SIG_DFL);
2577 exvwarning(const char *msg, va_list ap)
2582 fprintf(errs, "%s: ", arg0);
2584 const char *fmt = (!iflag || parsefile->fd) ?
2585 "%s: %d: " : "%s: ";
2586 fprintf(errs, fmt, commandname, startlinno);
2588 vfprintf(errs, msg, ap);
2589 outcslow('\n', errs);
2593 * Exverror is called to raise the error exception. If the second argument
2594 * is not NULL then error prints an error message using printf style
2595 * formatting. It then raises the error exception.
2598 exverror(int cond, const char *msg, va_list ap)
2602 TRACE(("exverror(%d, \"", cond));
2604 TRACE(("\") pid=%d\n", getpid()));
2606 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2609 exvwarning(msg, ap);
2618 sh_error(const char *msg, ...)
2623 exverror(EXERROR, msg, ap);
2630 exerror(int cond, const char *msg, ...)
2635 exverror(cond, msg, ap);
2641 * error/warning routines for external builtins
2645 sh_warnx(const char *fmt, ...)
2650 exvwarning(fmt, ap);
2656 * Return a string describing an error. The returned string may be a
2657 * pointer to a static buffer that will be overwritten on the next call.
2658 * Action describes the operation that got the error.
2662 errmsg(int e, const char *em)
2664 if(e == ENOENT || e == ENOTDIR) {
2675 * Evaluate a command.
2678 /* flags in argument to evaltree */
2679 #define EV_EXIT 01 /* exit after evaluating tree */
2680 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2681 #define EV_BACKCMD 04 /* command executing within back quotes */
2684 static void evalloop(union node *, int);
2685 static void evalfor(union node *, int);
2686 static void evalcase(union node *, int);
2687 static void evalsubshell(union node *, int);
2688 static void expredir(union node *);
2689 static void evalpipe(union node *, int);
2690 static void evalcommand(union node *, int);
2691 static int evalbltin(const struct builtincmd *, int, char **);
2692 static int evalfun(struct funcnode *, int, char **, int);
2693 static void prehash(union node *);
2694 static int bltincmd(int, char **);
2697 static const struct builtincmd bltin = {
2703 * Called to reset things after an exception.
2711 evalcmd(int argc, char **argv)
2720 STARTSTACKSTR(concat);
2723 concat = stputs(p, concat);
2724 if ((p = *ap++) == NULL)
2726 STPUTC(' ', concat);
2728 STPUTC('\0', concat);
2729 p = grabstackstr(concat);
2731 evalstring(p, ~SKIPEVAL);
2739 * Execute a command or commands contained in a string.
2743 evalstring(char *s, int mask)
2746 struct stackmark smark;
2750 setstackmark(&smark);
2753 while ((n = parsecmd(0)) != NEOF) {
2755 popstackmark(&smark);
2770 * Evaluate a parse tree. The value is left in the global variable
2775 evaltree(union node *n, int flags)
2778 void (*evalfn)(union node *, int);
2782 TRACE(("evaltree(NULL) called\n"));
2785 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2786 getpid(), n, n->type, flags));
2790 out1fmt("Node type = %d\n", n->type);
2795 evaltree(n->nnot.com, EV_TESTED);
2796 status = !exitstatus;
2799 expredir(n->nredir.redirect);
2800 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2802 evaltree(n->nredir.n, flags & EV_TESTED);
2803 status = exitstatus;
2808 evalfn = evalcommand;
2810 if (eflag && !(flags & EV_TESTED))
2822 evalfn = evalsubshell;
2834 #error NAND + 1 != NOR
2836 #if NOR + 1 != NSEMI
2837 #error NOR + 1 != NSEMI
2839 isor = n->type - NAND;
2842 (flags | ((isor >> 1) - 1)) & EV_TESTED
2844 if (!exitstatus == isor)
2856 evaltree(n->nif.test, EV_TESTED);
2859 if (exitstatus == 0) {
2862 } else if (n->nif.elsepart) {
2863 n = n->nif.elsepart;
2868 defun(n->narg.text, n->narg.next);
2872 exitstatus = status;
2876 if ((checkexit & exitstatus))
2877 evalskip |= SKIPEVAL;
2878 else if (pendingsigs && dotrap())
2881 if (flags & EV_EXIT) {
2888 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2891 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2895 evalloop(union node *n, int flags)
2905 evaltree(n->nbinary.ch1, EV_TESTED);
2907 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2911 if (evalskip == SKIPBREAK && --skipcount <= 0)
2916 if (n->type != NWHILE)
2920 evaltree(n->nbinary.ch2, flags);
2921 status = exitstatus;
2926 exitstatus = status;
2932 evalfor(union node *n, int flags)
2934 struct arglist arglist;
2937 struct stackmark smark;
2939 setstackmark(&smark);
2940 arglist.lastp = &arglist.list;
2941 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2942 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2947 *arglist.lastp = NULL;
2952 for (sp = arglist.list ; sp ; sp = sp->next) {
2953 setvar(n->nfor.var, sp->text, 0);
2954 evaltree(n->nfor.body, flags);
2956 if (evalskip == SKIPCONT && --skipcount <= 0) {
2960 if (evalskip == SKIPBREAK && --skipcount <= 0)
2967 popstackmark(&smark);
2973 evalcase(union node *n, int flags)
2977 struct arglist arglist;
2978 struct stackmark smark;
2980 setstackmark(&smark);
2981 arglist.lastp = &arglist.list;
2982 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2984 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2985 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2986 if (casematch(patp, arglist.list->text)) {
2987 if (evalskip == 0) {
2988 evaltree(cp->nclist.body, flags);
2995 popstackmark(&smark);
3001 * Kick off a subshell to evaluate a tree.
3005 evalsubshell(union node *n, int flags)
3008 int backgnd = (n->type == NBACKGND);
3011 expredir(n->nredir.redirect);
3012 if (!backgnd && flags & EV_EXIT && !trap[0])
3016 if (forkshell(jp, n, backgnd) == 0) {
3020 flags &=~ EV_TESTED;
3022 redirect(n->nredir.redirect, 0);
3023 evaltreenr(n->nredir.n, flags);
3028 status = waitforjob(jp);
3029 exitstatus = status;
3036 * Compute the names of the files in a redirection list.
3040 expredir(union node *n)
3044 for (redir = n ; redir ; redir = redir->nfile.next) {
3046 memset(&fn, 0, sizeof(struct arglist));
3047 fn.lastp = &fn.list;
3048 switch (redir->type) {
3054 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3055 redir->nfile.expfname = fn.list->text;
3059 if (redir->ndup.vname) {
3060 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3061 if (fn.list != NULL)
3062 fixredir(redir, fn.list->text, 1);
3064 sh_error("redir error");
3074 * Evaluate a pipeline. All the processes in the pipeline are children
3075 * of the process creating the pipeline. (This differs from some versions
3076 * of the shell, which make the last process in a pipeline the parent
3081 evalpipe(union node *n, int flags)
3084 struct nodelist *lp;
3089 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3091 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3095 jp = makejob(n, pipelen);
3097 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3101 if (pipe(pip) < 0) {
3103 sh_error("Pipe call failed");
3106 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3119 evaltreenr(lp->n, flags);
3127 if (n->npipe.backgnd == 0) {
3128 exitstatus = waitforjob(jp);
3129 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3137 * Execute a command inside back quotes. If it's a builtin command, we
3138 * want to save its output in a block obtained from malloc. Otherwise
3139 * we fork off a subprocess and get the output of the command via a pipe.
3140 * Should be called with interrupts off.
3144 evalbackcmd(union node *n, struct backcmd *result)
3156 saveherefd = herefd;
3164 sh_error("Pipe call failed");
3166 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3175 evaltreenr(n, EV_EXIT);
3179 result->fd = pip[0];
3182 herefd = saveherefd;
3184 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3185 result->fd, result->buf, result->nleft, result->jp));
3188 #ifdef CONFIG_ASH_CMDCMD
3189 static char ** parse_command_args(char **argv, const char **path)
3201 if (c == '-' && !*cp) {
3211 /* run 'typecmd' for other options */
3214 } while ((c = *cp++));
3220 static int isassignment(const char *p)
3222 const char *q = endofname(p);
3228 #ifdef CONFIG_ASH_EXPAND_PRMT
3229 static const char *expandstr(const char *ps);
3231 #define expandstr(s) s
3235 * Execute a simple command.
3239 evalcommand(union node *cmd, int flags)
3241 struct stackmark smark;
3243 struct arglist arglist;
3244 struct arglist varlist;
3247 const struct strlist *sp;
3248 struct cmdentry cmdentry;
3256 struct builtincmd *bcmd;
3257 int pseudovarflag = 0;
3259 /* First expand the arguments. */
3260 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3261 setstackmark(&smark);
3262 back_exitstatus = 0;
3264 cmdentry.cmdtype = CMDBUILTIN;
3265 cmdentry.u.cmd = &bltin;
3266 varlist.lastp = &varlist.list;
3267 *varlist.lastp = NULL;
3268 arglist.lastp = &arglist.list;
3269 *arglist.lastp = NULL;
3274 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3275 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3278 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3279 struct strlist **spp;
3281 spp = arglist.lastp;
3282 if (pseudovarflag && isassignment(argp->narg.text))
3283 expandarg(argp, &arglist, EXP_VARTILDE);
3285 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3287 for (sp = *spp; sp; sp = sp->next)
3291 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3292 for (sp = arglist.list ; sp ; sp = sp->next) {
3293 TRACE(("evalcommand arg: %s\n", sp->text));
3294 *nargv++ = sp->text;
3299 if (iflag && funcnest == 0 && argc > 0)
3300 lastarg = nargv[-1];
3303 expredir(cmd->ncmd.redirect);
3304 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3307 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3308 struct strlist **spp;
3311 spp = varlist.lastp;
3312 expandarg(argp, &varlist, EXP_VARTILDE);
3315 * Modify the command lookup path, if a PATH= assignment
3319 if (varequal(p, path))
3323 /* Print the command if xflag is set. */
3326 const char *p = " %s";
3329 dprintf(preverrout_fd, p, expandstr(ps4val()));
3332 for(n = 0; n < 2; n++) {
3334 dprintf(preverrout_fd, p, sp->text);
3342 full_write(preverrout_fd, "\n", 1);
3348 /* Now locate the command. */
3350 const char *oldpath;
3351 int cmd_flag = DO_ERR;
3356 find_command(argv[0], &cmdentry, cmd_flag, path);
3357 if (cmdentry.cmdtype == CMDUNKNOWN) {
3363 /* implement bltin and command here */
3364 if (cmdentry.cmdtype != CMDBUILTIN)
3367 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3368 if (cmdentry.u.cmd == EXECCMD)
3370 #ifdef CONFIG_ASH_CMDCMD
3371 if (cmdentry.u.cmd == COMMANDCMD) {
3374 nargv = parse_command_args(argv, &path);
3377 argc -= nargv - argv;
3379 cmd_flag |= DO_NOFUNC;
3387 /* We have a redirection error. */
3391 exitstatus = status;
3395 /* Execute the command. */
3396 switch (cmdentry.cmdtype) {
3398 /* Fork off a child process if necessary. */
3399 if (!(flags & EV_EXIT) || trap[0]) {
3401 jp = makejob(cmd, 1);
3402 if (forkshell(jp, cmd, FORK_FG) != 0) {
3403 exitstatus = waitforjob(jp);
3409 listsetvar(varlist.list, VEXPORT|VSTACK);
3410 shellexec(argv, path, cmdentry.u.index);
3414 cmdenviron = varlist.list;
3416 struct strlist *list = cmdenviron;
3418 if (spclbltin > 0 || argc == 0) {
3420 if (cmd_is_exec && argc > 1)
3423 listsetvar(list, i);
3425 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3440 exit_status = j + 128;
3441 exitstatus = exit_status;
3443 if (i == EXINT || spclbltin > 0) {
3445 longjmp(handler->loc, 1);
3452 listsetvar(varlist.list, 0);
3453 if (evalfun(cmdentry.u.func, argc, argv, flags))
3459 popredir(cmd_is_exec);
3461 /* dsl: I think this is intended to be used to support
3462 * '_' in 'vi' command mode during line editing...
3463 * However I implemented that within libedit itself.
3465 setvar("_", lastarg, 0);
3466 popstackmark(&smark);
3470 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3471 char *volatile savecmdname;
3472 struct jmploc *volatile savehandler;
3473 struct jmploc jmploc;
3476 savecmdname = commandname;
3477 if ((i = setjmp(jmploc.loc)))
3479 savehandler = handler;
3481 commandname = argv[0];
3483 optptr = NULL; /* initialize nextopt */
3484 exitstatus = (*cmd->builtin)(argc, argv);
3487 exitstatus |= ferror(stdout);
3489 commandname = savecmdname;
3491 handler = savehandler;
3497 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3499 volatile struct shparam saveparam;
3500 struct localvar *volatile savelocalvars;
3501 struct jmploc *volatile savehandler;
3502 struct jmploc jmploc;
3505 saveparam = shellparam;
3506 savelocalvars = localvars;
3507 if ((e = setjmp(jmploc.loc))) {
3511 savehandler = handler;
3514 shellparam.malloc = 0;
3518 shellparam.nparam = argc - 1;
3519 shellparam.p = argv + 1;
3520 #ifdef CONFIG_ASH_GETOPTS
3521 shellparam.optind = 1;
3522 shellparam.optoff = -1;
3524 evaltree(&func->n, flags & EV_TESTED);
3530 localvars = savelocalvars;
3531 freeparam(&shellparam);
3532 shellparam = saveparam;
3533 handler = savehandler;
3535 evalskip &= ~SKIPFUNC;
3540 static int goodname(const char *p)
3542 return !*endofname(p);
3546 * Search for a command. This is called before we fork so that the
3547 * location of the command will be available in the parent as well as
3548 * the child. The check for "goodname" is an overly conservative
3549 * check that the name will not be subject to expansion.
3553 prehash(union node *n)
3555 struct cmdentry entry;
3557 if (n->type == NCMD && n->ncmd.args)
3558 if (goodname(n->ncmd.args->narg.text))
3559 find_command(n->ncmd.args->narg.text, &entry, 0,
3566 * Builtin commands. Builtin commands whose functions are closely
3567 * tied to evaluation are implemented here.
3575 bltincmd(int argc, char **argv)
3578 * Preserve exitstatus of a previous possible redirection
3581 return back_exitstatus;
3586 * Handle break and continue commands. Break, continue, and return are
3587 * all handled by setting the evalskip flag. The evaluation routines
3588 * above all check this flag, and if it is set they start skipping
3589 * commands rather than executing them. The variable skipcount is
3590 * the number of loops to break/continue, or the number of function
3591 * levels to return. (The latter is always 1.) It should probably
3592 * be an error to break out of more loops than exist, but it isn't
3593 * in the standard shell so we don't make it one here.
3597 breakcmd(int argc, char **argv)
3599 int n = argc > 1 ? number(argv[1]) : 1;
3602 sh_error(illnum, argv[1]);
3606 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3614 * The return command.
3618 returncmd(int argc, char **argv)
3621 * If called outside a function, do what ksh does;
3622 * skip the rest of the file.
3624 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3625 return argv[1] ? number(argv[1]) : exitstatus;
3630 falsecmd(int argc, char **argv)
3637 truecmd(int argc, char **argv)
3644 execcmd(int argc, char **argv)
3647 iflag = 0; /* exit on error */
3650 shellexec(argv + 1, pathval(), 0);
3659 * When commands are first encountered, they are entered in a hash table.
3660 * This ensures that a full path search will not have to be done for them
3661 * on each invocation.
3663 * We should investigate converting to a linear search, even though that
3664 * would make the command name "hash" a misnomer.
3667 #define CMDTABLESIZE 31 /* should be prime */
3668 #define ARB 1 /* actual size determined at run time */
3673 struct tblentry *next; /* next entry in hash chain */
3674 union param param; /* definition of builtin function */
3675 short cmdtype; /* index identifying command */
3676 char rehash; /* if set, cd done since entry created */
3677 char cmdname[ARB]; /* name of command */
3681 static struct tblentry *cmdtable[CMDTABLESIZE];
3682 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3685 static void tryexec(char *, char **, char **);
3686 static void clearcmdentry(int);
3687 static struct tblentry *cmdlookup(const char *, int);
3688 static void delete_cmd_entry(void);
3692 * Exec a program. Never returns. If you change this routine, you may
3693 * have to change the find_command routine as well.
3697 shellexec(char **argv, const char *path, int idx)
3705 envp = environment();
3706 if (strchr(argv[0], '/') != NULL
3707 || is_safe_applet(argv[0])
3708 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3709 || find_applet_by_name(argv[0])
3712 tryexec(argv[0], argv, envp);
3716 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3717 if (--idx < 0 && pathopt == NULL) {
3718 tryexec(cmdname, argv, envp);
3719 if (errno != ENOENT && errno != ENOTDIR)
3726 /* Map to POSIX errors */
3738 exitstatus = exerrno;
3739 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3740 argv[0], e, suppressint ));
3741 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3747 tryexec(char *cmd, char **argv, char **envp)
3750 struct BB_applet *a;
3754 if(strchr(cmd, '/') == NULL && is_safe_applet(cmd) && (a = find_applet_by_name(cmd)) != NULL) {
3756 while (*c != NULL) {
3760 exit(a->main(argc, argv));
3762 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3763 if(find_applet_by_name(cmd) != NULL) {
3764 /* re-exec ourselves with the new arguments */
3765 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3766 /* If they called chroot or otherwise made the binary no longer
3767 * executable, fall through */
3774 execve(cmd, argv, envp);
3775 } while (errno == EINTR);
3777 execve(cmd, argv, envp);
3781 } else if (errno == ENOEXEC) {
3785 for (ap = argv; *ap; ap++)
3787 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3789 *ap = cmd = (char *)DEFAULT_SHELL;
3792 while ((*ap++ = *argv++))
3802 * Do a path search. The variable path (passed by reference) should be
3803 * set to the start of the path before the first call; padvance will update
3804 * this value as it proceeds. Successive calls to padvance will return
3805 * the possible path expansions in sequence. If an option (indicated by
3806 * a percent sign) appears in the path entry then the global variable
3807 * pathopt will be set to point to it; otherwise pathopt will be set to
3812 padvance(const char **path, const char *name)
3822 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3823 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3824 while (stackblocksize() < len)
3828 memcpy(q, start, p - start);
3836 while (*p && *p != ':') p++;
3842 return stalloc(len);
3846 /*** Command hashing code ***/
3849 printentry(struct tblentry *cmdp)
3855 idx = cmdp->param.index;
3858 name = padvance(&path, cmdp->cmdname);
3860 } while (--idx >= 0);
3861 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3866 hashcmd(int argc, char **argv)
3868 struct tblentry **pp;
3869 struct tblentry *cmdp;
3871 struct cmdentry entry;
3874 while ((c = nextopt("r")) != '\0') {
3878 if (*argptr == NULL) {
3879 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3880 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3881 if (cmdp->cmdtype == CMDNORMAL)
3888 while ((name = *argptr) != NULL) {
3889 if ((cmdp = cmdlookup(name, 0)) != NULL
3890 && (cmdp->cmdtype == CMDNORMAL
3891 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3893 find_command(name, &entry, DO_ERR, pathval());
3894 if (entry.cmdtype == CMDUNKNOWN)
3903 * Resolve a command name. If you change this routine, you may have to
3904 * change the shellexec routine as well.
3908 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3910 struct tblentry *cmdp;
3917 struct builtincmd *bcmd;
3919 /* If name contains a slash, don't use PATH or hash table */
3920 if (strchr(name, '/') != NULL) {
3921 entry->u.index = -1;
3923 while (stat(name, &statb) < 0) {
3928 entry->cmdtype = CMDUNKNOWN;
3932 entry->cmdtype = CMDNORMAL;
3936 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3937 if (find_applet_by_name(name)) {
3938 entry->cmdtype = CMDNORMAL;
3939 entry->u.index = -1;
3944 if (is_safe_applet(name)) {
3945 entry->cmdtype = CMDNORMAL;
3946 entry->u.index = -1;
3950 updatetbl = (path == pathval());
3953 if (strstr(path, "%builtin") != NULL)
3957 /* If name is in the table, check answer will be ok */
3958 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3961 switch (cmdp->cmdtype) {
3979 } else if (cmdp->rehash == 0)
3980 /* if not invalidated by cd, we're done */
3984 /* If %builtin not in path, check for builtin next */
3985 bcmd = find_builtin(name);
3986 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3987 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3989 goto builtin_success;
3991 /* We have to search path. */
3992 prev = -1; /* where to start */
3993 if (cmdp && cmdp->rehash) { /* doing a rehash */
3994 if (cmdp->cmdtype == CMDBUILTIN)
3997 prev = cmdp->param.index;
4003 while ((fullname = padvance(&path, name)) != NULL) {
4004 stunalloc(fullname);
4007 if (prefix(pathopt, "builtin")) {
4009 goto builtin_success;
4011 } else if (!(act & DO_NOFUNC) &&
4012 prefix(pathopt, "func")) {
4015 /* ignore unimplemented options */
4019 /* if rehash, don't redo absolute path names */
4020 if (fullname[0] == '/' && idx <= prev) {
4023 TRACE(("searchexec \"%s\": no change\n", name));
4026 while (stat(fullname, &statb) < 0) {
4031 if (errno != ENOENT && errno != ENOTDIR)
4035 e = EACCES; /* if we fail, this will be the error */
4036 if (!S_ISREG(statb.st_mode))
4038 if (pathopt) { /* this is a %func directory */
4039 stalloc(strlen(fullname) + 1);
4040 readcmdfile(fullname);
4041 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4042 cmdp->cmdtype != CMDFUNCTION)
4043 sh_error("%s not defined in %s", name, fullname);
4044 stunalloc(fullname);
4047 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4049 entry->cmdtype = CMDNORMAL;
4050 entry->u.index = idx;
4054 cmdp = cmdlookup(name, 1);
4055 cmdp->cmdtype = CMDNORMAL;
4056 cmdp->param.index = idx;
4061 /* We failed. If there was an entry for this command, delete it */
4062 if (cmdp && updatetbl)
4065 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4066 entry->cmdtype = CMDUNKNOWN;
4071 entry->cmdtype = CMDBUILTIN;
4072 entry->u.cmd = bcmd;
4076 cmdp = cmdlookup(name, 1);
4077 cmdp->cmdtype = CMDBUILTIN;
4078 cmdp->param.cmd = bcmd;
4082 entry->cmdtype = cmdp->cmdtype;
4083 entry->u = cmdp->param;
4088 * Wrapper around strcmp for qsort/bsearch/...
4090 static int pstrcmp(const void *a, const void *b)
4092 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4096 * Search the table of builtin commands.
4099 static struct builtincmd *
4100 find_builtin(const char *name)
4102 struct builtincmd *bp;
4105 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4114 * Called when a cd is done. Marks all commands so the next time they
4115 * are executed they will be rehashed.
4121 struct tblentry **pp;
4122 struct tblentry *cmdp;
4124 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4125 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4126 if (cmdp->cmdtype == CMDNORMAL || (
4127 cmdp->cmdtype == CMDBUILTIN &&
4128 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4139 * Fix command hash table when PATH changed.
4140 * Called before PATH is changed. The argument is the new value of PATH;
4141 * pathval() still returns the old value at this point.
4142 * Called with interrupts off.
4146 changepath(const char *newval)
4148 const char *old, *new;
4155 firstchange = 9999; /* assume no change */
4161 if ((*old == '\0' && *new == ':')
4162 || (*old == ':' && *new == '\0'))
4164 old = new; /* ignore subsequent differences */
4168 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4175 if (builtinloc < 0 && idx_bltin >= 0)
4176 builtinloc = idx_bltin; /* zap builtins */
4177 if (builtinloc >= 0 && idx_bltin < 0)
4179 clearcmdentry(firstchange);
4180 builtinloc = idx_bltin;
4185 * Clear out command entries. The argument specifies the first entry in
4186 * PATH which has changed.
4190 clearcmdentry(int firstchange)
4192 struct tblentry **tblp;
4193 struct tblentry **pp;
4194 struct tblentry *cmdp;
4197 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4199 while ((cmdp = *pp) != NULL) {
4200 if ((cmdp->cmdtype == CMDNORMAL &&
4201 cmdp->param.index >= firstchange)
4202 || (cmdp->cmdtype == CMDBUILTIN &&
4203 builtinloc >= firstchange)) {
4217 * Locate a command in the command hash table. If "add" is nonzero,
4218 * add the command to the table if it is not already present. The
4219 * variable "lastcmdentry" is set to point to the address of the link
4220 * pointing to the entry, so that delete_cmd_entry can delete the
4223 * Interrupts must be off if called with add != 0.
4226 static struct tblentry **lastcmdentry;
4229 static struct tblentry *
4230 cmdlookup(const char *name, int add)
4232 unsigned int hashval;
4234 struct tblentry *cmdp;
4235 struct tblentry **pp;
4238 hashval = (unsigned char)*p << 4;
4240 hashval += (unsigned char)*p++;
4242 pp = &cmdtable[hashval % CMDTABLESIZE];
4243 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4244 if (equal(cmdp->cmdname, name))
4248 if (add && cmdp == NULL) {
4249 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4250 + strlen(name) + 1);
4252 cmdp->cmdtype = CMDUNKNOWN;
4253 strcpy(cmdp->cmdname, name);
4260 * Delete the command entry returned on the last lookup.
4264 delete_cmd_entry(void)
4266 struct tblentry *cmdp;
4269 cmdp = *lastcmdentry;
4270 *lastcmdentry = cmdp->next;
4271 if (cmdp->cmdtype == CMDFUNCTION)
4272 freefunc(cmdp->param.func);
4279 * Add a new command entry, replacing any existing command entry for
4280 * the same name - except special builtins.
4283 static void addcmdentry(char *name, struct cmdentry *entry)
4285 struct tblentry *cmdp;
4287 cmdp = cmdlookup(name, 1);
4288 if (cmdp->cmdtype == CMDFUNCTION) {
4289 freefunc(cmdp->param.func);
4291 cmdp->cmdtype = entry->cmdtype;
4292 cmdp->param = entry->u;
4297 * Make a copy of a parse tree.
4300 static struct funcnode * copyfunc(union node *n)
4305 funcblocksize = offsetof(struct funcnode, n);
4308 blocksize = funcblocksize;
4309 f = ckmalloc(blocksize + funcstringsize);
4310 funcblock = (char *) f + offsetof(struct funcnode, n);
4311 funcstring = (char *) f + blocksize;
4318 * Define a shell function.
4322 defun(char *name, union node *func)
4324 struct cmdentry entry;
4327 entry.cmdtype = CMDFUNCTION;
4328 entry.u.func = copyfunc(func);
4329 addcmdentry(name, &entry);
4335 * Delete a function if it exists.
4339 unsetfunc(const char *name)
4341 struct tblentry *cmdp;
4343 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4344 cmdp->cmdtype == CMDFUNCTION)
4349 * Locate and print what a word is...
4353 #ifdef CONFIG_ASH_CMDCMD
4355 describe_command(char *command, int describe_command_verbose)
4357 #define describe_command_verbose 1
4359 describe_command(char *command)
4362 struct cmdentry entry;
4363 struct tblentry *cmdp;
4364 #ifdef CONFIG_ASH_ALIAS
4365 const struct alias *ap;
4367 const char *path = pathval();
4369 if (describe_command_verbose) {
4373 /* First look at the keywords */
4374 if (findkwd(command)) {
4375 out1str(describe_command_verbose ? " is a shell keyword" : command);
4379 #ifdef CONFIG_ASH_ALIAS
4380 /* Then look at the aliases */
4381 if ((ap = lookupalias(command, 0)) != NULL) {
4382 if (describe_command_verbose) {
4383 out1fmt(" is an alias for %s", ap->val);
4392 /* Then check if it is a tracked alias */
4393 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4394 entry.cmdtype = cmdp->cmdtype;
4395 entry.u = cmdp->param;
4397 /* Finally use brute force */
4398 find_command(command, &entry, DO_ABS, path);
4401 switch (entry.cmdtype) {
4403 int j = entry.u.index;
4409 p = padvance(&path, command);
4413 if (describe_command_verbose) {
4415 (cmdp ? " a tracked alias for" : nullstr), p
4424 if (describe_command_verbose) {
4425 out1str(" is a shell function");
4432 if (describe_command_verbose) {
4433 out1fmt(" is a %sshell builtin",
4434 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4435 "special " : nullstr
4443 if (describe_command_verbose) {
4444 out1str(": not found\n");
4450 outstr("\n", stdout);
4455 typecmd(int argc, char **argv)
4460 for (i = 1; i < argc; i++) {
4461 #ifdef CONFIG_ASH_CMDCMD
4462 err |= describe_command(argv[i], 1);
4464 err |= describe_command(argv[i]);
4470 #ifdef CONFIG_ASH_CMDCMD
4472 commandcmd(int argc, char **argv)
4480 while ((c = nextopt("pvV")) != '\0')
4482 verify |= VERIFY_VERBOSE;
4484 verify |= VERIFY_BRIEF;
4490 return describe_command(*argptr, verify - VERIFY_BRIEF);
4499 * Routines to expand arguments to commands. We have to deal with
4500 * backquotes, shell variables, and file metacharacters.
4506 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4507 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4508 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4509 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4510 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4513 * Structure specifying which parts of the string should be searched
4514 * for IFS characters.
4518 struct ifsregion *next; /* next region in list */
4519 int begoff; /* offset of start of region */
4520 int endoff; /* offset of end of region */
4521 int nulonly; /* search for nul bytes only */
4524 /* output of current string */
4525 static char *expdest;
4526 /* list of back quote expressions */
4527 static struct nodelist *argbackq;
4528 /* first struct in list of ifs regions */
4529 static struct ifsregion ifsfirst;
4530 /* last struct in list */
4531 static struct ifsregion *ifslastp;
4532 /* holds expanded arg list */
4533 static struct arglist exparg;
4535 static void argstr(char *, int);
4536 static char *exptilde(char *, char *, int);
4537 static void expbackq(union node *, int, int);
4538 static const char *subevalvar(char *, char *, int, int, int, int, int);
4539 static char *evalvar(char *, int);
4540 static void strtodest(const char *, int, int);
4541 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4542 static ssize_t varvalue(char *, int, int);
4543 static void recordregion(int, int, int);
4544 static void removerecordregions(int);
4545 static void ifsbreakup(char *, struct arglist *);
4546 static void ifsfree(void);
4547 static void expandmeta(struct strlist *, int);
4548 static int patmatch(char *, const char *);
4550 static int cvtnum(arith_t);
4551 static size_t esclen(const char *, const char *);
4552 static char *scanleft(char *, char *, char *, char *, int, int);
4553 static char *scanright(char *, char *, char *, char *, int, int);
4554 static void varunset(const char *, const char *, const char *, int)
4558 #define pmatch(a, b) !fnmatch((a), (b), 0)
4560 * Prepare a pattern for a expmeta (internal glob(3)) call.
4562 * Returns an stalloced string.
4565 static char * preglob(const char *pattern, int quoted, int flag) {
4566 flag |= RMESCAPE_GLOB;
4568 flag |= RMESCAPE_QUOTED;
4570 return _rmescapes((char *)pattern, flag);
4575 esclen(const char *start, const char *p) {
4578 while (p > start && *--p == CTLESC) {
4586 * Expand shell variables and backquotes inside a here document.
4589 static void expandhere(union node *arg, int fd)
4592 expandarg(arg, (struct arglist *)NULL, 0);
4593 full_write(fd, stackblock(), expdest - (char *)stackblock());
4598 * Perform variable substitution and command substitution on an argument,
4599 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4600 * perform splitting and file name expansion. When arglist is NULL, perform
4601 * here document expansion.
4605 expandarg(union node *arg, struct arglist *arglist, int flag)
4610 argbackq = arg->narg.backquote;
4611 STARTSTACKSTR(expdest);
4612 ifsfirst.next = NULL;
4614 argstr(arg->narg.text, flag);
4615 p = _STPUTC('\0', expdest);
4617 if (arglist == NULL) {
4618 return; /* here document expanded */
4620 p = grabstackstr(p);
4621 exparg.lastp = &exparg.list;
4625 if (flag & EXP_FULL) {
4626 ifsbreakup(p, &exparg);
4627 *exparg.lastp = NULL;
4628 exparg.lastp = &exparg.list;
4629 expandmeta(exparg.list, flag);
4631 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4633 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4636 exparg.lastp = &sp->next;
4640 *exparg.lastp = NULL;
4642 *arglist->lastp = exparg.list;
4643 arglist->lastp = exparg.lastp;
4649 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4650 * characters to allow for further processing. Otherwise treat
4651 * $@ like $* since no splitting will be performed.
4655 argstr(char *p, int flag)
4657 static const char spclchars[] = {
4665 CTLBACKQ | CTLQUOTE,
4666 #ifdef CONFIG_ASH_MATH_SUPPORT
4671 const char *reject = spclchars;
4673 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4674 int breakall = flag & EXP_WORD;
4679 if (!(flag & EXP_VARTILDE)) {
4681 } else if (flag & EXP_VARTILDE2) {
4686 if (flag & EXP_TILDE) {
4692 if (*q == CTLESC && (flag & EXP_QWORD))
4695 p = exptilde(p, q, flag);
4698 startloc = expdest - (char *)stackblock();
4700 length += strcspn(p + length, reject);
4702 if (c && (!(c & 0x80)
4703 #ifdef CONFIG_ASH_MATH_SUPPORT
4707 /* c == '=' || c == ':' || c == CTLENDARI */
4712 expdest = stnputs(p, length, expdest);
4713 newloc = expdest - (char *)stackblock();
4714 if (breakall && !inquotes && newloc > startloc) {
4715 recordregion(startloc, newloc, 0);
4726 if (flag & EXP_VARTILDE2) {
4730 flag |= EXP_VARTILDE2;
4735 * sort of a hack - expand tildes in variable
4736 * assignments (after the first '=' and after ':'s).
4745 case CTLENDVAR: /* ??? */
4748 /* "$@" syntax adherence hack */
4751 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4752 (p[4] == CTLQUOTEMARK || (
4753 p[4] == CTLENDVAR &&
4754 p[5] == CTLQUOTEMARK
4757 p = evalvar(p + 1, flag) + 1;
4760 inquotes = !inquotes;
4773 p = evalvar(p, flag);
4777 case CTLBACKQ|CTLQUOTE:
4778 expbackq(argbackq->n, c, quotes);
4779 argbackq = argbackq->next;
4781 #ifdef CONFIG_ASH_MATH_SUPPORT
4794 exptilde(char *startp, char *p, int flag)
4800 int quotes = flag & (EXP_FULL | EXP_CASE);
4805 while ((c = *++p) != '\0') {
4812 if (flag & EXP_VARTILDE)
4822 if (*name == '\0') {
4823 home = lookupvar(homestr);
4825 if ((pw = getpwnam(name)) == NULL)
4829 if (!home || !*home)
4832 startloc = expdest - (char *)stackblock();
4833 strtodest(home, SQSYNTAX, quotes);
4834 recordregion(startloc, expdest - (char *)stackblock(), 0);
4843 removerecordregions(int endoff)
4845 if (ifslastp == NULL)
4848 if (ifsfirst.endoff > endoff) {
4849 while (ifsfirst.next != NULL) {
4850 struct ifsregion *ifsp;
4852 ifsp = ifsfirst.next->next;
4853 ckfree(ifsfirst.next);
4854 ifsfirst.next = ifsp;
4857 if (ifsfirst.begoff > endoff)
4860 ifslastp = &ifsfirst;
4861 ifsfirst.endoff = endoff;
4866 ifslastp = &ifsfirst;
4867 while (ifslastp->next && ifslastp->next->begoff < endoff)
4868 ifslastp=ifslastp->next;
4869 while (ifslastp->next != NULL) {
4870 struct ifsregion *ifsp;
4872 ifsp = ifslastp->next->next;
4873 ckfree(ifslastp->next);
4874 ifslastp->next = ifsp;
4877 if (ifslastp->endoff > endoff)
4878 ifslastp->endoff = endoff;
4882 #ifdef CONFIG_ASH_MATH_SUPPORT
4884 * Expand arithmetic expression. Backup to start of expression,
4885 * evaluate, place result in (backed up) result, adjust string position.
4898 * This routine is slightly over-complicated for
4899 * efficiency. Next we scan backwards looking for the
4900 * start of arithmetic.
4902 start = stackblock();
4909 while (*p != CTLARI) {
4913 sh_error("missing CTLARI (shouldn't happen)");
4918 esc = esclen(start, p);
4928 removerecordregions(begoff);
4937 len = cvtnum(dash_arith(p + 2));
4940 recordregion(begoff, begoff + len, 0);
4945 * Expand stuff in backwards quotes.
4949 expbackq(union node *cmd, int quoted, int quotes)
4957 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4958 struct stackmark smark;
4961 setstackmark(&smark);
4963 startloc = dest - (char *)stackblock();
4965 evalbackcmd(cmd, (struct backcmd *) &in);
4966 popstackmark(&smark);
4973 memtodest(p, i, syntax, quotes);
4977 i = safe_read(in.fd, buf, sizeof buf);
4978 TRACE(("expbackq: read returns %d\n", i));
4988 back_exitstatus = waitforjob(in.jp);
4992 /* Eat all trailing newlines */
4994 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4999 recordregion(startloc, dest - (char *)stackblock(), 0);
5000 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5001 (dest - (char *)stackblock()) - startloc,
5002 (dest - (char *)stackblock()) - startloc,
5003 stackblock() + startloc));
5008 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5019 const char *s = loc2;
5025 match = pmatch(str, s);
5029 if (quotes && *loc == CTLESC)
5039 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5046 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5049 const char *s = loc2;
5054 match = pmatch(str, s);
5061 esc = esclen(startp, loc);
5073 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5077 int saveherefd = herefd;
5078 struct nodelist *saveargbackq = argbackq;
5080 char *rmesc, *rmescend;
5082 char *(*scan)(char *, char *, char *, char *, int , int);
5085 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5086 STPUTC('\0', expdest);
5087 herefd = saveherefd;
5088 argbackq = saveargbackq;
5089 startp = stackblock() + startloc;
5093 setvar(str, startp, 0);
5094 amount = startp - expdest;
5095 STADJUST(amount, expdest);
5099 varunset(p, str, startp, varflags);
5103 subtype -= VSTRIMRIGHT;
5105 if (subtype < 0 || subtype > 3)
5110 rmescend = stackblock() + strloc;
5112 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5113 if (rmesc != startp) {
5115 startp = stackblock() + startloc;
5119 str = stackblock() + strloc;
5120 preglob(str, varflags & VSQUOTE, 0);
5122 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5123 zero = subtype >> 1;
5124 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5125 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5127 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5130 memmove(startp, loc, str - loc);
5131 loc = startp + (str - loc) - 1;
5134 amount = loc - expdest;
5135 STADJUST(amount, expdest);
5142 * Expand a variable, and return a pointer to the next character in the
5146 evalvar(char *p, int flag)
5159 quotes = flag & (EXP_FULL | EXP_CASE);
5161 subtype = varflags & VSTYPE;
5162 quoted = varflags & VSQUOTE;
5164 easy = (!quoted || (*var == '@' && shellparam.nparam));
5165 startloc = expdest - (char *)stackblock();
5166 p = strchr(p, '=') + 1;
5169 varlen = varvalue(var, varflags, flag);
5170 if (varflags & VSNUL)
5173 if (subtype == VSPLUS) {
5174 varlen = -1 - varlen;
5178 if (subtype == VSMINUS) {
5182 p, flag | EXP_TILDE |
5183 (quoted ? EXP_QWORD : EXP_WORD)
5192 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5194 if (subevalvar(p, var, 0, subtype, startloc,
5198 * Remove any recorded regions beyond
5201 removerecordregions(startloc);
5211 if (varlen < 0 && uflag)
5212 varunset(p, var, 0, 0);
5214 if (subtype == VSLENGTH) {
5215 cvtnum(varlen > 0 ? varlen : 0);
5219 if (subtype == VSNORMAL) {
5223 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5232 case VSTRIMRIGHTMAX:
5241 * Terminate the string and start recording the pattern
5244 STPUTC('\0', expdest);
5245 patloc = expdest - (char *)stackblock();
5246 if (subevalvar(p, NULL, patloc, subtype,
5247 startloc, varflags, quotes) == 0) {
5248 int amount = expdest - (
5249 (char *)stackblock() + patloc - 1
5251 STADJUST(-amount, expdest);
5253 /* Remove any recorded regions beyond start of variable */
5254 removerecordregions(startloc);
5259 if (subtype != VSNORMAL) { /* skip to end of alternative */
5262 if ((c = *p++) == CTLESC)
5264 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5266 argbackq = argbackq->next;
5267 } else if (c == CTLVAR) {
5268 if ((*p++ & VSTYPE) != VSNORMAL)
5270 } else if (c == CTLENDVAR) {
5281 * Put a string on the stack.
5285 memtodest(const char *p, size_t len, int syntax, int quotes) {
5288 q = makestrspace(len * 2, q);
5291 int c = SC2INT(*p++);
5294 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5304 strtodest(const char *p, int syntax, int quotes)
5306 memtodest(p, strlen(p), syntax, quotes);
5311 * Add the value of a specialized variable to the stack string.
5315 varvalue(char *name, int varflags, int flags)
5325 int quoted = varflags & VSQUOTE;
5326 int subtype = varflags & VSTYPE;
5327 int quotes = flags & (EXP_FULL | EXP_CASE);
5329 if (quoted && (flags & EXP_FULL))
5330 sep = 1 << CHAR_BIT;
5332 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5341 num = shellparam.nparam;
5351 p = makestrspace(NOPTS, expdest);
5352 for (i = NOPTS - 1; i >= 0; i--) {
5354 USTPUTC(optletters(i), p);
5365 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5366 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5369 if (!(ap = shellparam.p))
5371 while ((p = *ap++)) {
5374 partlen = strlen(p);
5377 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5378 memtodest(p, partlen, syntax, quotes);
5384 if (subtype == VSPLUS || subtype == VSLENGTH) {
5406 if (num < 0 || num > shellparam.nparam)
5408 p = num ? shellparam.p[num - 1] : arg0;
5411 p = lookupvar(name);
5417 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5418 memtodest(p, len, syntax, quotes);
5422 if (subtype == VSPLUS || subtype == VSLENGTH)
5423 STADJUST(-len, expdest);
5429 * Record the fact that we have to scan this region of the
5430 * string for IFS characters.
5434 recordregion(int start, int end, int nulonly)
5436 struct ifsregion *ifsp;
5438 if (ifslastp == NULL) {
5442 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5444 ifslastp->next = ifsp;
5448 ifslastp->begoff = start;
5449 ifslastp->endoff = end;
5450 ifslastp->nulonly = nulonly;
5455 * Break the argument string into pieces based upon IFS and add the
5456 * strings to the argument list. The regions of the string to be
5457 * searched for IFS characters have been stored by recordregion.
5460 ifsbreakup(char *string, struct arglist *arglist)
5462 struct ifsregion *ifsp;
5467 const char *ifs, *realifs;
5473 if (ifslastp != NULL) {
5476 realifs = ifsset() ? ifsval() : defifs;
5479 p = string + ifsp->begoff;
5480 nulonly = ifsp->nulonly;
5481 ifs = nulonly ? nullstr : realifs;
5483 while (p < string + ifsp->endoff) {
5487 if (strchr(ifs, *p)) {
5489 ifsspc = (strchr(defifs, *p) != NULL);
5490 /* Ignore IFS whitespace at start */
5491 if (q == start && ifsspc) {
5497 sp = (struct strlist *)stalloc(sizeof *sp);
5499 *arglist->lastp = sp;
5500 arglist->lastp = &sp->next;
5504 if (p >= string + ifsp->endoff) {
5510 if (strchr(ifs, *p) == NULL ) {
5513 } else if (strchr(defifs, *p) == NULL) {
5529 } while ((ifsp = ifsp->next) != NULL);
5538 sp = (struct strlist *)stalloc(sizeof *sp);
5540 *arglist->lastp = sp;
5541 arglist->lastp = &sp->next;
5547 struct ifsregion *p;
5552 struct ifsregion *ifsp;
5558 ifsfirst.next = NULL;
5562 static void expmeta(char *, char *);
5563 static struct strlist *expsort(struct strlist *);
5564 static struct strlist *msort(struct strlist *, int);
5566 static char *expdir;
5570 expandmeta(struct strlist *str, int flag)
5572 static const char metachars[] = {
5575 /* TODO - EXP_REDIR */
5578 struct strlist **savelastp;
5584 if (!strpbrk(str->text, metachars))
5586 savelastp = exparg.lastp;
5589 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5591 int i = strlen(str->text);
5592 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5600 if (exparg.lastp == savelastp) {
5605 *exparg.lastp = str;
5606 rmescapes(str->text);
5607 exparg.lastp = &str->next;
5609 *exparg.lastp = NULL;
5610 *savelastp = sp = expsort(*savelastp);
5611 while (sp->next != NULL)
5613 exparg.lastp = &sp->next;
5620 * Add a file name to the list.
5624 addfname(const char *name)
5628 sp = (struct strlist *)stalloc(sizeof *sp);
5629 sp->text = sstrdup(name);
5631 exparg.lastp = &sp->next;
5636 * Do metacharacter (i.e. *, ?, [...]) expansion.
5640 expmeta(char *enddir, char *name)
5655 for (p = name; *p; p++) {
5656 if (*p == '*' || *p == '?')
5658 else if (*p == '[') {
5665 if (*q == '/' || *q == '\0')
5672 } else if (*p == '\\')
5674 else if (*p == '/') {
5681 if (metaflag == 0) { /* we've reached the end of the file name */
5682 if (enddir != expdir)
5690 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5701 } while (p < start);
5703 if (enddir == expdir) {
5705 } else if (enddir == expdir + 1 && *expdir == '/') {
5711 if ((dirp = opendir(cp)) == NULL)
5713 if (enddir != expdir)
5715 if (*endname == 0) {
5727 while (! intpending && (dp = readdir(dirp)) != NULL) {
5728 if (dp->d_name[0] == '.' && ! matchdot)
5730 if (pmatch(start, dp->d_name)) {
5732 scopy(dp->d_name, enddir);
5735 for (p = enddir, cp = dp->d_name;
5736 (*p++ = *cp++) != '\0';)
5739 expmeta(p, endname);
5749 * Sort the results of file name expansion. It calculates the number of
5750 * strings to sort and then calls msort (short for merge sort) to do the
5754 static struct strlist *
5755 expsort(struct strlist *str)
5761 for (sp = str ; sp ; sp = sp->next)
5763 return msort(str, len);
5767 static struct strlist *
5768 msort(struct strlist *list, int len)
5770 struct strlist *p, *q = NULL;
5771 struct strlist **lpp;
5779 for (n = half ; --n >= 0 ; ) {
5783 q->next = NULL; /* terminate first half of list */
5784 q = msort(list, half); /* sort first half of list */
5785 p = msort(p, len - half); /* sort second half */
5788 #ifdef CONFIG_LOCALE_SUPPORT
5789 if (strcoll(p->text, q->text) < 0)
5791 if (strcmp(p->text, q->text) < 0)
5796 if ((p = *lpp) == NULL) {
5803 if ((q = *lpp) == NULL) {
5814 * Returns true if the pattern matches the string.
5817 static int patmatch(char *pattern, const char *string)
5819 return pmatch(preglob(pattern, 0, 0), string);
5824 * Remove any CTLESC characters from a string.
5828 _rmescapes(char *str, int flag)
5831 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5836 p = strpbrk(str, qchars);
5842 if (flag & RMESCAPE_ALLOC) {
5843 size_t len = p - str;
5844 size_t fulllen = len + strlen(p) + 1;
5846 if (flag & RMESCAPE_GROW) {
5847 r = makestrspace(fulllen, expdest);
5848 } else if (flag & RMESCAPE_HEAP) {
5849 r = ckmalloc(fulllen);
5851 r = stalloc(fulllen);
5855 q = mempcpy(q, str, len);
5858 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5859 globbing = flag & RMESCAPE_GLOB;
5860 notescaped = globbing;
5862 if (*p == CTLQUOTEMARK) {
5863 inquotes = ~inquotes;
5865 notescaped = globbing;
5869 /* naked back slash */
5875 if (notescaped && inquotes && *p != '/') {
5879 notescaped = globbing;
5884 if (flag & RMESCAPE_GROW) {
5886 STADJUST(q - r + 1, expdest);
5893 * See if a pattern matches in a case statement.
5897 casematch(union node *pattern, char *val)
5899 struct stackmark smark;
5902 setstackmark(&smark);
5903 argbackq = pattern->narg.backquote;
5904 STARTSTACKSTR(expdest);
5906 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5907 STACKSTRNUL(expdest);
5908 result = patmatch(stackblock(), val);
5909 popstackmark(&smark);
5922 expdest = makestrspace(32, expdest);
5923 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5924 len = fmtstr(expdest, 32, "%lld", (long long) num);
5926 len = fmtstr(expdest, 32, "%ld", num);
5928 STADJUST(len, expdest);
5933 varunset(const char *end, const char *var, const char *umsg, int varflags)
5939 msg = "parameter not set";
5941 if (*end == CTLENDVAR) {
5942 if (varflags & VSNUL)
5947 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5954 * This implements the input routines used by the parser.
5957 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5959 static void pushfile(void);
5962 * Read a character from the script, returning PEOF on end of file.
5963 * Nul characters in the input are silently discarded.
5967 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5969 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5970 #define pgetc_macro() pgetc()
5974 return pgetc_as_macro();
5977 #define pgetc_macro() pgetc_as_macro()
5981 return pgetc_macro();
5987 * Same as pgetc(), but ignores PEOA.
5989 #ifdef CONFIG_ASH_ALIAS
5990 static int pgetc2(void)
5996 } while (c == PEOA);
6000 static int pgetc2(void)
6002 return pgetc_macro();
6007 * Read a line from the script.
6010 static char * pfgets(char *line, int len)
6016 while (--nleft > 0) {
6033 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6034 #ifdef CONFIG_ASH_EXPAND_PRMT
6035 static char *cmdedit_prompt;
6037 static const char *cmdedit_prompt;
6039 static void putprompt(const char *s)
6041 #ifdef CONFIG_ASH_EXPAND_PRMT
6042 free(cmdedit_prompt);
6043 cmdedit_prompt = xstrdup(s);
6049 static void putprompt(const char *s)
6055 static int preadfd(void)
6058 char *buf = parsefile->buf;
6062 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6063 if (!iflag || parsefile->fd)
6064 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6066 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6067 cmdedit_path_lookup = pathval();
6069 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6071 /* Ctrl+C presend */
6080 if(nr < 0 && errno == 0) {
6081 /* Ctrl+D presend */
6086 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6090 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6091 int flags = fcntl(0, F_GETFL, 0);
6092 if (flags >= 0 && flags & O_NONBLOCK) {
6093 flags &=~ O_NONBLOCK;
6094 if (fcntl(0, F_SETFL, flags) >= 0) {
6095 out2str("sh: turning off NDELAY mode\n");
6105 * Refill the input buffer and return the next input character:
6107 * 1) If a string was pushed back on the input, pop it;
6108 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6109 * from a string so we can't refill the buffer, return EOF.
6110 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6111 * 4) Process input up to the next newline, deleting nul characters.
6121 while (parsefile->strpush) {
6122 #ifdef CONFIG_ASH_ALIAS
6123 if (parsenleft == -1 && parsefile->strpush->ap &&
6124 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6129 if (--parsenleft >= 0)
6130 return SC2INT(*parsenextc++);
6132 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6139 if ((more = preadfd()) <= 0) {
6140 parselleft = parsenleft = EOF_NLEFT;
6147 /* delete nul characters */
6155 memmove(q, q + 1, more);
6159 parsenleft = q - parsenextc - 1;
6165 parsenleft = q - parsenextc - 1;
6177 out2str(parsenextc);
6182 return SC2INT(*parsenextc++);
6186 * Undo the last call to pgetc. Only one character may be pushed back.
6187 * PEOF may be pushed back.
6198 * Push a string back onto the input at this current parsefile level.
6199 * We handle aliases this way.
6202 pushstring(char *s, void *ap)
6209 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6210 if (parsefile->strpush) {
6211 sp = ckmalloc(sizeof (struct strpush));
6212 sp->prev = parsefile->strpush;
6213 parsefile->strpush = sp;
6215 sp = parsefile->strpush = &(parsefile->basestrpush);
6216 sp->prevstring = parsenextc;
6217 sp->prevnleft = parsenleft;
6218 #ifdef CONFIG_ASH_ALIAS
6219 sp->ap = (struct alias *)ap;
6221 ((struct alias *)ap)->flag |= ALIASINUSE;
6233 struct strpush *sp = parsefile->strpush;
6236 #ifdef CONFIG_ASH_ALIAS
6238 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6239 checkkwd |= CHKALIAS;
6241 if (sp->string != sp->ap->val) {
6244 sp->ap->flag &= ~ALIASINUSE;
6245 if (sp->ap->flag & ALIASDEAD) {
6246 unalias(sp->ap->name);
6250 parsenextc = sp->prevstring;
6251 parsenleft = sp->prevnleft;
6252 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6253 parsefile->strpush = sp->prev;
6254 if (sp != &(parsefile->basestrpush))
6260 * Set the input to take input from a file. If push is set, push the
6261 * old input onto the stack first.
6265 setinputfile(const char *fname, int flags)
6271 if ((fd = open(fname, O_RDONLY)) < 0) {
6272 if (flags & INPUT_NOFILE_OK)
6274 sh_error("Can't open %s", fname);
6277 fd2 = copyfd(fd, 10);
6280 sh_error("Out of file descriptors");
6283 setinputfd(fd, flags & INPUT_PUSH_FILE);
6291 * Like setinputfile, but takes an open file descriptor. Call this with
6296 setinputfd(int fd, int push)
6298 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6304 if (parsefile->buf == NULL)
6305 parsefile->buf = ckmalloc(IBUFSIZ);
6306 parselleft = parsenleft = 0;
6312 * Like setinputfile, but takes input from a string.
6316 setinputstring(char *string)
6320 parsenextc = string;
6321 parsenleft = strlen(string);
6322 parsefile->buf = NULL;
6329 * To handle the "." command, a stack of input files is used. Pushfile
6330 * adds a new entry to the stack and popfile restores the previous level.
6336 struct parsefile *pf;
6338 parsefile->nleft = parsenleft;
6339 parsefile->lleft = parselleft;
6340 parsefile->nextc = parsenextc;
6341 parsefile->linno = plinno;
6342 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6343 pf->prev = parsefile;
6346 pf->basestrpush.prev = NULL;
6354 struct parsefile *pf = parsefile;
6363 parsefile = pf->prev;
6365 parsenleft = parsefile->nleft;
6366 parselleft = parsefile->lleft;
6367 parsenextc = parsefile->nextc;
6368 plinno = parsefile->linno;
6374 * Return to top level.
6380 while (parsefile != &basepf)
6386 * Close the file(s) that the shell is reading commands from. Called
6387 * after a fork is done.
6394 if (parsefile->fd > 0) {
6395 close(parsefile->fd);
6402 /* mode flags for set_curjob */
6403 #define CUR_DELETE 2
6404 #define CUR_RUNNING 1
6405 #define CUR_STOPPED 0
6407 /* mode flags for dowait */
6408 #define DOWAIT_NORMAL 0
6409 #define DOWAIT_BLOCK 1
6412 static struct job *jobtab;
6414 static unsigned njobs;
6416 /* pgrp of shell on invocation */
6417 static int initialpgrp;
6418 static int ttyfd = -1;
6421 static struct job *curjob;
6422 /* number of presumed living untracked jobs */
6425 static void set_curjob(struct job *, unsigned);
6427 static int restartjob(struct job *, int);
6428 static void xtcsetpgrp(int, pid_t);
6429 static char *commandtext(union node *);
6430 static void cmdlist(union node *, int);
6431 static void cmdtxt(union node *);
6432 static void cmdputs(const char *);
6433 static void showpipe(struct job *, FILE *);
6435 static int sprint_status(char *, int, int);
6436 static void freejob(struct job *);
6437 static struct job *getjob(const char *, int);
6438 static struct job *growjobtab(void);
6439 static void forkchild(struct job *, union node *, int);
6440 static void forkparent(struct job *, union node *, int, pid_t);
6441 static int dowait(int, struct job *);
6442 static int getstatus(struct job *);
6445 set_curjob(struct job *jp, unsigned mode)
6448 struct job **jpp, **curp;
6450 /* first remove from list */
6451 jpp = curp = &curjob;
6456 jpp = &jp1->prev_job;
6458 *jpp = jp1->prev_job;
6460 /* Then re-insert in correct position */
6468 /* job being deleted */
6471 /* newly created job or backgrounded job,
6472 put after all stopped jobs. */
6476 if (!jp1 || jp1->state != JOBSTOPPED)
6479 jpp = &jp1->prev_job;
6485 /* newly stopped job - becomes curjob */
6486 jp->prev_job = *jpp;
6494 * Turn job control on and off.
6496 * Note: This code assumes that the third arg to ioctl is a character
6497 * pointer, which is true on Berkeley systems but not System V. Since
6498 * System V doesn't have job control yet, this isn't a problem now.
6500 * Called with interrupts off.
6509 if (on == jobctl || rootshell == 0)
6513 ofd = fd = open(_PATH_TTY, O_RDWR);
6516 while (!isatty(fd) && --fd >= 0)
6519 fd = fcntl(fd, F_DUPFD, 10);
6523 fcntl(fd, F_SETFD, FD_CLOEXEC);
6524 do { /* while we are in the background */
6525 if ((pgrp = tcgetpgrp(fd)) < 0) {
6527 sh_warnx("can't access tty; job control turned off");
6531 if (pgrp == getpgrp())
6542 xtcsetpgrp(fd, pgrp);
6544 /* turning job control off */
6547 xtcsetpgrp(fd, pgrp);
6561 killcmd(int argc, char **argv)
6572 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6573 "kill -l [exitstatus]"
6577 if (**++argv == '-') {
6578 signo = get_signum(*argv + 1);
6582 while ((c = nextopt("ls:")) != '\0')
6592 signo = get_signum(optionarg);
6595 "invalid signal number or name: %s",
6606 if (!list && signo < 0)
6609 if ((signo < 0 || !*argv) ^ list) {
6617 for (i = 1; i < NSIG; i++) {
6618 name = get_signame(i);
6620 out1fmt(snlfmt, name);
6624 name = get_signame(signo);
6626 out1fmt(snlfmt, name);
6628 sh_error("invalid signal number or exit status: %s", *argptr);
6634 if (**argv == '%') {
6635 jp = getjob(*argv, 0);
6636 pid = -jp->ps[0].pid;
6638 pid = **argv == '-' ?
6639 -number(*argv + 1) : number(*argv);
6641 if (kill(pid, signo) != 0) {
6642 sh_warnx("(%d) - %m", pid);
6651 #if defined(JOBS) || DEBUG
6653 jobno(const struct job *jp)
6655 return jp - jobtab + 1;
6661 fgcmd(int argc, char **argv)
6668 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6673 jp = getjob(*argv, 1);
6674 if (mode == FORK_BG) {
6675 set_curjob(jp, CUR_RUNNING);
6676 fprintf(out, "[%d] ", jobno(jp));
6678 outstr(jp->ps->cmd, out);
6680 retval = restartjob(jp, mode);
6681 } while (*argv && *++argv);
6685 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6689 restartjob(struct job *jp, int mode)
6691 struct procstat *ps;
6697 if (jp->state == JOBDONE)
6699 jp->state = JOBRUNNING;
6701 if (mode == FORK_FG)
6702 xtcsetpgrp(ttyfd, pgid);
6703 killpg(pgid, SIGCONT);
6707 if (WIFSTOPPED(ps->status)) {
6710 } while (ps++, --i);
6712 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6719 sprint_status(char *s, int status, int sigonly)
6725 if (!WIFEXITED(status)) {
6727 if (WIFSTOPPED(status))
6728 st = WSTOPSIG(status);
6731 st = WTERMSIG(status);
6733 if (st == SIGINT || st == SIGPIPE)
6736 if (WIFSTOPPED(status))
6741 col = fmtstr(s, 32, strsignal(st));
6742 if (WCOREDUMP(status)) {
6743 col += fmtstr(s + col, 16, " (core dumped)");
6745 } else if (!sigonly) {
6746 st = WEXITSTATUS(status);
6748 col = fmtstr(s, 16, "Done(%d)", st);
6750 col = fmtstr(s, 16, "Done");
6759 showjob(FILE *out, struct job *jp, int mode)
6761 struct procstat *ps;
6762 struct procstat *psend;
6769 if (mode & SHOW_PGID) {
6770 /* just output process (group) id of pipeline */
6771 fprintf(out, "%d\n", ps->pid);
6775 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6780 else if (curjob && jp == curjob->prev_job)
6783 if (mode & SHOW_PID)
6784 col += fmtstr(s + col, 16, "%d ", ps->pid);
6786 psend = ps + jp->nprocs;
6788 if (jp->state == JOBRUNNING) {
6789 scopy("Running", s + col);
6790 col += strlen("Running");
6792 int status = psend[-1].status;
6794 if (jp->state == JOBSTOPPED)
6795 status = jp->stopstatus;
6797 col += sprint_status(s + col, status, 0);
6803 /* for each process */
6804 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6807 fprintf(out, "%s%*c%s",
6808 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6810 if (!(mode & SHOW_PID)) {
6814 if (++ps == psend) {
6815 outcslow('\n', out);
6822 if (jp->state == JOBDONE) {
6823 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6830 jobscmd(int argc, char **argv)
6836 while ((m = nextopt("lp")))
6846 showjob(out, getjob(*argv,0), mode);
6849 showjobs(out, mode);
6856 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6857 * statuses have changed since the last call to showjobs.
6861 showjobs(FILE *out, int mode)
6865 TRACE(("showjobs(%x) called\n", mode));
6867 /* If not even one one job changed, there is nothing to do */
6868 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6871 for (jp = curjob; jp; jp = jp->prev_job) {
6872 if (!(mode & SHOW_CHANGED) || jp->changed)
6873 showjob(out, jp, mode);
6879 * Mark a job structure as unused.
6883 freejob(struct job *jp)
6885 struct procstat *ps;
6889 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6890 if (ps->cmd != nullstr)
6893 if (jp->ps != &jp->ps0)
6896 set_curjob(jp, CUR_DELETE);
6902 waitcmd(int argc, char **argv)
6915 /* wait for all jobs */
6920 /* no running procs */
6923 if (jp->state == JOBRUNNING)
6928 dowait(DOWAIT_BLOCK, 0);
6934 if (**argv != '%') {
6935 pid_t pid = number(*argv);
6939 if (job->ps[job->nprocs - 1].pid == pid)
6941 job = job->prev_job;
6947 job = getjob(*argv, 0);
6948 /* loop until process terminated or stopped */
6949 while (job->state == JOBRUNNING)
6950 dowait(DOWAIT_BLOCK, 0);
6952 retval = getstatus(job);
6963 * Convert a job name to a job structure.
6967 getjob(const char *name, int getctl)
6971 const char *err_msg = "No such job: %s";
6975 char *(*match)(const char *, const char *);
6990 if (c == '+' || c == '%') {
6992 err_msg = "No current job";
6994 } else if (c == '-') {
6997 err_msg = "No previous job";
7008 jp = jobtab + num - 1;
7025 if (match(jp->ps[0].cmd, p)) {
7029 err_msg = "%s: ambiguous";
7036 err_msg = "job %s not created under job control";
7037 if (getctl && jp->jobctl == 0)
7042 sh_error(err_msg, name);
7047 * Return a new job structure.
7048 * Called with interrupts off.
7052 makejob(union node *node, int nprocs)
7057 for (i = njobs, jp = jobtab ; ; jp++) {
7064 if (jp->state != JOBDONE || !jp->waited)
7073 memset(jp, 0, sizeof(*jp));
7078 jp->prev_job = curjob;
7083 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7085 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7095 struct job *jp, *jq;
7097 len = njobs * sizeof(*jp);
7099 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7101 offset = (char *)jp - (char *)jq;
7103 /* Relocate pointers */
7106 jq = (struct job *)((char *)jq + l);
7110 #define joff(p) ((struct job *)((char *)(p) + l))
7111 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7112 if (xlikely(joff(jp)->ps == &jq->ps0))
7113 jmove(joff(jp)->ps);
7114 if (joff(jp)->prev_job)
7115 jmove(joff(jp)->prev_job);
7125 jp = (struct job *)((char *)jp + len);
7129 } while (--jq >= jp);
7135 * Fork off a subshell. If we are doing job control, give the subshell its
7136 * own process group. Jp is a job structure that the job is to be added to.
7137 * N is the command that will be evaluated by the child. Both jp and n may
7138 * be NULL. The mode parameter can be one of the following:
7139 * FORK_FG - Fork off a foreground process.
7140 * FORK_BG - Fork off a background process.
7141 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7142 * process group even if job control is on.
7144 * When job control is turned off, background processes have their standard
7145 * input redirected to /dev/null (except for the second and later processes
7148 * Called with interrupts off.
7151 static void forkchild(struct job *jp, union node *n, int mode)
7155 TRACE(("Child shell %d\n", getpid()));
7162 /* do job control only in root shell */
7164 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7167 if (jp->nprocs == 0)
7170 pgrp = jp->ps[0].pid;
7171 /* This can fail because we are doing it in the parent also */
7172 (void)setpgid(0, pgrp);
7173 if (mode == FORK_FG)
7174 xtcsetpgrp(ttyfd, pgrp);
7179 if (mode == FORK_BG) {
7182 if (jp->nprocs == 0) {
7184 if (open(bb_dev_null, O_RDONLY) != 0)
7185 sh_error("Can't open %s", bb_dev_null);
7188 if (!oldlvl && iflag) {
7193 for (jp = curjob; jp; jp = jp->prev_job)
7198 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7200 TRACE(("In parent shell: child = %d\n", pid));
7202 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7207 if (mode != FORK_NOJOB && jp->jobctl) {
7210 if (jp->nprocs == 0)
7213 pgrp = jp->ps[0].pid;
7214 /* This can fail because we are doing it in the child also */
7215 (void)setpgid(pid, pgrp);
7218 if (mode == FORK_BG) {
7219 backgndpid = pid; /* set $! */
7220 set_curjob(jp, CUR_RUNNING);
7223 struct procstat *ps = &jp->ps[jp->nprocs++];
7229 ps->cmd = commandtext(n);
7235 forkshell(struct job *jp, union node *n, int mode)
7239 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7242 TRACE(("Fork failed, errno=%d", errno));
7245 sh_error("Cannot fork");
7248 forkchild(jp, n, mode);
7250 forkparent(jp, n, mode, pid);
7255 * Wait for job to finish.
7257 * Under job control we have the problem that while a child process is
7258 * running interrupts generated by the user are sent to the child but not
7259 * to the shell. This means that an infinite loop started by an inter-
7260 * active user may be hard to kill. With job control turned off, an
7261 * interactive user may place an interactive program inside a loop. If
7262 * the interactive program catches interrupts, the user doesn't want
7263 * these interrupts to also abort the loop. The approach we take here
7264 * is to have the shell ignore interrupt signals while waiting for a
7265 * foreground process to terminate, and then send itself an interrupt
7266 * signal if the child process was terminated by an interrupt signal.
7267 * Unfortunately, some programs want to do a bit of cleanup and then
7268 * exit on interrupt; unless these processes terminate themselves by
7269 * sending a signal to themselves (instead of calling exit) they will
7270 * confuse this approach.
7272 * Called with interrupts off.
7276 waitforjob(struct job *jp)
7280 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7281 while (jp->state == JOBRUNNING) {
7282 dowait(DOWAIT_BLOCK, jp);
7287 xtcsetpgrp(ttyfd, rootpid);
7289 * This is truly gross.
7290 * If we're doing job control, then we did a TIOCSPGRP which
7291 * caused us (the shell) to no longer be in the controlling
7292 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7293 * intuit from the subprocess exit status whether a SIGINT
7294 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7299 if (jp->state == JOBDONE)
7307 * Do a wait system call. If job control is compiled in, we accept
7308 * stopped processes. If block is zero, we return a value of zero
7309 * rather than blocking.
7311 * System V doesn't have a non-blocking wait system call. It does
7312 * have a SIGCLD signal that is sent to a process when one of it's
7313 * children dies. The obvious way to use SIGCLD would be to install
7314 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7315 * was received, and have waitproc bump another counter when it got
7316 * the status of a process. Waitproc would then know that a wait
7317 * system call would not block if the two counters were different.
7318 * This approach doesn't work because if a process has children that
7319 * have not been waited for, System V will send it a SIGCLD when it
7320 * installs a signal handler for SIGCLD. What this means is that when
7321 * a child exits, the shell will be sent SIGCLD signals continuously
7322 * until is runs out of stack space, unless it does a wait call before
7323 * restoring the signal handler. The code below takes advantage of
7324 * this (mis)feature by installing a signal handler for SIGCLD and
7325 * then checking to see whether it was called. If there are any
7326 * children to be waited for, it will be.
7328 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7329 * waits at all. In this case, the user will not be informed when
7330 * a background process until the next time she runs a real program
7331 * (as opposed to running a builtin command or just typing return),
7332 * and the jobs command may give out of date information.
7335 static int waitproc(int block, int *status)
7345 return wait3(status, flags, (struct rusage *)NULL);
7349 * Wait for a process to terminate.
7353 dowait(int block, struct job *job)
7358 struct job *thisjob;
7361 TRACE(("dowait(%d) called\n", block));
7362 pid = waitproc(block, &status);
7363 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7368 for (jp = curjob; jp; jp = jp->prev_job) {
7369 struct procstat *sp;
7370 struct procstat *spend;
7371 if (jp->state == JOBDONE)
7374 spend = jp->ps + jp->nprocs;
7377 if (sp->pid == pid) {
7378 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7379 sp->status = status;
7382 if (sp->status == -1)
7385 if (state == JOBRUNNING)
7387 if (WIFSTOPPED(sp->status)) {
7388 jp->stopstatus = sp->status;
7392 } while (++sp < spend);
7397 if (!WIFSTOPPED(status))
7404 if (state != JOBRUNNING) {
7405 thisjob->changed = 1;
7407 if (thisjob->state != state) {
7408 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7409 thisjob->state = state;
7411 if (state == JOBSTOPPED) {
7412 set_curjob(thisjob, CUR_STOPPED);
7421 if (thisjob && thisjob == job) {
7425 len = sprint_status(s, status, 1);
7437 * return 1 if there are stopped jobs, otherwise 0
7450 if (jp && jp->state == JOBSTOPPED) {
7451 out2str("You have stopped jobs.\n");
7461 * Return a string identifying a command (to be printed by the
7466 static char *cmdnextc;
7469 commandtext(union node *n)
7473 STARTSTACKSTR(cmdnextc);
7475 name = stackblock();
7476 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7477 name, cmdnextc, cmdnextc));
7478 return savestr(name);
7482 cmdtxt(union node *n)
7485 struct nodelist *lp;
7497 lp = n->npipe.cmdlist;
7515 cmdtxt(n->nbinary.ch1);
7531 cmdtxt(n->nif.test);
7534 if (n->nif.elsepart) {
7537 n = n->nif.elsepart;
7553 cmdtxt(n->nbinary.ch1);
7563 cmdputs(n->nfor.var);
7565 cmdlist(n->nfor.args, 1);
7570 cmdputs(n->narg.text);
7574 cmdlist(n->ncmd.args, 1);
7575 cmdlist(n->ncmd.redirect, 0);
7588 cmdputs(n->ncase.expr->narg.text);
7590 for (np = n->ncase.cases; np; np = np->nclist.next) {
7591 cmdtxt(np->nclist.pattern);
7593 cmdtxt(np->nclist.body);
7619 s[0] = n->nfile.fd + '0';
7623 if (n->type == NTOFD || n->type == NFROMFD) {
7624 s[0] = n->ndup.dupfd + '0';
7635 cmdlist(union node *np, int sep)
7637 for (; np; np = np->narg.next) {
7641 if (sep && np->narg.next)
7647 cmdputs(const char *s)
7649 const char *p, *str;
7650 char c, cc[2] = " ";
7654 static const char vstype[VSTYPE + 1][4] = {
7655 "", "}", "-", "+", "?", "=",
7656 "%", "%%", "#", "##"
7658 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7660 while ((c = *p++) != 0) {
7668 if ((subtype & VSTYPE) == VSLENGTH)
7672 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7679 str = "\"}" + !(quoted & 1);
7686 case CTLBACKQ+CTLQUOTE:
7689 #ifdef CONFIG_ASH_MATH_SUPPORT
7704 if ((subtype & VSTYPE) != VSNORMAL)
7706 str = vstype[subtype & VSTYPE];
7707 if (subtype & VSNUL)
7716 /* These can only happen inside quotes */
7729 while ((c = *str++)) {
7734 USTPUTC('"', nextc);
7742 showpipe(struct job *jp, FILE *out)
7744 struct procstat *sp;
7745 struct procstat *spend;
7747 spend = jp->ps + jp->nprocs;
7748 for (sp = jp->ps + 1; sp < spend; sp++)
7749 fprintf(out, " | %s", sp->cmd);
7750 outcslow('\n', out);
7755 xtcsetpgrp(int fd, pid_t pgrp)
7757 if (tcsetpgrp(fd, pgrp))
7758 sh_error("Cannot set tty process group (%m)");
7763 getstatus(struct job *job) {
7767 status = job->ps[job->nprocs - 1].status;
7768 retval = WEXITSTATUS(status);
7769 if (!WIFEXITED(status)) {
7771 retval = WSTOPSIG(status);
7772 if (!WIFSTOPPED(status))
7775 /* XXX: limits number of signals */
7776 retval = WTERMSIG(status);
7778 if (retval == SIGINT)
7784 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7785 jobno(job), job->nprocs, status, retval));
7789 #ifdef CONFIG_ASH_MAIL
7793 * Routines to check for mail. (Perhaps make part of main.c?)
7796 #define MAXMBOXES 10
7798 /* times of mailboxes */
7799 static time_t mailtime[MAXMBOXES];
7800 /* Set if MAIL or MAILPATH is changed. */
7801 static int mail_var_path_changed;
7806 * Print appropriate message(s) if mail has arrived.
7807 * If mail_var_path_changed is set,
7808 * then the value of MAIL has mail_var_path_changed,
7809 * so we just update the values.
7819 struct stackmark smark;
7822 setstackmark(&smark);
7823 mpath = mpathset() ? mpathval() : mailval();
7824 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7825 p = padvance(&mpath, nullstr);
7830 for (q = p ; *q ; q++);
7835 q[-1] = '\0'; /* delete trailing '/' */
7836 if (stat(p, &statb) < 0) {
7840 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7843 pathopt ? pathopt : "you have mail"
7846 *mtp = statb.st_mtime;
7848 mail_var_path_changed = 0;
7849 popstackmark(&smark);
7854 changemail(const char *val)
7856 mail_var_path_changed++;
7859 #endif /* CONFIG_ASH_MAIL */
7865 static short profile_buf[16384];
7869 static int isloginsh;
7871 static void read_profile(const char *);
7874 * Main routine. We initialize things, parse the arguments, execute
7875 * profiles if we're a login shell, and then call cmdloop to execute
7876 * commands. The setjmp call sets up the location to jump to when an
7877 * exception occurs. When an exception occurs the variable "state"
7878 * is used to figure out how far we had gotten.
7882 ash_main(int argc, char **argv)
7886 struct jmploc jmploc;
7887 struct stackmark smark;
7890 dash_errno = __errno_location();
7894 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7897 if (setjmp(jmploc.loc)) {
7907 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7911 outcslow('\n', stderr);
7913 popstackmark(&smark);
7914 FORCEINTON; /* enable interrupts */
7927 trputs("Shell args: "); trargs(argv);
7931 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7932 rseed = rootpid + ((time_t)time((time_t *)0));
7935 setstackmark(&smark);
7936 procargs(argc, argv);
7937 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7939 const char *hp = lookupvar("HISTFILE");
7942 hp = lookupvar("HOME");
7944 char *defhp = concat_path_file(hp, ".ash_history");
7945 setvar("HISTFILE", defhp, 0);
7951 if (argv[0] && argv[0][0] == '-')
7955 read_profile("/etc/profile");
7958 read_profile(".profile");
7964 getuid() == geteuid() && getgid() == getegid() &&
7968 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7969 read_profile(shinit);
7975 evalstring(minusc, 0);
7977 if (sflag || minusc == NULL) {
7978 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7980 const char *hp = lookupvar("HISTFILE");
7983 load_history ( hp );
7986 state4: /* XXX ??? - why isn't this before the "if" statement */
7994 extern void _mcleanup(void);
8004 * Read and execute commands. "Top" is nonzero for the top level command
8005 * loop; it turns on prompting if the shell is interactive.
8012 struct stackmark smark;
8016 TRACE(("cmdloop(%d) called\n", top));
8020 setstackmark(&smark);
8023 showjobs(stderr, SHOW_CHANGED);
8028 #ifdef CONFIG_ASH_MAIL
8032 n = parsecmd(inter);
8033 /* showtree(n); DEBUG */
8035 if (!top || numeof >= 50)
8037 if (!stoppedjobs()) {
8040 out2str("\nUse \"exit\" to leave shell.\n");
8043 } else if (nflag == 0) {
8044 job_warning = (job_warning == 2) ? 1 : 0;
8048 popstackmark(&smark);
8053 return skip & SKIPEVAL;
8062 * Read /etc/profile or .profile. Return on error.
8066 read_profile(const char *name)
8070 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8082 * Read a file containing shell functions.
8086 readcmdfile(char *name)
8088 setinputfile(name, INPUT_PUSH_FILE);
8095 * Take commands from a file. To be compatible we should do a path
8096 * search for the file, which is necessary to find sub-commands.
8099 static char * find_dot_file(char *name)
8102 const char *path = pathval();
8105 /* don't try this for absolute or relative paths */
8106 if (strchr(name, '/'))
8109 while ((fullname = padvance(&path, name)) != NULL) {
8110 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8112 * Don't bother freeing here, since it will
8113 * be freed by the caller.
8117 stunalloc(fullname);
8120 /* not found in the PATH */
8121 sh_error(not_found_msg, name);
8125 static int dotcmd(int argc, char **argv)
8128 volatile struct shparam saveparam;
8131 for (sp = cmdenviron; sp; sp = sp->next)
8132 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8134 if (argc >= 2) { /* That's what SVR2 does */
8137 fullname = find_dot_file(argv[1]);
8140 saveparam = shellparam;
8141 shellparam.malloc = 0;
8142 shellparam.nparam = argc - 2;
8143 shellparam.p = argv + 2;
8146 setinputfile(fullname, INPUT_PUSH_FILE);
8147 commandname = fullname;
8152 freeparam(&shellparam);
8153 shellparam = saveparam;
8155 status = exitstatus;
8162 exitcmd(int argc, char **argv)
8167 exitstatus = number(argv[1]);
8172 #ifdef CONFIG_ASH_BUILTIN_ECHO
8174 echocmd(int argc, char **argv)
8176 return bb_echo(argc, argv);
8180 #ifdef CONFIG_ASH_BUILTIN_TEST
8182 testcmd(int argc, char **argv)
8184 return bb_test(argc, argv);
8191 * Same for malloc, realloc, but returns an error when out of space.
8195 ckrealloc(pointer p, size_t nbytes)
8197 p = realloc(p, nbytes);
8199 sh_error(bb_msg_memory_exhausted);
8204 ckmalloc(size_t nbytes)
8206 return ckrealloc(NULL, nbytes);
8210 * Make a copy of a string in safe storage.
8214 savestr(const char *s)
8216 char *p = strdup(s);
8218 sh_error(bb_msg_memory_exhausted);
8224 * Parse trees for commands are allocated in lifo order, so we use a stack
8225 * to make this more efficient, and also to avoid all sorts of exception
8226 * handling code to handle interrupts in the middle of a parse.
8228 * The size 504 was chosen because the Ultrix malloc handles that size
8234 stalloc(size_t nbytes)
8239 aligned = SHELL_ALIGN(nbytes);
8240 if (aligned > stacknleft) {
8243 struct stack_block *sp;
8245 blocksize = aligned;
8246 if (blocksize < MINSIZE)
8247 blocksize = MINSIZE;
8248 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8249 if (len < blocksize)
8250 sh_error(bb_msg_memory_exhausted);
8254 stacknxt = sp->space;
8255 stacknleft = blocksize;
8256 sstrend = stacknxt + blocksize;
8261 stacknxt += aligned;
8262 stacknleft -= aligned;
8268 stunalloc(pointer p)
8271 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8272 write(2, "stunalloc\n", 10);
8276 stacknleft += stacknxt - (char *)p;
8282 setstackmark(struct stackmark *mark)
8284 mark->stackp = stackp;
8285 mark->stacknxt = stacknxt;
8286 mark->stacknleft = stacknleft;
8287 mark->marknext = markp;
8293 popstackmark(struct stackmark *mark)
8295 struct stack_block *sp;
8298 markp = mark->marknext;
8299 while (stackp != mark->stackp) {
8304 stacknxt = mark->stacknxt;
8305 stacknleft = mark->stacknleft;
8306 sstrend = mark->stacknxt + mark->stacknleft;
8312 * When the parser reads in a string, it wants to stick the string on the
8313 * stack and only adjust the stack pointer when it knows how big the
8314 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8315 * of space on top of the stack and stackblocklen returns the length of
8316 * this block. Growstackblock will grow this space by at least one byte,
8317 * possibly moving it (like realloc). Grabstackblock actually allocates the
8318 * part of the block that has been used.
8322 growstackblock(void)
8326 newlen = stacknleft * 2;
8327 if (newlen < stacknleft)
8328 sh_error(bb_msg_memory_exhausted);
8332 if (stacknxt == stackp->space && stackp != &stackbase) {
8333 struct stack_block *oldstackp;
8334 struct stackmark *xmark;
8335 struct stack_block *sp;
8336 struct stack_block *prevstackp;
8342 prevstackp = sp->prev;
8343 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8344 sp = ckrealloc((pointer)sp, grosslen);
8345 sp->prev = prevstackp;
8347 stacknxt = sp->space;
8348 stacknleft = newlen;
8349 sstrend = sp->space + newlen;
8352 * Stack marks pointing to the start of the old block
8353 * must be relocated to point to the new block
8356 while (xmark != NULL && xmark->stackp == oldstackp) {
8357 xmark->stackp = stackp;
8358 xmark->stacknxt = stacknxt;
8359 xmark->stacknleft = stacknleft;
8360 xmark = xmark->marknext;
8364 char *oldspace = stacknxt;
8365 int oldlen = stacknleft;
8366 char *p = stalloc(newlen);
8368 /* free the space we just allocated */
8369 stacknxt = memcpy(p, oldspace, oldlen);
8370 stacknleft += newlen;
8374 static void grabstackblock(size_t len)
8376 len = SHELL_ALIGN(len);
8382 * The following routines are somewhat easier to use than the above.
8383 * The user declares a variable of type STACKSTR, which may be declared
8384 * to be a register. The macro STARTSTACKSTR initializes things. Then
8385 * the user uses the macro STPUTC to add characters to the string. In
8386 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8387 * grown as necessary. When the user is done, she can just leave the
8388 * string there and refer to it using stackblock(). Or she can allocate
8389 * the space for it using grabstackstr(). If it is necessary to allow
8390 * someone else to use the stack temporarily and then continue to grow
8391 * the string, the user should use grabstack to allocate the space, and
8392 * then call ungrabstr(p) to return to the previous mode of operation.
8394 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8395 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8396 * is space for at least one character.
8402 size_t len = stackblocksize();
8403 if (herefd >= 0 && len >= 1024) {
8404 full_write(herefd, stackblock(), len);
8405 return stackblock();
8408 return stackblock() + len;
8412 * Called from CHECKSTRSPACE.
8416 makestrspace(size_t newlen, char *p)
8418 size_t len = p - stacknxt;
8419 size_t size = stackblocksize();
8424 size = stackblocksize();
8426 if (nleft >= newlen)
8430 return stackblock() + len;
8434 stnputs(const char *s, size_t n, char *p)
8436 p = makestrspace(n, p);
8437 p = mempcpy(p, s, n);
8442 stputs(const char *s, char *p)
8444 return stnputs(s, strlen(s), p);
8452 * number(s) Convert a string of digits to an integer.
8453 * is_number(s) Return true if s is a string of digits.
8457 * prefix -- see if pfx is a prefix of string.
8461 prefix(const char *string, const char *pfx)
8464 if (*pfx++ != *string++)
8467 return (char *) string;
8472 * Convert a string of digits to an integer, printing an error message on
8477 number(const char *s)
8481 sh_error(illnum, s);
8487 * Check for a valid number. This should be elsewhere.
8491 is_number(const char *p)
8496 } while (*++p != '\0');
8502 * Produce a possibly single quoted string suitable as input to the shell.
8503 * The return string is allocated on the stack.
8507 single_quote(const char *s) {
8516 len = strchrnul(s, '\'') - s;
8518 q = p = makestrspace(len + 3, p);
8521 q = mempcpy(q, s, len);
8527 len = strspn(s, "'");
8531 q = p = makestrspace(len + 3, p);
8534 q = mempcpy(q, s, len);
8543 return stackblock();
8547 * Like strdup but works with the ash stack.
8551 sstrdup(const char *p)
8553 size_t len = strlen(p) + 1;
8554 return memcpy(stalloc(len), p, len);
8559 calcsize(union node *n)
8563 funcblocksize += nodesize[n->type];
8566 calcsize(n->ncmd.redirect);
8567 calcsize(n->ncmd.args);
8568 calcsize(n->ncmd.assign);
8571 sizenodelist(n->npipe.cmdlist);
8576 calcsize(n->nredir.redirect);
8577 calcsize(n->nredir.n);
8584 calcsize(n->nbinary.ch2);
8585 calcsize(n->nbinary.ch1);
8588 calcsize(n->nif.elsepart);
8589 calcsize(n->nif.ifpart);
8590 calcsize(n->nif.test);
8593 funcstringsize += strlen(n->nfor.var) + 1;
8594 calcsize(n->nfor.body);
8595 calcsize(n->nfor.args);
8598 calcsize(n->ncase.cases);
8599 calcsize(n->ncase.expr);
8602 calcsize(n->nclist.body);
8603 calcsize(n->nclist.pattern);
8604 calcsize(n->nclist.next);
8608 sizenodelist(n->narg.backquote);
8609 funcstringsize += strlen(n->narg.text) + 1;
8610 calcsize(n->narg.next);
8617 calcsize(n->nfile.fname);
8618 calcsize(n->nfile.next);
8622 calcsize(n->ndup.vname);
8623 calcsize(n->ndup.next);
8627 calcsize(n->nhere.doc);
8628 calcsize(n->nhere.next);
8631 calcsize(n->nnot.com);
8638 sizenodelist(struct nodelist *lp)
8641 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8649 copynode(union node *n)
8656 funcblock = (char *) funcblock + nodesize[n->type];
8659 new->ncmd.redirect = copynode(n->ncmd.redirect);
8660 new->ncmd.args = copynode(n->ncmd.args);
8661 new->ncmd.assign = copynode(n->ncmd.assign);
8664 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8665 new->npipe.backgnd = n->npipe.backgnd;
8670 new->nredir.redirect = copynode(n->nredir.redirect);
8671 new->nredir.n = copynode(n->nredir.n);
8678 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8679 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8682 new->nif.elsepart = copynode(n->nif.elsepart);
8683 new->nif.ifpart = copynode(n->nif.ifpart);
8684 new->nif.test = copynode(n->nif.test);
8687 new->nfor.var = nodesavestr(n->nfor.var);
8688 new->nfor.body = copynode(n->nfor.body);
8689 new->nfor.args = copynode(n->nfor.args);
8692 new->ncase.cases = copynode(n->ncase.cases);
8693 new->ncase.expr = copynode(n->ncase.expr);
8696 new->nclist.body = copynode(n->nclist.body);
8697 new->nclist.pattern = copynode(n->nclist.pattern);
8698 new->nclist.next = copynode(n->nclist.next);
8702 new->narg.backquote = copynodelist(n->narg.backquote);
8703 new->narg.text = nodesavestr(n->narg.text);
8704 new->narg.next = copynode(n->narg.next);
8711 new->nfile.fname = copynode(n->nfile.fname);
8712 new->nfile.fd = n->nfile.fd;
8713 new->nfile.next = copynode(n->nfile.next);
8717 new->ndup.vname = copynode(n->ndup.vname);
8718 new->ndup.dupfd = n->ndup.dupfd;
8719 new->ndup.fd = n->ndup.fd;
8720 new->ndup.next = copynode(n->ndup.next);
8724 new->nhere.doc = copynode(n->nhere.doc);
8725 new->nhere.fd = n->nhere.fd;
8726 new->nhere.next = copynode(n->nhere.next);
8729 new->nnot.com = copynode(n->nnot.com);
8732 new->type = n->type;
8737 static struct nodelist *
8738 copynodelist(struct nodelist *lp)
8740 struct nodelist *start;
8741 struct nodelist **lpp;
8746 funcblock = (char *) funcblock +
8747 SHELL_ALIGN(sizeof(struct nodelist));
8748 (*lpp)->n = copynode(lp->n);
8750 lpp = &(*lpp)->next;
8758 nodesavestr(char *s)
8760 char *rtn = funcstring;
8762 funcstring = stpcpy(funcstring, s) + 1;
8768 * Free a parse tree.
8772 freefunc(struct funcnode *f)
8774 if (f && --f->count < 0)
8779 static void options(int);
8780 static void setoption(int, int);
8784 * Process the shell command line arguments.
8788 procargs(int argc, char **argv)
8791 const char *xminusc;
8798 for (i = 0; i < NOPTS; i++)
8804 if (*xargv == NULL) {
8806 sh_error(bb_msg_requires_arg, "-c");
8809 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8813 for (i = 0; i < NOPTS; i++)
8814 if (optlist[i] == 2)
8819 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8824 } else if (!sflag) {
8825 setinputfile(*xargv, 0);
8831 shellparam.p = xargv;
8832 #ifdef CONFIG_ASH_GETOPTS
8833 shellparam.optind = 1;
8834 shellparam.optoff = -1;
8836 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8838 shellparam.nparam++;
8851 setinteractive(iflag);
8856 static void minus_o(char *name, int val)
8861 out1str("Current option settings\n");
8862 for (i = 0; i < NOPTS; i++)
8863 out1fmt("%-16s%s\n", optnames(i),
8864 optlist[i] ? "on" : "off");
8866 for (i = 0; i < NOPTS; i++)
8867 if (equal(name, optnames(i))) {
8871 sh_error("Illegal option -o %s", name);
8876 * Process shell options. The global variable argptr contains a pointer
8877 * to the argument list; we advance it past the options.
8881 options(int cmdline)
8889 while ((p = *argptr) != NULL) {
8891 if ((c = *p++) == '-') {
8893 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8895 /* "-" means turn off -x and -v */
8898 /* "--" means reset params */
8899 else if (*argptr == NULL)
8902 break; /* "-" or "--" terminates options */
8904 } else if (c == '+') {
8910 while ((c = *p++) != '\0') {
8911 if (c == 'c' && cmdline) {
8912 minusc = p; /* command is after shell args*/
8913 } else if (c == 'o') {
8914 minus_o(*argptr, val);
8917 } else if (cmdline && (c == '-')) { // long options
8918 if (strcmp(p, "login") == 0)
8930 setoption(int flag, int val)
8934 for (i = 0; i < NOPTS; i++)
8935 if (optletters(i) == flag) {
8939 sh_error("Illegal option -%c", flag);
8946 * Set the shell parameters.
8950 setparam(char **argv)
8956 for (nparam = 0 ; argv[nparam] ; nparam++);
8957 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8959 *ap++ = savestr(*argv++);
8962 freeparam(&shellparam);
8963 shellparam.malloc = 1;
8964 shellparam.nparam = nparam;
8965 shellparam.p = newparam;
8966 #ifdef CONFIG_ASH_GETOPTS
8967 shellparam.optind = 1;
8968 shellparam.optoff = -1;
8974 * Free the list of positional parameters.
8978 freeparam(volatile struct shparam *param)
8982 if (param->malloc) {
8983 for (ap = param->p ; *ap ; ap++)
8992 * The shift builtin command.
8996 shiftcmd(int argc, char **argv)
9003 n = number(argv[1]);
9004 if (n > shellparam.nparam)
9005 sh_error("can't shift that many");
9007 shellparam.nparam -= n;
9008 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9009 if (shellparam.malloc)
9013 while ((*ap2++ = *ap1++) != NULL);
9014 #ifdef CONFIG_ASH_GETOPTS
9015 shellparam.optind = 1;
9016 shellparam.optoff = -1;
9025 * The set command builtin.
9029 setcmd(int argc, char **argv)
9032 return showvars(nullstr, 0, VUNSET);
9036 if (*argptr != NULL) {
9044 #ifdef CONFIG_ASH_GETOPTS
9046 getoptsreset(const char *value)
9048 shellparam.optind = number(value);
9049 shellparam.optoff = -1;
9053 #ifdef CONFIG_LOCALE_SUPPORT
9054 static void change_lc_all(const char *value)
9056 if (value != 0 && *value != 0)
9057 setlocale(LC_ALL, value);
9060 static void change_lc_ctype(const char *value)
9062 if (value != 0 && *value != 0)
9063 setlocale(LC_CTYPE, value);
9068 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9069 /* Roughly copied from bash.. */
9070 static void change_random(const char *value)
9073 /* "get", generate */
9076 rseed = rseed * 1103515245 + 12345;
9077 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9078 /* set without recursion */
9079 setvar(vrandom.text, buf, VNOFUNC);
9080 vrandom.flags &= ~VNOFUNC;
9083 rseed = strtoul(value, (char **)NULL, 10);
9089 #ifdef CONFIG_ASH_GETOPTS
9091 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9100 if(*param_optind < 1)
9102 optnext = optfirst + *param_optind - 1;
9104 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9107 p = optnext[-1] + *optoff;
9108 if (p == NULL || *p == '\0') {
9109 /* Current word is done, advance */
9111 if (p == NULL || *p != '-' || *++p == '\0') {
9118 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9123 for (q = optstr; *q != c; ) {
9125 if (optstr[0] == ':') {
9128 err |= setvarsafe("OPTARG", s, 0);
9130 fprintf(stderr, "Illegal option -%c\n", c);
9131 (void) unsetvar("OPTARG");
9141 if (*p == '\0' && (p = *optnext) == NULL) {
9142 if (optstr[0] == ':') {
9145 err |= setvarsafe("OPTARG", s, 0);
9148 fprintf(stderr, "No arg for -%c option\n", c);
9149 (void) unsetvar("OPTARG");
9157 err |= setvarsafe("OPTARG", p, 0);
9160 err |= setvarsafe("OPTARG", nullstr, 0);
9163 *optoff = p ? p - *(optnext - 1) : -1;
9164 *param_optind = optnext - optfirst + 1;
9165 fmtstr(s, sizeof(s), "%d", *param_optind);
9166 err |= setvarsafe("OPTIND", s, VNOFUNC);
9169 err |= setvarsafe(optvar, s, 0);
9180 * The getopts builtin. Shellparam.optnext points to the next argument
9181 * to be processed. Shellparam.optptr points to the next character to
9182 * be processed in the current argument. If shellparam.optnext is NULL,
9183 * then it's the first time getopts has been called.
9187 getoptscmd(int argc, char **argv)
9192 sh_error("Usage: getopts optstring var [arg]");
9193 else if (argc == 3) {
9194 optbase = shellparam.p;
9195 if (shellparam.optind > shellparam.nparam + 1) {
9196 shellparam.optind = 1;
9197 shellparam.optoff = -1;
9202 if (shellparam.optind > argc - 2) {
9203 shellparam.optind = 1;
9204 shellparam.optoff = -1;
9208 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9209 &shellparam.optoff);
9211 #endif /* CONFIG_ASH_GETOPTS */
9214 * XXX - should get rid of. have all builtins use getopt(3). the
9215 * library getopt must have the BSD extension static variable "optreset"
9216 * otherwise it can't be used within the shell safely.
9218 * Standard option processing (a la getopt) for builtin routines. The
9219 * only argument that is passed to nextopt is the option string; the
9220 * other arguments are unnecessary. It return the character, or '\0' on
9225 nextopt(const char *optstring)
9231 if ((p = optptr) == NULL || *p == '\0') {
9233 if (p == NULL || *p != '-' || *++p == '\0')
9236 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9240 for (q = optstring ; *q != c ; ) {
9242 sh_error("Illegal option -%c", c);
9247 if (*p == '\0' && (p = *argptr++) == NULL)
9248 sh_error("No arg for -%c option", c);
9260 outstr(const char *p, FILE *file)
9285 outcslow(int c, FILE *dest)
9295 out1fmt(const char *fmt, ...)
9302 r = vprintf(fmt, ap);
9310 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9317 ret = vsnprintf(outbuf, length, fmt, ap);
9329 * Shell command parser.
9332 #define EOFMARKLEN 79
9336 struct heredoc *next; /* next here document in list */
9337 union node *here; /* redirection node */
9338 char *eofmark; /* string indicating end of input */
9339 int striptabs; /* if set, strip leading tabs */
9344 static struct heredoc *heredoclist; /* list of here documents to read */
9347 static union node *list(int);
9348 static union node *andor(void);
9349 static union node *pipeline(void);
9350 static union node *command(void);
9351 static union node *simplecmd(void);
9352 static union node *makename(void);
9353 static void parsefname(void);
9354 static void parseheredoc(void);
9355 static char peektoken(void);
9356 static int readtoken(void);
9357 static int xxreadtoken(void);
9358 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9359 static int noexpand(char *);
9360 static void synexpect(int) ATTRIBUTE_NORETURN;
9361 static void synerror(const char *) ATTRIBUTE_NORETURN;
9362 static void setprompt(int);
9368 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9369 * valid parse tree indicating a blank line.)
9373 parsecmd(int interact)
9378 doprompt = interact;
9380 setprompt(doprompt);
9395 union node *n1, *n2, *n3;
9398 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9399 if (nlflag == 2 && peektoken())
9405 if (tok == TBACKGND) {
9406 if (n2->type == NPIPE) {
9407 n2->npipe.backgnd = 1;
9409 if (n2->type != NREDIR) {
9410 n3 = stalloc(sizeof(struct nredir));
9412 n3->nredir.redirect = NULL;
9415 n2->type = NBACKGND;
9422 n3 = (union node *)stalloc(sizeof (struct nbinary));
9424 n3->nbinary.ch1 = n1;
9425 n3->nbinary.ch2 = n2;
9441 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9449 pungetc(); /* push back EOF on input */
9465 union node *n1, *n2, *n3;
9470 if ((t = readtoken()) == TAND) {
9472 } else if (t == TOR) {
9478 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9480 n3 = (union node *)stalloc(sizeof (struct nbinary));
9482 n3->nbinary.ch1 = n1;
9483 n3->nbinary.ch2 = n2;
9493 union node *n1, *n2, *pipenode;
9494 struct nodelist *lp, *prev;
9498 TRACE(("pipeline: entered\n"));
9499 if (readtoken() == TNOT) {
9501 checkkwd = CHKKWD | CHKALIAS;
9505 if (readtoken() == TPIPE) {
9506 pipenode = (union node *)stalloc(sizeof (struct npipe));
9507 pipenode->type = NPIPE;
9508 pipenode->npipe.backgnd = 0;
9509 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9510 pipenode->npipe.cmdlist = lp;
9514 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9515 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9518 } while (readtoken() == TPIPE);
9524 n2 = (union node *)stalloc(sizeof (struct nnot));
9537 union node *n1, *n2;
9538 union node *ap, **app;
9539 union node *cp, **cpp;
9540 union node *redir, **rpp;
9547 switch (readtoken()) {
9552 n1 = (union node *)stalloc(sizeof (struct nif));
9554 n1->nif.test = list(0);
9555 if (readtoken() != TTHEN)
9557 n1->nif.ifpart = list(0);
9559 while (readtoken() == TELIF) {
9560 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9561 n2 = n2->nif.elsepart;
9563 n2->nif.test = list(0);
9564 if (readtoken() != TTHEN)
9566 n2->nif.ifpart = list(0);
9568 if (lasttoken == TELSE)
9569 n2->nif.elsepart = list(0);
9571 n2->nif.elsepart = NULL;
9579 n1 = (union node *)stalloc(sizeof (struct nbinary));
9580 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9581 n1->nbinary.ch1 = list(0);
9582 if ((got=readtoken()) != TDO) {
9583 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9586 n1->nbinary.ch2 = list(0);
9591 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9592 synerror("Bad for loop variable");
9593 n1 = (union node *)stalloc(sizeof (struct nfor));
9595 n1->nfor.var = wordtext;
9596 checkkwd = CHKKWD | CHKALIAS;
9597 if (readtoken() == TIN) {
9599 while (readtoken() == TWORD) {
9600 n2 = (union node *)stalloc(sizeof (struct narg));
9602 n2->narg.text = wordtext;
9603 n2->narg.backquote = backquotelist;
9605 app = &n2->narg.next;
9609 if (lasttoken != TNL && lasttoken != TSEMI)
9612 n2 = (union node *)stalloc(sizeof (struct narg));
9614 n2->narg.text = (char *)dolatstr;
9615 n2->narg.backquote = NULL;
9616 n2->narg.next = NULL;
9619 * Newline or semicolon here is optional (but note
9620 * that the original Bourne shell only allowed NL).
9622 if (lasttoken != TNL && lasttoken != TSEMI)
9625 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9626 if (readtoken() != TDO)
9628 n1->nfor.body = list(0);
9632 n1 = (union node *)stalloc(sizeof (struct ncase));
9634 if (readtoken() != TWORD)
9636 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9638 n2->narg.text = wordtext;
9639 n2->narg.backquote = backquotelist;
9640 n2->narg.next = NULL;
9642 checkkwd = CHKKWD | CHKALIAS;
9643 } while (readtoken() == TNL);
9644 if (lasttoken != TIN)
9646 cpp = &n1->ncase.cases;
9648 checkkwd = CHKNL | CHKKWD;
9651 if (lasttoken == TLP)
9653 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9655 app = &cp->nclist.pattern;
9657 *app = ap = (union node *)stalloc(sizeof (struct narg));
9659 ap->narg.text = wordtext;
9660 ap->narg.backquote = backquotelist;
9661 if (readtoken() != TPIPE)
9663 app = &ap->narg.next;
9666 ap->narg.next = NULL;
9667 if (lasttoken != TRP)
9669 cp->nclist.body = list(2);
9671 cpp = &cp->nclist.next;
9673 checkkwd = CHKNL | CHKKWD;
9674 if ((t = readtoken()) != TESAC) {
9676 synexpect(TENDCASE);
9684 n1 = (union node *)stalloc(sizeof (struct nredir));
9685 n1->type = NSUBSHELL;
9686 n1->nredir.n = list(0);
9687 n1->nredir.redirect = NULL;
9700 if (readtoken() != t)
9704 /* Now check for redirection which may follow command */
9705 checkkwd = CHKKWD | CHKALIAS;
9707 while (readtoken() == TREDIR) {
9708 *rpp = n2 = redirnode;
9709 rpp = &n2->nfile.next;
9715 if (n1->type != NSUBSHELL) {
9716 n2 = (union node *)stalloc(sizeof (struct nredir));
9721 n1->nredir.redirect = redir;
9730 union node *args, **app;
9731 union node *n = NULL;
9732 union node *vars, **vpp;
9733 union node **rpp, *redir;
9743 savecheckkwd = CHKALIAS;
9745 checkkwd = savecheckkwd;
9746 switch (readtoken()) {
9748 n = (union node *)stalloc(sizeof (struct narg));
9750 n->narg.text = wordtext;
9751 n->narg.backquote = backquotelist;
9752 if (savecheckkwd && isassignment(wordtext)) {
9754 vpp = &n->narg.next;
9757 app = &n->narg.next;
9762 *rpp = n = redirnode;
9763 rpp = &n->nfile.next;
9764 parsefname(); /* read name of redirection file */
9768 args && app == &args->narg.next &&
9771 struct builtincmd *bcmd;
9774 /* We have a function */
9775 if (readtoken() != TRP)
9777 name = n->narg.text;
9779 !goodname(name) || (
9780 (bcmd = find_builtin(name)) &&
9781 IS_BUILTIN_SPECIAL(bcmd)
9784 synerror("Bad function name");
9786 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9787 n->narg.next = command();
9800 n = (union node *)stalloc(sizeof (struct ncmd));
9802 n->ncmd.args = args;
9803 n->ncmd.assign = vars;
9804 n->ncmd.redirect = redir;
9813 n = (union node *)stalloc(sizeof (struct narg));
9815 n->narg.next = NULL;
9816 n->narg.text = wordtext;
9817 n->narg.backquote = backquotelist;
9821 void fixredir(union node *n, const char *text, int err)
9823 TRACE(("Fix redir %s %d\n", text, err));
9825 n->ndup.vname = NULL;
9827 if (is_digit(text[0]) && text[1] == '\0')
9828 n->ndup.dupfd = digit_val(text[0]);
9829 else if (text[0] == '-' && text[1] == '\0')
9834 synerror("Bad fd number");
9836 n->ndup.vname = makename();
9844 union node *n = redirnode;
9846 if (readtoken() != TWORD)
9848 if (n->type == NHERE) {
9849 struct heredoc *here = heredoc;
9855 TRACE(("Here document %d\n", n->type));
9856 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9857 synerror("Illegal eof marker for << redirection");
9858 rmescapes(wordtext);
9859 here->eofmark = wordtext;
9861 if (heredoclist == NULL)
9864 for (p = heredoclist ; p->next ; p = p->next);
9867 } else if (n->type == NTOFD || n->type == NFROMFD) {
9868 fixredir(n, wordtext, 0);
9870 n->nfile.fname = makename();
9876 * Input any here documents.
9882 struct heredoc *here;
9892 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9893 here->eofmark, here->striptabs);
9894 n = (union node *)stalloc(sizeof (struct narg));
9895 n->narg.type = NARG;
9896 n->narg.next = NULL;
9897 n->narg.text = wordtext;
9898 n->narg.backquote = backquotelist;
9899 here->here->nhere.doc = n;
9904 static char peektoken(void)
9910 return tokname_array[t][0];
9918 int alreadyseen = tokpushback;
9921 #ifdef CONFIG_ASH_ALIAS
9930 if (checkkwd & CHKNL) {
9937 if (t != TWORD || quoteflag) {
9942 * check for keywords
9944 if (checkkwd & CHKKWD) {
9945 const char *const *pp;
9947 if ((pp = findkwd(wordtext))) {
9948 lasttoken = t = pp - tokname_array;
9949 TRACE(("keyword %s recognized\n", tokname(t)));
9954 if (checkkwd & CHKALIAS) {
9955 #ifdef CONFIG_ASH_ALIAS
9957 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9959 pushstring(ap->val, ap);
9969 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9971 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9978 * Read the next input token.
9979 * If the token is a word, we set backquotelist to the list of cmds in
9980 * backquotes. We set quoteflag to true if any part of the word was
9982 * If the token is TREDIR, then we set redirnode to a structure containing
9984 * In all cases, the variable startlinno is set to the number of the line
9985 * on which the token starts.
9987 * [Change comment: here documents and internal procedures]
9988 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9989 * word parsing code into a separate routine. In this case, readtoken
9990 * doesn't need to have any internal procedures, but parseword does.
9991 * We could also make parseoperator in essence the main routine, and
9992 * have parseword (readtoken1?) handle both words and redirection.]
9995 #define NEW_xxreadtoken
9996 #ifdef NEW_xxreadtoken
9998 /* singles must be first! */
9999 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10001 static const char xxreadtoken_tokens[] = {
10002 TNL, TLP, TRP, /* only single occurrence allowed */
10003 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10004 TEOF, /* corresponds to trailing nul */
10005 TAND, TOR, TENDCASE, /* if double occurrence */
10008 #define xxreadtoken_doubles \
10009 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10010 #define xxreadtoken_singles \
10011 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10013 static int xxreadtoken(void)
10024 startlinno = plinno;
10025 for (;;) { /* until token or start of word found */
10028 if ((c != ' ') && (c != '\t')
10029 #ifdef CONFIG_ASH_ALIAS
10034 while ((c = pgetc()) != '\n' && c != PEOF);
10036 } else if (c == '\\') {
10037 if (pgetc() != '\n') {
10041 startlinno = ++plinno;
10046 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10051 needprompt = doprompt;
10054 p = strchr(xxreadtoken_chars, c);
10057 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10060 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10061 if (pgetc() == *p) { /* double occurrence? */
10062 p += xxreadtoken_doubles + 1;
10069 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10077 #define RETURN(token) return lasttoken = token
10091 startlinno = plinno;
10092 for (;;) { /* until token or start of word found */
10095 case ' ': case '\t':
10096 #ifdef CONFIG_ASH_ALIAS
10101 while ((c = pgetc()) != '\n' && c != PEOF);
10105 if (pgetc() == '\n') {
10106 startlinno = ++plinno;
10115 needprompt = doprompt;
10120 if (pgetc() == '&')
10125 if (pgetc() == '|')
10130 if (pgetc() == ';')
10143 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10146 #endif /* NEW_xxreadtoken */
10150 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10151 * is not NULL, read a here document. In the latter case, eofmark is the
10152 * word which marks the end of the document and striptabs is true if
10153 * leading tabs should be stripped from the document. The argument firstc
10154 * is the first character of the input token or document.
10156 * Because C does not have internal subroutines, I have simulated them
10157 * using goto's to implement the subroutine linkage. The following macros
10158 * will run code that appears at the end of readtoken1.
10161 #define CHECKEND() {goto checkend; checkend_return:;}
10162 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10163 #define PARSESUB() {goto parsesub; parsesub_return:;}
10164 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10165 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10166 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10169 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10174 char line[EOFMARKLEN + 1];
10175 struct nodelist *bqlist = 0;
10178 int varnest = 0; /* levels of variables expansion */
10179 int arinest = 0; /* levels of arithmetic expansion */
10180 int parenlevel = 0; /* levels of parens in arithmetic */
10181 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10183 int prevsyntax = 0; /* syntax before arithmetic */
10185 /* Avoid longjmp clobbering */
10191 (void) &parenlevel;
10194 (void) &prevsyntax;
10198 startlinno = plinno;
10200 if (syntax == DQSYNTAX)
10209 STARTSTACKSTR(out);
10210 loop: { /* for each line, until end of word */
10211 CHECKEND(); /* set c to PEOF if at end of here document */
10212 for (;;) { /* until end of line or end of word */
10213 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10214 switch(SIT(c, syntax)) {
10215 case CNL: /* '\n' */
10216 if (syntax == BASESYNTAX)
10217 goto endword; /* exit outer loop */
10223 goto loop; /* continue outer loop */
10228 if (eofmark == NULL || dblquote)
10229 USTPUTC(CTLESC, out);
10232 case CBACK: /* backslash */
10235 USTPUTC(CTLESC, out);
10236 USTPUTC('\\', out);
10238 } else if (c == '\n') {
10243 c != '\\' && c != '`' &&
10248 USTPUTC(CTLESC, out);
10249 USTPUTC('\\', out);
10251 if (SIT(c, SQSYNTAX) == CCTL)
10252 USTPUTC(CTLESC, out);
10260 if (eofmark == NULL) {
10261 USTPUTC(CTLQUOTEMARK, out);
10269 if (eofmark != NULL && arinest == 0 &&
10273 if (dqvarnest == 0) {
10274 syntax = BASESYNTAX;
10281 case CVAR: /* '$' */
10282 PARSESUB(); /* parse substitution */
10284 case CENDVAR: /* '}' */
10287 if (dqvarnest > 0) {
10290 USTPUTC(CTLENDVAR, out);
10295 #ifdef CONFIG_ASH_MATH_SUPPORT
10296 case CLP: /* '(' in arithmetic */
10300 case CRP: /* ')' in arithmetic */
10301 if (parenlevel > 0) {
10305 if (pgetc() == ')') {
10306 if (--arinest == 0) {
10307 USTPUTC(CTLENDARI, out);
10308 syntax = prevsyntax;
10309 if (syntax == DQSYNTAX)
10317 * unbalanced parens
10318 * (don't 2nd guess - no error)
10326 case CBQUOTE: /* '`' */
10330 goto endword; /* exit outer loop */
10335 goto endword; /* exit outer loop */
10336 #ifdef CONFIG_ASH_ALIAS
10346 #ifdef CONFIG_ASH_MATH_SUPPORT
10347 if (syntax == ARISYNTAX)
10348 synerror("Missing '))'");
10350 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10351 synerror("Unterminated quoted string");
10352 if (varnest != 0) {
10353 startlinno = plinno;
10355 synerror("Missing '}'");
10357 USTPUTC('\0', out);
10358 len = out - (char *)stackblock();
10359 out = stackblock();
10360 if (eofmark == NULL) {
10361 if ((c == '>' || c == '<')
10364 && (*out == '\0' || is_digit(*out))) {
10366 return lasttoken = TREDIR;
10371 quoteflag = quotef;
10372 backquotelist = bqlist;
10373 grabstackblock(len);
10375 return lasttoken = TWORD;
10376 /* end of readtoken routine */
10381 * Check to see whether we are at the end of the here document. When this
10382 * is called, c is set to the first character of the next input line. If
10383 * we are at the end of the here document, this routine sets the c to PEOF.
10388 #ifdef CONFIG_ASH_ALIAS
10394 while (c == '\t') {
10398 if (c == *eofmark) {
10399 if (pfgets(line, sizeof line) != NULL) {
10403 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10404 if (*p == '\n' && *q == '\0') {
10407 needprompt = doprompt;
10409 pushstring(line, NULL);
10414 goto checkend_return;
10419 * Parse a redirection operator. The variable "out" points to a string
10420 * specifying the fd to be redirected. The variable "c" contains the
10421 * first character of the redirection operator.
10428 np = (union node *)stalloc(sizeof (struct nfile));
10433 np->type = NAPPEND;
10435 np->type = NCLOBBER;
10442 } else { /* c == '<' */
10444 switch (c = pgetc()) {
10446 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10447 np = (union node *)stalloc(sizeof (struct nhere));
10451 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10452 heredoc->here = np;
10453 if ((c = pgetc()) == '-') {
10454 heredoc->striptabs = 1;
10456 heredoc->striptabs = 0;
10462 np->type = NFROMFD;
10466 np->type = NFROMTO;
10476 np->nfile.fd = digit_val(fd);
10478 goto parseredir_return;
10483 * Parse a substitution. At this point, we have read the dollar sign
10484 * and nothing else.
10492 static const char types[] = "}-+?=";
10496 c <= PEOA_OR_PEOF ||
10497 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10501 } else if (c == '(') { /* $(command) or $((arith)) */
10502 if (pgetc() == '(') {
10503 #ifdef CONFIG_ASH_MATH_SUPPORT
10506 synerror("We unsupport $((arith))");
10513 USTPUTC(CTLVAR, out);
10514 typeloc = out - (char *)stackblock();
10515 USTPUTC(VSNORMAL, out);
10516 subtype = VSNORMAL;
10520 if ((c = pgetc()) == '}')
10523 subtype = VSLENGTH;
10528 if (c > PEOA_OR_PEOF && is_name(c)) {
10532 } while (c > PEOA_OR_PEOF && is_in_name(c));
10533 } else if (is_digit(c)) {
10537 } while (is_digit(c));
10539 else if (is_special(c)) {
10544 badsub: synerror("Bad substitution");
10548 if (subtype == 0) {
10555 p = strchr(types, c);
10558 subtype = p - types + VSNORMAL;
10564 subtype = c == '#' ? VSTRIMLEFT :
10577 if (dblquote || arinest)
10579 *((char *)stackblock() + typeloc) = subtype | flags;
10580 if (subtype != VSNORMAL) {
10582 if (dblquote || arinest) {
10587 goto parsesub_return;
10592 * Called to parse command substitutions. Newstyle is set if the command
10593 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10594 * list of commands (passed by reference), and savelen is the number of
10595 * characters on the top of the stack which must be preserved.
10599 struct nodelist **nlpp;
10602 char *volatile str;
10603 struct jmploc jmploc;
10604 struct jmploc *volatile savehandler;
10606 int saveprompt = 0;
10608 (void) &saveprompt;
10611 savepbq = parsebackquote;
10612 if (setjmp(jmploc.loc)) {
10615 parsebackquote = 0;
10616 handler = savehandler;
10617 longjmp(handler->loc, 1);
10621 savelen = out - (char *)stackblock();
10623 str = ckmalloc(savelen);
10624 memcpy(str, stackblock(), savelen);
10626 savehandler = handler;
10630 /* We must read until the closing backquote, giving special
10631 treatment to some slashes, and then push the string and
10632 reread it as input, interpreting it normally. */
10639 STARTSTACKSTR(pout);
10644 switch (pc = pgetc()) {
10649 if ((pc = pgetc()) == '\n') {
10654 * If eating a newline, avoid putting
10655 * the newline into the new character
10656 * stream (via the STPUTC after the
10661 if (pc != '\\' && pc != '`' && pc != '$'
10662 && (!dblquote || pc != '"'))
10663 STPUTC('\\', pout);
10664 if (pc > PEOA_OR_PEOF) {
10670 #ifdef CONFIG_ASH_ALIAS
10673 startlinno = plinno;
10674 synerror("EOF in backquote substitution");
10678 needprompt = doprompt;
10687 STPUTC('\0', pout);
10688 psavelen = pout - (char *)stackblock();
10689 if (psavelen > 0) {
10690 pstr = grabstackstr(pout);
10691 setinputstring(pstr);
10696 nlpp = &(*nlpp)->next;
10697 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10698 (*nlpp)->next = NULL;
10699 parsebackquote = oldstyle;
10702 saveprompt = doprompt;
10709 doprompt = saveprompt;
10711 if (readtoken() != TRP)
10718 * Start reading from old file again, ignoring any pushed back
10719 * tokens left from the backquote parsing
10724 while (stackblocksize() <= savelen)
10726 STARTSTACKSTR(out);
10728 memcpy(out, str, savelen);
10729 STADJUST(savelen, out);
10735 parsebackquote = savepbq;
10736 handler = savehandler;
10737 if (arinest || dblquote)
10738 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10740 USTPUTC(CTLBACKQ, out);
10742 goto parsebackq_oldreturn;
10744 goto parsebackq_newreturn;
10747 #ifdef CONFIG_ASH_MATH_SUPPORT
10749 * Parse an arithmetic expansion (indicate start of one and set state)
10753 if (++arinest == 1) {
10754 prevsyntax = syntax;
10755 syntax = ARISYNTAX;
10756 USTPUTC(CTLARI, out);
10763 * we collapse embedded arithmetic expansion to
10764 * parenthesis, which should be equivalent
10768 goto parsearith_return;
10772 } /* end of readtoken */
10777 * Returns true if the text contains nothing to expand (no dollar signs
10782 noexpand(char *text)
10788 while ((c = *p++) != '\0') {
10789 if (c == CTLQUOTEMARK)
10793 else if (SIT(c, BASESYNTAX) == CCTL)
10801 * Return of a legal variable name (a letter or underscore followed by zero or
10802 * more letters, underscores, and digits).
10806 endofname(const char *name)
10814 if (! is_in_name(*p))
10822 * Called when an unexpected token is read during the parse. The argument
10823 * is the token that is expected, or -1 if more than one type of token can
10824 * occur at this point.
10827 static void synexpect(int token)
10832 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10834 sprintf(msg + l, " (expecting %s)", tokname(token));
10840 synerror(const char *msg)
10842 sh_error("Syntax error: %s", msg);
10848 * called by editline -- any expansions to the prompt
10849 * should be added here.
10852 #ifdef CONFIG_ASH_EXPAND_PRMT
10853 static const char *
10854 expandstr(const char *ps)
10858 /* XXX Fix (char *) cast. */
10859 setinputstring((char *)ps);
10860 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10863 n.narg.type = NARG;
10864 n.narg.next = NULL;
10865 n.narg.text = wordtext;
10866 n.narg.backquote = backquotelist;
10868 expandarg(&n, NULL, 0);
10869 return stackblock();
10873 static void setprompt(int whichprompt)
10875 const char *prompt;
10876 #ifdef CONFIG_ASH_EXPAND_PRMT
10877 struct stackmark smark;
10882 switch (whichprompt) {
10892 #ifdef CONFIG_ASH_EXPAND_PRMT
10893 setstackmark(&smark);
10894 stalloc(stackblocksize());
10896 putprompt(expandstr(prompt));
10897 #ifdef CONFIG_ASH_EXPAND_PRMT
10898 popstackmark(&smark);
10903 static const char *const *findkwd(const char *s)
10905 return bsearch(s, tokname_array + KWDOFFSET,
10906 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10907 sizeof(const char *), pstrcmp);
10913 * Code for dealing with input/output redirection.
10916 #define EMPTY -2 /* marks an unused slot in redirtab */
10918 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10920 # define PIPESIZE PIPE_BUF
10924 * Open a file in noclobber mode.
10925 * The code was copied from bash.
10927 static int noclobberopen(const char *fname)
10930 struct stat finfo, finfo2;
10933 * If the file exists and is a regular file, return an error
10936 r = stat(fname, &finfo);
10937 if (r == 0 && S_ISREG(finfo.st_mode)) {
10943 * If the file was not present (r != 0), make sure we open it
10944 * exclusively so that if it is created before we open it, our open
10945 * will fail. Make sure that we do not truncate an existing file.
10946 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10947 * file was not a regular file, we leave O_EXCL off.
10950 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10951 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10953 /* If the open failed, return the file descriptor right away. */
10958 * OK, the open succeeded, but the file may have been changed from a
10959 * non-regular file to a regular file between the stat and the open.
10960 * We are assuming that the O_EXCL open handles the case where FILENAME
10961 * did not exist and is symlinked to an existing file between the stat
10966 * If we can open it and fstat the file descriptor, and neither check
10967 * revealed that it was a regular file, and the file has not been
10968 * replaced, return the file descriptor.
10970 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10971 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10974 /* The file has been replaced. badness. */
10981 * Handle here documents. Normally we fork off a process to write the
10982 * data to a pipe. If the document is short, we can stuff the data in
10983 * the pipe without forking.
10986 static int openhere(union node *redir)
10992 sh_error("Pipe call failed");
10993 if (redir->type == NHERE) {
10994 len = strlen(redir->nhere.doc->narg.text);
10995 if (len <= PIPESIZE) {
10996 full_write(pip[1], redir->nhere.doc->narg.text, len);
11000 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11002 signal(SIGINT, SIG_IGN);
11003 signal(SIGQUIT, SIG_IGN);
11004 signal(SIGHUP, SIG_IGN);
11006 signal(SIGTSTP, SIG_IGN);
11008 signal(SIGPIPE, SIG_DFL);
11009 if (redir->type == NHERE)
11010 full_write(pip[1], redir->nhere.doc->narg.text, len);
11012 expandhere(redir->nhere.doc, pip[1]);
11021 openredirect(union node *redir)
11026 switch (redir->nfile.type) {
11028 fname = redir->nfile.expfname;
11029 if ((f = open(fname, O_RDONLY)) < 0)
11033 fname = redir->nfile.expfname;
11034 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11038 /* Take care of noclobber mode. */
11040 fname = redir->nfile.expfname;
11041 if ((f = noclobberopen(fname)) < 0)
11047 fname = redir->nfile.expfname;
11048 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11052 fname = redir->nfile.expfname;
11053 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11060 /* Fall through to eliminate warning. */
11067 f = openhere(redir);
11073 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11075 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11078 static void dupredirect(union node *redir, int f)
11080 int fd = redir->nfile.fd;
11082 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11083 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11084 copyfd(redir->ndup.dupfd, fd);
11097 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11098 * old file descriptors are stashed away so that the redirection can be
11099 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11100 * standard output, and the standard error if it becomes a duplicate of
11101 * stdout, is saved in memory.
11105 redirect(union node *redir, int flags)
11108 struct redirtab *sv;
11119 if (flags & REDIR_PUSH) {
11120 struct redirtab *q;
11121 q = ckmalloc(sizeof (struct redirtab));
11122 q->next = redirlist;
11124 q->nullredirs = nullredirs - 1;
11125 for (i = 0 ; i < 10 ; i++)
11126 q->renamed[i] = EMPTY;
11133 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11134 n->ndup.dupfd == fd)
11135 continue; /* redirect from/to same file descriptor */
11137 newfd = openredirect(n);
11140 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11141 i = fcntl(fd, F_DUPFD, 10);
11148 sh_error("%d: %m", fd);
11158 dupredirect(n, newfd);
11159 } while ((n = n->nfile.next));
11161 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11162 preverrout_fd = sv->renamed[2];
11167 * Undo the effects of the last redirection.
11173 struct redirtab *rp;
11176 if (--nullredirs >= 0)
11180 for (i = 0 ; i < 10 ; i++) {
11181 if (rp->renamed[i] != EMPTY) {
11184 copyfd(rp->renamed[i], i);
11186 close(rp->renamed[i]);
11189 redirlist = rp->next;
11190 nullredirs = rp->nullredirs;
11196 * Undo all redirections. Called on error or interrupt.
11200 * Discard all saved file descriptors.
11204 clearredir(int drop)
11216 * Copy a file descriptor to be >= to. Returns -1
11217 * if the source file descriptor is closed, EMPTY if there are no unused
11218 * file descriptors left.
11222 copyfd(int from, int to)
11226 newfd = fcntl(from, F_DUPFD, to);
11228 if (errno == EMFILE)
11231 sh_error("%d: %m", from);
11238 redirectsafe(union node *redir, int flags)
11241 volatile int saveint;
11242 struct jmploc *volatile savehandler = handler;
11243 struct jmploc jmploc;
11246 if (!(err = setjmp(jmploc.loc) * 2)) {
11248 redirect(redir, flags);
11250 handler = savehandler;
11251 if (err && exception != EXERROR)
11252 longjmp(handler->loc, 1);
11253 RESTOREINT(saveint);
11260 static void shtree(union node *, int, char *, FILE*);
11261 static void shcmd(union node *, FILE *);
11262 static void sharg(union node *, FILE *);
11263 static void indent(int, char *, FILE *);
11264 static void trstring(char *);
11268 showtree(union node *n)
11270 trputs("showtree called\n");
11271 shtree(n, 1, NULL, stdout);
11276 shtree(union node *n, int ind, char *pfx, FILE *fp)
11278 struct nodelist *lp;
11284 indent(ind, pfx, fp);
11295 shtree(n->nbinary.ch1, ind, NULL, fp);
11298 shtree(n->nbinary.ch2, ind, NULL, fp);
11306 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11311 if (n->npipe.backgnd)
11317 fprintf(fp, "<node type %d>", n->type);
11326 shcmd(union node *cmd, FILE *fp)
11334 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11340 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11343 switch (np->nfile.type) {
11344 case NTO: s = ">"; dftfd = 1; break;
11345 case NCLOBBER: s = ">|"; dftfd = 1; break;
11346 case NAPPEND: s = ">>"; dftfd = 1; break;
11347 case NTOFD: s = ">&"; dftfd = 1; break;
11348 case NFROM: s = "<"; dftfd = 0; break;
11349 case NFROMFD: s = "<&"; dftfd = 0; break;
11350 case NFROMTO: s = "<>"; dftfd = 0; break;
11351 default: s = "*error*"; dftfd = 0; break;
11353 if (np->nfile.fd != dftfd)
11354 fprintf(fp, "%d", np->nfile.fd);
11356 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11357 fprintf(fp, "%d", np->ndup.dupfd);
11359 sharg(np->nfile.fname, fp);
11368 sharg(union node *arg, FILE *fp)
11371 struct nodelist *bqlist;
11374 if (arg->type != NARG) {
11375 out1fmt("<node type %d>\n", arg->type);
11378 bqlist = arg->narg.backquote;
11379 for (p = arg->narg.text ; *p ; p++) {
11388 if (subtype == VSLENGTH)
11394 if (subtype & VSNUL)
11397 switch (subtype & VSTYPE) {
11416 case VSTRIMLEFTMAX:
11423 case VSTRIMRIGHTMAX:
11430 out1fmt("<subtype %d>", subtype);
11437 case CTLBACKQ|CTLQUOTE:
11440 shtree(bqlist->n, -1, NULL, fp);
11452 indent(int amount, char *pfx, FILE *fp)
11456 for (i = 0 ; i < amount ; i++) {
11457 if (pfx && i == amount - 1)
11478 putc(c, tracefile);
11482 trace(const char *fmt, ...)
11489 (void) vfprintf(tracefile, fmt, va);
11494 tracev(const char *fmt, va_list va)
11498 (void) vfprintf(tracefile, fmt, va);
11503 trputs(const char *s)
11507 fputs(s, tracefile);
11519 putc('"', tracefile);
11520 for (p = s ; *p ; p++) {
11522 case '\n': c = 'n'; goto backslash;
11523 case '\t': c = 't'; goto backslash;
11524 case '\r': c = 'r'; goto backslash;
11525 case '"': c = '"'; goto backslash;
11526 case '\\': c = '\\'; goto backslash;
11527 case CTLESC: c = 'e'; goto backslash;
11528 case CTLVAR: c = 'v'; goto backslash;
11529 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11530 case CTLBACKQ: c = 'q'; goto backslash;
11531 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11532 backslash: putc('\\', tracefile);
11533 putc(c, tracefile);
11536 if (*p >= ' ' && *p <= '~')
11537 putc(*p, tracefile);
11539 putc('\\', tracefile);
11540 putc(*p >> 6 & 03, tracefile);
11541 putc(*p >> 3 & 07, tracefile);
11542 putc(*p & 07, tracefile);
11547 putc('"', tracefile);
11559 putc(' ', tracefile);
11561 putc('\n', tracefile);
11577 /* leave open because libedit might be using it */
11580 scopy("./trace", s);
11582 if (!freopen(s, "a", tracefile)) {
11583 fprintf(stderr, "Can't re-open %s\n", s);
11588 if ((tracefile = fopen(s, "a")) == NULL) {
11589 fprintf(stderr, "Can't open %s\n", s);
11595 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11596 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11598 setlinebuf(tracefile);
11599 fputs("\nTracing started.\n", tracefile);
11607 * Sigmode records the current value of the signal handlers for the various
11608 * modes. A value of zero means that the current handler is not known.
11609 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11612 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11613 #define S_CATCH 2 /* signal is caught */
11614 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11615 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11616 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11621 * The trap builtin.
11625 trapcmd(int argc, char **argv)
11634 for (signo = 0 ; signo < NSIG ; signo++) {
11635 if (trap[signo] != NULL) {
11638 sn = get_signame(signo);
11639 out1fmt("trap -- %s %s\n",
11640 single_quote(trap[signo]), sn);
11650 if ((signo = get_signum(*ap)) < 0)
11651 sh_error("%s: bad trap", *ap);
11654 if (action[0] == '-' && action[1] == '\0')
11657 action = savestr(action);
11660 ckfree(trap[signo]);
11661 trap[signo] = action;
11672 * Clear traps on a fork.
11680 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11681 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11685 if (tp != &trap[0])
11686 setsignal(tp - trap);
11694 * Set the signal handler for the specified signal. The routine figures
11695 * out what it should be set to.
11699 setsignal(int signo)
11703 struct sigaction act;
11705 if ((t = trap[signo]) == NULL)
11707 else if (*t != '\0')
11711 if (rootshell && action == S_DFL) {
11714 if (iflag || minusc || sflag == 0)
11737 t = &sigmode[signo - 1];
11741 * current setting unknown
11743 if (sigaction(signo, 0, &act) == -1) {
11745 * Pretend it worked; maybe we should give a warning
11746 * here, but other shells don't. We don't alter
11747 * sigmode, so that we retry every time.
11751 if (act.sa_handler == SIG_IGN) {
11752 if (mflag && (signo == SIGTSTP ||
11753 signo == SIGTTIN || signo == SIGTTOU)) {
11754 tsig = S_IGN; /* don't hard ignore these */
11758 tsig = S_RESET; /* force to be set */
11761 if (tsig == S_HARD_IGN || tsig == action)
11765 act.sa_handler = onsig;
11768 act.sa_handler = SIG_IGN;
11771 act.sa_handler = SIG_DFL;
11775 sigfillset(&act.sa_mask);
11776 sigaction(signo, &act, 0);
11784 ignoresig(int signo)
11786 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11787 signal(signo, SIG_IGN);
11789 sigmode[signo - 1] = S_HARD_IGN;
11800 gotsig[signo - 1] = 1;
11801 pendingsigs = signo;
11803 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11812 * Called to execute a trap. Perhaps we should avoid entering new trap
11813 * handlers while we are executing a trap handler.
11825 savestatus = exitstatus;
11829 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11837 skip = evalstring(p, SKIPEVAL);
11838 exitstatus = savestatus;
11848 * Controls whether the shell is interactive or not.
11852 setinteractive(int on)
11854 static int is_interactive;
11856 if (++on == is_interactive)
11858 is_interactive = on;
11860 setsignal(SIGQUIT);
11861 setsignal(SIGTERM);
11862 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11863 if(is_interactive > 1) {
11864 /* Looks like they want an interactive shell */
11865 static int do_banner;
11869 "\n\n%s Built-in shell (ash)\n"
11870 "Enter 'help' for a list of built-in commands.\n\n",
11879 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11880 /*** List the available builtins ***/
11882 static int helpcmd(int argc, char **argv)
11886 out1fmt("\nBuilt-in commands:\n-------------------\n");
11887 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11888 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11889 builtincmd[i].name + 1);
11895 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11897 extern const struct BB_applet applets[];
11898 extern const size_t NUM_APPLETS;
11900 for (i = 0; i < NUM_APPLETS; i++) {
11902 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11911 return EXIT_SUCCESS;
11913 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11916 * Called to exit the shell.
11926 status = exitstatus;
11927 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11928 if (setjmp(loc.loc)) {
11929 if (exception == EXEXIT)
11934 if ((p = trap[0])) {
11940 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11941 if (iflag && rootshell) {
11942 const char *hp = lookupvar("HISTFILE");
11945 save_history ( hp );
11955 static struct var *vartab[VTABSIZE];
11957 static int vpcmp(const void *, const void *);
11958 static struct var **findvar(struct var **, const char *);
11961 * Initialize the variable symbol tables and import the environment
11965 #ifdef CONFIG_ASH_GETOPTS
11967 * Safe version of setvar, returns 1 on success 0 on failure.
11971 setvarsafe(const char *name, const char *val, int flags)
11974 volatile int saveint;
11975 struct jmploc *volatile savehandler = handler;
11976 struct jmploc jmploc;
11979 if (setjmp(jmploc.loc))
11983 setvar(name, val, flags);
11986 handler = savehandler;
11987 RESTOREINT(saveint);
11993 * Set the value of a variable. The flags argument is ored with the
11994 * flags of the variable. If val is NULL, the variable is unset.
11998 setvar(const char *name, const char *val, int flags)
12005 q = endofname(name);
12006 p = strchrnul(q, '=');
12007 namelen = p - name;
12008 if (!namelen || p != q)
12009 sh_error("%.*s: bad variable name", namelen, name);
12014 vallen = strlen(val);
12017 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12020 p = mempcpy(p, val, vallen);
12023 setvareq(nameeq, flags | VNOSAVE);
12029 * Same as setvar except that the variable and value are passed in
12030 * the first argument as name=value. Since the first argument will
12031 * be actually stored in the table, it should not be a string that
12033 * Called with interrupts off.
12037 setvareq(char *s, int flags)
12039 struct var *vp, **vpp;
12042 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12043 vp = *findvar(vpp, s);
12045 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12048 if (flags & VNOSAVE)
12051 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12054 if (flags & VNOSET)
12057 if (vp->func && (flags & VNOFUNC) == 0)
12058 (*vp->func)(strchrnul(s, '=') + 1);
12060 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12063 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12065 if (flags & VNOSET)
12068 vp = ckmalloc(sizeof (*vp));
12073 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12081 * Process a linked list of variable assignments.
12085 listsetvar(struct strlist *list_set_var, int flags)
12087 struct strlist *lp = list_set_var;
12093 setvareq(lp->text, flags);
12094 } while ((lp = lp->next));
12100 * Find the value of a variable. Returns NULL if not set.
12104 lookupvar(const char *name)
12108 if ((v = *findvar(hashvar(name), name))) {
12111 * Dynamic variables are implemented roughly the same way they are
12112 * in bash. Namely, they're "special" so long as they aren't unset.
12113 * As soon as they're unset, they're no longer dynamic, and dynamic
12114 * lookup will no longer happen at that point. -- PFM.
12116 if((v->flags & VDYNAMIC))
12119 if(!(v->flags & VUNSET))
12120 return strchrnul(v->text, '=') + 1;
12128 * Search the environment of a builtin command.
12132 bltinlookup(const char *name)
12134 struct strlist *sp;
12136 for (sp = cmdenviron ; sp ; sp = sp->next) {
12137 if (varequal(sp->text, name))
12138 return strchrnul(sp->text, '=') + 1;
12140 return lookupvar(name);
12145 * Generate a list of variables satisfying the given conditions.
12149 listvars(int on, int off, char ***end)
12160 for (vp = *vpp ; vp ; vp = vp->next)
12161 if ((vp->flags & mask) == on) {
12162 if (ep == stackstrend())
12163 ep = growstackstr();
12164 *ep++ = (char *) vp->text;
12166 } while (++vpp < vartab + VTABSIZE);
12167 if (ep == stackstrend())
12168 ep = growstackstr();
12172 return grabstackstr(ep);
12177 * POSIX requires that 'set' (but not export or readonly) output the
12178 * variables in lexicographic order - by the locale's collating order (sigh).
12179 * Maybe we could keep them in an ordered balanced binary tree
12180 * instead of hashed lists.
12181 * For now just roll 'em through qsort for printing...
12185 showvars(const char *sep_prefix, int on, int off)
12188 char **ep, **epend;
12190 ep = listvars(on, off, &epend);
12191 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12193 sep = *sep_prefix ? spcstr : sep_prefix;
12195 for (; ep < epend; ep++) {
12199 p = strchrnul(*ep, '=');
12202 q = single_quote(++p);
12204 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12213 * The export and readonly commands.
12217 exportcmd(int argc, char **argv)
12223 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12226 notp = nextopt("p") - 'p';
12227 if (notp && ((name = *(aptr = argptr)))) {
12229 if ((p = strchr(name, '=')) != NULL) {
12232 if ((vp = *findvar(hashvar(name), name))) {
12237 setvar(name, p, flag);
12238 } while ((name = *++aptr) != NULL);
12240 showvars(argv[0], flag, 0);
12247 * Make a variable a local variable. When a variable is made local, it's
12248 * value and flags are saved in a localvar structure. The saved values
12249 * will be restored when the shell function returns. We handle the name
12250 * "-" as a special case.
12253 static void mklocal(char *name)
12255 struct localvar *lvp;
12260 lvp = ckmalloc(sizeof (struct localvar));
12261 if (name[0] == '-' && name[1] == '\0') {
12263 p = ckmalloc(sizeof(optlist));
12264 lvp->text = memcpy(p, optlist, sizeof(optlist));
12269 vpp = hashvar(name);
12270 vp = *findvar(vpp, name);
12271 eq = strchr(name, '=');
12274 setvareq(name, VSTRFIXED);
12276 setvar(name, NULL, VSTRFIXED);
12277 vp = *vpp; /* the new variable */
12278 lvp->flags = VUNSET;
12280 lvp->text = vp->text;
12281 lvp->flags = vp->flags;
12282 vp->flags |= VSTRFIXED|VTEXTFIXED;
12288 lvp->next = localvars;
12294 * The "local" command.
12298 localcmd(int argc, char **argv)
12303 while ((name = *argv++) != NULL) {
12311 * Called after a function returns.
12312 * Interrupts must be off.
12318 struct localvar *lvp;
12321 while ((lvp = localvars) != NULL) {
12322 localvars = lvp->next;
12324 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12325 if (vp == NULL) { /* $- saved */
12326 memcpy(optlist, lvp->text, sizeof(optlist));
12329 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12330 unsetvar(vp->text);
12333 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12334 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12336 vp->flags = lvp->flags;
12337 vp->text = lvp->text;
12345 * The unset builtin command. We unset the function before we unset the
12346 * variable to allow a function to be unset when there is a readonly variable
12347 * with the same name.
12351 unsetcmd(int argc, char **argv)
12358 while ((i = nextopt("vf")) != '\0') {
12362 for (ap = argptr; *ap ; ap++) {
12377 * Unset the specified variable.
12381 unsetvar(const char *s)
12387 vpp = findvar(hashvar(s), s);
12391 int flags = vp->flags;
12394 if (flags & VREADONLY)
12397 vp->flags &= ~VDYNAMIC;
12399 if (flags & VUNSET)
12401 if ((flags & VSTRFIXED) == 0) {
12403 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12410 vp->flags &= ~VEXPORT;
12423 * Find the appropriate entry in the hash table from the name.
12426 static struct var **
12427 hashvar(const char *p)
12429 unsigned int hashval;
12431 hashval = ((unsigned char) *p) << 4;
12432 while (*p && *p != '=')
12433 hashval += (unsigned char) *p++;
12434 return &vartab[hashval % VTABSIZE];
12440 * Compares two strings up to the first = or '\0'. The first
12441 * string must be terminated by '='; the second may be terminated by
12442 * either '=' or '\0'.
12446 varcmp(const char *p, const char *q)
12450 while ((c = *p) == (d = *q)) {
12451 if (!c || c == '=')
12465 vpcmp(const void *a, const void *b)
12467 return varcmp(*(const char **)a, *(const char **)b);
12470 static struct var **
12471 findvar(struct var **vpp, const char *name)
12473 for (; *vpp; vpp = &(*vpp)->next) {
12474 if (varequal((*vpp)->text, name)) {
12482 #include <sys/times.h>
12484 static const unsigned char timescmd_str[] = {
12485 ' ', offsetof(struct tms, tms_utime),
12486 '\n', offsetof(struct tms, tms_stime),
12487 ' ', offsetof(struct tms, tms_cutime),
12488 '\n', offsetof(struct tms, tms_cstime),
12492 static int timescmd(int ac, char **av)
12494 long int clk_tck, s, t;
12495 const unsigned char *p;
12498 clk_tck = sysconf(_SC_CLK_TCK);
12503 t = *(clock_t *)(((char *) &buf) + p[1]);
12505 out1fmt("%ldm%ld.%.3lds%c",
12507 ((t - s * clk_tck) * 1000) / clk_tck,
12509 } while (*(p += 2));
12514 #ifdef CONFIG_ASH_MATH_SUPPORT
12516 dash_arith(const char *s)
12522 result = arith(s, &errcode);
12525 sh_error("exponent less than 0");
12526 else if (errcode == -2)
12527 sh_error("divide by zero");
12528 else if (errcode == -5)
12529 sh_error("expression recursion loop detected");
12540 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12541 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12543 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12547 letcmd(int argc, char **argv)
12554 sh_error("expression expected");
12555 for (ap = argv + 1; *ap; ap++) {
12556 i = dash_arith(*ap);
12561 #endif /* CONFIG_ASH_MATH_SUPPORT */
12566 * Miscellaneous builtins.
12572 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12573 typedef enum __rlimit_resource rlim_t;
12579 * The read builtin. The -e option causes backslashes to escape the
12580 * following character.
12582 * This uses unbuffered input, which may be avoidable in some cases.
12586 readcmd(int argc, char **argv)
12598 #if defined(CONFIG_ASH_READ_NCHARS)
12602 struct termios tty, old_tty;
12604 #if defined(CONFIG_ASH_READ_TIMEOUT)
12608 ts.tv_sec = ts.tv_usec = 0;
12613 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12614 while ((i = nextopt("p:rt:n:s")) != '\0')
12615 #elif defined(CONFIG_ASH_READ_NCHARS)
12616 while ((i = nextopt("p:rn:s")) != '\0')
12617 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12618 while ((i = nextopt("p:rt:")) != '\0')
12620 while ((i = nextopt("p:r")) != '\0')
12625 prompt = optionarg;
12627 #if defined(CONFIG_ASH_READ_NCHARS)
12629 nchars = strtol(optionarg, &p, 10);
12631 sh_error("invalid count");
12632 nch_flag = (nchars > 0);
12638 #if defined(CONFIG_ASH_READ_TIMEOUT)
12640 ts.tv_sec = strtol(optionarg, &p, 10);
12646 ts.tv_usec = strtol(p, &p2, 10);
12648 sh_error("invalid timeout");
12650 /* normalize to usec */
12652 sh_error("invalid timeout");
12653 while (scale++ < 6)
12657 sh_error("invalid timeout");
12659 if ( ! ts.tv_sec && ! ts.tv_usec)
12660 sh_error("invalid timeout");
12670 if (prompt && isatty(0)) {
12673 if (*(ap = argptr) == NULL)
12674 sh_error("arg count");
12675 if ((ifs = bltinlookup("IFS")) == NULL)
12677 #if defined(CONFIG_ASH_READ_NCHARS)
12678 if (nch_flag || silent) {
12679 tcgetattr(0, &tty);
12682 tty.c_lflag &= ~ICANON;
12683 tty.c_cc[VMIN] = nchars;
12686 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12689 tcsetattr(0, TCSANOW, &tty);
12692 #if defined(CONFIG_ASH_READ_TIMEOUT)
12693 if (ts.tv_sec || ts.tv_usec) {
12697 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12699 #if defined(CONFIG_ASH_READ_NCHARS)
12701 tcsetattr(0, TCSANOW, &old_tty);
12711 #if defined(CONFIG_ASH_READ_NCHARS)
12712 while (!nch_flag || nchars--)
12717 if (read(0, &c, 1) != 1) {
12729 if (!rflag && c == '\\') {
12735 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12739 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12741 setvar(*ap, stackblock(), 0);
12750 #if defined(CONFIG_ASH_READ_NCHARS)
12751 if (nch_flag || silent)
12752 tcsetattr(0, TCSANOW, &old_tty);
12756 /* Remove trailing blanks */
12757 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12759 setvar(*ap, stackblock(), 0);
12760 while (*++ap != NULL)
12761 setvar(*ap, nullstr, 0);
12766 static int umaskcmd(int argc, char **argv)
12768 static const char permuser[3] = "ugo";
12769 static const char permmode[3] = "rwx";
12770 static const short int permmask[] = {
12771 S_IRUSR, S_IWUSR, S_IXUSR,
12772 S_IRGRP, S_IWGRP, S_IXGRP,
12773 S_IROTH, S_IWOTH, S_IXOTH
12779 int symbolic_mode = 0;
12781 while (nextopt("S") != '\0') {
12790 if ((ap = *argptr) == NULL) {
12791 if (symbolic_mode) {
12795 for (i = 0; i < 3; i++) {
12798 *p++ = permuser[i];
12800 for (j = 0; j < 3; j++) {
12801 if ((mask & permmask[3 * i + j]) == 0) {
12802 *p++ = permmode[j];
12810 out1fmt("%.4o\n", mask);
12813 if (is_digit((unsigned char) *ap)) {
12816 if (*ap >= '8' || *ap < '0')
12817 sh_error(illnum, argv[1]);
12818 mask = (mask << 3) + (*ap - '0');
12819 } while (*++ap != '\0');
12822 mask = ~mask & 0777;
12823 if (!bb_parse_mode(ap, &mask)) {
12824 sh_error("Illegal mode: %s", ap);
12826 umask(~mask & 0777);
12835 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12836 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12837 * ash by J.T. Conklin.
12845 int factor; /* multiply by to get rlim_{cur,max} values */
12849 static const struct limits limits[] = {
12851 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12853 #ifdef RLIMIT_FSIZE
12854 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12857 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12859 #ifdef RLIMIT_STACK
12860 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12863 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12866 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12868 #ifdef RLIMIT_MEMLOCK
12869 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12871 #ifdef RLIMIT_NPROC
12872 { "process", RLIMIT_NPROC, 1, 'p' },
12874 #ifdef RLIMIT_NOFILE
12875 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12878 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12880 #ifdef RLIMIT_LOCKS
12881 { "locks", RLIMIT_LOCKS, 1, 'w' },
12883 { (char *) 0, 0, 0, '\0' }
12886 enum limtype { SOFT = 0x1, HARD = 0x2 };
12888 static void printlim(enum limtype how, const struct rlimit *limit,
12889 const struct limits *l)
12893 val = limit->rlim_max;
12895 val = limit->rlim_cur;
12897 if (val == RLIM_INFINITY)
12898 out1fmt("unlimited\n");
12901 out1fmt("%lld\n", (long long) val);
12906 ulimitcmd(int argc, char **argv)
12910 enum limtype how = SOFT | HARD;
12911 const struct limits *l;
12914 struct rlimit limit;
12917 while ((optc = nextopt("HSa"
12921 #ifdef RLIMIT_FSIZE
12927 #ifdef RLIMIT_STACK
12936 #ifdef RLIMIT_MEMLOCK
12939 #ifdef RLIMIT_NPROC
12942 #ifdef RLIMIT_NOFILE
12948 #ifdef RLIMIT_LOCKS
12966 for (l = limits; l->option != what; l++)
12969 set = *argptr ? 1 : 0;
12973 if (all || argptr[1])
12974 sh_error("too many arguments");
12975 if (strncmp(p, "unlimited\n", 9) == 0)
12976 val = RLIM_INFINITY;
12980 while ((c = *p++) >= '0' && c <= '9')
12982 val = (val * 10) + (long)(c - '0');
12983 if (val < (rlim_t) 0)
12987 sh_error("bad number");
12992 for (l = limits; l->name; l++) {
12993 getrlimit(l->cmd, &limit);
12994 out1fmt("%-20s ", l->name);
12995 printlim(how, &limit, l);
13000 getrlimit(l->cmd, &limit);
13003 limit.rlim_max = val;
13005 limit.rlim_cur = val;
13006 if (setrlimit(l->cmd, &limit) < 0)
13007 sh_error("error setting limit (%m)");
13009 printlim(how, &limit, l);
13015 #ifdef CONFIG_ASH_MATH_SUPPORT
13017 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13019 Permission is hereby granted, free of charge, to any person obtaining
13020 a copy of this software and associated documentation files (the
13021 "Software"), to deal in the Software without restriction, including
13022 without limitation the rights to use, copy, modify, merge, publish,
13023 distribute, sublicense, and/or sell copies of the Software, and to
13024 permit persons to whom the Software is furnished to do so, subject to
13025 the following conditions:
13027 The above copyright notice and this permission notice shall be
13028 included in all copies or substantial portions of the Software.
13030 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13031 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13032 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13033 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13034 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13035 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13036 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13039 /* This is my infix parser/evaluator. It is optimized for size, intended
13040 * as a replacement for yacc-based parsers. However, it may well be faster
13041 * than a comparable parser written in yacc. The supported operators are
13042 * listed in #defines below. Parens, order of operations, and error handling
13043 * are supported. This code is thread safe. The exact expression format should
13044 * be that which POSIX specifies for shells. */
13046 /* The code uses a simple two-stack algorithm. See
13047 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13048 * for a detailed explanation of the infix-to-postfix algorithm on which
13049 * this is based (this code differs in that it applies operators immediately
13050 * to the stack instead of adding them to a queue to end up with an
13053 /* To use the routine, call it with an expression string and error return
13057 * Aug 24, 2001 Manuel Novoa III
13059 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13061 * 1) In arith_apply():
13062 * a) Cached values of *numptr and &(numptr[-1]).
13063 * b) Removed redundant test for zero denominator.
13066 * a) Eliminated redundant code for processing operator tokens by moving
13067 * to a table-based implementation. Also folded handling of parens
13069 * b) Combined all 3 loops which called arith_apply to reduce generated
13070 * code size at the cost of speed.
13072 * 3) The following expressions were treated as valid by the original code:
13073 * 1() , 0! , 1 ( *3 ) .
13074 * These bugs have been fixed by internally enclosing the expression in
13075 * parens and then checking that all binary ops and right parens are
13076 * preceded by a valid expression (NUM_TOKEN).
13078 * Note: It may be desirable to replace Aaron's test for whitespace with
13079 * ctype's isspace() if it is used by another busybox applet or if additional
13080 * whitespace chars should be considered. Look below the "#include"s for a
13081 * precompiler test.
13085 * Aug 26, 2001 Manuel Novoa III
13087 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13089 * Merge in Aaron's comments previously posted to the busybox list,
13090 * modified slightly to take account of my changes to the code.
13095 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13097 * - allow access to variable,
13098 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13099 * - realize assign syntax (VAR=expr, +=, *= etc)
13100 * - realize exponentiation (** operator)
13101 * - realize comma separated - expr, expr
13102 * - realise ++expr --expr expr++ expr--
13103 * - realise expr ? expr : expr (but, second expr calculate always)
13104 * - allow hexadecimal and octal numbers
13105 * - was restored loses XOR operator
13106 * - remove one goto label, added three ;-)
13107 * - protect $((num num)) as true zero expr (Manuel`s error)
13108 * - always use special isspace(), see comment from bash ;-)
13112 #define arith_isspace(arithval) \
13113 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13116 typedef unsigned char operator;
13118 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13119 * precedence, and 3 high bits are an ID unique across operators of that
13120 * precedence. The ID portion is so that multiple operators can have the
13121 * same precedence, ensuring that the leftmost one is evaluated first.
13122 * Consider * and /. */
13124 #define tok_decl(prec,id) (((id)<<5)|(prec))
13125 #define PREC(op) ((op) & 0x1F)
13127 #define TOK_LPAREN tok_decl(0,0)
13129 #define TOK_COMMA tok_decl(1,0)
13131 #define TOK_ASSIGN tok_decl(2,0)
13132 #define TOK_AND_ASSIGN tok_decl(2,1)
13133 #define TOK_OR_ASSIGN tok_decl(2,2)
13134 #define TOK_XOR_ASSIGN tok_decl(2,3)
13135 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13136 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13137 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13138 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13140 #define TOK_MUL_ASSIGN tok_decl(3,0)
13141 #define TOK_DIV_ASSIGN tok_decl(3,1)
13142 #define TOK_REM_ASSIGN tok_decl(3,2)
13144 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13145 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13147 /* conditional is right associativity too */
13148 #define TOK_CONDITIONAL tok_decl(4,0)
13149 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13151 #define TOK_OR tok_decl(5,0)
13153 #define TOK_AND tok_decl(6,0)
13155 #define TOK_BOR tok_decl(7,0)
13157 #define TOK_BXOR tok_decl(8,0)
13159 #define TOK_BAND tok_decl(9,0)
13161 #define TOK_EQ tok_decl(10,0)
13162 #define TOK_NE tok_decl(10,1)
13164 #define TOK_LT tok_decl(11,0)
13165 #define TOK_GT tok_decl(11,1)
13166 #define TOK_GE tok_decl(11,2)
13167 #define TOK_LE tok_decl(11,3)
13169 #define TOK_LSHIFT tok_decl(12,0)
13170 #define TOK_RSHIFT tok_decl(12,1)
13172 #define TOK_ADD tok_decl(13,0)
13173 #define TOK_SUB tok_decl(13,1)
13175 #define TOK_MUL tok_decl(14,0)
13176 #define TOK_DIV tok_decl(14,1)
13177 #define TOK_REM tok_decl(14,2)
13179 /* exponent is right associativity */
13180 #define TOK_EXPONENT tok_decl(15,1)
13182 /* For now unary operators. */
13183 #define UNARYPREC 16
13184 #define TOK_BNOT tok_decl(UNARYPREC,0)
13185 #define TOK_NOT tok_decl(UNARYPREC,1)
13187 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13188 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13190 #define PREC_PRE (UNARYPREC+2)
13192 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13193 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13195 #define PREC_POST (UNARYPREC+3)
13197 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13198 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13200 #define SPEC_PREC (UNARYPREC+4)
13202 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13203 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13205 #define NUMPTR (*numstackptr)
13207 static int tok_have_assign(operator op)
13209 operator prec = PREC(op);
13211 convert_prec_is_assing(prec);
13212 return (prec == PREC(TOK_ASSIGN) ||
13213 prec == PREC_PRE || prec == PREC_POST);
13216 static int is_right_associativity(operator prec)
13218 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13219 prec == PREC(TOK_CONDITIONAL));
13223 typedef struct ARITCH_VAR_NUM {
13225 arith_t contidional_second_val;
13226 char contidional_second_val_initialized;
13227 char *var; /* if NULL then is regular number,
13228 else is variable name */
13232 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13234 struct CHK_VAR_RECURSIVE_LOOPED *next;
13235 } chk_var_recursive_looped_t;
13237 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13240 static int arith_lookup_val(v_n_t *t)
13243 const char * p = lookupvar(t->var);
13248 /* recursive try as expression */
13249 chk_var_recursive_looped_t *cur;
13250 chk_var_recursive_looped_t cur_save;
13252 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13253 if(strcmp(cur->var, t->var) == 0) {
13254 /* expression recursion loop detected */
13258 /* save current lookuped var name */
13259 cur = prev_chk_var_recursive;
13260 cur_save.var = t->var;
13261 cur_save.next = cur;
13262 prev_chk_var_recursive = &cur_save;
13264 t->val = arith (p, &errcode);
13265 /* restore previous ptr after recursiving */
13266 prev_chk_var_recursive = cur;
13269 /* allow undefined var as 0 */
13276 /* "applying" a token means performing it on the top elements on the integer
13277 * stack. For a unary operator it will only change the top element, but a
13278 * binary operator will pop two arguments and push a result */
13279 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13282 arith_t numptr_val, rez;
13283 int ret_arith_lookup_val;
13285 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13286 without arguments */
13287 numptr_m1 = NUMPTR - 1;
13289 /* check operand is var with noninteger value */
13290 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13291 if(ret_arith_lookup_val)
13292 return ret_arith_lookup_val;
13294 rez = numptr_m1->val;
13295 if (op == TOK_UMINUS)
13297 else if (op == TOK_NOT)
13299 else if (op == TOK_BNOT)
13301 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13303 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13305 else if (op != TOK_UPLUS) {
13306 /* Binary operators */
13308 /* check and binary operators need two arguments */
13309 if (numptr_m1 == numstack) goto err;
13311 /* ... and they pop one */
13314 if (op == TOK_CONDITIONAL) {
13315 if(! numptr_m1->contidional_second_val_initialized) {
13316 /* protect $((expr1 ? expr2)) without ": expr" */
13319 rez = numptr_m1->contidional_second_val;
13320 } else if(numptr_m1->contidional_second_val_initialized) {
13321 /* protect $((expr1 : expr2)) without "expr ? " */
13324 numptr_m1 = NUMPTR - 1;
13325 if(op != TOK_ASSIGN) {
13326 /* check operand is var with noninteger value for not '=' */
13327 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13328 if(ret_arith_lookup_val)
13329 return ret_arith_lookup_val;
13331 if (op == TOK_CONDITIONAL) {
13332 numptr_m1->contidional_second_val = rez;
13334 rez = numptr_m1->val;
13335 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13337 else if (op == TOK_OR)
13338 rez = numptr_val || rez;
13339 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13341 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13343 else if (op == TOK_AND)
13344 rez = rez && numptr_val;
13345 else if (op == TOK_EQ)
13346 rez = (rez == numptr_val);
13347 else if (op == TOK_NE)
13348 rez = (rez != numptr_val);
13349 else if (op == TOK_GE)
13350 rez = (rez >= numptr_val);
13351 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13352 rez >>= numptr_val;
13353 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13354 rez <<= numptr_val;
13355 else if (op == TOK_GT)
13356 rez = (rez > numptr_val);
13357 else if (op == TOK_LT)
13358 rez = (rez < numptr_val);
13359 else if (op == TOK_LE)
13360 rez = (rez <= numptr_val);
13361 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13363 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13365 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13367 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13369 else if (op == TOK_CONDITIONAL_SEP) {
13370 if (numptr_m1 == numstack) {
13371 /* protect $((expr : expr)) without "expr ? " */
13374 numptr_m1->contidional_second_val_initialized = op;
13375 numptr_m1->contidional_second_val = numptr_val;
13377 else if (op == TOK_CONDITIONAL) {
13379 numptr_val : numptr_m1->contidional_second_val;
13381 else if(op == TOK_EXPONENT) {
13383 return -3; /* exponent less than 0 */
13388 while(numptr_val--)
13393 else if(numptr_val==0) /* zero divisor check */
13395 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13397 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13400 if(tok_have_assign(op)) {
13403 if(numptr_m1->var == NULL) {
13407 /* save to shell variable */
13408 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13409 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13411 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13413 setvar(numptr_m1->var, buf, 0);
13414 /* after saving, make previous value for v++ or v-- */
13415 if(op == TOK_POST_INC)
13417 else if(op == TOK_POST_DEC)
13420 numptr_m1->val = rez;
13421 /* protect geting var value, is number now */
13422 numptr_m1->var = NULL;
13427 /* longest must first */
13428 static const char op_tokens[] = {
13429 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13430 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13431 '<','<', 0, TOK_LSHIFT,
13432 '>','>', 0, TOK_RSHIFT,
13433 '|','|', 0, TOK_OR,
13434 '&','&', 0, TOK_AND,
13435 '!','=', 0, TOK_NE,
13436 '<','=', 0, TOK_LE,
13437 '>','=', 0, TOK_GE,
13438 '=','=', 0, TOK_EQ,
13439 '|','=', 0, TOK_OR_ASSIGN,
13440 '&','=', 0, TOK_AND_ASSIGN,
13441 '*','=', 0, TOK_MUL_ASSIGN,
13442 '/','=', 0, TOK_DIV_ASSIGN,
13443 '%','=', 0, TOK_REM_ASSIGN,
13444 '+','=', 0, TOK_PLUS_ASSIGN,
13445 '-','=', 0, TOK_MINUS_ASSIGN,
13446 '-','-', 0, TOK_POST_DEC,
13447 '^','=', 0, TOK_XOR_ASSIGN,
13448 '+','+', 0, TOK_POST_INC,
13449 '*','*', 0, TOK_EXPONENT,
13453 '=', 0, TOK_ASSIGN,
13465 '?', 0, TOK_CONDITIONAL,
13466 ':', 0, TOK_CONDITIONAL_SEP,
13467 ')', 0, TOK_RPAREN,
13468 '(', 0, TOK_LPAREN,
13472 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13475 static arith_t arith (const char *expr, int *perrcode)
13477 char arithval; /* Current character under analysis */
13478 operator lasttok, op;
13481 const char *p = endexpression;
13484 size_t datasizes = strlen(expr) + 2;
13486 /* Stack of integers */
13487 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13488 * in any given correct or incorrect expression is left as an exercise to
13490 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13491 *numstackptr = numstack;
13492 /* Stack of operator tokens */
13493 operator *stack = alloca((datasizes) * sizeof(operator)),
13496 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13497 *perrcode = errcode = 0;
13500 if ((arithval = *expr) == 0) {
13501 if (p == endexpression) {
13502 /* Null expression. */
13506 /* This is only reached after all tokens have been extracted from the
13507 * input stream. If there are still tokens on the operator stack, they
13508 * are to be applied in order. At the end, there should be a final
13509 * result on the integer stack */
13511 if (expr != endexpression + 1) {
13512 /* If we haven't done so already, */
13513 /* append a closing right paren */
13514 expr = endexpression;
13515 /* and let the loop process it. */
13518 /* At this point, we're done with the expression. */
13519 if (numstackptr != numstack+1) {
13520 /* ... but if there isn't, it's bad */
13522 return (*perrcode = -1);
13524 if(numstack->var) {
13525 /* expression is $((var)) only, lookup now */
13526 errcode = arith_lookup_val(numstack);
13529 *perrcode = errcode;
13530 return numstack->val;
13532 /* Continue processing the expression. */
13533 if (arith_isspace(arithval)) {
13534 /* Skip whitespace */
13537 if((p = endofname(expr)) != expr) {
13538 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13540 numstackptr->var = alloca(var_name_size);
13541 safe_strncpy(numstackptr->var, expr, var_name_size);
13544 numstackptr->contidional_second_val_initialized = 0;
13548 } else if (is_digit(arithval)) {
13549 numstackptr->var = NULL;
13550 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13551 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13553 numstackptr->val = strtol(expr, (char **) &expr, 0);
13557 for(p = op_tokens; ; p++) {
13561 /* strange operator not found */
13564 for(o = expr; *p && *o == *p; p++)
13571 /* skip tail uncompared token */
13574 /* skip zero delim */
13579 /* post grammar: a++ reduce to num */
13580 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13583 /* Plus and minus are binary (not unary) _only_ if the last
13584 * token was as number, or a right paren (which pretends to be
13585 * a number, since it evaluates to one). Think about it.
13586 * It makes sense. */
13587 if (lasttok != TOK_NUM) {
13603 /* We don't want a unary operator to cause recursive descent on the
13604 * stack, because there can be many in a row and it could cause an
13605 * operator to be evaluated before its argument is pushed onto the
13606 * integer stack. */
13607 /* But for binary operators, "apply" everything on the operator
13608 * stack until we find an operator with a lesser priority than the
13609 * one we have just extracted. */
13610 /* Left paren is given the lowest priority so it will never be
13611 * "applied" in this way.
13612 * if associativity is right and priority eq, applied also skip
13615 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13616 /* not left paren or unary */
13617 if (lasttok != TOK_NUM) {
13618 /* binary op must be preceded by a num */
13621 while (stackptr != stack) {
13622 if (op == TOK_RPAREN) {
13623 /* The algorithm employed here is simple: while we don't
13624 * hit an open paren nor the bottom of the stack, pop
13625 * tokens and apply them */
13626 if (stackptr[-1] == TOK_LPAREN) {
13628 /* Any operator directly after a */
13630 /* close paren should consider itself binary */
13634 operator prev_prec = PREC(stackptr[-1]);
13636 convert_prec_is_assing(prec);
13637 convert_prec_is_assing(prev_prec);
13638 if (prev_prec < prec)
13640 /* check right assoc */
13641 if(prev_prec == prec && is_right_associativity(prec))
13644 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13645 if(errcode) goto ret;
13647 if (op == TOK_RPAREN) {
13652 /* Push this operator to the stack and remember it. */
13653 *stackptr++ = lasttok = op;
13660 #endif /* CONFIG_ASH_MATH_SUPPORT */
13664 const char *applet_name = "debug stuff usage";
13665 int main(int argc, char **argv)
13667 return ash_main(argc, argv);
13672 * Copyright (c) 1989, 1991, 1993, 1994
13673 * The Regents of the University of California. All rights reserved.
13675 * This code is derived from software contributed to Berkeley by
13676 * Kenneth Almquist.
13678 * Redistribution and use in source and binary forms, with or without
13679 * modification, are permitted provided that the following conditions
13681 * 1. Redistributions of source code must retain the above copyright
13682 * notice, this list of conditions and the following disclaimer.
13683 * 2. Redistributions in binary form must reproduce the above copyright
13684 * notice, this list of conditions and the following disclaimer in the
13685 * documentation and/or other materials provided with the distribution.
13686 * 3. Neither the name of the University nor the names of its contributors
13687 * may be used to endorse or promote products derived from this software
13688 * without specific prior written permission.
13690 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13691 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13692 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13693 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13694 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13695 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13696 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13697 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13698 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13699 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF