1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
36 * The follow should be set to reflect the type of system you have:
37 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
38 * define SYSV if you are running under System V.
39 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
40 * define DEBUG=2 to compile in and turn on debugging.
42 * When debugging is on, debugging info will be written to ./trace and
43 * a quit signal will generate a core dump.
57 #include <sys/types.h>
58 #include <sys/ioctl.h>
59 #include <sys/param.h>
60 #include <sys/resource.h>
80 /*#include <stdint.h>*/
84 #ifdef CONFIG_ASH_JOB_CONTROL
90 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
98 static int *dash_errno;
100 #define errno (*dash_errno)
103 #if defined(__uClinux__)
104 #error "Do not even bother, ash will not run on uClinux"
108 #define _DIAGASSERT(assert_expr) assert(assert_expr)
110 #define _DIAGASSERT(assert_expr)
114 #ifdef CONFIG_ASH_ALIAS
127 static struct alias *lookupalias(const char *, int);
128 static int aliascmd(int, char **);
129 static int unaliascmd(int, char **);
130 static void rmaliases(void);
131 static int unalias(const char *);
132 static void printalias(const struct alias *);
138 static void setpwd(const char *, int);
144 * Types of operations (passed to the errmsg routine).
148 static const char not_found_msg[] = "%s: not found";
151 #define E_OPEN "No such file" /* opening a file */
152 #define E_CREAT "Directory nonexistent" /* creating a file */
153 #define E_EXEC not_found_msg+4 /* executing a program */
156 * We enclose jmp_buf in a structure so that we can declare pointers to
157 * jump locations. The global variable handler contains the location to
158 * jump to when an exception occurs, and the global variable exception
159 * contains a code identifying the exception. To implement nested
160 * exception handlers, the user should save the value of handler on entry
161 * to an inner scope, set handler to point to a jmploc structure for the
162 * inner scope, and restore handler on exit from the scope.
169 static struct jmploc *handler;
170 static int exception;
171 static volatile int suppressint;
172 static volatile sig_atomic_t intpending;
175 #define EXINT 0 /* SIGINT received */
176 #define EXERROR 1 /* a generic error */
177 #define EXSHELLPROC 2 /* execute a shell procedure */
178 #define EXEXEC 3 /* command execution failed */
179 #define EXEXIT 4 /* exit the shell */
180 #define EXSIG 5 /* trapped signal in wait(1) */
183 /* do we generate EXSIG events */
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsigs;
189 * These macros allow the user to suspend the handling of interrupt signals
190 * over a period of time. This is similar to SIGHOLD to or sigblock, but
191 * much more efficient and portable. (But hacking the kernel is so much
192 * more fun than worrying about efficiency and portability. :-))
195 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
202 #define SAVEINT(v) ((v) = suppressint)
203 #define RESTOREINT(v) \
206 if ((suppressint = (v)) == 0 && intpending) onint(); \
217 /* EXSIG is turned off by evalbltin(). */
220 static void exraise(int) ATTRIBUTE_NORETURN;
221 static void onint(void) ATTRIBUTE_NORETURN;
223 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
224 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
226 static void sh_warnx(const char *, ...);
228 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
231 if (--suppressint == 0 && intpending) {
235 #define INTON inton()
236 static void forceinton(void)
242 #define FORCEINTON forceinton()
247 if (--suppressint == 0 && intpending) onint(); \
254 if (intpending) onint(); \
257 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
262 struct strlist *next;
268 struct strlist *list;
269 struct strlist **lastp;
275 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
276 #define EXP_TILDE 0x2 /* do normal tilde expansion */
277 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
278 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
279 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
280 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
281 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
282 #define EXP_WORD 0x80 /* expand word in parameter expansion */
283 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
287 static void expandarg(union node *, struct arglist *, int);
288 #define rmescapes(p) _rmescapes((p), 0)
289 static char *_rmescapes(char *, int);
290 static int casematch(union node *, char *);
292 #ifdef CONFIG_ASH_MATH_SUPPORT
293 static void expari(int);
298 static char *commandname; /* currently executing command */
299 static struct strlist *cmdenviron; /* environment for builtin command */
300 static int exitstatus; /* exit status of last command */
301 static int back_exitstatus; /* exit status of backquoted command */
304 struct backcmd { /* result of evalbackcmd */
305 int fd; /* file descriptor to read from */
306 char *buf; /* buffer */
307 int nleft; /* number of chars in buffer */
308 struct job *jp; /* job structure for command */
312 * This file was generated by the mknodes program.
348 union node *redirect;
355 struct nodelist *cmdlist;
362 union node *redirect;
377 union node *elsepart;
408 struct nodelist *backquote;
448 struct nredir nredir;
449 struct nbinary nbinary;
453 struct nclist nclist;
463 struct nodelist *next;
474 static void freefunc(struct funcnode *);
477 /* control characters in argument strings */
478 #define CTL_FIRST '\201' /* first 'special' character */
479 #define CTLESC '\201' /* escape next character */
480 #define CTLVAR '\202' /* variable defn */
481 #define CTLENDVAR '\203'
482 #define CTLBACKQ '\204'
483 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
484 /* CTLBACKQ | CTLQUOTE == '\205' */
485 #define CTLARI '\206' /* arithmetic expression */
486 #define CTLENDARI '\207'
487 #define CTLQUOTEMARK '\210'
488 #define CTL_LAST '\210' /* last 'special' character */
490 /* variable substitution byte (follows CTLVAR) */
491 #define VSTYPE 0x0f /* type of variable substitution */
492 #define VSNUL 0x10 /* colon--treat the empty string as unset */
493 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
495 /* values of VSTYPE field */
496 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
497 #define VSMINUS 0x2 /* ${var-text} */
498 #define VSPLUS 0x3 /* ${var+text} */
499 #define VSQUESTION 0x4 /* ${var?message} */
500 #define VSASSIGN 0x5 /* ${var=text} */
501 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
502 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
503 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
504 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
505 #define VSLENGTH 0xa /* ${#var} */
507 /* values of checkkwd variable */
512 #define IBUFSIZ (BUFSIZ + 1)
515 * NEOF is returned by parsecmd when it encounters an end of file. It
516 * must be distinct from NULL, so we use the address of a variable that
517 * happens to be handy.
519 static int plinno = 1; /* input line number */
521 /* number of characters left in input buffer */
522 static int parsenleft; /* copy of parsefile->nleft */
523 static int parselleft; /* copy of parsefile->lleft */
525 /* next character in input buffer */
526 static char *parsenextc; /* copy of parsefile->nextc */
529 struct strpush *prev; /* preceding string on stack */
532 #ifdef CONFIG_ASH_ALIAS
533 struct alias *ap; /* if push was associated with an alias */
535 char *string; /* remember the string since it may change */
539 struct parsefile *prev; /* preceding file on stack */
540 int linno; /* current line */
541 int fd; /* file descriptor (or -1 if string) */
542 int nleft; /* number of chars left in this line */
543 int lleft; /* number of chars left in this buffer */
544 char *nextc; /* next char in buffer */
545 char *buf; /* input buffer */
546 struct strpush *strpush; /* for pushing strings at this level */
547 struct strpush basestrpush; /* so pushing one is fast */
550 static struct parsefile basepf; /* top level input file */
551 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
552 static struct parsefile *parsefile = &basepf; /* current input file */
555 static int tokpushback; /* last token pushed back */
556 #define NEOF ((union node *)&tokpushback)
557 static int parsebackquote; /* nonzero if we are inside backquotes */
558 static int doprompt; /* if set, prompt the user */
559 static int needprompt; /* true if interactive and at start of line */
560 static int lasttoken; /* last token read */
561 static char *wordtext; /* text of last word returned by readtoken */
563 static struct nodelist *backquotelist;
564 static union node *redirnode;
565 static struct heredoc *heredoc;
566 static int quoteflag; /* set if (part of) last token was quoted */
567 static int startlinno; /* line # where last token started */
569 static union node *parsecmd(int);
570 static void fixredir(union node *, const char *, int);
571 static const char *const *findkwd(const char *);
572 static char *endofname(const char *);
576 typedef void *pointer;
578 static char nullstr[1]; /* zero length string */
579 static const char spcstr[] = " ";
580 static const char snlfmt[] = "%s\n";
581 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
582 static const char illnum[] = "Illegal number: %s";
583 static const char homestr[] = "HOME";
586 #define TRACE(param) trace param
587 #define TRACEV(param) tracev param
590 #define TRACEV(param)
593 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
594 #define __builtin_expect(x, expected_value) (x)
597 #define xlikely(x) __builtin_expect((x),1)
612 #define TENDBQUOTE 12
630 /* first char is indicating which tokens mark the end of a list */
631 static const char *const tokname_array[] = {
646 /* the following are keywords */
665 static const char *tokname(int tok)
671 sprintf(buf + (tok >= TSEMI), "%s%c",
672 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
679 * Most machines require the value returned from malloc to be aligned
680 * in some way. The following macro will get this right on many machines.
683 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
685 * It appears that grabstackstr() will barf with such alignments
686 * because stalloc() will return a string allocated in a new stackblock.
688 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
691 * This file was generated by the mksyntax program.
696 #define CWORD 0 /* character is nothing special */
697 #define CNL 1 /* newline character */
698 #define CBACK 2 /* a backslash character */
699 #define CSQUOTE 3 /* single quote */
700 #define CDQUOTE 4 /* double quote */
701 #define CENDQUOTE 5 /* a terminating quote */
702 #define CBQUOTE 6 /* backwards single quote */
703 #define CVAR 7 /* a dollar sign */
704 #define CENDVAR 8 /* a '}' character */
705 #define CLP 9 /* a left paren in arithmetic */
706 #define CRP 10 /* a right paren in arithmetic */
707 #define CENDFILE 11 /* end of file */
708 #define CCTL 12 /* like CWORD, except it must be escaped */
709 #define CSPCL 13 /* these terminate a word */
710 #define CIGN 14 /* character should be ignored */
712 #ifdef CONFIG_ASH_ALIAS
716 #define PEOA_OR_PEOF PEOA
720 #define PEOA_OR_PEOF PEOF
723 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
724 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
725 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
727 /* C99 say: "char" declaration may be signed or unsigned default */
728 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
731 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
732 * (assuming ascii char codes, as the original implementation did)
734 #define is_special(c) \
735 ( (((unsigned int)c) - 33 < 32) \
736 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
738 #define digit_val(c) ((c) - '0')
741 * This file was generated by the mksyntax program.
744 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
745 #define USE_SIT_FUNCTION
748 /* number syntax index */
749 #define BASESYNTAX 0 /* not in quotes */
750 #define DQSYNTAX 1 /* in double quotes */
751 #define SQSYNTAX 2 /* in single quotes */
752 #define ARISYNTAX 3 /* in arithmetic */
754 #ifdef CONFIG_ASH_MATH_SUPPORT
755 static const char S_I_T[][4] = {
756 #ifdef CONFIG_ASH_ALIAS
757 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
759 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
760 {CNL, CNL, CNL, CNL}, /* 2, \n */
761 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
762 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
763 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
764 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
765 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
766 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
767 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
768 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
769 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
770 #ifndef USE_SIT_FUNCTION
771 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
772 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
773 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
777 static const char S_I_T[][3] = {
778 #ifdef CONFIG_ASH_ALIAS
779 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
781 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
782 {CNL, CNL, CNL}, /* 2, \n */
783 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
784 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
785 {CVAR, CVAR, CWORD}, /* 5, $ */
786 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
787 {CSPCL, CWORD, CWORD}, /* 7, ( */
788 {CSPCL, CWORD, CWORD}, /* 8, ) */
789 {CBACK, CBACK, CCTL}, /* 9, \ */
790 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
791 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
792 #ifndef USE_SIT_FUNCTION
793 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
794 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
795 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
798 #endif /* CONFIG_ASH_MATH_SUPPORT */
800 #ifdef USE_SIT_FUNCTION
802 #define U_C(c) ((unsigned char)(c))
804 static int SIT(int c, int syntax)
806 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
807 #ifdef CONFIG_ASH_ALIAS
808 static const char syntax_index_table[] = {
809 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
810 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
811 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
815 static const char syntax_index_table[] = {
816 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
817 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
818 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
825 if (c == PEOF) /* 2^8+2 */
827 #ifdef CONFIG_ASH_ALIAS
828 if (c == PEOA) /* 2^8+1 */
832 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
835 s = strchr(spec_symbls, c);
836 if (s == 0 || *s == 0)
838 indx = syntax_index_table[(s - spec_symbls)];
840 return S_I_T[indx][syntax];
843 #else /* USE_SIT_FUNCTION */
845 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
847 #ifdef CONFIG_ASH_ALIAS
848 #define CSPCL_CIGN_CIGN_CIGN 0
849 #define CSPCL_CWORD_CWORD_CWORD 1
850 #define CNL_CNL_CNL_CNL 2
851 #define CWORD_CCTL_CCTL_CWORD 3
852 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
853 #define CVAR_CVAR_CWORD_CVAR 5
854 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
855 #define CSPCL_CWORD_CWORD_CLP 7
856 #define CSPCL_CWORD_CWORD_CRP 8
857 #define CBACK_CBACK_CCTL_CBACK 9
858 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
859 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
860 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
861 #define CWORD_CWORD_CWORD_CWORD 13
862 #define CCTL_CCTL_CCTL_CCTL 14
864 #define CSPCL_CWORD_CWORD_CWORD 0
865 #define CNL_CNL_CNL_CNL 1
866 #define CWORD_CCTL_CCTL_CWORD 2
867 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
868 #define CVAR_CVAR_CWORD_CVAR 4
869 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
870 #define CSPCL_CWORD_CWORD_CLP 6
871 #define CSPCL_CWORD_CWORD_CRP 7
872 #define CBACK_CBACK_CCTL_CBACK 8
873 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
874 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
875 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
876 #define CWORD_CWORD_CWORD_CWORD 12
877 #define CCTL_CCTL_CCTL_CCTL 13
880 static const char syntax_index_table[258] = {
881 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
882 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
883 #ifdef CONFIG_ASH_ALIAS
884 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
886 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
887 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
888 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
889 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
890 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
891 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
892 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
893 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
894 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
895 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
896 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
897 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
898 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
899 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
900 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
901 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
902 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
903 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
904 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
905 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
906 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
907 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
908 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
909 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
910 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
911 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
912 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
913 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
914 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
915 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
916 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
917 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
918 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
919 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
920 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
921 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
922 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
923 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
924 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
925 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
926 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
927 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
928 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
929 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
930 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
931 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
932 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
933 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
934 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
935 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
936 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
937 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
938 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
939 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
940 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
941 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
942 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
943 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
944 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
945 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
946 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
947 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
948 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
949 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
950 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
951 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
952 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
953 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
954 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
955 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
956 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
957 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
958 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
959 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
960 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
961 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
962 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
963 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
964 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
965 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
966 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
967 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
968 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
969 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
970 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
971 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
972 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
973 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
974 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
975 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
976 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
977 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
978 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
979 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
980 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
981 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
982 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
983 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
984 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
985 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
986 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
987 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
988 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
989 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
990 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
991 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
992 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
993 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
994 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
995 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
996 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
997 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
998 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
999 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1024 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1025 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1047 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1048 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1049 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1050 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1051 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1052 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1053 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1054 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1055 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1056 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1057 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1058 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1059 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1060 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1061 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1062 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1063 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1064 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1073 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1074 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1075 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1076 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1077 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1078 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1079 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1106 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1107 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1108 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1111 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1139 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1140 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1141 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1144 #endif /* USE_SIT_FUNCTION */
1151 static int funcblocksize; /* size of structures in function */
1152 static int funcstringsize; /* size of strings in node */
1153 static pointer funcblock; /* block to allocate function from */
1154 static char *funcstring; /* block to allocate strings from */
1156 static const short nodesize[26] = {
1157 SHELL_ALIGN(sizeof (struct ncmd)),
1158 SHELL_ALIGN(sizeof (struct npipe)),
1159 SHELL_ALIGN(sizeof (struct nredir)),
1160 SHELL_ALIGN(sizeof (struct nredir)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nbinary)),
1163 SHELL_ALIGN(sizeof (struct nbinary)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nif)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nfor)),
1169 SHELL_ALIGN(sizeof (struct ncase)),
1170 SHELL_ALIGN(sizeof (struct nclist)),
1171 SHELL_ALIGN(sizeof (struct narg)),
1172 SHELL_ALIGN(sizeof (struct narg)),
1173 SHELL_ALIGN(sizeof (struct nfile)),
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 ndup)),
1179 SHELL_ALIGN(sizeof (struct ndup)),
1180 SHELL_ALIGN(sizeof (struct nhere)),
1181 SHELL_ALIGN(sizeof (struct nhere)),
1182 SHELL_ALIGN(sizeof (struct nnot)),
1186 static void calcsize(union node *);
1187 static void sizenodelist(struct nodelist *);
1188 static union node *copynode(union node *);
1189 static struct nodelist *copynodelist(struct nodelist *);
1190 static char *nodesavestr(char *);
1193 static int evalstring(char *, int mask);
1194 union node; /* BLETCH for ansi C */
1195 static void evaltree(union node *, int);
1196 static void evalbackcmd(union node *, struct backcmd *);
1198 static int evalskip; /* set if we are skipping commands */
1199 static int skipcount; /* number of levels to skip */
1200 static int funcnest; /* depth of function calls */
1202 /* reasons for skipping commands (see comment on breakcmd routine) */
1203 #define SKIPBREAK (1 << 0)
1204 #define SKIPCONT (1 << 1)
1205 #define SKIPFUNC (1 << 2)
1206 #define SKIPFILE (1 << 3)
1207 #define SKIPEVAL (1 << 4)
1210 * This file was generated by the mkbuiltins program.
1214 static int bgcmd(int, char **);
1216 static int breakcmd(int, char **);
1217 static int cdcmd(int, char **);
1218 #ifdef CONFIG_ASH_CMDCMD
1219 static int commandcmd(int, char **);
1221 static int dotcmd(int, char **);
1222 static int evalcmd(int, char **);
1223 #ifdef CONFIG_ASH_BUILTIN_ECHO
1224 static int echocmd(int, char **);
1226 #ifdef CONFIG_ASH_BUILTIN_TEST
1227 static int testcmd(int, char **);
1229 static int execcmd(int, char **);
1230 static int exitcmd(int, char **);
1231 static int exportcmd(int, char **);
1232 static int falsecmd(int, char **);
1234 static int fgcmd(int, char **);
1236 #ifdef CONFIG_ASH_GETOPTS
1237 static int getoptscmd(int, char **);
1239 static int hashcmd(int, char **);
1240 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1241 static int helpcmd(int argc, char **argv);
1244 static int jobscmd(int, char **);
1246 #ifdef CONFIG_ASH_MATH_SUPPORT
1247 static int letcmd(int, char **);
1249 static int localcmd(int, char **);
1250 static int pwdcmd(int, char **);
1251 static int readcmd(int, char **);
1252 static int returncmd(int, char **);
1253 static int setcmd(int, char **);
1254 static int shiftcmd(int, char **);
1255 static int timescmd(int, char **);
1256 static int trapcmd(int, char **);
1257 static int truecmd(int, char **);
1258 static int typecmd(int, char **);
1259 static int umaskcmd(int, char **);
1260 static int unsetcmd(int, char **);
1261 static int waitcmd(int, char **);
1262 static int ulimitcmd(int, char **);
1264 static int killcmd(int, char **);
1269 #ifdef CONFIG_ASH_MAIL
1270 static void chkmail(void);
1271 static void changemail(const char *);
1276 /* values of cmdtype */
1277 #define CMDUNKNOWN -1 /* no entry in table for command */
1278 #define CMDNORMAL 0 /* command is an executable program */
1279 #define CMDFUNCTION 1 /* command is a shell function */
1280 #define CMDBUILTIN 2 /* command is a shell builtin */
1284 int (*builtin)(int, char **);
1285 /* unsigned flags; */
1289 #define COMMANDCMD (builtincmd + 5 + \
1290 2 * ENABLE_ASH_BUILTIN_TEST + \
1291 ENABLE_ASH_ALIAS + \
1292 ENABLE_ASH_JOB_CONTROL)
1293 #define EXECCMD (builtincmd + 7 + \
1294 2 * ENABLE_ASH_BUILTIN_TEST + \
1295 ENABLE_ASH_ALIAS + \
1296 ENABLE_ASH_JOB_CONTROL + \
1297 ENABLE_ASH_CMDCMD + \
1298 ENABLE_ASH_BUILTIN_ECHO)
1300 #define BUILTIN_NOSPEC "0"
1301 #define BUILTIN_SPECIAL "1"
1302 #define BUILTIN_REGULAR "2"
1303 #define BUILTIN_SPEC_REG "3"
1304 #define BUILTIN_ASSIGN "4"
1305 #define BUILTIN_SPEC_ASSG "5"
1306 #define BUILTIN_REG_ASSG "6"
1307 #define BUILTIN_SPEC_REG_ASSG "7"
1309 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1310 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1311 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1313 /* make sure to keep these in proper order since it is searched via bsearch() */
1314 static const struct builtincmd builtincmd[] = {
1315 { BUILTIN_SPEC_REG ".", dotcmd },
1316 { BUILTIN_SPEC_REG ":", truecmd },
1317 #ifdef CONFIG_ASH_BUILTIN_TEST
1318 { BUILTIN_REGULAR "[", testcmd },
1319 { BUILTIN_REGULAR "[[", testcmd },
1321 #ifdef CONFIG_ASH_ALIAS
1322 { BUILTIN_REG_ASSG "alias", aliascmd },
1325 { BUILTIN_REGULAR "bg", bgcmd },
1327 { BUILTIN_SPEC_REG "break", breakcmd },
1328 { BUILTIN_REGULAR "cd", cdcmd },
1329 { BUILTIN_NOSPEC "chdir", cdcmd },
1330 #ifdef CONFIG_ASH_CMDCMD
1331 { BUILTIN_REGULAR "command", commandcmd },
1333 { BUILTIN_SPEC_REG "continue", breakcmd },
1334 #ifdef CONFIG_ASH_BUILTIN_ECHO
1335 { BUILTIN_REGULAR "echo", echocmd },
1337 { BUILTIN_SPEC_REG "eval", evalcmd },
1338 { BUILTIN_SPEC_REG "exec", execcmd },
1339 { BUILTIN_SPEC_REG "exit", exitcmd },
1340 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1341 { BUILTIN_REGULAR "false", falsecmd },
1343 { BUILTIN_REGULAR "fg", fgcmd },
1345 #ifdef CONFIG_ASH_GETOPTS
1346 { BUILTIN_REGULAR "getopts", getoptscmd },
1348 { BUILTIN_NOSPEC "hash", hashcmd },
1349 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1350 { BUILTIN_NOSPEC "help", helpcmd },
1353 { BUILTIN_REGULAR "jobs", jobscmd },
1354 { BUILTIN_REGULAR "kill", killcmd },
1356 #ifdef CONFIG_ASH_MATH_SUPPORT
1357 { BUILTIN_NOSPEC "let", letcmd },
1359 { BUILTIN_ASSIGN "local", localcmd },
1360 { BUILTIN_NOSPEC "pwd", pwdcmd },
1361 { BUILTIN_REGULAR "read", readcmd },
1362 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1363 { BUILTIN_SPEC_REG "return", returncmd },
1364 { BUILTIN_SPEC_REG "set", setcmd },
1365 { BUILTIN_SPEC_REG "shift", shiftcmd },
1366 { BUILTIN_SPEC_REG "source", dotcmd },
1367 #ifdef CONFIG_ASH_BUILTIN_TEST
1368 { BUILTIN_REGULAR "test", testcmd },
1370 { BUILTIN_SPEC_REG "times", timescmd },
1371 { BUILTIN_SPEC_REG "trap", trapcmd },
1372 { BUILTIN_REGULAR "true", truecmd },
1373 { BUILTIN_NOSPEC "type", typecmd },
1374 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1375 { BUILTIN_REGULAR "umask", umaskcmd },
1376 #ifdef CONFIG_ASH_ALIAS
1377 { BUILTIN_REGULAR "unalias", unaliascmd },
1379 { BUILTIN_SPEC_REG "unset", unsetcmd },
1380 { BUILTIN_REGULAR "wait", waitcmd },
1383 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1385 static const char *safe_applets[] = {
1386 "[", "test", "echo", "cat",
1387 "ln", "cp", "touch", "mkdir", "rm",
1388 "cut", "hexdump", "awk", "sort",
1389 "find", "xargs", "ls", "dd",
1398 const struct builtincmd *cmd;
1399 struct funcnode *func;
1404 /* action to find_command() */
1405 #define DO_ERR 0x01 /* prints errors */
1406 #define DO_ABS 0x02 /* checks absolute paths */
1407 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1408 #define DO_ALTPATH 0x08 /* using alternate path */
1409 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1411 static const char *pathopt; /* set by padvance */
1413 static void shellexec(char **, const char *, int)
1415 static char *padvance(const char **, const char *);
1416 static void find_command(char *, struct cmdentry *, int, const char *);
1417 static struct builtincmd *find_builtin(const char *);
1418 static void hashcd(void);
1419 static void changepath(const char *);
1420 static void defun(char *, union node *);
1421 static void unsetfunc(const char *);
1423 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1424 typedef int64_t arith_t;
1425 #define arith_t_type (long long)
1427 typedef long arith_t;
1428 #define arith_t_type (long)
1431 #ifdef CONFIG_ASH_MATH_SUPPORT
1432 static arith_t dash_arith(const char *);
1433 static arith_t arith(const char *expr, int *perrcode);
1436 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1437 static unsigned long rseed;
1438 static void change_random(const char *);
1439 # ifndef DYNAMIC_VAR
1440 # define DYNAMIC_VAR
1446 static void reset(void);
1455 #define VEXPORT 0x01 /* variable is exported */
1456 #define VREADONLY 0x02 /* variable cannot be modified */
1457 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1458 #define VTEXTFIXED 0x08 /* text is statically allocated */
1459 #define VSTACK 0x10 /* text is allocated on the stack */
1460 #define VUNSET 0x20 /* the variable is not set */
1461 #define VNOFUNC 0x40 /* don't call the callback function */
1462 #define VNOSET 0x80 /* do not set variable - just readonly test */
1463 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1465 # define VDYNAMIC 0x200 /* dynamic variable */
1471 struct var *next; /* next entry in hash list */
1472 int flags; /* flags are defined above */
1473 const char *text; /* name=value */
1474 void (*func)(const char *); /* function to be called when */
1475 /* the variable gets set/unset */
1479 struct localvar *next; /* next local variable in list */
1480 struct var *vp; /* the variable that was made local */
1481 int flags; /* saved flags */
1482 const char *text; /* saved text */
1486 static struct localvar *localvars;
1492 #ifdef CONFIG_ASH_GETOPTS
1493 static void getoptsreset(const char *);
1496 #ifdef CONFIG_LOCALE_SUPPORT
1498 static void change_lc_all(const char *value);
1499 static void change_lc_ctype(const char *value);
1505 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1507 static const char defifsvar[] = "IFS= \t\n";
1508 #define defifs (defifsvar + 4)
1510 static const char defifs[] = " \t\n";
1514 static struct var varinit[] = {
1516 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1518 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1521 #ifdef CONFIG_ASH_MAIL
1522 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1523 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1526 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1527 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1528 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1529 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1530 #ifdef CONFIG_ASH_GETOPTS
1531 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1533 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1534 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1536 #ifdef CONFIG_LOCALE_SUPPORT
1537 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1538 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1540 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1541 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1545 #define vifs varinit[0]
1546 #ifdef CONFIG_ASH_MAIL
1547 #define vmail (&vifs)[1]
1548 #define vmpath (&vmail)[1]
1552 #define vpath (&vmpath)[1]
1553 #define vps1 (&vpath)[1]
1554 #define vps2 (&vps1)[1]
1555 #define vps4 (&vps2)[1]
1556 #define voptind (&vps4)[1]
1557 #ifdef CONFIG_ASH_GETOPTS
1558 #define vrandom (&voptind)[1]
1560 #define vrandom (&vps4)[1]
1562 #define defpath (defpathvar + 5)
1565 * The following macros access the values of the above variables.
1566 * They have to skip over the name. They return the null string
1567 * for unset variables.
1570 #define ifsval() (vifs.text + 4)
1571 #define ifsset() ((vifs.flags & VUNSET) == 0)
1572 #define mailval() (vmail.text + 5)
1573 #define mpathval() (vmpath.text + 9)
1574 #define pathval() (vpath.text + 5)
1575 #define ps1val() (vps1.text + 4)
1576 #define ps2val() (vps2.text + 4)
1577 #define ps4val() (vps4.text + 4)
1578 #define optindval() (voptind.text + 7)
1580 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1582 static void setvar(const char *, const char *, int);
1583 static void setvareq(char *, int);
1584 static void listsetvar(struct strlist *, int);
1585 static char *lookupvar(const char *);
1586 static char *bltinlookup(const char *);
1587 static char **listvars(int, int, char ***);
1588 #define environment() listvars(VEXPORT, VUNSET, 0)
1589 static int showvars(const char *, int, int);
1590 static void poplocalvars(void);
1591 static int unsetvar(const char *);
1592 #ifdef CONFIG_ASH_GETOPTS
1593 static int setvarsafe(const char *, const char *, int);
1595 static int varcmp(const char *, const char *);
1596 static struct var **hashvar(const char *);
1599 static int varequal(const char *a, const char *b) {
1600 return !varcmp(a, b);
1604 static int loopnest; /* current loop nesting level */
1607 * The parsefile structure pointed to by the global variable parsefile
1608 * contains information about the current file being read.
1613 struct redirtab *next;
1618 static struct redirtab *redirlist;
1619 static int nullredirs;
1621 extern char **environ;
1626 static void outstr(const char *, FILE *);
1627 static void outcslow(int, FILE *);
1628 static void flushall(void);
1629 static void flusherr(void);
1630 static int out1fmt(const char *, ...)
1631 __attribute__((__format__(__printf__,1,2)));
1632 static int fmtstr(char *, size_t, const char *, ...)
1633 __attribute__((__format__(__printf__,3,4)));
1635 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1638 static void out1str(const char *p)
1643 static void out2str(const char *p)
1650 * Initialization code.
1654 * This routine initializes the builtin variables.
1657 static void initvar(void)
1664 * PS1 depends on uid
1666 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1667 vps1.text = "PS1=\\w \\$ ";
1670 vps1.text = "PS1=# ";
1673 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1675 vpp = hashvar(vp->text);
1678 } while (++vp < end);
1681 static void init(void)
1686 basepf.nextc = basepf.buf = basebuf;
1691 signal(SIGCHLD, SIG_DFL);
1699 struct stat st1, st2;
1702 for (envp = environ ; envp && *envp ; envp++) {
1703 if (strchr(*envp, '=')) {
1704 setvareq(*envp, VEXPORT|VTEXTFIXED);
1708 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1709 setvar("PPID", ppid, 0);
1711 p = lookupvar("PWD");
1713 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1714 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1720 /* PEOF (the end of file marker) */
1723 INPUT_PUSH_FILE = 1,
1724 INPUT_NOFILE_OK = 2,
1728 * The input line number. Input.c just defines this variable, and saves
1729 * and restores it when files are pushed and popped. The user of this
1730 * package must set its value.
1733 static int pgetc(void);
1734 static int pgetc2(void);
1735 static int preadbuffer(void);
1736 static void pungetc(void);
1737 static void pushstring(char *, void *);
1738 static void popstring(void);
1739 static void setinputfd(int, int);
1740 static void setinputstring(char *);
1741 static void popfile(void);
1742 static void popallfiles(void);
1743 static void closescript(void);
1749 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1752 #define FORK_NOJOB 2
1754 /* mode flags for showjob(s) */
1755 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1756 #define SHOW_PID 0x04 /* include process pid */
1757 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1761 * A job structure contains information about a job. A job is either a
1762 * single process or a set of processes contained in a pipeline. In the
1763 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1768 pid_t pid; /* process id */
1769 int status; /* last process status from wait() */
1770 char *cmd; /* text of command being run */
1774 struct procstat ps0; /* status of process */
1775 struct procstat *ps; /* status or processes when more than one */
1777 int stopstatus; /* status of a stopped job */
1780 nprocs: 16, /* number of processes */
1782 #define JOBRUNNING 0 /* at least one proc running */
1783 #define JOBSTOPPED 1 /* all procs are stopped */
1784 #define JOBDONE 2 /* all procs are completed */
1786 sigint: 1, /* job was killed by SIGINT */
1787 jobctl: 1, /* job running under job control */
1789 waited: 1, /* true if this entry has been waited for */
1790 used: 1, /* true if this entry is in used */
1791 changed: 1; /* true if status has changed */
1792 struct job *prev_job; /* previous job */
1795 static pid_t backgndpid; /* pid of last background process */
1796 static int job_warning; /* user was warned about stopped jobs */
1798 static int jobctl; /* true if doing job control */
1801 static struct job *makejob(union node *, int);
1802 static int forkshell(struct job *, union node *, int);
1803 static int waitforjob(struct job *);
1804 static int stoppedjobs(void);
1807 #define setjobctl(on) /* do nothing */
1809 static void setjobctl(int);
1810 static void showjobs(FILE *, int);
1816 /* pid of main shell */
1818 /* shell level: 0 for the main shell, 1 for its children, and so on */
1820 #define rootshell (!shlvl)
1822 static void readcmdfile(char *);
1823 static int cmdloop(int);
1829 struct stack_block *stackp;
1832 struct stackmark *marknext;
1835 /* minimum size of a block */
1836 #define MINSIZE SHELL_ALIGN(504)
1838 struct stack_block {
1839 struct stack_block *prev;
1840 char space[MINSIZE];
1843 static struct stack_block stackbase;
1844 static struct stack_block *stackp = &stackbase;
1845 static struct stackmark *markp;
1846 static char *stacknxt = stackbase.space;
1847 static size_t stacknleft = MINSIZE;
1848 static char *sstrend = stackbase.space + MINSIZE;
1849 static int herefd = -1;
1852 static pointer ckmalloc(size_t);
1853 static pointer ckrealloc(pointer, size_t);
1854 static char *savestr(const char *);
1855 static pointer stalloc(size_t);
1856 static void stunalloc(pointer);
1857 static void setstackmark(struct stackmark *);
1858 static void popstackmark(struct stackmark *);
1859 static void growstackblock(void);
1860 static void *growstackstr(void);
1861 static char *makestrspace(size_t, char *);
1862 static char *stnputs(const char *, size_t, char *);
1863 static char *stputs(const char *, char *);
1866 static char *_STPUTC(int c, char *p) {
1873 #define stackblock() ((void *)stacknxt)
1874 #define stackblocksize() stacknleft
1875 #define STARTSTACKSTR(p) ((p) = stackblock())
1876 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1877 #define CHECKSTRSPACE(n, p) \
1881 size_t m = sstrend - q; \
1883 (p) = makestrspace(l, q); \
1886 #define USTPUTC(c, p) (*p++ = (c))
1887 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1888 #define STUNPUTC(p) (--p)
1889 #define STTOPC(p) p[-1]
1890 #define STADJUST(amount, p) (p += (amount))
1892 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1893 #define ungrabstackstr(s, p) stunalloc((s))
1894 #define stackstrend() ((void *)sstrend)
1896 #define ckfree(p) free((pointer)(p))
1901 #define DOLATSTRLEN 4
1903 static char *prefix(const char *, const char *);
1904 static int number(const char *);
1905 static int is_number(const char *);
1906 static char *single_quote(const char *);
1907 static char *sstrdup(const char *);
1909 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1910 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1915 int nparam; /* # of positional parameters (without $0) */
1916 unsigned char malloc; /* if parameter list dynamically allocated */
1917 char **p; /* parameter list */
1918 #ifdef CONFIG_ASH_GETOPTS
1919 int optind; /* next parameter to be processed by getopts */
1920 int optoff; /* used by getopts */
1925 #define eflag optlist[0]
1926 #define fflag optlist[1]
1927 #define Iflag optlist[2]
1928 #define iflag optlist[3]
1929 #define mflag optlist[4]
1930 #define nflag optlist[5]
1931 #define sflag optlist[6]
1932 #define xflag optlist[7]
1933 #define vflag optlist[8]
1934 #define Cflag optlist[9]
1935 #define aflag optlist[10]
1936 #define bflag optlist[11]
1937 #define uflag optlist[12]
1938 #define viflag optlist[13]
1941 #define nolog optlist[14]
1942 #define debug optlist[15]
1945 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1946 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1952 static const char *const optletters_optnames[] = {
1973 #define optletters(n) optletters_optnames[(n)][0]
1974 #define optnames(n) (&optletters_optnames[(n)][1])
1976 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1978 static char optlist[NOPTS];
1981 static char *arg0; /* value of $0 */
1982 static struct shparam shellparam; /* $@ current positional parameters */
1983 static char **argptr; /* argument list for builtin commands */
1984 static char *optionarg; /* set by nextopt (like getopt) */
1985 static char *optptr; /* used by nextopt */
1987 static char *minusc; /* argument to -c option */
1990 static void procargs(int, char **);
1991 static void optschanged(void);
1992 static void setparam(char **);
1993 static void freeparam(volatile struct shparam *);
1994 static int shiftcmd(int, char **);
1995 static int setcmd(int, char **);
1996 static int nextopt(const char *);
2000 /* flags passed to redirect */
2001 #define REDIR_PUSH 01 /* save previous values of file descriptors */
2002 #define REDIR_SAVEFD2 03 /* set preverrout */
2005 static void redirect(union node *, int);
2006 static void popredir(int);
2007 static void clearredir(int);
2008 static int copyfd(int, int);
2009 static int redirectsafe(union node *, int);
2015 static void showtree(union node *);
2016 static void trace(const char *, ...);
2017 static void tracev(const char *, va_list);
2018 static void trargs(char **);
2019 static void trputc(int);
2020 static void trputs(const char *);
2021 static void opentrace(void);
2027 /* trap handler commands */
2028 static char *trap[NSIG];
2029 /* current value of signal */
2030 static char sigmode[NSIG - 1];
2031 /* indicates specified signal received */
2032 static char gotsig[NSIG - 1];
2034 static void clear_traps(void);
2035 static void setsignal(int);
2036 static void ignoresig(int);
2037 static void onsig(int);
2038 static int dotrap(void);
2039 static void setinteractive(int);
2040 static void exitshell(void) ATTRIBUTE_NORETURN;
2043 static int is_safe_applet(char *name)
2045 int n = sizeof(safe_applets) / sizeof(char *);
2047 for (i = 0; i < n; i++)
2048 if (strcmp(safe_applets[i], name) == 0)
2056 * This routine is called when an error or an interrupt occurs in an
2057 * interactive shell and control is returned to the main command loop.
2071 parselleft = parsenleft = 0; /* clear input buffer */
2075 /* from parser.c: */
2088 #ifdef CONFIG_ASH_ALIAS
2089 static struct alias *atab[ATABSIZE];
2091 static void setalias(const char *, const char *);
2092 static struct alias *freealias(struct alias *);
2093 static struct alias **__lookupalias(const char *);
2096 setalias(const char *name, const char *val)
2098 struct alias *ap, **app;
2100 app = __lookupalias(name);
2104 if (!(ap->flag & ALIASINUSE)) {
2107 ap->val = savestr(val);
2108 ap->flag &= ~ALIASDEAD;
2111 ap = ckmalloc(sizeof (struct alias));
2112 ap->name = savestr(name);
2113 ap->val = savestr(val);
2122 unalias(const char *name)
2126 app = __lookupalias(name);
2130 *app = freealias(*app);
2141 struct alias *ap, **app;
2145 for (i = 0; i < ATABSIZE; i++) {
2147 for (ap = *app; ap; ap = *app) {
2148 *app = freealias(*app);
2157 static struct alias *
2158 lookupalias(const char *name, int check)
2160 struct alias *ap = *__lookupalias(name);
2162 if (check && ap && (ap->flag & ALIASINUSE))
2168 * TODO - sort output
2171 aliascmd(int argc, char **argv)
2180 for (i = 0; i < ATABSIZE; i++)
2181 for (ap = atab[i]; ap; ap = ap->next) {
2186 while ((n = *++argv) != NULL) {
2187 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2188 if ((ap = *__lookupalias(n)) == NULL) {
2189 fprintf(stderr, "%s: %s not found\n", "alias", n);
2203 unaliascmd(int argc, char **argv)
2207 while ((i = nextopt("a")) != '\0') {
2213 for (i = 0; *argptr; argptr++) {
2214 if (unalias(*argptr)) {
2215 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2223 static struct alias *
2224 freealias(struct alias *ap) {
2227 if (ap->flag & ALIASINUSE) {
2228 ap->flag |= ALIASDEAD;
2240 printalias(const struct alias *ap) {
2241 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2244 static struct alias **
2245 __lookupalias(const char *name) {
2246 unsigned int hashval;
2253 ch = (unsigned char)*p;
2257 ch = (unsigned char)*++p;
2259 app = &atab[hashval % ATABSIZE];
2261 for (; *app; app = &(*app)->next) {
2262 if (equal(name, (*app)->name)) {
2269 #endif /* CONFIG_ASH_ALIAS */
2275 * The cd and pwd commands.
2278 #define CD_PHYSICAL 1
2281 static int docd(const char *, int);
2282 static int cdopt(void);
2284 static char *curdir = nullstr; /* current working directory */
2285 static char *physdir = nullstr; /* physical working directory */
2294 while ((i = nextopt("LP"))) {
2296 flags ^= CD_PHYSICAL;
2305 cdcmd(int argc, char **argv)
2317 dest = bltinlookup(homestr);
2318 else if (dest[0] == '-' && dest[1] == '\0') {
2319 dest = bltinlookup("OLDPWD");
2341 if (!(path = bltinlookup("CDPATH"))) {
2349 p = padvance(&path, dest);
2350 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2354 if (!docd(p, flags))
2359 sh_error("can't cd to %s", dest);
2362 if (flags & CD_PRINT)
2363 out1fmt(snlfmt, curdir);
2369 * Update curdir (the name of the current directory) in response to a
2373 static const char * updatepwd(const char *dir)
2380 cdcomppath = sstrdup(dir);
2383 if (curdir == nullstr)
2385 new = stputs(curdir, new);
2387 new = makestrspace(strlen(dir) + 2, new);
2388 lim = stackblock() + 1;
2392 if (new > lim && *lim == '/')
2397 if (dir[1] == '/' && dir[2] != '/') {
2403 p = strtok(cdcomppath, "/");
2407 if (p[1] == '.' && p[2] == '\0') {
2414 } else if (p[1] == '\0')
2418 new = stputs(p, new);
2426 return stackblock();
2430 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2431 * know that the current directory has changed.
2435 docd(const char *dest, int flags)
2437 const char *dir = 0;
2440 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2443 if (!(flags & CD_PHYSICAL)) {
2444 dir = updatepwd(dest);
2459 * Find out what the current directory is. If we already know the current
2460 * directory, this routine returns immediately.
2462 static char * getpwd(void)
2464 char *dir = getcwd(0, 0);
2465 return dir ? dir : nullstr;
2469 pwdcmd(int argc, char **argv)
2472 const char *dir = curdir;
2476 if (physdir == nullstr)
2480 out1fmt(snlfmt, dir);
2485 setpwd(const char *val, int setold)
2489 oldcur = dir = curdir;
2492 setvar("OLDPWD", oldcur, VEXPORT);
2495 if (physdir != nullstr) {
2496 if (physdir != oldcur)
2500 if (oldcur == val || !val) {
2507 if (oldcur != dir && oldcur != nullstr) {
2512 setvar("PWD", dir, VEXPORT);
2518 * Errors and exceptions.
2522 * Code to handle exceptions in C.
2527 static void exverror(int, const char *, va_list)
2531 * Called to raise an exception. Since C doesn't include exceptions, we
2532 * just do a longjmp to the exception handler. The type of exception is
2533 * stored in the global variable "exception".
2540 if (handler == NULL)
2546 longjmp(handler->loc, 1);
2551 * Called from trap.c when a SIGINT is received. (If the user specifies
2552 * that SIGINT is to be trapped or ignored using the trap builtin, then
2553 * this routine is not called.) Suppressint is nonzero when interrupts
2554 * are held using the INTOFF macro. (The test for iflag is just
2555 * defensive programming.)
2564 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2565 if (!(rootshell && iflag)) {
2566 signal(SIGINT, SIG_DFL);
2576 exvwarning(const char *msg, va_list ap)
2581 fprintf(errs, "%s: ", arg0);
2583 const char *fmt = (!iflag || parsefile->fd) ?
2584 "%s: %d: " : "%s: ";
2585 fprintf(errs, fmt, commandname, startlinno);
2587 vfprintf(errs, msg, ap);
2588 outcslow('\n', errs);
2592 * Exverror is called to raise the error exception. If the second argument
2593 * is not NULL then error prints an error message using printf style
2594 * formatting. It then raises the error exception.
2597 exverror(int cond, const char *msg, va_list ap)
2601 TRACE(("exverror(%d, \"", cond));
2603 TRACE(("\") pid=%d\n", getpid()));
2605 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2608 exvwarning(msg, ap);
2617 sh_error(const char *msg, ...)
2622 exverror(EXERROR, msg, ap);
2629 exerror(int cond, const char *msg, ...)
2634 exverror(cond, msg, ap);
2640 * error/warning routines for external builtins
2644 sh_warnx(const char *fmt, ...)
2649 exvwarning(fmt, ap);
2655 * Return a string describing an error. The returned string may be a
2656 * pointer to a static buffer that will be overwritten on the next call.
2657 * Action describes the operation that got the error.
2661 errmsg(int e, const char *em)
2663 if(e == ENOENT || e == ENOTDIR) {
2674 * Evaluate a command.
2677 /* flags in argument to evaltree */
2678 #define EV_EXIT 01 /* exit after evaluating tree */
2679 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2680 #define EV_BACKCMD 04 /* command executing within back quotes */
2683 static void evalloop(union node *, int);
2684 static void evalfor(union node *, int);
2685 static void evalcase(union node *, int);
2686 static void evalsubshell(union node *, int);
2687 static void expredir(union node *);
2688 static void evalpipe(union node *, int);
2689 static void evalcommand(union node *, int);
2690 static int evalbltin(const struct builtincmd *, int, char **);
2691 static int evalfun(struct funcnode *, int, char **, int);
2692 static void prehash(union node *);
2693 static int bltincmd(int, char **);
2696 static const struct builtincmd bltin = {
2702 * Called to reset things after an exception.
2710 evalcmd(int argc, char **argv)
2719 STARTSTACKSTR(concat);
2722 concat = stputs(p, concat);
2723 if ((p = *ap++) == NULL)
2725 STPUTC(' ', concat);
2727 STPUTC('\0', concat);
2728 p = grabstackstr(concat);
2730 evalstring(p, ~SKIPEVAL);
2738 * Execute a command or commands contained in a string.
2742 evalstring(char *s, int mask)
2745 struct stackmark smark;
2749 setstackmark(&smark);
2752 while ((n = parsecmd(0)) != NEOF) {
2754 popstackmark(&smark);
2769 * Evaluate a parse tree. The value is left in the global variable
2774 evaltree(union node *n, int flags)
2777 void (*evalfn)(union node *, int);
2781 TRACE(("evaltree(NULL) called\n"));
2784 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2785 getpid(), n, n->type, flags));
2789 out1fmt("Node type = %d\n", n->type);
2794 evaltree(n->nnot.com, EV_TESTED);
2795 status = !exitstatus;
2798 expredir(n->nredir.redirect);
2799 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2801 evaltree(n->nredir.n, flags & EV_TESTED);
2802 status = exitstatus;
2807 evalfn = evalcommand;
2809 if (eflag && !(flags & EV_TESTED))
2821 evalfn = evalsubshell;
2833 #error NAND + 1 != NOR
2835 #if NOR + 1 != NSEMI
2836 #error NOR + 1 != NSEMI
2838 isor = n->type - NAND;
2841 (flags | ((isor >> 1) - 1)) & EV_TESTED
2843 if (!exitstatus == isor)
2855 evaltree(n->nif.test, EV_TESTED);
2858 if (exitstatus == 0) {
2861 } else if (n->nif.elsepart) {
2862 n = n->nif.elsepart;
2867 defun(n->narg.text, n->narg.next);
2871 exitstatus = status;
2875 if ((checkexit & exitstatus))
2876 evalskip |= SKIPEVAL;
2877 else if (pendingsigs && dotrap())
2880 if (flags & EV_EXIT) {
2887 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2890 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2894 evalloop(union node *n, int flags)
2904 evaltree(n->nbinary.ch1, EV_TESTED);
2906 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2910 if (evalskip == SKIPBREAK && --skipcount <= 0)
2915 if (n->type != NWHILE)
2919 evaltree(n->nbinary.ch2, flags);
2920 status = exitstatus;
2925 exitstatus = status;
2931 evalfor(union node *n, int flags)
2933 struct arglist arglist;
2936 struct stackmark smark;
2938 setstackmark(&smark);
2939 arglist.lastp = &arglist.list;
2940 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2941 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2946 *arglist.lastp = NULL;
2951 for (sp = arglist.list ; sp ; sp = sp->next) {
2952 setvar(n->nfor.var, sp->text, 0);
2953 evaltree(n->nfor.body, flags);
2955 if (evalskip == SKIPCONT && --skipcount <= 0) {
2959 if (evalskip == SKIPBREAK && --skipcount <= 0)
2966 popstackmark(&smark);
2972 evalcase(union node *n, int flags)
2976 struct arglist arglist;
2977 struct stackmark smark;
2979 setstackmark(&smark);
2980 arglist.lastp = &arglist.list;
2981 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2983 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2984 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2985 if (casematch(patp, arglist.list->text)) {
2986 if (evalskip == 0) {
2987 evaltree(cp->nclist.body, flags);
2994 popstackmark(&smark);
3000 * Kick off a subshell to evaluate a tree.
3004 evalsubshell(union node *n, int flags)
3007 int backgnd = (n->type == NBACKGND);
3010 expredir(n->nredir.redirect);
3011 if (!backgnd && flags & EV_EXIT && !trap[0])
3015 if (forkshell(jp, n, backgnd) == 0) {
3019 flags &=~ EV_TESTED;
3021 redirect(n->nredir.redirect, 0);
3022 evaltreenr(n->nredir.n, flags);
3027 status = waitforjob(jp);
3028 exitstatus = status;
3035 * Compute the names of the files in a redirection list.
3039 expredir(union node *n)
3043 for (redir = n ; redir ; redir = redir->nfile.next) {
3045 fn.lastp = &fn.list;
3046 switch (redir->type) {
3052 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3053 redir->nfile.expfname = fn.list->text;
3057 if (redir->ndup.vname) {
3058 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3059 fixredir(redir, fn.list->text, 1);
3069 * Evaluate a pipeline. All the processes in the pipeline are children
3070 * of the process creating the pipeline. (This differs from some versions
3071 * of the shell, which make the last process in a pipeline the parent
3076 evalpipe(union node *n, int flags)
3079 struct nodelist *lp;
3084 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3086 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3090 jp = makejob(n, pipelen);
3092 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3096 if (pipe(pip) < 0) {
3098 sh_error("Pipe call failed");
3101 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3114 evaltreenr(lp->n, flags);
3122 if (n->npipe.backgnd == 0) {
3123 exitstatus = waitforjob(jp);
3124 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3132 * Execute a command inside back quotes. If it's a builtin command, we
3133 * want to save its output in a block obtained from malloc. Otherwise
3134 * we fork off a subprocess and get the output of the command via a pipe.
3135 * Should be called with interrupts off.
3139 evalbackcmd(union node *n, struct backcmd *result)
3151 saveherefd = herefd;
3159 sh_error("Pipe call failed");
3161 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3170 evaltreenr(n, EV_EXIT);
3174 result->fd = pip[0];
3177 herefd = saveherefd;
3179 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3180 result->fd, result->buf, result->nleft, result->jp));
3183 #ifdef CONFIG_ASH_CMDCMD
3184 static char ** parse_command_args(char **argv, const char **path)
3196 if (c == '-' && !*cp) {
3206 /* run 'typecmd' for other options */
3209 } while ((c = *cp++));
3215 static int isassignment(const char *p)
3217 const char *q = endofname(p);
3223 #ifdef CONFIG_ASH_EXPAND_PRMT
3224 static const char *expandstr(const char *ps);
3226 #define expandstr(s) s
3230 * Execute a simple command.
3234 evalcommand(union node *cmd, int flags)
3236 struct stackmark smark;
3238 struct arglist arglist;
3239 struct arglist varlist;
3242 const struct strlist *sp;
3243 struct cmdentry cmdentry;
3251 struct builtincmd *bcmd;
3252 int pseudovarflag = 0;
3254 /* First expand the arguments. */
3255 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3256 setstackmark(&smark);
3257 back_exitstatus = 0;
3259 cmdentry.cmdtype = CMDBUILTIN;
3260 cmdentry.u.cmd = &bltin;
3261 varlist.lastp = &varlist.list;
3262 *varlist.lastp = NULL;
3263 arglist.lastp = &arglist.list;
3264 *arglist.lastp = NULL;
3269 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3270 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3273 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3274 struct strlist **spp;
3276 spp = arglist.lastp;
3277 if (pseudovarflag && isassignment(argp->narg.text))
3278 expandarg(argp, &arglist, EXP_VARTILDE);
3280 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3282 for (sp = *spp; sp; sp = sp->next)
3286 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3287 for (sp = arglist.list ; sp ; sp = sp->next) {
3288 TRACE(("evalcommand arg: %s\n", sp->text));
3289 *nargv++ = sp->text;
3294 if (iflag && funcnest == 0 && argc > 0)
3295 lastarg = nargv[-1];
3298 expredir(cmd->ncmd.redirect);
3299 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3302 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3303 struct strlist **spp;
3306 spp = varlist.lastp;
3307 expandarg(argp, &varlist, EXP_VARTILDE);
3310 * Modify the command lookup path, if a PATH= assignment
3314 if (varequal(p, path))
3318 /* Print the command if xflag is set. */
3321 const char *p = " %s";
3324 dprintf(preverrout_fd, p, expandstr(ps4val()));
3327 for(n = 0; n < 2; n++) {
3329 dprintf(preverrout_fd, p, sp->text);
3337 full_write(preverrout_fd, "\n", 1);
3343 /* Now locate the command. */
3345 const char *oldpath;
3346 int cmd_flag = DO_ERR;
3351 find_command(argv[0], &cmdentry, cmd_flag, path);
3352 if (cmdentry.cmdtype == CMDUNKNOWN) {
3358 /* implement bltin and command here */
3359 if (cmdentry.cmdtype != CMDBUILTIN)
3362 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3363 if (cmdentry.u.cmd == EXECCMD)
3365 #ifdef CONFIG_ASH_CMDCMD
3366 if (cmdentry.u.cmd == COMMANDCMD) {
3369 nargv = parse_command_args(argv, &path);
3372 argc -= nargv - argv;
3374 cmd_flag |= DO_NOFUNC;
3382 /* We have a redirection error. */
3386 exitstatus = status;
3390 /* Execute the command. */
3391 switch (cmdentry.cmdtype) {
3393 /* Fork off a child process if necessary. */
3394 if (!(flags & EV_EXIT) || trap[0]) {
3396 jp = makejob(cmd, 1);
3397 if (forkshell(jp, cmd, FORK_FG) != 0) {
3398 exitstatus = waitforjob(jp);
3404 listsetvar(varlist.list, VEXPORT|VSTACK);
3405 shellexec(argv, path, cmdentry.u.index);
3409 cmdenviron = varlist.list;
3411 struct strlist *list = cmdenviron;
3413 if (spclbltin > 0 || argc == 0) {
3415 if (cmd_is_exec && argc > 1)
3418 listsetvar(list, i);
3420 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3435 exit_status = j + 128;
3436 exitstatus = exit_status;
3438 if (i == EXINT || spclbltin > 0) {
3440 longjmp(handler->loc, 1);
3447 listsetvar(varlist.list, 0);
3448 if (evalfun(cmdentry.u.func, argc, argv, flags))
3454 popredir(cmd_is_exec);
3456 /* dsl: I think this is intended to be used to support
3457 * '_' in 'vi' command mode during line editing...
3458 * However I implemented that within libedit itself.
3460 setvar("_", lastarg, 0);
3461 popstackmark(&smark);
3465 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3466 char *volatile savecmdname;
3467 struct jmploc *volatile savehandler;
3468 struct jmploc jmploc;
3471 savecmdname = commandname;
3472 if ((i = setjmp(jmploc.loc)))
3474 savehandler = handler;
3476 commandname = argv[0];
3478 optptr = NULL; /* initialize nextopt */
3479 exitstatus = (*cmd->builtin)(argc, argv);
3482 exitstatus |= ferror(stdout);
3484 commandname = savecmdname;
3486 handler = savehandler;
3492 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3494 volatile struct shparam saveparam;
3495 struct localvar *volatile savelocalvars;
3496 struct jmploc *volatile savehandler;
3497 struct jmploc jmploc;
3500 saveparam = shellparam;
3501 savelocalvars = localvars;
3502 if ((e = setjmp(jmploc.loc))) {
3506 savehandler = handler;
3509 shellparam.malloc = 0;
3513 shellparam.nparam = argc - 1;
3514 shellparam.p = argv + 1;
3515 #ifdef CONFIG_ASH_GETOPTS
3516 shellparam.optind = 1;
3517 shellparam.optoff = -1;
3519 evaltree(&func->n, flags & EV_TESTED);
3525 localvars = savelocalvars;
3526 freeparam(&shellparam);
3527 shellparam = saveparam;
3528 handler = savehandler;
3530 evalskip &= ~SKIPFUNC;
3535 static int goodname(const char *p)
3537 return !*endofname(p);
3541 * Search for a command. This is called before we fork so that the
3542 * location of the command will be available in the parent as well as
3543 * the child. The check for "goodname" is an overly conservative
3544 * check that the name will not be subject to expansion.
3548 prehash(union node *n)
3550 struct cmdentry entry;
3552 if (n->type == NCMD && n->ncmd.args)
3553 if (goodname(n->ncmd.args->narg.text))
3554 find_command(n->ncmd.args->narg.text, &entry, 0,
3561 * Builtin commands. Builtin commands whose functions are closely
3562 * tied to evaluation are implemented here.
3570 bltincmd(int argc, char **argv)
3573 * Preserve exitstatus of a previous possible redirection
3576 return back_exitstatus;
3581 * Handle break and continue commands. Break, continue, and return are
3582 * all handled by setting the evalskip flag. The evaluation routines
3583 * above all check this flag, and if it is set they start skipping
3584 * commands rather than executing them. The variable skipcount is
3585 * the number of loops to break/continue, or the number of function
3586 * levels to return. (The latter is always 1.) It should probably
3587 * be an error to break out of more loops than exist, but it isn't
3588 * in the standard shell so we don't make it one here.
3592 breakcmd(int argc, char **argv)
3594 int n = argc > 1 ? number(argv[1]) : 1;
3597 sh_error(illnum, argv[1]);
3601 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3609 * The return command.
3613 returncmd(int argc, char **argv)
3616 * If called outside a function, do what ksh does;
3617 * skip the rest of the file.
3619 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3620 return argv[1] ? number(argv[1]) : exitstatus;
3625 falsecmd(int argc, char **argv)
3632 truecmd(int argc, char **argv)
3639 execcmd(int argc, char **argv)
3642 iflag = 0; /* exit on error */
3645 shellexec(argv + 1, pathval(), 0);
3654 * When commands are first encountered, they are entered in a hash table.
3655 * This ensures that a full path search will not have to be done for them
3656 * on each invocation.
3658 * We should investigate converting to a linear search, even though that
3659 * would make the command name "hash" a misnomer.
3662 #define CMDTABLESIZE 31 /* should be prime */
3663 #define ARB 1 /* actual size determined at run time */
3668 struct tblentry *next; /* next entry in hash chain */
3669 union param param; /* definition of builtin function */
3670 short cmdtype; /* index identifying command */
3671 char rehash; /* if set, cd done since entry created */
3672 char cmdname[ARB]; /* name of command */
3676 static struct tblentry *cmdtable[CMDTABLESIZE];
3677 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3680 static void tryexec(char *, char **, char **);
3681 static void clearcmdentry(int);
3682 static struct tblentry *cmdlookup(const char *, int);
3683 static void delete_cmd_entry(void);
3687 * Exec a program. Never returns. If you change this routine, you may
3688 * have to change the find_command routine as well.
3692 shellexec(char **argv, const char *path, int idx)
3700 envp = environment();
3701 if (strchr(argv[0], '/') != NULL
3702 || is_safe_applet(argv[0])
3703 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3704 || find_applet_by_name(argv[0])
3707 tryexec(argv[0], argv, envp);
3711 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3712 if (--idx < 0 && pathopt == NULL) {
3713 tryexec(cmdname, argv, envp);
3714 if (errno != ENOENT && errno != ENOTDIR)
3721 /* Map to POSIX errors */
3733 exitstatus = exerrno;
3734 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3735 argv[0], e, suppressint ));
3736 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3742 tryexec(char *cmd, char **argv, char **envp)
3745 struct BB_applet *a;
3749 if(strchr(cmd, '/') == NULL && is_safe_applet(cmd) && (a = find_applet_by_name(cmd)) != NULL) {
3751 while (*c != NULL) {
3755 exit(a->main(argc, argv));
3757 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3758 if(find_applet_by_name(cmd) != NULL) {
3759 /* re-exec ourselves with the new arguments */
3760 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3761 /* If they called chroot or otherwise made the binary no longer
3762 * executable, fall through */
3769 execve(cmd, argv, envp);
3770 } while (errno == EINTR);
3772 execve(cmd, argv, envp);
3776 } else if (errno == ENOEXEC) {
3780 for (ap = argv; *ap; ap++)
3782 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3784 *ap = cmd = (char *)DEFAULT_SHELL;
3787 while ((*ap++ = *argv++))
3797 * Do a path search. The variable path (passed by reference) should be
3798 * set to the start of the path before the first call; padvance will update
3799 * this value as it proceeds. Successive calls to padvance will return
3800 * the possible path expansions in sequence. If an option (indicated by
3801 * a percent sign) appears in the path entry then the global variable
3802 * pathopt will be set to point to it; otherwise pathopt will be set to
3807 padvance(const char **path, const char *name)
3817 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3818 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3819 while (stackblocksize() < len)
3823 memcpy(q, start, p - start);
3831 while (*p && *p != ':') p++;
3837 return stalloc(len);
3841 /*** Command hashing code ***/
3844 printentry(struct tblentry *cmdp)
3850 idx = cmdp->param.index;
3853 name = padvance(&path, cmdp->cmdname);
3855 } while (--idx >= 0);
3856 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3861 hashcmd(int argc, char **argv)
3863 struct tblentry **pp;
3864 struct tblentry *cmdp;
3866 struct cmdentry entry;
3869 while ((c = nextopt("r")) != '\0') {
3873 if (*argptr == NULL) {
3874 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3875 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3876 if (cmdp->cmdtype == CMDNORMAL)
3883 while ((name = *argptr) != NULL) {
3884 if ((cmdp = cmdlookup(name, 0)) != NULL
3885 && (cmdp->cmdtype == CMDNORMAL
3886 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3888 find_command(name, &entry, DO_ERR, pathval());
3889 if (entry.cmdtype == CMDUNKNOWN)
3898 * Resolve a command name. If you change this routine, you may have to
3899 * change the shellexec routine as well.
3903 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3905 struct tblentry *cmdp;
3912 struct builtincmd *bcmd;
3914 /* If name contains a slash, don't use PATH or hash table */
3915 if (strchr(name, '/') != NULL) {
3916 entry->u.index = -1;
3918 while (stat(name, &statb) < 0) {
3923 entry->cmdtype = CMDUNKNOWN;
3927 entry->cmdtype = CMDNORMAL;
3931 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3932 if (find_applet_by_name(name)) {
3933 entry->cmdtype = CMDNORMAL;
3934 entry->u.index = -1;
3939 if (is_safe_applet(name)) {
3940 entry->cmdtype = CMDNORMAL;
3941 entry->u.index = -1;
3945 updatetbl = (path == pathval());
3948 if (strstr(path, "%builtin") != NULL)
3952 /* If name is in the table, check answer will be ok */
3953 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3956 switch (cmdp->cmdtype) {
3974 } else if (cmdp->rehash == 0)
3975 /* if not invalidated by cd, we're done */
3979 /* If %builtin not in path, check for builtin next */
3980 bcmd = find_builtin(name);
3981 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3982 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3984 goto builtin_success;
3986 /* We have to search path. */
3987 prev = -1; /* where to start */
3988 if (cmdp && cmdp->rehash) { /* doing a rehash */
3989 if (cmdp->cmdtype == CMDBUILTIN)
3992 prev = cmdp->param.index;
3998 while ((fullname = padvance(&path, name)) != NULL) {
3999 stunalloc(fullname);
4002 if (prefix(pathopt, "builtin")) {
4004 goto builtin_success;
4006 } else if (!(act & DO_NOFUNC) &&
4007 prefix(pathopt, "func")) {
4010 /* ignore unimplemented options */
4014 /* if rehash, don't redo absolute path names */
4015 if (fullname[0] == '/' && idx <= prev) {
4018 TRACE(("searchexec \"%s\": no change\n", name));
4021 while (stat(fullname, &statb) < 0) {
4026 if (errno != ENOENT && errno != ENOTDIR)
4030 e = EACCES; /* if we fail, this will be the error */
4031 if (!S_ISREG(statb.st_mode))
4033 if (pathopt) { /* this is a %func directory */
4034 stalloc(strlen(fullname) + 1);
4035 readcmdfile(fullname);
4036 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4037 cmdp->cmdtype != CMDFUNCTION)
4038 sh_error("%s not defined in %s", name, fullname);
4039 stunalloc(fullname);
4042 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4044 entry->cmdtype = CMDNORMAL;
4045 entry->u.index = idx;
4049 cmdp = cmdlookup(name, 1);
4050 cmdp->cmdtype = CMDNORMAL;
4051 cmdp->param.index = idx;
4056 /* We failed. If there was an entry for this command, delete it */
4057 if (cmdp && updatetbl)
4060 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4061 entry->cmdtype = CMDUNKNOWN;
4066 entry->cmdtype = CMDBUILTIN;
4067 entry->u.cmd = bcmd;
4071 cmdp = cmdlookup(name, 1);
4072 cmdp->cmdtype = CMDBUILTIN;
4073 cmdp->param.cmd = bcmd;
4077 entry->cmdtype = cmdp->cmdtype;
4078 entry->u = cmdp->param;
4083 * Wrapper around strcmp for qsort/bsearch/...
4085 static int pstrcmp(const void *a, const void *b)
4087 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4091 * Search the table of builtin commands.
4094 static struct builtincmd *
4095 find_builtin(const char *name)
4097 struct builtincmd *bp;
4100 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4109 * Called when a cd is done. Marks all commands so the next time they
4110 * are executed they will be rehashed.
4116 struct tblentry **pp;
4117 struct tblentry *cmdp;
4119 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4120 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4121 if (cmdp->cmdtype == CMDNORMAL || (
4122 cmdp->cmdtype == CMDBUILTIN &&
4123 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4134 * Fix command hash table when PATH changed.
4135 * Called before PATH is changed. The argument is the new value of PATH;
4136 * pathval() still returns the old value at this point.
4137 * Called with interrupts off.
4141 changepath(const char *newval)
4143 const char *old, *new;
4150 firstchange = 9999; /* assume no change */
4156 if ((*old == '\0' && *new == ':')
4157 || (*old == ':' && *new == '\0'))
4159 old = new; /* ignore subsequent differences */
4163 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4170 if (builtinloc < 0 && idx_bltin >= 0)
4171 builtinloc = idx_bltin; /* zap builtins */
4172 if (builtinloc >= 0 && idx_bltin < 0)
4174 clearcmdentry(firstchange);
4175 builtinloc = idx_bltin;
4180 * Clear out command entries. The argument specifies the first entry in
4181 * PATH which has changed.
4185 clearcmdentry(int firstchange)
4187 struct tblentry **tblp;
4188 struct tblentry **pp;
4189 struct tblentry *cmdp;
4192 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4194 while ((cmdp = *pp) != NULL) {
4195 if ((cmdp->cmdtype == CMDNORMAL &&
4196 cmdp->param.index >= firstchange)
4197 || (cmdp->cmdtype == CMDBUILTIN &&
4198 builtinloc >= firstchange)) {
4212 * Locate a command in the command hash table. If "add" is nonzero,
4213 * add the command to the table if it is not already present. The
4214 * variable "lastcmdentry" is set to point to the address of the link
4215 * pointing to the entry, so that delete_cmd_entry can delete the
4218 * Interrupts must be off if called with add != 0.
4221 static struct tblentry **lastcmdentry;
4224 static struct tblentry *
4225 cmdlookup(const char *name, int add)
4227 unsigned int hashval;
4229 struct tblentry *cmdp;
4230 struct tblentry **pp;
4233 hashval = (unsigned char)*p << 4;
4235 hashval += (unsigned char)*p++;
4237 pp = &cmdtable[hashval % CMDTABLESIZE];
4238 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4239 if (equal(cmdp->cmdname, name))
4243 if (add && cmdp == NULL) {
4244 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4245 + strlen(name) + 1);
4247 cmdp->cmdtype = CMDUNKNOWN;
4248 strcpy(cmdp->cmdname, name);
4255 * Delete the command entry returned on the last lookup.
4259 delete_cmd_entry(void)
4261 struct tblentry *cmdp;
4264 cmdp = *lastcmdentry;
4265 *lastcmdentry = cmdp->next;
4266 if (cmdp->cmdtype == CMDFUNCTION)
4267 freefunc(cmdp->param.func);
4274 * Add a new command entry, replacing any existing command entry for
4275 * the same name - except special builtins.
4278 static void addcmdentry(char *name, struct cmdentry *entry)
4280 struct tblentry *cmdp;
4282 cmdp = cmdlookup(name, 1);
4283 if (cmdp->cmdtype == CMDFUNCTION) {
4284 freefunc(cmdp->param.func);
4286 cmdp->cmdtype = entry->cmdtype;
4287 cmdp->param = entry->u;
4292 * Make a copy of a parse tree.
4295 static struct funcnode * copyfunc(union node *n)
4300 funcblocksize = offsetof(struct funcnode, n);
4303 blocksize = funcblocksize;
4304 f = ckmalloc(blocksize + funcstringsize);
4305 funcblock = (char *) f + offsetof(struct funcnode, n);
4306 funcstring = (char *) f + blocksize;
4313 * Define a shell function.
4317 defun(char *name, union node *func)
4319 struct cmdentry entry;
4322 entry.cmdtype = CMDFUNCTION;
4323 entry.u.func = copyfunc(func);
4324 addcmdentry(name, &entry);
4330 * Delete a function if it exists.
4334 unsetfunc(const char *name)
4336 struct tblentry *cmdp;
4338 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4339 cmdp->cmdtype == CMDFUNCTION)
4344 * Locate and print what a word is...
4348 #ifdef CONFIG_ASH_CMDCMD
4350 describe_command(char *command, int describe_command_verbose)
4352 #define describe_command_verbose 1
4354 describe_command(char *command)
4357 struct cmdentry entry;
4358 struct tblentry *cmdp;
4359 #ifdef CONFIG_ASH_ALIAS
4360 const struct alias *ap;
4362 const char *path = pathval();
4364 if (describe_command_verbose) {
4368 /* First look at the keywords */
4369 if (findkwd(command)) {
4370 out1str(describe_command_verbose ? " is a shell keyword" : command);
4374 #ifdef CONFIG_ASH_ALIAS
4375 /* Then look at the aliases */
4376 if ((ap = lookupalias(command, 0)) != NULL) {
4377 if (describe_command_verbose) {
4378 out1fmt(" is an alias for %s", ap->val);
4387 /* Then check if it is a tracked alias */
4388 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4389 entry.cmdtype = cmdp->cmdtype;
4390 entry.u = cmdp->param;
4392 /* Finally use brute force */
4393 find_command(command, &entry, DO_ABS, path);
4396 switch (entry.cmdtype) {
4398 int j = entry.u.index;
4404 p = padvance(&path, command);
4408 if (describe_command_verbose) {
4410 (cmdp ? " a tracked alias for" : nullstr), p
4419 if (describe_command_verbose) {
4420 out1str(" is a shell function");
4427 if (describe_command_verbose) {
4428 out1fmt(" is a %sshell builtin",
4429 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4430 "special " : nullstr
4438 if (describe_command_verbose) {
4439 out1str(": not found\n");
4445 outstr("\n", stdout);
4450 typecmd(int argc, char **argv)
4455 for (i = 1; i < argc; i++) {
4456 #ifdef CONFIG_ASH_CMDCMD
4457 err |= describe_command(argv[i], 1);
4459 err |= describe_command(argv[i]);
4465 #ifdef CONFIG_ASH_CMDCMD
4467 commandcmd(int argc, char **argv)
4475 while ((c = nextopt("pvV")) != '\0')
4477 verify |= VERIFY_VERBOSE;
4479 verify |= VERIFY_BRIEF;
4485 return describe_command(*argptr, verify - VERIFY_BRIEF);
4494 * Routines to expand arguments to commands. We have to deal with
4495 * backquotes, shell variables, and file metacharacters.
4501 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4502 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4503 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4504 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4505 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4508 * Structure specifying which parts of the string should be searched
4509 * for IFS characters.
4513 struct ifsregion *next; /* next region in list */
4514 int begoff; /* offset of start of region */
4515 int endoff; /* offset of end of region */
4516 int nulonly; /* search for nul bytes only */
4519 /* output of current string */
4520 static char *expdest;
4521 /* list of back quote expressions */
4522 static struct nodelist *argbackq;
4523 /* first struct in list of ifs regions */
4524 static struct ifsregion ifsfirst;
4525 /* last struct in list */
4526 static struct ifsregion *ifslastp;
4527 /* holds expanded arg list */
4528 static struct arglist exparg;
4530 static void argstr(char *, int);
4531 static char *exptilde(char *, char *, int);
4532 static void expbackq(union node *, int, int);
4533 static const char *subevalvar(char *, char *, int, int, int, int, int);
4534 static char *evalvar(char *, int);
4535 static void strtodest(const char *, int, int);
4536 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4537 static ssize_t varvalue(char *, int, int);
4538 static void recordregion(int, int, int);
4539 static void removerecordregions(int);
4540 static void ifsbreakup(char *, struct arglist *);
4541 static void ifsfree(void);
4542 static void expandmeta(struct strlist *, int);
4543 static int patmatch(char *, const char *);
4545 static int cvtnum(arith_t);
4546 static size_t esclen(const char *, const char *);
4547 static char *scanleft(char *, char *, char *, char *, int, int);
4548 static char *scanright(char *, char *, char *, char *, int, int);
4549 static void varunset(const char *, const char *, const char *, int)
4553 #define pmatch(a, b) !fnmatch((a), (b), 0)
4555 * Prepare a pattern for a expmeta (internal glob(3)) call.
4557 * Returns an stalloced string.
4560 static char * preglob(const char *pattern, int quoted, int flag) {
4561 flag |= RMESCAPE_GLOB;
4563 flag |= RMESCAPE_QUOTED;
4565 return _rmescapes((char *)pattern, flag);
4570 esclen(const char *start, const char *p) {
4573 while (p > start && *--p == CTLESC) {
4581 * Expand shell variables and backquotes inside a here document.
4584 static void expandhere(union node *arg, int fd)
4587 expandarg(arg, (struct arglist *)NULL, 0);
4588 full_write(fd, stackblock(), expdest - (char *)stackblock());
4593 * Perform variable substitution and command substitution on an argument,
4594 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4595 * perform splitting and file name expansion. When arglist is NULL, perform
4596 * here document expansion.
4600 expandarg(union node *arg, struct arglist *arglist, int flag)
4605 argbackq = arg->narg.backquote;
4606 STARTSTACKSTR(expdest);
4607 ifsfirst.next = NULL;
4609 argstr(arg->narg.text, flag);
4610 p = _STPUTC('\0', expdest);
4612 if (arglist == NULL) {
4613 return; /* here document expanded */
4615 p = grabstackstr(p);
4616 exparg.lastp = &exparg.list;
4620 if (flag & EXP_FULL) {
4621 ifsbreakup(p, &exparg);
4622 *exparg.lastp = NULL;
4623 exparg.lastp = &exparg.list;
4624 expandmeta(exparg.list, flag);
4626 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4628 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4631 exparg.lastp = &sp->next;
4635 *exparg.lastp = NULL;
4637 *arglist->lastp = exparg.list;
4638 arglist->lastp = exparg.lastp;
4644 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4645 * characters to allow for further processing. Otherwise treat
4646 * $@ like $* since no splitting will be performed.
4650 argstr(char *p, int flag)
4652 static const char spclchars[] = {
4660 CTLBACKQ | CTLQUOTE,
4661 #ifdef CONFIG_ASH_MATH_SUPPORT
4666 const char *reject = spclchars;
4668 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4669 int breakall = flag & EXP_WORD;
4674 if (!(flag & EXP_VARTILDE)) {
4676 } else if (flag & EXP_VARTILDE2) {
4681 if (flag & EXP_TILDE) {
4687 if (*q == CTLESC && (flag & EXP_QWORD))
4690 p = exptilde(p, q, flag);
4693 startloc = expdest - (char *)stackblock();
4695 length += strcspn(p + length, reject);
4697 if (c && (!(c & 0x80)
4698 #ifdef CONFIG_ASH_MATH_SUPPORT
4702 /* c == '=' || c == ':' || c == CTLENDARI */
4707 expdest = stnputs(p, length, expdest);
4708 newloc = expdest - (char *)stackblock();
4709 if (breakall && !inquotes && newloc > startloc) {
4710 recordregion(startloc, newloc, 0);
4721 if (flag & EXP_VARTILDE2) {
4725 flag |= EXP_VARTILDE2;
4730 * sort of a hack - expand tildes in variable
4731 * assignments (after the first '=' and after ':'s).
4740 case CTLENDVAR: /* ??? */
4743 /* "$@" syntax adherence hack */
4746 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4747 (p[4] == CTLQUOTEMARK || (
4748 p[4] == CTLENDVAR &&
4749 p[5] == CTLQUOTEMARK
4752 p = evalvar(p + 1, flag) + 1;
4755 inquotes = !inquotes;
4768 p = evalvar(p, flag);
4772 case CTLBACKQ|CTLQUOTE:
4773 expbackq(argbackq->n, c, quotes);
4774 argbackq = argbackq->next;
4776 #ifdef CONFIG_ASH_MATH_SUPPORT
4789 exptilde(char *startp, char *p, int flag)
4795 int quotes = flag & (EXP_FULL | EXP_CASE);
4800 while ((c = *++p) != '\0') {
4807 if (flag & EXP_VARTILDE)
4817 if (*name == '\0') {
4818 home = lookupvar(homestr);
4820 if ((pw = getpwnam(name)) == NULL)
4824 if (!home || !*home)
4827 startloc = expdest - (char *)stackblock();
4828 strtodest(home, SQSYNTAX, quotes);
4829 recordregion(startloc, expdest - (char *)stackblock(), 0);
4838 removerecordregions(int endoff)
4840 if (ifslastp == NULL)
4843 if (ifsfirst.endoff > endoff) {
4844 while (ifsfirst.next != NULL) {
4845 struct ifsregion *ifsp;
4847 ifsp = ifsfirst.next->next;
4848 ckfree(ifsfirst.next);
4849 ifsfirst.next = ifsp;
4852 if (ifsfirst.begoff > endoff)
4855 ifslastp = &ifsfirst;
4856 ifsfirst.endoff = endoff;
4861 ifslastp = &ifsfirst;
4862 while (ifslastp->next && ifslastp->next->begoff < endoff)
4863 ifslastp=ifslastp->next;
4864 while (ifslastp->next != NULL) {
4865 struct ifsregion *ifsp;
4867 ifsp = ifslastp->next->next;
4868 ckfree(ifslastp->next);
4869 ifslastp->next = ifsp;
4872 if (ifslastp->endoff > endoff)
4873 ifslastp->endoff = endoff;
4877 #ifdef CONFIG_ASH_MATH_SUPPORT
4879 * Expand arithmetic expression. Backup to start of expression,
4880 * evaluate, place result in (backed up) result, adjust string position.
4893 * This routine is slightly over-complicated for
4894 * efficiency. Next we scan backwards looking for the
4895 * start of arithmetic.
4897 start = stackblock();
4904 while (*p != CTLARI) {
4908 sh_error("missing CTLARI (shouldn't happen)");
4913 esc = esclen(start, p);
4923 removerecordregions(begoff);
4932 len = cvtnum(dash_arith(p + 2));
4935 recordregion(begoff, begoff + len, 0);
4940 * Expand stuff in backwards quotes.
4944 expbackq(union node *cmd, int quoted, int quotes)
4952 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4953 struct stackmark smark;
4956 setstackmark(&smark);
4958 startloc = dest - (char *)stackblock();
4960 evalbackcmd(cmd, (struct backcmd *) &in);
4961 popstackmark(&smark);
4968 memtodest(p, i, syntax, quotes);
4972 i = safe_read(in.fd, buf, sizeof buf);
4973 TRACE(("expbackq: read returns %d\n", i));
4983 back_exitstatus = waitforjob(in.jp);
4987 /* Eat all trailing newlines */
4989 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4994 recordregion(startloc, dest - (char *)stackblock(), 0);
4995 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4996 (dest - (char *)stackblock()) - startloc,
4997 (dest - (char *)stackblock()) - startloc,
4998 stackblock() + startloc));
5003 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5014 const char *s = loc2;
5020 match = pmatch(str, s);
5024 if (quotes && *loc == CTLESC)
5034 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5041 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5044 const char *s = loc2;
5049 match = pmatch(str, s);
5056 esc = esclen(startp, loc);
5068 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5072 int saveherefd = herefd;
5073 struct nodelist *saveargbackq = argbackq;
5075 char *rmesc, *rmescend;
5077 char *(*scan)(char *, char *, char *, char *, int , int);
5080 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5081 STPUTC('\0', expdest);
5082 herefd = saveherefd;
5083 argbackq = saveargbackq;
5084 startp = stackblock() + startloc;
5088 setvar(str, startp, 0);
5089 amount = startp - expdest;
5090 STADJUST(amount, expdest);
5094 varunset(p, str, startp, varflags);
5098 subtype -= VSTRIMRIGHT;
5100 if (subtype < 0 || subtype > 3)
5105 rmescend = stackblock() + strloc;
5107 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5108 if (rmesc != startp) {
5110 startp = stackblock() + startloc;
5114 str = stackblock() + strloc;
5115 preglob(str, varflags & VSQUOTE, 0);
5117 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5118 zero = subtype >> 1;
5119 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5120 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5122 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5125 memmove(startp, loc, str - loc);
5126 loc = startp + (str - loc) - 1;
5129 amount = loc - expdest;
5130 STADJUST(amount, expdest);
5137 * Expand a variable, and return a pointer to the next character in the
5141 evalvar(char *p, int flag)
5154 quotes = flag & (EXP_FULL | EXP_CASE);
5156 subtype = varflags & VSTYPE;
5157 quoted = varflags & VSQUOTE;
5159 easy = (!quoted || (*var == '@' && shellparam.nparam));
5160 startloc = expdest - (char *)stackblock();
5161 p = strchr(p, '=') + 1;
5164 varlen = varvalue(var, varflags, flag);
5165 if (varflags & VSNUL)
5168 if (subtype == VSPLUS) {
5169 varlen = -1 - varlen;
5173 if (subtype == VSMINUS) {
5177 p, flag | EXP_TILDE |
5178 (quoted ? EXP_QWORD : EXP_WORD)
5187 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5189 if (subevalvar(p, var, 0, subtype, startloc,
5193 * Remove any recorded regions beyond
5196 removerecordregions(startloc);
5206 if (varlen < 0 && uflag)
5207 varunset(p, var, 0, 0);
5209 if (subtype == VSLENGTH) {
5210 cvtnum(varlen > 0 ? varlen : 0);
5214 if (subtype == VSNORMAL) {
5218 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5227 case VSTRIMRIGHTMAX:
5236 * Terminate the string and start recording the pattern
5239 STPUTC('\0', expdest);
5240 patloc = expdest - (char *)stackblock();
5241 if (subevalvar(p, NULL, patloc, subtype,
5242 startloc, varflags, quotes) == 0) {
5243 int amount = expdest - (
5244 (char *)stackblock() + patloc - 1
5246 STADJUST(-amount, expdest);
5248 /* Remove any recorded regions beyond start of variable */
5249 removerecordregions(startloc);
5254 if (subtype != VSNORMAL) { /* skip to end of alternative */
5257 if ((c = *p++) == CTLESC)
5259 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5261 argbackq = argbackq->next;
5262 } else if (c == CTLVAR) {
5263 if ((*p++ & VSTYPE) != VSNORMAL)
5265 } else if (c == CTLENDVAR) {
5276 * Put a string on the stack.
5280 memtodest(const char *p, size_t len, int syntax, int quotes) {
5283 q = makestrspace(len * 2, q);
5286 int c = SC2INT(*p++);
5289 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5299 strtodest(const char *p, int syntax, int quotes)
5301 memtodest(p, strlen(p), syntax, quotes);
5306 * Add the value of a specialized variable to the stack string.
5310 varvalue(char *name, int varflags, int flags)
5320 int quoted = varflags & VSQUOTE;
5321 int subtype = varflags & VSTYPE;
5322 int quotes = flags & (EXP_FULL | EXP_CASE);
5324 if (quoted && (flags & EXP_FULL))
5325 sep = 1 << CHAR_BIT;
5327 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5336 num = shellparam.nparam;
5346 p = makestrspace(NOPTS, expdest);
5347 for (i = NOPTS - 1; i >= 0; i--) {
5349 USTPUTC(optletters(i), p);
5360 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5361 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5364 if (!(ap = shellparam.p))
5366 while ((p = *ap++)) {
5369 partlen = strlen(p);
5372 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5373 memtodest(p, partlen, syntax, quotes);
5379 if (subtype == VSPLUS || subtype == VSLENGTH) {
5401 if (num < 0 || num > shellparam.nparam)
5403 p = num ? shellparam.p[num - 1] : arg0;
5406 p = lookupvar(name);
5412 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5413 memtodest(p, len, syntax, quotes);
5417 if (subtype == VSPLUS || subtype == VSLENGTH)
5418 STADJUST(-len, expdest);
5424 * Record the fact that we have to scan this region of the
5425 * string for IFS characters.
5429 recordregion(int start, int end, int nulonly)
5431 struct ifsregion *ifsp;
5433 if (ifslastp == NULL) {
5437 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5439 ifslastp->next = ifsp;
5443 ifslastp->begoff = start;
5444 ifslastp->endoff = end;
5445 ifslastp->nulonly = nulonly;
5450 * Break the argument string into pieces based upon IFS and add the
5451 * strings to the argument list. The regions of the string to be
5452 * searched for IFS characters have been stored by recordregion.
5455 ifsbreakup(char *string, struct arglist *arglist)
5457 struct ifsregion *ifsp;
5462 const char *ifs, *realifs;
5468 if (ifslastp != NULL) {
5471 realifs = ifsset() ? ifsval() : defifs;
5474 p = string + ifsp->begoff;
5475 nulonly = ifsp->nulonly;
5476 ifs = nulonly ? nullstr : realifs;
5478 while (p < string + ifsp->endoff) {
5482 if (strchr(ifs, *p)) {
5484 ifsspc = (strchr(defifs, *p) != NULL);
5485 /* Ignore IFS whitespace at start */
5486 if (q == start && ifsspc) {
5492 sp = (struct strlist *)stalloc(sizeof *sp);
5494 *arglist->lastp = sp;
5495 arglist->lastp = &sp->next;
5499 if (p >= string + ifsp->endoff) {
5505 if (strchr(ifs, *p) == NULL ) {
5508 } else if (strchr(defifs, *p) == NULL) {
5524 } while ((ifsp = ifsp->next) != NULL);
5533 sp = (struct strlist *)stalloc(sizeof *sp);
5535 *arglist->lastp = sp;
5536 arglist->lastp = &sp->next;
5542 struct ifsregion *p;
5547 struct ifsregion *ifsp;
5553 ifsfirst.next = NULL;
5557 static void expmeta(char *, char *);
5558 static struct strlist *expsort(struct strlist *);
5559 static struct strlist *msort(struct strlist *, int);
5561 static char *expdir;
5565 expandmeta(struct strlist *str, int flag)
5567 static const char metachars[] = {
5570 /* TODO - EXP_REDIR */
5573 struct strlist **savelastp;
5579 if (!strpbrk(str->text, metachars))
5581 savelastp = exparg.lastp;
5584 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5586 int i = strlen(str->text);
5587 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5595 if (exparg.lastp == savelastp) {
5600 *exparg.lastp = str;
5601 rmescapes(str->text);
5602 exparg.lastp = &str->next;
5604 *exparg.lastp = NULL;
5605 *savelastp = sp = expsort(*savelastp);
5606 while (sp->next != NULL)
5608 exparg.lastp = &sp->next;
5615 * Add a file name to the list.
5619 addfname(const char *name)
5623 sp = (struct strlist *)stalloc(sizeof *sp);
5624 sp->text = sstrdup(name);
5626 exparg.lastp = &sp->next;
5631 * Do metacharacter (i.e. *, ?, [...]) expansion.
5635 expmeta(char *enddir, char *name)
5650 for (p = name; *p; p++) {
5651 if (*p == '*' || *p == '?')
5653 else if (*p == '[') {
5660 if (*q == '/' || *q == '\0')
5667 } else if (*p == '\\')
5669 else if (*p == '/') {
5676 if (metaflag == 0) { /* we've reached the end of the file name */
5677 if (enddir != expdir)
5685 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5696 } while (p < start);
5698 if (enddir == expdir) {
5700 } else if (enddir == expdir + 1 && *expdir == '/') {
5706 if ((dirp = opendir(cp)) == NULL)
5708 if (enddir != expdir)
5710 if (*endname == 0) {
5722 while (! intpending && (dp = readdir(dirp)) != NULL) {
5723 if (dp->d_name[0] == '.' && ! matchdot)
5725 if (pmatch(start, dp->d_name)) {
5727 scopy(dp->d_name, enddir);
5730 for (p = enddir, cp = dp->d_name;
5731 (*p++ = *cp++) != '\0';)
5734 expmeta(p, endname);
5744 * Sort the results of file name expansion. It calculates the number of
5745 * strings to sort and then calls msort (short for merge sort) to do the
5749 static struct strlist *
5750 expsort(struct strlist *str)
5756 for (sp = str ; sp ; sp = sp->next)
5758 return msort(str, len);
5762 static struct strlist *
5763 msort(struct strlist *list, int len)
5765 struct strlist *p, *q = NULL;
5766 struct strlist **lpp;
5774 for (n = half ; --n >= 0 ; ) {
5778 q->next = NULL; /* terminate first half of list */
5779 q = msort(list, half); /* sort first half of list */
5780 p = msort(p, len - half); /* sort second half */
5783 #ifdef CONFIG_LOCALE_SUPPORT
5784 if (strcoll(p->text, q->text) < 0)
5786 if (strcmp(p->text, q->text) < 0)
5791 if ((p = *lpp) == NULL) {
5798 if ((q = *lpp) == NULL) {
5809 * Returns true if the pattern matches the string.
5812 static int patmatch(char *pattern, const char *string)
5814 return pmatch(preglob(pattern, 0, 0), string);
5819 * Remove any CTLESC characters from a string.
5823 _rmescapes(char *str, int flag)
5826 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5831 p = strpbrk(str, qchars);
5837 if (flag & RMESCAPE_ALLOC) {
5838 size_t len = p - str;
5839 size_t fulllen = len + strlen(p) + 1;
5841 if (flag & RMESCAPE_GROW) {
5842 r = makestrspace(fulllen, expdest);
5843 } else if (flag & RMESCAPE_HEAP) {
5844 r = ckmalloc(fulllen);
5846 r = stalloc(fulllen);
5850 q = mempcpy(q, str, len);
5853 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5854 globbing = flag & RMESCAPE_GLOB;
5855 notescaped = globbing;
5857 if (*p == CTLQUOTEMARK) {
5858 inquotes = ~inquotes;
5860 notescaped = globbing;
5864 /* naked back slash */
5870 if (notescaped && inquotes && *p != '/') {
5874 notescaped = globbing;
5879 if (flag & RMESCAPE_GROW) {
5881 STADJUST(q - r + 1, expdest);
5888 * See if a pattern matches in a case statement.
5892 casematch(union node *pattern, char *val)
5894 struct stackmark smark;
5897 setstackmark(&smark);
5898 argbackq = pattern->narg.backquote;
5899 STARTSTACKSTR(expdest);
5901 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5902 STACKSTRNUL(expdest);
5903 result = patmatch(stackblock(), val);
5904 popstackmark(&smark);
5917 expdest = makestrspace(32, expdest);
5918 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5919 len = fmtstr(expdest, 32, "%lld", (long long) num);
5921 len = fmtstr(expdest, 32, "%ld", num);
5923 STADJUST(len, expdest);
5928 varunset(const char *end, const char *var, const char *umsg, int varflags)
5934 msg = "parameter not set";
5936 if (*end == CTLENDVAR) {
5937 if (varflags & VSNUL)
5942 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5949 * This implements the input routines used by the parser.
5952 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5954 static void pushfile(void);
5957 * Read a character from the script, returning PEOF on end of file.
5958 * Nul characters in the input are silently discarded.
5962 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5964 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5965 #define pgetc_macro() pgetc()
5969 return pgetc_as_macro();
5972 #define pgetc_macro() pgetc_as_macro()
5976 return pgetc_macro();
5982 * Same as pgetc(), but ignores PEOA.
5984 #ifdef CONFIG_ASH_ALIAS
5985 static int pgetc2(void)
5991 } while (c == PEOA);
5995 static int pgetc2(void)
5997 return pgetc_macro();
6002 * Read a line from the script.
6005 static char * pfgets(char *line, int len)
6011 while (--nleft > 0) {
6028 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6029 #ifdef CONFIG_ASH_EXPAND_PRMT
6030 static char *cmdedit_prompt;
6032 static const char *cmdedit_prompt;
6034 static void putprompt(const char *s)
6036 #ifdef CONFIG_ASH_EXPAND_PRMT
6037 free(cmdedit_prompt);
6038 cmdedit_prompt = xstrdup(s);
6044 static void putprompt(const char *s)
6050 static int preadfd(void)
6053 char *buf = parsefile->buf;
6057 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6058 if (!iflag || parsefile->fd)
6059 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6061 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6062 cmdedit_path_lookup = pathval();
6064 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6066 /* Ctrl+C presend */
6075 if(nr < 0 && errno == 0) {
6076 /* Ctrl+D presend */
6081 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6085 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6086 int flags = fcntl(0, F_GETFL, 0);
6087 if (flags >= 0 && flags & O_NONBLOCK) {
6088 flags &=~ O_NONBLOCK;
6089 if (fcntl(0, F_SETFL, flags) >= 0) {
6090 out2str("sh: turning off NDELAY mode\n");
6100 * Refill the input buffer and return the next input character:
6102 * 1) If a string was pushed back on the input, pop it;
6103 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6104 * from a string so we can't refill the buffer, return EOF.
6105 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6106 * 4) Process input up to the next newline, deleting nul characters.
6116 while (parsefile->strpush) {
6117 #ifdef CONFIG_ASH_ALIAS
6118 if (parsenleft == -1 && parsefile->strpush->ap &&
6119 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6124 if (--parsenleft >= 0)
6125 return SC2INT(*parsenextc++);
6127 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6134 if ((more = preadfd()) <= 0) {
6135 parselleft = parsenleft = EOF_NLEFT;
6142 /* delete nul characters */
6150 memmove(q, q + 1, more);
6154 parsenleft = q - parsenextc - 1;
6160 parsenleft = q - parsenextc - 1;
6172 out2str(parsenextc);
6177 return SC2INT(*parsenextc++);
6181 * Undo the last call to pgetc. Only one character may be pushed back.
6182 * PEOF may be pushed back.
6193 * Push a string back onto the input at this current parsefile level.
6194 * We handle aliases this way.
6197 pushstring(char *s, void *ap)
6204 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6205 if (parsefile->strpush) {
6206 sp = ckmalloc(sizeof (struct strpush));
6207 sp->prev = parsefile->strpush;
6208 parsefile->strpush = sp;
6210 sp = parsefile->strpush = &(parsefile->basestrpush);
6211 sp->prevstring = parsenextc;
6212 sp->prevnleft = parsenleft;
6213 #ifdef CONFIG_ASH_ALIAS
6214 sp->ap = (struct alias *)ap;
6216 ((struct alias *)ap)->flag |= ALIASINUSE;
6228 struct strpush *sp = parsefile->strpush;
6231 #ifdef CONFIG_ASH_ALIAS
6233 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6234 checkkwd |= CHKALIAS;
6236 if (sp->string != sp->ap->val) {
6239 sp->ap->flag &= ~ALIASINUSE;
6240 if (sp->ap->flag & ALIASDEAD) {
6241 unalias(sp->ap->name);
6245 parsenextc = sp->prevstring;
6246 parsenleft = sp->prevnleft;
6247 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6248 parsefile->strpush = sp->prev;
6249 if (sp != &(parsefile->basestrpush))
6255 * Set the input to take input from a file. If push is set, push the
6256 * old input onto the stack first.
6260 setinputfile(const char *fname, int flags)
6266 if ((fd = open(fname, O_RDONLY)) < 0) {
6267 if (flags & INPUT_NOFILE_OK)
6269 sh_error("Can't open %s", fname);
6272 fd2 = copyfd(fd, 10);
6275 sh_error("Out of file descriptors");
6278 setinputfd(fd, flags & INPUT_PUSH_FILE);
6286 * Like setinputfile, but takes an open file descriptor. Call this with
6291 setinputfd(int fd, int push)
6293 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6299 if (parsefile->buf == NULL)
6300 parsefile->buf = ckmalloc(IBUFSIZ);
6301 parselleft = parsenleft = 0;
6307 * Like setinputfile, but takes input from a string.
6311 setinputstring(char *string)
6315 parsenextc = string;
6316 parsenleft = strlen(string);
6317 parsefile->buf = NULL;
6324 * To handle the "." command, a stack of input files is used. Pushfile
6325 * adds a new entry to the stack and popfile restores the previous level.
6331 struct parsefile *pf;
6333 parsefile->nleft = parsenleft;
6334 parsefile->lleft = parselleft;
6335 parsefile->nextc = parsenextc;
6336 parsefile->linno = plinno;
6337 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6338 pf->prev = parsefile;
6341 pf->basestrpush.prev = NULL;
6349 struct parsefile *pf = parsefile;
6358 parsefile = pf->prev;
6360 parsenleft = parsefile->nleft;
6361 parselleft = parsefile->lleft;
6362 parsenextc = parsefile->nextc;
6363 plinno = parsefile->linno;
6369 * Return to top level.
6375 while (parsefile != &basepf)
6381 * Close the file(s) that the shell is reading commands from. Called
6382 * after a fork is done.
6389 if (parsefile->fd > 0) {
6390 close(parsefile->fd);
6397 /* mode flags for set_curjob */
6398 #define CUR_DELETE 2
6399 #define CUR_RUNNING 1
6400 #define CUR_STOPPED 0
6402 /* mode flags for dowait */
6403 #define DOWAIT_NORMAL 0
6404 #define DOWAIT_BLOCK 1
6407 static struct job *jobtab;
6409 static unsigned njobs;
6411 /* pgrp of shell on invocation */
6412 static int initialpgrp;
6413 static int ttyfd = -1;
6416 static struct job *curjob;
6417 /* number of presumed living untracked jobs */
6420 static void set_curjob(struct job *, unsigned);
6422 static int restartjob(struct job *, int);
6423 static void xtcsetpgrp(int, pid_t);
6424 static char *commandtext(union node *);
6425 static void cmdlist(union node *, int);
6426 static void cmdtxt(union node *);
6427 static void cmdputs(const char *);
6428 static void showpipe(struct job *, FILE *);
6430 static int sprint_status(char *, int, int);
6431 static void freejob(struct job *);
6432 static struct job *getjob(const char *, int);
6433 static struct job *growjobtab(void);
6434 static void forkchild(struct job *, union node *, int);
6435 static void forkparent(struct job *, union node *, int, pid_t);
6436 static int dowait(int, struct job *);
6437 static int getstatus(struct job *);
6440 set_curjob(struct job *jp, unsigned mode)
6443 struct job **jpp, **curp;
6445 /* first remove from list */
6446 jpp = curp = &curjob;
6451 jpp = &jp1->prev_job;
6453 *jpp = jp1->prev_job;
6455 /* Then re-insert in correct position */
6463 /* job being deleted */
6466 /* newly created job or backgrounded job,
6467 put after all stopped jobs. */
6471 if (!jp1 || jp1->state != JOBSTOPPED)
6474 jpp = &jp1->prev_job;
6480 /* newly stopped job - becomes curjob */
6481 jp->prev_job = *jpp;
6489 * Turn job control on and off.
6491 * Note: This code assumes that the third arg to ioctl is a character
6492 * pointer, which is true on Berkeley systems but not System V. Since
6493 * System V doesn't have job control yet, this isn't a problem now.
6495 * Called with interrupts off.
6504 if (on == jobctl || rootshell == 0)
6508 ofd = fd = open(_PATH_TTY, O_RDWR);
6511 while (!isatty(fd) && --fd >= 0)
6514 fd = fcntl(fd, F_DUPFD, 10);
6518 fcntl(fd, F_SETFD, FD_CLOEXEC);
6519 do { /* while we are in the background */
6520 if ((pgrp = tcgetpgrp(fd)) < 0) {
6522 sh_warnx("can't access tty; job control turned off");
6526 if (pgrp == getpgrp())
6537 xtcsetpgrp(fd, pgrp);
6539 /* turning job control off */
6542 xtcsetpgrp(fd, pgrp);
6556 killcmd(int argc, char **argv)
6567 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6568 "kill -l [exitstatus]"
6572 if (**++argv == '-') {
6573 signo = get_signum(*argv + 1);
6577 while ((c = nextopt("ls:")) != '\0')
6587 signo = get_signum(optionarg);
6590 "invalid signal number or name: %s",
6601 if (!list && signo < 0)
6604 if ((signo < 0 || !*argv) ^ list) {
6612 for (i = 1; i < NSIG; i++) {
6613 name = get_signame(i);
6615 out1fmt(snlfmt, name);
6619 name = get_signame(signo);
6621 out1fmt(snlfmt, name);
6623 sh_error("invalid signal number or exit status: %s", *argptr);
6629 if (**argv == '%') {
6630 jp = getjob(*argv, 0);
6631 pid = -jp->ps[0].pid;
6633 pid = **argv == '-' ?
6634 -number(*argv + 1) : number(*argv);
6636 if (kill(pid, signo) != 0) {
6637 sh_warnx("(%d) - %m", pid);
6646 #if defined(JOBS) || defined(DEBUG)
6648 jobno(const struct job *jp)
6650 return jp - jobtab + 1;
6656 fgcmd(int argc, char **argv)
6663 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6668 jp = getjob(*argv, 1);
6669 if (mode == FORK_BG) {
6670 set_curjob(jp, CUR_RUNNING);
6671 fprintf(out, "[%d] ", jobno(jp));
6673 outstr(jp->ps->cmd, out);
6675 retval = restartjob(jp, mode);
6676 } while (*argv && *++argv);
6680 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6684 restartjob(struct job *jp, int mode)
6686 struct procstat *ps;
6692 if (jp->state == JOBDONE)
6694 jp->state = JOBRUNNING;
6696 if (mode == FORK_FG)
6697 xtcsetpgrp(ttyfd, pgid);
6698 killpg(pgid, SIGCONT);
6702 if (WIFSTOPPED(ps->status)) {
6705 } while (ps++, --i);
6707 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6714 sprint_status(char *s, int status, int sigonly)
6720 if (!WIFEXITED(status)) {
6722 if (WIFSTOPPED(status))
6723 st = WSTOPSIG(status);
6726 st = WTERMSIG(status);
6728 if (st == SIGINT || st == SIGPIPE)
6731 if (WIFSTOPPED(status))
6736 col = fmtstr(s, 32, strsignal(st));
6737 if (WCOREDUMP(status)) {
6738 col += fmtstr(s + col, 16, " (core dumped)");
6740 } else if (!sigonly) {
6741 st = WEXITSTATUS(status);
6743 col = fmtstr(s, 16, "Done(%d)", st);
6745 col = fmtstr(s, 16, "Done");
6754 showjob(FILE *out, struct job *jp, int mode)
6756 struct procstat *ps;
6757 struct procstat *psend;
6764 if (mode & SHOW_PGID) {
6765 /* just output process (group) id of pipeline */
6766 fprintf(out, "%d\n", ps->pid);
6770 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6775 else if (curjob && jp == curjob->prev_job)
6778 if (mode & SHOW_PID)
6779 col += fmtstr(s + col, 16, "%d ", ps->pid);
6781 psend = ps + jp->nprocs;
6783 if (jp->state == JOBRUNNING) {
6784 scopy("Running", s + col);
6785 col += strlen("Running");
6787 int status = psend[-1].status;
6789 if (jp->state == JOBSTOPPED)
6790 status = jp->stopstatus;
6792 col += sprint_status(s + col, status, 0);
6798 /* for each process */
6799 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6802 fprintf(out, "%s%*c%s",
6803 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6805 if (!(mode & SHOW_PID)) {
6809 if (++ps == psend) {
6810 outcslow('\n', out);
6817 if (jp->state == JOBDONE) {
6818 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6825 jobscmd(int argc, char **argv)
6831 while ((m = nextopt("lp")))
6841 showjob(out, getjob(*argv,0), mode);
6844 showjobs(out, mode);
6851 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6852 * statuses have changed since the last call to showjobs.
6856 showjobs(FILE *out, int mode)
6860 TRACE(("showjobs(%x) called\n", mode));
6862 /* If not even one one job changed, there is nothing to do */
6863 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6866 for (jp = curjob; jp; jp = jp->prev_job) {
6867 if (!(mode & SHOW_CHANGED) || jp->changed)
6868 showjob(out, jp, mode);
6874 * Mark a job structure as unused.
6878 freejob(struct job *jp)
6880 struct procstat *ps;
6884 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6885 if (ps->cmd != nullstr)
6888 if (jp->ps != &jp->ps0)
6891 set_curjob(jp, CUR_DELETE);
6897 waitcmd(int argc, char **argv)
6910 /* wait for all jobs */
6915 /* no running procs */
6918 if (jp->state == JOBRUNNING)
6923 dowait(DOWAIT_BLOCK, 0);
6929 if (**argv != '%') {
6930 pid_t pid = number(*argv);
6934 if (job->ps[job->nprocs - 1].pid == pid)
6936 job = job->prev_job;
6942 job = getjob(*argv, 0);
6943 /* loop until process terminated or stopped */
6944 while (job->state == JOBRUNNING)
6945 dowait(DOWAIT_BLOCK, 0);
6947 retval = getstatus(job);
6958 * Convert a job name to a job structure.
6962 getjob(const char *name, int getctl)
6966 const char *err_msg = "No such job: %s";
6970 char *(*match)(const char *, const char *);
6985 if (c == '+' || c == '%') {
6987 err_msg = "No current job";
6989 } else if (c == '-') {
6992 err_msg = "No previous job";
7003 jp = jobtab + num - 1;
7020 if (match(jp->ps[0].cmd, p)) {
7024 err_msg = "%s: ambiguous";
7031 err_msg = "job %s not created under job control";
7032 if (getctl && jp->jobctl == 0)
7037 sh_error(err_msg, name);
7042 * Return a new job structure.
7043 * Called with interrupts off.
7047 makejob(union node *node, int nprocs)
7052 for (i = njobs, jp = jobtab ; ; jp++) {
7059 if (jp->state != JOBDONE || !jp->waited)
7068 memset(jp, 0, sizeof(*jp));
7073 jp->prev_job = curjob;
7078 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7080 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7090 struct job *jp, *jq;
7092 len = njobs * sizeof(*jp);
7094 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7096 offset = (char *)jp - (char *)jq;
7098 /* Relocate pointers */
7101 jq = (struct job *)((char *)jq + l);
7105 #define joff(p) ((struct job *)((char *)(p) + l))
7106 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7107 if (xlikely(joff(jp)->ps == &jq->ps0))
7108 jmove(joff(jp)->ps);
7109 if (joff(jp)->prev_job)
7110 jmove(joff(jp)->prev_job);
7120 jp = (struct job *)((char *)jp + len);
7124 } while (--jq >= jp);
7130 * Fork off a subshell. If we are doing job control, give the subshell its
7131 * own process group. Jp is a job structure that the job is to be added to.
7132 * N is the command that will be evaluated by the child. Both jp and n may
7133 * be NULL. The mode parameter can be one of the following:
7134 * FORK_FG - Fork off a foreground process.
7135 * FORK_BG - Fork off a background process.
7136 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7137 * process group even if job control is on.
7139 * When job control is turned off, background processes have their standard
7140 * input redirected to /dev/null (except for the second and later processes
7143 * Called with interrupts off.
7146 static void forkchild(struct job *jp, union node *n, int mode)
7150 TRACE(("Child shell %d\n", getpid()));
7157 /* do job control only in root shell */
7159 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7162 if (jp->nprocs == 0)
7165 pgrp = jp->ps[0].pid;
7166 /* This can fail because we are doing it in the parent also */
7167 (void)setpgid(0, pgrp);
7168 if (mode == FORK_FG)
7169 xtcsetpgrp(ttyfd, pgrp);
7174 if (mode == FORK_BG) {
7177 if (jp->nprocs == 0) {
7179 if (open(bb_dev_null, O_RDONLY) != 0)
7180 sh_error("Can't open %s", bb_dev_null);
7183 if (!oldlvl && iflag) {
7188 for (jp = curjob; jp; jp = jp->prev_job)
7193 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7195 TRACE(("In parent shell: child = %d\n", pid));
7197 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7202 if (mode != FORK_NOJOB && jp->jobctl) {
7205 if (jp->nprocs == 0)
7208 pgrp = jp->ps[0].pid;
7209 /* This can fail because we are doing it in the child also */
7210 (void)setpgid(pid, pgrp);
7213 if (mode == FORK_BG) {
7214 backgndpid = pid; /* set $! */
7215 set_curjob(jp, CUR_RUNNING);
7218 struct procstat *ps = &jp->ps[jp->nprocs++];
7224 ps->cmd = commandtext(n);
7230 forkshell(struct job *jp, union node *n, int mode)
7234 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7237 TRACE(("Fork failed, errno=%d", errno));
7240 sh_error("Cannot fork");
7243 forkchild(jp, n, mode);
7245 forkparent(jp, n, mode, pid);
7250 * Wait for job to finish.
7252 * Under job control we have the problem that while a child process is
7253 * running interrupts generated by the user are sent to the child but not
7254 * to the shell. This means that an infinite loop started by an inter-
7255 * active user may be hard to kill. With job control turned off, an
7256 * interactive user may place an interactive program inside a loop. If
7257 * the interactive program catches interrupts, the user doesn't want
7258 * these interrupts to also abort the loop. The approach we take here
7259 * is to have the shell ignore interrupt signals while waiting for a
7260 * foreground process to terminate, and then send itself an interrupt
7261 * signal if the child process was terminated by an interrupt signal.
7262 * Unfortunately, some programs want to do a bit of cleanup and then
7263 * exit on interrupt; unless these processes terminate themselves by
7264 * sending a signal to themselves (instead of calling exit) they will
7265 * confuse this approach.
7267 * Called with interrupts off.
7271 waitforjob(struct job *jp)
7275 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7276 while (jp->state == JOBRUNNING) {
7277 dowait(DOWAIT_BLOCK, jp);
7282 xtcsetpgrp(ttyfd, rootpid);
7284 * This is truly gross.
7285 * If we're doing job control, then we did a TIOCSPGRP which
7286 * caused us (the shell) to no longer be in the controlling
7287 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7288 * intuit from the subprocess exit status whether a SIGINT
7289 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7294 if (jp->state == JOBDONE)
7302 * Do a wait system call. If job control is compiled in, we accept
7303 * stopped processes. If block is zero, we return a value of zero
7304 * rather than blocking.
7306 * System V doesn't have a non-blocking wait system call. It does
7307 * have a SIGCLD signal that is sent to a process when one of it's
7308 * children dies. The obvious way to use SIGCLD would be to install
7309 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7310 * was received, and have waitproc bump another counter when it got
7311 * the status of a process. Waitproc would then know that a wait
7312 * system call would not block if the two counters were different.
7313 * This approach doesn't work because if a process has children that
7314 * have not been waited for, System V will send it a SIGCLD when it
7315 * installs a signal handler for SIGCLD. What this means is that when
7316 * a child exits, the shell will be sent SIGCLD signals continuously
7317 * until is runs out of stack space, unless it does a wait call before
7318 * restoring the signal handler. The code below takes advantage of
7319 * this (mis)feature by installing a signal handler for SIGCLD and
7320 * then checking to see whether it was called. If there are any
7321 * children to be waited for, it will be.
7323 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7324 * waits at all. In this case, the user will not be informed when
7325 * a background process until the next time she runs a real program
7326 * (as opposed to running a builtin command or just typing return),
7327 * and the jobs command may give out of date information.
7330 static int waitproc(int block, int *status)
7340 return wait3(status, flags, (struct rusage *)NULL);
7344 * Wait for a process to terminate.
7348 dowait(int block, struct job *job)
7353 struct job *thisjob;
7356 TRACE(("dowait(%d) called\n", block));
7357 pid = waitproc(block, &status);
7358 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7363 for (jp = curjob; jp; jp = jp->prev_job) {
7364 struct procstat *sp;
7365 struct procstat *spend;
7366 if (jp->state == JOBDONE)
7369 spend = jp->ps + jp->nprocs;
7372 if (sp->pid == pid) {
7373 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7374 sp->status = status;
7377 if (sp->status == -1)
7380 if (state == JOBRUNNING)
7382 if (WIFSTOPPED(sp->status)) {
7383 jp->stopstatus = sp->status;
7387 } while (++sp < spend);
7392 if (!WIFSTOPPED(status))
7399 if (state != JOBRUNNING) {
7400 thisjob->changed = 1;
7402 if (thisjob->state != state) {
7403 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7404 thisjob->state = state;
7406 if (state == JOBSTOPPED) {
7407 set_curjob(thisjob, CUR_STOPPED);
7416 if (thisjob && thisjob == job) {
7420 len = sprint_status(s, status, 1);
7432 * return 1 if there are stopped jobs, otherwise 0
7445 if (jp && jp->state == JOBSTOPPED) {
7446 out2str("You have stopped jobs.\n");
7456 * Return a string identifying a command (to be printed by the
7461 static char *cmdnextc;
7464 commandtext(union node *n)
7468 STARTSTACKSTR(cmdnextc);
7470 name = stackblock();
7471 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7472 name, cmdnextc, cmdnextc));
7473 return savestr(name);
7477 cmdtxt(union node *n)
7480 struct nodelist *lp;
7492 lp = n->npipe.cmdlist;
7510 cmdtxt(n->nbinary.ch1);
7526 cmdtxt(n->nif.test);
7529 if (n->nif.elsepart) {
7532 n = n->nif.elsepart;
7548 cmdtxt(n->nbinary.ch1);
7558 cmdputs(n->nfor.var);
7560 cmdlist(n->nfor.args, 1);
7565 cmdputs(n->narg.text);
7569 cmdlist(n->ncmd.args, 1);
7570 cmdlist(n->ncmd.redirect, 0);
7583 cmdputs(n->ncase.expr->narg.text);
7585 for (np = n->ncase.cases; np; np = np->nclist.next) {
7586 cmdtxt(np->nclist.pattern);
7588 cmdtxt(np->nclist.body);
7614 s[0] = n->nfile.fd + '0';
7618 if (n->type == NTOFD || n->type == NFROMFD) {
7619 s[0] = n->ndup.dupfd + '0';
7630 cmdlist(union node *np, int sep)
7632 for (; np; np = np->narg.next) {
7636 if (sep && np->narg.next)
7642 cmdputs(const char *s)
7644 const char *p, *str;
7645 char c, cc[2] = " ";
7649 static const char vstype[VSTYPE + 1][4] = {
7650 "", "}", "-", "+", "?", "=",
7651 "%", "%%", "#", "##"
7653 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7655 while ((c = *p++) != 0) {
7663 if ((subtype & VSTYPE) == VSLENGTH)
7667 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7674 str = "\"}" + !(quoted & 1);
7681 case CTLBACKQ+CTLQUOTE:
7684 #ifdef CONFIG_ASH_MATH_SUPPORT
7699 if ((subtype & VSTYPE) != VSNORMAL)
7701 str = vstype[subtype & VSTYPE];
7702 if (subtype & VSNUL)
7711 /* These can only happen inside quotes */
7724 while ((c = *str++)) {
7729 USTPUTC('"', nextc);
7737 showpipe(struct job *jp, FILE *out)
7739 struct procstat *sp;
7740 struct procstat *spend;
7742 spend = jp->ps + jp->nprocs;
7743 for (sp = jp->ps + 1; sp < spend; sp++)
7744 fprintf(out, " | %s", sp->cmd);
7745 outcslow('\n', out);
7750 xtcsetpgrp(int fd, pid_t pgrp)
7752 if (tcsetpgrp(fd, pgrp))
7753 sh_error("Cannot set tty process group (%m)");
7758 getstatus(struct job *job) {
7762 status = job->ps[job->nprocs - 1].status;
7763 retval = WEXITSTATUS(status);
7764 if (!WIFEXITED(status)) {
7766 retval = WSTOPSIG(status);
7767 if (!WIFSTOPPED(status))
7770 /* XXX: limits number of signals */
7771 retval = WTERMSIG(status);
7773 if (retval == SIGINT)
7779 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7780 jobno(job), job->nprocs, status, retval));
7784 #ifdef CONFIG_ASH_MAIL
7788 * Routines to check for mail. (Perhaps make part of main.c?)
7791 #define MAXMBOXES 10
7793 /* times of mailboxes */
7794 static time_t mailtime[MAXMBOXES];
7795 /* Set if MAIL or MAILPATH is changed. */
7796 static int mail_var_path_changed;
7801 * Print appropriate message(s) if mail has arrived.
7802 * If mail_var_path_changed is set,
7803 * then the value of MAIL has mail_var_path_changed,
7804 * so we just update the values.
7814 struct stackmark smark;
7817 setstackmark(&smark);
7818 mpath = mpathset() ? mpathval() : mailval();
7819 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7820 p = padvance(&mpath, nullstr);
7825 for (q = p ; *q ; q++);
7830 q[-1] = '\0'; /* delete trailing '/' */
7831 if (stat(p, &statb) < 0) {
7835 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7838 pathopt ? pathopt : "you have mail"
7841 *mtp = statb.st_mtime;
7843 mail_var_path_changed = 0;
7844 popstackmark(&smark);
7849 changemail(const char *val)
7851 mail_var_path_changed++;
7854 #endif /* CONFIG_ASH_MAIL */
7860 static short profile_buf[16384];
7864 static int isloginsh;
7866 static void read_profile(const char *);
7869 * Main routine. We initialize things, parse the arguments, execute
7870 * profiles if we're a login shell, and then call cmdloop to execute
7871 * commands. The setjmp call sets up the location to jump to when an
7872 * exception occurs. When an exception occurs the variable "state"
7873 * is used to figure out how far we had gotten.
7877 ash_main(int argc, char **argv)
7881 struct jmploc jmploc;
7882 struct stackmark smark;
7885 dash_errno = __errno_location();
7889 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7892 if (setjmp(jmploc.loc)) {
7902 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7906 outcslow('\n', stderr);
7908 popstackmark(&smark);
7909 FORCEINTON; /* enable interrupts */
7922 trputs("Shell args: "); trargs(argv);
7926 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7927 rseed = rootpid + ((time_t)time((time_t *)0));
7930 setstackmark(&smark);
7931 procargs(argc, argv);
7932 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7934 const char *hp = lookupvar("HISTFILE");
7937 hp = lookupvar("HOME");
7939 char *defhp = concat_path_file(hp, ".ash_history");
7940 setvar("HISTFILE", defhp, 0);
7946 if (argv[0] && argv[0][0] == '-')
7950 read_profile("/etc/profile");
7953 read_profile(".profile");
7959 getuid() == geteuid() && getgid() == getegid() &&
7963 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7964 read_profile(shinit);
7970 evalstring(minusc, 0);
7972 if (sflag || minusc == NULL) {
7973 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7975 const char *hp = lookupvar("HISTFILE");
7978 load_history ( hp );
7981 state4: /* XXX ??? - why isn't this before the "if" statement */
7989 extern void _mcleanup(void);
7999 * Read and execute commands. "Top" is nonzero for the top level command
8000 * loop; it turns on prompting if the shell is interactive.
8007 struct stackmark smark;
8011 TRACE(("cmdloop(%d) called\n", top));
8015 setstackmark(&smark);
8018 showjobs(stderr, SHOW_CHANGED);
8023 #ifdef CONFIG_ASH_MAIL
8027 n = parsecmd(inter);
8028 /* showtree(n); DEBUG */
8030 if (!top || numeof >= 50)
8032 if (!stoppedjobs()) {
8035 out2str("\nUse \"exit\" to leave shell.\n");
8038 } else if (nflag == 0) {
8039 job_warning = (job_warning == 2) ? 1 : 0;
8043 popstackmark(&smark);
8048 return skip & SKIPEVAL;
8057 * Read /etc/profile or .profile. Return on error.
8061 read_profile(const char *name)
8065 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8077 * Read a file containing shell functions.
8081 readcmdfile(char *name)
8083 setinputfile(name, INPUT_PUSH_FILE);
8090 * Take commands from a file. To be compatible we should do a path
8091 * search for the file, which is necessary to find sub-commands.
8094 static char * find_dot_file(char *name)
8097 const char *path = pathval();
8100 /* don't try this for absolute or relative paths */
8101 if (strchr(name, '/'))
8104 while ((fullname = padvance(&path, name)) != NULL) {
8105 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8107 * Don't bother freeing here, since it will
8108 * be freed by the caller.
8112 stunalloc(fullname);
8115 /* not found in the PATH */
8116 sh_error(not_found_msg, name);
8120 static int dotcmd(int argc, char **argv)
8123 volatile struct shparam saveparam;
8126 for (sp = cmdenviron; sp; sp = sp->next)
8127 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8129 if (argc >= 2) { /* That's what SVR2 does */
8132 fullname = find_dot_file(argv[1]);
8135 saveparam = shellparam;
8136 shellparam.malloc = 0;
8137 shellparam.nparam = argc - 2;
8138 shellparam.p = argv + 2;
8141 setinputfile(fullname, INPUT_PUSH_FILE);
8142 commandname = fullname;
8147 freeparam(&shellparam);
8148 shellparam = saveparam;
8150 status = exitstatus;
8157 exitcmd(int argc, char **argv)
8162 exitstatus = number(argv[1]);
8167 #ifdef CONFIG_ASH_BUILTIN_ECHO
8169 echocmd(int argc, char **argv)
8171 return bb_echo(argc, argv);
8175 #ifdef CONFIG_ASH_BUILTIN_TEST
8177 testcmd(int argc, char **argv)
8179 return bb_test(argc, argv);
8186 * Same for malloc, realloc, but returns an error when out of space.
8190 ckrealloc(pointer p, size_t nbytes)
8192 p = realloc(p, nbytes);
8194 sh_error(bb_msg_memory_exhausted);
8199 ckmalloc(size_t nbytes)
8201 return ckrealloc(NULL, nbytes);
8205 * Make a copy of a string in safe storage.
8209 savestr(const char *s)
8211 char *p = strdup(s);
8213 sh_error(bb_msg_memory_exhausted);
8219 * Parse trees for commands are allocated in lifo order, so we use a stack
8220 * to make this more efficient, and also to avoid all sorts of exception
8221 * handling code to handle interrupts in the middle of a parse.
8223 * The size 504 was chosen because the Ultrix malloc handles that size
8229 stalloc(size_t nbytes)
8234 aligned = SHELL_ALIGN(nbytes);
8235 if (aligned > stacknleft) {
8238 struct stack_block *sp;
8240 blocksize = aligned;
8241 if (blocksize < MINSIZE)
8242 blocksize = MINSIZE;
8243 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8244 if (len < blocksize)
8245 sh_error(bb_msg_memory_exhausted);
8249 stacknxt = sp->space;
8250 stacknleft = blocksize;
8251 sstrend = stacknxt + blocksize;
8256 stacknxt += aligned;
8257 stacknleft -= aligned;
8263 stunalloc(pointer p)
8266 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8267 write(2, "stunalloc\n", 10);
8271 stacknleft += stacknxt - (char *)p;
8277 setstackmark(struct stackmark *mark)
8279 mark->stackp = stackp;
8280 mark->stacknxt = stacknxt;
8281 mark->stacknleft = stacknleft;
8282 mark->marknext = markp;
8288 popstackmark(struct stackmark *mark)
8290 struct stack_block *sp;
8293 markp = mark->marknext;
8294 while (stackp != mark->stackp) {
8299 stacknxt = mark->stacknxt;
8300 stacknleft = mark->stacknleft;
8301 sstrend = mark->stacknxt + mark->stacknleft;
8307 * When the parser reads in a string, it wants to stick the string on the
8308 * stack and only adjust the stack pointer when it knows how big the
8309 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8310 * of space on top of the stack and stackblocklen returns the length of
8311 * this block. Growstackblock will grow this space by at least one byte,
8312 * possibly moving it (like realloc). Grabstackblock actually allocates the
8313 * part of the block that has been used.
8317 growstackblock(void)
8321 newlen = stacknleft * 2;
8322 if (newlen < stacknleft)
8323 sh_error(bb_msg_memory_exhausted);
8327 if (stacknxt == stackp->space && stackp != &stackbase) {
8328 struct stack_block *oldstackp;
8329 struct stackmark *xmark;
8330 struct stack_block *sp;
8331 struct stack_block *prevstackp;
8337 prevstackp = sp->prev;
8338 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8339 sp = ckrealloc((pointer)sp, grosslen);
8340 sp->prev = prevstackp;
8342 stacknxt = sp->space;
8343 stacknleft = newlen;
8344 sstrend = sp->space + newlen;
8347 * Stack marks pointing to the start of the old block
8348 * must be relocated to point to the new block
8351 while (xmark != NULL && xmark->stackp == oldstackp) {
8352 xmark->stackp = stackp;
8353 xmark->stacknxt = stacknxt;
8354 xmark->stacknleft = stacknleft;
8355 xmark = xmark->marknext;
8359 char *oldspace = stacknxt;
8360 int oldlen = stacknleft;
8361 char *p = stalloc(newlen);
8363 /* free the space we just allocated */
8364 stacknxt = memcpy(p, oldspace, oldlen);
8365 stacknleft += newlen;
8369 static void grabstackblock(size_t len)
8371 len = SHELL_ALIGN(len);
8377 * The following routines are somewhat easier to use than the above.
8378 * The user declares a variable of type STACKSTR, which may be declared
8379 * to be a register. The macro STARTSTACKSTR initializes things. Then
8380 * the user uses the macro STPUTC to add characters to the string. In
8381 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8382 * grown as necessary. When the user is done, she can just leave the
8383 * string there and refer to it using stackblock(). Or she can allocate
8384 * the space for it using grabstackstr(). If it is necessary to allow
8385 * someone else to use the stack temporarily and then continue to grow
8386 * the string, the user should use grabstack to allocate the space, and
8387 * then call ungrabstr(p) to return to the previous mode of operation.
8389 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8390 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8391 * is space for at least one character.
8397 size_t len = stackblocksize();
8398 if (herefd >= 0 && len >= 1024) {
8399 full_write(herefd, stackblock(), len);
8400 return stackblock();
8403 return stackblock() + len;
8407 * Called from CHECKSTRSPACE.
8411 makestrspace(size_t newlen, char *p)
8413 size_t len = p - stacknxt;
8414 size_t size = stackblocksize();
8419 size = stackblocksize();
8421 if (nleft >= newlen)
8425 return stackblock() + len;
8429 stnputs(const char *s, size_t n, char *p)
8431 p = makestrspace(n, p);
8432 p = mempcpy(p, s, n);
8437 stputs(const char *s, char *p)
8439 return stnputs(s, strlen(s), p);
8447 * number(s) Convert a string of digits to an integer.
8448 * is_number(s) Return true if s is a string of digits.
8452 * prefix -- see if pfx is a prefix of string.
8456 prefix(const char *string, const char *pfx)
8459 if (*pfx++ != *string++)
8462 return (char *) string;
8467 * Convert a string of digits to an integer, printing an error message on
8472 number(const char *s)
8476 sh_error(illnum, s);
8482 * Check for a valid number. This should be elsewhere.
8486 is_number(const char *p)
8491 } while (*++p != '\0');
8497 * Produce a possibly single quoted string suitable as input to the shell.
8498 * The return string is allocated on the stack.
8502 single_quote(const char *s) {
8511 len = strchrnul(s, '\'') - s;
8513 q = p = makestrspace(len + 3, p);
8516 q = mempcpy(q, s, len);
8522 len = strspn(s, "'");
8526 q = p = makestrspace(len + 3, p);
8529 q = mempcpy(q, s, len);
8538 return stackblock();
8542 * Like strdup but works with the ash stack.
8546 sstrdup(const char *p)
8548 size_t len = strlen(p) + 1;
8549 return memcpy(stalloc(len), p, len);
8554 calcsize(union node *n)
8558 funcblocksize += nodesize[n->type];
8561 calcsize(n->ncmd.redirect);
8562 calcsize(n->ncmd.args);
8563 calcsize(n->ncmd.assign);
8566 sizenodelist(n->npipe.cmdlist);
8571 calcsize(n->nredir.redirect);
8572 calcsize(n->nredir.n);
8579 calcsize(n->nbinary.ch2);
8580 calcsize(n->nbinary.ch1);
8583 calcsize(n->nif.elsepart);
8584 calcsize(n->nif.ifpart);
8585 calcsize(n->nif.test);
8588 funcstringsize += strlen(n->nfor.var) + 1;
8589 calcsize(n->nfor.body);
8590 calcsize(n->nfor.args);
8593 calcsize(n->ncase.cases);
8594 calcsize(n->ncase.expr);
8597 calcsize(n->nclist.body);
8598 calcsize(n->nclist.pattern);
8599 calcsize(n->nclist.next);
8603 sizenodelist(n->narg.backquote);
8604 funcstringsize += strlen(n->narg.text) + 1;
8605 calcsize(n->narg.next);
8612 calcsize(n->nfile.fname);
8613 calcsize(n->nfile.next);
8617 calcsize(n->ndup.vname);
8618 calcsize(n->ndup.next);
8622 calcsize(n->nhere.doc);
8623 calcsize(n->nhere.next);
8626 calcsize(n->nnot.com);
8633 sizenodelist(struct nodelist *lp)
8636 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8644 copynode(union node *n)
8651 funcblock = (char *) funcblock + nodesize[n->type];
8654 new->ncmd.redirect = copynode(n->ncmd.redirect);
8655 new->ncmd.args = copynode(n->ncmd.args);
8656 new->ncmd.assign = copynode(n->ncmd.assign);
8659 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8660 new->npipe.backgnd = n->npipe.backgnd;
8665 new->nredir.redirect = copynode(n->nredir.redirect);
8666 new->nredir.n = copynode(n->nredir.n);
8673 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8674 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8677 new->nif.elsepart = copynode(n->nif.elsepart);
8678 new->nif.ifpart = copynode(n->nif.ifpart);
8679 new->nif.test = copynode(n->nif.test);
8682 new->nfor.var = nodesavestr(n->nfor.var);
8683 new->nfor.body = copynode(n->nfor.body);
8684 new->nfor.args = copynode(n->nfor.args);
8687 new->ncase.cases = copynode(n->ncase.cases);
8688 new->ncase.expr = copynode(n->ncase.expr);
8691 new->nclist.body = copynode(n->nclist.body);
8692 new->nclist.pattern = copynode(n->nclist.pattern);
8693 new->nclist.next = copynode(n->nclist.next);
8697 new->narg.backquote = copynodelist(n->narg.backquote);
8698 new->narg.text = nodesavestr(n->narg.text);
8699 new->narg.next = copynode(n->narg.next);
8706 new->nfile.fname = copynode(n->nfile.fname);
8707 new->nfile.fd = n->nfile.fd;
8708 new->nfile.next = copynode(n->nfile.next);
8712 new->ndup.vname = copynode(n->ndup.vname);
8713 new->ndup.dupfd = n->ndup.dupfd;
8714 new->ndup.fd = n->ndup.fd;
8715 new->ndup.next = copynode(n->ndup.next);
8719 new->nhere.doc = copynode(n->nhere.doc);
8720 new->nhere.fd = n->nhere.fd;
8721 new->nhere.next = copynode(n->nhere.next);
8724 new->nnot.com = copynode(n->nnot.com);
8727 new->type = n->type;
8732 static struct nodelist *
8733 copynodelist(struct nodelist *lp)
8735 struct nodelist *start;
8736 struct nodelist **lpp;
8741 funcblock = (char *) funcblock +
8742 SHELL_ALIGN(sizeof(struct nodelist));
8743 (*lpp)->n = copynode(lp->n);
8745 lpp = &(*lpp)->next;
8753 nodesavestr(char *s)
8755 char *rtn = funcstring;
8757 funcstring = stpcpy(funcstring, s) + 1;
8763 * Free a parse tree.
8767 freefunc(struct funcnode *f)
8769 if (f && --f->count < 0)
8774 static void options(int);
8775 static void setoption(int, int);
8779 * Process the shell command line arguments.
8783 procargs(int argc, char **argv)
8786 const char *xminusc;
8793 for (i = 0; i < NOPTS; i++)
8799 if (*xargv == NULL) {
8801 sh_error(bb_msg_requires_arg, "-c");
8804 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8808 for (i = 0; i < NOPTS; i++)
8809 if (optlist[i] == 2)
8814 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8819 } else if (!sflag) {
8820 setinputfile(*xargv, 0);
8826 shellparam.p = xargv;
8827 #ifdef CONFIG_ASH_GETOPTS
8828 shellparam.optind = 1;
8829 shellparam.optoff = -1;
8831 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8833 shellparam.nparam++;
8846 setinteractive(iflag);
8851 static void minus_o(char *name, int val)
8856 out1str("Current option settings\n");
8857 for (i = 0; i < NOPTS; i++)
8858 out1fmt("%-16s%s\n", optnames(i),
8859 optlist[i] ? "on" : "off");
8861 for (i = 0; i < NOPTS; i++)
8862 if (equal(name, optnames(i))) {
8866 sh_error("Illegal option -o %s", name);
8871 * Process shell options. The global variable argptr contains a pointer
8872 * to the argument list; we advance it past the options.
8876 options(int cmdline)
8884 while ((p = *argptr) != NULL) {
8886 if ((c = *p++) == '-') {
8888 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8890 /* "-" means turn off -x and -v */
8893 /* "--" means reset params */
8894 else if (*argptr == NULL)
8897 break; /* "-" or "--" terminates options */
8899 } else if (c == '+') {
8905 while ((c = *p++) != '\0') {
8906 if (c == 'c' && cmdline) {
8907 minusc = p; /* command is after shell args*/
8908 } else if (c == 'o') {
8909 minus_o(*argptr, val);
8912 } else if (cmdline && (c == '-')) { // long options
8913 if (strcmp(p, "login") == 0)
8925 setoption(int flag, int val)
8929 for (i = 0; i < NOPTS; i++)
8930 if (optletters(i) == flag) {
8934 sh_error("Illegal option -%c", flag);
8941 * Set the shell parameters.
8945 setparam(char **argv)
8951 for (nparam = 0 ; argv[nparam] ; nparam++);
8952 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8954 *ap++ = savestr(*argv++);
8957 freeparam(&shellparam);
8958 shellparam.malloc = 1;
8959 shellparam.nparam = nparam;
8960 shellparam.p = newparam;
8961 #ifdef CONFIG_ASH_GETOPTS
8962 shellparam.optind = 1;
8963 shellparam.optoff = -1;
8969 * Free the list of positional parameters.
8973 freeparam(volatile struct shparam *param)
8977 if (param->malloc) {
8978 for (ap = param->p ; *ap ; ap++)
8987 * The shift builtin command.
8991 shiftcmd(int argc, char **argv)
8998 n = number(argv[1]);
8999 if (n > shellparam.nparam)
9000 sh_error("can't shift that many");
9002 shellparam.nparam -= n;
9003 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9004 if (shellparam.malloc)
9008 while ((*ap2++ = *ap1++) != NULL);
9009 #ifdef CONFIG_ASH_GETOPTS
9010 shellparam.optind = 1;
9011 shellparam.optoff = -1;
9020 * The set command builtin.
9024 setcmd(int argc, char **argv)
9027 return showvars(nullstr, 0, VUNSET);
9031 if (*argptr != NULL) {
9039 #ifdef CONFIG_ASH_GETOPTS
9041 getoptsreset(const char *value)
9043 shellparam.optind = number(value);
9044 shellparam.optoff = -1;
9048 #ifdef CONFIG_LOCALE_SUPPORT
9049 static void change_lc_all(const char *value)
9051 if (value != 0 && *value != 0)
9052 setlocale(LC_ALL, value);
9055 static void change_lc_ctype(const char *value)
9057 if (value != 0 && *value != 0)
9058 setlocale(LC_CTYPE, value);
9063 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9064 /* Roughly copied from bash.. */
9065 static void change_random(const char *value)
9068 /* "get", generate */
9071 rseed = rseed * 1103515245 + 12345;
9072 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9073 /* set without recursion */
9074 setvar(vrandom.text, buf, VNOFUNC);
9075 vrandom.flags &= ~VNOFUNC;
9078 rseed = strtoul(value, (char **)NULL, 10);
9084 #ifdef CONFIG_ASH_GETOPTS
9086 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9095 if(*param_optind < 1)
9097 optnext = optfirst + *param_optind - 1;
9099 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9102 p = optnext[-1] + *optoff;
9103 if (p == NULL || *p == '\0') {
9104 /* Current word is done, advance */
9106 if (p == NULL || *p != '-' || *++p == '\0') {
9113 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9118 for (q = optstr; *q != c; ) {
9120 if (optstr[0] == ':') {
9123 err |= setvarsafe("OPTARG", s, 0);
9125 fprintf(stderr, "Illegal option -%c\n", c);
9126 (void) unsetvar("OPTARG");
9136 if (*p == '\0' && (p = *optnext) == NULL) {
9137 if (optstr[0] == ':') {
9140 err |= setvarsafe("OPTARG", s, 0);
9143 fprintf(stderr, "No arg for -%c option\n", c);
9144 (void) unsetvar("OPTARG");
9152 err |= setvarsafe("OPTARG", p, 0);
9155 err |= setvarsafe("OPTARG", nullstr, 0);
9158 *optoff = p ? p - *(optnext - 1) : -1;
9159 *param_optind = optnext - optfirst + 1;
9160 fmtstr(s, sizeof(s), "%d", *param_optind);
9161 err |= setvarsafe("OPTIND", s, VNOFUNC);
9164 err |= setvarsafe(optvar, s, 0);
9175 * The getopts builtin. Shellparam.optnext points to the next argument
9176 * to be processed. Shellparam.optptr points to the next character to
9177 * be processed in the current argument. If shellparam.optnext is NULL,
9178 * then it's the first time getopts has been called.
9182 getoptscmd(int argc, char **argv)
9187 sh_error("Usage: getopts optstring var [arg]");
9188 else if (argc == 3) {
9189 optbase = shellparam.p;
9190 if (shellparam.optind > shellparam.nparam + 1) {
9191 shellparam.optind = 1;
9192 shellparam.optoff = -1;
9197 if (shellparam.optind > argc - 2) {
9198 shellparam.optind = 1;
9199 shellparam.optoff = -1;
9203 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9204 &shellparam.optoff);
9206 #endif /* CONFIG_ASH_GETOPTS */
9209 * XXX - should get rid of. have all builtins use getopt(3). the
9210 * library getopt must have the BSD extension static variable "optreset"
9211 * otherwise it can't be used within the shell safely.
9213 * Standard option processing (a la getopt) for builtin routines. The
9214 * only argument that is passed to nextopt is the option string; the
9215 * other arguments are unnecessary. It return the character, or '\0' on
9220 nextopt(const char *optstring)
9226 if ((p = optptr) == NULL || *p == '\0') {
9228 if (p == NULL || *p != '-' || *++p == '\0')
9231 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9235 for (q = optstring ; *q != c ; ) {
9237 sh_error("Illegal option -%c", c);
9242 if (*p == '\0' && (p = *argptr++) == NULL)
9243 sh_error("No arg for -%c option", c);
9255 outstr(const char *p, FILE *file)
9280 outcslow(int c, FILE *dest)
9290 out1fmt(const char *fmt, ...)
9297 r = vprintf(fmt, ap);
9305 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9312 ret = vsnprintf(outbuf, length, fmt, ap);
9324 * Shell command parser.
9327 #define EOFMARKLEN 79
9331 struct heredoc *next; /* next here document in list */
9332 union node *here; /* redirection node */
9333 char *eofmark; /* string indicating end of input */
9334 int striptabs; /* if set, strip leading tabs */
9339 static struct heredoc *heredoclist; /* list of here documents to read */
9342 static union node *list(int);
9343 static union node *andor(void);
9344 static union node *pipeline(void);
9345 static union node *command(void);
9346 static union node *simplecmd(void);
9347 static union node *makename(void);
9348 static void parsefname(void);
9349 static void parseheredoc(void);
9350 static char peektoken(void);
9351 static int readtoken(void);
9352 static int xxreadtoken(void);
9353 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9354 static int noexpand(char *);
9355 static void synexpect(int) ATTRIBUTE_NORETURN;
9356 static void synerror(const char *) ATTRIBUTE_NORETURN;
9357 static void setprompt(int);
9363 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9364 * valid parse tree indicating a blank line.)
9368 parsecmd(int interact)
9373 doprompt = interact;
9375 setprompt(doprompt);
9390 union node *n1, *n2, *n3;
9393 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9394 if (nlflag == 2 && peektoken())
9400 if (tok == TBACKGND) {
9401 if (n2->type == NPIPE) {
9402 n2->npipe.backgnd = 1;
9404 if (n2->type != NREDIR) {
9405 n3 = stalloc(sizeof(struct nredir));
9407 n3->nredir.redirect = NULL;
9410 n2->type = NBACKGND;
9417 n3 = (union node *)stalloc(sizeof (struct nbinary));
9419 n3->nbinary.ch1 = n1;
9420 n3->nbinary.ch2 = n2;
9436 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9444 pungetc(); /* push back EOF on input */
9460 union node *n1, *n2, *n3;
9465 if ((t = readtoken()) == TAND) {
9467 } else if (t == TOR) {
9473 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9475 n3 = (union node *)stalloc(sizeof (struct nbinary));
9477 n3->nbinary.ch1 = n1;
9478 n3->nbinary.ch2 = n2;
9488 union node *n1, *n2, *pipenode;
9489 struct nodelist *lp, *prev;
9493 TRACE(("pipeline: entered\n"));
9494 if (readtoken() == TNOT) {
9496 checkkwd = CHKKWD | CHKALIAS;
9500 if (readtoken() == TPIPE) {
9501 pipenode = (union node *)stalloc(sizeof (struct npipe));
9502 pipenode->type = NPIPE;
9503 pipenode->npipe.backgnd = 0;
9504 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9505 pipenode->npipe.cmdlist = lp;
9509 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9510 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9513 } while (readtoken() == TPIPE);
9519 n2 = (union node *)stalloc(sizeof (struct nnot));
9532 union node *n1, *n2;
9533 union node *ap, **app;
9534 union node *cp, **cpp;
9535 union node *redir, **rpp;
9542 switch (readtoken()) {
9547 n1 = (union node *)stalloc(sizeof (struct nif));
9549 n1->nif.test = list(0);
9550 if (readtoken() != TTHEN)
9552 n1->nif.ifpart = list(0);
9554 while (readtoken() == TELIF) {
9555 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9556 n2 = n2->nif.elsepart;
9558 n2->nif.test = list(0);
9559 if (readtoken() != TTHEN)
9561 n2->nif.ifpart = list(0);
9563 if (lasttoken == TELSE)
9564 n2->nif.elsepart = list(0);
9566 n2->nif.elsepart = NULL;
9574 n1 = (union node *)stalloc(sizeof (struct nbinary));
9575 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9576 n1->nbinary.ch1 = list(0);
9577 if ((got=readtoken()) != TDO) {
9578 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9581 n1->nbinary.ch2 = list(0);
9586 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9587 synerror("Bad for loop variable");
9588 n1 = (union node *)stalloc(sizeof (struct nfor));
9590 n1->nfor.var = wordtext;
9591 checkkwd = CHKKWD | CHKALIAS;
9592 if (readtoken() == TIN) {
9594 while (readtoken() == TWORD) {
9595 n2 = (union node *)stalloc(sizeof (struct narg));
9597 n2->narg.text = wordtext;
9598 n2->narg.backquote = backquotelist;
9600 app = &n2->narg.next;
9604 if (lasttoken != TNL && lasttoken != TSEMI)
9607 n2 = (union node *)stalloc(sizeof (struct narg));
9609 n2->narg.text = (char *)dolatstr;
9610 n2->narg.backquote = NULL;
9611 n2->narg.next = NULL;
9614 * Newline or semicolon here is optional (but note
9615 * that the original Bourne shell only allowed NL).
9617 if (lasttoken != TNL && lasttoken != TSEMI)
9620 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9621 if (readtoken() != TDO)
9623 n1->nfor.body = list(0);
9627 n1 = (union node *)stalloc(sizeof (struct ncase));
9629 if (readtoken() != TWORD)
9631 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9633 n2->narg.text = wordtext;
9634 n2->narg.backquote = backquotelist;
9635 n2->narg.next = NULL;
9637 checkkwd = CHKKWD | CHKALIAS;
9638 } while (readtoken() == TNL);
9639 if (lasttoken != TIN)
9641 cpp = &n1->ncase.cases;
9643 checkkwd = CHKNL | CHKKWD;
9646 if (lasttoken == TLP)
9648 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9650 app = &cp->nclist.pattern;
9652 *app = ap = (union node *)stalloc(sizeof (struct narg));
9654 ap->narg.text = wordtext;
9655 ap->narg.backquote = backquotelist;
9656 if (readtoken() != TPIPE)
9658 app = &ap->narg.next;
9661 ap->narg.next = NULL;
9662 if (lasttoken != TRP)
9664 cp->nclist.body = list(2);
9666 cpp = &cp->nclist.next;
9668 checkkwd = CHKNL | CHKKWD;
9669 if ((t = readtoken()) != TESAC) {
9671 synexpect(TENDCASE);
9679 n1 = (union node *)stalloc(sizeof (struct nredir));
9680 n1->type = NSUBSHELL;
9681 n1->nredir.n = list(0);
9682 n1->nredir.redirect = NULL;
9695 if (readtoken() != t)
9699 /* Now check for redirection which may follow command */
9700 checkkwd = CHKKWD | CHKALIAS;
9702 while (readtoken() == TREDIR) {
9703 *rpp = n2 = redirnode;
9704 rpp = &n2->nfile.next;
9710 if (n1->type != NSUBSHELL) {
9711 n2 = (union node *)stalloc(sizeof (struct nredir));
9716 n1->nredir.redirect = redir;
9725 union node *args, **app;
9726 union node *n = NULL;
9727 union node *vars, **vpp;
9728 union node **rpp, *redir;
9738 savecheckkwd = CHKALIAS;
9740 checkkwd = savecheckkwd;
9741 switch (readtoken()) {
9743 n = (union node *)stalloc(sizeof (struct narg));
9745 n->narg.text = wordtext;
9746 n->narg.backquote = backquotelist;
9747 if (savecheckkwd && isassignment(wordtext)) {
9749 vpp = &n->narg.next;
9752 app = &n->narg.next;
9757 *rpp = n = redirnode;
9758 rpp = &n->nfile.next;
9759 parsefname(); /* read name of redirection file */
9763 args && app == &args->narg.next &&
9766 struct builtincmd *bcmd;
9769 /* We have a function */
9770 if (readtoken() != TRP)
9772 name = n->narg.text;
9774 !goodname(name) || (
9775 (bcmd = find_builtin(name)) &&
9776 IS_BUILTIN_SPECIAL(bcmd)
9779 synerror("Bad function name");
9781 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9782 n->narg.next = command();
9795 n = (union node *)stalloc(sizeof (struct ncmd));
9797 n->ncmd.args = args;
9798 n->ncmd.assign = vars;
9799 n->ncmd.redirect = redir;
9808 n = (union node *)stalloc(sizeof (struct narg));
9810 n->narg.next = NULL;
9811 n->narg.text = wordtext;
9812 n->narg.backquote = backquotelist;
9816 void fixredir(union node *n, const char *text, int err)
9818 TRACE(("Fix redir %s %d\n", text, err));
9820 n->ndup.vname = NULL;
9822 if (is_digit(text[0]) && text[1] == '\0')
9823 n->ndup.dupfd = digit_val(text[0]);
9824 else if (text[0] == '-' && text[1] == '\0')
9829 synerror("Bad fd number");
9831 n->ndup.vname = makename();
9839 union node *n = redirnode;
9841 if (readtoken() != TWORD)
9843 if (n->type == NHERE) {
9844 struct heredoc *here = heredoc;
9850 TRACE(("Here document %d\n", n->type));
9851 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9852 synerror("Illegal eof marker for << redirection");
9853 rmescapes(wordtext);
9854 here->eofmark = wordtext;
9856 if (heredoclist == NULL)
9859 for (p = heredoclist ; p->next ; p = p->next);
9862 } else if (n->type == NTOFD || n->type == NFROMFD) {
9863 fixredir(n, wordtext, 0);
9865 n->nfile.fname = makename();
9871 * Input any here documents.
9877 struct heredoc *here;
9887 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9888 here->eofmark, here->striptabs);
9889 n = (union node *)stalloc(sizeof (struct narg));
9890 n->narg.type = NARG;
9891 n->narg.next = NULL;
9892 n->narg.text = wordtext;
9893 n->narg.backquote = backquotelist;
9894 here->here->nhere.doc = n;
9899 static char peektoken(void)
9905 return tokname_array[t][0];
9913 int alreadyseen = tokpushback;
9916 #ifdef CONFIG_ASH_ALIAS
9925 if (checkkwd & CHKNL) {
9932 if (t != TWORD || quoteflag) {
9937 * check for keywords
9939 if (checkkwd & CHKKWD) {
9940 const char *const *pp;
9942 if ((pp = findkwd(wordtext))) {
9943 lasttoken = t = pp - tokname_array;
9944 TRACE(("keyword %s recognized\n", tokname(t)));
9949 if (checkkwd & CHKALIAS) {
9950 #ifdef CONFIG_ASH_ALIAS
9952 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9954 pushstring(ap->val, ap);
9964 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9966 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9973 * Read the next input token.
9974 * If the token is a word, we set backquotelist to the list of cmds in
9975 * backquotes. We set quoteflag to true if any part of the word was
9977 * If the token is TREDIR, then we set redirnode to a structure containing
9979 * In all cases, the variable startlinno is set to the number of the line
9980 * on which the token starts.
9982 * [Change comment: here documents and internal procedures]
9983 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9984 * word parsing code into a separate routine. In this case, readtoken
9985 * doesn't need to have any internal procedures, but parseword does.
9986 * We could also make parseoperator in essence the main routine, and
9987 * have parseword (readtoken1?) handle both words and redirection.]
9990 #define NEW_xxreadtoken
9991 #ifdef NEW_xxreadtoken
9993 /* singles must be first! */
9994 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9996 static const char xxreadtoken_tokens[] = {
9997 TNL, TLP, TRP, /* only single occurrence allowed */
9998 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9999 TEOF, /* corresponds to trailing nul */
10000 TAND, TOR, TENDCASE, /* if double occurrence */
10003 #define xxreadtoken_doubles \
10004 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10005 #define xxreadtoken_singles \
10006 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10008 static int xxreadtoken(void)
10019 startlinno = plinno;
10020 for (;;) { /* until token or start of word found */
10023 if ((c != ' ') && (c != '\t')
10024 #ifdef CONFIG_ASH_ALIAS
10029 while ((c = pgetc()) != '\n' && c != PEOF);
10031 } else if (c == '\\') {
10032 if (pgetc() != '\n') {
10036 startlinno = ++plinno;
10041 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10046 needprompt = doprompt;
10049 p = strchr(xxreadtoken_chars, c);
10052 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10055 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10056 if (pgetc() == *p) { /* double occurrence? */
10057 p += xxreadtoken_doubles + 1;
10064 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10072 #define RETURN(token) return lasttoken = token
10086 startlinno = plinno;
10087 for (;;) { /* until token or start of word found */
10090 case ' ': case '\t':
10091 #ifdef CONFIG_ASH_ALIAS
10096 while ((c = pgetc()) != '\n' && c != PEOF);
10100 if (pgetc() == '\n') {
10101 startlinno = ++plinno;
10110 needprompt = doprompt;
10115 if (pgetc() == '&')
10120 if (pgetc() == '|')
10125 if (pgetc() == ';')
10138 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10141 #endif /* NEW_xxreadtoken */
10145 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10146 * is not NULL, read a here document. In the latter case, eofmark is the
10147 * word which marks the end of the document and striptabs is true if
10148 * leading tabs should be stripped from the document. The argument firstc
10149 * is the first character of the input token or document.
10151 * Because C does not have internal subroutines, I have simulated them
10152 * using goto's to implement the subroutine linkage. The following macros
10153 * will run code that appears at the end of readtoken1.
10156 #define CHECKEND() {goto checkend; checkend_return:;}
10157 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10158 #define PARSESUB() {goto parsesub; parsesub_return:;}
10159 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10160 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10161 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10164 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10169 char line[EOFMARKLEN + 1];
10170 struct nodelist *bqlist = 0;
10173 int varnest = 0; /* levels of variables expansion */
10174 int arinest = 0; /* levels of arithmetic expansion */
10175 int parenlevel = 0; /* levels of parens in arithmetic */
10176 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10178 int prevsyntax = 0; /* syntax before arithmetic */
10180 /* Avoid longjmp clobbering */
10186 (void) &parenlevel;
10189 (void) &prevsyntax;
10193 startlinno = plinno;
10195 if (syntax == DQSYNTAX)
10204 STARTSTACKSTR(out);
10205 loop: { /* for each line, until end of word */
10206 CHECKEND(); /* set c to PEOF if at end of here document */
10207 for (;;) { /* until end of line or end of word */
10208 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10209 switch(SIT(c, syntax)) {
10210 case CNL: /* '\n' */
10211 if (syntax == BASESYNTAX)
10212 goto endword; /* exit outer loop */
10218 goto loop; /* continue outer loop */
10223 if (eofmark == NULL || dblquote)
10224 USTPUTC(CTLESC, out);
10227 case CBACK: /* backslash */
10230 USTPUTC(CTLESC, out);
10231 USTPUTC('\\', out);
10233 } else if (c == '\n') {
10238 c != '\\' && c != '`' &&
10243 USTPUTC(CTLESC, out);
10244 USTPUTC('\\', out);
10246 if (SIT(c, SQSYNTAX) == CCTL)
10247 USTPUTC(CTLESC, out);
10255 if (eofmark == NULL) {
10256 USTPUTC(CTLQUOTEMARK, out);
10264 if (eofmark != NULL && arinest == 0 &&
10268 if (dqvarnest == 0) {
10269 syntax = BASESYNTAX;
10276 case CVAR: /* '$' */
10277 PARSESUB(); /* parse substitution */
10279 case CENDVAR: /* '}' */
10282 if (dqvarnest > 0) {
10285 USTPUTC(CTLENDVAR, out);
10290 #ifdef CONFIG_ASH_MATH_SUPPORT
10291 case CLP: /* '(' in arithmetic */
10295 case CRP: /* ')' in arithmetic */
10296 if (parenlevel > 0) {
10300 if (pgetc() == ')') {
10301 if (--arinest == 0) {
10302 USTPUTC(CTLENDARI, out);
10303 syntax = prevsyntax;
10304 if (syntax == DQSYNTAX)
10312 * unbalanced parens
10313 * (don't 2nd guess - no error)
10321 case CBQUOTE: /* '`' */
10325 goto endword; /* exit outer loop */
10330 goto endword; /* exit outer loop */
10331 #ifdef CONFIG_ASH_ALIAS
10341 #ifdef CONFIG_ASH_MATH_SUPPORT
10342 if (syntax == ARISYNTAX)
10343 synerror("Missing '))'");
10345 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10346 synerror("Unterminated quoted string");
10347 if (varnest != 0) {
10348 startlinno = plinno;
10350 synerror("Missing '}'");
10352 USTPUTC('\0', out);
10353 len = out - (char *)stackblock();
10354 out = stackblock();
10355 if (eofmark == NULL) {
10356 if ((c == '>' || c == '<')
10359 && (*out == '\0' || is_digit(*out))) {
10361 return lasttoken = TREDIR;
10366 quoteflag = quotef;
10367 backquotelist = bqlist;
10368 grabstackblock(len);
10370 return lasttoken = TWORD;
10371 /* end of readtoken routine */
10376 * Check to see whether we are at the end of the here document. When this
10377 * is called, c is set to the first character of the next input line. If
10378 * we are at the end of the here document, this routine sets the c to PEOF.
10383 #ifdef CONFIG_ASH_ALIAS
10389 while (c == '\t') {
10393 if (c == *eofmark) {
10394 if (pfgets(line, sizeof line) != NULL) {
10398 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10399 if (*p == '\n' && *q == '\0') {
10402 needprompt = doprompt;
10404 pushstring(line, NULL);
10409 goto checkend_return;
10414 * Parse a redirection operator. The variable "out" points to a string
10415 * specifying the fd to be redirected. The variable "c" contains the
10416 * first character of the redirection operator.
10423 np = (union node *)stalloc(sizeof (struct nfile));
10428 np->type = NAPPEND;
10430 np->type = NCLOBBER;
10437 } else { /* c == '<' */
10439 switch (c = pgetc()) {
10441 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10442 np = (union node *)stalloc(sizeof (struct nhere));
10446 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10447 heredoc->here = np;
10448 if ((c = pgetc()) == '-') {
10449 heredoc->striptabs = 1;
10451 heredoc->striptabs = 0;
10457 np->type = NFROMFD;
10461 np->type = NFROMTO;
10471 np->nfile.fd = digit_val(fd);
10473 goto parseredir_return;
10478 * Parse a substitution. At this point, we have read the dollar sign
10479 * and nothing else.
10487 static const char types[] = "}-+?=";
10491 c <= PEOA_OR_PEOF ||
10492 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10496 } else if (c == '(') { /* $(command) or $((arith)) */
10497 if (pgetc() == '(') {
10498 #ifdef CONFIG_ASH_MATH_SUPPORT
10501 synerror("We unsupport $((arith))");
10508 USTPUTC(CTLVAR, out);
10509 typeloc = out - (char *)stackblock();
10510 USTPUTC(VSNORMAL, out);
10511 subtype = VSNORMAL;
10515 if ((c = pgetc()) == '}')
10518 subtype = VSLENGTH;
10523 if (c > PEOA_OR_PEOF && is_name(c)) {
10527 } while (c > PEOA_OR_PEOF && is_in_name(c));
10528 } else if (is_digit(c)) {
10532 } while (is_digit(c));
10534 else if (is_special(c)) {
10539 badsub: synerror("Bad substitution");
10543 if (subtype == 0) {
10550 p = strchr(types, c);
10553 subtype = p - types + VSNORMAL;
10559 subtype = c == '#' ? VSTRIMLEFT :
10572 if (dblquote || arinest)
10574 *((char *)stackblock() + typeloc) = subtype | flags;
10575 if (subtype != VSNORMAL) {
10577 if (dblquote || arinest) {
10582 goto parsesub_return;
10587 * Called to parse command substitutions. Newstyle is set if the command
10588 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10589 * list of commands (passed by reference), and savelen is the number of
10590 * characters on the top of the stack which must be preserved.
10594 struct nodelist **nlpp;
10597 char *volatile str;
10598 struct jmploc jmploc;
10599 struct jmploc *volatile savehandler;
10601 int saveprompt = 0;
10603 (void) &saveprompt;
10606 savepbq = parsebackquote;
10607 if (setjmp(jmploc.loc)) {
10610 parsebackquote = 0;
10611 handler = savehandler;
10612 longjmp(handler->loc, 1);
10616 savelen = out - (char *)stackblock();
10618 str = ckmalloc(savelen);
10619 memcpy(str, stackblock(), savelen);
10621 savehandler = handler;
10625 /* We must read until the closing backquote, giving special
10626 treatment to some slashes, and then push the string and
10627 reread it as input, interpreting it normally. */
10634 STARTSTACKSTR(pout);
10639 switch (pc = pgetc()) {
10644 if ((pc = pgetc()) == '\n') {
10649 * If eating a newline, avoid putting
10650 * the newline into the new character
10651 * stream (via the STPUTC after the
10656 if (pc != '\\' && pc != '`' && pc != '$'
10657 && (!dblquote || pc != '"'))
10658 STPUTC('\\', pout);
10659 if (pc > PEOA_OR_PEOF) {
10665 #ifdef CONFIG_ASH_ALIAS
10668 startlinno = plinno;
10669 synerror("EOF in backquote substitution");
10673 needprompt = doprompt;
10682 STPUTC('\0', pout);
10683 psavelen = pout - (char *)stackblock();
10684 if (psavelen > 0) {
10685 pstr = grabstackstr(pout);
10686 setinputstring(pstr);
10691 nlpp = &(*nlpp)->next;
10692 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10693 (*nlpp)->next = NULL;
10694 parsebackquote = oldstyle;
10697 saveprompt = doprompt;
10704 doprompt = saveprompt;
10706 if (readtoken() != TRP)
10713 * Start reading from old file again, ignoring any pushed back
10714 * tokens left from the backquote parsing
10719 while (stackblocksize() <= savelen)
10721 STARTSTACKSTR(out);
10723 memcpy(out, str, savelen);
10724 STADJUST(savelen, out);
10730 parsebackquote = savepbq;
10731 handler = savehandler;
10732 if (arinest || dblquote)
10733 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10735 USTPUTC(CTLBACKQ, out);
10737 goto parsebackq_oldreturn;
10739 goto parsebackq_newreturn;
10742 #ifdef CONFIG_ASH_MATH_SUPPORT
10744 * Parse an arithmetic expansion (indicate start of one and set state)
10748 if (++arinest == 1) {
10749 prevsyntax = syntax;
10750 syntax = ARISYNTAX;
10751 USTPUTC(CTLARI, out);
10758 * we collapse embedded arithmetic expansion to
10759 * parenthesis, which should be equivalent
10763 goto parsearith_return;
10767 } /* end of readtoken */
10772 * Returns true if the text contains nothing to expand (no dollar signs
10777 noexpand(char *text)
10783 while ((c = *p++) != '\0') {
10784 if (c == CTLQUOTEMARK)
10788 else if (SIT(c, BASESYNTAX) == CCTL)
10796 * Return of a legal variable name (a letter or underscore followed by zero or
10797 * more letters, underscores, and digits).
10801 endofname(const char *name)
10809 if (! is_in_name(*p))
10817 * Called when an unexpected token is read during the parse. The argument
10818 * is the token that is expected, or -1 if more than one type of token can
10819 * occur at this point.
10822 static void synexpect(int token)
10827 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10829 sprintf(msg + l, " (expecting %s)", tokname(token));
10835 synerror(const char *msg)
10837 sh_error("Syntax error: %s", msg);
10843 * called by editline -- any expansions to the prompt
10844 * should be added here.
10847 #ifdef CONFIG_ASH_EXPAND_PRMT
10848 static const char *
10849 expandstr(const char *ps)
10853 /* XXX Fix (char *) cast. */
10854 setinputstring((char *)ps);
10855 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10858 n.narg.type = NARG;
10859 n.narg.next = NULL;
10860 n.narg.text = wordtext;
10861 n.narg.backquote = backquotelist;
10863 expandarg(&n, NULL, 0);
10864 return stackblock();
10868 static void setprompt(int whichprompt)
10870 const char *prompt;
10871 #ifdef CONFIG_ASH_EXPAND_PRMT
10872 struct stackmark smark;
10877 switch (whichprompt) {
10887 #ifdef CONFIG_ASH_EXPAND_PRMT
10888 setstackmark(&smark);
10889 stalloc(stackblocksize());
10891 putprompt(expandstr(prompt));
10892 #ifdef CONFIG_ASH_EXPAND_PRMT
10893 popstackmark(&smark);
10898 static const char *const *findkwd(const char *s)
10900 return bsearch(s, tokname_array + KWDOFFSET,
10901 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10902 sizeof(const char *), pstrcmp);
10908 * Code for dealing with input/output redirection.
10911 #define EMPTY -2 /* marks an unused slot in redirtab */
10913 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10915 # define PIPESIZE PIPE_BUF
10919 * Open a file in noclobber mode.
10920 * The code was copied from bash.
10922 static int noclobberopen(const char *fname)
10925 struct stat finfo, finfo2;
10928 * If the file exists and is a regular file, return an error
10931 r = stat(fname, &finfo);
10932 if (r == 0 && S_ISREG(finfo.st_mode)) {
10938 * If the file was not present (r != 0), make sure we open it
10939 * exclusively so that if it is created before we open it, our open
10940 * will fail. Make sure that we do not truncate an existing file.
10941 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10942 * file was not a regular file, we leave O_EXCL off.
10945 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10946 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10948 /* If the open failed, return the file descriptor right away. */
10953 * OK, the open succeeded, but the file may have been changed from a
10954 * non-regular file to a regular file between the stat and the open.
10955 * We are assuming that the O_EXCL open handles the case where FILENAME
10956 * did not exist and is symlinked to an existing file between the stat
10961 * If we can open it and fstat the file descriptor, and neither check
10962 * revealed that it was a regular file, and the file has not been
10963 * replaced, return the file descriptor.
10965 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10966 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10969 /* The file has been replaced. badness. */
10976 * Handle here documents. Normally we fork off a process to write the
10977 * data to a pipe. If the document is short, we can stuff the data in
10978 * the pipe without forking.
10981 static int openhere(union node *redir)
10987 sh_error("Pipe call failed");
10988 if (redir->type == NHERE) {
10989 len = strlen(redir->nhere.doc->narg.text);
10990 if (len <= PIPESIZE) {
10991 full_write(pip[1], redir->nhere.doc->narg.text, len);
10995 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10997 signal(SIGINT, SIG_IGN);
10998 signal(SIGQUIT, SIG_IGN);
10999 signal(SIGHUP, SIG_IGN);
11001 signal(SIGTSTP, SIG_IGN);
11003 signal(SIGPIPE, SIG_DFL);
11004 if (redir->type == NHERE)
11005 full_write(pip[1], redir->nhere.doc->narg.text, len);
11007 expandhere(redir->nhere.doc, pip[1]);
11016 openredirect(union node *redir)
11021 switch (redir->nfile.type) {
11023 fname = redir->nfile.expfname;
11024 if ((f = open(fname, O_RDONLY)) < 0)
11028 fname = redir->nfile.expfname;
11029 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11033 /* Take care of noclobber mode. */
11035 fname = redir->nfile.expfname;
11036 if ((f = noclobberopen(fname)) < 0)
11042 fname = redir->nfile.expfname;
11043 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11047 fname = redir->nfile.expfname;
11048 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11055 /* Fall through to eliminate warning. */
11062 f = openhere(redir);
11068 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11070 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11073 static void dupredirect(union node *redir, int f)
11075 int fd = redir->nfile.fd;
11077 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11078 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11079 copyfd(redir->ndup.dupfd, fd);
11092 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11093 * old file descriptors are stashed away so that the redirection can be
11094 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11095 * standard output, and the standard error if it becomes a duplicate of
11096 * stdout, is saved in memory.
11100 redirect(union node *redir, int flags)
11103 struct redirtab *sv;
11114 if (flags & REDIR_PUSH) {
11115 struct redirtab *q;
11116 q = ckmalloc(sizeof (struct redirtab));
11117 q->next = redirlist;
11119 q->nullredirs = nullredirs - 1;
11120 for (i = 0 ; i < 10 ; i++)
11121 q->renamed[i] = EMPTY;
11128 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11129 n->ndup.dupfd == fd)
11130 continue; /* redirect from/to same file descriptor */
11132 newfd = openredirect(n);
11135 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11136 i = fcntl(fd, F_DUPFD, 10);
11143 sh_error("%d: %m", fd);
11153 dupredirect(n, newfd);
11154 } while ((n = n->nfile.next));
11156 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11157 preverrout_fd = sv->renamed[2];
11162 * Undo the effects of the last redirection.
11168 struct redirtab *rp;
11171 if (--nullredirs >= 0)
11175 for (i = 0 ; i < 10 ; i++) {
11176 if (rp->renamed[i] != EMPTY) {
11179 copyfd(rp->renamed[i], i);
11181 close(rp->renamed[i]);
11184 redirlist = rp->next;
11185 nullredirs = rp->nullredirs;
11191 * Undo all redirections. Called on error or interrupt.
11195 * Discard all saved file descriptors.
11199 clearredir(int drop)
11211 * Copy a file descriptor to be >= to. Returns -1
11212 * if the source file descriptor is closed, EMPTY if there are no unused
11213 * file descriptors left.
11217 copyfd(int from, int to)
11221 newfd = fcntl(from, F_DUPFD, to);
11223 if (errno == EMFILE)
11226 sh_error("%d: %m", from);
11233 redirectsafe(union node *redir, int flags)
11236 volatile int saveint;
11237 struct jmploc *volatile savehandler = handler;
11238 struct jmploc jmploc;
11241 if (!(err = setjmp(jmploc.loc) * 2)) {
11243 redirect(redir, flags);
11245 handler = savehandler;
11246 if (err && exception != EXERROR)
11247 longjmp(handler->loc, 1);
11248 RESTOREINT(saveint);
11255 static void shtree(union node *, int, char *, FILE*);
11256 static void shcmd(union node *, FILE *);
11257 static void sharg(union node *, FILE *);
11258 static void indent(int, char *, FILE *);
11259 static void trstring(char *);
11263 showtree(union node *n)
11265 trputs("showtree called\n");
11266 shtree(n, 1, NULL, stdout);
11271 shtree(union node *n, int ind, char *pfx, FILE *fp)
11273 struct nodelist *lp;
11279 indent(ind, pfx, fp);
11290 shtree(n->nbinary.ch1, ind, NULL, fp);
11293 shtree(n->nbinary.ch2, ind, NULL, fp);
11301 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11306 if (n->npipe.backgnd)
11312 fprintf(fp, "<node type %d>", n->type);
11321 shcmd(union node *cmd, FILE *fp)
11329 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11335 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11338 switch (np->nfile.type) {
11339 case NTO: s = ">"; dftfd = 1; break;
11340 case NCLOBBER: s = ">|"; dftfd = 1; break;
11341 case NAPPEND: s = ">>"; dftfd = 1; break;
11342 case NTOFD: s = ">&"; dftfd = 1; break;
11343 case NFROM: s = "<"; dftfd = 0; break;
11344 case NFROMFD: s = "<&"; dftfd = 0; break;
11345 case NFROMTO: s = "<>"; dftfd = 0; break;
11346 default: s = "*error*"; dftfd = 0; break;
11348 if (np->nfile.fd != dftfd)
11349 fprintf(fp, "%d", np->nfile.fd);
11351 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11352 fprintf(fp, "%d", np->ndup.dupfd);
11354 sharg(np->nfile.fname, fp);
11363 sharg(union node *arg, FILE *fp)
11366 struct nodelist *bqlist;
11369 if (arg->type != NARG) {
11370 out1fmt("<node type %d>\n", arg->type);
11373 bqlist = arg->narg.backquote;
11374 for (p = arg->narg.text ; *p ; p++) {
11383 if (subtype == VSLENGTH)
11389 if (subtype & VSNUL)
11392 switch (subtype & VSTYPE) {
11411 case VSTRIMLEFTMAX:
11418 case VSTRIMRIGHTMAX:
11425 out1fmt("<subtype %d>", subtype);
11432 case CTLBACKQ|CTLQUOTE:
11435 shtree(bqlist->n, -1, NULL, fp);
11447 indent(int amount, char *pfx, FILE *fp)
11451 for (i = 0 ; i < amount ; i++) {
11452 if (pfx && i == amount - 1)
11473 putc(c, tracefile);
11477 trace(const char *fmt, ...)
11484 (void) vfprintf(tracefile, fmt, va);
11489 tracev(const char *fmt, va_list va)
11493 (void) vfprintf(tracefile, fmt, va);
11498 trputs(const char *s)
11502 fputs(s, tracefile);
11514 putc('"', tracefile);
11515 for (p = s ; *p ; p++) {
11517 case '\n': c = 'n'; goto backslash;
11518 case '\t': c = 't'; goto backslash;
11519 case '\r': c = 'r'; goto backslash;
11520 case '"': c = '"'; goto backslash;
11521 case '\\': c = '\\'; goto backslash;
11522 case CTLESC: c = 'e'; goto backslash;
11523 case CTLVAR: c = 'v'; goto backslash;
11524 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11525 case CTLBACKQ: c = 'q'; goto backslash;
11526 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11527 backslash: putc('\\', tracefile);
11528 putc(c, tracefile);
11531 if (*p >= ' ' && *p <= '~')
11532 putc(*p, tracefile);
11534 putc('\\', tracefile);
11535 putc(*p >> 6 & 03, tracefile);
11536 putc(*p >> 3 & 07, tracefile);
11537 putc(*p & 07, tracefile);
11542 putc('"', tracefile);
11554 putc(' ', tracefile);
11556 putc('\n', tracefile);
11572 /* leave open because libedit might be using it */
11575 scopy("./trace", s);
11577 if (!freopen(s, "a", tracefile)) {
11578 fprintf(stderr, "Can't re-open %s\n", s);
11583 if ((tracefile = fopen(s, "a")) == NULL) {
11584 fprintf(stderr, "Can't open %s\n", s);
11590 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11591 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11593 setlinebuf(tracefile);
11594 fputs("\nTracing started.\n", tracefile);
11602 * Sigmode records the current value of the signal handlers for the various
11603 * modes. A value of zero means that the current handler is not known.
11604 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11607 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11608 #define S_CATCH 2 /* signal is caught */
11609 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11610 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11611 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11616 * The trap builtin.
11620 trapcmd(int argc, char **argv)
11629 for (signo = 0 ; signo < NSIG ; signo++) {
11630 if (trap[signo] != NULL) {
11633 sn = get_signame(signo);
11634 out1fmt("trap -- %s %s\n",
11635 single_quote(trap[signo]), sn);
11645 if ((signo = get_signum(*ap)) < 0)
11646 sh_error("%s: bad trap", *ap);
11649 if (action[0] == '-' && action[1] == '\0')
11652 action = savestr(action);
11655 ckfree(trap[signo]);
11656 trap[signo] = action;
11667 * Clear traps on a fork.
11675 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11676 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11680 if (tp != &trap[0])
11681 setsignal(tp - trap);
11689 * Set the signal handler for the specified signal. The routine figures
11690 * out what it should be set to.
11694 setsignal(int signo)
11698 struct sigaction act;
11700 if ((t = trap[signo]) == NULL)
11702 else if (*t != '\0')
11706 if (rootshell && action == S_DFL) {
11709 if (iflag || minusc || sflag == 0)
11732 t = &sigmode[signo - 1];
11736 * current setting unknown
11738 if (sigaction(signo, 0, &act) == -1) {
11740 * Pretend it worked; maybe we should give a warning
11741 * here, but other shells don't. We don't alter
11742 * sigmode, so that we retry every time.
11746 if (act.sa_handler == SIG_IGN) {
11747 if (mflag && (signo == SIGTSTP ||
11748 signo == SIGTTIN || signo == SIGTTOU)) {
11749 tsig = S_IGN; /* don't hard ignore these */
11753 tsig = S_RESET; /* force to be set */
11756 if (tsig == S_HARD_IGN || tsig == action)
11760 act.sa_handler = onsig;
11763 act.sa_handler = SIG_IGN;
11766 act.sa_handler = SIG_DFL;
11770 sigfillset(&act.sa_mask);
11771 sigaction(signo, &act, 0);
11779 ignoresig(int signo)
11781 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11782 signal(signo, SIG_IGN);
11784 sigmode[signo - 1] = S_HARD_IGN;
11795 gotsig[signo - 1] = 1;
11796 pendingsigs = signo;
11798 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11807 * Called to execute a trap. Perhaps we should avoid entering new trap
11808 * handlers while we are executing a trap handler.
11820 savestatus = exitstatus;
11824 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11832 skip = evalstring(p, SKIPEVAL);
11833 exitstatus = savestatus;
11843 * Controls whether the shell is interactive or not.
11847 setinteractive(int on)
11849 static int is_interactive;
11851 if (++on == is_interactive)
11853 is_interactive = on;
11855 setsignal(SIGQUIT);
11856 setsignal(SIGTERM);
11857 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11858 if(is_interactive > 1) {
11859 /* Looks like they want an interactive shell */
11860 static int do_banner;
11864 "\n\n%s Built-in shell (ash)\n"
11865 "Enter 'help' for a list of built-in commands.\n\n",
11874 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11875 /*** List the available builtins ***/
11877 static int helpcmd(int argc, char **argv)
11881 out1fmt("\nBuilt-in commands:\n-------------------\n");
11882 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11883 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11884 builtincmd[i].name + 1);
11890 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11892 extern const struct BB_applet applets[];
11893 extern const size_t NUM_APPLETS;
11895 for (i = 0; i < NUM_APPLETS; i++) {
11897 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11906 return EXIT_SUCCESS;
11908 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11911 * Called to exit the shell.
11921 status = exitstatus;
11922 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11923 if (setjmp(loc.loc)) {
11924 if (exception == EXEXIT)
11929 if ((p = trap[0])) {
11935 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11936 if (iflag && rootshell) {
11937 const char *hp = lookupvar("HISTFILE");
11940 save_history ( hp );
11950 static struct var *vartab[VTABSIZE];
11952 static int vpcmp(const void *, const void *);
11953 static struct var **findvar(struct var **, const char *);
11956 * Initialize the variable symbol tables and import the environment
11960 #ifdef CONFIG_ASH_GETOPTS
11962 * Safe version of setvar, returns 1 on success 0 on failure.
11966 setvarsafe(const char *name, const char *val, int flags)
11969 volatile int saveint;
11970 struct jmploc *volatile savehandler = handler;
11971 struct jmploc jmploc;
11974 if (setjmp(jmploc.loc))
11978 setvar(name, val, flags);
11981 handler = savehandler;
11982 RESTOREINT(saveint);
11988 * Set the value of a variable. The flags argument is ored with the
11989 * flags of the variable. If val is NULL, the variable is unset.
11993 setvar(const char *name, const char *val, int flags)
12000 q = endofname(name);
12001 p = strchrnul(q, '=');
12002 namelen = p - name;
12003 if (!namelen || p != q)
12004 sh_error("%.*s: bad variable name", namelen, name);
12009 vallen = strlen(val);
12012 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12015 p = mempcpy(p, val, vallen);
12018 setvareq(nameeq, flags | VNOSAVE);
12024 * Same as setvar except that the variable and value are passed in
12025 * the first argument as name=value. Since the first argument will
12026 * be actually stored in the table, it should not be a string that
12028 * Called with interrupts off.
12032 setvareq(char *s, int flags)
12034 struct var *vp, **vpp;
12037 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12038 vp = *findvar(vpp, s);
12040 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12043 if (flags & VNOSAVE)
12046 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12049 if (flags & VNOSET)
12052 if (vp->func && (flags & VNOFUNC) == 0)
12053 (*vp->func)(strchrnul(s, '=') + 1);
12055 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12058 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12060 if (flags & VNOSET)
12063 vp = ckmalloc(sizeof (*vp));
12068 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12076 * Process a linked list of variable assignments.
12080 listsetvar(struct strlist *list_set_var, int flags)
12082 struct strlist *lp = list_set_var;
12088 setvareq(lp->text, flags);
12089 } while ((lp = lp->next));
12095 * Find the value of a variable. Returns NULL if not set.
12099 lookupvar(const char *name)
12103 if ((v = *findvar(hashvar(name), name))) {
12106 * Dynamic variables are implemented roughly the same way they are
12107 * in bash. Namely, they're "special" so long as they aren't unset.
12108 * As soon as they're unset, they're no longer dynamic, and dynamic
12109 * lookup will no longer happen at that point. -- PFM.
12111 if((v->flags & VDYNAMIC))
12114 if(!(v->flags & VUNSET))
12115 return strchrnul(v->text, '=') + 1;
12123 * Search the environment of a builtin command.
12127 bltinlookup(const char *name)
12129 struct strlist *sp;
12131 for (sp = cmdenviron ; sp ; sp = sp->next) {
12132 if (varequal(sp->text, name))
12133 return strchrnul(sp->text, '=') + 1;
12135 return lookupvar(name);
12140 * Generate a list of variables satisfying the given conditions.
12144 listvars(int on, int off, char ***end)
12155 for (vp = *vpp ; vp ; vp = vp->next)
12156 if ((vp->flags & mask) == on) {
12157 if (ep == stackstrend())
12158 ep = growstackstr();
12159 *ep++ = (char *) vp->text;
12161 } while (++vpp < vartab + VTABSIZE);
12162 if (ep == stackstrend())
12163 ep = growstackstr();
12167 return grabstackstr(ep);
12172 * POSIX requires that 'set' (but not export or readonly) output the
12173 * variables in lexicographic order - by the locale's collating order (sigh).
12174 * Maybe we could keep them in an ordered balanced binary tree
12175 * instead of hashed lists.
12176 * For now just roll 'em through qsort for printing...
12180 showvars(const char *sep_prefix, int on, int off)
12183 char **ep, **epend;
12185 ep = listvars(on, off, &epend);
12186 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12188 sep = *sep_prefix ? spcstr : sep_prefix;
12190 for (; ep < epend; ep++) {
12194 p = strchrnul(*ep, '=');
12197 q = single_quote(++p);
12199 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12208 * The export and readonly commands.
12212 exportcmd(int argc, char **argv)
12218 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12221 notp = nextopt("p") - 'p';
12222 if (notp && ((name = *(aptr = argptr)))) {
12224 if ((p = strchr(name, '=')) != NULL) {
12227 if ((vp = *findvar(hashvar(name), name))) {
12232 setvar(name, p, flag);
12233 } while ((name = *++aptr) != NULL);
12235 showvars(argv[0], flag, 0);
12242 * Make a variable a local variable. When a variable is made local, it's
12243 * value and flags are saved in a localvar structure. The saved values
12244 * will be restored when the shell function returns. We handle the name
12245 * "-" as a special case.
12248 static void mklocal(char *name)
12250 struct localvar *lvp;
12255 lvp = ckmalloc(sizeof (struct localvar));
12256 if (name[0] == '-' && name[1] == '\0') {
12258 p = ckmalloc(sizeof(optlist));
12259 lvp->text = memcpy(p, optlist, sizeof(optlist));
12264 vpp = hashvar(name);
12265 vp = *findvar(vpp, name);
12266 eq = strchr(name, '=');
12269 setvareq(name, VSTRFIXED);
12271 setvar(name, NULL, VSTRFIXED);
12272 vp = *vpp; /* the new variable */
12273 lvp->flags = VUNSET;
12275 lvp->text = vp->text;
12276 lvp->flags = vp->flags;
12277 vp->flags |= VSTRFIXED|VTEXTFIXED;
12283 lvp->next = localvars;
12289 * The "local" command.
12293 localcmd(int argc, char **argv)
12298 while ((name = *argv++) != NULL) {
12306 * Called after a function returns.
12307 * Interrupts must be off.
12313 struct localvar *lvp;
12316 while ((lvp = localvars) != NULL) {
12317 localvars = lvp->next;
12319 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12320 if (vp == NULL) { /* $- saved */
12321 memcpy(optlist, lvp->text, sizeof(optlist));
12324 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12325 unsetvar(vp->text);
12328 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12329 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12331 vp->flags = lvp->flags;
12332 vp->text = lvp->text;
12340 * The unset builtin command. We unset the function before we unset the
12341 * variable to allow a function to be unset when there is a readonly variable
12342 * with the same name.
12346 unsetcmd(int argc, char **argv)
12353 while ((i = nextopt("vf")) != '\0') {
12357 for (ap = argptr; *ap ; ap++) {
12372 * Unset the specified variable.
12376 unsetvar(const char *s)
12382 vpp = findvar(hashvar(s), s);
12386 int flags = vp->flags;
12389 if (flags & VREADONLY)
12392 vp->flags &= ~VDYNAMIC;
12394 if (flags & VUNSET)
12396 if ((flags & VSTRFIXED) == 0) {
12398 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12405 vp->flags &= ~VEXPORT;
12418 * Find the appropriate entry in the hash table from the name.
12421 static struct var **
12422 hashvar(const char *p)
12424 unsigned int hashval;
12426 hashval = ((unsigned char) *p) << 4;
12427 while (*p && *p != '=')
12428 hashval += (unsigned char) *p++;
12429 return &vartab[hashval % VTABSIZE];
12435 * Compares two strings up to the first = or '\0'. The first
12436 * string must be terminated by '='; the second may be terminated by
12437 * either '=' or '\0'.
12441 varcmp(const char *p, const char *q)
12445 while ((c = *p) == (d = *q)) {
12446 if (!c || c == '=')
12460 vpcmp(const void *a, const void *b)
12462 return varcmp(*(const char **)a, *(const char **)b);
12465 static struct var **
12466 findvar(struct var **vpp, const char *name)
12468 for (; *vpp; vpp = &(*vpp)->next) {
12469 if (varequal((*vpp)->text, name)) {
12477 #include <sys/times.h>
12479 static const unsigned char timescmd_str[] = {
12480 ' ', offsetof(struct tms, tms_utime),
12481 '\n', offsetof(struct tms, tms_stime),
12482 ' ', offsetof(struct tms, tms_cutime),
12483 '\n', offsetof(struct tms, tms_cstime),
12487 static int timescmd(int ac, char **av)
12489 long int clk_tck, s, t;
12490 const unsigned char *p;
12493 clk_tck = sysconf(_SC_CLK_TCK);
12498 t = *(clock_t *)(((char *) &buf) + p[1]);
12500 out1fmt("%ldm%ld.%.3lds%c",
12502 ((t - s * clk_tck) * 1000) / clk_tck,
12504 } while (*(p += 2));
12509 #ifdef CONFIG_ASH_MATH_SUPPORT
12511 dash_arith(const char *s)
12517 result = arith(s, &errcode);
12520 sh_error("exponent less than 0");
12521 else if (errcode == -2)
12522 sh_error("divide by zero");
12523 else if (errcode == -5)
12524 sh_error("expression recursion loop detected");
12535 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12536 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12538 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12542 letcmd(int argc, char **argv)
12549 sh_error("expression expected");
12550 for (ap = argv + 1; *ap; ap++) {
12551 i = dash_arith(*ap);
12556 #endif /* CONFIG_ASH_MATH_SUPPORT */
12561 * Miscellaneous builtins.
12567 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12568 typedef enum __rlimit_resource rlim_t;
12574 * The read builtin. The -e option causes backslashes to escape the
12575 * following character.
12577 * This uses unbuffered input, which may be avoidable in some cases.
12581 readcmd(int argc, char **argv)
12593 #if defined(CONFIG_ASH_READ_NCHARS)
12597 struct termios tty, old_tty;
12599 #if defined(CONFIG_ASH_READ_TIMEOUT)
12603 ts.tv_sec = ts.tv_usec = 0;
12608 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12609 while ((i = nextopt("p:rt:n:s")) != '\0')
12610 #elif defined(CONFIG_ASH_READ_NCHARS)
12611 while ((i = nextopt("p:rn:s")) != '\0')
12612 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12613 while ((i = nextopt("p:rt:")) != '\0')
12615 while ((i = nextopt("p:r")) != '\0')
12620 prompt = optionarg;
12622 #if defined(CONFIG_ASH_READ_NCHARS)
12624 nchars = strtol(optionarg, &p, 10);
12626 sh_error("invalid count");
12627 nch_flag = (nchars > 0);
12633 #if defined(CONFIG_ASH_READ_TIMEOUT)
12635 ts.tv_sec = strtol(optionarg, &p, 10);
12641 ts.tv_usec = strtol(p, &p2, 10);
12643 sh_error("invalid timeout");
12645 /* normalize to usec */
12647 sh_error("invalid timeout");
12648 while (scale++ < 6)
12652 sh_error("invalid timeout");
12654 if ( ! ts.tv_sec && ! ts.tv_usec)
12655 sh_error("invalid timeout");
12665 if (prompt && isatty(0)) {
12668 if (*(ap = argptr) == NULL)
12669 sh_error("arg count");
12670 if ((ifs = bltinlookup("IFS")) == NULL)
12672 #if defined(CONFIG_ASH_READ_NCHARS)
12673 if (nch_flag || silent) {
12674 tcgetattr(0, &tty);
12677 tty.c_lflag &= ~ICANON;
12678 tty.c_cc[VMIN] = nchars;
12681 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12684 tcsetattr(0, TCSANOW, &tty);
12687 #if defined(CONFIG_ASH_READ_TIMEOUT)
12688 if (ts.tv_sec || ts.tv_usec) {
12692 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12694 #if defined(CONFIG_ASH_READ_NCHARS)
12696 tcsetattr(0, TCSANOW, &old_tty);
12706 #if defined(CONFIG_ASH_READ_NCHARS)
12707 while (!nch_flag || nchars--)
12712 if (read(0, &c, 1) != 1) {
12724 if (!rflag && c == '\\') {
12730 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12734 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12736 setvar(*ap, stackblock(), 0);
12745 #if defined(CONFIG_ASH_READ_NCHARS)
12746 if (nch_flag || silent)
12747 tcsetattr(0, TCSANOW, &old_tty);
12751 /* Remove trailing blanks */
12752 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12754 setvar(*ap, stackblock(), 0);
12755 while (*++ap != NULL)
12756 setvar(*ap, nullstr, 0);
12761 static int umaskcmd(int argc, char **argv)
12763 static const char permuser[3] = "ugo";
12764 static const char permmode[3] = "rwx";
12765 static const short int permmask[] = {
12766 S_IRUSR, S_IWUSR, S_IXUSR,
12767 S_IRGRP, S_IWGRP, S_IXGRP,
12768 S_IROTH, S_IWOTH, S_IXOTH
12774 int symbolic_mode = 0;
12776 while (nextopt("S") != '\0') {
12785 if ((ap = *argptr) == NULL) {
12786 if (symbolic_mode) {
12790 for (i = 0; i < 3; i++) {
12793 *p++ = permuser[i];
12795 for (j = 0; j < 3; j++) {
12796 if ((mask & permmask[3 * i + j]) == 0) {
12797 *p++ = permmode[j];
12805 out1fmt("%.4o\n", mask);
12808 if (is_digit((unsigned char) *ap)) {
12811 if (*ap >= '8' || *ap < '0')
12812 sh_error(illnum, argv[1]);
12813 mask = (mask << 3) + (*ap - '0');
12814 } while (*++ap != '\0');
12817 mask = ~mask & 0777;
12818 if (!bb_parse_mode(ap, &mask)) {
12819 sh_error("Illegal mode: %s", ap);
12821 umask(~mask & 0777);
12830 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12831 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12832 * ash by J.T. Conklin.
12840 int factor; /* multiply by to get rlim_{cur,max} values */
12844 static const struct limits limits[] = {
12846 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12848 #ifdef RLIMIT_FSIZE
12849 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12852 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12854 #ifdef RLIMIT_STACK
12855 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12858 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12861 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12863 #ifdef RLIMIT_MEMLOCK
12864 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12866 #ifdef RLIMIT_NPROC
12867 { "process", RLIMIT_NPROC, 1, 'p' },
12869 #ifdef RLIMIT_NOFILE
12870 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12873 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12875 #ifdef RLIMIT_LOCKS
12876 { "locks", RLIMIT_LOCKS, 1, 'w' },
12878 { (char *) 0, 0, 0, '\0' }
12881 enum limtype { SOFT = 0x1, HARD = 0x2 };
12883 static void printlim(enum limtype how, const struct rlimit *limit,
12884 const struct limits *l)
12888 val = limit->rlim_max;
12890 val = limit->rlim_cur;
12892 if (val == RLIM_INFINITY)
12893 out1fmt("unlimited\n");
12896 out1fmt("%lld\n", (long long) val);
12901 ulimitcmd(int argc, char **argv)
12905 enum limtype how = SOFT | HARD;
12906 const struct limits *l;
12909 struct rlimit limit;
12912 while ((optc = nextopt("HSa"
12916 #ifdef RLIMIT_FSIZE
12922 #ifdef RLIMIT_STACK
12931 #ifdef RLIMIT_MEMLOCK
12934 #ifdef RLIMIT_NPROC
12937 #ifdef RLIMIT_NOFILE
12943 #ifdef RLIMIT_LOCKS
12961 for (l = limits; l->option != what; l++)
12964 set = *argptr ? 1 : 0;
12968 if (all || argptr[1])
12969 sh_error("too many arguments");
12970 if (strncmp(p, "unlimited\n", 9) == 0)
12971 val = RLIM_INFINITY;
12975 while ((c = *p++) >= '0' && c <= '9')
12977 val = (val * 10) + (long)(c - '0');
12978 if (val < (rlim_t) 0)
12982 sh_error("bad number");
12987 for (l = limits; l->name; l++) {
12988 getrlimit(l->cmd, &limit);
12989 out1fmt("%-20s ", l->name);
12990 printlim(how, &limit, l);
12995 getrlimit(l->cmd, &limit);
12998 limit.rlim_max = val;
13000 limit.rlim_cur = val;
13001 if (setrlimit(l->cmd, &limit) < 0)
13002 sh_error("error setting limit (%m)");
13004 printlim(how, &limit, l);
13010 #ifdef CONFIG_ASH_MATH_SUPPORT
13012 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13014 Permission is hereby granted, free of charge, to any person obtaining
13015 a copy of this software and associated documentation files (the
13016 "Software"), to deal in the Software without restriction, including
13017 without limitation the rights to use, copy, modify, merge, publish,
13018 distribute, sublicense, and/or sell copies of the Software, and to
13019 permit persons to whom the Software is furnished to do so, subject to
13020 the following conditions:
13022 The above copyright notice and this permission notice shall be
13023 included in all copies or substantial portions of the Software.
13025 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13026 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13027 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13028 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13029 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13030 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13031 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13034 /* This is my infix parser/evaluator. It is optimized for size, intended
13035 * as a replacement for yacc-based parsers. However, it may well be faster
13036 * than a comparable parser written in yacc. The supported operators are
13037 * listed in #defines below. Parens, order of operations, and error handling
13038 * are supported. This code is thread safe. The exact expression format should
13039 * be that which POSIX specifies for shells. */
13041 /* The code uses a simple two-stack algorithm. See
13042 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13043 * for a detailed explanation of the infix-to-postfix algorithm on which
13044 * this is based (this code differs in that it applies operators immediately
13045 * to the stack instead of adding them to a queue to end up with an
13048 /* To use the routine, call it with an expression string and error return
13052 * Aug 24, 2001 Manuel Novoa III
13054 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13056 * 1) In arith_apply():
13057 * a) Cached values of *numptr and &(numptr[-1]).
13058 * b) Removed redundant test for zero denominator.
13061 * a) Eliminated redundant code for processing operator tokens by moving
13062 * to a table-based implementation. Also folded handling of parens
13064 * b) Combined all 3 loops which called arith_apply to reduce generated
13065 * code size at the cost of speed.
13067 * 3) The following expressions were treated as valid by the original code:
13068 * 1() , 0! , 1 ( *3 ) .
13069 * These bugs have been fixed by internally enclosing the expression in
13070 * parens and then checking that all binary ops and right parens are
13071 * preceded by a valid expression (NUM_TOKEN).
13073 * Note: It may be desirable to replace Aaron's test for whitespace with
13074 * ctype's isspace() if it is used by another busybox applet or if additional
13075 * whitespace chars should be considered. Look below the "#include"s for a
13076 * precompiler test.
13080 * Aug 26, 2001 Manuel Novoa III
13082 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13084 * Merge in Aaron's comments previously posted to the busybox list,
13085 * modified slightly to take account of my changes to the code.
13090 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13092 * - allow access to variable,
13093 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13094 * - realize assign syntax (VAR=expr, +=, *= etc)
13095 * - realize exponentiation (** operator)
13096 * - realize comma separated - expr, expr
13097 * - realise ++expr --expr expr++ expr--
13098 * - realise expr ? expr : expr (but, second expr calculate always)
13099 * - allow hexadecimal and octal numbers
13100 * - was restored loses XOR operator
13101 * - remove one goto label, added three ;-)
13102 * - protect $((num num)) as true zero expr (Manuel`s error)
13103 * - always use special isspace(), see comment from bash ;-)
13107 #define arith_isspace(arithval) \
13108 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13111 typedef unsigned char operator;
13113 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13114 * precedence, and 3 high bits are an ID unique across operators of that
13115 * precedence. The ID portion is so that multiple operators can have the
13116 * same precedence, ensuring that the leftmost one is evaluated first.
13117 * Consider * and /. */
13119 #define tok_decl(prec,id) (((id)<<5)|(prec))
13120 #define PREC(op) ((op) & 0x1F)
13122 #define TOK_LPAREN tok_decl(0,0)
13124 #define TOK_COMMA tok_decl(1,0)
13126 #define TOK_ASSIGN tok_decl(2,0)
13127 #define TOK_AND_ASSIGN tok_decl(2,1)
13128 #define TOK_OR_ASSIGN tok_decl(2,2)
13129 #define TOK_XOR_ASSIGN tok_decl(2,3)
13130 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13131 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13132 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13133 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13135 #define TOK_MUL_ASSIGN tok_decl(3,0)
13136 #define TOK_DIV_ASSIGN tok_decl(3,1)
13137 #define TOK_REM_ASSIGN tok_decl(3,2)
13139 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13140 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13142 /* conditional is right associativity too */
13143 #define TOK_CONDITIONAL tok_decl(4,0)
13144 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13146 #define TOK_OR tok_decl(5,0)
13148 #define TOK_AND tok_decl(6,0)
13150 #define TOK_BOR tok_decl(7,0)
13152 #define TOK_BXOR tok_decl(8,0)
13154 #define TOK_BAND tok_decl(9,0)
13156 #define TOK_EQ tok_decl(10,0)
13157 #define TOK_NE tok_decl(10,1)
13159 #define TOK_LT tok_decl(11,0)
13160 #define TOK_GT tok_decl(11,1)
13161 #define TOK_GE tok_decl(11,2)
13162 #define TOK_LE tok_decl(11,3)
13164 #define TOK_LSHIFT tok_decl(12,0)
13165 #define TOK_RSHIFT tok_decl(12,1)
13167 #define TOK_ADD tok_decl(13,0)
13168 #define TOK_SUB tok_decl(13,1)
13170 #define TOK_MUL tok_decl(14,0)
13171 #define TOK_DIV tok_decl(14,1)
13172 #define TOK_REM tok_decl(14,2)
13174 /* exponent is right associativity */
13175 #define TOK_EXPONENT tok_decl(15,1)
13177 /* For now unary operators. */
13178 #define UNARYPREC 16
13179 #define TOK_BNOT tok_decl(UNARYPREC,0)
13180 #define TOK_NOT tok_decl(UNARYPREC,1)
13182 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13183 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13185 #define PREC_PRE (UNARYPREC+2)
13187 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13188 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13190 #define PREC_POST (UNARYPREC+3)
13192 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13193 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13195 #define SPEC_PREC (UNARYPREC+4)
13197 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13198 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13200 #define NUMPTR (*numstackptr)
13202 static int tok_have_assign(operator op)
13204 operator prec = PREC(op);
13206 convert_prec_is_assing(prec);
13207 return (prec == PREC(TOK_ASSIGN) ||
13208 prec == PREC_PRE || prec == PREC_POST);
13211 static int is_right_associativity(operator prec)
13213 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13214 prec == PREC(TOK_CONDITIONAL));
13218 typedef struct ARITCH_VAR_NUM {
13220 arith_t contidional_second_val;
13221 char contidional_second_val_initialized;
13222 char *var; /* if NULL then is regular number,
13223 else is variable name */
13227 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13229 struct CHK_VAR_RECURSIVE_LOOPED *next;
13230 } chk_var_recursive_looped_t;
13232 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13235 static int arith_lookup_val(v_n_t *t)
13238 const char * p = lookupvar(t->var);
13243 /* recursive try as expression */
13244 chk_var_recursive_looped_t *cur;
13245 chk_var_recursive_looped_t cur_save;
13247 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13248 if(strcmp(cur->var, t->var) == 0) {
13249 /* expression recursion loop detected */
13253 /* save current lookuped var name */
13254 cur = prev_chk_var_recursive;
13255 cur_save.var = t->var;
13256 cur_save.next = cur;
13257 prev_chk_var_recursive = &cur_save;
13259 t->val = arith (p, &errcode);
13260 /* restore previous ptr after recursiving */
13261 prev_chk_var_recursive = cur;
13264 /* allow undefined var as 0 */
13271 /* "applying" a token means performing it on the top elements on the integer
13272 * stack. For a unary operator it will only change the top element, but a
13273 * binary operator will pop two arguments and push a result */
13274 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13277 arith_t numptr_val, rez;
13278 int ret_arith_lookup_val;
13280 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13281 without arguments */
13282 numptr_m1 = NUMPTR - 1;
13284 /* check operand is var with noninteger value */
13285 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13286 if(ret_arith_lookup_val)
13287 return ret_arith_lookup_val;
13289 rez = numptr_m1->val;
13290 if (op == TOK_UMINUS)
13292 else if (op == TOK_NOT)
13294 else if (op == TOK_BNOT)
13296 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13298 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13300 else if (op != TOK_UPLUS) {
13301 /* Binary operators */
13303 /* check and binary operators need two arguments */
13304 if (numptr_m1 == numstack) goto err;
13306 /* ... and they pop one */
13309 if (op == TOK_CONDITIONAL) {
13310 if(! numptr_m1->contidional_second_val_initialized) {
13311 /* protect $((expr1 ? expr2)) without ": expr" */
13314 rez = numptr_m1->contidional_second_val;
13315 } else if(numptr_m1->contidional_second_val_initialized) {
13316 /* protect $((expr1 : expr2)) without "expr ? " */
13319 numptr_m1 = NUMPTR - 1;
13320 if(op != TOK_ASSIGN) {
13321 /* check operand is var with noninteger value for not '=' */
13322 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13323 if(ret_arith_lookup_val)
13324 return ret_arith_lookup_val;
13326 if (op == TOK_CONDITIONAL) {
13327 numptr_m1->contidional_second_val = rez;
13329 rez = numptr_m1->val;
13330 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13332 else if (op == TOK_OR)
13333 rez = numptr_val || rez;
13334 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13336 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13338 else if (op == TOK_AND)
13339 rez = rez && numptr_val;
13340 else if (op == TOK_EQ)
13341 rez = (rez == numptr_val);
13342 else if (op == TOK_NE)
13343 rez = (rez != numptr_val);
13344 else if (op == TOK_GE)
13345 rez = (rez >= numptr_val);
13346 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13347 rez >>= numptr_val;
13348 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13349 rez <<= numptr_val;
13350 else if (op == TOK_GT)
13351 rez = (rez > numptr_val);
13352 else if (op == TOK_LT)
13353 rez = (rez < numptr_val);
13354 else if (op == TOK_LE)
13355 rez = (rez <= numptr_val);
13356 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13358 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13360 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13362 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13364 else if (op == TOK_CONDITIONAL_SEP) {
13365 if (numptr_m1 == numstack) {
13366 /* protect $((expr : expr)) without "expr ? " */
13369 numptr_m1->contidional_second_val_initialized = op;
13370 numptr_m1->contidional_second_val = numptr_val;
13372 else if (op == TOK_CONDITIONAL) {
13374 numptr_val : numptr_m1->contidional_second_val;
13376 else if(op == TOK_EXPONENT) {
13378 return -3; /* exponent less than 0 */
13383 while(numptr_val--)
13388 else if(numptr_val==0) /* zero divisor check */
13390 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13392 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13395 if(tok_have_assign(op)) {
13398 if(numptr_m1->var == NULL) {
13402 /* save to shell variable */
13403 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13404 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13406 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13408 setvar(numptr_m1->var, buf, 0);
13409 /* after saving, make previous value for v++ or v-- */
13410 if(op == TOK_POST_INC)
13412 else if(op == TOK_POST_DEC)
13415 numptr_m1->val = rez;
13416 /* protect geting var value, is number now */
13417 numptr_m1->var = NULL;
13422 /* longest must first */
13423 static const char op_tokens[] = {
13424 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13425 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13426 '<','<', 0, TOK_LSHIFT,
13427 '>','>', 0, TOK_RSHIFT,
13428 '|','|', 0, TOK_OR,
13429 '&','&', 0, TOK_AND,
13430 '!','=', 0, TOK_NE,
13431 '<','=', 0, TOK_LE,
13432 '>','=', 0, TOK_GE,
13433 '=','=', 0, TOK_EQ,
13434 '|','=', 0, TOK_OR_ASSIGN,
13435 '&','=', 0, TOK_AND_ASSIGN,
13436 '*','=', 0, TOK_MUL_ASSIGN,
13437 '/','=', 0, TOK_DIV_ASSIGN,
13438 '%','=', 0, TOK_REM_ASSIGN,
13439 '+','=', 0, TOK_PLUS_ASSIGN,
13440 '-','=', 0, TOK_MINUS_ASSIGN,
13441 '-','-', 0, TOK_POST_DEC,
13442 '^','=', 0, TOK_XOR_ASSIGN,
13443 '+','+', 0, TOK_POST_INC,
13444 '*','*', 0, TOK_EXPONENT,
13448 '=', 0, TOK_ASSIGN,
13460 '?', 0, TOK_CONDITIONAL,
13461 ':', 0, TOK_CONDITIONAL_SEP,
13462 ')', 0, TOK_RPAREN,
13463 '(', 0, TOK_LPAREN,
13467 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13470 static arith_t arith (const char *expr, int *perrcode)
13472 char arithval; /* Current character under analysis */
13473 operator lasttok, op;
13476 const char *p = endexpression;
13479 size_t datasizes = strlen(expr) + 2;
13481 /* Stack of integers */
13482 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13483 * in any given correct or incorrect expression is left as an exercise to
13485 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13486 *numstackptr = numstack;
13487 /* Stack of operator tokens */
13488 operator *stack = alloca((datasizes) * sizeof(operator)),
13491 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13492 *perrcode = errcode = 0;
13495 if ((arithval = *expr) == 0) {
13496 if (p == endexpression) {
13497 /* Null expression. */
13501 /* This is only reached after all tokens have been extracted from the
13502 * input stream. If there are still tokens on the operator stack, they
13503 * are to be applied in order. At the end, there should be a final
13504 * result on the integer stack */
13506 if (expr != endexpression + 1) {
13507 /* If we haven't done so already, */
13508 /* append a closing right paren */
13509 expr = endexpression;
13510 /* and let the loop process it. */
13513 /* At this point, we're done with the expression. */
13514 if (numstackptr != numstack+1) {
13515 /* ... but if there isn't, it's bad */
13517 return (*perrcode = -1);
13519 if(numstack->var) {
13520 /* expression is $((var)) only, lookup now */
13521 errcode = arith_lookup_val(numstack);
13524 *perrcode = errcode;
13525 return numstack->val;
13527 /* Continue processing the expression. */
13528 if (arith_isspace(arithval)) {
13529 /* Skip whitespace */
13532 if((p = endofname(expr)) != expr) {
13533 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13535 numstackptr->var = alloca(var_name_size);
13536 safe_strncpy(numstackptr->var, expr, var_name_size);
13539 numstackptr->contidional_second_val_initialized = 0;
13543 } else if (is_digit(arithval)) {
13544 numstackptr->var = NULL;
13545 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13546 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13548 numstackptr->val = strtol(expr, (char **) &expr, 0);
13552 for(p = op_tokens; ; p++) {
13556 /* strange operator not found */
13559 for(o = expr; *p && *o == *p; p++)
13566 /* skip tail uncompared token */
13569 /* skip zero delim */
13574 /* post grammar: a++ reduce to num */
13575 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13578 /* Plus and minus are binary (not unary) _only_ if the last
13579 * token was as number, or a right paren (which pretends to be
13580 * a number, since it evaluates to one). Think about it.
13581 * It makes sense. */
13582 if (lasttok != TOK_NUM) {
13598 /* We don't want a unary operator to cause recursive descent on the
13599 * stack, because there can be many in a row and it could cause an
13600 * operator to be evaluated before its argument is pushed onto the
13601 * integer stack. */
13602 /* But for binary operators, "apply" everything on the operator
13603 * stack until we find an operator with a lesser priority than the
13604 * one we have just extracted. */
13605 /* Left paren is given the lowest priority so it will never be
13606 * "applied" in this way.
13607 * if associativity is right and priority eq, applied also skip
13610 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13611 /* not left paren or unary */
13612 if (lasttok != TOK_NUM) {
13613 /* binary op must be preceded by a num */
13616 while (stackptr != stack) {
13617 if (op == TOK_RPAREN) {
13618 /* The algorithm employed here is simple: while we don't
13619 * hit an open paren nor the bottom of the stack, pop
13620 * tokens and apply them */
13621 if (stackptr[-1] == TOK_LPAREN) {
13623 /* Any operator directly after a */
13625 /* close paren should consider itself binary */
13629 operator prev_prec = PREC(stackptr[-1]);
13631 convert_prec_is_assing(prec);
13632 convert_prec_is_assing(prev_prec);
13633 if (prev_prec < prec)
13635 /* check right assoc */
13636 if(prev_prec == prec && is_right_associativity(prec))
13639 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13640 if(errcode) goto ret;
13642 if (op == TOK_RPAREN) {
13647 /* Push this operator to the stack and remember it. */
13648 *stackptr++ = lasttok = op;
13655 #endif /* CONFIG_ASH_MATH_SUPPORT */
13659 const char *applet_name = "debug stuff usage";
13660 int main(int argc, char **argv)
13662 return ash_main(argc, argv);
13667 * Copyright (c) 1989, 1991, 1993, 1994
13668 * The Regents of the University of California. All rights reserved.
13670 * This code is derived from software contributed to Berkeley by
13671 * Kenneth Almquist.
13673 * Redistribution and use in source and binary forms, with or without
13674 * modification, are permitted provided that the following conditions
13676 * 1. Redistributions of source code must retain the above copyright
13677 * notice, this list of conditions and the following disclaimer.
13678 * 2. Redistributions in binary form must reproduce the above copyright
13679 * notice, this list of conditions and the following disclaimer in the
13680 * documentation and/or other materials provided with the distribution.
13681 * 3. Neither the name of the University nor the names of its contributors
13682 * may be used to endorse or promote products derived from this software
13683 * without specific prior written permission.
13685 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13686 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13687 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13688 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13689 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13690 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13691 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13692 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13693 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13694 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF