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(builtincmd[0]))
1391 const struct builtincmd *cmd;
1392 struct funcnode *func;
1397 /* action to find_command() */
1398 #define DO_ERR 0x01 /* prints errors */
1399 #define DO_ABS 0x02 /* checks absolute paths */
1400 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1401 #define DO_ALTPATH 0x08 /* using alternate path */
1402 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1404 static const char *pathopt; /* set by padvance */
1406 static void shellexec(char **, const char *, int)
1408 static char *padvance(const char **, const char *);
1409 static void find_command(char *, struct cmdentry *, int, const char *);
1410 static struct builtincmd *find_builtin(const char *);
1411 static void hashcd(void);
1412 static void changepath(const char *);
1413 static void defun(char *, union node *);
1414 static void unsetfunc(const char *);
1416 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1417 typedef int64_t arith_t;
1418 #define arith_t_type (long long)
1420 typedef long arith_t;
1421 #define arith_t_type (long)
1424 #ifdef CONFIG_ASH_MATH_SUPPORT
1425 static arith_t dash_arith(const char *);
1426 static arith_t arith(const char *expr, int *perrcode);
1429 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1430 static unsigned long rseed;
1431 static void change_random(const char *);
1432 # ifndef DYNAMIC_VAR
1433 # define DYNAMIC_VAR
1439 static void reset(void);
1448 #define VEXPORT 0x01 /* variable is exported */
1449 #define VREADONLY 0x02 /* variable cannot be modified */
1450 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1451 #define VTEXTFIXED 0x08 /* text is statically allocated */
1452 #define VSTACK 0x10 /* text is allocated on the stack */
1453 #define VUNSET 0x20 /* the variable is not set */
1454 #define VNOFUNC 0x40 /* don't call the callback function */
1455 #define VNOSET 0x80 /* do not set variable - just readonly test */
1456 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1458 # define VDYNAMIC 0x200 /* dynamic variable */
1464 struct var *next; /* next entry in hash list */
1465 int flags; /* flags are defined above */
1466 const char *text; /* name=value */
1467 void (*func)(const char *); /* function to be called when */
1468 /* the variable gets set/unset */
1472 struct localvar *next; /* next local variable in list */
1473 struct var *vp; /* the variable that was made local */
1474 int flags; /* saved flags */
1475 const char *text; /* saved text */
1479 static struct localvar *localvars;
1485 #ifdef CONFIG_ASH_GETOPTS
1486 static void getoptsreset(const char *);
1489 #ifdef CONFIG_LOCALE_SUPPORT
1490 static void change_lc_all(const char *value);
1491 static void change_lc_ctype(const char *value);
1497 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1499 static const char defifsvar[] = "IFS= \t\n";
1500 #define defifs (defifsvar + 4)
1502 static const char defifs[] = " \t\n";
1506 static struct var varinit[] = {
1508 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1510 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1513 #ifdef CONFIG_ASH_MAIL
1514 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1515 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1518 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1519 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1520 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1521 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1522 #ifdef CONFIG_ASH_GETOPTS
1523 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1525 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1526 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1528 #ifdef CONFIG_LOCALE_SUPPORT
1529 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1530 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1532 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1533 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1537 #define vifs varinit[0]
1538 #ifdef CONFIG_ASH_MAIL
1539 #define vmail (&vifs)[1]
1540 #define vmpath (&vmail)[1]
1544 #define vpath (&vmpath)[1]
1545 #define vps1 (&vpath)[1]
1546 #define vps2 (&vps1)[1]
1547 #define vps4 (&vps2)[1]
1548 #define voptind (&vps4)[1]
1549 #ifdef CONFIG_ASH_GETOPTS
1550 #define vrandom (&voptind)[1]
1552 #define vrandom (&vps4)[1]
1554 #define defpath (defpathvar + 5)
1557 * The following macros access the values of the above variables.
1558 * They have to skip over the name. They return the null string
1559 * for unset variables.
1562 #define ifsval() (vifs.text + 4)
1563 #define ifsset() ((vifs.flags & VUNSET) == 0)
1564 #define mailval() (vmail.text + 5)
1565 #define mpathval() (vmpath.text + 9)
1566 #define pathval() (vpath.text + 5)
1567 #define ps1val() (vps1.text + 4)
1568 #define ps2val() (vps2.text + 4)
1569 #define ps4val() (vps4.text + 4)
1570 #define optindval() (voptind.text + 7)
1572 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1574 static void setvar(const char *, const char *, int);
1575 static void setvareq(char *, int);
1576 static void listsetvar(struct strlist *, int);
1577 static char *lookupvar(const char *);
1578 static char *bltinlookup(const char *);
1579 static char **listvars(int, int, char ***);
1580 #define environment() listvars(VEXPORT, VUNSET, 0)
1581 static int showvars(const char *, int, int);
1582 static void poplocalvars(void);
1583 static int unsetvar(const char *);
1584 #ifdef CONFIG_ASH_GETOPTS
1585 static int setvarsafe(const char *, const char *, int);
1587 static int varcmp(const char *, const char *);
1588 static struct var **hashvar(const char *);
1591 static int varequal(const char *a, const char *b) {
1592 return !varcmp(a, b);
1596 static int loopnest; /* current loop nesting level */
1599 * The parsefile structure pointed to by the global variable parsefile
1600 * contains information about the current file being read.
1605 struct redirtab *next;
1610 static struct redirtab *redirlist;
1611 static int nullredirs;
1613 extern char **environ;
1618 static void outstr(const char *, FILE *);
1619 static void outcslow(int, FILE *);
1620 static void flushall(void);
1621 static void flusherr(void);
1622 static int out1fmt(const char *, ...)
1623 __attribute__((__format__(__printf__,1,2)));
1624 static int fmtstr(char *, size_t, const char *, ...)
1625 __attribute__((__format__(__printf__,3,4)));
1627 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1630 static void out1str(const char *p)
1635 static void out2str(const char *p)
1642 * Initialization code.
1646 * This routine initializes the builtin variables.
1649 static void initvar(void)
1656 * PS1 depends on uid
1658 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1659 vps1.text = "PS1=\\w \\$ ";
1662 vps1.text = "PS1=# ";
1665 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1667 vpp = hashvar(vp->text);
1670 } while (++vp < end);
1673 static void init(void)
1678 basepf.nextc = basepf.buf = basebuf;
1683 signal(SIGCHLD, SIG_DFL);
1691 struct stat st1, st2;
1694 for (envp = environ ; envp && *envp ; envp++) {
1695 if (strchr(*envp, '=')) {
1696 setvareq(*envp, VEXPORT|VTEXTFIXED);
1700 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1701 setvar("PPID", ppid, 0);
1703 p = lookupvar("PWD");
1705 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1706 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1712 /* PEOF (the end of file marker) */
1715 INPUT_PUSH_FILE = 1,
1716 INPUT_NOFILE_OK = 2,
1720 * The input line number. Input.c just defines this variable, and saves
1721 * and restores it when files are pushed and popped. The user of this
1722 * package must set its value.
1725 static int pgetc(void);
1726 static int pgetc2(void);
1727 static int preadbuffer(void);
1728 static void pungetc(void);
1729 static void pushstring(char *, void *);
1730 static void popstring(void);
1731 static void setinputfd(int, int);
1732 static void setinputstring(char *);
1733 static void popfile(void);
1734 static void popallfiles(void);
1735 static void closescript(void);
1741 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1744 #define FORK_NOJOB 2
1746 /* mode flags for showjob(s) */
1747 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1748 #define SHOW_PID 0x04 /* include process pid */
1749 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1753 * A job structure contains information about a job. A job is either a
1754 * single process or a set of processes contained in a pipeline. In the
1755 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1760 pid_t pid; /* process id */
1761 int status; /* last process status from wait() */
1762 char *cmd; /* text of command being run */
1766 struct procstat ps0; /* status of process */
1767 struct procstat *ps; /* status or processes when more than one */
1769 int stopstatus; /* status of a stopped job */
1772 nprocs: 16, /* number of processes */
1774 #define JOBRUNNING 0 /* at least one proc running */
1775 #define JOBSTOPPED 1 /* all procs are stopped */
1776 #define JOBDONE 2 /* all procs are completed */
1778 sigint: 1, /* job was killed by SIGINT */
1779 jobctl: 1, /* job running under job control */
1781 waited: 1, /* true if this entry has been waited for */
1782 used: 1, /* true if this entry is in used */
1783 changed: 1; /* true if status has changed */
1784 struct job *prev_job; /* previous job */
1787 static pid_t backgndpid; /* pid of last background process */
1788 static int job_warning; /* user was warned about stopped jobs */
1790 static int jobctl; /* true if doing job control */
1793 static struct job *makejob(union node *, int);
1794 static int forkshell(struct job *, union node *, int);
1795 static int waitforjob(struct job *);
1796 static int stoppedjobs(void);
1799 #define setjobctl(on) /* do nothing */
1801 static void setjobctl(int);
1802 static void showjobs(FILE *, int);
1808 /* pid of main shell */
1810 /* shell level: 0 for the main shell, 1 for its children, and so on */
1812 #define rootshell (!shlvl)
1814 static void readcmdfile(char *);
1815 static int cmdloop(int);
1821 struct stack_block *stackp;
1824 struct stackmark *marknext;
1827 /* minimum size of a block */
1828 #define MINSIZE SHELL_ALIGN(504)
1830 struct stack_block {
1831 struct stack_block *prev;
1832 char space[MINSIZE];
1835 static struct stack_block stackbase;
1836 static struct stack_block *stackp = &stackbase;
1837 static struct stackmark *markp;
1838 static char *stacknxt = stackbase.space;
1839 static size_t stacknleft = MINSIZE;
1840 static char *sstrend = stackbase.space + MINSIZE;
1841 static int herefd = -1;
1844 static pointer ckmalloc(size_t);
1845 static pointer ckrealloc(pointer, size_t);
1846 static char *savestr(const char *);
1847 static pointer stalloc(size_t);
1848 static void stunalloc(pointer);
1849 static void setstackmark(struct stackmark *);
1850 static void popstackmark(struct stackmark *);
1851 static void growstackblock(void);
1852 static void *growstackstr(void);
1853 static char *makestrspace(size_t, char *);
1854 static char *stnputs(const char *, size_t, char *);
1855 static char *stputs(const char *, char *);
1858 static char *_STPUTC(int c, char *p) {
1865 #define stackblock() ((void *)stacknxt)
1866 #define stackblocksize() stacknleft
1867 #define STARTSTACKSTR(p) ((p) = stackblock())
1868 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1869 #define CHECKSTRSPACE(n, p) \
1873 size_t m = sstrend - q; \
1875 (p) = makestrspace(l, q); \
1878 #define USTPUTC(c, p) (*p++ = (c))
1879 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1880 #define STUNPUTC(p) (--p)
1881 #define STTOPC(p) p[-1]
1882 #define STADJUST(amount, p) (p += (amount))
1884 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1885 #define ungrabstackstr(s, p) stunalloc((s))
1886 #define stackstrend() ((void *)sstrend)
1888 #define ckfree(p) free((pointer)(p))
1893 #define DOLATSTRLEN 4
1895 static char *prefix(const char *, const char *);
1896 static int number(const char *);
1897 static int is_number(const char *);
1898 static char *single_quote(const char *);
1899 static char *sstrdup(const char *);
1901 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1902 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1907 int nparam; /* # of positional parameters (without $0) */
1908 unsigned char malloc; /* if parameter list dynamically allocated */
1909 char **p; /* parameter list */
1910 #ifdef CONFIG_ASH_GETOPTS
1911 int optind; /* next parameter to be processed by getopts */
1912 int optoff; /* used by getopts */
1917 #define eflag optlist[0]
1918 #define fflag optlist[1]
1919 #define Iflag optlist[2]
1920 #define iflag optlist[3]
1921 #define mflag optlist[4]
1922 #define nflag optlist[5]
1923 #define sflag optlist[6]
1924 #define xflag optlist[7]
1925 #define vflag optlist[8]
1926 #define Cflag optlist[9]
1927 #define aflag optlist[10]
1928 #define bflag optlist[11]
1929 #define uflag optlist[12]
1930 #define viflag optlist[13]
1933 #define nolog optlist[14]
1934 #define debug optlist[15]
1937 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1938 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1944 static const char *const optletters_optnames[] = {
1965 #define optletters(n) optletters_optnames[(n)][0]
1966 #define optnames(n) (&optletters_optnames[(n)][1])
1968 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1970 static char optlist[NOPTS];
1973 static char *arg0; /* value of $0 */
1974 static struct shparam shellparam; /* $@ current positional parameters */
1975 static char **argptr; /* argument list for builtin commands */
1976 static char *optionarg; /* set by nextopt (like getopt) */
1977 static char *optptr; /* used by nextopt */
1979 static char *minusc; /* argument to -c option */
1982 static void procargs(int, char **);
1983 static void optschanged(void);
1984 static void setparam(char **);
1985 static void freeparam(volatile struct shparam *);
1986 static int shiftcmd(int, char **);
1987 static int setcmd(int, char **);
1988 static int nextopt(const char *);
1992 /* flags passed to redirect */
1993 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1994 #define REDIR_SAVEFD2 03 /* set preverrout */
1997 static void redirect(union node *, int);
1998 static void popredir(int);
1999 static void clearredir(int);
2000 static int copyfd(int, int);
2001 static int redirectsafe(union node *, int);
2007 static void showtree(union node *);
2008 static void trace(const char *, ...);
2009 static void tracev(const char *, va_list);
2010 static void trargs(char **);
2011 static void trputc(int);
2012 static void trputs(const char *);
2013 static void opentrace(void);
2019 /* trap handler commands */
2020 static char *trap[NSIG];
2021 /* current value of signal */
2022 static char sigmode[NSIG - 1];
2023 /* indicates specified signal received */
2024 static char gotsig[NSIG - 1];
2026 static void clear_traps(void);
2027 static void setsignal(int);
2028 static void ignoresig(int);
2029 static void onsig(int);
2030 static int dotrap(void);
2031 static void setinteractive(int);
2032 static void exitshell(void) ATTRIBUTE_NORETURN;
2035 static int is_safe_applet(char *name)
2037 /* It isn't a bug to have non-existent applet here... */
2038 /* ...just a waste of space... */
2039 static const char safe_applets[][8] = {
2043 USE_CHMOD (, "chmod" )
2044 USE_CHOWN (, "chown" )
2048 USE_ECHO (, "echo" )
2049 USE_FIND (, "find" )
2050 USE_HEXDUMP(, "hexdump")
2053 USE_MKDIR (, "mkdir" )
2055 USE_SORT (, "sort" )
2056 USE_TEST (, "test" )
2057 USE_TOUCH (, "touch" )
2058 USE_XARGS (, "xargs" )
2060 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
2062 for (i = 0; i < n; i++)
2063 if (strcmp(safe_applets[i], name) == 0)
2071 * This routine is called when an error or an interrupt occurs in an
2072 * interactive shell and control is returned to the main command loop.
2086 parselleft = parsenleft = 0; /* clear input buffer */
2090 /* from parser.c: */
2103 #ifdef CONFIG_ASH_ALIAS
2104 static struct alias *atab[ATABSIZE];
2106 static void setalias(const char *, const char *);
2107 static struct alias *freealias(struct alias *);
2108 static struct alias **__lookupalias(const char *);
2111 setalias(const char *name, const char *val)
2113 struct alias *ap, **app;
2115 app = __lookupalias(name);
2119 if (!(ap->flag & ALIASINUSE)) {
2122 ap->val = savestr(val);
2123 ap->flag &= ~ALIASDEAD;
2126 ap = ckmalloc(sizeof (struct alias));
2127 ap->name = savestr(name);
2128 ap->val = savestr(val);
2137 unalias(const char *name)
2141 app = __lookupalias(name);
2145 *app = freealias(*app);
2156 struct alias *ap, **app;
2160 for (i = 0; i < ATABSIZE; i++) {
2162 for (ap = *app; ap; ap = *app) {
2163 *app = freealias(*app);
2172 static struct alias *
2173 lookupalias(const char *name, int check)
2175 struct alias *ap = *__lookupalias(name);
2177 if (check && ap && (ap->flag & ALIASINUSE))
2183 * TODO - sort output
2186 aliascmd(int argc, char **argv)
2195 for (i = 0; i < ATABSIZE; i++)
2196 for (ap = atab[i]; ap; ap = ap->next) {
2201 while ((n = *++argv) != NULL) {
2202 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2203 if ((ap = *__lookupalias(n)) == NULL) {
2204 fprintf(stderr, "%s: %s not found\n", "alias", n);
2218 unaliascmd(int argc, char **argv)
2222 while ((i = nextopt("a")) != '\0') {
2228 for (i = 0; *argptr; argptr++) {
2229 if (unalias(*argptr)) {
2230 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2238 static struct alias *
2239 freealias(struct alias *ap) {
2242 if (ap->flag & ALIASINUSE) {
2243 ap->flag |= ALIASDEAD;
2255 printalias(const struct alias *ap) {
2256 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2259 static struct alias **
2260 __lookupalias(const char *name) {
2261 unsigned int hashval;
2268 ch = (unsigned char)*p;
2272 ch = (unsigned char)*++p;
2274 app = &atab[hashval % ATABSIZE];
2276 for (; *app; app = &(*app)->next) {
2277 if (equal(name, (*app)->name)) {
2284 #endif /* CONFIG_ASH_ALIAS */
2290 * The cd and pwd commands.
2293 #define CD_PHYSICAL 1
2296 static int docd(const char *, int);
2297 static int cdopt(void);
2299 static char *curdir = nullstr; /* current working directory */
2300 static char *physdir = nullstr; /* physical working directory */
2309 while ((i = nextopt("LP"))) {
2311 flags ^= CD_PHYSICAL;
2320 cdcmd(int argc, char **argv)
2332 dest = bltinlookup(homestr);
2333 else if (LONE_DASH(dest)) {
2334 dest = bltinlookup("OLDPWD");
2356 if (!(path = bltinlookup("CDPATH"))) {
2364 p = padvance(&path, dest);
2365 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2369 if (!docd(p, flags))
2374 sh_error("can't cd to %s", dest);
2377 if (flags & CD_PRINT)
2378 out1fmt(snlfmt, curdir);
2384 * Update curdir (the name of the current directory) in response to a
2388 static const char * updatepwd(const char *dir)
2395 cdcomppath = sstrdup(dir);
2398 if (curdir == nullstr)
2400 new = stputs(curdir, new);
2402 new = makestrspace(strlen(dir) + 2, new);
2403 lim = stackblock() + 1;
2407 if (new > lim && *lim == '/')
2412 if (dir[1] == '/' && dir[2] != '/') {
2418 p = strtok(cdcomppath, "/");
2422 if (p[1] == '.' && p[2] == '\0') {
2429 } else if (p[1] == '\0')
2433 new = stputs(p, new);
2441 return stackblock();
2445 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2446 * know that the current directory has changed.
2450 docd(const char *dest, int flags)
2452 const char *dir = 0;
2455 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2458 if (!(flags & CD_PHYSICAL)) {
2459 dir = updatepwd(dest);
2474 * Find out what the current directory is. If we already know the current
2475 * directory, this routine returns immediately.
2477 static char * getpwd(void)
2479 char *dir = getcwd(0, 0);
2480 return dir ? dir : nullstr;
2484 pwdcmd(int argc, char **argv)
2487 const char *dir = curdir;
2491 if (physdir == nullstr)
2495 out1fmt(snlfmt, dir);
2500 setpwd(const char *val, int setold)
2504 oldcur = dir = curdir;
2507 setvar("OLDPWD", oldcur, VEXPORT);
2510 if (physdir != nullstr) {
2511 if (physdir != oldcur)
2515 if (oldcur == val || !val) {
2522 if (oldcur != dir && oldcur != nullstr) {
2527 setvar("PWD", dir, VEXPORT);
2533 * Errors and exceptions.
2537 * Code to handle exceptions in C.
2542 static void exverror(int, const char *, va_list)
2546 * Called to raise an exception. Since C doesn't include exceptions, we
2547 * just do a longjmp to the exception handler. The type of exception is
2548 * stored in the global variable "exception".
2555 if (handler == NULL)
2561 longjmp(handler->loc, 1);
2566 * Called from trap.c when a SIGINT is received. (If the user specifies
2567 * that SIGINT is to be trapped or ignored using the trap builtin, then
2568 * this routine is not called.) Suppressint is nonzero when interrupts
2569 * are held using the INTOFF macro. (The test for iflag is just
2570 * defensive programming.)
2579 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2580 if (!(rootshell && iflag)) {
2581 signal(SIGINT, SIG_DFL);
2591 exvwarning(const char *msg, va_list ap)
2596 fprintf(errs, "%s: ", arg0);
2598 const char *fmt = (!iflag || parsefile->fd) ?
2599 "%s: %d: " : "%s: ";
2600 fprintf(errs, fmt, commandname, startlinno);
2602 vfprintf(errs, msg, ap);
2603 outcslow('\n', errs);
2607 * Exverror is called to raise the error exception. If the second argument
2608 * is not NULL then error prints an error message using printf style
2609 * formatting. It then raises the error exception.
2612 exverror(int cond, const char *msg, va_list ap)
2616 TRACE(("exverror(%d, \"", cond));
2618 TRACE(("\") pid=%d\n", getpid()));
2620 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2623 exvwarning(msg, ap);
2632 sh_error(const char *msg, ...)
2637 exverror(EXERROR, msg, ap);
2644 exerror(int cond, const char *msg, ...)
2649 exverror(cond, msg, ap);
2655 * error/warning routines for external builtins
2659 sh_warnx(const char *fmt, ...)
2664 exvwarning(fmt, ap);
2670 * Return a string describing an error. The returned string may be a
2671 * pointer to a static buffer that will be overwritten on the next call.
2672 * Action describes the operation that got the error.
2676 errmsg(int e, const char *em)
2678 if(e == ENOENT || e == ENOTDIR) {
2689 * Evaluate a command.
2692 /* flags in argument to evaltree */
2693 #define EV_EXIT 01 /* exit after evaluating tree */
2694 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2695 #define EV_BACKCMD 04 /* command executing within back quotes */
2698 static void evalloop(union node *, int);
2699 static void evalfor(union node *, int);
2700 static void evalcase(union node *, int);
2701 static void evalsubshell(union node *, int);
2702 static void expredir(union node *);
2703 static void evalpipe(union node *, int);
2704 static void evalcommand(union node *, int);
2705 static int evalbltin(const struct builtincmd *, int, char **);
2706 static int evalfun(struct funcnode *, int, char **, int);
2707 static void prehash(union node *);
2708 static int bltincmd(int, char **);
2711 static const struct builtincmd bltin = {
2717 * Called to reset things after an exception.
2725 evalcmd(int argc, char **argv)
2734 STARTSTACKSTR(concat);
2737 concat = stputs(p, concat);
2738 if ((p = *ap++) == NULL)
2740 STPUTC(' ', concat);
2742 STPUTC('\0', concat);
2743 p = grabstackstr(concat);
2745 evalstring(p, ~SKIPEVAL);
2753 * Execute a command or commands contained in a string.
2757 evalstring(char *s, int mask)
2760 struct stackmark smark;
2764 setstackmark(&smark);
2767 while ((n = parsecmd(0)) != NEOF) {
2769 popstackmark(&smark);
2784 * Evaluate a parse tree. The value is left in the global variable
2789 evaltree(union node *n, int flags)
2792 void (*evalfn)(union node *, int);
2796 TRACE(("evaltree(NULL) called\n"));
2799 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2800 getpid(), n, n->type, flags));
2804 out1fmt("Node type = %d\n", n->type);
2809 evaltree(n->nnot.com, EV_TESTED);
2810 status = !exitstatus;
2813 expredir(n->nredir.redirect);
2814 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2816 evaltree(n->nredir.n, flags & EV_TESTED);
2817 status = exitstatus;
2822 evalfn = evalcommand;
2824 if (eflag && !(flags & EV_TESTED))
2836 evalfn = evalsubshell;
2848 #error NAND + 1 != NOR
2850 #if NOR + 1 != NSEMI
2851 #error NOR + 1 != NSEMI
2853 isor = n->type - NAND;
2856 (flags | ((isor >> 1) - 1)) & EV_TESTED
2858 if (!exitstatus == isor)
2870 evaltree(n->nif.test, EV_TESTED);
2873 if (exitstatus == 0) {
2876 } else if (n->nif.elsepart) {
2877 n = n->nif.elsepart;
2882 defun(n->narg.text, n->narg.next);
2886 exitstatus = status;
2890 if ((checkexit & exitstatus))
2891 evalskip |= SKIPEVAL;
2892 else if (pendingsigs && dotrap())
2895 if (flags & EV_EXIT) {
2902 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2905 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2909 evalloop(union node *n, int flags)
2919 evaltree(n->nbinary.ch1, EV_TESTED);
2921 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2925 if (evalskip == SKIPBREAK && --skipcount <= 0)
2930 if (n->type != NWHILE)
2934 evaltree(n->nbinary.ch2, flags);
2935 status = exitstatus;
2940 exitstatus = status;
2946 evalfor(union node *n, int flags)
2948 struct arglist arglist;
2951 struct stackmark smark;
2953 setstackmark(&smark);
2954 arglist.lastp = &arglist.list;
2955 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2956 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2961 *arglist.lastp = NULL;
2966 for (sp = arglist.list ; sp ; sp = sp->next) {
2967 setvar(n->nfor.var, sp->text, 0);
2968 evaltree(n->nfor.body, flags);
2970 if (evalskip == SKIPCONT && --skipcount <= 0) {
2974 if (evalskip == SKIPBREAK && --skipcount <= 0)
2981 popstackmark(&smark);
2987 evalcase(union node *n, int flags)
2991 struct arglist arglist;
2992 struct stackmark smark;
2994 setstackmark(&smark);
2995 arglist.lastp = &arglist.list;
2996 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2998 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2999 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
3000 if (casematch(patp, arglist.list->text)) {
3001 if (evalskip == 0) {
3002 evaltree(cp->nclist.body, flags);
3009 popstackmark(&smark);
3015 * Kick off a subshell to evaluate a tree.
3019 evalsubshell(union node *n, int flags)
3022 int backgnd = (n->type == NBACKGND);
3025 expredir(n->nredir.redirect);
3026 if (!backgnd && flags & EV_EXIT && !trap[0])
3030 if (forkshell(jp, n, backgnd) == 0) {
3034 flags &=~ EV_TESTED;
3036 redirect(n->nredir.redirect, 0);
3037 evaltreenr(n->nredir.n, flags);
3042 status = waitforjob(jp);
3043 exitstatus = status;
3050 * Compute the names of the files in a redirection list.
3054 expredir(union node *n)
3058 for (redir = n ; redir ; redir = redir->nfile.next) {
3060 memset(&fn, 0, sizeof(struct arglist));
3061 fn.lastp = &fn.list;
3062 switch (redir->type) {
3068 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3069 redir->nfile.expfname = fn.list->text;
3073 if (redir->ndup.vname) {
3074 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3075 if (fn.list != NULL)
3076 fixredir(redir, fn.list->text, 1);
3078 sh_error("redir error");
3088 * Evaluate a pipeline. All the processes in the pipeline are children
3089 * of the process creating the pipeline. (This differs from some versions
3090 * of the shell, which make the last process in a pipeline the parent
3095 evalpipe(union node *n, int flags)
3098 struct nodelist *lp;
3103 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3105 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3109 jp = makejob(n, pipelen);
3111 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3115 if (pipe(pip) < 0) {
3117 sh_error("Pipe call failed");
3120 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3133 evaltreenr(lp->n, flags);
3141 if (n->npipe.backgnd == 0) {
3142 exitstatus = waitforjob(jp);
3143 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3151 * Execute a command inside back quotes. If it's a builtin command, we
3152 * want to save its output in a block obtained from malloc. Otherwise
3153 * we fork off a subprocess and get the output of the command via a pipe.
3154 * Should be called with interrupts off.
3158 evalbackcmd(union node *n, struct backcmd *result)
3170 saveherefd = herefd;
3178 sh_error("Pipe call failed");
3180 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3189 evaltreenr(n, EV_EXIT);
3193 result->fd = pip[0];
3196 herefd = saveherefd;
3198 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3199 result->fd, result->buf, result->nleft, result->jp));
3202 #ifdef CONFIG_ASH_CMDCMD
3203 static char ** parse_command_args(char **argv, const char **path)
3215 if (c == '-' && !*cp) {
3225 /* run 'typecmd' for other options */
3228 } while ((c = *cp++));
3234 static int isassignment(const char *p)
3236 const char *q = endofname(p);
3242 #ifdef CONFIG_ASH_EXPAND_PRMT
3243 static const char *expandstr(const char *ps);
3245 #define expandstr(s) s
3249 * Execute a simple command.
3253 evalcommand(union node *cmd, int flags)
3255 struct stackmark smark;
3257 struct arglist arglist;
3258 struct arglist varlist;
3261 const struct strlist *sp;
3262 struct cmdentry cmdentry;
3270 struct builtincmd *bcmd;
3271 int pseudovarflag = 0;
3273 /* First expand the arguments. */
3274 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3275 setstackmark(&smark);
3276 back_exitstatus = 0;
3278 cmdentry.cmdtype = CMDBUILTIN;
3279 cmdentry.u.cmd = &bltin;
3280 varlist.lastp = &varlist.list;
3281 *varlist.lastp = NULL;
3282 arglist.lastp = &arglist.list;
3283 *arglist.lastp = NULL;
3288 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3289 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3292 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3293 struct strlist **spp;
3295 spp = arglist.lastp;
3296 if (pseudovarflag && isassignment(argp->narg.text))
3297 expandarg(argp, &arglist, EXP_VARTILDE);
3299 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3301 for (sp = *spp; sp; sp = sp->next)
3305 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3306 for (sp = arglist.list ; sp ; sp = sp->next) {
3307 TRACE(("evalcommand arg: %s\n", sp->text));
3308 *nargv++ = sp->text;
3313 if (iflag && funcnest == 0 && argc > 0)
3314 lastarg = nargv[-1];
3317 expredir(cmd->ncmd.redirect);
3318 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3321 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3322 struct strlist **spp;
3325 spp = varlist.lastp;
3326 expandarg(argp, &varlist, EXP_VARTILDE);
3329 * Modify the command lookup path, if a PATH= assignment
3333 if (varequal(p, path))
3337 /* Print the command if xflag is set. */
3340 const char *p = " %s";
3343 dprintf(preverrout_fd, p, expandstr(ps4val()));
3346 for(n = 0; n < 2; n++) {
3348 dprintf(preverrout_fd, p, sp->text);
3356 full_write(preverrout_fd, "\n", 1);
3362 /* Now locate the command. */
3364 const char *oldpath;
3365 int cmd_flag = DO_ERR;
3370 find_command(argv[0], &cmdentry, cmd_flag, path);
3371 if (cmdentry.cmdtype == CMDUNKNOWN) {
3377 /* implement bltin and command here */
3378 if (cmdentry.cmdtype != CMDBUILTIN)
3381 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3382 if (cmdentry.u.cmd == EXECCMD)
3384 #ifdef CONFIG_ASH_CMDCMD
3385 if (cmdentry.u.cmd == COMMANDCMD) {
3388 nargv = parse_command_args(argv, &path);
3391 argc -= nargv - argv;
3393 cmd_flag |= DO_NOFUNC;
3401 /* We have a redirection error. */
3405 exitstatus = status;
3409 /* Execute the command. */
3410 switch (cmdentry.cmdtype) {
3412 /* Fork off a child process if necessary. */
3413 if (!(flags & EV_EXIT) || trap[0]) {
3415 jp = makejob(cmd, 1);
3416 if (forkshell(jp, cmd, FORK_FG) != 0) {
3417 exitstatus = waitforjob(jp);
3423 listsetvar(varlist.list, VEXPORT|VSTACK);
3424 shellexec(argv, path, cmdentry.u.index);
3428 cmdenviron = varlist.list;
3430 struct strlist *list = cmdenviron;
3432 if (spclbltin > 0 || argc == 0) {
3434 if (cmd_is_exec && argc > 1)
3437 listsetvar(list, i);
3439 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3454 exit_status = j + 128;
3455 exitstatus = exit_status;
3457 if (i == EXINT || spclbltin > 0) {
3459 longjmp(handler->loc, 1);
3466 listsetvar(varlist.list, 0);
3467 if (evalfun(cmdentry.u.func, argc, argv, flags))
3473 popredir(cmd_is_exec);
3475 /* dsl: I think this is intended to be used to support
3476 * '_' in 'vi' command mode during line editing...
3477 * However I implemented that within libedit itself.
3479 setvar("_", lastarg, 0);
3480 popstackmark(&smark);
3484 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3485 char *volatile savecmdname;
3486 struct jmploc *volatile savehandler;
3487 struct jmploc jmploc;
3490 savecmdname = commandname;
3491 if ((i = setjmp(jmploc.loc)))
3493 savehandler = handler;
3495 commandname = argv[0];
3497 optptr = NULL; /* initialize nextopt */
3498 exitstatus = (*cmd->builtin)(argc, argv);
3501 exitstatus |= ferror(stdout);
3503 commandname = savecmdname;
3505 handler = savehandler;
3511 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3513 volatile struct shparam saveparam;
3514 struct localvar *volatile savelocalvars;
3515 struct jmploc *volatile savehandler;
3516 struct jmploc jmploc;
3519 saveparam = shellparam;
3520 savelocalvars = localvars;
3521 if ((e = setjmp(jmploc.loc))) {
3525 savehandler = handler;
3528 shellparam.malloc = 0;
3532 shellparam.nparam = argc - 1;
3533 shellparam.p = argv + 1;
3534 #ifdef CONFIG_ASH_GETOPTS
3535 shellparam.optind = 1;
3536 shellparam.optoff = -1;
3538 evaltree(&func->n, flags & EV_TESTED);
3544 localvars = savelocalvars;
3545 freeparam(&shellparam);
3546 shellparam = saveparam;
3547 handler = savehandler;
3549 evalskip &= ~SKIPFUNC;
3554 static int goodname(const char *p)
3556 return !*endofname(p);
3560 * Search for a command. This is called before we fork so that the
3561 * location of the command will be available in the parent as well as
3562 * the child. The check for "goodname" is an overly conservative
3563 * check that the name will not be subject to expansion.
3567 prehash(union node *n)
3569 struct cmdentry entry;
3571 if (n->type == NCMD && n->ncmd.args)
3572 if (goodname(n->ncmd.args->narg.text))
3573 find_command(n->ncmd.args->narg.text, &entry, 0,
3580 * Builtin commands. Builtin commands whose functions are closely
3581 * tied to evaluation are implemented here.
3589 bltincmd(int argc, char **argv)
3592 * Preserve exitstatus of a previous possible redirection
3595 return back_exitstatus;
3600 * Handle break and continue commands. Break, continue, and return are
3601 * all handled by setting the evalskip flag. The evaluation routines
3602 * above all check this flag, and if it is set they start skipping
3603 * commands rather than executing them. The variable skipcount is
3604 * the number of loops to break/continue, or the number of function
3605 * levels to return. (The latter is always 1.) It should probably
3606 * be an error to break out of more loops than exist, but it isn't
3607 * in the standard shell so we don't make it one here.
3611 breakcmd(int argc, char **argv)
3613 int n = argc > 1 ? number(argv[1]) : 1;
3616 sh_error(illnum, argv[1]);
3620 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3628 * The return command.
3632 returncmd(int argc, char **argv)
3635 * If called outside a function, do what ksh does;
3636 * skip the rest of the file.
3638 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3639 return argv[1] ? number(argv[1]) : exitstatus;
3644 falsecmd(int argc, char **argv)
3651 truecmd(int argc, char **argv)
3658 execcmd(int argc, char **argv)
3661 iflag = 0; /* exit on error */
3664 shellexec(argv + 1, pathval(), 0);
3673 * When commands are first encountered, they are entered in a hash table.
3674 * This ensures that a full path search will not have to be done for them
3675 * on each invocation.
3677 * We should investigate converting to a linear search, even though that
3678 * would make the command name "hash" a misnomer.
3681 #define CMDTABLESIZE 31 /* should be prime */
3682 #define ARB 1 /* actual size determined at run time */
3687 struct tblentry *next; /* next entry in hash chain */
3688 union param param; /* definition of builtin function */
3689 short cmdtype; /* index identifying command */
3690 char rehash; /* if set, cd done since entry created */
3691 char cmdname[ARB]; /* name of command */
3695 static struct tblentry *cmdtable[CMDTABLESIZE];
3696 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3699 static void tryexec(char *, char **, char **);
3700 static void clearcmdentry(int);
3701 static struct tblentry *cmdlookup(const char *, int);
3702 static void delete_cmd_entry(void);
3706 * Exec a program. Never returns. If you change this routine, you may
3707 * have to change the find_command routine as well.
3711 shellexec(char **argv, const char *path, int idx)
3719 envp = environment();
3720 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
3721 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3722 || find_applet_by_name(argv[0])
3725 tryexec(argv[0], argv, envp);
3729 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3730 if (--idx < 0 && pathopt == NULL) {
3731 tryexec(cmdname, argv, envp);
3732 if (errno != ENOENT && errno != ENOTDIR)
3739 /* Map to POSIX errors */
3751 exitstatus = exerrno;
3752 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3753 argv[0], e, suppressint ));
3754 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3760 tryexec(char *cmd, char **argv, char **envp)
3763 struct BB_applet *a;
3767 if (strchr(cmd, '/') == NULL
3768 && (a = find_applet_by_name(cmd)) != NULL
3769 && is_safe_applet(cmd)
3772 while (*c != NULL) {
3776 exit(a->main(argc, argv));
3778 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3779 if (find_applet_by_name(cmd) != NULL) {
3780 /* re-exec ourselves with the new arguments */
3781 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3782 /* If they called chroot or otherwise made the binary no longer
3783 * executable, fall through */
3790 execve(cmd, argv, envp);
3791 } while (errno == EINTR);
3793 execve(cmd, argv, envp);
3797 } else if (errno == ENOEXEC) {
3801 for (ap = argv; *ap; ap++)
3803 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3805 *ap = cmd = (char *)DEFAULT_SHELL;
3808 while ((*ap++ = *argv++))
3818 * Do a path search. The variable path (passed by reference) should be
3819 * set to the start of the path before the first call; padvance will update
3820 * this value as it proceeds. Successive calls to padvance will return
3821 * the possible path expansions in sequence. If an option (indicated by
3822 * a percent sign) appears in the path entry then the global variable
3823 * pathopt will be set to point to it; otherwise pathopt will be set to
3828 padvance(const char **path, const char *name)
3838 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3839 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3840 while (stackblocksize() < len)
3844 memcpy(q, start, p - start);
3852 while (*p && *p != ':') p++;
3858 return stalloc(len);
3862 /*** Command hashing code ***/
3865 printentry(struct tblentry *cmdp)
3871 idx = cmdp->param.index;
3874 name = padvance(&path, cmdp->cmdname);
3876 } while (--idx >= 0);
3877 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3882 hashcmd(int argc, char **argv)
3884 struct tblentry **pp;
3885 struct tblentry *cmdp;
3887 struct cmdentry entry;
3890 while ((c = nextopt("r")) != '\0') {
3894 if (*argptr == NULL) {
3895 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3896 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3897 if (cmdp->cmdtype == CMDNORMAL)
3904 while ((name = *argptr) != NULL) {
3905 if ((cmdp = cmdlookup(name, 0)) != NULL
3906 && (cmdp->cmdtype == CMDNORMAL
3907 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3909 find_command(name, &entry, DO_ERR, pathval());
3910 if (entry.cmdtype == CMDUNKNOWN)
3919 * Resolve a command name. If you change this routine, you may have to
3920 * change the shellexec routine as well.
3924 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3926 struct tblentry *cmdp;
3933 struct builtincmd *bcmd;
3935 /* If name contains a slash, don't use PATH or hash table */
3936 if (strchr(name, '/') != NULL) {
3937 entry->u.index = -1;
3939 while (stat(name, &statb) < 0) {
3944 entry->cmdtype = CMDUNKNOWN;
3948 entry->cmdtype = CMDNORMAL;
3952 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3953 if (find_applet_by_name(name)) {
3954 entry->cmdtype = CMDNORMAL;
3955 entry->u.index = -1;
3960 if (is_safe_applet(name)) {
3961 entry->cmdtype = CMDNORMAL;
3962 entry->u.index = -1;
3966 updatetbl = (path == pathval());
3969 if (strstr(path, "%builtin") != NULL)
3973 /* If name is in the table, check answer will be ok */
3974 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3977 switch (cmdp->cmdtype) {
3995 } else if (cmdp->rehash == 0)
3996 /* if not invalidated by cd, we're done */
4000 /* If %builtin not in path, check for builtin next */
4001 bcmd = find_builtin(name);
4002 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
4003 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
4005 goto builtin_success;
4007 /* We have to search path. */
4008 prev = -1; /* where to start */
4009 if (cmdp && cmdp->rehash) { /* doing a rehash */
4010 if (cmdp->cmdtype == CMDBUILTIN)
4013 prev = cmdp->param.index;
4019 while ((fullname = padvance(&path, name)) != NULL) {
4020 stunalloc(fullname);
4023 if (prefix(pathopt, "builtin")) {
4025 goto builtin_success;
4027 } else if (!(act & DO_NOFUNC) &&
4028 prefix(pathopt, "func")) {
4031 /* ignore unimplemented options */
4035 /* if rehash, don't redo absolute path names */
4036 if (fullname[0] == '/' && idx <= prev) {
4039 TRACE(("searchexec \"%s\": no change\n", name));
4042 while (stat(fullname, &statb) < 0) {
4047 if (errno != ENOENT && errno != ENOTDIR)
4051 e = EACCES; /* if we fail, this will be the error */
4052 if (!S_ISREG(statb.st_mode))
4054 if (pathopt) { /* this is a %func directory */
4055 stalloc(strlen(fullname) + 1);
4056 readcmdfile(fullname);
4057 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4058 cmdp->cmdtype != CMDFUNCTION)
4059 sh_error("%s not defined in %s", name, fullname);
4060 stunalloc(fullname);
4063 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4065 entry->cmdtype = CMDNORMAL;
4066 entry->u.index = idx;
4070 cmdp = cmdlookup(name, 1);
4071 cmdp->cmdtype = CMDNORMAL;
4072 cmdp->param.index = idx;
4077 /* We failed. If there was an entry for this command, delete it */
4078 if (cmdp && updatetbl)
4081 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4082 entry->cmdtype = CMDUNKNOWN;
4087 entry->cmdtype = CMDBUILTIN;
4088 entry->u.cmd = bcmd;
4092 cmdp = cmdlookup(name, 1);
4093 cmdp->cmdtype = CMDBUILTIN;
4094 cmdp->param.cmd = bcmd;
4098 entry->cmdtype = cmdp->cmdtype;
4099 entry->u = cmdp->param;
4104 * Wrapper around strcmp for qsort/bsearch/...
4106 static int pstrcmp(const void *a, const void *b)
4108 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4112 * Search the table of builtin commands.
4115 static struct builtincmd *
4116 find_builtin(const char *name)
4118 struct builtincmd *bp;
4121 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4130 * Called when a cd is done. Marks all commands so the next time they
4131 * are executed they will be rehashed.
4137 struct tblentry **pp;
4138 struct tblentry *cmdp;
4140 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4141 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4142 if (cmdp->cmdtype == CMDNORMAL || (
4143 cmdp->cmdtype == CMDBUILTIN &&
4144 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4155 * Fix command hash table when PATH changed.
4156 * Called before PATH is changed. The argument is the new value of PATH;
4157 * pathval() still returns the old value at this point.
4158 * Called with interrupts off.
4162 changepath(const char *newval)
4164 const char *old, *new;
4171 firstchange = 9999; /* assume no change */
4177 if ((*old == '\0' && *new == ':')
4178 || (*old == ':' && *new == '\0'))
4180 old = new; /* ignore subsequent differences */
4184 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4191 if (builtinloc < 0 && idx_bltin >= 0)
4192 builtinloc = idx_bltin; /* zap builtins */
4193 if (builtinloc >= 0 && idx_bltin < 0)
4195 clearcmdentry(firstchange);
4196 builtinloc = idx_bltin;
4201 * Clear out command entries. The argument specifies the first entry in
4202 * PATH which has changed.
4206 clearcmdentry(int firstchange)
4208 struct tblentry **tblp;
4209 struct tblentry **pp;
4210 struct tblentry *cmdp;
4213 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4215 while ((cmdp = *pp) != NULL) {
4216 if ((cmdp->cmdtype == CMDNORMAL &&
4217 cmdp->param.index >= firstchange)
4218 || (cmdp->cmdtype == CMDBUILTIN &&
4219 builtinloc >= firstchange)) {
4233 * Locate a command in the command hash table. If "add" is nonzero,
4234 * add the command to the table if it is not already present. The
4235 * variable "lastcmdentry" is set to point to the address of the link
4236 * pointing to the entry, so that delete_cmd_entry can delete the
4239 * Interrupts must be off if called with add != 0.
4242 static struct tblentry **lastcmdentry;
4245 static struct tblentry *
4246 cmdlookup(const char *name, int add)
4248 unsigned int hashval;
4250 struct tblentry *cmdp;
4251 struct tblentry **pp;
4254 hashval = (unsigned char)*p << 4;
4256 hashval += (unsigned char)*p++;
4258 pp = &cmdtable[hashval % CMDTABLESIZE];
4259 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4260 if (equal(cmdp->cmdname, name))
4264 if (add && cmdp == NULL) {
4265 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4266 + strlen(name) + 1);
4268 cmdp->cmdtype = CMDUNKNOWN;
4269 strcpy(cmdp->cmdname, name);
4276 * Delete the command entry returned on the last lookup.
4280 delete_cmd_entry(void)
4282 struct tblentry *cmdp;
4285 cmdp = *lastcmdentry;
4286 *lastcmdentry = cmdp->next;
4287 if (cmdp->cmdtype == CMDFUNCTION)
4288 freefunc(cmdp->param.func);
4295 * Add a new command entry, replacing any existing command entry for
4296 * the same name - except special builtins.
4299 static void addcmdentry(char *name, struct cmdentry *entry)
4301 struct tblentry *cmdp;
4303 cmdp = cmdlookup(name, 1);
4304 if (cmdp->cmdtype == CMDFUNCTION) {
4305 freefunc(cmdp->param.func);
4307 cmdp->cmdtype = entry->cmdtype;
4308 cmdp->param = entry->u;
4313 * Make a copy of a parse tree.
4316 static struct funcnode * copyfunc(union node *n)
4321 funcblocksize = offsetof(struct funcnode, n);
4324 blocksize = funcblocksize;
4325 f = ckmalloc(blocksize + funcstringsize);
4326 funcblock = (char *) f + offsetof(struct funcnode, n);
4327 funcstring = (char *) f + blocksize;
4334 * Define a shell function.
4338 defun(char *name, union node *func)
4340 struct cmdentry entry;
4343 entry.cmdtype = CMDFUNCTION;
4344 entry.u.func = copyfunc(func);
4345 addcmdentry(name, &entry);
4351 * Delete a function if it exists.
4355 unsetfunc(const char *name)
4357 struct tblentry *cmdp;
4359 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4360 cmdp->cmdtype == CMDFUNCTION)
4365 * Locate and print what a word is...
4369 #ifdef CONFIG_ASH_CMDCMD
4371 describe_command(char *command, int describe_command_verbose)
4373 #define describe_command_verbose 1
4375 describe_command(char *command)
4378 struct cmdentry entry;
4379 struct tblentry *cmdp;
4380 #ifdef CONFIG_ASH_ALIAS
4381 const struct alias *ap;
4383 const char *path = pathval();
4385 if (describe_command_verbose) {
4389 /* First look at the keywords */
4390 if (findkwd(command)) {
4391 out1str(describe_command_verbose ? " is a shell keyword" : command);
4395 #ifdef CONFIG_ASH_ALIAS
4396 /* Then look at the aliases */
4397 if ((ap = lookupalias(command, 0)) != NULL) {
4398 if (describe_command_verbose) {
4399 out1fmt(" is an alias for %s", ap->val);
4408 /* Then check if it is a tracked alias */
4409 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4410 entry.cmdtype = cmdp->cmdtype;
4411 entry.u = cmdp->param;
4413 /* Finally use brute force */
4414 find_command(command, &entry, DO_ABS, path);
4417 switch (entry.cmdtype) {
4419 int j = entry.u.index;
4425 p = padvance(&path, command);
4429 if (describe_command_verbose) {
4431 (cmdp ? " a tracked alias for" : nullstr), p
4440 if (describe_command_verbose) {
4441 out1str(" is a shell function");
4448 if (describe_command_verbose) {
4449 out1fmt(" is a %sshell builtin",
4450 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4451 "special " : nullstr
4459 if (describe_command_verbose) {
4460 out1str(": not found\n");
4466 outstr("\n", stdout);
4471 typecmd(int argc, char **argv)
4476 for (i = 1; i < argc; i++) {
4477 #ifdef CONFIG_ASH_CMDCMD
4478 err |= describe_command(argv[i], 1);
4480 err |= describe_command(argv[i]);
4486 #ifdef CONFIG_ASH_CMDCMD
4488 commandcmd(int argc, char **argv)
4496 while ((c = nextopt("pvV")) != '\0')
4498 verify |= VERIFY_VERBOSE;
4500 verify |= VERIFY_BRIEF;
4506 return describe_command(*argptr, verify - VERIFY_BRIEF);
4515 * Routines to expand arguments to commands. We have to deal with
4516 * backquotes, shell variables, and file metacharacters.
4522 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4523 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4524 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4525 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4526 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4529 * Structure specifying which parts of the string should be searched
4530 * for IFS characters.
4534 struct ifsregion *next; /* next region in list */
4535 int begoff; /* offset of start of region */
4536 int endoff; /* offset of end of region */
4537 int nulonly; /* search for nul bytes only */
4540 /* output of current string */
4541 static char *expdest;
4542 /* list of back quote expressions */
4543 static struct nodelist *argbackq;
4544 /* first struct in list of ifs regions */
4545 static struct ifsregion ifsfirst;
4546 /* last struct in list */
4547 static struct ifsregion *ifslastp;
4548 /* holds expanded arg list */
4549 static struct arglist exparg;
4551 static void argstr(char *, int);
4552 static char *exptilde(char *, char *, int);
4553 static void expbackq(union node *, int, int);
4554 static const char *subevalvar(char *, char *, int, int, int, int, int);
4555 static char *evalvar(char *, int);
4556 static void strtodest(const char *, int, int);
4557 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4558 static ssize_t varvalue(char *, int, int);
4559 static void recordregion(int, int, int);
4560 static void removerecordregions(int);
4561 static void ifsbreakup(char *, struct arglist *);
4562 static void ifsfree(void);
4563 static void expandmeta(struct strlist *, int);
4564 static int patmatch(char *, const char *);
4566 static int cvtnum(arith_t);
4567 static size_t esclen(const char *, const char *);
4568 static char *scanleft(char *, char *, char *, char *, int, int);
4569 static char *scanright(char *, char *, char *, char *, int, int);
4570 static void varunset(const char *, const char *, const char *, int)
4574 #define pmatch(a, b) !fnmatch((a), (b), 0)
4576 * Prepare a pattern for a expmeta (internal glob(3)) call.
4578 * Returns an stalloced string.
4581 static char * preglob(const char *pattern, int quoted, int flag) {
4582 flag |= RMESCAPE_GLOB;
4584 flag |= RMESCAPE_QUOTED;
4586 return _rmescapes((char *)pattern, flag);
4591 esclen(const char *start, const char *p) {
4594 while (p > start && *--p == CTLESC) {
4602 * Expand shell variables and backquotes inside a here document.
4605 static void expandhere(union node *arg, int fd)
4608 expandarg(arg, (struct arglist *)NULL, 0);
4609 full_write(fd, stackblock(), expdest - (char *)stackblock());
4614 * Perform variable substitution and command substitution on an argument,
4615 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4616 * perform splitting and file name expansion. When arglist is NULL, perform
4617 * here document expansion.
4621 expandarg(union node *arg, struct arglist *arglist, int flag)
4626 argbackq = arg->narg.backquote;
4627 STARTSTACKSTR(expdest);
4628 ifsfirst.next = NULL;
4630 argstr(arg->narg.text, flag);
4631 p = _STPUTC('\0', expdest);
4633 if (arglist == NULL) {
4634 return; /* here document expanded */
4636 p = grabstackstr(p);
4637 exparg.lastp = &exparg.list;
4641 if (flag & EXP_FULL) {
4642 ifsbreakup(p, &exparg);
4643 *exparg.lastp = NULL;
4644 exparg.lastp = &exparg.list;
4645 expandmeta(exparg.list, flag);
4647 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4649 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4652 exparg.lastp = &sp->next;
4656 *exparg.lastp = NULL;
4658 *arglist->lastp = exparg.list;
4659 arglist->lastp = exparg.lastp;
4665 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4666 * characters to allow for further processing. Otherwise treat
4667 * $@ like $* since no splitting will be performed.
4671 argstr(char *p, int flag)
4673 static const char spclchars[] = {
4681 CTLBACKQ | CTLQUOTE,
4682 #ifdef CONFIG_ASH_MATH_SUPPORT
4687 const char *reject = spclchars;
4689 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4690 int breakall = flag & EXP_WORD;
4695 if (!(flag & EXP_VARTILDE)) {
4697 } else if (flag & EXP_VARTILDE2) {
4702 if (flag & EXP_TILDE) {
4708 if (*q == CTLESC && (flag & EXP_QWORD))
4711 p = exptilde(p, q, flag);
4714 startloc = expdest - (char *)stackblock();
4716 length += strcspn(p + length, reject);
4718 if (c && (!(c & 0x80)
4719 #ifdef CONFIG_ASH_MATH_SUPPORT
4723 /* c == '=' || c == ':' || c == CTLENDARI */
4728 expdest = stnputs(p, length, expdest);
4729 newloc = expdest - (char *)stackblock();
4730 if (breakall && !inquotes && newloc > startloc) {
4731 recordregion(startloc, newloc, 0);
4742 if (flag & EXP_VARTILDE2) {
4746 flag |= EXP_VARTILDE2;
4751 * sort of a hack - expand tildes in variable
4752 * assignments (after the first '=' and after ':'s).
4761 case CTLENDVAR: /* ??? */
4764 /* "$@" syntax adherence hack */
4767 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4768 (p[4] == CTLQUOTEMARK || (
4769 p[4] == CTLENDVAR &&
4770 p[5] == CTLQUOTEMARK
4773 p = evalvar(p + 1, flag) + 1;
4776 inquotes = !inquotes;
4789 p = evalvar(p, flag);
4793 case CTLBACKQ|CTLQUOTE:
4794 expbackq(argbackq->n, c, quotes);
4795 argbackq = argbackq->next;
4797 #ifdef CONFIG_ASH_MATH_SUPPORT
4810 exptilde(char *startp, char *p, int flag)
4816 int quotes = flag & (EXP_FULL | EXP_CASE);
4821 while ((c = *++p) != '\0') {
4828 if (flag & EXP_VARTILDE)
4838 if (*name == '\0') {
4839 home = lookupvar(homestr);
4841 if ((pw = getpwnam(name)) == NULL)
4845 if (!home || !*home)
4848 startloc = expdest - (char *)stackblock();
4849 strtodest(home, SQSYNTAX, quotes);
4850 recordregion(startloc, expdest - (char *)stackblock(), 0);
4859 removerecordregions(int endoff)
4861 if (ifslastp == NULL)
4864 if (ifsfirst.endoff > endoff) {
4865 while (ifsfirst.next != NULL) {
4866 struct ifsregion *ifsp;
4868 ifsp = ifsfirst.next->next;
4869 ckfree(ifsfirst.next);
4870 ifsfirst.next = ifsp;
4873 if (ifsfirst.begoff > endoff)
4876 ifslastp = &ifsfirst;
4877 ifsfirst.endoff = endoff;
4882 ifslastp = &ifsfirst;
4883 while (ifslastp->next && ifslastp->next->begoff < endoff)
4884 ifslastp=ifslastp->next;
4885 while (ifslastp->next != NULL) {
4886 struct ifsregion *ifsp;
4888 ifsp = ifslastp->next->next;
4889 ckfree(ifslastp->next);
4890 ifslastp->next = ifsp;
4893 if (ifslastp->endoff > endoff)
4894 ifslastp->endoff = endoff;
4898 #ifdef CONFIG_ASH_MATH_SUPPORT
4900 * Expand arithmetic expression. Backup to start of expression,
4901 * evaluate, place result in (backed up) result, adjust string position.
4914 * This routine is slightly over-complicated for
4915 * efficiency. Next we scan backwards looking for the
4916 * start of arithmetic.
4918 start = stackblock();
4925 while (*p != CTLARI) {
4929 sh_error("missing CTLARI (shouldn't happen)");
4934 esc = esclen(start, p);
4944 removerecordregions(begoff);
4953 len = cvtnum(dash_arith(p + 2));
4956 recordregion(begoff, begoff + len, 0);
4961 * Expand stuff in backwards quotes.
4965 expbackq(union node *cmd, int quoted, int quotes)
4973 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4974 struct stackmark smark;
4977 setstackmark(&smark);
4979 startloc = dest - (char *)stackblock();
4981 evalbackcmd(cmd, (struct backcmd *) &in);
4982 popstackmark(&smark);
4989 memtodest(p, i, syntax, quotes);
4993 i = safe_read(in.fd, buf, sizeof buf);
4994 TRACE(("expbackq: read returns %d\n", i));
5004 back_exitstatus = waitforjob(in.jp);
5008 /* Eat all trailing newlines */
5010 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5015 recordregion(startloc, dest - (char *)stackblock(), 0);
5016 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5017 (dest - (char *)stackblock()) - startloc,
5018 (dest - (char *)stackblock()) - startloc,
5019 stackblock() + startloc));
5024 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5035 const char *s = loc2;
5041 match = pmatch(str, s);
5045 if (quotes && *loc == CTLESC)
5055 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5062 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5065 const char *s = loc2;
5070 match = pmatch(str, s);
5077 esc = esclen(startp, loc);
5089 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5093 int saveherefd = herefd;
5094 struct nodelist *saveargbackq = argbackq;
5096 char *rmesc, *rmescend;
5098 char *(*scan)(char *, char *, char *, char *, int , int);
5101 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5102 STPUTC('\0', expdest);
5103 herefd = saveherefd;
5104 argbackq = saveargbackq;
5105 startp = stackblock() + startloc;
5109 setvar(str, startp, 0);
5110 amount = startp - expdest;
5111 STADJUST(amount, expdest);
5115 varunset(p, str, startp, varflags);
5119 subtype -= VSTRIMRIGHT;
5121 if (subtype < 0 || subtype > 3)
5126 rmescend = stackblock() + strloc;
5128 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5129 if (rmesc != startp) {
5131 startp = stackblock() + startloc;
5135 str = stackblock() + strloc;
5136 preglob(str, varflags & VSQUOTE, 0);
5138 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5139 zero = subtype >> 1;
5140 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5141 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5143 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5146 memmove(startp, loc, str - loc);
5147 loc = startp + (str - loc) - 1;
5150 amount = loc - expdest;
5151 STADJUST(amount, expdest);
5158 * Expand a variable, and return a pointer to the next character in the
5162 evalvar(char *p, int flag)
5175 quotes = flag & (EXP_FULL | EXP_CASE);
5177 subtype = varflags & VSTYPE;
5178 quoted = varflags & VSQUOTE;
5180 easy = (!quoted || (*var == '@' && shellparam.nparam));
5181 startloc = expdest - (char *)stackblock();
5182 p = strchr(p, '=') + 1;
5185 varlen = varvalue(var, varflags, flag);
5186 if (varflags & VSNUL)
5189 if (subtype == VSPLUS) {
5190 varlen = -1 - varlen;
5194 if (subtype == VSMINUS) {
5198 p, flag | EXP_TILDE |
5199 (quoted ? EXP_QWORD : EXP_WORD)
5208 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5210 if (subevalvar(p, var, 0, subtype, startloc,
5214 * Remove any recorded regions beyond
5217 removerecordregions(startloc);
5227 if (varlen < 0 && uflag)
5228 varunset(p, var, 0, 0);
5230 if (subtype == VSLENGTH) {
5231 cvtnum(varlen > 0 ? varlen : 0);
5235 if (subtype == VSNORMAL) {
5239 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5248 case VSTRIMRIGHTMAX:
5257 * Terminate the string and start recording the pattern
5260 STPUTC('\0', expdest);
5261 patloc = expdest - (char *)stackblock();
5262 if (subevalvar(p, NULL, patloc, subtype,
5263 startloc, varflags, quotes) == 0) {
5264 int amount = expdest - (
5265 (char *)stackblock() + patloc - 1
5267 STADJUST(-amount, expdest);
5269 /* Remove any recorded regions beyond start of variable */
5270 removerecordregions(startloc);
5275 if (subtype != VSNORMAL) { /* skip to end of alternative */
5278 if ((c = *p++) == CTLESC)
5280 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5282 argbackq = argbackq->next;
5283 } else if (c == CTLVAR) {
5284 if ((*p++ & VSTYPE) != VSNORMAL)
5286 } else if (c == CTLENDVAR) {
5297 * Put a string on the stack.
5301 memtodest(const char *p, size_t len, int syntax, int quotes) {
5304 q = makestrspace(len * 2, q);
5307 int c = SC2INT(*p++);
5310 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5320 strtodest(const char *p, int syntax, int quotes)
5322 memtodest(p, strlen(p), syntax, quotes);
5327 * Add the value of a specialized variable to the stack string.
5331 varvalue(char *name, int varflags, int flags)
5341 int quoted = varflags & VSQUOTE;
5342 int subtype = varflags & VSTYPE;
5343 int quotes = flags & (EXP_FULL | EXP_CASE);
5345 if (quoted && (flags & EXP_FULL))
5346 sep = 1 << CHAR_BIT;
5348 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5357 num = shellparam.nparam;
5367 p = makestrspace(NOPTS, expdest);
5368 for (i = NOPTS - 1; i >= 0; i--) {
5370 USTPUTC(optletters(i), p);
5381 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5382 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5385 if (!(ap = shellparam.p))
5387 while ((p = *ap++)) {
5390 partlen = strlen(p);
5393 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5394 memtodest(p, partlen, syntax, quotes);
5400 if (subtype == VSPLUS || subtype == VSLENGTH) {
5422 if (num < 0 || num > shellparam.nparam)
5424 p = num ? shellparam.p[num - 1] : arg0;
5427 p = lookupvar(name);
5433 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5434 memtodest(p, len, syntax, quotes);
5438 if (subtype == VSPLUS || subtype == VSLENGTH)
5439 STADJUST(-len, expdest);
5445 * Record the fact that we have to scan this region of the
5446 * string for IFS characters.
5450 recordregion(int start, int end, int nulonly)
5452 struct ifsregion *ifsp;
5454 if (ifslastp == NULL) {
5458 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5460 ifslastp->next = ifsp;
5464 ifslastp->begoff = start;
5465 ifslastp->endoff = end;
5466 ifslastp->nulonly = nulonly;
5471 * Break the argument string into pieces based upon IFS and add the
5472 * strings to the argument list. The regions of the string to be
5473 * searched for IFS characters have been stored by recordregion.
5476 ifsbreakup(char *string, struct arglist *arglist)
5478 struct ifsregion *ifsp;
5483 const char *ifs, *realifs;
5489 if (ifslastp != NULL) {
5492 realifs = ifsset() ? ifsval() : defifs;
5495 p = string + ifsp->begoff;
5496 nulonly = ifsp->nulonly;
5497 ifs = nulonly ? nullstr : realifs;
5499 while (p < string + ifsp->endoff) {
5503 if (strchr(ifs, *p)) {
5505 ifsspc = (strchr(defifs, *p) != NULL);
5506 /* Ignore IFS whitespace at start */
5507 if (q == start && ifsspc) {
5513 sp = (struct strlist *)stalloc(sizeof *sp);
5515 *arglist->lastp = sp;
5516 arglist->lastp = &sp->next;
5520 if (p >= string + ifsp->endoff) {
5526 if (strchr(ifs, *p) == NULL ) {
5529 } else if (strchr(defifs, *p) == NULL) {
5545 } while ((ifsp = ifsp->next) != NULL);
5554 sp = (struct strlist *)stalloc(sizeof *sp);
5556 *arglist->lastp = sp;
5557 arglist->lastp = &sp->next;
5563 struct ifsregion *p;
5568 struct ifsregion *ifsp;
5574 ifsfirst.next = NULL;
5578 static void expmeta(char *, char *);
5579 static struct strlist *expsort(struct strlist *);
5580 static struct strlist *msort(struct strlist *, int);
5582 static char *expdir;
5586 expandmeta(struct strlist *str, int flag)
5588 static const char metachars[] = {
5591 /* TODO - EXP_REDIR */
5594 struct strlist **savelastp;
5600 if (!strpbrk(str->text, metachars))
5602 savelastp = exparg.lastp;
5605 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5607 int i = strlen(str->text);
5608 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5616 if (exparg.lastp == savelastp) {
5621 *exparg.lastp = str;
5622 rmescapes(str->text);
5623 exparg.lastp = &str->next;
5625 *exparg.lastp = NULL;
5626 *savelastp = sp = expsort(*savelastp);
5627 while (sp->next != NULL)
5629 exparg.lastp = &sp->next;
5636 * Add a file name to the list.
5640 addfname(const char *name)
5644 sp = (struct strlist *)stalloc(sizeof *sp);
5645 sp->text = sstrdup(name);
5647 exparg.lastp = &sp->next;
5652 * Do metacharacter (i.e. *, ?, [...]) expansion.
5656 expmeta(char *enddir, char *name)
5671 for (p = name; *p; p++) {
5672 if (*p == '*' || *p == '?')
5674 else if (*p == '[') {
5681 if (*q == '/' || *q == '\0')
5688 } else if (*p == '\\')
5690 else if (*p == '/') {
5697 if (metaflag == 0) { /* we've reached the end of the file name */
5698 if (enddir != expdir)
5706 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5717 } while (p < start);
5719 if (enddir == expdir) {
5721 } else if (enddir == expdir + 1 && *expdir == '/') {
5727 if ((dirp = opendir(cp)) == NULL)
5729 if (enddir != expdir)
5731 if (*endname == 0) {
5743 while (! intpending && (dp = readdir(dirp)) != NULL) {
5744 if (dp->d_name[0] == '.' && ! matchdot)
5746 if (pmatch(start, dp->d_name)) {
5748 scopy(dp->d_name, enddir);
5751 for (p = enddir, cp = dp->d_name;
5752 (*p++ = *cp++) != '\0';)
5755 expmeta(p, endname);
5765 * Sort the results of file name expansion. It calculates the number of
5766 * strings to sort and then calls msort (short for merge sort) to do the
5770 static struct strlist *
5771 expsort(struct strlist *str)
5777 for (sp = str ; sp ; sp = sp->next)
5779 return msort(str, len);
5783 static struct strlist *
5784 msort(struct strlist *list, int len)
5786 struct strlist *p, *q = NULL;
5787 struct strlist **lpp;
5795 for (n = half ; --n >= 0 ; ) {
5799 q->next = NULL; /* terminate first half of list */
5800 q = msort(list, half); /* sort first half of list */
5801 p = msort(p, len - half); /* sort second half */
5804 #ifdef CONFIG_LOCALE_SUPPORT
5805 if (strcoll(p->text, q->text) < 0)
5807 if (strcmp(p->text, q->text) < 0)
5812 if ((p = *lpp) == NULL) {
5819 if ((q = *lpp) == NULL) {
5830 * Returns true if the pattern matches the string.
5833 static int patmatch(char *pattern, const char *string)
5835 return pmatch(preglob(pattern, 0, 0), string);
5840 * Remove any CTLESC characters from a string.
5844 _rmescapes(char *str, int flag)
5847 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5852 p = strpbrk(str, qchars);
5858 if (flag & RMESCAPE_ALLOC) {
5859 size_t len = p - str;
5860 size_t fulllen = len + strlen(p) + 1;
5862 if (flag & RMESCAPE_GROW) {
5863 r = makestrspace(fulllen, expdest);
5864 } else if (flag & RMESCAPE_HEAP) {
5865 r = ckmalloc(fulllen);
5867 r = stalloc(fulllen);
5871 q = memcpy(q, str, len) + len;
5874 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5875 globbing = flag & RMESCAPE_GLOB;
5876 notescaped = globbing;
5878 if (*p == CTLQUOTEMARK) {
5879 inquotes = ~inquotes;
5881 notescaped = globbing;
5885 /* naked back slash */
5891 if (notescaped && inquotes && *p != '/') {
5895 notescaped = globbing;
5900 if (flag & RMESCAPE_GROW) {
5902 STADJUST(q - r + 1, expdest);
5909 * See if a pattern matches in a case statement.
5913 casematch(union node *pattern, char *val)
5915 struct stackmark smark;
5918 setstackmark(&smark);
5919 argbackq = pattern->narg.backquote;
5920 STARTSTACKSTR(expdest);
5922 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5923 STACKSTRNUL(expdest);
5924 result = patmatch(stackblock(), val);
5925 popstackmark(&smark);
5938 expdest = makestrspace(32, expdest);
5939 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5940 len = fmtstr(expdest, 32, "%lld", (long long) num);
5942 len = fmtstr(expdest, 32, "%ld", num);
5944 STADJUST(len, expdest);
5949 varunset(const char *end, const char *var, const char *umsg, int varflags)
5955 msg = "parameter not set";
5957 if (*end == CTLENDVAR) {
5958 if (varflags & VSNUL)
5963 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5970 * This implements the input routines used by the parser.
5973 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5975 static void pushfile(void);
5978 * Read a character from the script, returning PEOF on end of file.
5979 * Nul characters in the input are silently discarded.
5983 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5985 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5986 #define pgetc_macro() pgetc()
5990 return pgetc_as_macro();
5993 #define pgetc_macro() pgetc_as_macro()
5997 return pgetc_macro();
6003 * Same as pgetc(), but ignores PEOA.
6005 #ifdef CONFIG_ASH_ALIAS
6006 static int pgetc2(void)
6012 } while (c == PEOA);
6016 static int pgetc2(void)
6018 return pgetc_macro();
6023 * Read a line from the script.
6026 static char * pfgets(char *line, int len)
6032 while (--nleft > 0) {
6049 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6050 #ifdef CONFIG_ASH_EXPAND_PRMT
6051 static char *cmdedit_prompt;
6053 static const char *cmdedit_prompt;
6055 static void putprompt(const char *s)
6057 #ifdef CONFIG_ASH_EXPAND_PRMT
6058 free(cmdedit_prompt);
6059 cmdedit_prompt = xstrdup(s);
6065 static void putprompt(const char *s)
6071 static int preadfd(void)
6074 char *buf = parsefile->buf;
6078 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6079 if (!iflag || parsefile->fd)
6080 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6082 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6083 cmdedit_path_lookup = pathval();
6085 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6087 /* Ctrl+C presend */
6096 if(nr < 0 && errno == 0) {
6097 /* Ctrl+D presend */
6102 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6106 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6107 int flags = fcntl(0, F_GETFL, 0);
6108 if (flags >= 0 && flags & O_NONBLOCK) {
6109 flags &=~ O_NONBLOCK;
6110 if (fcntl(0, F_SETFL, flags) >= 0) {
6111 out2str("sh: turning off NDELAY mode\n");
6121 * Refill the input buffer and return the next input character:
6123 * 1) If a string was pushed back on the input, pop it;
6124 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6125 * from a string so we can't refill the buffer, return EOF.
6126 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6127 * 4) Process input up to the next newline, deleting nul characters.
6137 while (parsefile->strpush) {
6138 #ifdef CONFIG_ASH_ALIAS
6139 if (parsenleft == -1 && parsefile->strpush->ap &&
6140 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6145 if (--parsenleft >= 0)
6146 return SC2INT(*parsenextc++);
6148 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6155 if ((more = preadfd()) <= 0) {
6156 parselleft = parsenleft = EOF_NLEFT;
6163 /* delete nul characters */
6171 memmove(q, q + 1, more);
6175 parsenleft = q - parsenextc - 1;
6181 parsenleft = q - parsenextc - 1;
6193 out2str(parsenextc);
6198 return SC2INT(*parsenextc++);
6202 * Undo the last call to pgetc. Only one character may be pushed back.
6203 * PEOF may be pushed back.
6214 * Push a string back onto the input at this current parsefile level.
6215 * We handle aliases this way.
6218 pushstring(char *s, void *ap)
6225 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6226 if (parsefile->strpush) {
6227 sp = ckmalloc(sizeof (struct strpush));
6228 sp->prev = parsefile->strpush;
6229 parsefile->strpush = sp;
6231 sp = parsefile->strpush = &(parsefile->basestrpush);
6232 sp->prevstring = parsenextc;
6233 sp->prevnleft = parsenleft;
6234 #ifdef CONFIG_ASH_ALIAS
6235 sp->ap = (struct alias *)ap;
6237 ((struct alias *)ap)->flag |= ALIASINUSE;
6249 struct strpush *sp = parsefile->strpush;
6252 #ifdef CONFIG_ASH_ALIAS
6254 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6255 checkkwd |= CHKALIAS;
6257 if (sp->string != sp->ap->val) {
6260 sp->ap->flag &= ~ALIASINUSE;
6261 if (sp->ap->flag & ALIASDEAD) {
6262 unalias(sp->ap->name);
6266 parsenextc = sp->prevstring;
6267 parsenleft = sp->prevnleft;
6268 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6269 parsefile->strpush = sp->prev;
6270 if (sp != &(parsefile->basestrpush))
6276 * Set the input to take input from a file. If push is set, push the
6277 * old input onto the stack first.
6281 setinputfile(const char *fname, int flags)
6287 if ((fd = open(fname, O_RDONLY)) < 0) {
6288 if (flags & INPUT_NOFILE_OK)
6290 sh_error("Can't open %s", fname);
6293 fd2 = copyfd(fd, 10);
6296 sh_error("Out of file descriptors");
6299 setinputfd(fd, flags & INPUT_PUSH_FILE);
6307 * Like setinputfile, but takes an open file descriptor. Call this with
6312 setinputfd(int fd, int push)
6314 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6320 if (parsefile->buf == NULL)
6321 parsefile->buf = ckmalloc(IBUFSIZ);
6322 parselleft = parsenleft = 0;
6328 * Like setinputfile, but takes input from a string.
6332 setinputstring(char *string)
6336 parsenextc = string;
6337 parsenleft = strlen(string);
6338 parsefile->buf = NULL;
6345 * To handle the "." command, a stack of input files is used. Pushfile
6346 * adds a new entry to the stack and popfile restores the previous level.
6352 struct parsefile *pf;
6354 parsefile->nleft = parsenleft;
6355 parsefile->lleft = parselleft;
6356 parsefile->nextc = parsenextc;
6357 parsefile->linno = plinno;
6358 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6359 pf->prev = parsefile;
6362 pf->basestrpush.prev = NULL;
6370 struct parsefile *pf = parsefile;
6379 parsefile = pf->prev;
6381 parsenleft = parsefile->nleft;
6382 parselleft = parsefile->lleft;
6383 parsenextc = parsefile->nextc;
6384 plinno = parsefile->linno;
6390 * Return to top level.
6396 while (parsefile != &basepf)
6402 * Close the file(s) that the shell is reading commands from. Called
6403 * after a fork is done.
6410 if (parsefile->fd > 0) {
6411 close(parsefile->fd);
6418 /* mode flags for set_curjob */
6419 #define CUR_DELETE 2
6420 #define CUR_RUNNING 1
6421 #define CUR_STOPPED 0
6423 /* mode flags for dowait */
6424 #define DOWAIT_NORMAL 0
6425 #define DOWAIT_BLOCK 1
6428 static struct job *jobtab;
6430 static unsigned njobs;
6432 /* pgrp of shell on invocation */
6433 static int initialpgrp;
6434 static int ttyfd = -1;
6437 static struct job *curjob;
6438 /* number of presumed living untracked jobs */
6441 static void set_curjob(struct job *, unsigned);
6443 static int restartjob(struct job *, int);
6444 static void xtcsetpgrp(int, pid_t);
6445 static char *commandtext(union node *);
6446 static void cmdlist(union node *, int);
6447 static void cmdtxt(union node *);
6448 static void cmdputs(const char *);
6449 static void showpipe(struct job *, FILE *);
6451 static int sprint_status(char *, int, int);
6452 static void freejob(struct job *);
6453 static struct job *getjob(const char *, int);
6454 static struct job *growjobtab(void);
6455 static void forkchild(struct job *, union node *, int);
6456 static void forkparent(struct job *, union node *, int, pid_t);
6457 static int dowait(int, struct job *);
6458 static int getstatus(struct job *);
6461 set_curjob(struct job *jp, unsigned mode)
6464 struct job **jpp, **curp;
6466 /* first remove from list */
6467 jpp = curp = &curjob;
6472 jpp = &jp1->prev_job;
6474 *jpp = jp1->prev_job;
6476 /* Then re-insert in correct position */
6484 /* job being deleted */
6487 /* newly created job or backgrounded job,
6488 put after all stopped jobs. */
6492 if (!jp1 || jp1->state != JOBSTOPPED)
6495 jpp = &jp1->prev_job;
6501 /* newly stopped job - becomes curjob */
6502 jp->prev_job = *jpp;
6510 * Turn job control on and off.
6512 * Note: This code assumes that the third arg to ioctl is a character
6513 * pointer, which is true on Berkeley systems but not System V. Since
6514 * System V doesn't have job control yet, this isn't a problem now.
6516 * Called with interrupts off.
6525 if (on == jobctl || rootshell == 0)
6529 ofd = fd = open(_PATH_TTY, O_RDWR);
6532 while (!isatty(fd) && --fd >= 0)
6535 fd = fcntl(fd, F_DUPFD, 10);
6539 fcntl(fd, F_SETFD, FD_CLOEXEC);
6540 do { /* while we are in the background */
6541 if ((pgrp = tcgetpgrp(fd)) < 0) {
6543 sh_warnx("can't access tty; job control turned off");
6547 if (pgrp == getpgrp())
6558 xtcsetpgrp(fd, pgrp);
6560 /* turning job control off */
6563 xtcsetpgrp(fd, pgrp);
6577 killcmd(int argc, char **argv)
6588 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6589 "kill -l [exitstatus]"
6593 if (**++argv == '-') {
6594 signo = get_signum(*argv + 1);
6598 while ((c = nextopt("ls:")) != '\0')
6608 signo = get_signum(optionarg);
6611 "invalid signal number or name: %s",
6622 if (!list && signo < 0)
6625 if ((signo < 0 || !*argv) ^ list) {
6633 for (i = 1; i < NSIG; i++) {
6634 name = get_signame(i);
6636 out1fmt(snlfmt, name);
6640 name = get_signame(signo);
6642 out1fmt(snlfmt, name);
6644 sh_error("invalid signal number or exit status: %s", *argptr);
6650 if (**argv == '%') {
6651 jp = getjob(*argv, 0);
6652 pid = -jp->ps[0].pid;
6654 pid = **argv == '-' ?
6655 -number(*argv + 1) : number(*argv);
6657 if (kill(pid, signo) != 0) {
6658 sh_warnx("(%d) - %m", pid);
6669 jobno(const struct job *jp)
6671 return jp - jobtab + 1;
6677 fgcmd(int argc, char **argv)
6684 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6689 jp = getjob(*argv, 1);
6690 if (mode == FORK_BG) {
6691 set_curjob(jp, CUR_RUNNING);
6692 fprintf(out, "[%d] ", jobno(jp));
6694 outstr(jp->ps->cmd, out);
6696 retval = restartjob(jp, mode);
6697 } while (*argv && *++argv);
6701 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6705 restartjob(struct job *jp, int mode)
6707 struct procstat *ps;
6713 if (jp->state == JOBDONE)
6715 jp->state = JOBRUNNING;
6717 if (mode == FORK_FG)
6718 xtcsetpgrp(ttyfd, pgid);
6719 killpg(pgid, SIGCONT);
6723 if (WIFSTOPPED(ps->status)) {
6726 } while (ps++, --i);
6728 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6735 sprint_status(char *s, int status, int sigonly)
6741 if (!WIFEXITED(status)) {
6743 if (WIFSTOPPED(status))
6744 st = WSTOPSIG(status);
6747 st = WTERMSIG(status);
6749 if (st == SIGINT || st == SIGPIPE)
6752 if (WIFSTOPPED(status))
6757 col = fmtstr(s, 32, strsignal(st));
6758 if (WCOREDUMP(status)) {
6759 col += fmtstr(s + col, 16, " (core dumped)");
6761 } else if (!sigonly) {
6762 st = WEXITSTATUS(status);
6764 col = fmtstr(s, 16, "Done(%d)", st);
6766 col = fmtstr(s, 16, "Done");
6775 showjob(FILE *out, struct job *jp, int mode)
6777 struct procstat *ps;
6778 struct procstat *psend;
6785 if (mode & SHOW_PGID) {
6786 /* just output process (group) id of pipeline */
6787 fprintf(out, "%d\n", ps->pid);
6791 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6796 else if (curjob && jp == curjob->prev_job)
6799 if (mode & SHOW_PID)
6800 col += fmtstr(s + col, 16, "%d ", ps->pid);
6802 psend = ps + jp->nprocs;
6804 if (jp->state == JOBRUNNING) {
6805 scopy("Running", s + col);
6806 col += strlen("Running");
6808 int status = psend[-1].status;
6810 if (jp->state == JOBSTOPPED)
6811 status = jp->stopstatus;
6813 col += sprint_status(s + col, status, 0);
6819 /* for each process */
6820 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6823 fprintf(out, "%s%*c%s",
6824 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6826 if (!(mode & SHOW_PID)) {
6830 if (++ps == psend) {
6831 outcslow('\n', out);
6838 if (jp->state == JOBDONE) {
6839 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6846 jobscmd(int argc, char **argv)
6852 while ((m = nextopt("lp")))
6862 showjob(out, getjob(*argv,0), mode);
6865 showjobs(out, mode);
6872 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6873 * statuses have changed since the last call to showjobs.
6877 showjobs(FILE *out, int mode)
6881 TRACE(("showjobs(%x) called\n", mode));
6883 /* If not even one one job changed, there is nothing to do */
6884 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6887 for (jp = curjob; jp; jp = jp->prev_job) {
6888 if (!(mode & SHOW_CHANGED) || jp->changed)
6889 showjob(out, jp, mode);
6895 * Mark a job structure as unused.
6899 freejob(struct job *jp)
6901 struct procstat *ps;
6905 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6906 if (ps->cmd != nullstr)
6909 if (jp->ps != &jp->ps0)
6912 set_curjob(jp, CUR_DELETE);
6918 waitcmd(int argc, char **argv)
6931 /* wait for all jobs */
6936 /* no running procs */
6939 if (jp->state == JOBRUNNING)
6944 dowait(DOWAIT_BLOCK, 0);
6950 if (**argv != '%') {
6951 pid_t pid = number(*argv);
6955 if (job->ps[job->nprocs - 1].pid == pid)
6957 job = job->prev_job;
6963 job = getjob(*argv, 0);
6964 /* loop until process terminated or stopped */
6965 while (job->state == JOBRUNNING)
6966 dowait(DOWAIT_BLOCK, 0);
6968 retval = getstatus(job);
6979 * Convert a job name to a job structure.
6983 getjob(const char *name, int getctl)
6987 const char *err_msg = "No such job: %s";
6991 char *(*match)(const char *, const char *);
7006 if (c == '+' || c == '%') {
7008 err_msg = "No current job";
7010 } else if (c == '-') {
7013 err_msg = "No previous job";
7024 jp = jobtab + num - 1;
7041 if (match(jp->ps[0].cmd, p)) {
7045 err_msg = "%s: ambiguous";
7052 err_msg = "job %s not created under job control";
7053 if (getctl && jp->jobctl == 0)
7058 sh_error(err_msg, name);
7063 * Return a new job structure.
7064 * Called with interrupts off.
7068 makejob(union node *node, int nprocs)
7073 for (i = njobs, jp = jobtab ; ; jp++) {
7080 if (jp->state != JOBDONE || !jp->waited)
7089 memset(jp, 0, sizeof(*jp));
7094 jp->prev_job = curjob;
7099 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7101 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7111 struct job *jp, *jq;
7113 len = njobs * sizeof(*jp);
7115 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7117 offset = (char *)jp - (char *)jq;
7119 /* Relocate pointers */
7122 jq = (struct job *)((char *)jq + l);
7126 #define joff(p) ((struct job *)((char *)(p) + l))
7127 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7128 if (xlikely(joff(jp)->ps == &jq->ps0))
7129 jmove(joff(jp)->ps);
7130 if (joff(jp)->prev_job)
7131 jmove(joff(jp)->prev_job);
7141 jp = (struct job *)((char *)jp + len);
7145 } while (--jq >= jp);
7151 * Fork off a subshell. If we are doing job control, give the subshell its
7152 * own process group. Jp is a job structure that the job is to be added to.
7153 * N is the command that will be evaluated by the child. Both jp and n may
7154 * be NULL. The mode parameter can be one of the following:
7155 * FORK_FG - Fork off a foreground process.
7156 * FORK_BG - Fork off a background process.
7157 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7158 * process group even if job control is on.
7160 * When job control is turned off, background processes have their standard
7161 * input redirected to /dev/null (except for the second and later processes
7164 * Called with interrupts off.
7167 static void forkchild(struct job *jp, union node *n, int mode)
7171 TRACE(("Child shell %d\n", getpid()));
7178 /* do job control only in root shell */
7180 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7183 if (jp->nprocs == 0)
7186 pgrp = jp->ps[0].pid;
7187 /* This can fail because we are doing it in the parent also */
7188 (void)setpgid(0, pgrp);
7189 if (mode == FORK_FG)
7190 xtcsetpgrp(ttyfd, pgrp);
7195 if (mode == FORK_BG) {
7198 if (jp->nprocs == 0) {
7200 if (open(bb_dev_null, O_RDONLY) != 0)
7201 sh_error("Can't open %s", bb_dev_null);
7204 if (!oldlvl && iflag) {
7209 for (jp = curjob; jp; jp = jp->prev_job)
7214 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7216 TRACE(("In parent shell: child = %d\n", pid));
7218 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7223 if (mode != FORK_NOJOB && jp->jobctl) {
7226 if (jp->nprocs == 0)
7229 pgrp = jp->ps[0].pid;
7230 /* This can fail because we are doing it in the child also */
7231 (void)setpgid(pid, pgrp);
7234 if (mode == FORK_BG) {
7235 backgndpid = pid; /* set $! */
7236 set_curjob(jp, CUR_RUNNING);
7239 struct procstat *ps = &jp->ps[jp->nprocs++];
7245 ps->cmd = commandtext(n);
7251 forkshell(struct job *jp, union node *n, int mode)
7255 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7258 TRACE(("Fork failed, errno=%d", errno));
7261 sh_error("Cannot fork");
7264 forkchild(jp, n, mode);
7266 forkparent(jp, n, mode, pid);
7271 * Wait for job to finish.
7273 * Under job control we have the problem that while a child process is
7274 * running interrupts generated by the user are sent to the child but not
7275 * to the shell. This means that an infinite loop started by an inter-
7276 * active user may be hard to kill. With job control turned off, an
7277 * interactive user may place an interactive program inside a loop. If
7278 * the interactive program catches interrupts, the user doesn't want
7279 * these interrupts to also abort the loop. The approach we take here
7280 * is to have the shell ignore interrupt signals while waiting for a
7281 * foreground process to terminate, and then send itself an interrupt
7282 * signal if the child process was terminated by an interrupt signal.
7283 * Unfortunately, some programs want to do a bit of cleanup and then
7284 * exit on interrupt; unless these processes terminate themselves by
7285 * sending a signal to themselves (instead of calling exit) they will
7286 * confuse this approach.
7288 * Called with interrupts off.
7292 waitforjob(struct job *jp)
7296 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7297 while (jp->state == JOBRUNNING) {
7298 dowait(DOWAIT_BLOCK, jp);
7303 xtcsetpgrp(ttyfd, rootpid);
7305 * This is truly gross.
7306 * If we're doing job control, then we did a TIOCSPGRP which
7307 * caused us (the shell) to no longer be in the controlling
7308 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7309 * intuit from the subprocess exit status whether a SIGINT
7310 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7315 if (jp->state == JOBDONE)
7323 * Do a wait system call. If job control is compiled in, we accept
7324 * stopped processes. If block is zero, we return a value of zero
7325 * rather than blocking.
7327 * System V doesn't have a non-blocking wait system call. It does
7328 * have a SIGCLD signal that is sent to a process when one of it's
7329 * children dies. The obvious way to use SIGCLD would be to install
7330 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7331 * was received, and have waitproc bump another counter when it got
7332 * the status of a process. Waitproc would then know that a wait
7333 * system call would not block if the two counters were different.
7334 * This approach doesn't work because if a process has children that
7335 * have not been waited for, System V will send it a SIGCLD when it
7336 * installs a signal handler for SIGCLD. What this means is that when
7337 * a child exits, the shell will be sent SIGCLD signals continuously
7338 * until is runs out of stack space, unless it does a wait call before
7339 * restoring the signal handler. The code below takes advantage of
7340 * this (mis)feature by installing a signal handler for SIGCLD and
7341 * then checking to see whether it was called. If there are any
7342 * children to be waited for, it will be.
7344 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7345 * waits at all. In this case, the user will not be informed when
7346 * a background process until the next time she runs a real program
7347 * (as opposed to running a builtin command or just typing return),
7348 * and the jobs command may give out of date information.
7351 static int waitproc(int block, int *status)
7361 return wait3(status, flags, (struct rusage *)NULL);
7365 * Wait for a process to terminate.
7369 dowait(int block, struct job *job)
7374 struct job *thisjob;
7377 TRACE(("dowait(%d) called\n", block));
7378 pid = waitproc(block, &status);
7379 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7384 for (jp = curjob; jp; jp = jp->prev_job) {
7385 struct procstat *sp;
7386 struct procstat *spend;
7387 if (jp->state == JOBDONE)
7390 spend = jp->ps + jp->nprocs;
7393 if (sp->pid == pid) {
7394 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7395 sp->status = status;
7398 if (sp->status == -1)
7401 if (state == JOBRUNNING)
7403 if (WIFSTOPPED(sp->status)) {
7404 jp->stopstatus = sp->status;
7408 } while (++sp < spend);
7413 if (!WIFSTOPPED(status))
7420 if (state != JOBRUNNING) {
7421 thisjob->changed = 1;
7423 if (thisjob->state != state) {
7424 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7425 thisjob->state = state;
7427 if (state == JOBSTOPPED) {
7428 set_curjob(thisjob, CUR_STOPPED);
7437 if (thisjob && thisjob == job) {
7441 len = sprint_status(s, status, 1);
7453 * return 1 if there are stopped jobs, otherwise 0
7466 if (jp && jp->state == JOBSTOPPED) {
7467 out2str("You have stopped jobs.\n");
7477 * Return a string identifying a command (to be printed by the
7482 static char *cmdnextc;
7485 commandtext(union node *n)
7489 STARTSTACKSTR(cmdnextc);
7491 name = stackblock();
7492 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7493 name, cmdnextc, cmdnextc));
7494 return savestr(name);
7498 cmdtxt(union node *n)
7501 struct nodelist *lp;
7513 lp = n->npipe.cmdlist;
7531 cmdtxt(n->nbinary.ch1);
7547 cmdtxt(n->nif.test);
7550 if (n->nif.elsepart) {
7553 n = n->nif.elsepart;
7569 cmdtxt(n->nbinary.ch1);
7579 cmdputs(n->nfor.var);
7581 cmdlist(n->nfor.args, 1);
7586 cmdputs(n->narg.text);
7590 cmdlist(n->ncmd.args, 1);
7591 cmdlist(n->ncmd.redirect, 0);
7604 cmdputs(n->ncase.expr->narg.text);
7606 for (np = n->ncase.cases; np; np = np->nclist.next) {
7607 cmdtxt(np->nclist.pattern);
7609 cmdtxt(np->nclist.body);
7635 s[0] = n->nfile.fd + '0';
7639 if (n->type == NTOFD || n->type == NFROMFD) {
7640 s[0] = n->ndup.dupfd + '0';
7651 cmdlist(union node *np, int sep)
7653 for (; np; np = np->narg.next) {
7657 if (sep && np->narg.next)
7663 cmdputs(const char *s)
7665 const char *p, *str;
7666 char c, cc[2] = " ";
7670 static const char vstype[VSTYPE + 1][4] = {
7671 "", "}", "-", "+", "?", "=",
7672 "%", "%%", "#", "##"
7674 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7676 while ((c = *p++) != 0) {
7684 if ((subtype & VSTYPE) == VSLENGTH)
7688 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7695 str = "\"}" + !(quoted & 1);
7702 case CTLBACKQ+CTLQUOTE:
7705 #ifdef CONFIG_ASH_MATH_SUPPORT
7720 if ((subtype & VSTYPE) != VSNORMAL)
7722 str = vstype[subtype & VSTYPE];
7723 if (subtype & VSNUL)
7732 /* These can only happen inside quotes */
7745 while ((c = *str++)) {
7750 USTPUTC('"', nextc);
7758 showpipe(struct job *jp, FILE *out)
7760 struct procstat *sp;
7761 struct procstat *spend;
7763 spend = jp->ps + jp->nprocs;
7764 for (sp = jp->ps + 1; sp < spend; sp++)
7765 fprintf(out, " | %s", sp->cmd);
7766 outcslow('\n', out);
7771 xtcsetpgrp(int fd, pid_t pgrp)
7773 if (tcsetpgrp(fd, pgrp))
7774 sh_error("Cannot set tty process group (%m)");
7779 getstatus(struct job *job) {
7783 status = job->ps[job->nprocs - 1].status;
7784 retval = WEXITSTATUS(status);
7785 if (!WIFEXITED(status)) {
7787 retval = WSTOPSIG(status);
7788 if (!WIFSTOPPED(status))
7791 /* XXX: limits number of signals */
7792 retval = WTERMSIG(status);
7794 if (retval == SIGINT)
7800 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7801 jobno(job), job->nprocs, status, retval));
7805 #ifdef CONFIG_ASH_MAIL
7809 * Routines to check for mail. (Perhaps make part of main.c?)
7812 #define MAXMBOXES 10
7814 /* times of mailboxes */
7815 static time_t mailtime[MAXMBOXES];
7816 /* Set if MAIL or MAILPATH is changed. */
7817 static int mail_var_path_changed;
7822 * Print appropriate message(s) if mail has arrived.
7823 * If mail_var_path_changed is set,
7824 * then the value of MAIL has mail_var_path_changed,
7825 * so we just update the values.
7835 struct stackmark smark;
7838 setstackmark(&smark);
7839 mpath = mpathset() ? mpathval() : mailval();
7840 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7841 p = padvance(&mpath, nullstr);
7846 for (q = p ; *q ; q++);
7851 q[-1] = '\0'; /* delete trailing '/' */
7852 if (stat(p, &statb) < 0) {
7856 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7859 pathopt ? pathopt : "you have mail"
7862 *mtp = statb.st_mtime;
7864 mail_var_path_changed = 0;
7865 popstackmark(&smark);
7870 changemail(const char *val)
7872 mail_var_path_changed++;
7875 #endif /* CONFIG_ASH_MAIL */
7881 static short profile_buf[16384];
7885 static int isloginsh;
7887 static void read_profile(const char *);
7890 * Main routine. We initialize things, parse the arguments, execute
7891 * profiles if we're a login shell, and then call cmdloop to execute
7892 * commands. The setjmp call sets up the location to jump to when an
7893 * exception occurs. When an exception occurs the variable "state"
7894 * is used to figure out how far we had gotten.
7898 ash_main(int argc, char **argv)
7902 struct jmploc jmploc;
7903 struct stackmark smark;
7906 dash_errno = __errno_location();
7910 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7913 if (setjmp(jmploc.loc)) {
7923 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7927 outcslow('\n', stderr);
7929 popstackmark(&smark);
7930 FORCEINTON; /* enable interrupts */
7943 trputs("Shell args: "); trargs(argv);
7947 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7948 rseed = rootpid + ((time_t)time((time_t *)0));
7951 setstackmark(&smark);
7952 procargs(argc, argv);
7953 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7955 const char *hp = lookupvar("HISTFILE");
7958 hp = lookupvar("HOME");
7960 char *defhp = concat_path_file(hp, ".ash_history");
7961 setvar("HISTFILE", defhp, 0);
7967 if (argv[0] && argv[0][0] == '-')
7971 read_profile("/etc/profile");
7974 read_profile(".profile");
7980 getuid() == geteuid() && getgid() == getegid() &&
7984 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7985 read_profile(shinit);
7991 evalstring(minusc, 0);
7993 if (sflag || minusc == NULL) {
7994 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7996 const char *hp = lookupvar("HISTFILE");
7999 load_history ( hp );
8002 state4: /* XXX ??? - why isn't this before the "if" statement */
8010 extern void _mcleanup(void);
8020 * Read and execute commands. "Top" is nonzero for the top level command
8021 * loop; it turns on prompting if the shell is interactive.
8028 struct stackmark smark;
8032 TRACE(("cmdloop(%d) called\n", top));
8036 setstackmark(&smark);
8039 showjobs(stderr, SHOW_CHANGED);
8044 #ifdef CONFIG_ASH_MAIL
8048 n = parsecmd(inter);
8049 /* showtree(n); DEBUG */
8051 if (!top || numeof >= 50)
8053 if (!stoppedjobs()) {
8056 out2str("\nUse \"exit\" to leave shell.\n");
8059 } else if (nflag == 0) {
8060 job_warning = (job_warning == 2) ? 1 : 0;
8064 popstackmark(&smark);
8069 return skip & SKIPEVAL;
8078 * Read /etc/profile or .profile. Return on error.
8082 read_profile(const char *name)
8086 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8098 * Read a file containing shell functions.
8102 readcmdfile(char *name)
8104 setinputfile(name, INPUT_PUSH_FILE);
8111 * Take commands from a file. To be compatible we should do a path
8112 * search for the file, which is necessary to find sub-commands.
8115 static char * find_dot_file(char *name)
8118 const char *path = pathval();
8121 /* don't try this for absolute or relative paths */
8122 if (strchr(name, '/'))
8125 while ((fullname = padvance(&path, name)) != NULL) {
8126 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8128 * Don't bother freeing here, since it will
8129 * be freed by the caller.
8133 stunalloc(fullname);
8136 /* not found in the PATH */
8137 sh_error(not_found_msg, name);
8141 static int dotcmd(int argc, char **argv)
8144 volatile struct shparam saveparam;
8147 for (sp = cmdenviron; sp; sp = sp->next)
8148 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8150 if (argc >= 2) { /* That's what SVR2 does */
8153 fullname = find_dot_file(argv[1]);
8156 saveparam = shellparam;
8157 shellparam.malloc = 0;
8158 shellparam.nparam = argc - 2;
8159 shellparam.p = argv + 2;
8162 setinputfile(fullname, INPUT_PUSH_FILE);
8163 commandname = fullname;
8168 freeparam(&shellparam);
8169 shellparam = saveparam;
8171 status = exitstatus;
8178 exitcmd(int argc, char **argv)
8183 exitstatus = number(argv[1]);
8188 #ifdef CONFIG_ASH_BUILTIN_ECHO
8190 echocmd(int argc, char **argv)
8192 return bb_echo(argv);
8196 #ifdef CONFIG_ASH_BUILTIN_TEST
8198 testcmd(int argc, char **argv)
8200 return bb_test(argc, argv);
8207 * Same for malloc, realloc, but returns an error when out of space.
8211 ckrealloc(pointer p, size_t nbytes)
8213 p = realloc(p, nbytes);
8215 sh_error(bb_msg_memory_exhausted);
8220 ckmalloc(size_t nbytes)
8222 return ckrealloc(NULL, nbytes);
8226 * Make a copy of a string in safe storage.
8230 savestr(const char *s)
8232 char *p = strdup(s);
8234 sh_error(bb_msg_memory_exhausted);
8240 * Parse trees for commands are allocated in lifo order, so we use a stack
8241 * to make this more efficient, and also to avoid all sorts of exception
8242 * handling code to handle interrupts in the middle of a parse.
8244 * The size 504 was chosen because the Ultrix malloc handles that size
8250 stalloc(size_t nbytes)
8255 aligned = SHELL_ALIGN(nbytes);
8256 if (aligned > stacknleft) {
8259 struct stack_block *sp;
8261 blocksize = aligned;
8262 if (blocksize < MINSIZE)
8263 blocksize = MINSIZE;
8264 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8265 if (len < blocksize)
8266 sh_error(bb_msg_memory_exhausted);
8270 stacknxt = sp->space;
8271 stacknleft = blocksize;
8272 sstrend = stacknxt + blocksize;
8277 stacknxt += aligned;
8278 stacknleft -= aligned;
8284 stunalloc(pointer p)
8287 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8288 write(2, "stunalloc\n", 10);
8292 stacknleft += stacknxt - (char *)p;
8298 setstackmark(struct stackmark *mark)
8300 mark->stackp = stackp;
8301 mark->stacknxt = stacknxt;
8302 mark->stacknleft = stacknleft;
8303 mark->marknext = markp;
8309 popstackmark(struct stackmark *mark)
8311 struct stack_block *sp;
8314 markp = mark->marknext;
8315 while (stackp != mark->stackp) {
8320 stacknxt = mark->stacknxt;
8321 stacknleft = mark->stacknleft;
8322 sstrend = mark->stacknxt + mark->stacknleft;
8328 * When the parser reads in a string, it wants to stick the string on the
8329 * stack and only adjust the stack pointer when it knows how big the
8330 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8331 * of space on top of the stack and stackblocklen returns the length of
8332 * this block. Growstackblock will grow this space by at least one byte,
8333 * possibly moving it (like realloc). Grabstackblock actually allocates the
8334 * part of the block that has been used.
8338 growstackblock(void)
8342 newlen = stacknleft * 2;
8343 if (newlen < stacknleft)
8344 sh_error(bb_msg_memory_exhausted);
8348 if (stacknxt == stackp->space && stackp != &stackbase) {
8349 struct stack_block *oldstackp;
8350 struct stackmark *xmark;
8351 struct stack_block *sp;
8352 struct stack_block *prevstackp;
8358 prevstackp = sp->prev;
8359 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8360 sp = ckrealloc((pointer)sp, grosslen);
8361 sp->prev = prevstackp;
8363 stacknxt = sp->space;
8364 stacknleft = newlen;
8365 sstrend = sp->space + newlen;
8368 * Stack marks pointing to the start of the old block
8369 * must be relocated to point to the new block
8372 while (xmark != NULL && xmark->stackp == oldstackp) {
8373 xmark->stackp = stackp;
8374 xmark->stacknxt = stacknxt;
8375 xmark->stacknleft = stacknleft;
8376 xmark = xmark->marknext;
8380 char *oldspace = stacknxt;
8381 int oldlen = stacknleft;
8382 char *p = stalloc(newlen);
8384 /* free the space we just allocated */
8385 stacknxt = memcpy(p, oldspace, oldlen);
8386 stacknleft += newlen;
8390 static void grabstackblock(size_t len)
8392 len = SHELL_ALIGN(len);
8398 * The following routines are somewhat easier to use than the above.
8399 * The user declares a variable of type STACKSTR, which may be declared
8400 * to be a register. The macro STARTSTACKSTR initializes things. Then
8401 * the user uses the macro STPUTC to add characters to the string. In
8402 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8403 * grown as necessary. When the user is done, she can just leave the
8404 * string there and refer to it using stackblock(). Or she can allocate
8405 * the space for it using grabstackstr(). If it is necessary to allow
8406 * someone else to use the stack temporarily and then continue to grow
8407 * the string, the user should use grabstack to allocate the space, and
8408 * then call ungrabstr(p) to return to the previous mode of operation.
8410 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8411 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8412 * is space for at least one character.
8418 size_t len = stackblocksize();
8419 if (herefd >= 0 && len >= 1024) {
8420 full_write(herefd, stackblock(), len);
8421 return stackblock();
8424 return stackblock() + len;
8428 * Called from CHECKSTRSPACE.
8432 makestrspace(size_t newlen, char *p)
8434 size_t len = p - stacknxt;
8435 size_t size = stackblocksize();
8440 size = stackblocksize();
8442 if (nleft >= newlen)
8446 return stackblock() + len;
8450 stnputs(const char *s, size_t n, char *p)
8452 p = makestrspace(n, p);
8453 p = memcpy(p, s, n) + n;
8458 stputs(const char *s, char *p)
8460 return stnputs(s, strlen(s), p);
8468 * number(s) Convert a string of digits to an integer.
8469 * is_number(s) Return true if s is a string of digits.
8473 * prefix -- see if pfx is a prefix of string.
8477 prefix(const char *string, const char *pfx)
8480 if (*pfx++ != *string++)
8483 return (char *) string;
8488 * Convert a string of digits to an integer, printing an error message on
8493 number(const char *s)
8497 sh_error(illnum, s);
8503 * Check for a valid number. This should be elsewhere.
8507 is_number(const char *p)
8512 } while (*++p != '\0');
8518 * Produce a possibly single quoted string suitable as input to the shell.
8519 * The return string is allocated on the stack.
8523 single_quote(const char *s) {
8532 len = strchrnul(s, '\'') - s;
8534 q = p = makestrspace(len + 3, p);
8537 q = memcpy(q, s, len) + len;
8543 len = strspn(s, "'");
8547 q = p = makestrspace(len + 3, p);
8550 q = memcpy(q, s, len) + len;
8559 return stackblock();
8563 * Like strdup but works with the ash stack.
8567 sstrdup(const char *p)
8569 size_t len = strlen(p) + 1;
8570 return memcpy(stalloc(len), p, len);
8575 calcsize(union node *n)
8579 funcblocksize += nodesize[n->type];
8582 calcsize(n->ncmd.redirect);
8583 calcsize(n->ncmd.args);
8584 calcsize(n->ncmd.assign);
8587 sizenodelist(n->npipe.cmdlist);
8592 calcsize(n->nredir.redirect);
8593 calcsize(n->nredir.n);
8600 calcsize(n->nbinary.ch2);
8601 calcsize(n->nbinary.ch1);
8604 calcsize(n->nif.elsepart);
8605 calcsize(n->nif.ifpart);
8606 calcsize(n->nif.test);
8609 funcstringsize += strlen(n->nfor.var) + 1;
8610 calcsize(n->nfor.body);
8611 calcsize(n->nfor.args);
8614 calcsize(n->ncase.cases);
8615 calcsize(n->ncase.expr);
8618 calcsize(n->nclist.body);
8619 calcsize(n->nclist.pattern);
8620 calcsize(n->nclist.next);
8624 sizenodelist(n->narg.backquote);
8625 funcstringsize += strlen(n->narg.text) + 1;
8626 calcsize(n->narg.next);
8633 calcsize(n->nfile.fname);
8634 calcsize(n->nfile.next);
8638 calcsize(n->ndup.vname);
8639 calcsize(n->ndup.next);
8643 calcsize(n->nhere.doc);
8644 calcsize(n->nhere.next);
8647 calcsize(n->nnot.com);
8654 sizenodelist(struct nodelist *lp)
8657 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8665 copynode(union node *n)
8672 funcblock = (char *) funcblock + nodesize[n->type];
8675 new->ncmd.redirect = copynode(n->ncmd.redirect);
8676 new->ncmd.args = copynode(n->ncmd.args);
8677 new->ncmd.assign = copynode(n->ncmd.assign);
8680 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8681 new->npipe.backgnd = n->npipe.backgnd;
8686 new->nredir.redirect = copynode(n->nredir.redirect);
8687 new->nredir.n = copynode(n->nredir.n);
8694 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8695 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8698 new->nif.elsepart = copynode(n->nif.elsepart);
8699 new->nif.ifpart = copynode(n->nif.ifpart);
8700 new->nif.test = copynode(n->nif.test);
8703 new->nfor.var = nodesavestr(n->nfor.var);
8704 new->nfor.body = copynode(n->nfor.body);
8705 new->nfor.args = copynode(n->nfor.args);
8708 new->ncase.cases = copynode(n->ncase.cases);
8709 new->ncase.expr = copynode(n->ncase.expr);
8712 new->nclist.body = copynode(n->nclist.body);
8713 new->nclist.pattern = copynode(n->nclist.pattern);
8714 new->nclist.next = copynode(n->nclist.next);
8718 new->narg.backquote = copynodelist(n->narg.backquote);
8719 new->narg.text = nodesavestr(n->narg.text);
8720 new->narg.next = copynode(n->narg.next);
8727 new->nfile.fname = copynode(n->nfile.fname);
8728 new->nfile.fd = n->nfile.fd;
8729 new->nfile.next = copynode(n->nfile.next);
8733 new->ndup.vname = copynode(n->ndup.vname);
8734 new->ndup.dupfd = n->ndup.dupfd;
8735 new->ndup.fd = n->ndup.fd;
8736 new->ndup.next = copynode(n->ndup.next);
8740 new->nhere.doc = copynode(n->nhere.doc);
8741 new->nhere.fd = n->nhere.fd;
8742 new->nhere.next = copynode(n->nhere.next);
8745 new->nnot.com = copynode(n->nnot.com);
8748 new->type = n->type;
8753 static struct nodelist *
8754 copynodelist(struct nodelist *lp)
8756 struct nodelist *start;
8757 struct nodelist **lpp;
8762 funcblock = (char *) funcblock +
8763 SHELL_ALIGN(sizeof(struct nodelist));
8764 (*lpp)->n = copynode(lp->n);
8766 lpp = &(*lpp)->next;
8774 nodesavestr(char *s)
8776 char *rtn = funcstring;
8778 strcpy(funcstring, s);
8779 funcstring += strlen(s) + 1;
8785 * Free a parse tree.
8789 freefunc(struct funcnode *f)
8791 if (f && --f->count < 0)
8796 static void options(int);
8797 static void setoption(int, int);
8801 * Process the shell command line arguments.
8805 procargs(int argc, char **argv)
8808 const char *xminusc;
8815 for (i = 0; i < NOPTS; i++)
8821 if (*xargv == NULL) {
8823 sh_error(bb_msg_requires_arg, "-c");
8826 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8830 for (i = 0; i < NOPTS; i++)
8831 if (optlist[i] == 2)
8836 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8841 } else if (!sflag) {
8842 setinputfile(*xargv, 0);
8848 shellparam.p = xargv;
8849 #ifdef CONFIG_ASH_GETOPTS
8850 shellparam.optind = 1;
8851 shellparam.optoff = -1;
8853 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8855 shellparam.nparam++;
8868 setinteractive(iflag);
8873 static void minus_o(char *name, int val)
8878 out1str("Current option settings\n");
8879 for (i = 0; i < NOPTS; i++)
8880 out1fmt("%-16s%s\n", optnames(i),
8881 optlist[i] ? "on" : "off");
8883 for (i = 0; i < NOPTS; i++)
8884 if (equal(name, optnames(i))) {
8888 sh_error("Illegal option -o %s", name);
8893 * Process shell options. The global variable argptr contains a pointer
8894 * to the argument list; we advance it past the options.
8898 options(int cmdline)
8906 while ((p = *argptr) != NULL) {
8908 if ((c = *p++) == '-') {
8910 if (p[0] == '\0' || LONE_DASH(p)) {
8912 /* "-" means turn off -x and -v */
8915 /* "--" means reset params */
8916 else if (*argptr == NULL)
8919 break; /* "-" or "--" terminates options */
8921 } else if (c == '+') {
8927 while ((c = *p++) != '\0') {
8928 if (c == 'c' && cmdline) {
8929 minusc = p; /* command is after shell args*/
8930 } else if (c == 'o') {
8931 minus_o(*argptr, val);
8934 } else if (cmdline && (c == '-')) { // long options
8935 if (strcmp(p, "login") == 0)
8947 setoption(int flag, int val)
8951 for (i = 0; i < NOPTS; i++)
8952 if (optletters(i) == flag) {
8956 sh_error("Illegal option -%c", flag);
8963 * Set the shell parameters.
8967 setparam(char **argv)
8973 for (nparam = 0 ; argv[nparam] ; nparam++);
8974 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8976 *ap++ = savestr(*argv++);
8979 freeparam(&shellparam);
8980 shellparam.malloc = 1;
8981 shellparam.nparam = nparam;
8982 shellparam.p = newparam;
8983 #ifdef CONFIG_ASH_GETOPTS
8984 shellparam.optind = 1;
8985 shellparam.optoff = -1;
8991 * Free the list of positional parameters.
8995 freeparam(volatile struct shparam *param)
8999 if (param->malloc) {
9000 for (ap = param->p ; *ap ; ap++)
9009 * The shift builtin command.
9013 shiftcmd(int argc, char **argv)
9020 n = number(argv[1]);
9021 if (n > shellparam.nparam)
9022 sh_error("can't shift that many");
9024 shellparam.nparam -= n;
9025 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9026 if (shellparam.malloc)
9030 while ((*ap2++ = *ap1++) != NULL);
9031 #ifdef CONFIG_ASH_GETOPTS
9032 shellparam.optind = 1;
9033 shellparam.optoff = -1;
9042 * The set command builtin.
9046 setcmd(int argc, char **argv)
9049 return showvars(nullstr, 0, VUNSET);
9053 if (*argptr != NULL) {
9061 #ifdef CONFIG_ASH_GETOPTS
9063 getoptsreset(const char *value)
9065 shellparam.optind = number(value);
9066 shellparam.optoff = -1;
9070 #ifdef CONFIG_LOCALE_SUPPORT
9071 static void change_lc_all(const char *value)
9073 if (value != 0 && *value != 0)
9074 setlocale(LC_ALL, value);
9077 static void change_lc_ctype(const char *value)
9079 if (value != 0 && *value != 0)
9080 setlocale(LC_CTYPE, value);
9085 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9086 /* Roughly copied from bash.. */
9087 static void change_random(const char *value)
9090 /* "get", generate */
9093 rseed = rseed * 1103515245 + 12345;
9094 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9095 /* set without recursion */
9096 setvar(vrandom.text, buf, VNOFUNC);
9097 vrandom.flags &= ~VNOFUNC;
9100 rseed = strtoul(value, (char **)NULL, 10);
9106 #ifdef CONFIG_ASH_GETOPTS
9108 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9117 if(*param_optind < 1)
9119 optnext = optfirst + *param_optind - 1;
9121 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9124 p = optnext[-1] + *optoff;
9125 if (p == NULL || *p == '\0') {
9126 /* Current word is done, advance */
9128 if (p == NULL || *p != '-' || *++p == '\0') {
9135 if (LONE_DASH(p)) /* check for "--" */
9140 for (q = optstr; *q != c; ) {
9142 if (optstr[0] == ':') {
9145 err |= setvarsafe("OPTARG", s, 0);
9147 fprintf(stderr, "Illegal option -%c\n", c);
9148 (void) unsetvar("OPTARG");
9158 if (*p == '\0' && (p = *optnext) == NULL) {
9159 if (optstr[0] == ':') {
9162 err |= setvarsafe("OPTARG", s, 0);
9165 fprintf(stderr, "No arg for -%c option\n", c);
9166 (void) unsetvar("OPTARG");
9174 err |= setvarsafe("OPTARG", p, 0);
9177 err |= setvarsafe("OPTARG", nullstr, 0);
9180 *optoff = p ? p - *(optnext - 1) : -1;
9181 *param_optind = optnext - optfirst + 1;
9182 fmtstr(s, sizeof(s), "%d", *param_optind);
9183 err |= setvarsafe("OPTIND", s, VNOFUNC);
9186 err |= setvarsafe(optvar, s, 0);
9197 * The getopts builtin. Shellparam.optnext points to the next argument
9198 * to be processed. Shellparam.optptr points to the next character to
9199 * be processed in the current argument. If shellparam.optnext is NULL,
9200 * then it's the first time getopts has been called.
9204 getoptscmd(int argc, char **argv)
9209 sh_error("Usage: getopts optstring var [arg]");
9210 else if (argc == 3) {
9211 optbase = shellparam.p;
9212 if (shellparam.optind > shellparam.nparam + 1) {
9213 shellparam.optind = 1;
9214 shellparam.optoff = -1;
9219 if (shellparam.optind > argc - 2) {
9220 shellparam.optind = 1;
9221 shellparam.optoff = -1;
9225 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9226 &shellparam.optoff);
9228 #endif /* CONFIG_ASH_GETOPTS */
9231 * XXX - should get rid of. have all builtins use getopt(3). the
9232 * library getopt must have the BSD extension static variable "optreset"
9233 * otherwise it can't be used within the shell safely.
9235 * Standard option processing (a la getopt) for builtin routines. The
9236 * only argument that is passed to nextopt is the option string; the
9237 * other arguments are unnecessary. It return the character, or '\0' on
9242 nextopt(const char *optstring)
9248 if ((p = optptr) == NULL || *p == '\0') {
9250 if (p == NULL || *p != '-' || *++p == '\0')
9253 if (LONE_DASH(p)) /* check for "--" */
9257 for (q = optstring ; *q != c ; ) {
9259 sh_error("Illegal option -%c", c);
9264 if (*p == '\0' && (p = *argptr++) == NULL)
9265 sh_error("No arg for -%c option", c);
9277 outstr(const char *p, FILE *file)
9302 outcslow(int c, FILE *dest)
9312 out1fmt(const char *fmt, ...)
9319 r = vprintf(fmt, ap);
9327 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9334 ret = vsnprintf(outbuf, length, fmt, ap);
9346 * Shell command parser.
9349 #define EOFMARKLEN 79
9353 struct heredoc *next; /* next here document in list */
9354 union node *here; /* redirection node */
9355 char *eofmark; /* string indicating end of input */
9356 int striptabs; /* if set, strip leading tabs */
9361 static struct heredoc *heredoclist; /* list of here documents to read */
9364 static union node *list(int);
9365 static union node *andor(void);
9366 static union node *pipeline(void);
9367 static union node *command(void);
9368 static union node *simplecmd(void);
9369 static union node *makename(void);
9370 static void parsefname(void);
9371 static void parseheredoc(void);
9372 static char peektoken(void);
9373 static int readtoken(void);
9374 static int xxreadtoken(void);
9375 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9376 static int noexpand(char *);
9377 static void synexpect(int) ATTRIBUTE_NORETURN;
9378 static void synerror(const char *) ATTRIBUTE_NORETURN;
9379 static void setprompt(int);
9385 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9386 * valid parse tree indicating a blank line.)
9390 parsecmd(int interact)
9395 doprompt = interact;
9397 setprompt(doprompt);
9412 union node *n1, *n2, *n3;
9415 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9416 if (nlflag == 2 && peektoken())
9422 if (tok == TBACKGND) {
9423 if (n2->type == NPIPE) {
9424 n2->npipe.backgnd = 1;
9426 if (n2->type != NREDIR) {
9427 n3 = stalloc(sizeof(struct nredir));
9429 n3->nredir.redirect = NULL;
9432 n2->type = NBACKGND;
9439 n3 = (union node *)stalloc(sizeof (struct nbinary));
9441 n3->nbinary.ch1 = n1;
9442 n3->nbinary.ch2 = n2;
9458 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9466 pungetc(); /* push back EOF on input */
9482 union node *n1, *n2, *n3;
9487 if ((t = readtoken()) == TAND) {
9489 } else if (t == TOR) {
9495 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9497 n3 = (union node *)stalloc(sizeof (struct nbinary));
9499 n3->nbinary.ch1 = n1;
9500 n3->nbinary.ch2 = n2;
9510 union node *n1, *n2, *pipenode;
9511 struct nodelist *lp, *prev;
9515 TRACE(("pipeline: entered\n"));
9516 if (readtoken() == TNOT) {
9518 checkkwd = CHKKWD | CHKALIAS;
9522 if (readtoken() == TPIPE) {
9523 pipenode = (union node *)stalloc(sizeof (struct npipe));
9524 pipenode->type = NPIPE;
9525 pipenode->npipe.backgnd = 0;
9526 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9527 pipenode->npipe.cmdlist = lp;
9531 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9532 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9535 } while (readtoken() == TPIPE);
9541 n2 = (union node *)stalloc(sizeof (struct nnot));
9554 union node *n1, *n2;
9555 union node *ap, **app;
9556 union node *cp, **cpp;
9557 union node *redir, **rpp;
9564 switch (readtoken()) {
9569 n1 = (union node *)stalloc(sizeof (struct nif));
9571 n1->nif.test = list(0);
9572 if (readtoken() != TTHEN)
9574 n1->nif.ifpart = list(0);
9576 while (readtoken() == TELIF) {
9577 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9578 n2 = n2->nif.elsepart;
9580 n2->nif.test = list(0);
9581 if (readtoken() != TTHEN)
9583 n2->nif.ifpart = list(0);
9585 if (lasttoken == TELSE)
9586 n2->nif.elsepart = list(0);
9588 n2->nif.elsepart = NULL;
9596 n1 = (union node *)stalloc(sizeof (struct nbinary));
9597 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9598 n1->nbinary.ch1 = list(0);
9599 if ((got=readtoken()) != TDO) {
9600 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9603 n1->nbinary.ch2 = list(0);
9608 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9609 synerror("Bad for loop variable");
9610 n1 = (union node *)stalloc(sizeof (struct nfor));
9612 n1->nfor.var = wordtext;
9613 checkkwd = CHKKWD | CHKALIAS;
9614 if (readtoken() == TIN) {
9616 while (readtoken() == TWORD) {
9617 n2 = (union node *)stalloc(sizeof (struct narg));
9619 n2->narg.text = wordtext;
9620 n2->narg.backquote = backquotelist;
9622 app = &n2->narg.next;
9626 if (lasttoken != TNL && lasttoken != TSEMI)
9629 n2 = (union node *)stalloc(sizeof (struct narg));
9631 n2->narg.text = (char *)dolatstr;
9632 n2->narg.backquote = NULL;
9633 n2->narg.next = NULL;
9636 * Newline or semicolon here is optional (but note
9637 * that the original Bourne shell only allowed NL).
9639 if (lasttoken != TNL && lasttoken != TSEMI)
9642 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9643 if (readtoken() != TDO)
9645 n1->nfor.body = list(0);
9649 n1 = (union node *)stalloc(sizeof (struct ncase));
9651 if (readtoken() != TWORD)
9653 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9655 n2->narg.text = wordtext;
9656 n2->narg.backquote = backquotelist;
9657 n2->narg.next = NULL;
9659 checkkwd = CHKKWD | CHKALIAS;
9660 } while (readtoken() == TNL);
9661 if (lasttoken != TIN)
9663 cpp = &n1->ncase.cases;
9665 checkkwd = CHKNL | CHKKWD;
9668 if (lasttoken == TLP)
9670 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9672 app = &cp->nclist.pattern;
9674 *app = ap = (union node *)stalloc(sizeof (struct narg));
9676 ap->narg.text = wordtext;
9677 ap->narg.backquote = backquotelist;
9678 if (readtoken() != TPIPE)
9680 app = &ap->narg.next;
9683 ap->narg.next = NULL;
9684 if (lasttoken != TRP)
9686 cp->nclist.body = list(2);
9688 cpp = &cp->nclist.next;
9690 checkkwd = CHKNL | CHKKWD;
9691 if ((t = readtoken()) != TESAC) {
9693 synexpect(TENDCASE);
9701 n1 = (union node *)stalloc(sizeof (struct nredir));
9702 n1->type = NSUBSHELL;
9703 n1->nredir.n = list(0);
9704 n1->nredir.redirect = NULL;
9717 if (readtoken() != t)
9721 /* Now check for redirection which may follow command */
9722 checkkwd = CHKKWD | CHKALIAS;
9724 while (readtoken() == TREDIR) {
9725 *rpp = n2 = redirnode;
9726 rpp = &n2->nfile.next;
9732 if (n1->type != NSUBSHELL) {
9733 n2 = (union node *)stalloc(sizeof (struct nredir));
9738 n1->nredir.redirect = redir;
9747 union node *args, **app;
9748 union node *n = NULL;
9749 union node *vars, **vpp;
9750 union node **rpp, *redir;
9760 savecheckkwd = CHKALIAS;
9762 checkkwd = savecheckkwd;
9763 switch (readtoken()) {
9765 n = (union node *)stalloc(sizeof (struct narg));
9767 n->narg.text = wordtext;
9768 n->narg.backquote = backquotelist;
9769 if (savecheckkwd && isassignment(wordtext)) {
9771 vpp = &n->narg.next;
9774 app = &n->narg.next;
9779 *rpp = n = redirnode;
9780 rpp = &n->nfile.next;
9781 parsefname(); /* read name of redirection file */
9785 args && app == &args->narg.next &&
9788 struct builtincmd *bcmd;
9791 /* We have a function */
9792 if (readtoken() != TRP)
9794 name = n->narg.text;
9796 !goodname(name) || (
9797 (bcmd = find_builtin(name)) &&
9798 IS_BUILTIN_SPECIAL(bcmd)
9801 synerror("Bad function name");
9803 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9804 n->narg.next = command();
9817 n = (union node *)stalloc(sizeof (struct ncmd));
9819 n->ncmd.args = args;
9820 n->ncmd.assign = vars;
9821 n->ncmd.redirect = redir;
9830 n = (union node *)stalloc(sizeof (struct narg));
9832 n->narg.next = NULL;
9833 n->narg.text = wordtext;
9834 n->narg.backquote = backquotelist;
9838 void fixredir(union node *n, const char *text, int err)
9840 TRACE(("Fix redir %s %d\n", text, err));
9842 n->ndup.vname = NULL;
9844 if (is_digit(text[0]) && text[1] == '\0')
9845 n->ndup.dupfd = digit_val(text[0]);
9846 else if (LONE_DASH(text))
9851 synerror("Bad fd number");
9853 n->ndup.vname = makename();
9861 union node *n = redirnode;
9863 if (readtoken() != TWORD)
9865 if (n->type == NHERE) {
9866 struct heredoc *here = heredoc;
9872 TRACE(("Here document %d\n", n->type));
9873 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9874 synerror("Illegal eof marker for << redirection");
9875 rmescapes(wordtext);
9876 here->eofmark = wordtext;
9878 if (heredoclist == NULL)
9881 for (p = heredoclist ; p->next ; p = p->next);
9884 } else if (n->type == NTOFD || n->type == NFROMFD) {
9885 fixredir(n, wordtext, 0);
9887 n->nfile.fname = makename();
9893 * Input any here documents.
9899 struct heredoc *here;
9909 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9910 here->eofmark, here->striptabs);
9911 n = (union node *)stalloc(sizeof (struct narg));
9912 n->narg.type = NARG;
9913 n->narg.next = NULL;
9914 n->narg.text = wordtext;
9915 n->narg.backquote = backquotelist;
9916 here->here->nhere.doc = n;
9921 static char peektoken(void)
9927 return tokname_array[t][0];
9935 int alreadyseen = tokpushback;
9938 #ifdef CONFIG_ASH_ALIAS
9947 if (checkkwd & CHKNL) {
9954 if (t != TWORD || quoteflag) {
9959 * check for keywords
9961 if (checkkwd & CHKKWD) {
9962 const char *const *pp;
9964 if ((pp = findkwd(wordtext))) {
9965 lasttoken = t = pp - tokname_array;
9966 TRACE(("keyword %s recognized\n", tokname(t)));
9971 if (checkkwd & CHKALIAS) {
9972 #ifdef CONFIG_ASH_ALIAS
9974 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9976 pushstring(ap->val, ap);
9986 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9988 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9995 * Read the next input token.
9996 * If the token is a word, we set backquotelist to the list of cmds in
9997 * backquotes. We set quoteflag to true if any part of the word was
9999 * If the token is TREDIR, then we set redirnode to a structure containing
10001 * In all cases, the variable startlinno is set to the number of the line
10002 * on which the token starts.
10004 * [Change comment: here documents and internal procedures]
10005 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10006 * word parsing code into a separate routine. In this case, readtoken
10007 * doesn't need to have any internal procedures, but parseword does.
10008 * We could also make parseoperator in essence the main routine, and
10009 * have parseword (readtoken1?) handle both words and redirection.]
10012 #define NEW_xxreadtoken
10013 #ifdef NEW_xxreadtoken
10015 /* singles must be first! */
10016 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10018 static const char xxreadtoken_tokens[] = {
10019 TNL, TLP, TRP, /* only single occurrence allowed */
10020 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10021 TEOF, /* corresponds to trailing nul */
10022 TAND, TOR, TENDCASE, /* if double occurrence */
10025 #define xxreadtoken_doubles \
10026 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10027 #define xxreadtoken_singles \
10028 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10030 static int xxreadtoken(void)
10041 startlinno = plinno;
10042 for (;;) { /* until token or start of word found */
10045 if ((c != ' ') && (c != '\t')
10046 #ifdef CONFIG_ASH_ALIAS
10051 while ((c = pgetc()) != '\n' && c != PEOF);
10053 } else if (c == '\\') {
10054 if (pgetc() != '\n') {
10058 startlinno = ++plinno;
10063 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10068 needprompt = doprompt;
10071 p = strchr(xxreadtoken_chars, c);
10074 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10077 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10078 if (pgetc() == *p) { /* double occurrence? */
10079 p += xxreadtoken_doubles + 1;
10086 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10094 #define RETURN(token) return lasttoken = token
10108 startlinno = plinno;
10109 for (;;) { /* until token or start of word found */
10112 case ' ': case '\t':
10113 #ifdef CONFIG_ASH_ALIAS
10118 while ((c = pgetc()) != '\n' && c != PEOF);
10122 if (pgetc() == '\n') {
10123 startlinno = ++plinno;
10132 needprompt = doprompt;
10137 if (pgetc() == '&')
10142 if (pgetc() == '|')
10147 if (pgetc() == ';')
10160 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10163 #endif /* NEW_xxreadtoken */
10167 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10168 * is not NULL, read a here document. In the latter case, eofmark is the
10169 * word which marks the end of the document and striptabs is true if
10170 * leading tabs should be stripped from the document. The argument firstc
10171 * is the first character of the input token or document.
10173 * Because C does not have internal subroutines, I have simulated them
10174 * using goto's to implement the subroutine linkage. The following macros
10175 * will run code that appears at the end of readtoken1.
10178 #define CHECKEND() {goto checkend; checkend_return:;}
10179 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10180 #define PARSESUB() {goto parsesub; parsesub_return:;}
10181 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10182 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10183 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10186 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10191 char line[EOFMARKLEN + 1];
10192 struct nodelist *bqlist = 0;
10195 int varnest = 0; /* levels of variables expansion */
10196 int arinest = 0; /* levels of arithmetic expansion */
10197 int parenlevel = 0; /* levels of parens in arithmetic */
10198 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10200 int prevsyntax = 0; /* syntax before arithmetic */
10202 /* Avoid longjmp clobbering */
10208 (void) &parenlevel;
10211 (void) &prevsyntax;
10215 startlinno = plinno;
10217 if (syntax == DQSYNTAX)
10226 STARTSTACKSTR(out);
10227 loop: { /* for each line, until end of word */
10228 CHECKEND(); /* set c to PEOF if at end of here document */
10229 for (;;) { /* until end of line or end of word */
10230 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10231 switch (SIT(c, syntax)) {
10232 case CNL: /* '\n' */
10233 if (syntax == BASESYNTAX)
10234 goto endword; /* exit outer loop */
10240 goto loop; /* continue outer loop */
10245 if (eofmark == NULL || dblquote)
10246 USTPUTC(CTLESC, out);
10249 case CBACK: /* backslash */
10252 USTPUTC(CTLESC, out);
10253 USTPUTC('\\', out);
10255 } else if (c == '\n') {
10260 c != '\\' && c != '`' &&
10265 USTPUTC(CTLESC, out);
10266 USTPUTC('\\', out);
10268 if (SIT(c, SQSYNTAX) == CCTL)
10269 USTPUTC(CTLESC, out);
10277 if (eofmark == NULL) {
10278 USTPUTC(CTLQUOTEMARK, out);
10286 if (eofmark != NULL && arinest == 0 &&
10290 if (dqvarnest == 0) {
10291 syntax = BASESYNTAX;
10298 case CVAR: /* '$' */
10299 PARSESUB(); /* parse substitution */
10301 case CENDVAR: /* '}' */
10304 if (dqvarnest > 0) {
10307 USTPUTC(CTLENDVAR, out);
10312 #ifdef CONFIG_ASH_MATH_SUPPORT
10313 case CLP: /* '(' in arithmetic */
10317 case CRP: /* ')' in arithmetic */
10318 if (parenlevel > 0) {
10322 if (pgetc() == ')') {
10323 if (--arinest == 0) {
10324 USTPUTC(CTLENDARI, out);
10325 syntax = prevsyntax;
10326 if (syntax == DQSYNTAX)
10334 * unbalanced parens
10335 * (don't 2nd guess - no error)
10343 case CBQUOTE: /* '`' */
10347 goto endword; /* exit outer loop */
10352 goto endword; /* exit outer loop */
10353 #ifdef CONFIG_ASH_ALIAS
10363 #ifdef CONFIG_ASH_MATH_SUPPORT
10364 if (syntax == ARISYNTAX)
10365 synerror("Missing '))'");
10367 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10368 synerror("Unterminated quoted string");
10369 if (varnest != 0) {
10370 startlinno = plinno;
10372 synerror("Missing '}'");
10374 USTPUTC('\0', out);
10375 len = out - (char *)stackblock();
10376 out = stackblock();
10377 if (eofmark == NULL) {
10378 if ((c == '>' || c == '<')
10381 && (*out == '\0' || is_digit(*out))) {
10383 return lasttoken = TREDIR;
10388 quoteflag = quotef;
10389 backquotelist = bqlist;
10390 grabstackblock(len);
10392 return lasttoken = TWORD;
10393 /* end of readtoken routine */
10398 * Check to see whether we are at the end of the here document. When this
10399 * is called, c is set to the first character of the next input line. If
10400 * we are at the end of the here document, this routine sets the c to PEOF.
10405 #ifdef CONFIG_ASH_ALIAS
10411 while (c == '\t') {
10415 if (c == *eofmark) {
10416 if (pfgets(line, sizeof line) != NULL) {
10420 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10421 if (*p == '\n' && *q == '\0') {
10424 needprompt = doprompt;
10426 pushstring(line, NULL);
10431 goto checkend_return;
10436 * Parse a redirection operator. The variable "out" points to a string
10437 * specifying the fd to be redirected. The variable "c" contains the
10438 * first character of the redirection operator.
10445 np = (union node *)stalloc(sizeof (struct nfile));
10450 np->type = NAPPEND;
10452 np->type = NCLOBBER;
10459 } else { /* c == '<' */
10461 switch (c = pgetc()) {
10463 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10464 np = (union node *)stalloc(sizeof (struct nhere));
10468 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10469 heredoc->here = np;
10470 if ((c = pgetc()) == '-') {
10471 heredoc->striptabs = 1;
10473 heredoc->striptabs = 0;
10479 np->type = NFROMFD;
10483 np->type = NFROMTO;
10493 np->nfile.fd = digit_val(fd);
10495 goto parseredir_return;
10500 * Parse a substitution. At this point, we have read the dollar sign
10501 * and nothing else.
10509 static const char types[] = "}-+?=";
10513 c <= PEOA_OR_PEOF ||
10514 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10518 } else if (c == '(') { /* $(command) or $((arith)) */
10519 if (pgetc() == '(') {
10520 #ifdef CONFIG_ASH_MATH_SUPPORT
10523 synerror("We unsupport $((arith))");
10530 USTPUTC(CTLVAR, out);
10531 typeloc = out - (char *)stackblock();
10532 USTPUTC(VSNORMAL, out);
10533 subtype = VSNORMAL;
10537 if ((c = pgetc()) == '}')
10540 subtype = VSLENGTH;
10545 if (c > PEOA_OR_PEOF && is_name(c)) {
10549 } while (c > PEOA_OR_PEOF && is_in_name(c));
10550 } else if (is_digit(c)) {
10554 } while (is_digit(c));
10556 else if (is_special(c)) {
10561 badsub: synerror("Bad substitution");
10565 if (subtype == 0) {
10572 p = strchr(types, c);
10575 subtype = p - types + VSNORMAL;
10581 subtype = c == '#' ? VSTRIMLEFT :
10594 if (dblquote || arinest)
10596 *((char *)stackblock() + typeloc) = subtype | flags;
10597 if (subtype != VSNORMAL) {
10599 if (dblquote || arinest) {
10604 goto parsesub_return;
10609 * Called to parse command substitutions. Newstyle is set if the command
10610 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10611 * list of commands (passed by reference), and savelen is the number of
10612 * characters on the top of the stack which must be preserved.
10616 struct nodelist **nlpp;
10619 char *volatile str;
10620 struct jmploc jmploc;
10621 struct jmploc *volatile savehandler;
10623 int saveprompt = 0;
10625 (void) &saveprompt;
10628 savepbq = parsebackquote;
10629 if (setjmp(jmploc.loc)) {
10632 parsebackquote = 0;
10633 handler = savehandler;
10634 longjmp(handler->loc, 1);
10638 savelen = out - (char *)stackblock();
10640 str = ckmalloc(savelen);
10641 memcpy(str, stackblock(), savelen);
10643 savehandler = handler;
10647 /* We must read until the closing backquote, giving special
10648 treatment to some slashes, and then push the string and
10649 reread it as input, interpreting it normally. */
10656 STARTSTACKSTR(pout);
10661 switch (pc = pgetc()) {
10666 if ((pc = pgetc()) == '\n') {
10671 * If eating a newline, avoid putting
10672 * the newline into the new character
10673 * stream (via the STPUTC after the
10678 if (pc != '\\' && pc != '`' && pc != '$'
10679 && (!dblquote || pc != '"'))
10680 STPUTC('\\', pout);
10681 if (pc > PEOA_OR_PEOF) {
10687 #ifdef CONFIG_ASH_ALIAS
10690 startlinno = plinno;
10691 synerror("EOF in backquote substitution");
10695 needprompt = doprompt;
10704 STPUTC('\0', pout);
10705 psavelen = pout - (char *)stackblock();
10706 if (psavelen > 0) {
10707 pstr = grabstackstr(pout);
10708 setinputstring(pstr);
10713 nlpp = &(*nlpp)->next;
10714 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10715 (*nlpp)->next = NULL;
10716 parsebackquote = oldstyle;
10719 saveprompt = doprompt;
10726 doprompt = saveprompt;
10728 if (readtoken() != TRP)
10735 * Start reading from old file again, ignoring any pushed back
10736 * tokens left from the backquote parsing
10741 while (stackblocksize() <= savelen)
10743 STARTSTACKSTR(out);
10745 memcpy(out, str, savelen);
10746 STADJUST(savelen, out);
10752 parsebackquote = savepbq;
10753 handler = savehandler;
10754 if (arinest || dblquote)
10755 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10757 USTPUTC(CTLBACKQ, out);
10759 goto parsebackq_oldreturn;
10761 goto parsebackq_newreturn;
10764 #ifdef CONFIG_ASH_MATH_SUPPORT
10766 * Parse an arithmetic expansion (indicate start of one and set state)
10770 if (++arinest == 1) {
10771 prevsyntax = syntax;
10772 syntax = ARISYNTAX;
10773 USTPUTC(CTLARI, out);
10780 * we collapse embedded arithmetic expansion to
10781 * parenthesis, which should be equivalent
10785 goto parsearith_return;
10789 } /* end of readtoken */
10794 * Returns true if the text contains nothing to expand (no dollar signs
10799 noexpand(char *text)
10805 while ((c = *p++) != '\0') {
10806 if (c == CTLQUOTEMARK)
10810 else if (SIT(c, BASESYNTAX) == CCTL)
10818 * Return of a legal variable name (a letter or underscore followed by zero or
10819 * more letters, underscores, and digits).
10823 endofname(const char *name)
10831 if (! is_in_name(*p))
10839 * Called when an unexpected token is read during the parse. The argument
10840 * is the token that is expected, or -1 if more than one type of token can
10841 * occur at this point.
10844 static void synexpect(int token)
10849 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10851 sprintf(msg + l, " (expecting %s)", tokname(token));
10857 synerror(const char *msg)
10859 sh_error("Syntax error: %s", msg);
10865 * called by editline -- any expansions to the prompt
10866 * should be added here.
10869 #ifdef CONFIG_ASH_EXPAND_PRMT
10870 static const char *
10871 expandstr(const char *ps)
10875 /* XXX Fix (char *) cast. */
10876 setinputstring((char *)ps);
10877 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10880 n.narg.type = NARG;
10881 n.narg.next = NULL;
10882 n.narg.text = wordtext;
10883 n.narg.backquote = backquotelist;
10885 expandarg(&n, NULL, 0);
10886 return stackblock();
10890 static void setprompt(int whichprompt)
10892 const char *prompt;
10893 #ifdef CONFIG_ASH_EXPAND_PRMT
10894 struct stackmark smark;
10899 switch (whichprompt) {
10909 #ifdef CONFIG_ASH_EXPAND_PRMT
10910 setstackmark(&smark);
10911 stalloc(stackblocksize());
10913 putprompt(expandstr(prompt));
10914 #ifdef CONFIG_ASH_EXPAND_PRMT
10915 popstackmark(&smark);
10920 static const char *const *findkwd(const char *s)
10922 return bsearch(s, tokname_array + KWDOFFSET,
10923 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10924 sizeof(const char *), pstrcmp);
10930 * Code for dealing with input/output redirection.
10933 #define EMPTY -2 /* marks an unused slot in redirtab */
10935 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10937 # define PIPESIZE PIPE_BUF
10941 * Open a file in noclobber mode.
10942 * The code was copied from bash.
10944 static int noclobberopen(const char *fname)
10947 struct stat finfo, finfo2;
10950 * If the file exists and is a regular file, return an error
10953 r = stat(fname, &finfo);
10954 if (r == 0 && S_ISREG(finfo.st_mode)) {
10960 * If the file was not present (r != 0), make sure we open it
10961 * exclusively so that if it is created before we open it, our open
10962 * will fail. Make sure that we do not truncate an existing file.
10963 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10964 * file was not a regular file, we leave O_EXCL off.
10967 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10968 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10970 /* If the open failed, return the file descriptor right away. */
10975 * OK, the open succeeded, but the file may have been changed from a
10976 * non-regular file to a regular file between the stat and the open.
10977 * We are assuming that the O_EXCL open handles the case where FILENAME
10978 * did not exist and is symlinked to an existing file between the stat
10983 * If we can open it and fstat the file descriptor, and neither check
10984 * revealed that it was a regular file, and the file has not been
10985 * replaced, return the file descriptor.
10987 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10988 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10991 /* The file has been replaced. badness. */
10998 * Handle here documents. Normally we fork off a process to write the
10999 * data to a pipe. If the document is short, we can stuff the data in
11000 * the pipe without forking.
11003 static int openhere(union node *redir)
11009 sh_error("Pipe call failed");
11010 if (redir->type == NHERE) {
11011 len = strlen(redir->nhere.doc->narg.text);
11012 if (len <= PIPESIZE) {
11013 full_write(pip[1], redir->nhere.doc->narg.text, len);
11017 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11019 signal(SIGINT, SIG_IGN);
11020 signal(SIGQUIT, SIG_IGN);
11021 signal(SIGHUP, SIG_IGN);
11023 signal(SIGTSTP, SIG_IGN);
11025 signal(SIGPIPE, SIG_DFL);
11026 if (redir->type == NHERE)
11027 full_write(pip[1], redir->nhere.doc->narg.text, len);
11029 expandhere(redir->nhere.doc, pip[1]);
11038 openredirect(union node *redir)
11043 switch (redir->nfile.type) {
11045 fname = redir->nfile.expfname;
11046 if ((f = open(fname, O_RDONLY)) < 0)
11050 fname = redir->nfile.expfname;
11051 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11055 /* Take care of noclobber mode. */
11057 fname = redir->nfile.expfname;
11058 if ((f = noclobberopen(fname)) < 0)
11064 fname = redir->nfile.expfname;
11065 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11069 fname = redir->nfile.expfname;
11070 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11077 /* Fall through to eliminate warning. */
11084 f = openhere(redir);
11090 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11092 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11095 static void dupredirect(union node *redir, int f)
11097 int fd = redir->nfile.fd;
11099 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11100 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11101 copyfd(redir->ndup.dupfd, fd);
11114 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11115 * old file descriptors are stashed away so that the redirection can be
11116 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11117 * standard output, and the standard error if it becomes a duplicate of
11118 * stdout, is saved in memory.
11122 redirect(union node *redir, int flags)
11125 struct redirtab *sv;
11136 if (flags & REDIR_PUSH) {
11137 struct redirtab *q;
11138 q = ckmalloc(sizeof (struct redirtab));
11139 q->next = redirlist;
11141 q->nullredirs = nullredirs - 1;
11142 for (i = 0 ; i < 10 ; i++)
11143 q->renamed[i] = EMPTY;
11150 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11151 n->ndup.dupfd == fd)
11152 continue; /* redirect from/to same file descriptor */
11154 newfd = openredirect(n);
11157 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11158 i = fcntl(fd, F_DUPFD, 10);
11165 sh_error("%d: %m", fd);
11175 dupredirect(n, newfd);
11176 } while ((n = n->nfile.next));
11178 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11179 preverrout_fd = sv->renamed[2];
11184 * Undo the effects of the last redirection.
11190 struct redirtab *rp;
11193 if (--nullredirs >= 0)
11197 for (i = 0 ; i < 10 ; i++) {
11198 if (rp->renamed[i] != EMPTY) {
11201 copyfd(rp->renamed[i], i);
11203 close(rp->renamed[i]);
11206 redirlist = rp->next;
11207 nullredirs = rp->nullredirs;
11213 * Undo all redirections. Called on error or interrupt.
11217 * Discard all saved file descriptors.
11221 clearredir(int drop)
11233 * Copy a file descriptor to be >= to. Returns -1
11234 * if the source file descriptor is closed, EMPTY if there are no unused
11235 * file descriptors left.
11239 copyfd(int from, int to)
11243 newfd = fcntl(from, F_DUPFD, to);
11245 if (errno == EMFILE)
11248 sh_error("%d: %m", from);
11255 redirectsafe(union node *redir, int flags)
11258 volatile int saveint;
11259 struct jmploc *volatile savehandler = handler;
11260 struct jmploc jmploc;
11263 if (!(err = setjmp(jmploc.loc) * 2)) {
11265 redirect(redir, flags);
11267 handler = savehandler;
11268 if (err && exception != EXERROR)
11269 longjmp(handler->loc, 1);
11270 RESTOREINT(saveint);
11277 static void shtree(union node *, int, char *, FILE*);
11278 static void shcmd(union node *, FILE *);
11279 static void sharg(union node *, FILE *);
11280 static void indent(int, char *, FILE *);
11281 static void trstring(char *);
11285 showtree(union node *n)
11287 trputs("showtree called\n");
11288 shtree(n, 1, NULL, stdout);
11293 shtree(union node *n, int ind, char *pfx, FILE *fp)
11295 struct nodelist *lp;
11301 indent(ind, pfx, fp);
11312 shtree(n->nbinary.ch1, ind, NULL, fp);
11315 shtree(n->nbinary.ch2, ind, NULL, fp);
11323 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11328 if (n->npipe.backgnd)
11334 fprintf(fp, "<node type %d>", n->type);
11343 shcmd(union node *cmd, FILE *fp)
11351 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11357 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11360 switch (np->nfile.type) {
11361 case NTO: s = ">"; dftfd = 1; break;
11362 case NCLOBBER: s = ">|"; dftfd = 1; break;
11363 case NAPPEND: s = ">>"; dftfd = 1; break;
11364 case NTOFD: s = ">&"; dftfd = 1; break;
11365 case NFROM: s = "<"; dftfd = 0; break;
11366 case NFROMFD: s = "<&"; dftfd = 0; break;
11367 case NFROMTO: s = "<>"; dftfd = 0; break;
11368 default: s = "*error*"; dftfd = 0; break;
11370 if (np->nfile.fd != dftfd)
11371 fprintf(fp, "%d", np->nfile.fd);
11373 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11374 fprintf(fp, "%d", np->ndup.dupfd);
11376 sharg(np->nfile.fname, fp);
11385 sharg(union node *arg, FILE *fp)
11388 struct nodelist *bqlist;
11391 if (arg->type != NARG) {
11392 out1fmt("<node type %d>\n", arg->type);
11395 bqlist = arg->narg.backquote;
11396 for (p = arg->narg.text ; *p ; p++) {
11405 if (subtype == VSLENGTH)
11411 if (subtype & VSNUL)
11414 switch (subtype & VSTYPE) {
11433 case VSTRIMLEFTMAX:
11440 case VSTRIMRIGHTMAX:
11447 out1fmt("<subtype %d>", subtype);
11454 case CTLBACKQ|CTLQUOTE:
11457 shtree(bqlist->n, -1, NULL, fp);
11469 indent(int amount, char *pfx, FILE *fp)
11473 for (i = 0 ; i < amount ; i++) {
11474 if (pfx && i == amount - 1)
11495 putc(c, tracefile);
11499 trace(const char *fmt, ...)
11506 (void) vfprintf(tracefile, fmt, va);
11511 tracev(const char *fmt, va_list va)
11515 (void) vfprintf(tracefile, fmt, va);
11520 trputs(const char *s)
11524 fputs(s, tracefile);
11536 putc('"', tracefile);
11537 for (p = s ; *p ; p++) {
11539 case '\n': c = 'n'; goto backslash;
11540 case '\t': c = 't'; goto backslash;
11541 case '\r': c = 'r'; goto backslash;
11542 case '"': c = '"'; goto backslash;
11543 case '\\': c = '\\'; goto backslash;
11544 case CTLESC: c = 'e'; goto backslash;
11545 case CTLVAR: c = 'v'; goto backslash;
11546 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11547 case CTLBACKQ: c = 'q'; goto backslash;
11548 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11549 backslash: putc('\\', tracefile);
11550 putc(c, tracefile);
11553 if (*p >= ' ' && *p <= '~')
11554 putc(*p, tracefile);
11556 putc('\\', tracefile);
11557 putc(*p >> 6 & 03, tracefile);
11558 putc(*p >> 3 & 07, tracefile);
11559 putc(*p & 07, tracefile);
11564 putc('"', tracefile);
11576 putc(' ', tracefile);
11578 putc('\n', tracefile);
11594 /* leave open because libedit might be using it */
11597 scopy("./trace", s);
11599 if (!freopen(s, "a", tracefile)) {
11600 fprintf(stderr, "Can't re-open %s\n", s);
11605 if ((tracefile = fopen(s, "a")) == NULL) {
11606 fprintf(stderr, "Can't open %s\n", s);
11612 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11613 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11615 setlinebuf(tracefile);
11616 fputs("\nTracing started.\n", tracefile);
11624 * Sigmode records the current value of the signal handlers for the various
11625 * modes. A value of zero means that the current handler is not known.
11626 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11629 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11630 #define S_CATCH 2 /* signal is caught */
11631 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11632 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11633 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11638 * The trap builtin.
11642 trapcmd(int argc, char **argv)
11651 for (signo = 0 ; signo < NSIG ; signo++) {
11652 if (trap[signo] != NULL) {
11655 sn = get_signame(signo);
11656 out1fmt("trap -- %s %s\n",
11657 single_quote(trap[signo]), sn);
11667 if ((signo = get_signum(*ap)) < 0)
11668 sh_error("%s: bad trap", *ap);
11671 if (LONE_DASH(action))
11674 action = savestr(action);
11677 ckfree(trap[signo]);
11678 trap[signo] = action;
11689 * Clear traps on a fork.
11697 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11698 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11702 if (tp != &trap[0])
11703 setsignal(tp - trap);
11711 * Set the signal handler for the specified signal. The routine figures
11712 * out what it should be set to.
11716 setsignal(int signo)
11720 struct sigaction act;
11722 if ((t = trap[signo]) == NULL)
11724 else if (*t != '\0')
11728 if (rootshell && action == S_DFL) {
11731 if (iflag || minusc || sflag == 0)
11754 t = &sigmode[signo - 1];
11758 * current setting unknown
11760 if (sigaction(signo, 0, &act) == -1) {
11762 * Pretend it worked; maybe we should give a warning
11763 * here, but other shells don't. We don't alter
11764 * sigmode, so that we retry every time.
11768 if (act.sa_handler == SIG_IGN) {
11769 if (mflag && (signo == SIGTSTP ||
11770 signo == SIGTTIN || signo == SIGTTOU)) {
11771 tsig = S_IGN; /* don't hard ignore these */
11775 tsig = S_RESET; /* force to be set */
11778 if (tsig == S_HARD_IGN || tsig == action)
11782 act.sa_handler = onsig;
11785 act.sa_handler = SIG_IGN;
11788 act.sa_handler = SIG_DFL;
11792 sigfillset(&act.sa_mask);
11793 sigaction(signo, &act, 0);
11801 ignoresig(int signo)
11803 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11804 signal(signo, SIG_IGN);
11806 sigmode[signo - 1] = S_HARD_IGN;
11817 gotsig[signo - 1] = 1;
11818 pendingsigs = signo;
11820 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11829 * Called to execute a trap. Perhaps we should avoid entering new trap
11830 * handlers while we are executing a trap handler.
11842 savestatus = exitstatus;
11846 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11854 skip = evalstring(p, SKIPEVAL);
11855 exitstatus = savestatus;
11865 * Controls whether the shell is interactive or not.
11869 setinteractive(int on)
11871 static int is_interactive;
11873 if (++on == is_interactive)
11875 is_interactive = on;
11877 setsignal(SIGQUIT);
11878 setsignal(SIGTERM);
11879 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11880 if(is_interactive > 1) {
11881 /* Looks like they want an interactive shell */
11882 static int do_banner;
11886 "\n\n%s Built-in shell (ash)\n"
11887 "Enter 'help' for a list of built-in commands.\n\n",
11896 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11897 /*** List the available builtins ***/
11899 static int helpcmd(int argc, char **argv)
11903 out1fmt("\nBuilt-in commands:\n-------------------\n");
11904 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11905 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11906 builtincmd[i].name + 1);
11912 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11913 for (i = 0; i < NUM_APPLETS; i++) {
11914 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11922 return EXIT_SUCCESS;
11924 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11927 * Called to exit the shell.
11937 status = exitstatus;
11938 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11939 if (setjmp(loc.loc)) {
11940 if (exception == EXEXIT)
11941 /* dash bug: it just does _exit(exitstatus) here
11942 * but we have to do setjobctl(0) first!
11943 * (bug is still not fixed in dash-0.5.3 - if you run dash
11944 * under Midnight Commander, on exit MC is backgrounded) */
11945 status = exitstatus;
11949 if ((p = trap[0])) {
11954 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11955 if (iflag && rootshell) {
11956 const char *hp = lookupvar("HISTFILE");
11970 static struct var *vartab[VTABSIZE];
11972 static int vpcmp(const void *, const void *);
11973 static struct var **findvar(struct var **, const char *);
11976 * Initialize the variable symbol tables and import the environment
11980 #ifdef CONFIG_ASH_GETOPTS
11982 * Safe version of setvar, returns 1 on success 0 on failure.
11986 setvarsafe(const char *name, const char *val, int flags)
11989 volatile int saveint;
11990 struct jmploc *volatile savehandler = handler;
11991 struct jmploc jmploc;
11994 if (setjmp(jmploc.loc))
11998 setvar(name, val, flags);
12001 handler = savehandler;
12002 RESTOREINT(saveint);
12008 * Set the value of a variable. The flags argument is ored with the
12009 * flags of the variable. If val is NULL, the variable is unset.
12013 setvar(const char *name, const char *val, int flags)
12020 q = endofname(name);
12021 p = strchrnul(q, '=');
12022 namelen = p - name;
12023 if (!namelen || p != q)
12024 sh_error("%.*s: bad variable name", namelen, name);
12029 vallen = strlen(val);
12032 nameeq = ckmalloc(namelen + vallen + 2);
12033 p = memcpy(nameeq, name, namelen) + namelen;
12036 p = memcpy(p, val, vallen) + vallen;
12039 setvareq(nameeq, flags | VNOSAVE);
12045 * Same as setvar except that the variable and value are passed in
12046 * the first argument as name=value. Since the first argument will
12047 * be actually stored in the table, it should not be a string that
12049 * Called with interrupts off.
12053 setvareq(char *s, int flags)
12055 struct var *vp, **vpp;
12058 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12059 vp = *findvar(vpp, s);
12061 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12064 if (flags & VNOSAVE)
12067 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12070 if (flags & VNOSET)
12073 if (vp->func && (flags & VNOFUNC) == 0)
12074 (*vp->func)(strchrnul(s, '=') + 1);
12076 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12079 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12081 if (flags & VNOSET)
12084 vp = ckmalloc(sizeof (*vp));
12089 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12097 * Process a linked list of variable assignments.
12101 listsetvar(struct strlist *list_set_var, int flags)
12103 struct strlist *lp = list_set_var;
12109 setvareq(lp->text, flags);
12110 } while ((lp = lp->next));
12116 * Find the value of a variable. Returns NULL if not set.
12120 lookupvar(const char *name)
12124 if ((v = *findvar(hashvar(name), name))) {
12127 * Dynamic variables are implemented roughly the same way they are
12128 * in bash. Namely, they're "special" so long as they aren't unset.
12129 * As soon as they're unset, they're no longer dynamic, and dynamic
12130 * lookup will no longer happen at that point. -- PFM.
12132 if((v->flags & VDYNAMIC))
12135 if(!(v->flags & VUNSET))
12136 return strchrnul(v->text, '=') + 1;
12144 * Search the environment of a builtin command.
12148 bltinlookup(const char *name)
12150 struct strlist *sp;
12152 for (sp = cmdenviron ; sp ; sp = sp->next) {
12153 if (varequal(sp->text, name))
12154 return strchrnul(sp->text, '=') + 1;
12156 return lookupvar(name);
12161 * Generate a list of variables satisfying the given conditions.
12165 listvars(int on, int off, char ***end)
12176 for (vp = *vpp ; vp ; vp = vp->next)
12177 if ((vp->flags & mask) == on) {
12178 if (ep == stackstrend())
12179 ep = growstackstr();
12180 *ep++ = (char *) vp->text;
12182 } while (++vpp < vartab + VTABSIZE);
12183 if (ep == stackstrend())
12184 ep = growstackstr();
12188 return grabstackstr(ep);
12193 * POSIX requires that 'set' (but not export or readonly) output the
12194 * variables in lexicographic order - by the locale's collating order (sigh).
12195 * Maybe we could keep them in an ordered balanced binary tree
12196 * instead of hashed lists.
12197 * For now just roll 'em through qsort for printing...
12201 showvars(const char *sep_prefix, int on, int off)
12204 char **ep, **epend;
12206 ep = listvars(on, off, &epend);
12207 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12209 sep = *sep_prefix ? spcstr : sep_prefix;
12211 for (; ep < epend; ep++) {
12215 p = strchrnul(*ep, '=');
12218 q = single_quote(++p);
12220 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12229 * The export and readonly commands.
12233 exportcmd(int argc, char **argv)
12239 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12242 notp = nextopt("p") - 'p';
12243 if (notp && ((name = *(aptr = argptr)))) {
12245 if ((p = strchr(name, '=')) != NULL) {
12248 if ((vp = *findvar(hashvar(name), name))) {
12253 setvar(name, p, flag);
12254 } while ((name = *++aptr) != NULL);
12256 showvars(argv[0], flag, 0);
12263 * Make a variable a local variable. When a variable is made local, it's
12264 * value and flags are saved in a localvar structure. The saved values
12265 * will be restored when the shell function returns. We handle the name
12266 * "-" as a special case.
12269 static void mklocal(char *name)
12271 struct localvar *lvp;
12276 lvp = ckmalloc(sizeof (struct localvar));
12277 if (LONE_DASH(name)) {
12279 p = ckmalloc(sizeof(optlist));
12280 lvp->text = memcpy(p, optlist, sizeof(optlist));
12285 vpp = hashvar(name);
12286 vp = *findvar(vpp, name);
12287 eq = strchr(name, '=');
12290 setvareq(name, VSTRFIXED);
12292 setvar(name, NULL, VSTRFIXED);
12293 vp = *vpp; /* the new variable */
12294 lvp->flags = VUNSET;
12296 lvp->text = vp->text;
12297 lvp->flags = vp->flags;
12298 vp->flags |= VSTRFIXED|VTEXTFIXED;
12304 lvp->next = localvars;
12310 * The "local" command.
12314 localcmd(int argc, char **argv)
12319 while ((name = *argv++) != NULL) {
12327 * Called after a function returns.
12328 * Interrupts must be off.
12334 struct localvar *lvp;
12337 while ((lvp = localvars) != NULL) {
12338 localvars = lvp->next;
12340 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12341 if (vp == NULL) { /* $- saved */
12342 memcpy(optlist, lvp->text, sizeof(optlist));
12345 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12346 unsetvar(vp->text);
12349 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12350 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12352 vp->flags = lvp->flags;
12353 vp->text = lvp->text;
12361 * The unset builtin command. We unset the function before we unset the
12362 * variable to allow a function to be unset when there is a readonly variable
12363 * with the same name.
12367 unsetcmd(int argc, char **argv)
12374 while ((i = nextopt("vf")) != '\0') {
12378 for (ap = argptr; *ap ; ap++) {
12393 * Unset the specified variable.
12397 unsetvar(const char *s)
12403 vpp = findvar(hashvar(s), s);
12407 int flags = vp->flags;
12410 if (flags & VREADONLY)
12413 vp->flags &= ~VDYNAMIC;
12415 if (flags & VUNSET)
12417 if ((flags & VSTRFIXED) == 0) {
12419 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12426 vp->flags &= ~VEXPORT;
12439 * Find the appropriate entry in the hash table from the name.
12442 static struct var **
12443 hashvar(const char *p)
12445 unsigned int hashval;
12447 hashval = ((unsigned char) *p) << 4;
12448 while (*p && *p != '=')
12449 hashval += (unsigned char) *p++;
12450 return &vartab[hashval % VTABSIZE];
12456 * Compares two strings up to the first = or '\0'. The first
12457 * string must be terminated by '='; the second may be terminated by
12458 * either '=' or '\0'.
12462 varcmp(const char *p, const char *q)
12466 while ((c = *p) == (d = *q)) {
12467 if (!c || c == '=')
12481 vpcmp(const void *a, const void *b)
12483 return varcmp(*(const char **)a, *(const char **)b);
12486 static struct var **
12487 findvar(struct var **vpp, const char *name)
12489 for (; *vpp; vpp = &(*vpp)->next) {
12490 if (varequal((*vpp)->text, name)) {
12498 #include <sys/times.h>
12500 static const unsigned char timescmd_str[] = {
12501 ' ', offsetof(struct tms, tms_utime),
12502 '\n', offsetof(struct tms, tms_stime),
12503 ' ', offsetof(struct tms, tms_cutime),
12504 '\n', offsetof(struct tms, tms_cstime),
12508 static int timescmd(int ac, char **av)
12510 long int clk_tck, s, t;
12511 const unsigned char *p;
12514 clk_tck = sysconf(_SC_CLK_TCK);
12519 t = *(clock_t *)(((char *) &buf) + p[1]);
12521 out1fmt("%ldm%ld.%.3lds%c",
12523 ((t - s * clk_tck) * 1000) / clk_tck,
12525 } while (*(p += 2));
12530 #ifdef CONFIG_ASH_MATH_SUPPORT
12532 dash_arith(const char *s)
12538 result = arith(s, &errcode);
12541 sh_error("exponent less than 0");
12542 else if (errcode == -2)
12543 sh_error("divide by zero");
12544 else if (errcode == -5)
12545 sh_error("expression recursion loop detected");
12556 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12557 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12559 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12563 letcmd(int argc, char **argv)
12570 sh_error("expression expected");
12571 for (ap = argv + 1; *ap; ap++) {
12572 i = dash_arith(*ap);
12577 #endif /* CONFIG_ASH_MATH_SUPPORT */
12582 * Miscellaneous builtins.
12587 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12588 typedef enum __rlimit_resource rlim_t;
12593 * The read builtin. The -e option causes backslashes to escape the
12594 * following character.
12596 * This uses unbuffered input, which may be avoidable in some cases.
12600 readcmd(int argc, char **argv)
12612 #if defined(CONFIG_ASH_READ_NCHARS)
12616 struct termios tty, old_tty;
12618 #if defined(CONFIG_ASH_READ_TIMEOUT)
12622 ts.tv_sec = ts.tv_usec = 0;
12627 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12628 while ((i = nextopt("p:rt:n:s")) != '\0')
12629 #elif defined(CONFIG_ASH_READ_NCHARS)
12630 while ((i = nextopt("p:rn:s")) != '\0')
12631 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12632 while ((i = nextopt("p:rt:")) != '\0')
12634 while ((i = nextopt("p:r")) != '\0')
12639 prompt = optionarg;
12641 #if defined(CONFIG_ASH_READ_NCHARS)
12643 nchars = strtol(optionarg, &p, 10);
12645 sh_error("invalid count");
12646 nch_flag = (nchars > 0);
12652 #if defined(CONFIG_ASH_READ_TIMEOUT)
12654 ts.tv_sec = strtol(optionarg, &p, 10);
12660 ts.tv_usec = strtol(p, &p2, 10);
12662 sh_error("invalid timeout");
12664 /* normalize to usec */
12666 sh_error("invalid timeout");
12667 while (scale++ < 6)
12671 sh_error("invalid timeout");
12673 if ( ! ts.tv_sec && ! ts.tv_usec)
12674 sh_error("invalid timeout");
12684 if (prompt && isatty(0)) {
12687 if (*(ap = argptr) == NULL)
12688 sh_error("arg count");
12689 if ((ifs = bltinlookup("IFS")) == NULL)
12691 #if defined(CONFIG_ASH_READ_NCHARS)
12692 if (nch_flag || silent) {
12693 tcgetattr(0, &tty);
12696 tty.c_lflag &= ~ICANON;
12697 tty.c_cc[VMIN] = nchars;
12700 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12703 tcsetattr(0, TCSANOW, &tty);
12706 #if defined(CONFIG_ASH_READ_TIMEOUT)
12707 if (ts.tv_sec || ts.tv_usec) {
12711 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
12713 #if defined(CONFIG_ASH_READ_NCHARS)
12715 tcsetattr(0, TCSANOW, &old_tty);
12725 #if defined(CONFIG_ASH_READ_NCHARS)
12726 while (!nch_flag || nchars--)
12731 if (read(0, &c, 1) != 1) {
12743 if (!rflag && c == '\\') {
12749 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12753 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12755 setvar(*ap, stackblock(), 0);
12764 #if defined(CONFIG_ASH_READ_NCHARS)
12765 if (nch_flag || silent)
12766 tcsetattr(0, TCSANOW, &old_tty);
12770 /* Remove trailing blanks */
12771 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12773 setvar(*ap, stackblock(), 0);
12774 while (*++ap != NULL)
12775 setvar(*ap, nullstr, 0);
12780 static int umaskcmd(int argc, char **argv)
12782 static const char permuser[3] = "ugo";
12783 static const char permmode[3] = "rwx";
12784 static const short int permmask[] = {
12785 S_IRUSR, S_IWUSR, S_IXUSR,
12786 S_IRGRP, S_IWGRP, S_IXGRP,
12787 S_IROTH, S_IWOTH, S_IXOTH
12793 int symbolic_mode = 0;
12795 while (nextopt("S") != '\0') {
12804 if ((ap = *argptr) == NULL) {
12805 if (symbolic_mode) {
12809 for (i = 0; i < 3; i++) {
12812 *p++ = permuser[i];
12814 for (j = 0; j < 3; j++) {
12815 if ((mask & permmask[3 * i + j]) == 0) {
12816 *p++ = permmode[j];
12824 out1fmt("%.4o\n", mask);
12827 if (is_digit((unsigned char) *ap)) {
12830 if (*ap >= '8' || *ap < '0')
12831 sh_error(illnum, argv[1]);
12832 mask = (mask << 3) + (*ap - '0');
12833 } while (*++ap != '\0');
12836 mask = ~mask & 0777;
12837 if (!bb_parse_mode(ap, &mask)) {
12838 sh_error("Illegal mode: %s", ap);
12840 umask(~mask & 0777);
12849 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12850 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12851 * ash by J.T. Conklin.
12859 int factor; /* multiply by to get rlim_{cur,max} values */
12863 static const struct limits limits[] = {
12865 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12867 #ifdef RLIMIT_FSIZE
12868 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12871 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12873 #ifdef RLIMIT_STACK
12874 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12877 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12880 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12882 #ifdef RLIMIT_MEMLOCK
12883 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12885 #ifdef RLIMIT_NPROC
12886 { "process", RLIMIT_NPROC, 1, 'p' },
12888 #ifdef RLIMIT_NOFILE
12889 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12892 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12894 #ifdef RLIMIT_LOCKS
12895 { "locks", RLIMIT_LOCKS, 1, 'w' },
12897 { (char *) 0, 0, 0, '\0' }
12900 enum limtype { SOFT = 0x1, HARD = 0x2 };
12902 static void printlim(enum limtype how, const struct rlimit *limit,
12903 const struct limits *l)
12907 val = limit->rlim_max;
12909 val = limit->rlim_cur;
12911 if (val == RLIM_INFINITY)
12912 out1fmt("unlimited\n");
12915 out1fmt("%lld\n", (long long) val);
12920 ulimitcmd(int argc, char **argv)
12924 enum limtype how = SOFT | HARD;
12925 const struct limits *l;
12928 struct rlimit limit;
12931 while ((optc = nextopt("HSa"
12935 #ifdef RLIMIT_FSIZE
12941 #ifdef RLIMIT_STACK
12950 #ifdef RLIMIT_MEMLOCK
12953 #ifdef RLIMIT_NPROC
12956 #ifdef RLIMIT_NOFILE
12962 #ifdef RLIMIT_LOCKS
12980 for (l = limits; l->option != what; l++)
12983 set = *argptr ? 1 : 0;
12987 if (all || argptr[1])
12988 sh_error("too many arguments");
12989 if (strncmp(p, "unlimited\n", 9) == 0)
12990 val = RLIM_INFINITY;
12994 while ((c = *p++) >= '0' && c <= '9')
12996 val = (val * 10) + (long)(c - '0');
12997 if (val < (rlim_t) 0)
13001 sh_error("bad number");
13006 for (l = limits; l->name; l++) {
13007 getrlimit(l->cmd, &limit);
13008 out1fmt("%-20s ", l->name);
13009 printlim(how, &limit, l);
13014 getrlimit(l->cmd, &limit);
13017 limit.rlim_max = val;
13019 limit.rlim_cur = val;
13020 if (setrlimit(l->cmd, &limit) < 0)
13021 sh_error("error setting limit (%m)");
13023 printlim(how, &limit, l);
13029 #ifdef CONFIG_ASH_MATH_SUPPORT
13031 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13033 Permission is hereby granted, free of charge, to any person obtaining
13034 a copy of this software and associated documentation files (the
13035 "Software"), to deal in the Software without restriction, including
13036 without limitation the rights to use, copy, modify, merge, publish,
13037 distribute, sublicense, and/or sell copies of the Software, and to
13038 permit persons to whom the Software is furnished to do so, subject to
13039 the following conditions:
13041 The above copyright notice and this permission notice shall be
13042 included in all copies or substantial portions of the Software.
13044 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13045 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13046 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13047 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13048 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13049 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13050 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13053 /* This is my infix parser/evaluator. It is optimized for size, intended
13054 * as a replacement for yacc-based parsers. However, it may well be faster
13055 * than a comparable parser written in yacc. The supported operators are
13056 * listed in #defines below. Parens, order of operations, and error handling
13057 * are supported. This code is thread safe. The exact expression format should
13058 * be that which POSIX specifies for shells. */
13060 /* The code uses a simple two-stack algorithm. See
13061 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13062 * for a detailed explanation of the infix-to-postfix algorithm on which
13063 * this is based (this code differs in that it applies operators immediately
13064 * to the stack instead of adding them to a queue to end up with an
13067 /* To use the routine, call it with an expression string and error return
13071 * Aug 24, 2001 Manuel Novoa III
13073 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13075 * 1) In arith_apply():
13076 * a) Cached values of *numptr and &(numptr[-1]).
13077 * b) Removed redundant test for zero denominator.
13080 * a) Eliminated redundant code for processing operator tokens by moving
13081 * to a table-based implementation. Also folded handling of parens
13083 * b) Combined all 3 loops which called arith_apply to reduce generated
13084 * code size at the cost of speed.
13086 * 3) The following expressions were treated as valid by the original code:
13087 * 1() , 0! , 1 ( *3 ) .
13088 * These bugs have been fixed by internally enclosing the expression in
13089 * parens and then checking that all binary ops and right parens are
13090 * preceded by a valid expression (NUM_TOKEN).
13092 * Note: It may be desirable to replace Aaron's test for whitespace with
13093 * ctype's isspace() if it is used by another busybox applet or if additional
13094 * whitespace chars should be considered. Look below the "#include"s for a
13095 * precompiler test.
13099 * Aug 26, 2001 Manuel Novoa III
13101 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13103 * Merge in Aaron's comments previously posted to the busybox list,
13104 * modified slightly to take account of my changes to the code.
13109 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13111 * - allow access to variable,
13112 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13113 * - realize assign syntax (VAR=expr, +=, *= etc)
13114 * - realize exponentiation (** operator)
13115 * - realize comma separated - expr, expr
13116 * - realise ++expr --expr expr++ expr--
13117 * - realise expr ? expr : expr (but, second expr calculate always)
13118 * - allow hexadecimal and octal numbers
13119 * - was restored loses XOR operator
13120 * - remove one goto label, added three ;-)
13121 * - protect $((num num)) as true zero expr (Manuel`s error)
13122 * - always use special isspace(), see comment from bash ;-)
13126 #define arith_isspace(arithval) \
13127 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13130 typedef unsigned char operator;
13132 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13133 * precedence, and 3 high bits are an ID unique across operators of that
13134 * precedence. The ID portion is so that multiple operators can have the
13135 * same precedence, ensuring that the leftmost one is evaluated first.
13136 * Consider * and /. */
13138 #define tok_decl(prec,id) (((id)<<5)|(prec))
13139 #define PREC(op) ((op) & 0x1F)
13141 #define TOK_LPAREN tok_decl(0,0)
13143 #define TOK_COMMA tok_decl(1,0)
13145 #define TOK_ASSIGN tok_decl(2,0)
13146 #define TOK_AND_ASSIGN tok_decl(2,1)
13147 #define TOK_OR_ASSIGN tok_decl(2,2)
13148 #define TOK_XOR_ASSIGN tok_decl(2,3)
13149 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13150 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13151 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13152 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13154 #define TOK_MUL_ASSIGN tok_decl(3,0)
13155 #define TOK_DIV_ASSIGN tok_decl(3,1)
13156 #define TOK_REM_ASSIGN tok_decl(3,2)
13158 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13159 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13161 /* conditional is right associativity too */
13162 #define TOK_CONDITIONAL tok_decl(4,0)
13163 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13165 #define TOK_OR tok_decl(5,0)
13167 #define TOK_AND tok_decl(6,0)
13169 #define TOK_BOR tok_decl(7,0)
13171 #define TOK_BXOR tok_decl(8,0)
13173 #define TOK_BAND tok_decl(9,0)
13175 #define TOK_EQ tok_decl(10,0)
13176 #define TOK_NE tok_decl(10,1)
13178 #define TOK_LT tok_decl(11,0)
13179 #define TOK_GT tok_decl(11,1)
13180 #define TOK_GE tok_decl(11,2)
13181 #define TOK_LE tok_decl(11,3)
13183 #define TOK_LSHIFT tok_decl(12,0)
13184 #define TOK_RSHIFT tok_decl(12,1)
13186 #define TOK_ADD tok_decl(13,0)
13187 #define TOK_SUB tok_decl(13,1)
13189 #define TOK_MUL tok_decl(14,0)
13190 #define TOK_DIV tok_decl(14,1)
13191 #define TOK_REM tok_decl(14,2)
13193 /* exponent is right associativity */
13194 #define TOK_EXPONENT tok_decl(15,1)
13196 /* For now unary operators. */
13197 #define UNARYPREC 16
13198 #define TOK_BNOT tok_decl(UNARYPREC,0)
13199 #define TOK_NOT tok_decl(UNARYPREC,1)
13201 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13202 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13204 #define PREC_PRE (UNARYPREC+2)
13206 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13207 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13209 #define PREC_POST (UNARYPREC+3)
13211 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13212 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13214 #define SPEC_PREC (UNARYPREC+4)
13216 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13217 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13219 #define NUMPTR (*numstackptr)
13221 static int tok_have_assign(operator op)
13223 operator prec = PREC(op);
13225 convert_prec_is_assing(prec);
13226 return (prec == PREC(TOK_ASSIGN) ||
13227 prec == PREC_PRE || prec == PREC_POST);
13230 static int is_right_associativity(operator prec)
13232 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13233 prec == PREC(TOK_CONDITIONAL));
13237 typedef struct ARITCH_VAR_NUM {
13239 arith_t contidional_second_val;
13240 char contidional_second_val_initialized;
13241 char *var; /* if NULL then is regular number,
13242 else is variable name */
13246 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13248 struct CHK_VAR_RECURSIVE_LOOPED *next;
13249 } chk_var_recursive_looped_t;
13251 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13254 static int arith_lookup_val(v_n_t *t)
13257 const char * p = lookupvar(t->var);
13262 /* recursive try as expression */
13263 chk_var_recursive_looped_t *cur;
13264 chk_var_recursive_looped_t cur_save;
13266 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13267 if(strcmp(cur->var, t->var) == 0) {
13268 /* expression recursion loop detected */
13272 /* save current lookuped var name */
13273 cur = prev_chk_var_recursive;
13274 cur_save.var = t->var;
13275 cur_save.next = cur;
13276 prev_chk_var_recursive = &cur_save;
13278 t->val = arith (p, &errcode);
13279 /* restore previous ptr after recursiving */
13280 prev_chk_var_recursive = cur;
13283 /* allow undefined var as 0 */
13290 /* "applying" a token means performing it on the top elements on the integer
13291 * stack. For a unary operator it will only change the top element, but a
13292 * binary operator will pop two arguments and push a result */
13293 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13296 arith_t numptr_val, rez;
13297 int ret_arith_lookup_val;
13299 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13300 without arguments */
13301 numptr_m1 = NUMPTR - 1;
13303 /* check operand is var with noninteger value */
13304 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13305 if(ret_arith_lookup_val)
13306 return ret_arith_lookup_val;
13308 rez = numptr_m1->val;
13309 if (op == TOK_UMINUS)
13311 else if (op == TOK_NOT)
13313 else if (op == TOK_BNOT)
13315 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13317 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13319 else if (op != TOK_UPLUS) {
13320 /* Binary operators */
13322 /* check and binary operators need two arguments */
13323 if (numptr_m1 == numstack) goto err;
13325 /* ... and they pop one */
13328 if (op == TOK_CONDITIONAL) {
13329 if(! numptr_m1->contidional_second_val_initialized) {
13330 /* protect $((expr1 ? expr2)) without ": expr" */
13333 rez = numptr_m1->contidional_second_val;
13334 } else if(numptr_m1->contidional_second_val_initialized) {
13335 /* protect $((expr1 : expr2)) without "expr ? " */
13338 numptr_m1 = NUMPTR - 1;
13339 if(op != TOK_ASSIGN) {
13340 /* check operand is var with noninteger value for not '=' */
13341 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13342 if(ret_arith_lookup_val)
13343 return ret_arith_lookup_val;
13345 if (op == TOK_CONDITIONAL) {
13346 numptr_m1->contidional_second_val = rez;
13348 rez = numptr_m1->val;
13349 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13351 else if (op == TOK_OR)
13352 rez = numptr_val || rez;
13353 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13355 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13357 else if (op == TOK_AND)
13358 rez = rez && numptr_val;
13359 else if (op == TOK_EQ)
13360 rez = (rez == numptr_val);
13361 else if (op == TOK_NE)
13362 rez = (rez != numptr_val);
13363 else if (op == TOK_GE)
13364 rez = (rez >= numptr_val);
13365 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13366 rez >>= numptr_val;
13367 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13368 rez <<= numptr_val;
13369 else if (op == TOK_GT)
13370 rez = (rez > numptr_val);
13371 else if (op == TOK_LT)
13372 rez = (rez < numptr_val);
13373 else if (op == TOK_LE)
13374 rez = (rez <= numptr_val);
13375 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13377 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13379 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13381 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13383 else if (op == TOK_CONDITIONAL_SEP) {
13384 if (numptr_m1 == numstack) {
13385 /* protect $((expr : expr)) without "expr ? " */
13388 numptr_m1->contidional_second_val_initialized = op;
13389 numptr_m1->contidional_second_val = numptr_val;
13391 else if (op == TOK_CONDITIONAL) {
13393 numptr_val : numptr_m1->contidional_second_val;
13395 else if(op == TOK_EXPONENT) {
13397 return -3; /* exponent less than 0 */
13402 while(numptr_val--)
13407 else if(numptr_val==0) /* zero divisor check */
13409 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13411 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13414 if(tok_have_assign(op)) {
13417 if(numptr_m1->var == NULL) {
13421 /* save to shell variable */
13422 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13423 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13425 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13427 setvar(numptr_m1->var, buf, 0);
13428 /* after saving, make previous value for v++ or v-- */
13429 if(op == TOK_POST_INC)
13431 else if(op == TOK_POST_DEC)
13434 numptr_m1->val = rez;
13435 /* protect geting var value, is number now */
13436 numptr_m1->var = NULL;
13442 /* longest must first */
13443 static const char op_tokens[] = {
13444 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13445 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13446 '<','<', 0, TOK_LSHIFT,
13447 '>','>', 0, TOK_RSHIFT,
13448 '|','|', 0, TOK_OR,
13449 '&','&', 0, TOK_AND,
13450 '!','=', 0, TOK_NE,
13451 '<','=', 0, TOK_LE,
13452 '>','=', 0, TOK_GE,
13453 '=','=', 0, TOK_EQ,
13454 '|','=', 0, TOK_OR_ASSIGN,
13455 '&','=', 0, TOK_AND_ASSIGN,
13456 '*','=', 0, TOK_MUL_ASSIGN,
13457 '/','=', 0, TOK_DIV_ASSIGN,
13458 '%','=', 0, TOK_REM_ASSIGN,
13459 '+','=', 0, TOK_PLUS_ASSIGN,
13460 '-','=', 0, TOK_MINUS_ASSIGN,
13461 '-','-', 0, TOK_POST_DEC,
13462 '^','=', 0, TOK_XOR_ASSIGN,
13463 '+','+', 0, TOK_POST_INC,
13464 '*','*', 0, TOK_EXPONENT,
13468 '=', 0, TOK_ASSIGN,
13480 '?', 0, TOK_CONDITIONAL,
13481 ':', 0, TOK_CONDITIONAL_SEP,
13482 ')', 0, TOK_RPAREN,
13483 '(', 0, TOK_LPAREN,
13487 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13490 static arith_t arith (const char *expr, int *perrcode)
13492 char arithval; /* Current character under analysis */
13493 operator lasttok, op;
13496 const char *p = endexpression;
13499 size_t datasizes = strlen(expr) + 2;
13501 /* Stack of integers */
13502 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13503 * in any given correct or incorrect expression is left as an exercise to
13505 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13506 *numstackptr = numstack;
13507 /* Stack of operator tokens */
13508 operator *stack = alloca((datasizes) * sizeof(operator)),
13511 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13512 *perrcode = errcode = 0;
13515 if ((arithval = *expr) == 0) {
13516 if (p == endexpression) {
13517 /* Null expression. */
13521 /* This is only reached after all tokens have been extracted from the
13522 * input stream. If there are still tokens on the operator stack, they
13523 * are to be applied in order. At the end, there should be a final
13524 * result on the integer stack */
13526 if (expr != endexpression + 1) {
13527 /* If we haven't done so already, */
13528 /* append a closing right paren */
13529 expr = endexpression;
13530 /* and let the loop process it. */
13533 /* At this point, we're done with the expression. */
13534 if (numstackptr != numstack+1) {
13535 /* ... but if there isn't, it's bad */
13537 return (*perrcode = -1);
13539 if(numstack->var) {
13540 /* expression is $((var)) only, lookup now */
13541 errcode = arith_lookup_val(numstack);
13544 *perrcode = errcode;
13545 return numstack->val;
13547 /* Continue processing the expression. */
13548 if (arith_isspace(arithval)) {
13549 /* Skip whitespace */
13552 if((p = endofname(expr)) != expr) {
13553 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13555 numstackptr->var = alloca(var_name_size);
13556 safe_strncpy(numstackptr->var, expr, var_name_size);
13559 numstackptr->contidional_second_val_initialized = 0;
13563 } else if (is_digit(arithval)) {
13564 numstackptr->var = NULL;
13565 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13566 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13568 numstackptr->val = strtol(expr, (char **) &expr, 0);
13572 for(p = op_tokens; ; p++) {
13576 /* strange operator not found */
13579 for(o = expr; *p && *o == *p; p++)
13586 /* skip tail uncompared token */
13589 /* skip zero delim */
13594 /* post grammar: a++ reduce to num */
13595 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13598 /* Plus and minus are binary (not unary) _only_ if the last
13599 * token was as number, or a right paren (which pretends to be
13600 * a number, since it evaluates to one). Think about it.
13601 * It makes sense. */
13602 if (lasttok != TOK_NUM) {
13618 /* We don't want a unary operator to cause recursive descent on the
13619 * stack, because there can be many in a row and it could cause an
13620 * operator to be evaluated before its argument is pushed onto the
13621 * integer stack. */
13622 /* But for binary operators, "apply" everything on the operator
13623 * stack until we find an operator with a lesser priority than the
13624 * one we have just extracted. */
13625 /* Left paren is given the lowest priority so it will never be
13626 * "applied" in this way.
13627 * if associativity is right and priority eq, applied also skip
13630 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13631 /* not left paren or unary */
13632 if (lasttok != TOK_NUM) {
13633 /* binary op must be preceded by a num */
13636 while (stackptr != stack) {
13637 if (op == TOK_RPAREN) {
13638 /* The algorithm employed here is simple: while we don't
13639 * hit an open paren nor the bottom of the stack, pop
13640 * tokens and apply them */
13641 if (stackptr[-1] == TOK_LPAREN) {
13643 /* Any operator directly after a */
13645 /* close paren should consider itself binary */
13649 operator prev_prec = PREC(stackptr[-1]);
13651 convert_prec_is_assing(prec);
13652 convert_prec_is_assing(prev_prec);
13653 if (prev_prec < prec)
13655 /* check right assoc */
13656 if(prev_prec == prec && is_right_associativity(prec))
13659 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13660 if(errcode) goto ret;
13662 if (op == TOK_RPAREN) {
13667 /* Push this operator to the stack and remember it. */
13668 *stackptr++ = lasttok = op;
13675 #endif /* CONFIG_ASH_MATH_SUPPORT */
13679 const char *applet_name = "debug stuff usage";
13680 int main(int argc, char **argv)
13682 return ash_main(argc, argv);
13687 * Copyright (c) 1989, 1991, 1993, 1994
13688 * The Regents of the University of California. All rights reserved.
13690 * This code is derived from software contributed to Berkeley by
13691 * Kenneth Almquist.
13693 * Redistribution and use in source and binary forms, with or without
13694 * modification, are permitted provided that the following conditions
13696 * 1. Redistributions of source code must retain the above copyright
13697 * notice, this list of conditions and the following disclaimer.
13698 * 2. Redistributions in binary form must reproduce the above copyright
13699 * notice, this list of conditions and the following disclaimer in the
13700 * documentation and/or other materials provided with the distribution.
13701 * 3. Neither the name of the University nor the names of its contributors
13702 * may be used to endorse or promote products derived from this software
13703 * without specific prior written permission.
13705 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13706 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13707 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13708 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13709 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13710 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13711 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13712 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13713 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13714 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF