1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
36 * The follow should be set to reflect the type of system you have:
37 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
38 * define SYSV if you are running under System V.
39 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
40 * define DEBUG=2 to compile in and turn on debugging.
42 * When debugging is on, debugging info will be written to ./trace and
43 * a quit signal will generate a core dump.
58 #include <sys/types.h>
59 #include <sys/ioctl.h>
60 #include <sys/param.h>
61 #include <sys/resource.h>
81 /*#include <stdint.h>*/
85 #ifdef CONFIG_ASH_JOB_CONTROL
91 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
99 static int *dash_errno;
101 #define errno (*dash_errno)
104 #if defined(__uClinux__)
105 #error "Do not even bother, ash will not run on uClinux"
109 #define _DIAGASSERT(assert_expr) assert(assert_expr)
111 #define _DIAGASSERT(assert_expr)
115 #ifdef CONFIG_ASH_ALIAS
128 static struct alias *lookupalias(const char *, int);
129 static int aliascmd(int, char **);
130 static int unaliascmd(int, char **);
131 static void rmaliases(void);
132 static int unalias(const char *);
133 static void printalias(const struct alias *);
139 static void setpwd(const char *, int);
145 * Types of operations (passed to the errmsg routine).
149 static const char not_found_msg[] = "%s: not found";
152 #define E_OPEN "No such file" /* opening a file */
153 #define E_CREAT "Directory nonexistent" /* creating a file */
154 #define E_EXEC not_found_msg+4 /* executing a program */
157 * We enclose jmp_buf in a structure so that we can declare pointers to
158 * jump locations. The global variable handler contains the location to
159 * jump to when an exception occurs, and the global variable exception
160 * contains a code identifying the exception. To implement nested
161 * exception handlers, the user should save the value of handler on entry
162 * to an inner scope, set handler to point to a jmploc structure for the
163 * inner scope, and restore handler on exit from the scope.
170 static struct jmploc *handler;
171 static int exception;
172 static volatile int suppressint;
173 static volatile sig_atomic_t intpending;
176 #define EXINT 0 /* SIGINT received */
177 #define EXERROR 1 /* a generic error */
178 #define EXSHELLPROC 2 /* execute a shell procedure */
179 #define EXEXEC 3 /* command execution failed */
180 #define EXEXIT 4 /* exit the shell */
181 #define EXSIG 5 /* trapped signal in wait(1) */
184 /* do we generate EXSIG events */
186 /* last pending signal */
187 static volatile sig_atomic_t pendingsigs;
190 * These macros allow the user to suspend the handling of interrupt signals
191 * over a period of time. This is similar to SIGHOLD to or sigblock, but
192 * much more efficient and portable. (But hacking the kernel is so much
193 * more fun than worrying about efficiency and portability. :-))
196 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
203 #define SAVEINT(v) ((v) = suppressint)
204 #define RESTOREINT(v) \
207 if ((suppressint = (v)) == 0 && intpending) onint(); \
218 /* EXSIG is turned off by evalbltin(). */
221 static void exraise(int) ATTRIBUTE_NORETURN;
222 static void onint(void) ATTRIBUTE_NORETURN;
224 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
225 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
227 static void sh_warnx(const char *, ...);
229 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
232 if (--suppressint == 0 && intpending) {
236 #define INTON inton()
237 static void forceinton(void)
243 #define FORCEINTON forceinton()
248 if (--suppressint == 0 && intpending) onint(); \
255 if (intpending) onint(); \
258 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
263 struct strlist *next;
269 struct strlist *list;
270 struct strlist **lastp;
276 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
277 #define EXP_TILDE 0x2 /* do normal tilde expansion */
278 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
279 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
280 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
281 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
282 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
283 #define EXP_WORD 0x80 /* expand word in parameter expansion */
284 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
288 static void expandarg(union node *, struct arglist *, int);
289 #define rmescapes(p) _rmescapes((p), 0)
290 static char *_rmescapes(char *, int);
291 static int casematch(union node *, char *);
293 #ifdef CONFIG_ASH_MATH_SUPPORT
294 static void expari(int);
299 static char *commandname; /* currently executing command */
300 static struct strlist *cmdenviron; /* environment for builtin command */
301 static int exitstatus; /* exit status of last command */
302 static int back_exitstatus; /* exit status of backquoted command */
305 struct backcmd { /* result of evalbackcmd */
306 int fd; /* file descriptor to read from */
307 char *buf; /* buffer */
308 int nleft; /* number of chars in buffer */
309 struct job *jp; /* job structure for command */
313 * This file was generated by the mknodes program.
349 union node *redirect;
356 struct nodelist *cmdlist;
363 union node *redirect;
378 union node *elsepart;
409 struct nodelist *backquote;
449 struct nredir nredir;
450 struct nbinary nbinary;
454 struct nclist nclist;
464 struct nodelist *next;
475 static void freefunc(struct funcnode *);
478 /* control characters in argument strings */
479 #define CTL_FIRST '\201' /* first 'special' character */
480 #define CTLESC '\201' /* escape next character */
481 #define CTLVAR '\202' /* variable defn */
482 #define CTLENDVAR '\203'
483 #define CTLBACKQ '\204'
484 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
485 /* CTLBACKQ | CTLQUOTE == '\205' */
486 #define CTLARI '\206' /* arithmetic expression */
487 #define CTLENDARI '\207'
488 #define CTLQUOTEMARK '\210'
489 #define CTL_LAST '\210' /* last 'special' character */
491 /* variable substitution byte (follows CTLVAR) */
492 #define VSTYPE 0x0f /* type of variable substitution */
493 #define VSNUL 0x10 /* colon--treat the empty string as unset */
494 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
496 /* values of VSTYPE field */
497 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
498 #define VSMINUS 0x2 /* ${var-text} */
499 #define VSPLUS 0x3 /* ${var+text} */
500 #define VSQUESTION 0x4 /* ${var?message} */
501 #define VSASSIGN 0x5 /* ${var=text} */
502 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
503 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
504 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
505 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
506 #define VSLENGTH 0xa /* ${#var} */
508 /* values of checkkwd variable */
513 #define IBUFSIZ (BUFSIZ + 1)
516 * NEOF is returned by parsecmd when it encounters an end of file. It
517 * must be distinct from NULL, so we use the address of a variable that
518 * happens to be handy.
520 static int plinno = 1; /* input line number */
522 /* number of characters left in input buffer */
523 static int parsenleft; /* copy of parsefile->nleft */
524 static int parselleft; /* copy of parsefile->lleft */
526 /* next character in input buffer */
527 static char *parsenextc; /* copy of parsefile->nextc */
530 struct strpush *prev; /* preceding string on stack */
533 #ifdef CONFIG_ASH_ALIAS
534 struct alias *ap; /* if push was associated with an alias */
536 char *string; /* remember the string since it may change */
540 struct parsefile *prev; /* preceding file on stack */
541 int linno; /* current line */
542 int fd; /* file descriptor (or -1 if string) */
543 int nleft; /* number of chars left in this line */
544 int lleft; /* number of chars left in this buffer */
545 char *nextc; /* next char in buffer */
546 char *buf; /* input buffer */
547 struct strpush *strpush; /* for pushing strings at this level */
548 struct strpush basestrpush; /* so pushing one is fast */
551 static struct parsefile basepf; /* top level input file */
552 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
553 static struct parsefile *parsefile = &basepf; /* current input file */
556 static int tokpushback; /* last token pushed back */
557 #define NEOF ((union node *)&tokpushback)
558 static int parsebackquote; /* nonzero if we are inside backquotes */
559 static int doprompt; /* if set, prompt the user */
560 static int needprompt; /* true if interactive and at start of line */
561 static int lasttoken; /* last token read */
562 static char *wordtext; /* text of last word returned by readtoken */
564 static struct nodelist *backquotelist;
565 static union node *redirnode;
566 static struct heredoc *heredoc;
567 static int quoteflag; /* set if (part of) last token was quoted */
568 static int startlinno; /* line # where last token started */
570 static union node *parsecmd(int);
571 static void fixredir(union node *, const char *, int);
572 static const char *const *findkwd(const char *);
573 static char *endofname(const char *);
577 typedef void *pointer;
579 static char nullstr[1]; /* zero length string */
580 static const char spcstr[] = " ";
581 static const char snlfmt[] = "%s\n";
582 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
583 static const char illnum[] = "Illegal number: %s";
584 static const char homestr[] = "HOME";
587 #define TRACE(param) trace param
588 #define TRACEV(param) tracev param
591 #define TRACEV(param)
594 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
595 #define __builtin_expect(x, expected_value) (x)
598 #define xlikely(x) __builtin_expect((x),1)
613 #define TENDBQUOTE 12
631 /* first char is indicating which tokens mark the end of a list */
632 static const char *const tokname_array[] = {
647 /* the following are keywords */
666 static const char *tokname(int tok)
672 sprintf(buf + (tok >= TSEMI), "%s%c",
673 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
680 * Most machines require the value returned from malloc to be aligned
681 * in some way. The following macro will get this right on many machines.
684 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
686 * It appears that grabstackstr() will barf with such alignments
687 * because stalloc() will return a string allocated in a new stackblock.
689 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
692 * This file was generated by the mksyntax program.
697 #define CWORD 0 /* character is nothing special */
698 #define CNL 1 /* newline character */
699 #define CBACK 2 /* a backslash character */
700 #define CSQUOTE 3 /* single quote */
701 #define CDQUOTE 4 /* double quote */
702 #define CENDQUOTE 5 /* a terminating quote */
703 #define CBQUOTE 6 /* backwards single quote */
704 #define CVAR 7 /* a dollar sign */
705 #define CENDVAR 8 /* a '}' character */
706 #define CLP 9 /* a left paren in arithmetic */
707 #define CRP 10 /* a right paren in arithmetic */
708 #define CENDFILE 11 /* end of file */
709 #define CCTL 12 /* like CWORD, except it must be escaped */
710 #define CSPCL 13 /* these terminate a word */
711 #define CIGN 14 /* character should be ignored */
713 #ifdef CONFIG_ASH_ALIAS
717 #define PEOA_OR_PEOF PEOA
721 #define PEOA_OR_PEOF PEOF
724 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
725 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
726 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
728 /* C99 say: "char" declaration may be signed or unsigned default */
729 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
732 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
733 * (assuming ascii char codes, as the original implementation did)
735 #define is_special(c) \
736 ( (((unsigned int)c) - 33 < 32) \
737 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
739 #define digit_val(c) ((c) - '0')
742 * This file was generated by the mksyntax program.
745 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
746 #define USE_SIT_FUNCTION
749 /* number syntax index */
750 #define BASESYNTAX 0 /* not in quotes */
751 #define DQSYNTAX 1 /* in double quotes */
752 #define SQSYNTAX 2 /* in single quotes */
753 #define ARISYNTAX 3 /* in arithmetic */
755 #ifdef CONFIG_ASH_MATH_SUPPORT
756 static const char S_I_T[][4] = {
757 #ifdef CONFIG_ASH_ALIAS
758 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
760 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
761 {CNL, CNL, CNL, CNL}, /* 2, \n */
762 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
763 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
764 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
765 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
766 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
767 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
768 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
769 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
770 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
771 #ifndef USE_SIT_FUNCTION
772 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
773 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
774 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
778 static const char S_I_T[][3] = {
779 #ifdef CONFIG_ASH_ALIAS
780 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
782 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
783 {CNL, CNL, CNL}, /* 2, \n */
784 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
785 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
786 {CVAR, CVAR, CWORD}, /* 5, $ */
787 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
788 {CSPCL, CWORD, CWORD}, /* 7, ( */
789 {CSPCL, CWORD, CWORD}, /* 8, ) */
790 {CBACK, CBACK, CCTL}, /* 9, \ */
791 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
792 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
793 #ifndef USE_SIT_FUNCTION
794 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
795 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
796 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
799 #endif /* CONFIG_ASH_MATH_SUPPORT */
801 #ifdef USE_SIT_FUNCTION
803 #define U_C(c) ((unsigned char)(c))
805 static int SIT(int c, int syntax)
807 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
808 #ifdef CONFIG_ASH_ALIAS
809 static const char syntax_index_table[] = {
810 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
811 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
812 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
816 static const char syntax_index_table[] = {
817 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
818 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
819 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
826 if (c == PEOF) /* 2^8+2 */
828 #ifdef CONFIG_ASH_ALIAS
829 if (c == PEOA) /* 2^8+1 */
833 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
836 s = strchr(spec_symbls, c);
837 if (s == 0 || *s == 0)
839 indx = syntax_index_table[(s - spec_symbls)];
841 return S_I_T[indx][syntax];
844 #else /* USE_SIT_FUNCTION */
846 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
848 #ifdef CONFIG_ASH_ALIAS
849 #define CSPCL_CIGN_CIGN_CIGN 0
850 #define CSPCL_CWORD_CWORD_CWORD 1
851 #define CNL_CNL_CNL_CNL 2
852 #define CWORD_CCTL_CCTL_CWORD 3
853 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
854 #define CVAR_CVAR_CWORD_CVAR 5
855 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
856 #define CSPCL_CWORD_CWORD_CLP 7
857 #define CSPCL_CWORD_CWORD_CRP 8
858 #define CBACK_CBACK_CCTL_CBACK 9
859 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
860 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
861 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
862 #define CWORD_CWORD_CWORD_CWORD 13
863 #define CCTL_CCTL_CCTL_CCTL 14
865 #define CSPCL_CWORD_CWORD_CWORD 0
866 #define CNL_CNL_CNL_CNL 1
867 #define CWORD_CCTL_CCTL_CWORD 2
868 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
869 #define CVAR_CVAR_CWORD_CVAR 4
870 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
871 #define CSPCL_CWORD_CWORD_CLP 6
872 #define CSPCL_CWORD_CWORD_CRP 7
873 #define CBACK_CBACK_CCTL_CBACK 8
874 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
875 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
876 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
877 #define CWORD_CWORD_CWORD_CWORD 12
878 #define CCTL_CCTL_CCTL_CCTL 13
881 static const char syntax_index_table[258] = {
882 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
883 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
884 #ifdef CONFIG_ASH_ALIAS
885 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
887 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
888 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
889 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
890 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
891 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
892 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
893 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
894 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
895 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
896 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
897 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
898 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
899 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
900 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
901 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
902 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
903 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
904 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
905 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
906 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
907 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
908 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
909 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
910 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
911 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
912 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
913 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
914 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
915 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
916 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
917 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
918 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
919 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
920 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
921 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
922 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
923 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
924 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
925 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
926 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
927 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
928 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
929 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
930 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
931 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
932 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
933 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
934 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
935 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
936 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
937 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
938 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
939 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
940 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
941 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
942 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
943 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
944 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
945 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
946 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
947 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
948 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
949 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
950 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
951 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
952 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
953 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
954 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
955 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
956 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
957 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
958 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
959 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
960 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
961 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
962 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
963 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
964 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
965 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
966 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
967 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
968 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
969 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
970 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
971 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
972 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
973 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
974 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
975 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
976 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
977 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
978 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
979 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
980 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
981 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
982 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
983 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
984 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
985 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
986 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
987 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
988 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
989 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
990 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
991 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
992 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
993 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
994 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
995 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
996 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
997 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
998 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
999 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1025 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1026 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1048 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1049 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1050 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1051 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1052 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1053 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1054 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1055 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1056 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1057 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1058 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1059 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1060 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1061 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1062 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1063 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1064 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1074 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1075 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1076 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1077 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1078 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1079 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1107 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1108 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1109 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1112 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1140 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1141 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1142 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1145 #endif /* USE_SIT_FUNCTION */
1152 static int funcblocksize; /* size of structures in function */
1153 static int funcstringsize; /* size of strings in node */
1154 static pointer funcblock; /* block to allocate function from */
1155 static char *funcstring; /* block to allocate strings from */
1157 static const short nodesize[26] = {
1158 SHELL_ALIGN(sizeof (struct ncmd)),
1159 SHELL_ALIGN(sizeof (struct npipe)),
1160 SHELL_ALIGN(sizeof (struct nredir)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nredir)),
1163 SHELL_ALIGN(sizeof (struct nbinary)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nbinary)),
1166 SHELL_ALIGN(sizeof (struct nif)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nfor)),
1170 SHELL_ALIGN(sizeof (struct ncase)),
1171 SHELL_ALIGN(sizeof (struct nclist)),
1172 SHELL_ALIGN(sizeof (struct narg)),
1173 SHELL_ALIGN(sizeof (struct narg)),
1174 SHELL_ALIGN(sizeof (struct nfile)),
1175 SHELL_ALIGN(sizeof (struct nfile)),
1176 SHELL_ALIGN(sizeof (struct nfile)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct ndup)),
1180 SHELL_ALIGN(sizeof (struct ndup)),
1181 SHELL_ALIGN(sizeof (struct nhere)),
1182 SHELL_ALIGN(sizeof (struct nhere)),
1183 SHELL_ALIGN(sizeof (struct nnot)),
1187 static void calcsize(union node *);
1188 static void sizenodelist(struct nodelist *);
1189 static union node *copynode(union node *);
1190 static struct nodelist *copynodelist(struct nodelist *);
1191 static char *nodesavestr(char *);
1194 static int evalstring(char *, int mask);
1195 union node; /* BLETCH for ansi C */
1196 static void evaltree(union node *, int);
1197 static void evalbackcmd(union node *, struct backcmd *);
1199 static int evalskip; /* set if we are skipping commands */
1200 static int skipcount; /* number of levels to skip */
1201 static int funcnest; /* depth of function calls */
1203 /* reasons for skipping commands (see comment on breakcmd routine) */
1204 #define SKIPBREAK (1 << 0)
1205 #define SKIPCONT (1 << 1)
1206 #define SKIPFUNC (1 << 2)
1207 #define SKIPFILE (1 << 3)
1208 #define SKIPEVAL (1 << 4)
1211 * This file was generated by the mkbuiltins program.
1215 static int bgcmd(int, char **);
1217 static int breakcmd(int, char **);
1218 static int cdcmd(int, char **);
1219 #ifdef CONFIG_ASH_CMDCMD
1220 static int commandcmd(int, char **);
1222 static int dotcmd(int, char **);
1223 static int evalcmd(int, char **);
1224 #ifdef CONFIG_ASH_BUILTIN_ECHO
1225 static int echocmd(int, char **);
1227 #ifdef CONFIG_ASH_BUILTIN_TEST
1228 static int testcmd(int, char **);
1230 static int execcmd(int, char **);
1231 static int exitcmd(int, char **);
1232 static int exportcmd(int, char **);
1233 static int falsecmd(int, char **);
1235 static int fgcmd(int, char **);
1237 #ifdef CONFIG_ASH_GETOPTS
1238 static int getoptscmd(int, char **);
1240 static int hashcmd(int, char **);
1241 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1242 static int helpcmd(int argc, char **argv);
1245 static int jobscmd(int, char **);
1247 #ifdef CONFIG_ASH_MATH_SUPPORT
1248 static int letcmd(int, char **);
1250 static int localcmd(int, char **);
1251 static int pwdcmd(int, char **);
1252 static int readcmd(int, char **);
1253 static int returncmd(int, char **);
1254 static int setcmd(int, char **);
1255 static int shiftcmd(int, char **);
1256 static int timescmd(int, char **);
1257 static int trapcmd(int, char **);
1258 static int truecmd(int, char **);
1259 static int typecmd(int, char **);
1260 static int umaskcmd(int, char **);
1261 static int unsetcmd(int, char **);
1262 static int waitcmd(int, char **);
1263 static int ulimitcmd(int, char **);
1265 static int killcmd(int, char **);
1270 #ifdef CONFIG_ASH_MAIL
1271 static void chkmail(void);
1272 static void changemail(const char *);
1277 /* values of cmdtype */
1278 #define CMDUNKNOWN -1 /* no entry in table for command */
1279 #define CMDNORMAL 0 /* command is an executable program */
1280 #define CMDFUNCTION 1 /* command is a shell function */
1281 #define CMDBUILTIN 2 /* command is a shell builtin */
1285 int (*builtin)(int, char **);
1286 /* unsigned flags; */
1290 #define COMMANDCMD (builtincmd + 5 + \
1291 2 * ENABLE_ASH_BUILTIN_TEST + \
1292 ENABLE_ASH_ALIAS + \
1293 ENABLE_ASH_JOB_CONTROL)
1294 #define EXECCMD (builtincmd + 7 + \
1295 2 * ENABLE_ASH_BUILTIN_TEST + \
1296 ENABLE_ASH_ALIAS + \
1297 ENABLE_ASH_JOB_CONTROL + \
1298 ENABLE_ASH_CMDCMD + \
1299 ENABLE_ASH_BUILTIN_ECHO)
1301 #define BUILTIN_NOSPEC "0"
1302 #define BUILTIN_SPECIAL "1"
1303 #define BUILTIN_REGULAR "2"
1304 #define BUILTIN_SPEC_REG "3"
1305 #define BUILTIN_ASSIGN "4"
1306 #define BUILTIN_SPEC_ASSG "5"
1307 #define BUILTIN_REG_ASSG "6"
1308 #define BUILTIN_SPEC_REG_ASSG "7"
1310 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1311 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1312 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1314 /* make sure to keep these in proper order since it is searched via bsearch() */
1315 static const struct builtincmd builtincmd[] = {
1316 { BUILTIN_SPEC_REG ".", dotcmd },
1317 { BUILTIN_SPEC_REG ":", truecmd },
1318 #ifdef CONFIG_ASH_BUILTIN_TEST
1319 { BUILTIN_REGULAR "[", testcmd },
1320 { BUILTIN_REGULAR "[[", testcmd },
1322 #ifdef CONFIG_ASH_ALIAS
1323 { BUILTIN_REG_ASSG "alias", aliascmd },
1326 { BUILTIN_REGULAR "bg", bgcmd },
1328 { BUILTIN_SPEC_REG "break", breakcmd },
1329 { BUILTIN_REGULAR "cd", cdcmd },
1330 { BUILTIN_NOSPEC "chdir", cdcmd },
1331 #ifdef CONFIG_ASH_CMDCMD
1332 { BUILTIN_REGULAR "command", commandcmd },
1334 { BUILTIN_SPEC_REG "continue", breakcmd },
1335 #ifdef CONFIG_ASH_BUILTIN_ECHO
1336 { BUILTIN_REGULAR "echo", echocmd },
1338 { BUILTIN_SPEC_REG "eval", evalcmd },
1339 { BUILTIN_SPEC_REG "exec", execcmd },
1340 { BUILTIN_SPEC_REG "exit", exitcmd },
1341 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1342 { BUILTIN_REGULAR "false", falsecmd },
1344 { BUILTIN_REGULAR "fg", fgcmd },
1346 #ifdef CONFIG_ASH_GETOPTS
1347 { BUILTIN_REGULAR "getopts", getoptscmd },
1349 { BUILTIN_NOSPEC "hash", hashcmd },
1350 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1351 { BUILTIN_NOSPEC "help", helpcmd },
1354 { BUILTIN_REGULAR "jobs", jobscmd },
1355 { BUILTIN_REGULAR "kill", killcmd },
1357 #ifdef CONFIG_ASH_MATH_SUPPORT
1358 { BUILTIN_NOSPEC "let", letcmd },
1360 { BUILTIN_ASSIGN "local", localcmd },
1361 { BUILTIN_NOSPEC "pwd", pwdcmd },
1362 { BUILTIN_REGULAR "read", readcmd },
1363 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1364 { BUILTIN_SPEC_REG "return", returncmd },
1365 { BUILTIN_SPEC_REG "set", setcmd },
1366 { BUILTIN_SPEC_REG "shift", shiftcmd },
1367 { BUILTIN_SPEC_REG "source", dotcmd },
1368 #ifdef CONFIG_ASH_BUILTIN_TEST
1369 { BUILTIN_REGULAR "test", testcmd },
1371 { BUILTIN_SPEC_REG "times", timescmd },
1372 { BUILTIN_SPEC_REG "trap", trapcmd },
1373 { BUILTIN_REGULAR "true", truecmd },
1374 { BUILTIN_NOSPEC "type", typecmd },
1375 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1376 { BUILTIN_REGULAR "umask", umaskcmd },
1377 #ifdef CONFIG_ASH_ALIAS
1378 { BUILTIN_REGULAR "unalias", unaliascmd },
1380 { BUILTIN_SPEC_REG "unset", unsetcmd },
1381 { BUILTIN_REGULAR "wait", waitcmd },
1384 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1386 static const char *safe_applets[] = {
1387 "[", "test", "echo", "cat",
1388 "ln", "cp", "touch", "mkdir", "rm",
1389 "cut", "hexdump", "awk", "sort",
1390 "find", "xargs", "ls", "dd",
1399 const struct builtincmd *cmd;
1400 struct funcnode *func;
1405 /* action to find_command() */
1406 #define DO_ERR 0x01 /* prints errors */
1407 #define DO_ABS 0x02 /* checks absolute paths */
1408 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1409 #define DO_ALTPATH 0x08 /* using alternate path */
1410 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1412 static const char *pathopt; /* set by padvance */
1414 static void shellexec(char **, const char *, int)
1416 static char *padvance(const char **, const char *);
1417 static void find_command(char *, struct cmdentry *, int, const char *);
1418 static struct builtincmd *find_builtin(const char *);
1419 static void hashcd(void);
1420 static void changepath(const char *);
1421 static void defun(char *, union node *);
1422 static void unsetfunc(const char *);
1424 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1425 typedef int64_t arith_t;
1426 #define arith_t_type (long long)
1428 typedef long arith_t;
1429 #define arith_t_type (long)
1432 #ifdef CONFIG_ASH_MATH_SUPPORT
1433 static arith_t dash_arith(const char *);
1434 static arith_t arith(const char *expr, int *perrcode);
1437 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1438 static unsigned long rseed;
1439 static void change_random(const char *);
1440 # ifndef DYNAMIC_VAR
1441 # define DYNAMIC_VAR
1447 static void reset(void);
1456 #define VEXPORT 0x01 /* variable is exported */
1457 #define VREADONLY 0x02 /* variable cannot be modified */
1458 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1459 #define VTEXTFIXED 0x08 /* text is statically allocated */
1460 #define VSTACK 0x10 /* text is allocated on the stack */
1461 #define VUNSET 0x20 /* the variable is not set */
1462 #define VNOFUNC 0x40 /* don't call the callback function */
1463 #define VNOSET 0x80 /* do not set variable - just readonly test */
1464 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1466 # define VDYNAMIC 0x200 /* dynamic variable */
1472 struct var *next; /* next entry in hash list */
1473 int flags; /* flags are defined above */
1474 const char *text; /* name=value */
1475 void (*func)(const char *); /* function to be called when */
1476 /* the variable gets set/unset */
1480 struct localvar *next; /* next local variable in list */
1481 struct var *vp; /* the variable that was made local */
1482 int flags; /* saved flags */
1483 const char *text; /* saved text */
1487 static struct localvar *localvars;
1493 #ifdef CONFIG_ASH_GETOPTS
1494 static void getoptsreset(const char *);
1497 #ifdef CONFIG_LOCALE_SUPPORT
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 (LONE_DASH(dest)) {
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 memset(&fn, 0, sizeof(struct arglist));
3046 fn.lastp = &fn.list;
3047 switch (redir->type) {
3053 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3054 redir->nfile.expfname = fn.list->text;
3058 if (redir->ndup.vname) {
3059 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3060 if (fn.list != NULL)
3061 fixredir(redir, fn.list->text, 1);
3063 sh_error("redir error");
3073 * Evaluate a pipeline. All the processes in the pipeline are children
3074 * of the process creating the pipeline. (This differs from some versions
3075 * of the shell, which make the last process in a pipeline the parent
3080 evalpipe(union node *n, int flags)
3083 struct nodelist *lp;
3088 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3090 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3094 jp = makejob(n, pipelen);
3096 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3100 if (pipe(pip) < 0) {
3102 sh_error("Pipe call failed");
3105 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3118 evaltreenr(lp->n, flags);
3126 if (n->npipe.backgnd == 0) {
3127 exitstatus = waitforjob(jp);
3128 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3136 * Execute a command inside back quotes. If it's a builtin command, we
3137 * want to save its output in a block obtained from malloc. Otherwise
3138 * we fork off a subprocess and get the output of the command via a pipe.
3139 * Should be called with interrupts off.
3143 evalbackcmd(union node *n, struct backcmd *result)
3155 saveherefd = herefd;
3163 sh_error("Pipe call failed");
3165 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3174 evaltreenr(n, EV_EXIT);
3178 result->fd = pip[0];
3181 herefd = saveherefd;
3183 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3184 result->fd, result->buf, result->nleft, result->jp));
3187 #ifdef CONFIG_ASH_CMDCMD
3188 static char ** parse_command_args(char **argv, const char **path)
3200 if (c == '-' && !*cp) {
3210 /* run 'typecmd' for other options */
3213 } while ((c = *cp++));
3219 static int isassignment(const char *p)
3221 const char *q = endofname(p);
3227 #ifdef CONFIG_ASH_EXPAND_PRMT
3228 static const char *expandstr(const char *ps);
3230 #define expandstr(s) s
3234 * Execute a simple command.
3238 evalcommand(union node *cmd, int flags)
3240 struct stackmark smark;
3242 struct arglist arglist;
3243 struct arglist varlist;
3246 const struct strlist *sp;
3247 struct cmdentry cmdentry;
3255 struct builtincmd *bcmd;
3256 int pseudovarflag = 0;
3258 /* First expand the arguments. */
3259 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3260 setstackmark(&smark);
3261 back_exitstatus = 0;
3263 cmdentry.cmdtype = CMDBUILTIN;
3264 cmdentry.u.cmd = &bltin;
3265 varlist.lastp = &varlist.list;
3266 *varlist.lastp = NULL;
3267 arglist.lastp = &arglist.list;
3268 *arglist.lastp = NULL;
3273 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3274 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3277 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3278 struct strlist **spp;
3280 spp = arglist.lastp;
3281 if (pseudovarflag && isassignment(argp->narg.text))
3282 expandarg(argp, &arglist, EXP_VARTILDE);
3284 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3286 for (sp = *spp; sp; sp = sp->next)
3290 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3291 for (sp = arglist.list ; sp ; sp = sp->next) {
3292 TRACE(("evalcommand arg: %s\n", sp->text));
3293 *nargv++ = sp->text;
3298 if (iflag && funcnest == 0 && argc > 0)
3299 lastarg = nargv[-1];
3302 expredir(cmd->ncmd.redirect);
3303 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3306 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3307 struct strlist **spp;
3310 spp = varlist.lastp;
3311 expandarg(argp, &varlist, EXP_VARTILDE);
3314 * Modify the command lookup path, if a PATH= assignment
3318 if (varequal(p, path))
3322 /* Print the command if xflag is set. */
3325 const char *p = " %s";
3328 dprintf(preverrout_fd, p, expandstr(ps4val()));
3331 for(n = 0; n < 2; n++) {
3333 dprintf(preverrout_fd, p, sp->text);
3341 full_write(preverrout_fd, "\n", 1);
3347 /* Now locate the command. */
3349 const char *oldpath;
3350 int cmd_flag = DO_ERR;
3355 find_command(argv[0], &cmdentry, cmd_flag, path);
3356 if (cmdentry.cmdtype == CMDUNKNOWN) {
3362 /* implement bltin and command here */
3363 if (cmdentry.cmdtype != CMDBUILTIN)
3366 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3367 if (cmdentry.u.cmd == EXECCMD)
3369 #ifdef CONFIG_ASH_CMDCMD
3370 if (cmdentry.u.cmd == COMMANDCMD) {
3373 nargv = parse_command_args(argv, &path);
3376 argc -= nargv - argv;
3378 cmd_flag |= DO_NOFUNC;
3386 /* We have a redirection error. */
3390 exitstatus = status;
3394 /* Execute the command. */
3395 switch (cmdentry.cmdtype) {
3397 /* Fork off a child process if necessary. */
3398 if (!(flags & EV_EXIT) || trap[0]) {
3400 jp = makejob(cmd, 1);
3401 if (forkshell(jp, cmd, FORK_FG) != 0) {
3402 exitstatus = waitforjob(jp);
3408 listsetvar(varlist.list, VEXPORT|VSTACK);
3409 shellexec(argv, path, cmdentry.u.index);
3413 cmdenviron = varlist.list;
3415 struct strlist *list = cmdenviron;
3417 if (spclbltin > 0 || argc == 0) {
3419 if (cmd_is_exec && argc > 1)
3422 listsetvar(list, i);
3424 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3439 exit_status = j + 128;
3440 exitstatus = exit_status;
3442 if (i == EXINT || spclbltin > 0) {
3444 longjmp(handler->loc, 1);
3451 listsetvar(varlist.list, 0);
3452 if (evalfun(cmdentry.u.func, argc, argv, flags))
3458 popredir(cmd_is_exec);
3460 /* dsl: I think this is intended to be used to support
3461 * '_' in 'vi' command mode during line editing...
3462 * However I implemented that within libedit itself.
3464 setvar("_", lastarg, 0);
3465 popstackmark(&smark);
3469 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3470 char *volatile savecmdname;
3471 struct jmploc *volatile savehandler;
3472 struct jmploc jmploc;
3475 savecmdname = commandname;
3476 if ((i = setjmp(jmploc.loc)))
3478 savehandler = handler;
3480 commandname = argv[0];
3482 optptr = NULL; /* initialize nextopt */
3483 exitstatus = (*cmd->builtin)(argc, argv);
3486 exitstatus |= ferror(stdout);
3488 commandname = savecmdname;
3490 handler = savehandler;
3496 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3498 volatile struct shparam saveparam;
3499 struct localvar *volatile savelocalvars;
3500 struct jmploc *volatile savehandler;
3501 struct jmploc jmploc;
3504 saveparam = shellparam;
3505 savelocalvars = localvars;
3506 if ((e = setjmp(jmploc.loc))) {
3510 savehandler = handler;
3513 shellparam.malloc = 0;
3517 shellparam.nparam = argc - 1;
3518 shellparam.p = argv + 1;
3519 #ifdef CONFIG_ASH_GETOPTS
3520 shellparam.optind = 1;
3521 shellparam.optoff = -1;
3523 evaltree(&func->n, flags & EV_TESTED);
3529 localvars = savelocalvars;
3530 freeparam(&shellparam);
3531 shellparam = saveparam;
3532 handler = savehandler;
3534 evalskip &= ~SKIPFUNC;
3539 static int goodname(const char *p)
3541 return !*endofname(p);
3545 * Search for a command. This is called before we fork so that the
3546 * location of the command will be available in the parent as well as
3547 * the child. The check for "goodname" is an overly conservative
3548 * check that the name will not be subject to expansion.
3552 prehash(union node *n)
3554 struct cmdentry entry;
3556 if (n->type == NCMD && n->ncmd.args)
3557 if (goodname(n->ncmd.args->narg.text))
3558 find_command(n->ncmd.args->narg.text, &entry, 0,
3565 * Builtin commands. Builtin commands whose functions are closely
3566 * tied to evaluation are implemented here.
3574 bltincmd(int argc, char **argv)
3577 * Preserve exitstatus of a previous possible redirection
3580 return back_exitstatus;
3585 * Handle break and continue commands. Break, continue, and return are
3586 * all handled by setting the evalskip flag. The evaluation routines
3587 * above all check this flag, and if it is set they start skipping
3588 * commands rather than executing them. The variable skipcount is
3589 * the number of loops to break/continue, or the number of function
3590 * levels to return. (The latter is always 1.) It should probably
3591 * be an error to break out of more loops than exist, but it isn't
3592 * in the standard shell so we don't make it one here.
3596 breakcmd(int argc, char **argv)
3598 int n = argc > 1 ? number(argv[1]) : 1;
3601 sh_error(illnum, argv[1]);
3605 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3613 * The return command.
3617 returncmd(int argc, char **argv)
3620 * If called outside a function, do what ksh does;
3621 * skip the rest of the file.
3623 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3624 return argv[1] ? number(argv[1]) : exitstatus;
3629 falsecmd(int argc, char **argv)
3636 truecmd(int argc, char **argv)
3643 execcmd(int argc, char **argv)
3646 iflag = 0; /* exit on error */
3649 shellexec(argv + 1, pathval(), 0);
3658 * When commands are first encountered, they are entered in a hash table.
3659 * This ensures that a full path search will not have to be done for them
3660 * on each invocation.
3662 * We should investigate converting to a linear search, even though that
3663 * would make the command name "hash" a misnomer.
3666 #define CMDTABLESIZE 31 /* should be prime */
3667 #define ARB 1 /* actual size determined at run time */
3672 struct tblentry *next; /* next entry in hash chain */
3673 union param param; /* definition of builtin function */
3674 short cmdtype; /* index identifying command */
3675 char rehash; /* if set, cd done since entry created */
3676 char cmdname[ARB]; /* name of command */
3680 static struct tblentry *cmdtable[CMDTABLESIZE];
3681 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3684 static void tryexec(char *, char **, char **);
3685 static void clearcmdentry(int);
3686 static struct tblentry *cmdlookup(const char *, int);
3687 static void delete_cmd_entry(void);
3691 * Exec a program. Never returns. If you change this routine, you may
3692 * have to change the find_command routine as well.
3696 shellexec(char **argv, const char *path, int idx)
3704 envp = environment();
3705 if (strchr(argv[0], '/') != NULL
3706 || is_safe_applet(argv[0])
3707 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3708 || find_applet_by_name(argv[0])
3711 tryexec(argv[0], argv, envp);
3715 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3716 if (--idx < 0 && pathopt == NULL) {
3717 tryexec(cmdname, argv, envp);
3718 if (errno != ENOENT && errno != ENOTDIR)
3725 /* Map to POSIX errors */
3737 exitstatus = exerrno;
3738 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3739 argv[0], e, suppressint ));
3740 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3746 tryexec(char *cmd, char **argv, char **envp)
3749 struct BB_applet *a;
3753 if(strchr(cmd, '/') == NULL && is_safe_applet(cmd) && (a = find_applet_by_name(cmd)) != NULL) {
3755 while (*c != NULL) {
3759 exit(a->main(argc, argv));
3761 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3762 if(find_applet_by_name(cmd) != NULL) {
3763 /* re-exec ourselves with the new arguments */
3764 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3765 /* If they called chroot or otherwise made the binary no longer
3766 * executable, fall through */
3773 execve(cmd, argv, envp);
3774 } while (errno == EINTR);
3776 execve(cmd, argv, envp);
3780 } else if (errno == ENOEXEC) {
3784 for (ap = argv; *ap; ap++)
3786 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3788 *ap = cmd = (char *)DEFAULT_SHELL;
3791 while ((*ap++ = *argv++))
3801 * Do a path search. The variable path (passed by reference) should be
3802 * set to the start of the path before the first call; padvance will update
3803 * this value as it proceeds. Successive calls to padvance will return
3804 * the possible path expansions in sequence. If an option (indicated by
3805 * a percent sign) appears in the path entry then the global variable
3806 * pathopt will be set to point to it; otherwise pathopt will be set to
3811 padvance(const char **path, const char *name)
3821 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3822 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3823 while (stackblocksize() < len)
3827 memcpy(q, start, p - start);
3835 while (*p && *p != ':') p++;
3841 return stalloc(len);
3845 /*** Command hashing code ***/
3848 printentry(struct tblentry *cmdp)
3854 idx = cmdp->param.index;
3857 name = padvance(&path, cmdp->cmdname);
3859 } while (--idx >= 0);
3860 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3865 hashcmd(int argc, char **argv)
3867 struct tblentry **pp;
3868 struct tblentry *cmdp;
3870 struct cmdentry entry;
3873 while ((c = nextopt("r")) != '\0') {
3877 if (*argptr == NULL) {
3878 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3879 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3880 if (cmdp->cmdtype == CMDNORMAL)
3887 while ((name = *argptr) != NULL) {
3888 if ((cmdp = cmdlookup(name, 0)) != NULL
3889 && (cmdp->cmdtype == CMDNORMAL
3890 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3892 find_command(name, &entry, DO_ERR, pathval());
3893 if (entry.cmdtype == CMDUNKNOWN)
3902 * Resolve a command name. If you change this routine, you may have to
3903 * change the shellexec routine as well.
3907 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3909 struct tblentry *cmdp;
3916 struct builtincmd *bcmd;
3918 /* If name contains a slash, don't use PATH or hash table */
3919 if (strchr(name, '/') != NULL) {
3920 entry->u.index = -1;
3922 while (stat(name, &statb) < 0) {
3927 entry->cmdtype = CMDUNKNOWN;
3931 entry->cmdtype = CMDNORMAL;
3935 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3936 if (find_applet_by_name(name)) {
3937 entry->cmdtype = CMDNORMAL;
3938 entry->u.index = -1;
3943 if (is_safe_applet(name)) {
3944 entry->cmdtype = CMDNORMAL;
3945 entry->u.index = -1;
3949 updatetbl = (path == pathval());
3952 if (strstr(path, "%builtin") != NULL)
3956 /* If name is in the table, check answer will be ok */
3957 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3960 switch (cmdp->cmdtype) {
3978 } else if (cmdp->rehash == 0)
3979 /* if not invalidated by cd, we're done */
3983 /* If %builtin not in path, check for builtin next */
3984 bcmd = find_builtin(name);
3985 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3986 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3988 goto builtin_success;
3990 /* We have to search path. */
3991 prev = -1; /* where to start */
3992 if (cmdp && cmdp->rehash) { /* doing a rehash */
3993 if (cmdp->cmdtype == CMDBUILTIN)
3996 prev = cmdp->param.index;
4002 while ((fullname = padvance(&path, name)) != NULL) {
4003 stunalloc(fullname);
4006 if (prefix(pathopt, "builtin")) {
4008 goto builtin_success;
4010 } else if (!(act & DO_NOFUNC) &&
4011 prefix(pathopt, "func")) {
4014 /* ignore unimplemented options */
4018 /* if rehash, don't redo absolute path names */
4019 if (fullname[0] == '/' && idx <= prev) {
4022 TRACE(("searchexec \"%s\": no change\n", name));
4025 while (stat(fullname, &statb) < 0) {
4030 if (errno != ENOENT && errno != ENOTDIR)
4034 e = EACCES; /* if we fail, this will be the error */
4035 if (!S_ISREG(statb.st_mode))
4037 if (pathopt) { /* this is a %func directory */
4038 stalloc(strlen(fullname) + 1);
4039 readcmdfile(fullname);
4040 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4041 cmdp->cmdtype != CMDFUNCTION)
4042 sh_error("%s not defined in %s", name, fullname);
4043 stunalloc(fullname);
4046 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4048 entry->cmdtype = CMDNORMAL;
4049 entry->u.index = idx;
4053 cmdp = cmdlookup(name, 1);
4054 cmdp->cmdtype = CMDNORMAL;
4055 cmdp->param.index = idx;
4060 /* We failed. If there was an entry for this command, delete it */
4061 if (cmdp && updatetbl)
4064 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4065 entry->cmdtype = CMDUNKNOWN;
4070 entry->cmdtype = CMDBUILTIN;
4071 entry->u.cmd = bcmd;
4075 cmdp = cmdlookup(name, 1);
4076 cmdp->cmdtype = CMDBUILTIN;
4077 cmdp->param.cmd = bcmd;
4081 entry->cmdtype = cmdp->cmdtype;
4082 entry->u = cmdp->param;
4087 * Wrapper around strcmp for qsort/bsearch/...
4089 static int pstrcmp(const void *a, const void *b)
4091 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4095 * Search the table of builtin commands.
4098 static struct builtincmd *
4099 find_builtin(const char *name)
4101 struct builtincmd *bp;
4104 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4113 * Called when a cd is done. Marks all commands so the next time they
4114 * are executed they will be rehashed.
4120 struct tblentry **pp;
4121 struct tblentry *cmdp;
4123 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4124 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4125 if (cmdp->cmdtype == CMDNORMAL || (
4126 cmdp->cmdtype == CMDBUILTIN &&
4127 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4138 * Fix command hash table when PATH changed.
4139 * Called before PATH is changed. The argument is the new value of PATH;
4140 * pathval() still returns the old value at this point.
4141 * Called with interrupts off.
4145 changepath(const char *newval)
4147 const char *old, *new;
4154 firstchange = 9999; /* assume no change */
4160 if ((*old == '\0' && *new == ':')
4161 || (*old == ':' && *new == '\0'))
4163 old = new; /* ignore subsequent differences */
4167 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4174 if (builtinloc < 0 && idx_bltin >= 0)
4175 builtinloc = idx_bltin; /* zap builtins */
4176 if (builtinloc >= 0 && idx_bltin < 0)
4178 clearcmdentry(firstchange);
4179 builtinloc = idx_bltin;
4184 * Clear out command entries. The argument specifies the first entry in
4185 * PATH which has changed.
4189 clearcmdentry(int firstchange)
4191 struct tblentry **tblp;
4192 struct tblentry **pp;
4193 struct tblentry *cmdp;
4196 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4198 while ((cmdp = *pp) != NULL) {
4199 if ((cmdp->cmdtype == CMDNORMAL &&
4200 cmdp->param.index >= firstchange)
4201 || (cmdp->cmdtype == CMDBUILTIN &&
4202 builtinloc >= firstchange)) {
4216 * Locate a command in the command hash table. If "add" is nonzero,
4217 * add the command to the table if it is not already present. The
4218 * variable "lastcmdentry" is set to point to the address of the link
4219 * pointing to the entry, so that delete_cmd_entry can delete the
4222 * Interrupts must be off if called with add != 0.
4225 static struct tblentry **lastcmdentry;
4228 static struct tblentry *
4229 cmdlookup(const char *name, int add)
4231 unsigned int hashval;
4233 struct tblentry *cmdp;
4234 struct tblentry **pp;
4237 hashval = (unsigned char)*p << 4;
4239 hashval += (unsigned char)*p++;
4241 pp = &cmdtable[hashval % CMDTABLESIZE];
4242 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4243 if (equal(cmdp->cmdname, name))
4247 if (add && cmdp == NULL) {
4248 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4249 + strlen(name) + 1);
4251 cmdp->cmdtype = CMDUNKNOWN;
4252 strcpy(cmdp->cmdname, name);
4259 * Delete the command entry returned on the last lookup.
4263 delete_cmd_entry(void)
4265 struct tblentry *cmdp;
4268 cmdp = *lastcmdentry;
4269 *lastcmdentry = cmdp->next;
4270 if (cmdp->cmdtype == CMDFUNCTION)
4271 freefunc(cmdp->param.func);
4278 * Add a new command entry, replacing any existing command entry for
4279 * the same name - except special builtins.
4282 static void addcmdentry(char *name, struct cmdentry *entry)
4284 struct tblentry *cmdp;
4286 cmdp = cmdlookup(name, 1);
4287 if (cmdp->cmdtype == CMDFUNCTION) {
4288 freefunc(cmdp->param.func);
4290 cmdp->cmdtype = entry->cmdtype;
4291 cmdp->param = entry->u;
4296 * Make a copy of a parse tree.
4299 static struct funcnode * copyfunc(union node *n)
4304 funcblocksize = offsetof(struct funcnode, n);
4307 blocksize = funcblocksize;
4308 f = ckmalloc(blocksize + funcstringsize);
4309 funcblock = (char *) f + offsetof(struct funcnode, n);
4310 funcstring = (char *) f + blocksize;
4317 * Define a shell function.
4321 defun(char *name, union node *func)
4323 struct cmdentry entry;
4326 entry.cmdtype = CMDFUNCTION;
4327 entry.u.func = copyfunc(func);
4328 addcmdentry(name, &entry);
4334 * Delete a function if it exists.
4338 unsetfunc(const char *name)
4340 struct tblentry *cmdp;
4342 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4343 cmdp->cmdtype == CMDFUNCTION)
4348 * Locate and print what a word is...
4352 #ifdef CONFIG_ASH_CMDCMD
4354 describe_command(char *command, int describe_command_verbose)
4356 #define describe_command_verbose 1
4358 describe_command(char *command)
4361 struct cmdentry entry;
4362 struct tblentry *cmdp;
4363 #ifdef CONFIG_ASH_ALIAS
4364 const struct alias *ap;
4366 const char *path = pathval();
4368 if (describe_command_verbose) {
4372 /* First look at the keywords */
4373 if (findkwd(command)) {
4374 out1str(describe_command_verbose ? " is a shell keyword" : command);
4378 #ifdef CONFIG_ASH_ALIAS
4379 /* Then look at the aliases */
4380 if ((ap = lookupalias(command, 0)) != NULL) {
4381 if (describe_command_verbose) {
4382 out1fmt(" is an alias for %s", ap->val);
4391 /* Then check if it is a tracked alias */
4392 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4393 entry.cmdtype = cmdp->cmdtype;
4394 entry.u = cmdp->param;
4396 /* Finally use brute force */
4397 find_command(command, &entry, DO_ABS, path);
4400 switch (entry.cmdtype) {
4402 int j = entry.u.index;
4408 p = padvance(&path, command);
4412 if (describe_command_verbose) {
4414 (cmdp ? " a tracked alias for" : nullstr), p
4423 if (describe_command_verbose) {
4424 out1str(" is a shell function");
4431 if (describe_command_verbose) {
4432 out1fmt(" is a %sshell builtin",
4433 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4434 "special " : nullstr
4442 if (describe_command_verbose) {
4443 out1str(": not found\n");
4449 outstr("\n", stdout);
4454 typecmd(int argc, char **argv)
4459 for (i = 1; i < argc; i++) {
4460 #ifdef CONFIG_ASH_CMDCMD
4461 err |= describe_command(argv[i], 1);
4463 err |= describe_command(argv[i]);
4469 #ifdef CONFIG_ASH_CMDCMD
4471 commandcmd(int argc, char **argv)
4479 while ((c = nextopt("pvV")) != '\0')
4481 verify |= VERIFY_VERBOSE;
4483 verify |= VERIFY_BRIEF;
4489 return describe_command(*argptr, verify - VERIFY_BRIEF);
4498 * Routines to expand arguments to commands. We have to deal with
4499 * backquotes, shell variables, and file metacharacters.
4505 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4506 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4507 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4508 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4509 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4512 * Structure specifying which parts of the string should be searched
4513 * for IFS characters.
4517 struct ifsregion *next; /* next region in list */
4518 int begoff; /* offset of start of region */
4519 int endoff; /* offset of end of region */
4520 int nulonly; /* search for nul bytes only */
4523 /* output of current string */
4524 static char *expdest;
4525 /* list of back quote expressions */
4526 static struct nodelist *argbackq;
4527 /* first struct in list of ifs regions */
4528 static struct ifsregion ifsfirst;
4529 /* last struct in list */
4530 static struct ifsregion *ifslastp;
4531 /* holds expanded arg list */
4532 static struct arglist exparg;
4534 static void argstr(char *, int);
4535 static char *exptilde(char *, char *, int);
4536 static void expbackq(union node *, int, int);
4537 static const char *subevalvar(char *, char *, int, int, int, int, int);
4538 static char *evalvar(char *, int);
4539 static void strtodest(const char *, int, int);
4540 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4541 static ssize_t varvalue(char *, int, int);
4542 static void recordregion(int, int, int);
4543 static void removerecordregions(int);
4544 static void ifsbreakup(char *, struct arglist *);
4545 static void ifsfree(void);
4546 static void expandmeta(struct strlist *, int);
4547 static int patmatch(char *, const char *);
4549 static int cvtnum(arith_t);
4550 static size_t esclen(const char *, const char *);
4551 static char *scanleft(char *, char *, char *, char *, int, int);
4552 static char *scanright(char *, char *, char *, char *, int, int);
4553 static void varunset(const char *, const char *, const char *, int)
4557 #define pmatch(a, b) !fnmatch((a), (b), 0)
4559 * Prepare a pattern for a expmeta (internal glob(3)) call.
4561 * Returns an stalloced string.
4564 static char * preglob(const char *pattern, int quoted, int flag) {
4565 flag |= RMESCAPE_GLOB;
4567 flag |= RMESCAPE_QUOTED;
4569 return _rmescapes((char *)pattern, flag);
4574 esclen(const char *start, const char *p) {
4577 while (p > start && *--p == CTLESC) {
4585 * Expand shell variables and backquotes inside a here document.
4588 static void expandhere(union node *arg, int fd)
4591 expandarg(arg, (struct arglist *)NULL, 0);
4592 full_write(fd, stackblock(), expdest - (char *)stackblock());
4597 * Perform variable substitution and command substitution on an argument,
4598 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4599 * perform splitting and file name expansion. When arglist is NULL, perform
4600 * here document expansion.
4604 expandarg(union node *arg, struct arglist *arglist, int flag)
4609 argbackq = arg->narg.backquote;
4610 STARTSTACKSTR(expdest);
4611 ifsfirst.next = NULL;
4613 argstr(arg->narg.text, flag);
4614 p = _STPUTC('\0', expdest);
4616 if (arglist == NULL) {
4617 return; /* here document expanded */
4619 p = grabstackstr(p);
4620 exparg.lastp = &exparg.list;
4624 if (flag & EXP_FULL) {
4625 ifsbreakup(p, &exparg);
4626 *exparg.lastp = NULL;
4627 exparg.lastp = &exparg.list;
4628 expandmeta(exparg.list, flag);
4630 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4632 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4635 exparg.lastp = &sp->next;
4639 *exparg.lastp = NULL;
4641 *arglist->lastp = exparg.list;
4642 arglist->lastp = exparg.lastp;
4648 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4649 * characters to allow for further processing. Otherwise treat
4650 * $@ like $* since no splitting will be performed.
4654 argstr(char *p, int flag)
4656 static const char spclchars[] = {
4664 CTLBACKQ | CTLQUOTE,
4665 #ifdef CONFIG_ASH_MATH_SUPPORT
4670 const char *reject = spclchars;
4672 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4673 int breakall = flag & EXP_WORD;
4678 if (!(flag & EXP_VARTILDE)) {
4680 } else if (flag & EXP_VARTILDE2) {
4685 if (flag & EXP_TILDE) {
4691 if (*q == CTLESC && (flag & EXP_QWORD))
4694 p = exptilde(p, q, flag);
4697 startloc = expdest - (char *)stackblock();
4699 length += strcspn(p + length, reject);
4701 if (c && (!(c & 0x80)
4702 #ifdef CONFIG_ASH_MATH_SUPPORT
4706 /* c == '=' || c == ':' || c == CTLENDARI */
4711 expdest = stnputs(p, length, expdest);
4712 newloc = expdest - (char *)stackblock();
4713 if (breakall && !inquotes && newloc > startloc) {
4714 recordregion(startloc, newloc, 0);
4725 if (flag & EXP_VARTILDE2) {
4729 flag |= EXP_VARTILDE2;
4734 * sort of a hack - expand tildes in variable
4735 * assignments (after the first '=' and after ':'s).
4744 case CTLENDVAR: /* ??? */
4747 /* "$@" syntax adherence hack */
4750 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4751 (p[4] == CTLQUOTEMARK || (
4752 p[4] == CTLENDVAR &&
4753 p[5] == CTLQUOTEMARK
4756 p = evalvar(p + 1, flag) + 1;
4759 inquotes = !inquotes;
4772 p = evalvar(p, flag);
4776 case CTLBACKQ|CTLQUOTE:
4777 expbackq(argbackq->n, c, quotes);
4778 argbackq = argbackq->next;
4780 #ifdef CONFIG_ASH_MATH_SUPPORT
4793 exptilde(char *startp, char *p, int flag)
4799 int quotes = flag & (EXP_FULL | EXP_CASE);
4804 while ((c = *++p) != '\0') {
4811 if (flag & EXP_VARTILDE)
4821 if (*name == '\0') {
4822 home = lookupvar(homestr);
4824 if ((pw = getpwnam(name)) == NULL)
4828 if (!home || !*home)
4831 startloc = expdest - (char *)stackblock();
4832 strtodest(home, SQSYNTAX, quotes);
4833 recordregion(startloc, expdest - (char *)stackblock(), 0);
4842 removerecordregions(int endoff)
4844 if (ifslastp == NULL)
4847 if (ifsfirst.endoff > endoff) {
4848 while (ifsfirst.next != NULL) {
4849 struct ifsregion *ifsp;
4851 ifsp = ifsfirst.next->next;
4852 ckfree(ifsfirst.next);
4853 ifsfirst.next = ifsp;
4856 if (ifsfirst.begoff > endoff)
4859 ifslastp = &ifsfirst;
4860 ifsfirst.endoff = endoff;
4865 ifslastp = &ifsfirst;
4866 while (ifslastp->next && ifslastp->next->begoff < endoff)
4867 ifslastp=ifslastp->next;
4868 while (ifslastp->next != NULL) {
4869 struct ifsregion *ifsp;
4871 ifsp = ifslastp->next->next;
4872 ckfree(ifslastp->next);
4873 ifslastp->next = ifsp;
4876 if (ifslastp->endoff > endoff)
4877 ifslastp->endoff = endoff;
4881 #ifdef CONFIG_ASH_MATH_SUPPORT
4883 * Expand arithmetic expression. Backup to start of expression,
4884 * evaluate, place result in (backed up) result, adjust string position.
4897 * This routine is slightly over-complicated for
4898 * efficiency. Next we scan backwards looking for the
4899 * start of arithmetic.
4901 start = stackblock();
4908 while (*p != CTLARI) {
4912 sh_error("missing CTLARI (shouldn't happen)");
4917 esc = esclen(start, p);
4927 removerecordregions(begoff);
4936 len = cvtnum(dash_arith(p + 2));
4939 recordregion(begoff, begoff + len, 0);
4944 * Expand stuff in backwards quotes.
4948 expbackq(union node *cmd, int quoted, int quotes)
4956 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4957 struct stackmark smark;
4960 setstackmark(&smark);
4962 startloc = dest - (char *)stackblock();
4964 evalbackcmd(cmd, (struct backcmd *) &in);
4965 popstackmark(&smark);
4972 memtodest(p, i, syntax, quotes);
4976 i = safe_read(in.fd, buf, sizeof buf);
4977 TRACE(("expbackq: read returns %d\n", i));
4987 back_exitstatus = waitforjob(in.jp);
4991 /* Eat all trailing newlines */
4993 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4998 recordregion(startloc, dest - (char *)stackblock(), 0);
4999 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5000 (dest - (char *)stackblock()) - startloc,
5001 (dest - (char *)stackblock()) - startloc,
5002 stackblock() + startloc));
5007 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5018 const char *s = loc2;
5024 match = pmatch(str, s);
5028 if (quotes && *loc == CTLESC)
5038 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5045 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5048 const char *s = loc2;
5053 match = pmatch(str, s);
5060 esc = esclen(startp, loc);
5072 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5076 int saveherefd = herefd;
5077 struct nodelist *saveargbackq = argbackq;
5079 char *rmesc, *rmescend;
5081 char *(*scan)(char *, char *, char *, char *, int , int);
5084 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5085 STPUTC('\0', expdest);
5086 herefd = saveherefd;
5087 argbackq = saveargbackq;
5088 startp = stackblock() + startloc;
5092 setvar(str, startp, 0);
5093 amount = startp - expdest;
5094 STADJUST(amount, expdest);
5098 varunset(p, str, startp, varflags);
5102 subtype -= VSTRIMRIGHT;
5104 if (subtype < 0 || subtype > 3)
5109 rmescend = stackblock() + strloc;
5111 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5112 if (rmesc != startp) {
5114 startp = stackblock() + startloc;
5118 str = stackblock() + strloc;
5119 preglob(str, varflags & VSQUOTE, 0);
5121 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5122 zero = subtype >> 1;
5123 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5124 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5126 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5129 memmove(startp, loc, str - loc);
5130 loc = startp + (str - loc) - 1;
5133 amount = loc - expdest;
5134 STADJUST(amount, expdest);
5141 * Expand a variable, and return a pointer to the next character in the
5145 evalvar(char *p, int flag)
5158 quotes = flag & (EXP_FULL | EXP_CASE);
5160 subtype = varflags & VSTYPE;
5161 quoted = varflags & VSQUOTE;
5163 easy = (!quoted || (*var == '@' && shellparam.nparam));
5164 startloc = expdest - (char *)stackblock();
5165 p = strchr(p, '=') + 1;
5168 varlen = varvalue(var, varflags, flag);
5169 if (varflags & VSNUL)
5172 if (subtype == VSPLUS) {
5173 varlen = -1 - varlen;
5177 if (subtype == VSMINUS) {
5181 p, flag | EXP_TILDE |
5182 (quoted ? EXP_QWORD : EXP_WORD)
5191 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5193 if (subevalvar(p, var, 0, subtype, startloc,
5197 * Remove any recorded regions beyond
5200 removerecordregions(startloc);
5210 if (varlen < 0 && uflag)
5211 varunset(p, var, 0, 0);
5213 if (subtype == VSLENGTH) {
5214 cvtnum(varlen > 0 ? varlen : 0);
5218 if (subtype == VSNORMAL) {
5222 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5231 case VSTRIMRIGHTMAX:
5240 * Terminate the string and start recording the pattern
5243 STPUTC('\0', expdest);
5244 patloc = expdest - (char *)stackblock();
5245 if (subevalvar(p, NULL, patloc, subtype,
5246 startloc, varflags, quotes) == 0) {
5247 int amount = expdest - (
5248 (char *)stackblock() + patloc - 1
5250 STADJUST(-amount, expdest);
5252 /* Remove any recorded regions beyond start of variable */
5253 removerecordregions(startloc);
5258 if (subtype != VSNORMAL) { /* skip to end of alternative */
5261 if ((c = *p++) == CTLESC)
5263 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5265 argbackq = argbackq->next;
5266 } else if (c == CTLVAR) {
5267 if ((*p++ & VSTYPE) != VSNORMAL)
5269 } else if (c == CTLENDVAR) {
5280 * Put a string on the stack.
5284 memtodest(const char *p, size_t len, int syntax, int quotes) {
5287 q = makestrspace(len * 2, q);
5290 int c = SC2INT(*p++);
5293 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5303 strtodest(const char *p, int syntax, int quotes)
5305 memtodest(p, strlen(p), syntax, quotes);
5310 * Add the value of a specialized variable to the stack string.
5314 varvalue(char *name, int varflags, int flags)
5324 int quoted = varflags & VSQUOTE;
5325 int subtype = varflags & VSTYPE;
5326 int quotes = flags & (EXP_FULL | EXP_CASE);
5328 if (quoted && (flags & EXP_FULL))
5329 sep = 1 << CHAR_BIT;
5331 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5340 num = shellparam.nparam;
5350 p = makestrspace(NOPTS, expdest);
5351 for (i = NOPTS - 1; i >= 0; i--) {
5353 USTPUTC(optletters(i), p);
5364 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5365 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5368 if (!(ap = shellparam.p))
5370 while ((p = *ap++)) {
5373 partlen = strlen(p);
5376 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5377 memtodest(p, partlen, syntax, quotes);
5383 if (subtype == VSPLUS || subtype == VSLENGTH) {
5405 if (num < 0 || num > shellparam.nparam)
5407 p = num ? shellparam.p[num - 1] : arg0;
5410 p = lookupvar(name);
5416 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5417 memtodest(p, len, syntax, quotes);
5421 if (subtype == VSPLUS || subtype == VSLENGTH)
5422 STADJUST(-len, expdest);
5428 * Record the fact that we have to scan this region of the
5429 * string for IFS characters.
5433 recordregion(int start, int end, int nulonly)
5435 struct ifsregion *ifsp;
5437 if (ifslastp == NULL) {
5441 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5443 ifslastp->next = ifsp;
5447 ifslastp->begoff = start;
5448 ifslastp->endoff = end;
5449 ifslastp->nulonly = nulonly;
5454 * Break the argument string into pieces based upon IFS and add the
5455 * strings to the argument list. The regions of the string to be
5456 * searched for IFS characters have been stored by recordregion.
5459 ifsbreakup(char *string, struct arglist *arglist)
5461 struct ifsregion *ifsp;
5466 const char *ifs, *realifs;
5472 if (ifslastp != NULL) {
5475 realifs = ifsset() ? ifsval() : defifs;
5478 p = string + ifsp->begoff;
5479 nulonly = ifsp->nulonly;
5480 ifs = nulonly ? nullstr : realifs;
5482 while (p < string + ifsp->endoff) {
5486 if (strchr(ifs, *p)) {
5488 ifsspc = (strchr(defifs, *p) != NULL);
5489 /* Ignore IFS whitespace at start */
5490 if (q == start && ifsspc) {
5496 sp = (struct strlist *)stalloc(sizeof *sp);
5498 *arglist->lastp = sp;
5499 arglist->lastp = &sp->next;
5503 if (p >= string + ifsp->endoff) {
5509 if (strchr(ifs, *p) == NULL ) {
5512 } else if (strchr(defifs, *p) == NULL) {
5528 } while ((ifsp = ifsp->next) != NULL);
5537 sp = (struct strlist *)stalloc(sizeof *sp);
5539 *arglist->lastp = sp;
5540 arglist->lastp = &sp->next;
5546 struct ifsregion *p;
5551 struct ifsregion *ifsp;
5557 ifsfirst.next = NULL;
5561 static void expmeta(char *, char *);
5562 static struct strlist *expsort(struct strlist *);
5563 static struct strlist *msort(struct strlist *, int);
5565 static char *expdir;
5569 expandmeta(struct strlist *str, int flag)
5571 static const char metachars[] = {
5574 /* TODO - EXP_REDIR */
5577 struct strlist **savelastp;
5583 if (!strpbrk(str->text, metachars))
5585 savelastp = exparg.lastp;
5588 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5590 int i = strlen(str->text);
5591 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5599 if (exparg.lastp == savelastp) {
5604 *exparg.lastp = str;
5605 rmescapes(str->text);
5606 exparg.lastp = &str->next;
5608 *exparg.lastp = NULL;
5609 *savelastp = sp = expsort(*savelastp);
5610 while (sp->next != NULL)
5612 exparg.lastp = &sp->next;
5619 * Add a file name to the list.
5623 addfname(const char *name)
5627 sp = (struct strlist *)stalloc(sizeof *sp);
5628 sp->text = sstrdup(name);
5630 exparg.lastp = &sp->next;
5635 * Do metacharacter (i.e. *, ?, [...]) expansion.
5639 expmeta(char *enddir, char *name)
5654 for (p = name; *p; p++) {
5655 if (*p == '*' || *p == '?')
5657 else if (*p == '[') {
5664 if (*q == '/' || *q == '\0')
5671 } else if (*p == '\\')
5673 else if (*p == '/') {
5680 if (metaflag == 0) { /* we've reached the end of the file name */
5681 if (enddir != expdir)
5689 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5700 } while (p < start);
5702 if (enddir == expdir) {
5704 } else if (enddir == expdir + 1 && *expdir == '/') {
5710 if ((dirp = opendir(cp)) == NULL)
5712 if (enddir != expdir)
5714 if (*endname == 0) {
5726 while (! intpending && (dp = readdir(dirp)) != NULL) {
5727 if (dp->d_name[0] == '.' && ! matchdot)
5729 if (pmatch(start, dp->d_name)) {
5731 scopy(dp->d_name, enddir);
5734 for (p = enddir, cp = dp->d_name;
5735 (*p++ = *cp++) != '\0';)
5738 expmeta(p, endname);
5748 * Sort the results of file name expansion. It calculates the number of
5749 * strings to sort and then calls msort (short for merge sort) to do the
5753 static struct strlist *
5754 expsort(struct strlist *str)
5760 for (sp = str ; sp ; sp = sp->next)
5762 return msort(str, len);
5766 static struct strlist *
5767 msort(struct strlist *list, int len)
5769 struct strlist *p, *q = NULL;
5770 struct strlist **lpp;
5778 for (n = half ; --n >= 0 ; ) {
5782 q->next = NULL; /* terminate first half of list */
5783 q = msort(list, half); /* sort first half of list */
5784 p = msort(p, len - half); /* sort second half */
5787 #ifdef CONFIG_LOCALE_SUPPORT
5788 if (strcoll(p->text, q->text) < 0)
5790 if (strcmp(p->text, q->text) < 0)
5795 if ((p = *lpp) == NULL) {
5802 if ((q = *lpp) == NULL) {
5813 * Returns true if the pattern matches the string.
5816 static int patmatch(char *pattern, const char *string)
5818 return pmatch(preglob(pattern, 0, 0), string);
5823 * Remove any CTLESC characters from a string.
5827 _rmescapes(char *str, int flag)
5830 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5835 p = strpbrk(str, qchars);
5841 if (flag & RMESCAPE_ALLOC) {
5842 size_t len = p - str;
5843 size_t fulllen = len + strlen(p) + 1;
5845 if (flag & RMESCAPE_GROW) {
5846 r = makestrspace(fulllen, expdest);
5847 } else if (flag & RMESCAPE_HEAP) {
5848 r = ckmalloc(fulllen);
5850 r = stalloc(fulllen);
5854 q = memcpy(q, str, len) + len;
5857 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5858 globbing = flag & RMESCAPE_GLOB;
5859 notescaped = globbing;
5861 if (*p == CTLQUOTEMARK) {
5862 inquotes = ~inquotes;
5864 notescaped = globbing;
5868 /* naked back slash */
5874 if (notescaped && inquotes && *p != '/') {
5878 notescaped = globbing;
5883 if (flag & RMESCAPE_GROW) {
5885 STADJUST(q - r + 1, expdest);
5892 * See if a pattern matches in a case statement.
5896 casematch(union node *pattern, char *val)
5898 struct stackmark smark;
5901 setstackmark(&smark);
5902 argbackq = pattern->narg.backquote;
5903 STARTSTACKSTR(expdest);
5905 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5906 STACKSTRNUL(expdest);
5907 result = patmatch(stackblock(), val);
5908 popstackmark(&smark);
5921 expdest = makestrspace(32, expdest);
5922 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5923 len = fmtstr(expdest, 32, "%lld", (long long) num);
5925 len = fmtstr(expdest, 32, "%ld", num);
5927 STADJUST(len, expdest);
5932 varunset(const char *end, const char *var, const char *umsg, int varflags)
5938 msg = "parameter not set";
5940 if (*end == CTLENDVAR) {
5941 if (varflags & VSNUL)
5946 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5953 * This implements the input routines used by the parser.
5956 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5958 static void pushfile(void);
5961 * Read a character from the script, returning PEOF on end of file.
5962 * Nul characters in the input are silently discarded.
5966 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5968 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5969 #define pgetc_macro() pgetc()
5973 return pgetc_as_macro();
5976 #define pgetc_macro() pgetc_as_macro()
5980 return pgetc_macro();
5986 * Same as pgetc(), but ignores PEOA.
5988 #ifdef CONFIG_ASH_ALIAS
5989 static int pgetc2(void)
5995 } while (c == PEOA);
5999 static int pgetc2(void)
6001 return pgetc_macro();
6006 * Read a line from the script.
6009 static char * pfgets(char *line, int len)
6015 while (--nleft > 0) {
6032 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6033 #ifdef CONFIG_ASH_EXPAND_PRMT
6034 static char *cmdedit_prompt;
6036 static const char *cmdedit_prompt;
6038 static void putprompt(const char *s)
6040 #ifdef CONFIG_ASH_EXPAND_PRMT
6041 free(cmdedit_prompt);
6042 cmdedit_prompt = xstrdup(s);
6048 static void putprompt(const char *s)
6054 static int preadfd(void)
6057 char *buf = parsefile->buf;
6061 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6062 if (!iflag || parsefile->fd)
6063 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6065 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6066 cmdedit_path_lookup = pathval();
6068 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6070 /* Ctrl+C presend */
6079 if(nr < 0 && errno == 0) {
6080 /* Ctrl+D presend */
6085 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6089 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6090 int flags = fcntl(0, F_GETFL, 0);
6091 if (flags >= 0 && flags & O_NONBLOCK) {
6092 flags &=~ O_NONBLOCK;
6093 if (fcntl(0, F_SETFL, flags) >= 0) {
6094 out2str("sh: turning off NDELAY mode\n");
6104 * Refill the input buffer and return the next input character:
6106 * 1) If a string was pushed back on the input, pop it;
6107 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6108 * from a string so we can't refill the buffer, return EOF.
6109 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6110 * 4) Process input up to the next newline, deleting nul characters.
6120 while (parsefile->strpush) {
6121 #ifdef CONFIG_ASH_ALIAS
6122 if (parsenleft == -1 && parsefile->strpush->ap &&
6123 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6128 if (--parsenleft >= 0)
6129 return SC2INT(*parsenextc++);
6131 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6138 if ((more = preadfd()) <= 0) {
6139 parselleft = parsenleft = EOF_NLEFT;
6146 /* delete nul characters */
6154 memmove(q, q + 1, more);
6158 parsenleft = q - parsenextc - 1;
6164 parsenleft = q - parsenextc - 1;
6176 out2str(parsenextc);
6181 return SC2INT(*parsenextc++);
6185 * Undo the last call to pgetc. Only one character may be pushed back.
6186 * PEOF may be pushed back.
6197 * Push a string back onto the input at this current parsefile level.
6198 * We handle aliases this way.
6201 pushstring(char *s, void *ap)
6208 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6209 if (parsefile->strpush) {
6210 sp = ckmalloc(sizeof (struct strpush));
6211 sp->prev = parsefile->strpush;
6212 parsefile->strpush = sp;
6214 sp = parsefile->strpush = &(parsefile->basestrpush);
6215 sp->prevstring = parsenextc;
6216 sp->prevnleft = parsenleft;
6217 #ifdef CONFIG_ASH_ALIAS
6218 sp->ap = (struct alias *)ap;
6220 ((struct alias *)ap)->flag |= ALIASINUSE;
6232 struct strpush *sp = parsefile->strpush;
6235 #ifdef CONFIG_ASH_ALIAS
6237 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6238 checkkwd |= CHKALIAS;
6240 if (sp->string != sp->ap->val) {
6243 sp->ap->flag &= ~ALIASINUSE;
6244 if (sp->ap->flag & ALIASDEAD) {
6245 unalias(sp->ap->name);
6249 parsenextc = sp->prevstring;
6250 parsenleft = sp->prevnleft;
6251 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6252 parsefile->strpush = sp->prev;
6253 if (sp != &(parsefile->basestrpush))
6259 * Set the input to take input from a file. If push is set, push the
6260 * old input onto the stack first.
6264 setinputfile(const char *fname, int flags)
6270 if ((fd = open(fname, O_RDONLY)) < 0) {
6271 if (flags & INPUT_NOFILE_OK)
6273 sh_error("Can't open %s", fname);
6276 fd2 = copyfd(fd, 10);
6279 sh_error("Out of file descriptors");
6282 setinputfd(fd, flags & INPUT_PUSH_FILE);
6290 * Like setinputfile, but takes an open file descriptor. Call this with
6295 setinputfd(int fd, int push)
6297 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6303 if (parsefile->buf == NULL)
6304 parsefile->buf = ckmalloc(IBUFSIZ);
6305 parselleft = parsenleft = 0;
6311 * Like setinputfile, but takes input from a string.
6315 setinputstring(char *string)
6319 parsenextc = string;
6320 parsenleft = strlen(string);
6321 parsefile->buf = NULL;
6328 * To handle the "." command, a stack of input files is used. Pushfile
6329 * adds a new entry to the stack and popfile restores the previous level.
6335 struct parsefile *pf;
6337 parsefile->nleft = parsenleft;
6338 parsefile->lleft = parselleft;
6339 parsefile->nextc = parsenextc;
6340 parsefile->linno = plinno;
6341 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6342 pf->prev = parsefile;
6345 pf->basestrpush.prev = NULL;
6353 struct parsefile *pf = parsefile;
6362 parsefile = pf->prev;
6364 parsenleft = parsefile->nleft;
6365 parselleft = parsefile->lleft;
6366 parsenextc = parsefile->nextc;
6367 plinno = parsefile->linno;
6373 * Return to top level.
6379 while (parsefile != &basepf)
6385 * Close the file(s) that the shell is reading commands from. Called
6386 * after a fork is done.
6393 if (parsefile->fd > 0) {
6394 close(parsefile->fd);
6401 /* mode flags for set_curjob */
6402 #define CUR_DELETE 2
6403 #define CUR_RUNNING 1
6404 #define CUR_STOPPED 0
6406 /* mode flags for dowait */
6407 #define DOWAIT_NORMAL 0
6408 #define DOWAIT_BLOCK 1
6411 static struct job *jobtab;
6413 static unsigned njobs;
6415 /* pgrp of shell on invocation */
6416 static int initialpgrp;
6417 static int ttyfd = -1;
6420 static struct job *curjob;
6421 /* number of presumed living untracked jobs */
6424 static void set_curjob(struct job *, unsigned);
6426 static int restartjob(struct job *, int);
6427 static void xtcsetpgrp(int, pid_t);
6428 static char *commandtext(union node *);
6429 static void cmdlist(union node *, int);
6430 static void cmdtxt(union node *);
6431 static void cmdputs(const char *);
6432 static void showpipe(struct job *, FILE *);
6434 static int sprint_status(char *, int, int);
6435 static void freejob(struct job *);
6436 static struct job *getjob(const char *, int);
6437 static struct job *growjobtab(void);
6438 static void forkchild(struct job *, union node *, int);
6439 static void forkparent(struct job *, union node *, int, pid_t);
6440 static int dowait(int, struct job *);
6441 static int getstatus(struct job *);
6444 set_curjob(struct job *jp, unsigned mode)
6447 struct job **jpp, **curp;
6449 /* first remove from list */
6450 jpp = curp = &curjob;
6455 jpp = &jp1->prev_job;
6457 *jpp = jp1->prev_job;
6459 /* Then re-insert in correct position */
6467 /* job being deleted */
6470 /* newly created job or backgrounded job,
6471 put after all stopped jobs. */
6475 if (!jp1 || jp1->state != JOBSTOPPED)
6478 jpp = &jp1->prev_job;
6484 /* newly stopped job - becomes curjob */
6485 jp->prev_job = *jpp;
6493 * Turn job control on and off.
6495 * Note: This code assumes that the third arg to ioctl is a character
6496 * pointer, which is true on Berkeley systems but not System V. Since
6497 * System V doesn't have job control yet, this isn't a problem now.
6499 * Called with interrupts off.
6508 if (on == jobctl || rootshell == 0)
6512 ofd = fd = open(_PATH_TTY, O_RDWR);
6515 while (!isatty(fd) && --fd >= 0)
6518 fd = fcntl(fd, F_DUPFD, 10);
6522 fcntl(fd, F_SETFD, FD_CLOEXEC);
6523 do { /* while we are in the background */
6524 if ((pgrp = tcgetpgrp(fd)) < 0) {
6526 sh_warnx("can't access tty; job control turned off");
6530 if (pgrp == getpgrp())
6541 xtcsetpgrp(fd, pgrp);
6543 /* turning job control off */
6546 xtcsetpgrp(fd, pgrp);
6560 killcmd(int argc, char **argv)
6571 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6572 "kill -l [exitstatus]"
6576 if (**++argv == '-') {
6577 signo = get_signum(*argv + 1);
6581 while ((c = nextopt("ls:")) != '\0')
6591 signo = get_signum(optionarg);
6594 "invalid signal number or name: %s",
6605 if (!list && signo < 0)
6608 if ((signo < 0 || !*argv) ^ list) {
6616 for (i = 1; i < NSIG; i++) {
6617 name = get_signame(i);
6619 out1fmt(snlfmt, name);
6623 name = get_signame(signo);
6625 out1fmt(snlfmt, name);
6627 sh_error("invalid signal number or exit status: %s", *argptr);
6633 if (**argv == '%') {
6634 jp = getjob(*argv, 0);
6635 pid = -jp->ps[0].pid;
6637 pid = **argv == '-' ?
6638 -number(*argv + 1) : number(*argv);
6640 if (kill(pid, signo) != 0) {
6641 sh_warnx("(%d) - %m", pid);
6650 #if defined(JOBS) || DEBUG
6652 jobno(const struct job *jp)
6654 return jp - jobtab + 1;
6660 fgcmd(int argc, char **argv)
6667 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6672 jp = getjob(*argv, 1);
6673 if (mode == FORK_BG) {
6674 set_curjob(jp, CUR_RUNNING);
6675 fprintf(out, "[%d] ", jobno(jp));
6677 outstr(jp->ps->cmd, out);
6679 retval = restartjob(jp, mode);
6680 } while (*argv && *++argv);
6684 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6688 restartjob(struct job *jp, int mode)
6690 struct procstat *ps;
6696 if (jp->state == JOBDONE)
6698 jp->state = JOBRUNNING;
6700 if (mode == FORK_FG)
6701 xtcsetpgrp(ttyfd, pgid);
6702 killpg(pgid, SIGCONT);
6706 if (WIFSTOPPED(ps->status)) {
6709 } while (ps++, --i);
6711 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6718 sprint_status(char *s, int status, int sigonly)
6724 if (!WIFEXITED(status)) {
6726 if (WIFSTOPPED(status))
6727 st = WSTOPSIG(status);
6730 st = WTERMSIG(status);
6732 if (st == SIGINT || st == SIGPIPE)
6735 if (WIFSTOPPED(status))
6740 col = fmtstr(s, 32, strsignal(st));
6741 if (WCOREDUMP(status)) {
6742 col += fmtstr(s + col, 16, " (core dumped)");
6744 } else if (!sigonly) {
6745 st = WEXITSTATUS(status);
6747 col = fmtstr(s, 16, "Done(%d)", st);
6749 col = fmtstr(s, 16, "Done");
6758 showjob(FILE *out, struct job *jp, int mode)
6760 struct procstat *ps;
6761 struct procstat *psend;
6768 if (mode & SHOW_PGID) {
6769 /* just output process (group) id of pipeline */
6770 fprintf(out, "%d\n", ps->pid);
6774 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6779 else if (curjob && jp == curjob->prev_job)
6782 if (mode & SHOW_PID)
6783 col += fmtstr(s + col, 16, "%d ", ps->pid);
6785 psend = ps + jp->nprocs;
6787 if (jp->state == JOBRUNNING) {
6788 scopy("Running", s + col);
6789 col += strlen("Running");
6791 int status = psend[-1].status;
6793 if (jp->state == JOBSTOPPED)
6794 status = jp->stopstatus;
6796 col += sprint_status(s + col, status, 0);
6802 /* for each process */
6803 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6806 fprintf(out, "%s%*c%s",
6807 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6809 if (!(mode & SHOW_PID)) {
6813 if (++ps == psend) {
6814 outcslow('\n', out);
6821 if (jp->state == JOBDONE) {
6822 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6829 jobscmd(int argc, char **argv)
6835 while ((m = nextopt("lp")))
6845 showjob(out, getjob(*argv,0), mode);
6848 showjobs(out, mode);
6855 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6856 * statuses have changed since the last call to showjobs.
6860 showjobs(FILE *out, int mode)
6864 TRACE(("showjobs(%x) called\n", mode));
6866 /* If not even one one job changed, there is nothing to do */
6867 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6870 for (jp = curjob; jp; jp = jp->prev_job) {
6871 if (!(mode & SHOW_CHANGED) || jp->changed)
6872 showjob(out, jp, mode);
6878 * Mark a job structure as unused.
6882 freejob(struct job *jp)
6884 struct procstat *ps;
6888 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6889 if (ps->cmd != nullstr)
6892 if (jp->ps != &jp->ps0)
6895 set_curjob(jp, CUR_DELETE);
6901 waitcmd(int argc, char **argv)
6914 /* wait for all jobs */
6919 /* no running procs */
6922 if (jp->state == JOBRUNNING)
6927 dowait(DOWAIT_BLOCK, 0);
6933 if (**argv != '%') {
6934 pid_t pid = number(*argv);
6938 if (job->ps[job->nprocs - 1].pid == pid)
6940 job = job->prev_job;
6946 job = getjob(*argv, 0);
6947 /* loop until process terminated or stopped */
6948 while (job->state == JOBRUNNING)
6949 dowait(DOWAIT_BLOCK, 0);
6951 retval = getstatus(job);
6962 * Convert a job name to a job structure.
6966 getjob(const char *name, int getctl)
6970 const char *err_msg = "No such job: %s";
6974 char *(*match)(const char *, const char *);
6989 if (c == '+' || c == '%') {
6991 err_msg = "No current job";
6993 } else if (c == '-') {
6996 err_msg = "No previous job";
7007 jp = jobtab + num - 1;
7024 if (match(jp->ps[0].cmd, p)) {
7028 err_msg = "%s: ambiguous";
7035 err_msg = "job %s not created under job control";
7036 if (getctl && jp->jobctl == 0)
7041 sh_error(err_msg, name);
7046 * Return a new job structure.
7047 * Called with interrupts off.
7051 makejob(union node *node, int nprocs)
7056 for (i = njobs, jp = jobtab ; ; jp++) {
7063 if (jp->state != JOBDONE || !jp->waited)
7072 memset(jp, 0, sizeof(*jp));
7077 jp->prev_job = curjob;
7082 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7084 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7094 struct job *jp, *jq;
7096 len = njobs * sizeof(*jp);
7098 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7100 offset = (char *)jp - (char *)jq;
7102 /* Relocate pointers */
7105 jq = (struct job *)((char *)jq + l);
7109 #define joff(p) ((struct job *)((char *)(p) + l))
7110 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7111 if (xlikely(joff(jp)->ps == &jq->ps0))
7112 jmove(joff(jp)->ps);
7113 if (joff(jp)->prev_job)
7114 jmove(joff(jp)->prev_job);
7124 jp = (struct job *)((char *)jp + len);
7128 } while (--jq >= jp);
7134 * Fork off a subshell. If we are doing job control, give the subshell its
7135 * own process group. Jp is a job structure that the job is to be added to.
7136 * N is the command that will be evaluated by the child. Both jp and n may
7137 * be NULL. The mode parameter can be one of the following:
7138 * FORK_FG - Fork off a foreground process.
7139 * FORK_BG - Fork off a background process.
7140 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7141 * process group even if job control is on.
7143 * When job control is turned off, background processes have their standard
7144 * input redirected to /dev/null (except for the second and later processes
7147 * Called with interrupts off.
7150 static void forkchild(struct job *jp, union node *n, int mode)
7154 TRACE(("Child shell %d\n", getpid()));
7161 /* do job control only in root shell */
7163 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7166 if (jp->nprocs == 0)
7169 pgrp = jp->ps[0].pid;
7170 /* This can fail because we are doing it in the parent also */
7171 (void)setpgid(0, pgrp);
7172 if (mode == FORK_FG)
7173 xtcsetpgrp(ttyfd, pgrp);
7178 if (mode == FORK_BG) {
7181 if (jp->nprocs == 0) {
7183 if (open(bb_dev_null, O_RDONLY) != 0)
7184 sh_error("Can't open %s", bb_dev_null);
7187 if (!oldlvl && iflag) {
7192 for (jp = curjob; jp; jp = jp->prev_job)
7197 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7199 TRACE(("In parent shell: child = %d\n", pid));
7201 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7206 if (mode != FORK_NOJOB && jp->jobctl) {
7209 if (jp->nprocs == 0)
7212 pgrp = jp->ps[0].pid;
7213 /* This can fail because we are doing it in the child also */
7214 (void)setpgid(pid, pgrp);
7217 if (mode == FORK_BG) {
7218 backgndpid = pid; /* set $! */
7219 set_curjob(jp, CUR_RUNNING);
7222 struct procstat *ps = &jp->ps[jp->nprocs++];
7228 ps->cmd = commandtext(n);
7234 forkshell(struct job *jp, union node *n, int mode)
7238 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7241 TRACE(("Fork failed, errno=%d", errno));
7244 sh_error("Cannot fork");
7247 forkchild(jp, n, mode);
7249 forkparent(jp, n, mode, pid);
7254 * Wait for job to finish.
7256 * Under job control we have the problem that while a child process is
7257 * running interrupts generated by the user are sent to the child but not
7258 * to the shell. This means that an infinite loop started by an inter-
7259 * active user may be hard to kill. With job control turned off, an
7260 * interactive user may place an interactive program inside a loop. If
7261 * the interactive program catches interrupts, the user doesn't want
7262 * these interrupts to also abort the loop. The approach we take here
7263 * is to have the shell ignore interrupt signals while waiting for a
7264 * foreground process to terminate, and then send itself an interrupt
7265 * signal if the child process was terminated by an interrupt signal.
7266 * Unfortunately, some programs want to do a bit of cleanup and then
7267 * exit on interrupt; unless these processes terminate themselves by
7268 * sending a signal to themselves (instead of calling exit) they will
7269 * confuse this approach.
7271 * Called with interrupts off.
7275 waitforjob(struct job *jp)
7279 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7280 while (jp->state == JOBRUNNING) {
7281 dowait(DOWAIT_BLOCK, jp);
7286 xtcsetpgrp(ttyfd, rootpid);
7288 * This is truly gross.
7289 * If we're doing job control, then we did a TIOCSPGRP which
7290 * caused us (the shell) to no longer be in the controlling
7291 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7292 * intuit from the subprocess exit status whether a SIGINT
7293 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7298 if (jp->state == JOBDONE)
7306 * Do a wait system call. If job control is compiled in, we accept
7307 * stopped processes. If block is zero, we return a value of zero
7308 * rather than blocking.
7310 * System V doesn't have a non-blocking wait system call. It does
7311 * have a SIGCLD signal that is sent to a process when one of it's
7312 * children dies. The obvious way to use SIGCLD would be to install
7313 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7314 * was received, and have waitproc bump another counter when it got
7315 * the status of a process. Waitproc would then know that a wait
7316 * system call would not block if the two counters were different.
7317 * This approach doesn't work because if a process has children that
7318 * have not been waited for, System V will send it a SIGCLD when it
7319 * installs a signal handler for SIGCLD. What this means is that when
7320 * a child exits, the shell will be sent SIGCLD signals continuously
7321 * until is runs out of stack space, unless it does a wait call before
7322 * restoring the signal handler. The code below takes advantage of
7323 * this (mis)feature by installing a signal handler for SIGCLD and
7324 * then checking to see whether it was called. If there are any
7325 * children to be waited for, it will be.
7327 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7328 * waits at all. In this case, the user will not be informed when
7329 * a background process until the next time she runs a real program
7330 * (as opposed to running a builtin command or just typing return),
7331 * and the jobs command may give out of date information.
7334 static int waitproc(int block, int *status)
7344 return wait3(status, flags, (struct rusage *)NULL);
7348 * Wait for a process to terminate.
7352 dowait(int block, struct job *job)
7357 struct job *thisjob;
7360 TRACE(("dowait(%d) called\n", block));
7361 pid = waitproc(block, &status);
7362 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7367 for (jp = curjob; jp; jp = jp->prev_job) {
7368 struct procstat *sp;
7369 struct procstat *spend;
7370 if (jp->state == JOBDONE)
7373 spend = jp->ps + jp->nprocs;
7376 if (sp->pid == pid) {
7377 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7378 sp->status = status;
7381 if (sp->status == -1)
7384 if (state == JOBRUNNING)
7386 if (WIFSTOPPED(sp->status)) {
7387 jp->stopstatus = sp->status;
7391 } while (++sp < spend);
7396 if (!WIFSTOPPED(status))
7403 if (state != JOBRUNNING) {
7404 thisjob->changed = 1;
7406 if (thisjob->state != state) {
7407 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7408 thisjob->state = state;
7410 if (state == JOBSTOPPED) {
7411 set_curjob(thisjob, CUR_STOPPED);
7420 if (thisjob && thisjob == job) {
7424 len = sprint_status(s, status, 1);
7436 * return 1 if there are stopped jobs, otherwise 0
7449 if (jp && jp->state == JOBSTOPPED) {
7450 out2str("You have stopped jobs.\n");
7460 * Return a string identifying a command (to be printed by the
7465 static char *cmdnextc;
7468 commandtext(union node *n)
7472 STARTSTACKSTR(cmdnextc);
7474 name = stackblock();
7475 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7476 name, cmdnextc, cmdnextc));
7477 return savestr(name);
7481 cmdtxt(union node *n)
7484 struct nodelist *lp;
7496 lp = n->npipe.cmdlist;
7514 cmdtxt(n->nbinary.ch1);
7530 cmdtxt(n->nif.test);
7533 if (n->nif.elsepart) {
7536 n = n->nif.elsepart;
7552 cmdtxt(n->nbinary.ch1);
7562 cmdputs(n->nfor.var);
7564 cmdlist(n->nfor.args, 1);
7569 cmdputs(n->narg.text);
7573 cmdlist(n->ncmd.args, 1);
7574 cmdlist(n->ncmd.redirect, 0);
7587 cmdputs(n->ncase.expr->narg.text);
7589 for (np = n->ncase.cases; np; np = np->nclist.next) {
7590 cmdtxt(np->nclist.pattern);
7592 cmdtxt(np->nclist.body);
7618 s[0] = n->nfile.fd + '0';
7622 if (n->type == NTOFD || n->type == NFROMFD) {
7623 s[0] = n->ndup.dupfd + '0';
7634 cmdlist(union node *np, int sep)
7636 for (; np; np = np->narg.next) {
7640 if (sep && np->narg.next)
7646 cmdputs(const char *s)
7648 const char *p, *str;
7649 char c, cc[2] = " ";
7653 static const char vstype[VSTYPE + 1][4] = {
7654 "", "}", "-", "+", "?", "=",
7655 "%", "%%", "#", "##"
7657 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7659 while ((c = *p++) != 0) {
7667 if ((subtype & VSTYPE) == VSLENGTH)
7671 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7678 str = "\"}" + !(quoted & 1);
7685 case CTLBACKQ+CTLQUOTE:
7688 #ifdef CONFIG_ASH_MATH_SUPPORT
7703 if ((subtype & VSTYPE) != VSNORMAL)
7705 str = vstype[subtype & VSTYPE];
7706 if (subtype & VSNUL)
7715 /* These can only happen inside quotes */
7728 while ((c = *str++)) {
7733 USTPUTC('"', nextc);
7741 showpipe(struct job *jp, FILE *out)
7743 struct procstat *sp;
7744 struct procstat *spend;
7746 spend = jp->ps + jp->nprocs;
7747 for (sp = jp->ps + 1; sp < spend; sp++)
7748 fprintf(out, " | %s", sp->cmd);
7749 outcslow('\n', out);
7754 xtcsetpgrp(int fd, pid_t pgrp)
7756 if (tcsetpgrp(fd, pgrp))
7757 sh_error("Cannot set tty process group (%m)");
7762 getstatus(struct job *job) {
7766 status = job->ps[job->nprocs - 1].status;
7767 retval = WEXITSTATUS(status);
7768 if (!WIFEXITED(status)) {
7770 retval = WSTOPSIG(status);
7771 if (!WIFSTOPPED(status))
7774 /* XXX: limits number of signals */
7775 retval = WTERMSIG(status);
7777 if (retval == SIGINT)
7783 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7784 jobno(job), job->nprocs, status, retval));
7788 #ifdef CONFIG_ASH_MAIL
7792 * Routines to check for mail. (Perhaps make part of main.c?)
7795 #define MAXMBOXES 10
7797 /* times of mailboxes */
7798 static time_t mailtime[MAXMBOXES];
7799 /* Set if MAIL or MAILPATH is changed. */
7800 static int mail_var_path_changed;
7805 * Print appropriate message(s) if mail has arrived.
7806 * If mail_var_path_changed is set,
7807 * then the value of MAIL has mail_var_path_changed,
7808 * so we just update the values.
7818 struct stackmark smark;
7821 setstackmark(&smark);
7822 mpath = mpathset() ? mpathval() : mailval();
7823 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7824 p = padvance(&mpath, nullstr);
7829 for (q = p ; *q ; q++);
7834 q[-1] = '\0'; /* delete trailing '/' */
7835 if (stat(p, &statb) < 0) {
7839 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7842 pathopt ? pathopt : "you have mail"
7845 *mtp = statb.st_mtime;
7847 mail_var_path_changed = 0;
7848 popstackmark(&smark);
7853 changemail(const char *val)
7855 mail_var_path_changed++;
7858 #endif /* CONFIG_ASH_MAIL */
7864 static short profile_buf[16384];
7868 static int isloginsh;
7870 static void read_profile(const char *);
7873 * Main routine. We initialize things, parse the arguments, execute
7874 * profiles if we're a login shell, and then call cmdloop to execute
7875 * commands. The setjmp call sets up the location to jump to when an
7876 * exception occurs. When an exception occurs the variable "state"
7877 * is used to figure out how far we had gotten.
7881 ash_main(int argc, char **argv)
7885 struct jmploc jmploc;
7886 struct stackmark smark;
7889 dash_errno = __errno_location();
7893 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7896 if (setjmp(jmploc.loc)) {
7906 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7910 outcslow('\n', stderr);
7912 popstackmark(&smark);
7913 FORCEINTON; /* enable interrupts */
7926 trputs("Shell args: "); trargs(argv);
7930 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7931 rseed = rootpid + ((time_t)time((time_t *)0));
7934 setstackmark(&smark);
7935 procargs(argc, argv);
7936 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7938 const char *hp = lookupvar("HISTFILE");
7941 hp = lookupvar("HOME");
7943 char *defhp = concat_path_file(hp, ".ash_history");
7944 setvar("HISTFILE", defhp, 0);
7950 if (argv[0] && argv[0][0] == '-')
7954 read_profile("/etc/profile");
7957 read_profile(".profile");
7963 getuid() == geteuid() && getgid() == getegid() &&
7967 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7968 read_profile(shinit);
7974 evalstring(minusc, 0);
7976 if (sflag || minusc == NULL) {
7977 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7979 const char *hp = lookupvar("HISTFILE");
7982 load_history ( hp );
7985 state4: /* XXX ??? - why isn't this before the "if" statement */
7993 extern void _mcleanup(void);
8003 * Read and execute commands. "Top" is nonzero for the top level command
8004 * loop; it turns on prompting if the shell is interactive.
8011 struct stackmark smark;
8015 TRACE(("cmdloop(%d) called\n", top));
8019 setstackmark(&smark);
8022 showjobs(stderr, SHOW_CHANGED);
8027 #ifdef CONFIG_ASH_MAIL
8031 n = parsecmd(inter);
8032 /* showtree(n); DEBUG */
8034 if (!top || numeof >= 50)
8036 if (!stoppedjobs()) {
8039 out2str("\nUse \"exit\" to leave shell.\n");
8042 } else if (nflag == 0) {
8043 job_warning = (job_warning == 2) ? 1 : 0;
8047 popstackmark(&smark);
8052 return skip & SKIPEVAL;
8061 * Read /etc/profile or .profile. Return on error.
8065 read_profile(const char *name)
8069 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8081 * Read a file containing shell functions.
8085 readcmdfile(char *name)
8087 setinputfile(name, INPUT_PUSH_FILE);
8094 * Take commands from a file. To be compatible we should do a path
8095 * search for the file, which is necessary to find sub-commands.
8098 static char * find_dot_file(char *name)
8101 const char *path = pathval();
8104 /* don't try this for absolute or relative paths */
8105 if (strchr(name, '/'))
8108 while ((fullname = padvance(&path, name)) != NULL) {
8109 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8111 * Don't bother freeing here, since it will
8112 * be freed by the caller.
8116 stunalloc(fullname);
8119 /* not found in the PATH */
8120 sh_error(not_found_msg, name);
8124 static int dotcmd(int argc, char **argv)
8127 volatile struct shparam saveparam;
8130 for (sp = cmdenviron; sp; sp = sp->next)
8131 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8133 if (argc >= 2) { /* That's what SVR2 does */
8136 fullname = find_dot_file(argv[1]);
8139 saveparam = shellparam;
8140 shellparam.malloc = 0;
8141 shellparam.nparam = argc - 2;
8142 shellparam.p = argv + 2;
8145 setinputfile(fullname, INPUT_PUSH_FILE);
8146 commandname = fullname;
8151 freeparam(&shellparam);
8152 shellparam = saveparam;
8154 status = exitstatus;
8161 exitcmd(int argc, char **argv)
8166 exitstatus = number(argv[1]);
8171 #ifdef CONFIG_ASH_BUILTIN_ECHO
8173 echocmd(int argc, char **argv)
8175 return bb_echo(argv);
8179 #ifdef CONFIG_ASH_BUILTIN_TEST
8181 testcmd(int argc, char **argv)
8183 return bb_test(argc, argv);
8190 * Same for malloc, realloc, but returns an error when out of space.
8194 ckrealloc(pointer p, size_t nbytes)
8196 p = realloc(p, nbytes);
8198 sh_error(bb_msg_memory_exhausted);
8203 ckmalloc(size_t nbytes)
8205 return ckrealloc(NULL, nbytes);
8209 * Make a copy of a string in safe storage.
8213 savestr(const char *s)
8215 char *p = strdup(s);
8217 sh_error(bb_msg_memory_exhausted);
8223 * Parse trees for commands are allocated in lifo order, so we use a stack
8224 * to make this more efficient, and also to avoid all sorts of exception
8225 * handling code to handle interrupts in the middle of a parse.
8227 * The size 504 was chosen because the Ultrix malloc handles that size
8233 stalloc(size_t nbytes)
8238 aligned = SHELL_ALIGN(nbytes);
8239 if (aligned > stacknleft) {
8242 struct stack_block *sp;
8244 blocksize = aligned;
8245 if (blocksize < MINSIZE)
8246 blocksize = MINSIZE;
8247 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8248 if (len < blocksize)
8249 sh_error(bb_msg_memory_exhausted);
8253 stacknxt = sp->space;
8254 stacknleft = blocksize;
8255 sstrend = stacknxt + blocksize;
8260 stacknxt += aligned;
8261 stacknleft -= aligned;
8267 stunalloc(pointer p)
8270 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8271 write(2, "stunalloc\n", 10);
8275 stacknleft += stacknxt - (char *)p;
8281 setstackmark(struct stackmark *mark)
8283 mark->stackp = stackp;
8284 mark->stacknxt = stacknxt;
8285 mark->stacknleft = stacknleft;
8286 mark->marknext = markp;
8292 popstackmark(struct stackmark *mark)
8294 struct stack_block *sp;
8297 markp = mark->marknext;
8298 while (stackp != mark->stackp) {
8303 stacknxt = mark->stacknxt;
8304 stacknleft = mark->stacknleft;
8305 sstrend = mark->stacknxt + mark->stacknleft;
8311 * When the parser reads in a string, it wants to stick the string on the
8312 * stack and only adjust the stack pointer when it knows how big the
8313 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8314 * of space on top of the stack and stackblocklen returns the length of
8315 * this block. Growstackblock will grow this space by at least one byte,
8316 * possibly moving it (like realloc). Grabstackblock actually allocates the
8317 * part of the block that has been used.
8321 growstackblock(void)
8325 newlen = stacknleft * 2;
8326 if (newlen < stacknleft)
8327 sh_error(bb_msg_memory_exhausted);
8331 if (stacknxt == stackp->space && stackp != &stackbase) {
8332 struct stack_block *oldstackp;
8333 struct stackmark *xmark;
8334 struct stack_block *sp;
8335 struct stack_block *prevstackp;
8341 prevstackp = sp->prev;
8342 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8343 sp = ckrealloc((pointer)sp, grosslen);
8344 sp->prev = prevstackp;
8346 stacknxt = sp->space;
8347 stacknleft = newlen;
8348 sstrend = sp->space + newlen;
8351 * Stack marks pointing to the start of the old block
8352 * must be relocated to point to the new block
8355 while (xmark != NULL && xmark->stackp == oldstackp) {
8356 xmark->stackp = stackp;
8357 xmark->stacknxt = stacknxt;
8358 xmark->stacknleft = stacknleft;
8359 xmark = xmark->marknext;
8363 char *oldspace = stacknxt;
8364 int oldlen = stacknleft;
8365 char *p = stalloc(newlen);
8367 /* free the space we just allocated */
8368 stacknxt = memcpy(p, oldspace, oldlen);
8369 stacknleft += newlen;
8373 static void grabstackblock(size_t len)
8375 len = SHELL_ALIGN(len);
8381 * The following routines are somewhat easier to use than the above.
8382 * The user declares a variable of type STACKSTR, which may be declared
8383 * to be a register. The macro STARTSTACKSTR initializes things. Then
8384 * the user uses the macro STPUTC to add characters to the string. In
8385 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8386 * grown as necessary. When the user is done, she can just leave the
8387 * string there and refer to it using stackblock(). Or she can allocate
8388 * the space for it using grabstackstr(). If it is necessary to allow
8389 * someone else to use the stack temporarily and then continue to grow
8390 * the string, the user should use grabstack to allocate the space, and
8391 * then call ungrabstr(p) to return to the previous mode of operation.
8393 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8394 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8395 * is space for at least one character.
8401 size_t len = stackblocksize();
8402 if (herefd >= 0 && len >= 1024) {
8403 full_write(herefd, stackblock(), len);
8404 return stackblock();
8407 return stackblock() + len;
8411 * Called from CHECKSTRSPACE.
8415 makestrspace(size_t newlen, char *p)
8417 size_t len = p - stacknxt;
8418 size_t size = stackblocksize();
8423 size = stackblocksize();
8425 if (nleft >= newlen)
8429 return stackblock() + len;
8433 stnputs(const char *s, size_t n, char *p)
8435 p = makestrspace(n, p);
8436 p = memcpy(p, s, n) + n;
8441 stputs(const char *s, char *p)
8443 return stnputs(s, strlen(s), p);
8451 * number(s) Convert a string of digits to an integer.
8452 * is_number(s) Return true if s is a string of digits.
8456 * prefix -- see if pfx is a prefix of string.
8460 prefix(const char *string, const char *pfx)
8463 if (*pfx++ != *string++)
8466 return (char *) string;
8471 * Convert a string of digits to an integer, printing an error message on
8476 number(const char *s)
8480 sh_error(illnum, s);
8486 * Check for a valid number. This should be elsewhere.
8490 is_number(const char *p)
8495 } while (*++p != '\0');
8501 * Produce a possibly single quoted string suitable as input to the shell.
8502 * The return string is allocated on the stack.
8506 single_quote(const char *s) {
8515 len = strchrnul(s, '\'') - s;
8517 q = p = makestrspace(len + 3, p);
8520 q = memcpy(q, s, len) + len;
8526 len = strspn(s, "'");
8530 q = p = makestrspace(len + 3, p);
8533 q = memcpy(q, s, len) + len;
8542 return stackblock();
8546 * Like strdup but works with the ash stack.
8550 sstrdup(const char *p)
8552 size_t len = strlen(p) + 1;
8553 return memcpy(stalloc(len), p, len);
8558 calcsize(union node *n)
8562 funcblocksize += nodesize[n->type];
8565 calcsize(n->ncmd.redirect);
8566 calcsize(n->ncmd.args);
8567 calcsize(n->ncmd.assign);
8570 sizenodelist(n->npipe.cmdlist);
8575 calcsize(n->nredir.redirect);
8576 calcsize(n->nredir.n);
8583 calcsize(n->nbinary.ch2);
8584 calcsize(n->nbinary.ch1);
8587 calcsize(n->nif.elsepart);
8588 calcsize(n->nif.ifpart);
8589 calcsize(n->nif.test);
8592 funcstringsize += strlen(n->nfor.var) + 1;
8593 calcsize(n->nfor.body);
8594 calcsize(n->nfor.args);
8597 calcsize(n->ncase.cases);
8598 calcsize(n->ncase.expr);
8601 calcsize(n->nclist.body);
8602 calcsize(n->nclist.pattern);
8603 calcsize(n->nclist.next);
8607 sizenodelist(n->narg.backquote);
8608 funcstringsize += strlen(n->narg.text) + 1;
8609 calcsize(n->narg.next);
8616 calcsize(n->nfile.fname);
8617 calcsize(n->nfile.next);
8621 calcsize(n->ndup.vname);
8622 calcsize(n->ndup.next);
8626 calcsize(n->nhere.doc);
8627 calcsize(n->nhere.next);
8630 calcsize(n->nnot.com);
8637 sizenodelist(struct nodelist *lp)
8640 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8648 copynode(union node *n)
8655 funcblock = (char *) funcblock + nodesize[n->type];
8658 new->ncmd.redirect = copynode(n->ncmd.redirect);
8659 new->ncmd.args = copynode(n->ncmd.args);
8660 new->ncmd.assign = copynode(n->ncmd.assign);
8663 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8664 new->npipe.backgnd = n->npipe.backgnd;
8669 new->nredir.redirect = copynode(n->nredir.redirect);
8670 new->nredir.n = copynode(n->nredir.n);
8677 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8678 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8681 new->nif.elsepart = copynode(n->nif.elsepart);
8682 new->nif.ifpart = copynode(n->nif.ifpart);
8683 new->nif.test = copynode(n->nif.test);
8686 new->nfor.var = nodesavestr(n->nfor.var);
8687 new->nfor.body = copynode(n->nfor.body);
8688 new->nfor.args = copynode(n->nfor.args);
8691 new->ncase.cases = copynode(n->ncase.cases);
8692 new->ncase.expr = copynode(n->ncase.expr);
8695 new->nclist.body = copynode(n->nclist.body);
8696 new->nclist.pattern = copynode(n->nclist.pattern);
8697 new->nclist.next = copynode(n->nclist.next);
8701 new->narg.backquote = copynodelist(n->narg.backquote);
8702 new->narg.text = nodesavestr(n->narg.text);
8703 new->narg.next = copynode(n->narg.next);
8710 new->nfile.fname = copynode(n->nfile.fname);
8711 new->nfile.fd = n->nfile.fd;
8712 new->nfile.next = copynode(n->nfile.next);
8716 new->ndup.vname = copynode(n->ndup.vname);
8717 new->ndup.dupfd = n->ndup.dupfd;
8718 new->ndup.fd = n->ndup.fd;
8719 new->ndup.next = copynode(n->ndup.next);
8723 new->nhere.doc = copynode(n->nhere.doc);
8724 new->nhere.fd = n->nhere.fd;
8725 new->nhere.next = copynode(n->nhere.next);
8728 new->nnot.com = copynode(n->nnot.com);
8731 new->type = n->type;
8736 static struct nodelist *
8737 copynodelist(struct nodelist *lp)
8739 struct nodelist *start;
8740 struct nodelist **lpp;
8745 funcblock = (char *) funcblock +
8746 SHELL_ALIGN(sizeof(struct nodelist));
8747 (*lpp)->n = copynode(lp->n);
8749 lpp = &(*lpp)->next;
8757 nodesavestr(char *s)
8759 char *rtn = funcstring;
8761 strcpy(funcstring, s);
8762 funcstring += strlen(s) + 1;
8768 * Free a parse tree.
8772 freefunc(struct funcnode *f)
8774 if (f && --f->count < 0)
8779 static void options(int);
8780 static void setoption(int, int);
8784 * Process the shell command line arguments.
8788 procargs(int argc, char **argv)
8791 const char *xminusc;
8798 for (i = 0; i < NOPTS; i++)
8804 if (*xargv == NULL) {
8806 sh_error(bb_msg_requires_arg, "-c");
8809 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8813 for (i = 0; i < NOPTS; i++)
8814 if (optlist[i] == 2)
8819 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8824 } else if (!sflag) {
8825 setinputfile(*xargv, 0);
8831 shellparam.p = xargv;
8832 #ifdef CONFIG_ASH_GETOPTS
8833 shellparam.optind = 1;
8834 shellparam.optoff = -1;
8836 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8838 shellparam.nparam++;
8851 setinteractive(iflag);
8856 static void minus_o(char *name, int val)
8861 out1str("Current option settings\n");
8862 for (i = 0; i < NOPTS; i++)
8863 out1fmt("%-16s%s\n", optnames(i),
8864 optlist[i] ? "on" : "off");
8866 for (i = 0; i < NOPTS; i++)
8867 if (equal(name, optnames(i))) {
8871 sh_error("Illegal option -o %s", name);
8876 * Process shell options. The global variable argptr contains a pointer
8877 * to the argument list; we advance it past the options.
8881 options(int cmdline)
8889 while ((p = *argptr) != NULL) {
8891 if ((c = *p++) == '-') {
8893 if (p[0] == '\0' || LONE_DASH(p)) {
8895 /* "-" means turn off -x and -v */
8898 /* "--" means reset params */
8899 else if (*argptr == NULL)
8902 break; /* "-" or "--" terminates options */
8904 } else if (c == '+') {
8910 while ((c = *p++) != '\0') {
8911 if (c == 'c' && cmdline) {
8912 minusc = p; /* command is after shell args*/
8913 } else if (c == 'o') {
8914 minus_o(*argptr, val);
8917 } else if (cmdline && (c == '-')) { // long options
8918 if (strcmp(p, "login") == 0)
8930 setoption(int flag, int val)
8934 for (i = 0; i < NOPTS; i++)
8935 if (optletters(i) == flag) {
8939 sh_error("Illegal option -%c", flag);
8946 * Set the shell parameters.
8950 setparam(char **argv)
8956 for (nparam = 0 ; argv[nparam] ; nparam++);
8957 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8959 *ap++ = savestr(*argv++);
8962 freeparam(&shellparam);
8963 shellparam.malloc = 1;
8964 shellparam.nparam = nparam;
8965 shellparam.p = newparam;
8966 #ifdef CONFIG_ASH_GETOPTS
8967 shellparam.optind = 1;
8968 shellparam.optoff = -1;
8974 * Free the list of positional parameters.
8978 freeparam(volatile struct shparam *param)
8982 if (param->malloc) {
8983 for (ap = param->p ; *ap ; ap++)
8992 * The shift builtin command.
8996 shiftcmd(int argc, char **argv)
9003 n = number(argv[1]);
9004 if (n > shellparam.nparam)
9005 sh_error("can't shift that many");
9007 shellparam.nparam -= n;
9008 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9009 if (shellparam.malloc)
9013 while ((*ap2++ = *ap1++) != NULL);
9014 #ifdef CONFIG_ASH_GETOPTS
9015 shellparam.optind = 1;
9016 shellparam.optoff = -1;
9025 * The set command builtin.
9029 setcmd(int argc, char **argv)
9032 return showvars(nullstr, 0, VUNSET);
9036 if (*argptr != NULL) {
9044 #ifdef CONFIG_ASH_GETOPTS
9046 getoptsreset(const char *value)
9048 shellparam.optind = number(value);
9049 shellparam.optoff = -1;
9053 #ifdef CONFIG_LOCALE_SUPPORT
9054 static void change_lc_all(const char *value)
9056 if (value != 0 && *value != 0)
9057 setlocale(LC_ALL, value);
9060 static void change_lc_ctype(const char *value)
9062 if (value != 0 && *value != 0)
9063 setlocale(LC_CTYPE, value);
9068 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9069 /* Roughly copied from bash.. */
9070 static void change_random(const char *value)
9073 /* "get", generate */
9076 rseed = rseed * 1103515245 + 12345;
9077 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9078 /* set without recursion */
9079 setvar(vrandom.text, buf, VNOFUNC);
9080 vrandom.flags &= ~VNOFUNC;
9083 rseed = strtoul(value, (char **)NULL, 10);
9089 #ifdef CONFIG_ASH_GETOPTS
9091 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9100 if(*param_optind < 1)
9102 optnext = optfirst + *param_optind - 1;
9104 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9107 p = optnext[-1] + *optoff;
9108 if (p == NULL || *p == '\0') {
9109 /* Current word is done, advance */
9111 if (p == NULL || *p != '-' || *++p == '\0') {
9118 if (LONE_DASH(p)) /* check for "--" */
9123 for (q = optstr; *q != c; ) {
9125 if (optstr[0] == ':') {
9128 err |= setvarsafe("OPTARG", s, 0);
9130 fprintf(stderr, "Illegal option -%c\n", c);
9131 (void) unsetvar("OPTARG");
9141 if (*p == '\0' && (p = *optnext) == NULL) {
9142 if (optstr[0] == ':') {
9145 err |= setvarsafe("OPTARG", s, 0);
9148 fprintf(stderr, "No arg for -%c option\n", c);
9149 (void) unsetvar("OPTARG");
9157 err |= setvarsafe("OPTARG", p, 0);
9160 err |= setvarsafe("OPTARG", nullstr, 0);
9163 *optoff = p ? p - *(optnext - 1) : -1;
9164 *param_optind = optnext - optfirst + 1;
9165 fmtstr(s, sizeof(s), "%d", *param_optind);
9166 err |= setvarsafe("OPTIND", s, VNOFUNC);
9169 err |= setvarsafe(optvar, s, 0);
9180 * The getopts builtin. Shellparam.optnext points to the next argument
9181 * to be processed. Shellparam.optptr points to the next character to
9182 * be processed in the current argument. If shellparam.optnext is NULL,
9183 * then it's the first time getopts has been called.
9187 getoptscmd(int argc, char **argv)
9192 sh_error("Usage: getopts optstring var [arg]");
9193 else if (argc == 3) {
9194 optbase = shellparam.p;
9195 if (shellparam.optind > shellparam.nparam + 1) {
9196 shellparam.optind = 1;
9197 shellparam.optoff = -1;
9202 if (shellparam.optind > argc - 2) {
9203 shellparam.optind = 1;
9204 shellparam.optoff = -1;
9208 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9209 &shellparam.optoff);
9211 #endif /* CONFIG_ASH_GETOPTS */
9214 * XXX - should get rid of. have all builtins use getopt(3). the
9215 * library getopt must have the BSD extension static variable "optreset"
9216 * otherwise it can't be used within the shell safely.
9218 * Standard option processing (a la getopt) for builtin routines. The
9219 * only argument that is passed to nextopt is the option string; the
9220 * other arguments are unnecessary. It return the character, or '\0' on
9225 nextopt(const char *optstring)
9231 if ((p = optptr) == NULL || *p == '\0') {
9233 if (p == NULL || *p != '-' || *++p == '\0')
9236 if (LONE_DASH(p)) /* check for "--" */
9240 for (q = optstring ; *q != c ; ) {
9242 sh_error("Illegal option -%c", c);
9247 if (*p == '\0' && (p = *argptr++) == NULL)
9248 sh_error("No arg for -%c option", c);
9260 outstr(const char *p, FILE *file)
9285 outcslow(int c, FILE *dest)
9295 out1fmt(const char *fmt, ...)
9302 r = vprintf(fmt, ap);
9310 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9317 ret = vsnprintf(outbuf, length, fmt, ap);
9329 * Shell command parser.
9332 #define EOFMARKLEN 79
9336 struct heredoc *next; /* next here document in list */
9337 union node *here; /* redirection node */
9338 char *eofmark; /* string indicating end of input */
9339 int striptabs; /* if set, strip leading tabs */
9344 static struct heredoc *heredoclist; /* list of here documents to read */
9347 static union node *list(int);
9348 static union node *andor(void);
9349 static union node *pipeline(void);
9350 static union node *command(void);
9351 static union node *simplecmd(void);
9352 static union node *makename(void);
9353 static void parsefname(void);
9354 static void parseheredoc(void);
9355 static char peektoken(void);
9356 static int readtoken(void);
9357 static int xxreadtoken(void);
9358 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9359 static int noexpand(char *);
9360 static void synexpect(int) ATTRIBUTE_NORETURN;
9361 static void synerror(const char *) ATTRIBUTE_NORETURN;
9362 static void setprompt(int);
9368 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9369 * valid parse tree indicating a blank line.)
9373 parsecmd(int interact)
9378 doprompt = interact;
9380 setprompt(doprompt);
9395 union node *n1, *n2, *n3;
9398 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9399 if (nlflag == 2 && peektoken())
9405 if (tok == TBACKGND) {
9406 if (n2->type == NPIPE) {
9407 n2->npipe.backgnd = 1;
9409 if (n2->type != NREDIR) {
9410 n3 = stalloc(sizeof(struct nredir));
9412 n3->nredir.redirect = NULL;
9415 n2->type = NBACKGND;
9422 n3 = (union node *)stalloc(sizeof (struct nbinary));
9424 n3->nbinary.ch1 = n1;
9425 n3->nbinary.ch2 = n2;
9441 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9449 pungetc(); /* push back EOF on input */
9465 union node *n1, *n2, *n3;
9470 if ((t = readtoken()) == TAND) {
9472 } else if (t == TOR) {
9478 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9480 n3 = (union node *)stalloc(sizeof (struct nbinary));
9482 n3->nbinary.ch1 = n1;
9483 n3->nbinary.ch2 = n2;
9493 union node *n1, *n2, *pipenode;
9494 struct nodelist *lp, *prev;
9498 TRACE(("pipeline: entered\n"));
9499 if (readtoken() == TNOT) {
9501 checkkwd = CHKKWD | CHKALIAS;
9505 if (readtoken() == TPIPE) {
9506 pipenode = (union node *)stalloc(sizeof (struct npipe));
9507 pipenode->type = NPIPE;
9508 pipenode->npipe.backgnd = 0;
9509 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9510 pipenode->npipe.cmdlist = lp;
9514 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9515 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9518 } while (readtoken() == TPIPE);
9524 n2 = (union node *)stalloc(sizeof (struct nnot));
9537 union node *n1, *n2;
9538 union node *ap, **app;
9539 union node *cp, **cpp;
9540 union node *redir, **rpp;
9547 switch (readtoken()) {
9552 n1 = (union node *)stalloc(sizeof (struct nif));
9554 n1->nif.test = list(0);
9555 if (readtoken() != TTHEN)
9557 n1->nif.ifpart = list(0);
9559 while (readtoken() == TELIF) {
9560 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9561 n2 = n2->nif.elsepart;
9563 n2->nif.test = list(0);
9564 if (readtoken() != TTHEN)
9566 n2->nif.ifpart = list(0);
9568 if (lasttoken == TELSE)
9569 n2->nif.elsepart = list(0);
9571 n2->nif.elsepart = NULL;
9579 n1 = (union node *)stalloc(sizeof (struct nbinary));
9580 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9581 n1->nbinary.ch1 = list(0);
9582 if ((got=readtoken()) != TDO) {
9583 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9586 n1->nbinary.ch2 = list(0);
9591 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9592 synerror("Bad for loop variable");
9593 n1 = (union node *)stalloc(sizeof (struct nfor));
9595 n1->nfor.var = wordtext;
9596 checkkwd = CHKKWD | CHKALIAS;
9597 if (readtoken() == TIN) {
9599 while (readtoken() == TWORD) {
9600 n2 = (union node *)stalloc(sizeof (struct narg));
9602 n2->narg.text = wordtext;
9603 n2->narg.backquote = backquotelist;
9605 app = &n2->narg.next;
9609 if (lasttoken != TNL && lasttoken != TSEMI)
9612 n2 = (union node *)stalloc(sizeof (struct narg));
9614 n2->narg.text = (char *)dolatstr;
9615 n2->narg.backquote = NULL;
9616 n2->narg.next = NULL;
9619 * Newline or semicolon here is optional (but note
9620 * that the original Bourne shell only allowed NL).
9622 if (lasttoken != TNL && lasttoken != TSEMI)
9625 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9626 if (readtoken() != TDO)
9628 n1->nfor.body = list(0);
9632 n1 = (union node *)stalloc(sizeof (struct ncase));
9634 if (readtoken() != TWORD)
9636 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9638 n2->narg.text = wordtext;
9639 n2->narg.backquote = backquotelist;
9640 n2->narg.next = NULL;
9642 checkkwd = CHKKWD | CHKALIAS;
9643 } while (readtoken() == TNL);
9644 if (lasttoken != TIN)
9646 cpp = &n1->ncase.cases;
9648 checkkwd = CHKNL | CHKKWD;
9651 if (lasttoken == TLP)
9653 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9655 app = &cp->nclist.pattern;
9657 *app = ap = (union node *)stalloc(sizeof (struct narg));
9659 ap->narg.text = wordtext;
9660 ap->narg.backquote = backquotelist;
9661 if (readtoken() != TPIPE)
9663 app = &ap->narg.next;
9666 ap->narg.next = NULL;
9667 if (lasttoken != TRP)
9669 cp->nclist.body = list(2);
9671 cpp = &cp->nclist.next;
9673 checkkwd = CHKNL | CHKKWD;
9674 if ((t = readtoken()) != TESAC) {
9676 synexpect(TENDCASE);
9684 n1 = (union node *)stalloc(sizeof (struct nredir));
9685 n1->type = NSUBSHELL;
9686 n1->nredir.n = list(0);
9687 n1->nredir.redirect = NULL;
9700 if (readtoken() != t)
9704 /* Now check for redirection which may follow command */
9705 checkkwd = CHKKWD | CHKALIAS;
9707 while (readtoken() == TREDIR) {
9708 *rpp = n2 = redirnode;
9709 rpp = &n2->nfile.next;
9715 if (n1->type != NSUBSHELL) {
9716 n2 = (union node *)stalloc(sizeof (struct nredir));
9721 n1->nredir.redirect = redir;
9730 union node *args, **app;
9731 union node *n = NULL;
9732 union node *vars, **vpp;
9733 union node **rpp, *redir;
9743 savecheckkwd = CHKALIAS;
9745 checkkwd = savecheckkwd;
9746 switch (readtoken()) {
9748 n = (union node *)stalloc(sizeof (struct narg));
9750 n->narg.text = wordtext;
9751 n->narg.backquote = backquotelist;
9752 if (savecheckkwd && isassignment(wordtext)) {
9754 vpp = &n->narg.next;
9757 app = &n->narg.next;
9762 *rpp = n = redirnode;
9763 rpp = &n->nfile.next;
9764 parsefname(); /* read name of redirection file */
9768 args && app == &args->narg.next &&
9771 struct builtincmd *bcmd;
9774 /* We have a function */
9775 if (readtoken() != TRP)
9777 name = n->narg.text;
9779 !goodname(name) || (
9780 (bcmd = find_builtin(name)) &&
9781 IS_BUILTIN_SPECIAL(bcmd)
9784 synerror("Bad function name");
9786 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9787 n->narg.next = command();
9800 n = (union node *)stalloc(sizeof (struct ncmd));
9802 n->ncmd.args = args;
9803 n->ncmd.assign = vars;
9804 n->ncmd.redirect = redir;
9813 n = (union node *)stalloc(sizeof (struct narg));
9815 n->narg.next = NULL;
9816 n->narg.text = wordtext;
9817 n->narg.backquote = backquotelist;
9821 void fixredir(union node *n, const char *text, int err)
9823 TRACE(("Fix redir %s %d\n", text, err));
9825 n->ndup.vname = NULL;
9827 if (is_digit(text[0]) && text[1] == '\0')
9828 n->ndup.dupfd = digit_val(text[0]);
9829 else if (LONE_DASH(text))
9834 synerror("Bad fd number");
9836 n->ndup.vname = makename();
9844 union node *n = redirnode;
9846 if (readtoken() != TWORD)
9848 if (n->type == NHERE) {
9849 struct heredoc *here = heredoc;
9855 TRACE(("Here document %d\n", n->type));
9856 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9857 synerror("Illegal eof marker for << redirection");
9858 rmescapes(wordtext);
9859 here->eofmark = wordtext;
9861 if (heredoclist == NULL)
9864 for (p = heredoclist ; p->next ; p = p->next);
9867 } else if (n->type == NTOFD || n->type == NFROMFD) {
9868 fixredir(n, wordtext, 0);
9870 n->nfile.fname = makename();
9876 * Input any here documents.
9882 struct heredoc *here;
9892 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9893 here->eofmark, here->striptabs);
9894 n = (union node *)stalloc(sizeof (struct narg));
9895 n->narg.type = NARG;
9896 n->narg.next = NULL;
9897 n->narg.text = wordtext;
9898 n->narg.backquote = backquotelist;
9899 here->here->nhere.doc = n;
9904 static char peektoken(void)
9910 return tokname_array[t][0];
9918 int alreadyseen = tokpushback;
9921 #ifdef CONFIG_ASH_ALIAS
9930 if (checkkwd & CHKNL) {
9937 if (t != TWORD || quoteflag) {
9942 * check for keywords
9944 if (checkkwd & CHKKWD) {
9945 const char *const *pp;
9947 if ((pp = findkwd(wordtext))) {
9948 lasttoken = t = pp - tokname_array;
9949 TRACE(("keyword %s recognized\n", tokname(t)));
9954 if (checkkwd & CHKALIAS) {
9955 #ifdef CONFIG_ASH_ALIAS
9957 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9959 pushstring(ap->val, ap);
9969 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9971 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9978 * Read the next input token.
9979 * If the token is a word, we set backquotelist to the list of cmds in
9980 * backquotes. We set quoteflag to true if any part of the word was
9982 * If the token is TREDIR, then we set redirnode to a structure containing
9984 * In all cases, the variable startlinno is set to the number of the line
9985 * on which the token starts.
9987 * [Change comment: here documents and internal procedures]
9988 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9989 * word parsing code into a separate routine. In this case, readtoken
9990 * doesn't need to have any internal procedures, but parseword does.
9991 * We could also make parseoperator in essence the main routine, and
9992 * have parseword (readtoken1?) handle both words and redirection.]
9995 #define NEW_xxreadtoken
9996 #ifdef NEW_xxreadtoken
9998 /* singles must be first! */
9999 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10001 static const char xxreadtoken_tokens[] = {
10002 TNL, TLP, TRP, /* only single occurrence allowed */
10003 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10004 TEOF, /* corresponds to trailing nul */
10005 TAND, TOR, TENDCASE, /* if double occurrence */
10008 #define xxreadtoken_doubles \
10009 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10010 #define xxreadtoken_singles \
10011 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10013 static int xxreadtoken(void)
10024 startlinno = plinno;
10025 for (;;) { /* until token or start of word found */
10028 if ((c != ' ') && (c != '\t')
10029 #ifdef CONFIG_ASH_ALIAS
10034 while ((c = pgetc()) != '\n' && c != PEOF);
10036 } else if (c == '\\') {
10037 if (pgetc() != '\n') {
10041 startlinno = ++plinno;
10046 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10051 needprompt = doprompt;
10054 p = strchr(xxreadtoken_chars, c);
10057 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10060 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10061 if (pgetc() == *p) { /* double occurrence? */
10062 p += xxreadtoken_doubles + 1;
10069 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10077 #define RETURN(token) return lasttoken = token
10091 startlinno = plinno;
10092 for (;;) { /* until token or start of word found */
10095 case ' ': case '\t':
10096 #ifdef CONFIG_ASH_ALIAS
10101 while ((c = pgetc()) != '\n' && c != PEOF);
10105 if (pgetc() == '\n') {
10106 startlinno = ++plinno;
10115 needprompt = doprompt;
10120 if (pgetc() == '&')
10125 if (pgetc() == '|')
10130 if (pgetc() == ';')
10143 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10146 #endif /* NEW_xxreadtoken */
10150 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10151 * is not NULL, read a here document. In the latter case, eofmark is the
10152 * word which marks the end of the document and striptabs is true if
10153 * leading tabs should be stripped from the document. The argument firstc
10154 * is the first character of the input token or document.
10156 * Because C does not have internal subroutines, I have simulated them
10157 * using goto's to implement the subroutine linkage. The following macros
10158 * will run code that appears at the end of readtoken1.
10161 #define CHECKEND() {goto checkend; checkend_return:;}
10162 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10163 #define PARSESUB() {goto parsesub; parsesub_return:;}
10164 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10165 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10166 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10169 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10174 char line[EOFMARKLEN + 1];
10175 struct nodelist *bqlist = 0;
10178 int varnest = 0; /* levels of variables expansion */
10179 int arinest = 0; /* levels of arithmetic expansion */
10180 int parenlevel = 0; /* levels of parens in arithmetic */
10181 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10183 int prevsyntax = 0; /* syntax before arithmetic */
10185 /* Avoid longjmp clobbering */
10191 (void) &parenlevel;
10194 (void) &prevsyntax;
10198 startlinno = plinno;
10200 if (syntax == DQSYNTAX)
10209 STARTSTACKSTR(out);
10210 loop: { /* for each line, until end of word */
10211 CHECKEND(); /* set c to PEOF if at end of here document */
10212 for (;;) { /* until end of line or end of word */
10213 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10214 switch(SIT(c, syntax)) {
10215 case CNL: /* '\n' */
10216 if (syntax == BASESYNTAX)
10217 goto endword; /* exit outer loop */
10223 goto loop; /* continue outer loop */
10228 if (eofmark == NULL || dblquote)
10229 USTPUTC(CTLESC, out);
10232 case CBACK: /* backslash */
10235 USTPUTC(CTLESC, out);
10236 USTPUTC('\\', out);
10238 } else if (c == '\n') {
10243 c != '\\' && c != '`' &&
10248 USTPUTC(CTLESC, out);
10249 USTPUTC('\\', out);
10251 if (SIT(c, SQSYNTAX) == CCTL)
10252 USTPUTC(CTLESC, out);
10260 if (eofmark == NULL) {
10261 USTPUTC(CTLQUOTEMARK, out);
10269 if (eofmark != NULL && arinest == 0 &&
10273 if (dqvarnest == 0) {
10274 syntax = BASESYNTAX;
10281 case CVAR: /* '$' */
10282 PARSESUB(); /* parse substitution */
10284 case CENDVAR: /* '}' */
10287 if (dqvarnest > 0) {
10290 USTPUTC(CTLENDVAR, out);
10295 #ifdef CONFIG_ASH_MATH_SUPPORT
10296 case CLP: /* '(' in arithmetic */
10300 case CRP: /* ')' in arithmetic */
10301 if (parenlevel > 0) {
10305 if (pgetc() == ')') {
10306 if (--arinest == 0) {
10307 USTPUTC(CTLENDARI, out);
10308 syntax = prevsyntax;
10309 if (syntax == DQSYNTAX)
10317 * unbalanced parens
10318 * (don't 2nd guess - no error)
10326 case CBQUOTE: /* '`' */
10330 goto endword; /* exit outer loop */
10335 goto endword; /* exit outer loop */
10336 #ifdef CONFIG_ASH_ALIAS
10346 #ifdef CONFIG_ASH_MATH_SUPPORT
10347 if (syntax == ARISYNTAX)
10348 synerror("Missing '))'");
10350 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10351 synerror("Unterminated quoted string");
10352 if (varnest != 0) {
10353 startlinno = plinno;
10355 synerror("Missing '}'");
10357 USTPUTC('\0', out);
10358 len = out - (char *)stackblock();
10359 out = stackblock();
10360 if (eofmark == NULL) {
10361 if ((c == '>' || c == '<')
10364 && (*out == '\0' || is_digit(*out))) {
10366 return lasttoken = TREDIR;
10371 quoteflag = quotef;
10372 backquotelist = bqlist;
10373 grabstackblock(len);
10375 return lasttoken = TWORD;
10376 /* end of readtoken routine */
10381 * Check to see whether we are at the end of the here document. When this
10382 * is called, c is set to the first character of the next input line. If
10383 * we are at the end of the here document, this routine sets the c to PEOF.
10388 #ifdef CONFIG_ASH_ALIAS
10394 while (c == '\t') {
10398 if (c == *eofmark) {
10399 if (pfgets(line, sizeof line) != NULL) {
10403 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10404 if (*p == '\n' && *q == '\0') {
10407 needprompt = doprompt;
10409 pushstring(line, NULL);
10414 goto checkend_return;
10419 * Parse a redirection operator. The variable "out" points to a string
10420 * specifying the fd to be redirected. The variable "c" contains the
10421 * first character of the redirection operator.
10428 np = (union node *)stalloc(sizeof (struct nfile));
10433 np->type = NAPPEND;
10435 np->type = NCLOBBER;
10442 } else { /* c == '<' */
10444 switch (c = pgetc()) {
10446 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10447 np = (union node *)stalloc(sizeof (struct nhere));
10451 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10452 heredoc->here = np;
10453 if ((c = pgetc()) == '-') {
10454 heredoc->striptabs = 1;
10456 heredoc->striptabs = 0;
10462 np->type = NFROMFD;
10466 np->type = NFROMTO;
10476 np->nfile.fd = digit_val(fd);
10478 goto parseredir_return;
10483 * Parse a substitution. At this point, we have read the dollar sign
10484 * and nothing else.
10492 static const char types[] = "}-+?=";
10496 c <= PEOA_OR_PEOF ||
10497 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10501 } else if (c == '(') { /* $(command) or $((arith)) */
10502 if (pgetc() == '(') {
10503 #ifdef CONFIG_ASH_MATH_SUPPORT
10506 synerror("We unsupport $((arith))");
10513 USTPUTC(CTLVAR, out);
10514 typeloc = out - (char *)stackblock();
10515 USTPUTC(VSNORMAL, out);
10516 subtype = VSNORMAL;
10520 if ((c = pgetc()) == '}')
10523 subtype = VSLENGTH;
10528 if (c > PEOA_OR_PEOF && is_name(c)) {
10532 } while (c > PEOA_OR_PEOF && is_in_name(c));
10533 } else if (is_digit(c)) {
10537 } while (is_digit(c));
10539 else if (is_special(c)) {
10544 badsub: synerror("Bad substitution");
10548 if (subtype == 0) {
10555 p = strchr(types, c);
10558 subtype = p - types + VSNORMAL;
10564 subtype = c == '#' ? VSTRIMLEFT :
10577 if (dblquote || arinest)
10579 *((char *)stackblock() + typeloc) = subtype | flags;
10580 if (subtype != VSNORMAL) {
10582 if (dblquote || arinest) {
10587 goto parsesub_return;
10592 * Called to parse command substitutions. Newstyle is set if the command
10593 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10594 * list of commands (passed by reference), and savelen is the number of
10595 * characters on the top of the stack which must be preserved.
10599 struct nodelist **nlpp;
10602 char *volatile str;
10603 struct jmploc jmploc;
10604 struct jmploc *volatile savehandler;
10606 int saveprompt = 0;
10608 (void) &saveprompt;
10611 savepbq = parsebackquote;
10612 if (setjmp(jmploc.loc)) {
10615 parsebackquote = 0;
10616 handler = savehandler;
10617 longjmp(handler->loc, 1);
10621 savelen = out - (char *)stackblock();
10623 str = ckmalloc(savelen);
10624 memcpy(str, stackblock(), savelen);
10626 savehandler = handler;
10630 /* We must read until the closing backquote, giving special
10631 treatment to some slashes, and then push the string and
10632 reread it as input, interpreting it normally. */
10639 STARTSTACKSTR(pout);
10644 switch (pc = pgetc()) {
10649 if ((pc = pgetc()) == '\n') {
10654 * If eating a newline, avoid putting
10655 * the newline into the new character
10656 * stream (via the STPUTC after the
10661 if (pc != '\\' && pc != '`' && pc != '$'
10662 && (!dblquote || pc != '"'))
10663 STPUTC('\\', pout);
10664 if (pc > PEOA_OR_PEOF) {
10670 #ifdef CONFIG_ASH_ALIAS
10673 startlinno = plinno;
10674 synerror("EOF in backquote substitution");
10678 needprompt = doprompt;
10687 STPUTC('\0', pout);
10688 psavelen = pout - (char *)stackblock();
10689 if (psavelen > 0) {
10690 pstr = grabstackstr(pout);
10691 setinputstring(pstr);
10696 nlpp = &(*nlpp)->next;
10697 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10698 (*nlpp)->next = NULL;
10699 parsebackquote = oldstyle;
10702 saveprompt = doprompt;
10709 doprompt = saveprompt;
10711 if (readtoken() != TRP)
10718 * Start reading from old file again, ignoring any pushed back
10719 * tokens left from the backquote parsing
10724 while (stackblocksize() <= savelen)
10726 STARTSTACKSTR(out);
10728 memcpy(out, str, savelen);
10729 STADJUST(savelen, out);
10735 parsebackquote = savepbq;
10736 handler = savehandler;
10737 if (arinest || dblquote)
10738 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10740 USTPUTC(CTLBACKQ, out);
10742 goto parsebackq_oldreturn;
10744 goto parsebackq_newreturn;
10747 #ifdef CONFIG_ASH_MATH_SUPPORT
10749 * Parse an arithmetic expansion (indicate start of one and set state)
10753 if (++arinest == 1) {
10754 prevsyntax = syntax;
10755 syntax = ARISYNTAX;
10756 USTPUTC(CTLARI, out);
10763 * we collapse embedded arithmetic expansion to
10764 * parenthesis, which should be equivalent
10768 goto parsearith_return;
10772 } /* end of readtoken */
10777 * Returns true if the text contains nothing to expand (no dollar signs
10782 noexpand(char *text)
10788 while ((c = *p++) != '\0') {
10789 if (c == CTLQUOTEMARK)
10793 else if (SIT(c, BASESYNTAX) == CCTL)
10801 * Return of a legal variable name (a letter or underscore followed by zero or
10802 * more letters, underscores, and digits).
10806 endofname(const char *name)
10814 if (! is_in_name(*p))
10822 * Called when an unexpected token is read during the parse. The argument
10823 * is the token that is expected, or -1 if more than one type of token can
10824 * occur at this point.
10827 static void synexpect(int token)
10832 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10834 sprintf(msg + l, " (expecting %s)", tokname(token));
10840 synerror(const char *msg)
10842 sh_error("Syntax error: %s", msg);
10848 * called by editline -- any expansions to the prompt
10849 * should be added here.
10852 #ifdef CONFIG_ASH_EXPAND_PRMT
10853 static const char *
10854 expandstr(const char *ps)
10858 /* XXX Fix (char *) cast. */
10859 setinputstring((char *)ps);
10860 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10863 n.narg.type = NARG;
10864 n.narg.next = NULL;
10865 n.narg.text = wordtext;
10866 n.narg.backquote = backquotelist;
10868 expandarg(&n, NULL, 0);
10869 return stackblock();
10873 static void setprompt(int whichprompt)
10875 const char *prompt;
10876 #ifdef CONFIG_ASH_EXPAND_PRMT
10877 struct stackmark smark;
10882 switch (whichprompt) {
10892 #ifdef CONFIG_ASH_EXPAND_PRMT
10893 setstackmark(&smark);
10894 stalloc(stackblocksize());
10896 putprompt(expandstr(prompt));
10897 #ifdef CONFIG_ASH_EXPAND_PRMT
10898 popstackmark(&smark);
10903 static const char *const *findkwd(const char *s)
10905 return bsearch(s, tokname_array + KWDOFFSET,
10906 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10907 sizeof(const char *), pstrcmp);
10913 * Code for dealing with input/output redirection.
10916 #define EMPTY -2 /* marks an unused slot in redirtab */
10918 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10920 # define PIPESIZE PIPE_BUF
10924 * Open a file in noclobber mode.
10925 * The code was copied from bash.
10927 static int noclobberopen(const char *fname)
10930 struct stat finfo, finfo2;
10933 * If the file exists and is a regular file, return an error
10936 r = stat(fname, &finfo);
10937 if (r == 0 && S_ISREG(finfo.st_mode)) {
10943 * If the file was not present (r != 0), make sure we open it
10944 * exclusively so that if it is created before we open it, our open
10945 * will fail. Make sure that we do not truncate an existing file.
10946 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10947 * file was not a regular file, we leave O_EXCL off.
10950 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10951 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10953 /* If the open failed, return the file descriptor right away. */
10958 * OK, the open succeeded, but the file may have been changed from a
10959 * non-regular file to a regular file between the stat and the open.
10960 * We are assuming that the O_EXCL open handles the case where FILENAME
10961 * did not exist and is symlinked to an existing file between the stat
10966 * If we can open it and fstat the file descriptor, and neither check
10967 * revealed that it was a regular file, and the file has not been
10968 * replaced, return the file descriptor.
10970 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10971 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10974 /* The file has been replaced. badness. */
10981 * Handle here documents. Normally we fork off a process to write the
10982 * data to a pipe. If the document is short, we can stuff the data in
10983 * the pipe without forking.
10986 static int openhere(union node *redir)
10992 sh_error("Pipe call failed");
10993 if (redir->type == NHERE) {
10994 len = strlen(redir->nhere.doc->narg.text);
10995 if (len <= PIPESIZE) {
10996 full_write(pip[1], redir->nhere.doc->narg.text, len);
11000 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11002 signal(SIGINT, SIG_IGN);
11003 signal(SIGQUIT, SIG_IGN);
11004 signal(SIGHUP, SIG_IGN);
11006 signal(SIGTSTP, SIG_IGN);
11008 signal(SIGPIPE, SIG_DFL);
11009 if (redir->type == NHERE)
11010 full_write(pip[1], redir->nhere.doc->narg.text, len);
11012 expandhere(redir->nhere.doc, pip[1]);
11021 openredirect(union node *redir)
11026 switch (redir->nfile.type) {
11028 fname = redir->nfile.expfname;
11029 if ((f = open(fname, O_RDONLY)) < 0)
11033 fname = redir->nfile.expfname;
11034 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11038 /* Take care of noclobber mode. */
11040 fname = redir->nfile.expfname;
11041 if ((f = noclobberopen(fname)) < 0)
11047 fname = redir->nfile.expfname;
11048 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11052 fname = redir->nfile.expfname;
11053 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11060 /* Fall through to eliminate warning. */
11067 f = openhere(redir);
11073 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11075 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11078 static void dupredirect(union node *redir, int f)
11080 int fd = redir->nfile.fd;
11082 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11083 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11084 copyfd(redir->ndup.dupfd, fd);
11097 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11098 * old file descriptors are stashed away so that the redirection can be
11099 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11100 * standard output, and the standard error if it becomes a duplicate of
11101 * stdout, is saved in memory.
11105 redirect(union node *redir, int flags)
11108 struct redirtab *sv;
11119 if (flags & REDIR_PUSH) {
11120 struct redirtab *q;
11121 q = ckmalloc(sizeof (struct redirtab));
11122 q->next = redirlist;
11124 q->nullredirs = nullredirs - 1;
11125 for (i = 0 ; i < 10 ; i++)
11126 q->renamed[i] = EMPTY;
11133 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11134 n->ndup.dupfd == fd)
11135 continue; /* redirect from/to same file descriptor */
11137 newfd = openredirect(n);
11140 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11141 i = fcntl(fd, F_DUPFD, 10);
11148 sh_error("%d: %m", fd);
11158 dupredirect(n, newfd);
11159 } while ((n = n->nfile.next));
11161 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11162 preverrout_fd = sv->renamed[2];
11167 * Undo the effects of the last redirection.
11173 struct redirtab *rp;
11176 if (--nullredirs >= 0)
11180 for (i = 0 ; i < 10 ; i++) {
11181 if (rp->renamed[i] != EMPTY) {
11184 copyfd(rp->renamed[i], i);
11186 close(rp->renamed[i]);
11189 redirlist = rp->next;
11190 nullredirs = rp->nullredirs;
11196 * Undo all redirections. Called on error or interrupt.
11200 * Discard all saved file descriptors.
11204 clearredir(int drop)
11216 * Copy a file descriptor to be >= to. Returns -1
11217 * if the source file descriptor is closed, EMPTY if there are no unused
11218 * file descriptors left.
11222 copyfd(int from, int to)
11226 newfd = fcntl(from, F_DUPFD, to);
11228 if (errno == EMFILE)
11231 sh_error("%d: %m", from);
11238 redirectsafe(union node *redir, int flags)
11241 volatile int saveint;
11242 struct jmploc *volatile savehandler = handler;
11243 struct jmploc jmploc;
11246 if (!(err = setjmp(jmploc.loc) * 2)) {
11248 redirect(redir, flags);
11250 handler = savehandler;
11251 if (err && exception != EXERROR)
11252 longjmp(handler->loc, 1);
11253 RESTOREINT(saveint);
11260 static void shtree(union node *, int, char *, FILE*);
11261 static void shcmd(union node *, FILE *);
11262 static void sharg(union node *, FILE *);
11263 static void indent(int, char *, FILE *);
11264 static void trstring(char *);
11268 showtree(union node *n)
11270 trputs("showtree called\n");
11271 shtree(n, 1, NULL, stdout);
11276 shtree(union node *n, int ind, char *pfx, FILE *fp)
11278 struct nodelist *lp;
11284 indent(ind, pfx, fp);
11295 shtree(n->nbinary.ch1, ind, NULL, fp);
11298 shtree(n->nbinary.ch2, ind, NULL, fp);
11306 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11311 if (n->npipe.backgnd)
11317 fprintf(fp, "<node type %d>", n->type);
11326 shcmd(union node *cmd, FILE *fp)
11334 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11340 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11343 switch (np->nfile.type) {
11344 case NTO: s = ">"; dftfd = 1; break;
11345 case NCLOBBER: s = ">|"; dftfd = 1; break;
11346 case NAPPEND: s = ">>"; dftfd = 1; break;
11347 case NTOFD: s = ">&"; dftfd = 1; break;
11348 case NFROM: s = "<"; dftfd = 0; break;
11349 case NFROMFD: s = "<&"; dftfd = 0; break;
11350 case NFROMTO: s = "<>"; dftfd = 0; break;
11351 default: s = "*error*"; dftfd = 0; break;
11353 if (np->nfile.fd != dftfd)
11354 fprintf(fp, "%d", np->nfile.fd);
11356 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11357 fprintf(fp, "%d", np->ndup.dupfd);
11359 sharg(np->nfile.fname, fp);
11368 sharg(union node *arg, FILE *fp)
11371 struct nodelist *bqlist;
11374 if (arg->type != NARG) {
11375 out1fmt("<node type %d>\n", arg->type);
11378 bqlist = arg->narg.backquote;
11379 for (p = arg->narg.text ; *p ; p++) {
11388 if (subtype == VSLENGTH)
11394 if (subtype & VSNUL)
11397 switch (subtype & VSTYPE) {
11416 case VSTRIMLEFTMAX:
11423 case VSTRIMRIGHTMAX:
11430 out1fmt("<subtype %d>", subtype);
11437 case CTLBACKQ|CTLQUOTE:
11440 shtree(bqlist->n, -1, NULL, fp);
11452 indent(int amount, char *pfx, FILE *fp)
11456 for (i = 0 ; i < amount ; i++) {
11457 if (pfx && i == amount - 1)
11478 putc(c, tracefile);
11482 trace(const char *fmt, ...)
11489 (void) vfprintf(tracefile, fmt, va);
11494 tracev(const char *fmt, va_list va)
11498 (void) vfprintf(tracefile, fmt, va);
11503 trputs(const char *s)
11507 fputs(s, tracefile);
11519 putc('"', tracefile);
11520 for (p = s ; *p ; p++) {
11522 case '\n': c = 'n'; goto backslash;
11523 case '\t': c = 't'; goto backslash;
11524 case '\r': c = 'r'; goto backslash;
11525 case '"': c = '"'; goto backslash;
11526 case '\\': c = '\\'; goto backslash;
11527 case CTLESC: c = 'e'; goto backslash;
11528 case CTLVAR: c = 'v'; goto backslash;
11529 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11530 case CTLBACKQ: c = 'q'; goto backslash;
11531 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11532 backslash: putc('\\', tracefile);
11533 putc(c, tracefile);
11536 if (*p >= ' ' && *p <= '~')
11537 putc(*p, tracefile);
11539 putc('\\', tracefile);
11540 putc(*p >> 6 & 03, tracefile);
11541 putc(*p >> 3 & 07, tracefile);
11542 putc(*p & 07, tracefile);
11547 putc('"', tracefile);
11559 putc(' ', tracefile);
11561 putc('\n', tracefile);
11577 /* leave open because libedit might be using it */
11580 scopy("./trace", s);
11582 if (!freopen(s, "a", tracefile)) {
11583 fprintf(stderr, "Can't re-open %s\n", s);
11588 if ((tracefile = fopen(s, "a")) == NULL) {
11589 fprintf(stderr, "Can't open %s\n", s);
11595 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11596 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11598 setlinebuf(tracefile);
11599 fputs("\nTracing started.\n", tracefile);
11607 * Sigmode records the current value of the signal handlers for the various
11608 * modes. A value of zero means that the current handler is not known.
11609 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11612 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11613 #define S_CATCH 2 /* signal is caught */
11614 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11615 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11616 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11621 * The trap builtin.
11625 trapcmd(int argc, char **argv)
11634 for (signo = 0 ; signo < NSIG ; signo++) {
11635 if (trap[signo] != NULL) {
11638 sn = get_signame(signo);
11639 out1fmt("trap -- %s %s\n",
11640 single_quote(trap[signo]), sn);
11650 if ((signo = get_signum(*ap)) < 0)
11651 sh_error("%s: bad trap", *ap);
11654 if (LONE_DASH(action))
11657 action = savestr(action);
11660 ckfree(trap[signo]);
11661 trap[signo] = action;
11672 * Clear traps on a fork.
11680 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11681 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11685 if (tp != &trap[0])
11686 setsignal(tp - trap);
11694 * Set the signal handler for the specified signal. The routine figures
11695 * out what it should be set to.
11699 setsignal(int signo)
11703 struct sigaction act;
11705 if ((t = trap[signo]) == NULL)
11707 else if (*t != '\0')
11711 if (rootshell && action == S_DFL) {
11714 if (iflag || minusc || sflag == 0)
11737 t = &sigmode[signo - 1];
11741 * current setting unknown
11743 if (sigaction(signo, 0, &act) == -1) {
11745 * Pretend it worked; maybe we should give a warning
11746 * here, but other shells don't. We don't alter
11747 * sigmode, so that we retry every time.
11751 if (act.sa_handler == SIG_IGN) {
11752 if (mflag && (signo == SIGTSTP ||
11753 signo == SIGTTIN || signo == SIGTTOU)) {
11754 tsig = S_IGN; /* don't hard ignore these */
11758 tsig = S_RESET; /* force to be set */
11761 if (tsig == S_HARD_IGN || tsig == action)
11765 act.sa_handler = onsig;
11768 act.sa_handler = SIG_IGN;
11771 act.sa_handler = SIG_DFL;
11775 sigfillset(&act.sa_mask);
11776 sigaction(signo, &act, 0);
11784 ignoresig(int signo)
11786 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11787 signal(signo, SIG_IGN);
11789 sigmode[signo - 1] = S_HARD_IGN;
11800 gotsig[signo - 1] = 1;
11801 pendingsigs = signo;
11803 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11812 * Called to execute a trap. Perhaps we should avoid entering new trap
11813 * handlers while we are executing a trap handler.
11825 savestatus = exitstatus;
11829 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11837 skip = evalstring(p, SKIPEVAL);
11838 exitstatus = savestatus;
11848 * Controls whether the shell is interactive or not.
11852 setinteractive(int on)
11854 static int is_interactive;
11856 if (++on == is_interactive)
11858 is_interactive = on;
11860 setsignal(SIGQUIT);
11861 setsignal(SIGTERM);
11862 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11863 if(is_interactive > 1) {
11864 /* Looks like they want an interactive shell */
11865 static int do_banner;
11869 "\n\n%s Built-in shell (ash)\n"
11870 "Enter 'help' for a list of built-in commands.\n\n",
11879 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11880 /*** List the available builtins ***/
11882 static int helpcmd(int argc, char **argv)
11886 out1fmt("\nBuilt-in commands:\n-------------------\n");
11887 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11888 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11889 builtincmd[i].name + 1);
11895 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11896 for (i = 0; i < NUM_APPLETS; i++) {
11897 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11905 return EXIT_SUCCESS;
11907 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11910 * Called to exit the shell.
11920 status = exitstatus;
11921 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11922 if (setjmp(loc.loc)) {
11923 if (exception == EXEXIT)
11928 if ((p = trap[0])) {
11934 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11935 if (iflag && rootshell) {
11936 const char *hp = lookupvar("HISTFILE");
11939 save_history ( hp );
11949 static struct var *vartab[VTABSIZE];
11951 static int vpcmp(const void *, const void *);
11952 static struct var **findvar(struct var **, const char *);
11955 * Initialize the variable symbol tables and import the environment
11959 #ifdef CONFIG_ASH_GETOPTS
11961 * Safe version of setvar, returns 1 on success 0 on failure.
11965 setvarsafe(const char *name, const char *val, int flags)
11968 volatile int saveint;
11969 struct jmploc *volatile savehandler = handler;
11970 struct jmploc jmploc;
11973 if (setjmp(jmploc.loc))
11977 setvar(name, val, flags);
11980 handler = savehandler;
11981 RESTOREINT(saveint);
11987 * Set the value of a variable. The flags argument is ored with the
11988 * flags of the variable. If val is NULL, the variable is unset.
11992 setvar(const char *name, const char *val, int flags)
11999 q = endofname(name);
12000 p = strchrnul(q, '=');
12001 namelen = p - name;
12002 if (!namelen || p != q)
12003 sh_error("%.*s: bad variable name", namelen, name);
12008 vallen = strlen(val);
12011 nameeq = ckmalloc(namelen + vallen + 2);
12012 p = memcpy(nameeq, name, namelen) + namelen;
12015 p = memcpy(p, val, vallen) + 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 (LONE_DASH(name)) {
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.
12566 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12567 typedef enum __rlimit_resource rlim_t;
12572 * The read builtin. The -e option causes backslashes to escape the
12573 * following character.
12575 * This uses unbuffered input, which may be avoidable in some cases.
12579 readcmd(int argc, char **argv)
12591 #if defined(CONFIG_ASH_READ_NCHARS)
12595 struct termios tty, old_tty;
12597 #if defined(CONFIG_ASH_READ_TIMEOUT)
12601 ts.tv_sec = ts.tv_usec = 0;
12606 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12607 while ((i = nextopt("p:rt:n:s")) != '\0')
12608 #elif defined(CONFIG_ASH_READ_NCHARS)
12609 while ((i = nextopt("p:rn:s")) != '\0')
12610 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12611 while ((i = nextopt("p:rt:")) != '\0')
12613 while ((i = nextopt("p:r")) != '\0')
12618 prompt = optionarg;
12620 #if defined(CONFIG_ASH_READ_NCHARS)
12622 nchars = strtol(optionarg, &p, 10);
12624 sh_error("invalid count");
12625 nch_flag = (nchars > 0);
12631 #if defined(CONFIG_ASH_READ_TIMEOUT)
12633 ts.tv_sec = strtol(optionarg, &p, 10);
12639 ts.tv_usec = strtol(p, &p2, 10);
12641 sh_error("invalid timeout");
12643 /* normalize to usec */
12645 sh_error("invalid timeout");
12646 while (scale++ < 6)
12650 sh_error("invalid timeout");
12652 if ( ! ts.tv_sec && ! ts.tv_usec)
12653 sh_error("invalid timeout");
12663 if (prompt && isatty(0)) {
12666 if (*(ap = argptr) == NULL)
12667 sh_error("arg count");
12668 if ((ifs = bltinlookup("IFS")) == NULL)
12670 #if defined(CONFIG_ASH_READ_NCHARS)
12671 if (nch_flag || silent) {
12672 tcgetattr(0, &tty);
12675 tty.c_lflag &= ~ICANON;
12676 tty.c_cc[VMIN] = nchars;
12679 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12682 tcsetattr(0, TCSANOW, &tty);
12685 #if defined(CONFIG_ASH_READ_TIMEOUT)
12686 if (ts.tv_sec || ts.tv_usec) {
12690 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
12692 #if defined(CONFIG_ASH_READ_NCHARS)
12694 tcsetattr(0, TCSANOW, &old_tty);
12704 #if defined(CONFIG_ASH_READ_NCHARS)
12705 while (!nch_flag || nchars--)
12710 if (read(0, &c, 1) != 1) {
12722 if (!rflag && c == '\\') {
12728 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12732 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12734 setvar(*ap, stackblock(), 0);
12743 #if defined(CONFIG_ASH_READ_NCHARS)
12744 if (nch_flag || silent)
12745 tcsetattr(0, TCSANOW, &old_tty);
12749 /* Remove trailing blanks */
12750 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12752 setvar(*ap, stackblock(), 0);
12753 while (*++ap != NULL)
12754 setvar(*ap, nullstr, 0);
12759 static int umaskcmd(int argc, char **argv)
12761 static const char permuser[3] = "ugo";
12762 static const char permmode[3] = "rwx";
12763 static const short int permmask[] = {
12764 S_IRUSR, S_IWUSR, S_IXUSR,
12765 S_IRGRP, S_IWGRP, S_IXGRP,
12766 S_IROTH, S_IWOTH, S_IXOTH
12772 int symbolic_mode = 0;
12774 while (nextopt("S") != '\0') {
12783 if ((ap = *argptr) == NULL) {
12784 if (symbolic_mode) {
12788 for (i = 0; i < 3; i++) {
12791 *p++ = permuser[i];
12793 for (j = 0; j < 3; j++) {
12794 if ((mask & permmask[3 * i + j]) == 0) {
12795 *p++ = permmode[j];
12803 out1fmt("%.4o\n", mask);
12806 if (is_digit((unsigned char) *ap)) {
12809 if (*ap >= '8' || *ap < '0')
12810 sh_error(illnum, argv[1]);
12811 mask = (mask << 3) + (*ap - '0');
12812 } while (*++ap != '\0');
12815 mask = ~mask & 0777;
12816 if (!bb_parse_mode(ap, &mask)) {
12817 sh_error("Illegal mode: %s", ap);
12819 umask(~mask & 0777);
12828 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12829 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12830 * ash by J.T. Conklin.
12838 int factor; /* multiply by to get rlim_{cur,max} values */
12842 static const struct limits limits[] = {
12844 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12846 #ifdef RLIMIT_FSIZE
12847 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12850 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12852 #ifdef RLIMIT_STACK
12853 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12856 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12859 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12861 #ifdef RLIMIT_MEMLOCK
12862 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12864 #ifdef RLIMIT_NPROC
12865 { "process", RLIMIT_NPROC, 1, 'p' },
12867 #ifdef RLIMIT_NOFILE
12868 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12871 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12873 #ifdef RLIMIT_LOCKS
12874 { "locks", RLIMIT_LOCKS, 1, 'w' },
12876 { (char *) 0, 0, 0, '\0' }
12879 enum limtype { SOFT = 0x1, HARD = 0x2 };
12881 static void printlim(enum limtype how, const struct rlimit *limit,
12882 const struct limits *l)
12886 val = limit->rlim_max;
12888 val = limit->rlim_cur;
12890 if (val == RLIM_INFINITY)
12891 out1fmt("unlimited\n");
12894 out1fmt("%lld\n", (long long) val);
12899 ulimitcmd(int argc, char **argv)
12903 enum limtype how = SOFT | HARD;
12904 const struct limits *l;
12907 struct rlimit limit;
12910 while ((optc = nextopt("HSa"
12914 #ifdef RLIMIT_FSIZE
12920 #ifdef RLIMIT_STACK
12929 #ifdef RLIMIT_MEMLOCK
12932 #ifdef RLIMIT_NPROC
12935 #ifdef RLIMIT_NOFILE
12941 #ifdef RLIMIT_LOCKS
12959 for (l = limits; l->option != what; l++)
12962 set = *argptr ? 1 : 0;
12966 if (all || argptr[1])
12967 sh_error("too many arguments");
12968 if (strncmp(p, "unlimited\n", 9) == 0)
12969 val = RLIM_INFINITY;
12973 while ((c = *p++) >= '0' && c <= '9')
12975 val = (val * 10) + (long)(c - '0');
12976 if (val < (rlim_t) 0)
12980 sh_error("bad number");
12985 for (l = limits; l->name; l++) {
12986 getrlimit(l->cmd, &limit);
12987 out1fmt("%-20s ", l->name);
12988 printlim(how, &limit, l);
12993 getrlimit(l->cmd, &limit);
12996 limit.rlim_max = val;
12998 limit.rlim_cur = val;
12999 if (setrlimit(l->cmd, &limit) < 0)
13000 sh_error("error setting limit (%m)");
13002 printlim(how, &limit, l);
13008 #ifdef CONFIG_ASH_MATH_SUPPORT
13010 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13012 Permission is hereby granted, free of charge, to any person obtaining
13013 a copy of this software and associated documentation files (the
13014 "Software"), to deal in the Software without restriction, including
13015 without limitation the rights to use, copy, modify, merge, publish,
13016 distribute, sublicense, and/or sell copies of the Software, and to
13017 permit persons to whom the Software is furnished to do so, subject to
13018 the following conditions:
13020 The above copyright notice and this permission notice shall be
13021 included in all copies or substantial portions of the Software.
13023 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13024 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13025 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13026 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13027 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13028 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13029 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13032 /* This is my infix parser/evaluator. It is optimized for size, intended
13033 * as a replacement for yacc-based parsers. However, it may well be faster
13034 * than a comparable parser written in yacc. The supported operators are
13035 * listed in #defines below. Parens, order of operations, and error handling
13036 * are supported. This code is thread safe. The exact expression format should
13037 * be that which POSIX specifies for shells. */
13039 /* The code uses a simple two-stack algorithm. See
13040 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13041 * for a detailed explanation of the infix-to-postfix algorithm on which
13042 * this is based (this code differs in that it applies operators immediately
13043 * to the stack instead of adding them to a queue to end up with an
13046 /* To use the routine, call it with an expression string and error return
13050 * Aug 24, 2001 Manuel Novoa III
13052 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13054 * 1) In arith_apply():
13055 * a) Cached values of *numptr and &(numptr[-1]).
13056 * b) Removed redundant test for zero denominator.
13059 * a) Eliminated redundant code for processing operator tokens by moving
13060 * to a table-based implementation. Also folded handling of parens
13062 * b) Combined all 3 loops which called arith_apply to reduce generated
13063 * code size at the cost of speed.
13065 * 3) The following expressions were treated as valid by the original code:
13066 * 1() , 0! , 1 ( *3 ) .
13067 * These bugs have been fixed by internally enclosing the expression in
13068 * parens and then checking that all binary ops and right parens are
13069 * preceded by a valid expression (NUM_TOKEN).
13071 * Note: It may be desirable to replace Aaron's test for whitespace with
13072 * ctype's isspace() if it is used by another busybox applet or if additional
13073 * whitespace chars should be considered. Look below the "#include"s for a
13074 * precompiler test.
13078 * Aug 26, 2001 Manuel Novoa III
13080 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13082 * Merge in Aaron's comments previously posted to the busybox list,
13083 * modified slightly to take account of my changes to the code.
13088 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13090 * - allow access to variable,
13091 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13092 * - realize assign syntax (VAR=expr, +=, *= etc)
13093 * - realize exponentiation (** operator)
13094 * - realize comma separated - expr, expr
13095 * - realise ++expr --expr expr++ expr--
13096 * - realise expr ? expr : expr (but, second expr calculate always)
13097 * - allow hexadecimal and octal numbers
13098 * - was restored loses XOR operator
13099 * - remove one goto label, added three ;-)
13100 * - protect $((num num)) as true zero expr (Manuel`s error)
13101 * - always use special isspace(), see comment from bash ;-)
13105 #define arith_isspace(arithval) \
13106 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13109 typedef unsigned char operator;
13111 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13112 * precedence, and 3 high bits are an ID unique across operators of that
13113 * precedence. The ID portion is so that multiple operators can have the
13114 * same precedence, ensuring that the leftmost one is evaluated first.
13115 * Consider * and /. */
13117 #define tok_decl(prec,id) (((id)<<5)|(prec))
13118 #define PREC(op) ((op) & 0x1F)
13120 #define TOK_LPAREN tok_decl(0,0)
13122 #define TOK_COMMA tok_decl(1,0)
13124 #define TOK_ASSIGN tok_decl(2,0)
13125 #define TOK_AND_ASSIGN tok_decl(2,1)
13126 #define TOK_OR_ASSIGN tok_decl(2,2)
13127 #define TOK_XOR_ASSIGN tok_decl(2,3)
13128 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13129 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13130 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13131 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13133 #define TOK_MUL_ASSIGN tok_decl(3,0)
13134 #define TOK_DIV_ASSIGN tok_decl(3,1)
13135 #define TOK_REM_ASSIGN tok_decl(3,2)
13137 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13138 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13140 /* conditional is right associativity too */
13141 #define TOK_CONDITIONAL tok_decl(4,0)
13142 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13144 #define TOK_OR tok_decl(5,0)
13146 #define TOK_AND tok_decl(6,0)
13148 #define TOK_BOR tok_decl(7,0)
13150 #define TOK_BXOR tok_decl(8,0)
13152 #define TOK_BAND tok_decl(9,0)
13154 #define TOK_EQ tok_decl(10,0)
13155 #define TOK_NE tok_decl(10,1)
13157 #define TOK_LT tok_decl(11,0)
13158 #define TOK_GT tok_decl(11,1)
13159 #define TOK_GE tok_decl(11,2)
13160 #define TOK_LE tok_decl(11,3)
13162 #define TOK_LSHIFT tok_decl(12,0)
13163 #define TOK_RSHIFT tok_decl(12,1)
13165 #define TOK_ADD tok_decl(13,0)
13166 #define TOK_SUB tok_decl(13,1)
13168 #define TOK_MUL tok_decl(14,0)
13169 #define TOK_DIV tok_decl(14,1)
13170 #define TOK_REM tok_decl(14,2)
13172 /* exponent is right associativity */
13173 #define TOK_EXPONENT tok_decl(15,1)
13175 /* For now unary operators. */
13176 #define UNARYPREC 16
13177 #define TOK_BNOT tok_decl(UNARYPREC,0)
13178 #define TOK_NOT tok_decl(UNARYPREC,1)
13180 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13181 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13183 #define PREC_PRE (UNARYPREC+2)
13185 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13186 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13188 #define PREC_POST (UNARYPREC+3)
13190 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13191 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13193 #define SPEC_PREC (UNARYPREC+4)
13195 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13196 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13198 #define NUMPTR (*numstackptr)
13200 static int tok_have_assign(operator op)
13202 operator prec = PREC(op);
13204 convert_prec_is_assing(prec);
13205 return (prec == PREC(TOK_ASSIGN) ||
13206 prec == PREC_PRE || prec == PREC_POST);
13209 static int is_right_associativity(operator prec)
13211 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13212 prec == PREC(TOK_CONDITIONAL));
13216 typedef struct ARITCH_VAR_NUM {
13218 arith_t contidional_second_val;
13219 char contidional_second_val_initialized;
13220 char *var; /* if NULL then is regular number,
13221 else is variable name */
13225 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13227 struct CHK_VAR_RECURSIVE_LOOPED *next;
13228 } chk_var_recursive_looped_t;
13230 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13233 static int arith_lookup_val(v_n_t *t)
13236 const char * p = lookupvar(t->var);
13241 /* recursive try as expression */
13242 chk_var_recursive_looped_t *cur;
13243 chk_var_recursive_looped_t cur_save;
13245 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13246 if(strcmp(cur->var, t->var) == 0) {
13247 /* expression recursion loop detected */
13251 /* save current lookuped var name */
13252 cur = prev_chk_var_recursive;
13253 cur_save.var = t->var;
13254 cur_save.next = cur;
13255 prev_chk_var_recursive = &cur_save;
13257 t->val = arith (p, &errcode);
13258 /* restore previous ptr after recursiving */
13259 prev_chk_var_recursive = cur;
13262 /* allow undefined var as 0 */
13269 /* "applying" a token means performing it on the top elements on the integer
13270 * stack. For a unary operator it will only change the top element, but a
13271 * binary operator will pop two arguments and push a result */
13272 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13275 arith_t numptr_val, rez;
13276 int ret_arith_lookup_val;
13278 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13279 without arguments */
13280 numptr_m1 = NUMPTR - 1;
13282 /* check operand is var with noninteger value */
13283 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13284 if(ret_arith_lookup_val)
13285 return ret_arith_lookup_val;
13287 rez = numptr_m1->val;
13288 if (op == TOK_UMINUS)
13290 else if (op == TOK_NOT)
13292 else if (op == TOK_BNOT)
13294 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13296 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13298 else if (op != TOK_UPLUS) {
13299 /* Binary operators */
13301 /* check and binary operators need two arguments */
13302 if (numptr_m1 == numstack) goto err;
13304 /* ... and they pop one */
13307 if (op == TOK_CONDITIONAL) {
13308 if(! numptr_m1->contidional_second_val_initialized) {
13309 /* protect $((expr1 ? expr2)) without ": expr" */
13312 rez = numptr_m1->contidional_second_val;
13313 } else if(numptr_m1->contidional_second_val_initialized) {
13314 /* protect $((expr1 : expr2)) without "expr ? " */
13317 numptr_m1 = NUMPTR - 1;
13318 if(op != TOK_ASSIGN) {
13319 /* check operand is var with noninteger value for not '=' */
13320 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13321 if(ret_arith_lookup_val)
13322 return ret_arith_lookup_val;
13324 if (op == TOK_CONDITIONAL) {
13325 numptr_m1->contidional_second_val = rez;
13327 rez = numptr_m1->val;
13328 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13330 else if (op == TOK_OR)
13331 rez = numptr_val || rez;
13332 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13334 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13336 else if (op == TOK_AND)
13337 rez = rez && numptr_val;
13338 else if (op == TOK_EQ)
13339 rez = (rez == numptr_val);
13340 else if (op == TOK_NE)
13341 rez = (rez != numptr_val);
13342 else if (op == TOK_GE)
13343 rez = (rez >= numptr_val);
13344 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13345 rez >>= numptr_val;
13346 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13347 rez <<= numptr_val;
13348 else if (op == TOK_GT)
13349 rez = (rez > numptr_val);
13350 else if (op == TOK_LT)
13351 rez = (rez < numptr_val);
13352 else if (op == TOK_LE)
13353 rez = (rez <= numptr_val);
13354 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13356 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13358 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13360 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13362 else if (op == TOK_CONDITIONAL_SEP) {
13363 if (numptr_m1 == numstack) {
13364 /* protect $((expr : expr)) without "expr ? " */
13367 numptr_m1->contidional_second_val_initialized = op;
13368 numptr_m1->contidional_second_val = numptr_val;
13370 else if (op == TOK_CONDITIONAL) {
13372 numptr_val : numptr_m1->contidional_second_val;
13374 else if(op == TOK_EXPONENT) {
13376 return -3; /* exponent less than 0 */
13381 while(numptr_val--)
13386 else if(numptr_val==0) /* zero divisor check */
13388 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13390 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13393 if(tok_have_assign(op)) {
13396 if(numptr_m1->var == NULL) {
13400 /* save to shell variable */
13401 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13402 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13404 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13406 setvar(numptr_m1->var, buf, 0);
13407 /* after saving, make previous value for v++ or v-- */
13408 if(op == TOK_POST_INC)
13410 else if(op == TOK_POST_DEC)
13413 numptr_m1->val = rez;
13414 /* protect geting var value, is number now */
13415 numptr_m1->var = NULL;
13421 /* longest must first */
13422 static const char op_tokens[] = {
13423 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13424 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13425 '<','<', 0, TOK_LSHIFT,
13426 '>','>', 0, TOK_RSHIFT,
13427 '|','|', 0, TOK_OR,
13428 '&','&', 0, TOK_AND,
13429 '!','=', 0, TOK_NE,
13430 '<','=', 0, TOK_LE,
13431 '>','=', 0, TOK_GE,
13432 '=','=', 0, TOK_EQ,
13433 '|','=', 0, TOK_OR_ASSIGN,
13434 '&','=', 0, TOK_AND_ASSIGN,
13435 '*','=', 0, TOK_MUL_ASSIGN,
13436 '/','=', 0, TOK_DIV_ASSIGN,
13437 '%','=', 0, TOK_REM_ASSIGN,
13438 '+','=', 0, TOK_PLUS_ASSIGN,
13439 '-','=', 0, TOK_MINUS_ASSIGN,
13440 '-','-', 0, TOK_POST_DEC,
13441 '^','=', 0, TOK_XOR_ASSIGN,
13442 '+','+', 0, TOK_POST_INC,
13443 '*','*', 0, TOK_EXPONENT,
13447 '=', 0, TOK_ASSIGN,
13459 '?', 0, TOK_CONDITIONAL,
13460 ':', 0, TOK_CONDITIONAL_SEP,
13461 ')', 0, TOK_RPAREN,
13462 '(', 0, TOK_LPAREN,
13466 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13469 static arith_t arith (const char *expr, int *perrcode)
13471 char arithval; /* Current character under analysis */
13472 operator lasttok, op;
13475 const char *p = endexpression;
13478 size_t datasizes = strlen(expr) + 2;
13480 /* Stack of integers */
13481 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13482 * in any given correct or incorrect expression is left as an exercise to
13484 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13485 *numstackptr = numstack;
13486 /* Stack of operator tokens */
13487 operator *stack = alloca((datasizes) * sizeof(operator)),
13490 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13491 *perrcode = errcode = 0;
13494 if ((arithval = *expr) == 0) {
13495 if (p == endexpression) {
13496 /* Null expression. */
13500 /* This is only reached after all tokens have been extracted from the
13501 * input stream. If there are still tokens on the operator stack, they
13502 * are to be applied in order. At the end, there should be a final
13503 * result on the integer stack */
13505 if (expr != endexpression + 1) {
13506 /* If we haven't done so already, */
13507 /* append a closing right paren */
13508 expr = endexpression;
13509 /* and let the loop process it. */
13512 /* At this point, we're done with the expression. */
13513 if (numstackptr != numstack+1) {
13514 /* ... but if there isn't, it's bad */
13516 return (*perrcode = -1);
13518 if(numstack->var) {
13519 /* expression is $((var)) only, lookup now */
13520 errcode = arith_lookup_val(numstack);
13523 *perrcode = errcode;
13524 return numstack->val;
13526 /* Continue processing the expression. */
13527 if (arith_isspace(arithval)) {
13528 /* Skip whitespace */
13531 if((p = endofname(expr)) != expr) {
13532 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13534 numstackptr->var = alloca(var_name_size);
13535 safe_strncpy(numstackptr->var, expr, var_name_size);
13538 numstackptr->contidional_second_val_initialized = 0;
13542 } else if (is_digit(arithval)) {
13543 numstackptr->var = NULL;
13544 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13545 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13547 numstackptr->val = strtol(expr, (char **) &expr, 0);
13551 for(p = op_tokens; ; p++) {
13555 /* strange operator not found */
13558 for(o = expr; *p && *o == *p; p++)
13565 /* skip tail uncompared token */
13568 /* skip zero delim */
13573 /* post grammar: a++ reduce to num */
13574 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13577 /* Plus and minus are binary (not unary) _only_ if the last
13578 * token was as number, or a right paren (which pretends to be
13579 * a number, since it evaluates to one). Think about it.
13580 * It makes sense. */
13581 if (lasttok != TOK_NUM) {
13597 /* We don't want a unary operator to cause recursive descent on the
13598 * stack, because there can be many in a row and it could cause an
13599 * operator to be evaluated before its argument is pushed onto the
13600 * integer stack. */
13601 /* But for binary operators, "apply" everything on the operator
13602 * stack until we find an operator with a lesser priority than the
13603 * one we have just extracted. */
13604 /* Left paren is given the lowest priority so it will never be
13605 * "applied" in this way.
13606 * if associativity is right and priority eq, applied also skip
13609 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13610 /* not left paren or unary */
13611 if (lasttok != TOK_NUM) {
13612 /* binary op must be preceded by a num */
13615 while (stackptr != stack) {
13616 if (op == TOK_RPAREN) {
13617 /* The algorithm employed here is simple: while we don't
13618 * hit an open paren nor the bottom of the stack, pop
13619 * tokens and apply them */
13620 if (stackptr[-1] == TOK_LPAREN) {
13622 /* Any operator directly after a */
13624 /* close paren should consider itself binary */
13628 operator prev_prec = PREC(stackptr[-1]);
13630 convert_prec_is_assing(prec);
13631 convert_prec_is_assing(prev_prec);
13632 if (prev_prec < prec)
13634 /* check right assoc */
13635 if(prev_prec == prec && is_right_associativity(prec))
13638 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13639 if(errcode) goto ret;
13641 if (op == TOK_RPAREN) {
13646 /* Push this operator to the stack and remember it. */
13647 *stackptr++ = lasttok = op;
13654 #endif /* CONFIG_ASH_MATH_SUPPORT */
13658 const char *applet_name = "debug stuff usage";
13659 int main(int argc, char **argv)
13661 return ash_main(argc, argv);
13666 * Copyright (c) 1989, 1991, 1993, 1994
13667 * The Regents of the University of California. All rights reserved.
13669 * This code is derived from software contributed to Berkeley by
13670 * Kenneth Almquist.
13672 * Redistribution and use in source and binary forms, with or without
13673 * modification, are permitted provided that the following conditions
13675 * 1. Redistributions of source code must retain the above copyright
13676 * notice, this list of conditions and the following disclaimer.
13677 * 2. Redistributions in binary form must reproduce the above copyright
13678 * notice, this list of conditions and the following disclaimer in the
13679 * documentation and/or other materials provided with the distribution.
13680 * 3. Neither the name of the University nor the names of its contributors
13681 * may be used to endorse or promote products derived from this software
13682 * without specific prior written permission.
13684 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13685 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13686 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13687 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13688 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13689 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13690 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13691 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13692 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13693 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF