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 #if ENABLE_ASH_JOB_CONTROL
91 #if JOBS || ENABLE_ASH_READ_NCHARS
98 static int *dash_errno;
100 #define errno (*dash_errno)
103 #if defined(__uClinux__)
104 #error "Do not even bother, ash will not run on uClinux"
108 #define _DIAGASSERT(assert_expr) assert(assert_expr)
110 #define _DIAGASSERT(assert_expr)
127 static struct alias *lookupalias(const char *, int);
128 static int aliascmd(int, char **);
129 static int unaliascmd(int, char **);
130 static void rmaliases(void);
131 static int unalias(const char *);
132 static void printalias(const struct alias *);
138 static void setpwd(const char *, int);
144 * Types of operations (passed to the errmsg routine).
148 static const char not_found_msg[] = "%s: not found";
151 #define E_OPEN "No such file" /* opening a file */
152 #define E_CREAT "Directory nonexistent" /* creating a file */
153 #define E_EXEC not_found_msg+4 /* executing a program */
156 * We enclose jmp_buf in a structure so that we can declare pointers to
157 * jump locations. The global variable handler contains the location to
158 * jump to when an exception occurs, and the global variable exception
159 * contains a code identifying the exception. To implement nested
160 * exception handlers, the user should save the value of handler on entry
161 * to an inner scope, set handler to point to a jmploc structure for the
162 * inner scope, and restore handler on exit from the scope.
169 static struct jmploc *handler;
170 static int exception;
171 static volatile int suppressint;
172 static volatile sig_atomic_t intpending;
175 #define EXINT 0 /* SIGINT received */
176 #define EXERROR 1 /* a generic error */
177 #define EXSHELLPROC 2 /* execute a shell procedure */
178 #define EXEXEC 3 /* command execution failed */
179 #define EXEXIT 4 /* exit the shell */
180 #define EXSIG 5 /* trapped signal in wait(1) */
183 /* do we generate EXSIG events */
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsigs;
189 * These macros allow the user to suspend the handling of interrupt signals
190 * over a period of time. This is similar to SIGHOLD to or sigblock, but
191 * much more efficient and portable. (But hacking the kernel is so much
192 * more fun than worrying about efficiency and portability. :-))
195 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
202 #define SAVEINT(v) ((v) = suppressint)
203 #define RESTOREINT(v) \
206 if ((suppressint = (v)) == 0 && intpending) onint(); \
217 /* EXSIG is turned off by evalbltin(). */
220 static void exraise(int) ATTRIBUTE_NORETURN;
221 static void onint(void) ATTRIBUTE_NORETURN;
223 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
224 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
226 static void sh_warnx(const char *, ...);
228 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
231 if (--suppressint == 0 && intpending) {
235 #define INTON inton()
236 static void forceinton(void)
242 #define FORCEINTON forceinton()
247 if (--suppressint == 0 && intpending) onint(); \
254 if (intpending) onint(); \
257 #endif /* ASH_OPTIMIZE_FOR_SIZE */
262 struct strlist *next;
268 struct strlist *list;
269 struct strlist **lastp;
275 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
276 #define EXP_TILDE 0x2 /* do normal tilde expansion */
277 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
278 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
279 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
280 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
281 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
282 #define EXP_WORD 0x80 /* expand word in parameter expansion */
283 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
287 static void expandarg(union node *, struct arglist *, int);
288 #define rmescapes(p) _rmescapes((p), 0)
289 static char *_rmescapes(char *, int);
290 static int casematch(union node *, char *);
292 #if ENABLE_ASH_MATH_SUPPORT
293 static void expari(int);
298 static char *commandname; /* currently executing command */
299 static struct strlist *cmdenviron; /* environment for builtin command */
300 static int exitstatus; /* exit status of last command */
301 static int back_exitstatus; /* exit status of backquoted command */
304 struct backcmd { /* result of evalbackcmd */
305 int fd; /* file descriptor to read from */
306 char *buf; /* buffer */
307 int nleft; /* number of chars in buffer */
308 struct job *jp; /* job structure for command */
312 * This file was generated by the mknodes program.
347 union node *redirect;
353 struct nodelist *cmdlist;
359 union node *redirect;
372 union node *elsepart;
399 struct nodelist *backquote;
434 struct nredir nredir;
435 struct nbinary nbinary;
439 struct nclist nclist;
448 struct nodelist *next;
458 static void freefunc(struct funcnode *);
461 /* control characters in argument strings */
462 #define CTL_FIRST '\201' /* first 'special' character */
463 #define CTLESC '\201' /* escape next character */
464 #define CTLVAR '\202' /* variable defn */
465 #define CTLENDVAR '\203'
466 #define CTLBACKQ '\204'
467 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
468 /* CTLBACKQ | CTLQUOTE == '\205' */
469 #define CTLARI '\206' /* arithmetic expression */
470 #define CTLENDARI '\207'
471 #define CTLQUOTEMARK '\210'
472 #define CTL_LAST '\210' /* last 'special' character */
474 /* variable substitution byte (follows CTLVAR) */
475 #define VSTYPE 0x0f /* type of variable substitution */
476 #define VSNUL 0x10 /* colon--treat the empty string as unset */
477 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
479 /* values of VSTYPE field */
480 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
481 #define VSMINUS 0x2 /* ${var-text} */
482 #define VSPLUS 0x3 /* ${var+text} */
483 #define VSQUESTION 0x4 /* ${var?message} */
484 #define VSASSIGN 0x5 /* ${var=text} */
485 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
486 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
487 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
488 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
489 #define VSLENGTH 0xa /* ${#var} */
491 /* values of checkkwd variable */
496 #define IBUFSIZ (BUFSIZ + 1)
499 * NEOF is returned by parsecmd when it encounters an end of file. It
500 * must be distinct from NULL, so we use the address of a variable that
501 * happens to be handy.
503 static int plinno = 1; /* input line number */
505 /* number of characters left in input buffer */
506 static int parsenleft; /* copy of parsefile->nleft */
507 static int parselleft; /* copy of parsefile->lleft */
509 /* next character in input buffer */
510 static char *parsenextc; /* copy of parsefile->nextc */
513 struct strpush *prev; /* preceding string on stack */
517 struct alias *ap; /* if push was associated with an alias */
519 char *string; /* remember the string since it may change */
523 struct parsefile *prev; /* preceding file on stack */
524 int linno; /* current line */
525 int fd; /* file descriptor (or -1 if string) */
526 int nleft; /* number of chars left in this line */
527 int lleft; /* number of chars left in this buffer */
528 char *nextc; /* next char in buffer */
529 char *buf; /* input buffer */
530 struct strpush *strpush; /* for pushing strings at this level */
531 struct strpush basestrpush; /* so pushing one is fast */
534 static struct parsefile basepf; /* top level input file */
535 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
536 static struct parsefile *parsefile = &basepf; /* current input file */
539 static int tokpushback; /* last token pushed back */
540 #define NEOF ((union node *)&tokpushback)
541 static int parsebackquote; /* nonzero if we are inside backquotes */
542 static int doprompt; /* if set, prompt the user */
543 static int needprompt; /* true if interactive and at start of line */
544 static int lasttoken; /* last token read */
545 static char *wordtext; /* text of last word returned by readtoken */
547 static struct nodelist *backquotelist;
548 static union node *redirnode;
549 static struct heredoc *heredoc;
550 static int quoteflag; /* set if (part of) last token was quoted */
551 static int startlinno; /* line # where last token started */
553 static union node *parsecmd(int);
554 static void fixredir(union node *, const char *, int);
555 static const char *const *findkwd(const char *);
556 static char *endofname(const char *);
560 typedef void *pointer;
562 static char nullstr[1]; /* zero length string */
563 static const char spcstr[] = " ";
564 static const char snlfmt[] = "%s\n";
565 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
566 static const char illnum[] = "Illegal number: %s";
567 static const char homestr[] = "HOME";
570 #define TRACE(param) trace param
571 #define TRACEV(param) tracev param
574 #define TRACEV(param)
577 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
578 #define __builtin_expect(x, expected_value) (x)
581 #define xlikely(x) __builtin_expect((x),1)
596 #define TENDBQUOTE 12
614 /* first char is indicating which tokens mark the end of a list */
615 static const char *const tokname_array[] = {
630 /* the following are keywords */
649 static const char *tokname(int tok)
655 sprintf(buf + (tok >= TSEMI), "%s%c",
656 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
663 * Most machines require the value returned from malloc to be aligned
664 * in some way. The following macro will get this right on many machines.
667 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
669 * It appears that grabstackstr() will barf with such alignments
670 * because stalloc() will return a string allocated in a new stackblock.
672 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
675 * This file was generated by the mksyntax program.
680 #define CWORD 0 /* character is nothing special */
681 #define CNL 1 /* newline character */
682 #define CBACK 2 /* a backslash character */
683 #define CSQUOTE 3 /* single quote */
684 #define CDQUOTE 4 /* double quote */
685 #define CENDQUOTE 5 /* a terminating quote */
686 #define CBQUOTE 6 /* backwards single quote */
687 #define CVAR 7 /* a dollar sign */
688 #define CENDVAR 8 /* a '}' character */
689 #define CLP 9 /* a left paren in arithmetic */
690 #define CRP 10 /* a right paren in arithmetic */
691 #define CENDFILE 11 /* end of file */
692 #define CCTL 12 /* like CWORD, except it must be escaped */
693 #define CSPCL 13 /* these terminate a word */
694 #define CIGN 14 /* character should be ignored */
700 #define PEOA_OR_PEOF PEOA
704 #define PEOA_OR_PEOF PEOF
707 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
708 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
709 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
711 /* C99 say: "char" declaration may be signed or unsigned default */
712 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
715 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
716 * (assuming ascii char codes, as the original implementation did)
718 #define is_special(c) \
719 ( (((unsigned int)c) - 33 < 32) \
720 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
722 #define digit_val(c) ((c) - '0')
725 * This file was generated by the mksyntax program.
728 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
729 #define USE_SIT_FUNCTION
732 /* number syntax index */
733 #define BASESYNTAX 0 /* not in quotes */
734 #define DQSYNTAX 1 /* in double quotes */
735 #define SQSYNTAX 2 /* in single quotes */
736 #define ARISYNTAX 3 /* in arithmetic */
738 #if ENABLE_ASH_MATH_SUPPORT
739 static const char S_I_T[][4] = {
741 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
743 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
744 {CNL, CNL, CNL, CNL}, /* 2, \n */
745 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
746 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
747 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
748 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
749 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
750 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
751 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
752 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
753 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
754 #ifndef USE_SIT_FUNCTION
755 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
756 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
757 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
761 static const char S_I_T[][3] = {
763 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
765 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
766 {CNL, CNL, CNL}, /* 2, \n */
767 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
768 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
769 {CVAR, CVAR, CWORD}, /* 5, $ */
770 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
771 {CSPCL, CWORD, CWORD}, /* 7, ( */
772 {CSPCL, CWORD, CWORD}, /* 8, ) */
773 {CBACK, CBACK, CCTL}, /* 9, \ */
774 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
775 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
776 #ifndef USE_SIT_FUNCTION
777 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
778 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
779 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
782 #endif /* ASH_MATH_SUPPORT */
784 #ifdef USE_SIT_FUNCTION
786 #define U_C(c) ((unsigned char)(c))
788 static int SIT(int c, int syntax)
790 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
792 static const char syntax_index_table[] = {
793 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
794 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
795 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
799 static const char syntax_index_table[] = {
800 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
801 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
802 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
809 if (c == PEOF) /* 2^8+2 */
812 if (c == PEOA) /* 2^8+1 */
816 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
819 s = strchr(spec_symbls, c);
820 if (s == 0 || *s == 0)
822 indx = syntax_index_table[(s - spec_symbls)];
824 return S_I_T[indx][syntax];
827 #else /* USE_SIT_FUNCTION */
829 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
832 #define CSPCL_CIGN_CIGN_CIGN 0
833 #define CSPCL_CWORD_CWORD_CWORD 1
834 #define CNL_CNL_CNL_CNL 2
835 #define CWORD_CCTL_CCTL_CWORD 3
836 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
837 #define CVAR_CVAR_CWORD_CVAR 5
838 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
839 #define CSPCL_CWORD_CWORD_CLP 7
840 #define CSPCL_CWORD_CWORD_CRP 8
841 #define CBACK_CBACK_CCTL_CBACK 9
842 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
843 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
844 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
845 #define CWORD_CWORD_CWORD_CWORD 13
846 #define CCTL_CCTL_CCTL_CCTL 14
848 #define CSPCL_CWORD_CWORD_CWORD 0
849 #define CNL_CNL_CNL_CNL 1
850 #define CWORD_CCTL_CCTL_CWORD 2
851 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
852 #define CVAR_CVAR_CWORD_CVAR 4
853 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
854 #define CSPCL_CWORD_CWORD_CLP 6
855 #define CSPCL_CWORD_CWORD_CRP 7
856 #define CBACK_CBACK_CCTL_CBACK 8
857 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
858 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
859 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
860 #define CWORD_CWORD_CWORD_CWORD 12
861 #define CCTL_CCTL_CCTL_CCTL 13
864 static const char syntax_index_table[258] = {
865 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
866 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
868 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
870 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
871 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
872 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
873 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
874 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
875 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
876 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
877 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
878 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
879 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
880 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
881 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
882 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
883 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
884 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
885 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
886 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
887 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
888 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
889 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
890 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
891 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
892 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
893 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
894 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
895 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
896 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
897 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
898 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
899 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
900 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
901 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
902 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
903 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
904 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
905 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
906 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
907 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
908 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
909 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
910 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
911 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
912 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
913 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
914 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
915 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
916 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
917 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
918 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
919 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
920 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
921 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
922 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
923 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
924 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
925 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
926 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
927 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
928 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
929 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
930 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
931 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
932 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
933 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
934 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
935 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
936 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
937 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
938 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
939 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
940 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
941 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
942 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
943 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
944 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
945 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
946 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
947 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
948 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
949 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
950 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
951 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
952 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
953 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
954 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
955 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
956 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
957 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
958 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
959 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
960 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
961 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
962 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
963 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
964 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
965 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
966 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
967 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
968 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
969 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
970 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
971 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
972 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
973 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
974 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
975 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
976 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
977 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
978 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
979 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
980 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
981 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
982 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
983 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
984 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
985 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
986 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
987 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
988 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
989 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
990 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
991 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
992 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
993 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
994 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
995 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
996 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
997 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
998 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
999 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1008 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1009 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1031 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1032 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1033 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1034 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1035 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1036 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1037 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1038 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1039 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1040 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1041 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1042 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1043 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1044 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1045 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1046 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1047 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1048 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1049 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1050 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1051 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1052 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1053 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1054 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1055 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1056 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1057 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1058 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1059 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1060 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1061 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1062 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1063 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1064 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1074 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1075 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1076 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1077 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1078 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1079 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1090 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1091 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1092 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1095 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1108 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1123 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1124 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1125 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1128 #endif /* USE_SIT_FUNCTION */
1135 static int funcblocksize; /* size of structures in function */
1136 static int funcstringsize; /* size of strings in node */
1137 static pointer funcblock; /* block to allocate function from */
1138 static char *funcstring; /* block to allocate strings from */
1140 static const short nodesize[26] = {
1141 SHELL_ALIGN(sizeof(struct ncmd)),
1142 SHELL_ALIGN(sizeof(struct npipe)),
1143 SHELL_ALIGN(sizeof(struct nredir)),
1144 SHELL_ALIGN(sizeof(struct nredir)),
1145 SHELL_ALIGN(sizeof(struct nredir)),
1146 SHELL_ALIGN(sizeof(struct nbinary)),
1147 SHELL_ALIGN(sizeof(struct nbinary)),
1148 SHELL_ALIGN(sizeof(struct nbinary)),
1149 SHELL_ALIGN(sizeof(struct nif)),
1150 SHELL_ALIGN(sizeof(struct nbinary)),
1151 SHELL_ALIGN(sizeof(struct nbinary)),
1152 SHELL_ALIGN(sizeof(struct nfor)),
1153 SHELL_ALIGN(sizeof(struct ncase)),
1154 SHELL_ALIGN(sizeof(struct nclist)),
1155 SHELL_ALIGN(sizeof(struct narg)),
1156 SHELL_ALIGN(sizeof(struct narg)),
1157 SHELL_ALIGN(sizeof(struct nfile)),
1158 SHELL_ALIGN(sizeof(struct nfile)),
1159 SHELL_ALIGN(sizeof(struct nfile)),
1160 SHELL_ALIGN(sizeof(struct nfile)),
1161 SHELL_ALIGN(sizeof(struct nfile)),
1162 SHELL_ALIGN(sizeof(struct ndup)),
1163 SHELL_ALIGN(sizeof(struct ndup)),
1164 SHELL_ALIGN(sizeof(struct nhere)),
1165 SHELL_ALIGN(sizeof(struct nhere)),
1166 SHELL_ALIGN(sizeof(struct nnot)),
1170 static void calcsize(union node *);
1171 static void sizenodelist(struct nodelist *);
1172 static union node *copynode(union node *);
1173 static struct nodelist *copynodelist(struct nodelist *);
1174 static char *nodesavestr(char *);
1177 static int evalstring(char *, int mask);
1178 union node; /* BLETCH for ansi C */
1179 static void evaltree(union node *, int);
1180 static void evalbackcmd(union node *, struct backcmd *);
1182 static int evalskip; /* set if we are skipping commands */
1183 static int skipcount; /* number of levels to skip */
1184 static int funcnest; /* depth of function calls */
1186 /* reasons for skipping commands (see comment on breakcmd routine) */
1187 #define SKIPBREAK (1 << 0)
1188 #define SKIPCONT (1 << 1)
1189 #define SKIPFUNC (1 << 2)
1190 #define SKIPFILE (1 << 3)
1191 #define SKIPEVAL (1 << 4)
1194 * This file was generated by the mkbuiltins program.
1198 static int bgcmd(int, char **);
1200 static int breakcmd(int, char **);
1201 static int cdcmd(int, char **);
1202 #if ENABLE_ASH_CMDCMD
1203 static int commandcmd(int, char **);
1205 static int dotcmd(int, char **);
1206 static int evalcmd(int, char **);
1207 #if ENABLE_ASH_BUILTIN_ECHO
1208 static int echocmd(int, char **);
1210 #if ENABLE_ASH_BUILTIN_TEST
1211 static int testcmd(int, char **);
1213 static int execcmd(int, char **);
1214 static int exitcmd(int, char **);
1215 static int exportcmd(int, char **);
1216 static int falsecmd(int, char **);
1218 static int fgcmd(int, char **);
1220 #if ENABLE_ASH_GETOPTS
1221 static int getoptscmd(int, char **);
1223 static int hashcmd(int, char **);
1224 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
1225 static int helpcmd(int argc, char **argv);
1228 static int jobscmd(int, char **);
1230 #if ENABLE_ASH_MATH_SUPPORT
1231 static int letcmd(int, char **);
1233 static int localcmd(int, char **);
1234 static int pwdcmd(int, char **);
1235 static int readcmd(int, char **);
1236 static int returncmd(int, char **);
1237 static int setcmd(int, char **);
1238 static int shiftcmd(int, char **);
1239 static int timescmd(int, char **);
1240 static int trapcmd(int, char **);
1241 static int truecmd(int, char **);
1242 static int typecmd(int, char **);
1243 static int umaskcmd(int, char **);
1244 static int unsetcmd(int, char **);
1245 static int waitcmd(int, char **);
1246 static int ulimitcmd(int, char **);
1248 static int killcmd(int, char **);
1254 static void chkmail(void);
1255 static void changemail(const char *);
1260 /* values of cmdtype */
1261 #define CMDUNKNOWN -1 /* no entry in table for command */
1262 #define CMDNORMAL 0 /* command is an executable program */
1263 #define CMDFUNCTION 1 /* command is a shell function */
1264 #define CMDBUILTIN 2 /* command is a shell builtin */
1268 int (*builtin)(int, char **);
1269 /* unsigned flags; */
1273 #define COMMANDCMD (builtincmd + 5 + \
1274 2 * ENABLE_ASH_BUILTIN_TEST + \
1275 ENABLE_ASH_ALIAS + \
1276 ENABLE_ASH_JOB_CONTROL)
1277 #define EXECCMD (builtincmd + 7 + \
1278 2 * ENABLE_ASH_BUILTIN_TEST + \
1279 ENABLE_ASH_ALIAS + \
1280 ENABLE_ASH_JOB_CONTROL + \
1281 ENABLE_ASH_CMDCMD + \
1282 ENABLE_ASH_BUILTIN_ECHO)
1284 #define BUILTIN_NOSPEC "0"
1285 #define BUILTIN_SPECIAL "1"
1286 #define BUILTIN_REGULAR "2"
1287 #define BUILTIN_SPEC_REG "3"
1288 #define BUILTIN_ASSIGN "4"
1289 #define BUILTIN_SPEC_ASSG "5"
1290 #define BUILTIN_REG_ASSG "6"
1291 #define BUILTIN_SPEC_REG_ASSG "7"
1293 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1294 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1295 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1297 /* make sure to keep these in proper order since it is searched via bsearch() */
1298 static const struct builtincmd builtincmd[] = {
1299 { BUILTIN_SPEC_REG ".", dotcmd },
1300 { BUILTIN_SPEC_REG ":", truecmd },
1301 #if ENABLE_ASH_BUILTIN_TEST
1302 { BUILTIN_REGULAR "[", testcmd },
1303 { BUILTIN_REGULAR "[[", testcmd },
1305 #if ENABLE_ASH_ALIAS
1306 { BUILTIN_REG_ASSG "alias", aliascmd },
1309 { BUILTIN_REGULAR "bg", bgcmd },
1311 { BUILTIN_SPEC_REG "break", breakcmd },
1312 { BUILTIN_REGULAR "cd", cdcmd },
1313 { BUILTIN_NOSPEC "chdir", cdcmd },
1314 #if ENABLE_ASH_CMDCMD
1315 { BUILTIN_REGULAR "command", commandcmd },
1317 { BUILTIN_SPEC_REG "continue", breakcmd },
1318 #if ENABLE_ASH_BUILTIN_ECHO
1319 { BUILTIN_REGULAR "echo", echocmd },
1321 { BUILTIN_SPEC_REG "eval", evalcmd },
1322 { BUILTIN_SPEC_REG "exec", execcmd },
1323 { BUILTIN_SPEC_REG "exit", exitcmd },
1324 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1325 { BUILTIN_REGULAR "false", falsecmd },
1327 { BUILTIN_REGULAR "fg", fgcmd },
1329 #if ENABLE_ASH_GETOPTS
1330 { BUILTIN_REGULAR "getopts", getoptscmd },
1332 { BUILTIN_NOSPEC "hash", hashcmd },
1333 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
1334 { BUILTIN_NOSPEC "help", helpcmd },
1337 { BUILTIN_REGULAR "jobs", jobscmd },
1338 { BUILTIN_REGULAR "kill", killcmd },
1340 #if ENABLE_ASH_MATH_SUPPORT
1341 { BUILTIN_NOSPEC "let", letcmd },
1343 { BUILTIN_ASSIGN "local", localcmd },
1344 { BUILTIN_NOSPEC "pwd", pwdcmd },
1345 { BUILTIN_REGULAR "read", readcmd },
1346 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1347 { BUILTIN_SPEC_REG "return", returncmd },
1348 { BUILTIN_SPEC_REG "set", setcmd },
1349 { BUILTIN_SPEC_REG "shift", shiftcmd },
1350 { BUILTIN_SPEC_REG "source", dotcmd },
1351 #if ENABLE_ASH_BUILTIN_TEST
1352 { BUILTIN_REGULAR "test", testcmd },
1354 { BUILTIN_SPEC_REG "times", timescmd },
1355 { BUILTIN_SPEC_REG "trap", trapcmd },
1356 { BUILTIN_REGULAR "true", truecmd },
1357 { BUILTIN_NOSPEC "type", typecmd },
1358 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1359 { BUILTIN_REGULAR "umask", umaskcmd },
1360 #if ENABLE_ASH_ALIAS
1361 { BUILTIN_REGULAR "unalias", unaliascmd },
1363 { BUILTIN_SPEC_REG "unset", unsetcmd },
1364 { BUILTIN_REGULAR "wait", waitcmd },
1367 #define NUMBUILTINS (sizeof(builtincmd) / sizeof(builtincmd[0]))
1374 const struct builtincmd *cmd;
1375 struct funcnode *func;
1380 /* action to find_command() */
1381 #define DO_ERR 0x01 /* prints errors */
1382 #define DO_ABS 0x02 /* checks absolute paths */
1383 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1384 #define DO_ALTPATH 0x08 /* using alternate path */
1385 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1387 static const char *pathopt; /* set by padvance */
1389 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
1390 static char *padvance(const char **, const char *);
1391 static void find_command(char *, struct cmdentry *, int, const char *);
1392 static struct builtincmd *find_builtin(const char *);
1393 static void hashcd(void);
1394 static void changepath(const char *);
1395 static void defun(char *, union node *);
1396 static void unsetfunc(const char *);
1398 #if ENABLE_ASH_MATH_SUPPORT_64
1399 typedef int64_t arith_t;
1400 #define arith_t_type (long long)
1402 typedef long arith_t;
1403 #define arith_t_type (long)
1406 #if ENABLE_ASH_MATH_SUPPORT
1407 static arith_t dash_arith(const char *);
1408 static arith_t arith(const char *expr, int *perrcode);
1411 #if ENABLE_ASH_RANDOM_SUPPORT
1412 static unsigned long rseed;
1413 static void change_random(const char *);
1414 # ifndef DYNAMIC_VAR
1415 # define DYNAMIC_VAR
1421 static void reset(void);
1430 #define VEXPORT 0x01 /* variable is exported */
1431 #define VREADONLY 0x02 /* variable cannot be modified */
1432 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1433 #define VTEXTFIXED 0x08 /* text is statically allocated */
1434 #define VSTACK 0x10 /* text is allocated on the stack */
1435 #define VUNSET 0x20 /* the variable is not set */
1436 #define VNOFUNC 0x40 /* don't call the callback function */
1437 #define VNOSET 0x80 /* do not set variable - just readonly test */
1438 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1440 # define VDYNAMIC 0x200 /* dynamic variable */
1446 struct var *next; /* next entry in hash list */
1447 int flags; /* flags are defined above */
1448 const char *text; /* name=value */
1449 void (*func)(const char *); /* function to be called when */
1450 /* the variable gets set/unset */
1454 struct localvar *next; /* next local variable in list */
1455 struct var *vp; /* the variable that was made local */
1456 int flags; /* saved flags */
1457 const char *text; /* saved text */
1461 static struct localvar *localvars;
1467 #if ENABLE_ASH_GETOPTS
1468 static void getoptsreset(const char *);
1471 #if ENABLE_LOCALE_SUPPORT
1472 static void change_lc_all(const char *value);
1473 static void change_lc_ctype(const char *value);
1479 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1481 static const char defifsvar[] = "IFS= \t\n";
1482 #define defifs (defifsvar + 4)
1484 static const char defifs[] = " \t\n";
1488 static struct var varinit[] = {
1490 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1492 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1496 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1497 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1500 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1501 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1502 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1503 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1504 #if ENABLE_ASH_GETOPTS
1505 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1507 #if ENABLE_ASH_RANDOM_SUPPORT
1508 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1510 #if ENABLE_LOCALE_SUPPORT
1511 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1512 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1514 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1515 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1519 #define vifs varinit[0]
1521 #define vmail (&vifs)[1]
1522 #define vmpath (&vmail)[1]
1526 #define vpath (&vmpath)[1]
1527 #define vps1 (&vpath)[1]
1528 #define vps2 (&vps1)[1]
1529 #define vps4 (&vps2)[1]
1530 #define voptind (&vps4)[1]
1531 #if ENABLE_ASH_GETOPTS
1532 #define vrandom (&voptind)[1]
1534 #define vrandom (&vps4)[1]
1536 #define defpath (defpathvar + 5)
1539 * The following macros access the values of the above variables.
1540 * They have to skip over the name. They return the null string
1541 * for unset variables.
1544 #define ifsval() (vifs.text + 4)
1545 #define ifsset() ((vifs.flags & VUNSET) == 0)
1546 #define mailval() (vmail.text + 5)
1547 #define mpathval() (vmpath.text + 9)
1548 #define pathval() (vpath.text + 5)
1549 #define ps1val() (vps1.text + 4)
1550 #define ps2val() (vps2.text + 4)
1551 #define ps4val() (vps4.text + 4)
1552 #define optindval() (voptind.text + 7)
1554 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1556 static void setvar(const char *, const char *, int);
1557 static void setvareq(char *, int);
1558 static void listsetvar(struct strlist *, int);
1559 static char *lookupvar(const char *);
1560 static char *bltinlookup(const char *);
1561 static char **listvars(int, int, char ***);
1562 #define environment() listvars(VEXPORT, VUNSET, 0)
1563 static int showvars(const char *, int, int);
1564 static void poplocalvars(void);
1565 static int unsetvar(const char *);
1566 #if ENABLE_ASH_GETOPTS
1567 static int setvarsafe(const char *, const char *, int);
1569 static int varcmp(const char *, const char *);
1570 static struct var **hashvar(const char *);
1573 static int varequal(const char *a, const char *b) {
1574 return !varcmp(a, b);
1578 static int loopnest; /* current loop nesting level */
1581 * The parsefile structure pointed to by the global variable parsefile
1582 * contains information about the current file being read.
1587 struct redirtab *next;
1592 static struct redirtab *redirlist;
1593 static int nullredirs;
1595 extern char **environ;
1600 static void outstr(const char *, FILE *);
1601 static void outcslow(int, FILE *);
1602 static void flushall(void);
1603 static void flusherr(void);
1604 static int out1fmt(const char *, ...)
1605 __attribute__((__format__(__printf__,1,2)));
1606 static int fmtstr(char *, size_t, const char *, ...)
1607 __attribute__((__format__(__printf__,3,4)));
1609 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1612 static void out1str(const char *p)
1617 static void out2str(const char *p)
1624 * Initialization code.
1628 * This routine initializes the builtin variables.
1631 static void initvar(void)
1638 * PS1 depends on uid
1640 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1641 vps1.text = "PS1=\\w \\$ ";
1644 vps1.text = "PS1=# ";
1647 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1649 vpp = hashvar(vp->text);
1652 } while (++vp < end);
1655 static void init(void)
1660 basepf.nextc = basepf.buf = basebuf;
1665 signal(SIGCHLD, SIG_DFL);
1673 struct stat st1, st2;
1676 for (envp = environ ; envp && *envp ; envp++) {
1677 if (strchr(*envp, '=')) {
1678 setvareq(*envp, VEXPORT|VTEXTFIXED);
1682 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1683 setvar("PPID", ppid, 0);
1685 p = lookupvar("PWD");
1687 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
1688 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1694 /* PEOF (the end of file marker) */
1697 INPUT_PUSH_FILE = 1,
1698 INPUT_NOFILE_OK = 2,
1702 * The input line number. Input.c just defines this variable, and saves
1703 * and restores it when files are pushed and popped. The user of this
1704 * package must set its value.
1707 static int pgetc(void);
1708 static int pgetc2(void);
1709 static int preadbuffer(void);
1710 static void pungetc(void);
1711 static void pushstring(char *, void *);
1712 static void popstring(void);
1713 static void setinputfd(int, int);
1714 static void setinputstring(char *);
1715 static void popfile(void);
1716 static void popallfiles(void);
1717 static void closescript(void);
1723 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1726 #define FORK_NOJOB 2
1728 /* mode flags for showjob(s) */
1729 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1730 #define SHOW_PID 0x04 /* include process pid */
1731 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1735 * A job structure contains information about a job. A job is either a
1736 * single process or a set of processes contained in a pipeline. In the
1737 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1742 pid_t pid; /* process id */
1743 int status; /* last process status from wait() */
1744 char *cmd; /* text of command being run */
1748 struct procstat ps0; /* status of process */
1749 struct procstat *ps; /* status or processes when more than one */
1751 int stopstatus; /* status of a stopped job */
1754 nprocs: 16, /* number of processes */
1756 #define JOBRUNNING 0 /* at least one proc running */
1757 #define JOBSTOPPED 1 /* all procs are stopped */
1758 #define JOBDONE 2 /* all procs are completed */
1760 sigint: 1, /* job was killed by SIGINT */
1761 jobctl: 1, /* job running under job control */
1763 waited: 1, /* true if this entry has been waited for */
1764 used: 1, /* true if this entry is in used */
1765 changed: 1; /* true if status has changed */
1766 struct job *prev_job; /* previous job */
1769 static pid_t backgndpid; /* pid of last background process */
1770 static int job_warning; /* user was warned about stopped jobs */
1772 static int jobctl; /* true if doing job control */
1775 static struct job *makejob(union node *, int);
1776 static int forkshell(struct job *, union node *, int);
1777 static int waitforjob(struct job *);
1778 static int stoppedjobs(void);
1781 #define setjobctl(on) /* do nothing */
1783 static void setjobctl(int);
1784 static void showjobs(FILE *, int);
1790 /* pid of main shell */
1792 /* shell level: 0 for the main shell, 1 for its children, and so on */
1794 #define rootshell (!shlvl)
1796 static void readcmdfile(char *);
1797 static int cmdloop(int);
1803 struct stack_block *stackp;
1806 struct stackmark *marknext;
1809 /* minimum size of a block */
1810 #define MINSIZE SHELL_ALIGN(504)
1812 struct stack_block {
1813 struct stack_block *prev;
1814 char space[MINSIZE];
1817 static struct stack_block stackbase;
1818 static struct stack_block *stackp = &stackbase;
1819 static struct stackmark *markp;
1820 static char *stacknxt = stackbase.space;
1821 static size_t stacknleft = MINSIZE;
1822 static char *sstrend = stackbase.space + MINSIZE;
1823 static int herefd = -1;
1826 static pointer ckmalloc(size_t);
1827 static pointer ckrealloc(pointer, size_t);
1828 static char *savestr(const char *);
1829 static pointer stalloc(size_t);
1830 static void stunalloc(pointer);
1831 static void setstackmark(struct stackmark *);
1832 static void popstackmark(struct stackmark *);
1833 static void growstackblock(void);
1834 static void *growstackstr(void);
1835 static char *makestrspace(size_t, char *);
1836 static char *stnputs(const char *, size_t, char *);
1837 static char *stputs(const char *, char *);
1840 static char *_STPUTC(int c, char *p) {
1847 #define stackblock() ((void *)stacknxt)
1848 #define stackblocksize() stacknleft
1849 #define STARTSTACKSTR(p) ((p) = stackblock())
1850 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1851 #define CHECKSTRSPACE(n, p) \
1855 size_t m = sstrend - q; \
1857 (p) = makestrspace(l, q); \
1860 #define USTPUTC(c, p) (*p++ = (c))
1861 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1862 #define STUNPUTC(p) (--p)
1863 #define STTOPC(p) p[-1]
1864 #define STADJUST(amount, p) (p += (amount))
1866 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1867 #define ungrabstackstr(s, p) stunalloc((s))
1868 #define stackstrend() ((void *)sstrend)
1870 #define ckfree(p) free((pointer)(p))
1875 #define DOLATSTRLEN 4
1877 static char *prefix(const char *, const char *);
1878 static int number(const char *);
1879 static int is_number(const char *);
1880 static char *single_quote(const char *);
1881 static char *sstrdup(const char *);
1883 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1884 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1889 int nparam; /* # of positional parameters (without $0) */
1890 unsigned char malloc; /* if parameter list dynamically allocated */
1891 char **p; /* parameter list */
1892 #if ENABLE_ASH_GETOPTS
1893 int optind; /* next parameter to be processed by getopts */
1894 int optoff; /* used by getopts */
1899 #define eflag optlist[0]
1900 #define fflag optlist[1]
1901 #define Iflag optlist[2]
1902 #define iflag optlist[3]
1903 #define mflag optlist[4]
1904 #define nflag optlist[5]
1905 #define sflag optlist[6]
1906 #define xflag optlist[7]
1907 #define vflag optlist[8]
1908 #define Cflag optlist[9]
1909 #define aflag optlist[10]
1910 #define bflag optlist[11]
1911 #define uflag optlist[12]
1912 #define viflag optlist[13]
1915 #define nolog optlist[14]
1916 #define debug optlist[15]
1922 static const char *const optletters_optnames[] = {
1943 #define optletters(n) optletters_optnames[(n)][0]
1944 #define optnames(n) (&optletters_optnames[(n)][1])
1946 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1948 static char optlist[NOPTS];
1951 static char *arg0; /* value of $0 */
1952 static struct shparam shellparam; /* $@ current positional parameters */
1953 static char **argptr; /* argument list for builtin commands */
1954 static char *optionarg; /* set by nextopt (like getopt) */
1955 static char *optptr; /* used by nextopt */
1957 static char *minusc; /* argument to -c option */
1960 static void procargs(int, char **);
1961 static void optschanged(void);
1962 static void setparam(char **);
1963 static void freeparam(volatile struct shparam *);
1964 static int shiftcmd(int, char **);
1965 static int setcmd(int, char **);
1966 static int nextopt(const char *);
1970 /* flags passed to redirect */
1971 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1972 #define REDIR_SAVEFD2 03 /* set preverrout */
1975 static void redirect(union node *, int);
1976 static void popredir(int);
1977 static void clearredir(int);
1978 static int copyfd(int, int);
1979 static int redirectsafe(union node *, int);
1985 static void showtree(union node *);
1986 static void trace(const char *, ...);
1987 static void tracev(const char *, va_list);
1988 static void trargs(char **);
1989 static void trputc(int);
1990 static void trputs(const char *);
1991 static void opentrace(void);
1997 /* trap handler commands */
1998 static char *trap[NSIG];
1999 /* current value of signal */
2000 static char sigmode[NSIG - 1];
2001 /* indicates specified signal received */
2002 static char gotsig[NSIG - 1];
2004 static void clear_traps(void);
2005 static void setsignal(int);
2006 static void ignoresig(int);
2007 static void onsig(int);
2008 static int dotrap(void);
2009 static void setinteractive(int);
2010 static void exitshell(void) ATTRIBUTE_NORETURN;
2013 static int is_safe_applet(char *name)
2015 /* It isn't a bug to have non-existent applet here... */
2016 /* ...just a waste of space... */
2017 static const char safe_applets[][8] = {
2021 USE_CHMOD (, "chmod" )
2022 USE_CHOWN (, "chown" )
2026 USE_ECHO (, "echo" )
2027 USE_FIND (, "find" )
2028 USE_HEXDUMP(, "hexdump")
2031 USE_MKDIR (, "mkdir" )
2033 USE_SORT (, "sort" )
2034 USE_TEST (, "test" )
2035 USE_TOUCH (, "touch" )
2036 USE_XARGS (, "xargs" )
2038 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
2040 for (i = 0; i < n; i++)
2041 if (strcmp(safe_applets[i], name) == 0)
2049 * This routine is called when an error or an interrupt occurs in an
2050 * interactive shell and control is returned to the main command loop.
2064 parselleft = parsenleft = 0; /* clear input buffer */
2068 /* from parser.c: */
2080 #if ENABLE_ASH_ALIAS
2081 static struct alias *atab[ATABSIZE];
2083 static void setalias(const char *, const char *);
2084 static struct alias *freealias(struct alias *);
2085 static struct alias **__lookupalias(const char *);
2088 setalias(const char *name, const char *val)
2090 struct alias *ap, **app;
2092 app = __lookupalias(name);
2096 if (!(ap->flag & ALIASINUSE)) {
2099 ap->val = savestr(val);
2100 ap->flag &= ~ALIASDEAD;
2103 ap = ckmalloc(sizeof(struct alias));
2104 ap->name = savestr(name);
2105 ap->val = savestr(val);
2114 unalias(const char *name)
2118 app = __lookupalias(name);
2122 *app = freealias(*app);
2133 struct alias *ap, **app;
2137 for (i = 0; i < ATABSIZE; i++) {
2139 for (ap = *app; ap; ap = *app) {
2140 *app = freealias(*app);
2149 static struct alias *
2150 lookupalias(const char *name, int check)
2152 struct alias *ap = *__lookupalias(name);
2154 if (check && ap && (ap->flag & ALIASINUSE))
2160 * TODO - sort output
2163 aliascmd(int argc, char **argv)
2172 for (i = 0; i < ATABSIZE; i++)
2173 for (ap = atab[i]; ap; ap = ap->next) {
2178 while ((n = *++argv) != NULL) {
2179 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2180 if ((ap = *__lookupalias(n)) == NULL) {
2181 fprintf(stderr, "%s: %s not found\n", "alias", n);
2195 unaliascmd(int argc, char **argv)
2199 while ((i = nextopt("a")) != '\0') {
2205 for (i = 0; *argptr; argptr++) {
2206 if (unalias(*argptr)) {
2207 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2215 static struct alias *
2216 freealias(struct alias *ap) {
2219 if (ap->flag & ALIASINUSE) {
2220 ap->flag |= ALIASDEAD;
2232 printalias(const struct alias *ap) {
2233 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2236 static struct alias **
2237 __lookupalias(const char *name) {
2238 unsigned int hashval;
2245 ch = (unsigned char)*p;
2249 ch = (unsigned char)*++p;
2251 app = &atab[hashval % ATABSIZE];
2253 for (; *app; app = &(*app)->next) {
2254 if (equal(name, (*app)->name)) {
2261 #endif /* ASH_ALIAS */
2267 * The cd and pwd commands.
2270 #define CD_PHYSICAL 1
2273 static int docd(const char *, int);
2274 static int cdopt(void);
2276 static char *curdir = nullstr; /* current working directory */
2277 static char *physdir = nullstr; /* physical working directory */
2286 while ((i = nextopt("LP"))) {
2288 flags ^= CD_PHYSICAL;
2297 cdcmd(int argc, char **argv)
2309 dest = bltinlookup(homestr);
2310 else if (LONE_DASH(dest)) {
2311 dest = bltinlookup("OLDPWD");
2333 if (!(path = bltinlookup("CDPATH"))) {
2341 p = padvance(&path, dest);
2342 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2346 if (!docd(p, flags))
2351 sh_error("can't cd to %s", dest);
2354 if (flags & CD_PRINT)
2355 out1fmt(snlfmt, curdir);
2361 * Update curdir (the name of the current directory) in response to a
2365 static const char * updatepwd(const char *dir)
2372 cdcomppath = sstrdup(dir);
2375 if (curdir == nullstr)
2377 new = stputs(curdir, new);
2379 new = makestrspace(strlen(dir) + 2, new);
2380 lim = stackblock() + 1;
2384 if (new > lim && *lim == '/')
2389 if (dir[1] == '/' && dir[2] != '/') {
2395 p = strtok(cdcomppath, "/");
2399 if (p[1] == '.' && p[2] == '\0') {
2406 } else if (p[1] == '\0')
2410 new = stputs(p, new);
2418 return stackblock();
2422 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2423 * know that the current directory has changed.
2427 docd(const char *dest, int flags)
2429 const char *dir = 0;
2432 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2435 if (!(flags & CD_PHYSICAL)) {
2436 dir = updatepwd(dest);
2451 * Find out what the current directory is. If we already know the current
2452 * directory, this routine returns immediately.
2454 static char * getpwd(void)
2456 char *dir = getcwd(0, 0);
2457 return dir ? dir : nullstr;
2461 pwdcmd(int argc, char **argv)
2464 const char *dir = curdir;
2468 if (physdir == nullstr)
2472 out1fmt(snlfmt, dir);
2477 setpwd(const char *val, int setold)
2481 oldcur = dir = curdir;
2484 setvar("OLDPWD", oldcur, VEXPORT);
2487 if (physdir != nullstr) {
2488 if (physdir != oldcur)
2492 if (oldcur == val || !val) {
2499 if (oldcur != dir && oldcur != nullstr) {
2504 setvar("PWD", dir, VEXPORT);
2510 * Errors and exceptions.
2514 * Code to handle exceptions in C.
2518 static void exverror(int, const char *, va_list) ATTRIBUTE_NORETURN;
2521 * Called to raise an exception. Since C doesn't include exceptions, we
2522 * just do a longjmp to the exception handler. The type of exception is
2523 * stored in the global variable "exception".
2530 if (handler == NULL)
2536 longjmp(handler->loc, 1);
2541 * Called from trap.c when a SIGINT is received. (If the user specifies
2542 * that SIGINT is to be trapped or ignored using the trap builtin, then
2543 * this routine is not called.) Suppressint is nonzero when interrupts
2544 * are held using the INTOFF macro. (The test for iflag is just
2545 * defensive programming.)
2554 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2555 if (!(rootshell && iflag)) {
2556 signal(SIGINT, SIG_DFL);
2566 exvwarning(const char *msg, va_list ap)
2571 fprintf(errs, "%s: ", arg0);
2573 const char *fmt = (!iflag || parsefile->fd) ?
2574 "%s: %d: " : "%s: ";
2575 fprintf(errs, fmt, commandname, startlinno);
2577 vfprintf(errs, msg, ap);
2578 outcslow('\n', errs);
2582 * Exverror is called to raise the error exception. If the second argument
2583 * is not NULL then error prints an error message using printf style
2584 * formatting. It then raises the error exception.
2587 exverror(int cond, const char *msg, va_list ap)
2591 TRACE(("exverror(%d, \"", cond));
2593 TRACE(("\") pid=%d\n", getpid()));
2595 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2598 exvwarning(msg, ap);
2607 sh_error(const char *msg, ...)
2612 exverror(EXERROR, msg, ap);
2619 exerror(int cond, const char *msg, ...)
2624 exverror(cond, msg, ap);
2630 * error/warning routines for external builtins
2634 sh_warnx(const char *fmt, ...)
2639 exvwarning(fmt, ap);
2645 * Return a string describing an error. The returned string may be a
2646 * pointer to a static buffer that will be overwritten on the next call.
2647 * Action describes the operation that got the error.
2651 errmsg(int e, const char *em)
2653 if (e == ENOENT || e == ENOTDIR) {
2663 * Evaluate a command.
2666 /* flags in argument to evaltree */
2667 #define EV_EXIT 01 /* exit after evaluating tree */
2668 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2669 #define EV_BACKCMD 04 /* command executing within back quotes */
2672 static void evalloop(union node *, int);
2673 static void evalfor(union node *, int);
2674 static void evalcase(union node *, int);
2675 static void evalsubshell(union node *, int);
2676 static void expredir(union node *);
2677 static void evalpipe(union node *, int);
2678 static void evalcommand(union node *, int);
2679 static int evalbltin(const struct builtincmd *, int, char **);
2680 static int evalfun(struct funcnode *, int, char **, int);
2681 static void prehash(union node *);
2682 static int bltincmd(int, char **);
2685 static const struct builtincmd bltin = {
2691 * Called to reset things after an exception.
2699 evalcmd(int argc, char **argv)
2708 STARTSTACKSTR(concat);
2711 concat = stputs(p, concat);
2712 if ((p = *ap++) == NULL)
2714 STPUTC(' ', concat);
2716 STPUTC('\0', concat);
2717 p = grabstackstr(concat);
2719 evalstring(p, ~SKIPEVAL);
2727 * Execute a command or commands contained in a string.
2731 evalstring(char *s, int mask)
2734 struct stackmark smark;
2738 setstackmark(&smark);
2741 while ((n = parsecmd(0)) != NEOF) {
2743 popstackmark(&smark);
2757 * Evaluate a parse tree. The value is left in the global variable
2762 evaltree(union node *n, int flags)
2765 void (*evalfn)(union node *, int);
2769 TRACE(("evaltree(NULL) called\n"));
2772 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2773 getpid(), n, n->type, flags));
2777 out1fmt("Node type = %d\n", n->type);
2782 evaltree(n->nnot.com, EV_TESTED);
2783 status = !exitstatus;
2786 expredir(n->nredir.redirect);
2787 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2789 evaltree(n->nredir.n, flags & EV_TESTED);
2790 status = exitstatus;
2795 evalfn = evalcommand;
2797 if (eflag && !(flags & EV_TESTED))
2809 evalfn = evalsubshell;
2821 #error NAND + 1 != NOR
2823 #if NOR + 1 != NSEMI
2824 #error NOR + 1 != NSEMI
2826 isor = n->type - NAND;
2829 (flags | ((isor >> 1) - 1)) & EV_TESTED
2831 if (!exitstatus == isor)
2843 evaltree(n->nif.test, EV_TESTED);
2846 if (exitstatus == 0) {
2849 } else if (n->nif.elsepart) {
2850 n = n->nif.elsepart;
2855 defun(n->narg.text, n->narg.next);
2859 exitstatus = status;
2863 if ((checkexit & exitstatus))
2864 evalskip |= SKIPEVAL;
2865 else if (pendingsigs && dotrap())
2868 if (flags & EV_EXIT) {
2875 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2878 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2882 evalloop(union node *n, int flags)
2892 evaltree(n->nbinary.ch1, EV_TESTED);
2894 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2898 if (evalskip == SKIPBREAK && --skipcount <= 0)
2903 if (n->type != NWHILE)
2907 evaltree(n->nbinary.ch2, flags);
2908 status = exitstatus;
2913 exitstatus = status;
2918 evalfor(union node *n, int flags)
2920 struct arglist arglist;
2923 struct stackmark smark;
2925 setstackmark(&smark);
2926 arglist.lastp = &arglist.list;
2927 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2928 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2933 *arglist.lastp = NULL;
2938 for (sp = arglist.list ; sp ; sp = sp->next) {
2939 setvar(n->nfor.var, sp->text, 0);
2940 evaltree(n->nfor.body, flags);
2942 if (evalskip == SKIPCONT && --skipcount <= 0) {
2946 if (evalskip == SKIPBREAK && --skipcount <= 0)
2953 popstackmark(&smark);
2959 evalcase(union node *n, int flags)
2963 struct arglist arglist;
2964 struct stackmark smark;
2966 setstackmark(&smark);
2967 arglist.lastp = &arglist.list;
2968 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2970 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2971 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2972 if (casematch(patp, arglist.list->text)) {
2973 if (evalskip == 0) {
2974 evaltree(cp->nclist.body, flags);
2981 popstackmark(&smark);
2986 * Kick off a subshell to evaluate a tree.
2990 evalsubshell(union node *n, int flags)
2993 int backgnd = (n->type == NBACKGND);
2996 expredir(n->nredir.redirect);
2997 if (!backgnd && flags & EV_EXIT && !trap[0])
3001 if (forkshell(jp, n, backgnd) == 0) {
3005 flags &=~ EV_TESTED;
3007 redirect(n->nredir.redirect, 0);
3008 evaltreenr(n->nredir.n, flags);
3013 status = waitforjob(jp);
3014 exitstatus = status;
3020 * Compute the names of the files in a redirection list.
3024 expredir(union node *n)
3028 for (redir = n ; redir ; redir = redir->nfile.next) {
3030 memset(&fn, 0, sizeof(struct arglist));
3031 fn.lastp = &fn.list;
3032 switch (redir->type) {
3038 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3039 redir->nfile.expfname = fn.list->text;
3043 if (redir->ndup.vname) {
3044 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3045 if (fn.list != NULL)
3046 fixredir(redir, fn.list->text, 1);
3048 sh_error("redir error");
3057 * Evaluate a pipeline. All the processes in the pipeline are children
3058 * of the process creating the pipeline. (This differs from some versions
3059 * of the shell, which make the last process in a pipeline the parent
3064 evalpipe(union node *n, int flags)
3067 struct nodelist *lp;
3072 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3074 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3078 jp = makejob(n, pipelen);
3080 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3084 if (pipe(pip) < 0) {
3086 sh_error("Pipe call failed");
3089 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3102 evaltreenr(lp->n, flags);
3110 if (n->npipe.backgnd == 0) {
3111 exitstatus = waitforjob(jp);
3112 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3119 * Execute a command inside back quotes. If it's a builtin command, we
3120 * want to save its output in a block obtained from malloc. Otherwise
3121 * we fork off a subprocess and get the output of the command via a pipe.
3122 * Should be called with interrupts off.
3126 evalbackcmd(union node *n, struct backcmd *result)
3138 saveherefd = herefd;
3146 sh_error("Pipe call failed");
3148 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3157 evaltreenr(n, EV_EXIT);
3161 result->fd = pip[0];
3164 herefd = saveherefd;
3166 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3167 result->fd, result->buf, result->nleft, result->jp));
3170 #if ENABLE_ASH_CMDCMD
3171 static char ** parse_command_args(char **argv, const char **path)
3183 if (c == '-' && !*cp) {
3193 /* run 'typecmd' for other options */
3196 } while ((c = *cp++));
3202 static int isassignment(const char *p)
3204 const char *q = endofname(p);
3210 #if ENABLE_ASH_EXPAND_PRMT
3211 static const char *expandstr(const char *ps);
3213 #define expandstr(s) s
3217 * Execute a simple command.
3221 evalcommand(union node *cmd, int flags)
3223 struct stackmark smark;
3225 struct arglist arglist;
3226 struct arglist varlist;
3229 const struct strlist *sp;
3230 struct cmdentry cmdentry;
3238 struct builtincmd *bcmd;
3239 int pseudovarflag = 0;
3241 /* First expand the arguments. */
3242 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3243 setstackmark(&smark);
3244 back_exitstatus = 0;
3246 cmdentry.cmdtype = CMDBUILTIN;
3247 cmdentry.u.cmd = &bltin;
3248 varlist.lastp = &varlist.list;
3249 *varlist.lastp = NULL;
3250 arglist.lastp = &arglist.list;
3251 *arglist.lastp = NULL;
3256 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3257 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3260 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3261 struct strlist **spp;
3263 spp = arglist.lastp;
3264 if (pseudovarflag && isassignment(argp->narg.text))
3265 expandarg(argp, &arglist, EXP_VARTILDE);
3267 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3269 for (sp = *spp; sp; sp = sp->next)
3273 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
3274 for (sp = arglist.list ; sp ; sp = sp->next) {
3275 TRACE(("evalcommand arg: %s\n", sp->text));
3276 *nargv++ = sp->text;
3281 if (iflag && funcnest == 0 && argc > 0)
3282 lastarg = nargv[-1];
3285 expredir(cmd->ncmd.redirect);
3286 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3289 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3290 struct strlist **spp;
3293 spp = varlist.lastp;
3294 expandarg(argp, &varlist, EXP_VARTILDE);
3297 * Modify the command lookup path, if a PATH= assignment
3301 if (varequal(p, path))
3305 /* Print the command if xflag is set. */
3308 const char *p = " %s";
3311 dprintf(preverrout_fd, p, expandstr(ps4val()));
3314 for (n = 0; n < 2; n++) {
3316 dprintf(preverrout_fd, p, sp->text);
3324 full_write(preverrout_fd, "\n", 1);
3330 /* Now locate the command. */
3332 const char *oldpath;
3333 int cmd_flag = DO_ERR;
3338 find_command(argv[0], &cmdentry, cmd_flag, path);
3339 if (cmdentry.cmdtype == CMDUNKNOWN) {
3345 /* implement bltin and command here */
3346 if (cmdentry.cmdtype != CMDBUILTIN)
3349 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3350 if (cmdentry.u.cmd == EXECCMD)
3352 #if ENABLE_ASH_CMDCMD
3353 if (cmdentry.u.cmd == COMMANDCMD) {
3356 nargv = parse_command_args(argv, &path);
3359 argc -= nargv - argv;
3361 cmd_flag |= DO_NOFUNC;
3369 /* We have a redirection error. */
3373 exitstatus = status;
3377 /* Execute the command. */
3378 switch (cmdentry.cmdtype) {
3380 /* Fork off a child process if necessary. */
3381 if (!(flags & EV_EXIT) || trap[0]) {
3383 jp = makejob(cmd, 1);
3384 if (forkshell(jp, cmd, FORK_FG) != 0) {
3385 exitstatus = waitforjob(jp);
3391 listsetvar(varlist.list, VEXPORT|VSTACK);
3392 shellexec(argv, path, cmdentry.u.index);
3396 cmdenviron = varlist.list;
3398 struct strlist *list = cmdenviron;
3400 if (spclbltin > 0 || argc == 0) {
3402 if (cmd_is_exec && argc > 1)
3405 listsetvar(list, i);
3407 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3422 exit_status = j + 128;
3423 exitstatus = exit_status;
3425 if (i == EXINT || spclbltin > 0) {
3427 longjmp(handler->loc, 1);
3434 listsetvar(varlist.list, 0);
3435 if (evalfun(cmdentry.u.func, argc, argv, flags))
3441 popredir(cmd_is_exec);
3443 /* dsl: I think this is intended to be used to support
3444 * '_' in 'vi' command mode during line editing...
3445 * However I implemented that within libedit itself.
3447 setvar("_", lastarg, 0);
3448 popstackmark(&smark);
3452 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3453 char *volatile savecmdname;
3454 struct jmploc *volatile savehandler;
3455 struct jmploc jmploc;
3458 savecmdname = commandname;
3459 if ((i = setjmp(jmploc.loc)))
3461 savehandler = handler;
3463 commandname = argv[0];
3465 optptr = NULL; /* initialize nextopt */
3466 exitstatus = (*cmd->builtin)(argc, argv);
3469 exitstatus |= ferror(stdout);
3471 commandname = savecmdname;
3473 handler = savehandler;
3479 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3481 volatile struct shparam saveparam;
3482 struct localvar *volatile savelocalvars;
3483 struct jmploc *volatile savehandler;
3484 struct jmploc jmploc;
3487 saveparam = shellparam;
3488 savelocalvars = localvars;
3489 if ((e = setjmp(jmploc.loc))) {
3493 savehandler = handler;
3496 shellparam.malloc = 0;
3500 shellparam.nparam = argc - 1;
3501 shellparam.p = argv + 1;
3502 #if ENABLE_ASH_GETOPTS
3503 shellparam.optind = 1;
3504 shellparam.optoff = -1;
3506 evaltree(&func->n, flags & EV_TESTED);
3512 localvars = savelocalvars;
3513 freeparam(&shellparam);
3514 shellparam = saveparam;
3515 handler = savehandler;
3517 evalskip &= ~SKIPFUNC;
3522 static int goodname(const char *p)
3524 return !*endofname(p);
3528 * Search for a command. This is called before we fork so that the
3529 * location of the command will be available in the parent as well as
3530 * the child. The check for "goodname" is an overly conservative
3531 * check that the name will not be subject to expansion.
3535 prehash(union node *n)
3537 struct cmdentry entry;
3539 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
3540 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
3546 * Builtin commands. Builtin commands whose functions are closely
3547 * tied to evaluation are implemented here.
3555 bltincmd(int argc, char **argv)
3558 * Preserve exitstatus of a previous possible redirection
3561 return back_exitstatus;
3566 * Handle break and continue commands. Break, continue, and return are
3567 * all handled by setting the evalskip flag. The evaluation routines
3568 * above all check this flag, and if it is set they start skipping
3569 * commands rather than executing them. The variable skipcount is
3570 * the number of loops to break/continue, or the number of function
3571 * levels to return. (The latter is always 1.) It should probably
3572 * be an error to break out of more loops than exist, but it isn't
3573 * in the standard shell so we don't make it one here.
3577 breakcmd(int argc, char **argv)
3579 int n = argc > 1 ? number(argv[1]) : 1;
3582 sh_error(illnum, argv[1]);
3586 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3594 * The return command.
3598 returncmd(int argc, char **argv)
3601 * If called outside a function, do what ksh does;
3602 * skip the rest of the file.
3604 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3605 return argv[1] ? number(argv[1]) : exitstatus;
3610 falsecmd(int argc, char **argv)
3617 truecmd(int argc, char **argv)
3624 execcmd(int argc, char **argv)
3627 iflag = 0; /* exit on error */
3630 shellexec(argv + 1, pathval(), 0);
3639 * When commands are first encountered, they are entered in a hash table.
3640 * This ensures that a full path search will not have to be done for them
3641 * on each invocation.
3643 * We should investigate converting to a linear search, even though that
3644 * would make the command name "hash" a misnomer.
3647 #define CMDTABLESIZE 31 /* should be prime */
3648 #define ARB 1 /* actual size determined at run time */
3653 struct tblentry *next; /* next entry in hash chain */
3654 union param param; /* definition of builtin function */
3655 short cmdtype; /* index identifying command */
3656 char rehash; /* if set, cd done since entry created */
3657 char cmdname[ARB]; /* name of command */
3661 static struct tblentry *cmdtable[CMDTABLESIZE];
3662 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3665 static void tryexec(char *, char **, char **);
3666 static void clearcmdentry(int);
3667 static struct tblentry *cmdlookup(const char *, int);
3668 static void delete_cmd_entry(void);
3672 * Exec a program. Never returns. If you change this routine, you may
3673 * have to change the find_command routine as well.
3677 shellexec(char **argv, const char *path, int idx)
3685 envp = environment();
3686 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
3687 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3688 || find_applet_by_name(argv[0])
3691 tryexec(argv[0], argv, envp);
3695 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3696 if (--idx < 0 && pathopt == NULL) {
3697 tryexec(cmdname, argv, envp);
3698 if (errno != ENOENT && errno != ENOTDIR)
3705 /* Map to POSIX errors */
3717 exitstatus = exerrno;
3718 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3719 argv[0], e, suppressint ));
3720 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3726 tryexec(char *cmd, char **argv, char **envp)
3729 struct BB_applet *a;
3733 if (strchr(cmd, '/') == NULL
3734 && (a = find_applet_by_name(cmd)) != NULL
3735 && is_safe_applet(cmd)
3738 while (*c != NULL) {
3742 exit(a->main(argc, argv));
3744 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3745 if (find_applet_by_name(cmd) != NULL) {
3746 /* re-exec ourselves with the new arguments */
3747 execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
3748 /* If they called chroot or otherwise made the binary no longer
3749 * executable, fall through */
3756 execve(cmd, argv, envp);
3757 } while (errno == EINTR);
3759 execve(cmd, argv, envp);
3763 } else if (errno == ENOEXEC) {
3767 for (ap = argv; *ap; ap++)
3769 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3771 *ap = cmd = (char *)DEFAULT_SHELL;
3774 while ((*ap++ = *argv++))
3784 * Do a path search. The variable path (passed by reference) should be
3785 * set to the start of the path before the first call; padvance will update
3786 * this value as it proceeds. Successive calls to padvance will return
3787 * the possible path expansions in sequence. If an option (indicated by
3788 * a percent sign) appears in the path entry then the global variable
3789 * pathopt will be set to point to it; otherwise pathopt will be set to
3794 padvance(const char **path, const char *name)
3804 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3805 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3806 while (stackblocksize() < len)
3810 memcpy(q, start, p - start);
3818 while (*p && *p != ':') p++;
3824 return stalloc(len);
3828 /*** Command hashing code ***/
3831 printentry(struct tblentry *cmdp)
3837 idx = cmdp->param.index;
3840 name = padvance(&path, cmdp->cmdname);
3842 } while (--idx >= 0);
3843 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3848 hashcmd(int argc, char **argv)
3850 struct tblentry **pp;
3851 struct tblentry *cmdp;
3853 struct cmdentry entry;
3856 while ((c = nextopt("r")) != '\0') {
3860 if (*argptr == NULL) {
3861 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3862 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3863 if (cmdp->cmdtype == CMDNORMAL)
3870 while ((name = *argptr) != NULL) {
3871 if ((cmdp = cmdlookup(name, 0)) != NULL
3872 && (cmdp->cmdtype == CMDNORMAL
3873 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3875 find_command(name, &entry, DO_ERR, pathval());
3876 if (entry.cmdtype == CMDUNKNOWN)
3885 * Resolve a command name. If you change this routine, you may have to
3886 * change the shellexec routine as well.
3890 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3892 struct tblentry *cmdp;
3899 struct builtincmd *bcmd;
3901 /* If name contains a slash, don't use PATH or hash table */
3902 if (strchr(name, '/') != NULL) {
3903 entry->u.index = -1;
3905 while (stat(name, &statb) < 0) {
3910 entry->cmdtype = CMDUNKNOWN;
3914 entry->cmdtype = CMDNORMAL;
3918 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3919 if (find_applet_by_name(name)) {
3920 entry->cmdtype = CMDNORMAL;
3921 entry->u.index = -1;
3926 if (is_safe_applet(name)) {
3927 entry->cmdtype = CMDNORMAL;
3928 entry->u.index = -1;
3932 updatetbl = (path == pathval());
3935 if (strstr(path, "%builtin") != NULL)
3939 /* If name is in the table, check answer will be ok */
3940 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3943 switch (cmdp->cmdtype) {
3961 } else if (cmdp->rehash == 0)
3962 /* if not invalidated by cd, we're done */
3966 /* If %builtin not in path, check for builtin next */
3967 bcmd = find_builtin(name);
3968 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3969 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3971 goto builtin_success;
3973 /* We have to search path. */
3974 prev = -1; /* where to start */
3975 if (cmdp && cmdp->rehash) { /* doing a rehash */
3976 if (cmdp->cmdtype == CMDBUILTIN)
3979 prev = cmdp->param.index;
3985 while ((fullname = padvance(&path, name)) != NULL) {
3986 stunalloc(fullname);
3989 if (prefix(pathopt, "builtin")) {
3991 goto builtin_success;
3993 } else if (!(act & DO_NOFUNC) &&
3994 prefix(pathopt, "func")) {
3997 /* ignore unimplemented options */
4001 /* if rehash, don't redo absolute path names */
4002 if (fullname[0] == '/' && idx <= prev) {
4005 TRACE(("searchexec \"%s\": no change\n", name));
4008 while (stat(fullname, &statb) < 0) {
4013 if (errno != ENOENT && errno != ENOTDIR)
4017 e = EACCES; /* if we fail, this will be the error */
4018 if (!S_ISREG(statb.st_mode))
4020 if (pathopt) { /* this is a %func directory */
4021 stalloc(strlen(fullname) + 1);
4022 readcmdfile(fullname);
4023 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4024 cmdp->cmdtype != CMDFUNCTION)
4025 sh_error("%s not defined in %s", name, fullname);
4026 stunalloc(fullname);
4029 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4031 entry->cmdtype = CMDNORMAL;
4032 entry->u.index = idx;
4036 cmdp = cmdlookup(name, 1);
4037 cmdp->cmdtype = CMDNORMAL;
4038 cmdp->param.index = idx;
4043 /* We failed. If there was an entry for this command, delete it */
4044 if (cmdp && updatetbl)
4047 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4048 entry->cmdtype = CMDUNKNOWN;
4053 entry->cmdtype = CMDBUILTIN;
4054 entry->u.cmd = bcmd;
4058 cmdp = cmdlookup(name, 1);
4059 cmdp->cmdtype = CMDBUILTIN;
4060 cmdp->param.cmd = bcmd;
4064 entry->cmdtype = cmdp->cmdtype;
4065 entry->u = cmdp->param;
4070 * Wrapper around strcmp for qsort/bsearch/...
4072 static int pstrcmp(const void *a, const void *b)
4074 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4078 * Search the table of builtin commands.
4081 static struct builtincmd *
4082 find_builtin(const char *name)
4084 struct builtincmd *bp;
4087 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4095 * Called when a cd is done. Marks all commands so the next time they
4096 * are executed they will be rehashed.
4102 struct tblentry **pp;
4103 struct tblentry *cmdp;
4105 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4106 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4107 if (cmdp->cmdtype == CMDNORMAL || (
4108 cmdp->cmdtype == CMDBUILTIN &&
4109 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4119 * Fix command hash table when PATH changed.
4120 * Called before PATH is changed. The argument is the new value of PATH;
4121 * pathval() still returns the old value at this point.
4122 * Called with interrupts off.
4126 changepath(const char *newval)
4128 const char *old, *new;
4135 firstchange = 9999; /* assume no change */
4141 if ((*old == '\0' && *new == ':')
4142 || (*old == ':' && *new == '\0'))
4144 old = new; /* ignore subsequent differences */
4148 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4155 if (builtinloc < 0 && idx_bltin >= 0)
4156 builtinloc = idx_bltin; /* zap builtins */
4157 if (builtinloc >= 0 && idx_bltin < 0)
4159 clearcmdentry(firstchange);
4160 builtinloc = idx_bltin;
4165 * Clear out command entries. The argument specifies the first entry in
4166 * PATH which has changed.
4170 clearcmdentry(int firstchange)
4172 struct tblentry **tblp;
4173 struct tblentry **pp;
4174 struct tblentry *cmdp;
4177 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4179 while ((cmdp = *pp) != NULL) {
4180 if ((cmdp->cmdtype == CMDNORMAL &&
4181 cmdp->param.index >= firstchange)
4182 || (cmdp->cmdtype == CMDBUILTIN &&
4183 builtinloc >= firstchange)
4198 * Locate a command in the command hash table. If "add" is nonzero,
4199 * add the command to the table if it is not already present. The
4200 * variable "lastcmdentry" is set to point to the address of the link
4201 * pointing to the entry, so that delete_cmd_entry can delete the
4204 * Interrupts must be off if called with add != 0.
4207 static struct tblentry **lastcmdentry;
4210 static struct tblentry *
4211 cmdlookup(const char *name, int add)
4213 unsigned int hashval;
4215 struct tblentry *cmdp;
4216 struct tblentry **pp;
4219 hashval = (unsigned char)*p << 4;
4221 hashval += (unsigned char)*p++;
4223 pp = &cmdtable[hashval % CMDTABLESIZE];
4224 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4225 if (equal(cmdp->cmdname, name))
4229 if (add && cmdp == NULL) {
4230 cmdp = *pp = ckmalloc(sizeof(struct tblentry) - ARB
4231 + strlen(name) + 1);
4233 cmdp->cmdtype = CMDUNKNOWN;
4234 strcpy(cmdp->cmdname, name);
4241 * Delete the command entry returned on the last lookup.
4245 delete_cmd_entry(void)
4247 struct tblentry *cmdp;
4250 cmdp = *lastcmdentry;
4251 *lastcmdentry = cmdp->next;
4252 if (cmdp->cmdtype == CMDFUNCTION)
4253 freefunc(cmdp->param.func);
4260 * Add a new command entry, replacing any existing command entry for
4261 * the same name - except special builtins.
4264 static void addcmdentry(char *name, struct cmdentry *entry)
4266 struct tblentry *cmdp;
4268 cmdp = cmdlookup(name, 1);
4269 if (cmdp->cmdtype == CMDFUNCTION) {
4270 freefunc(cmdp->param.func);
4272 cmdp->cmdtype = entry->cmdtype;
4273 cmdp->param = entry->u;
4278 * Make a copy of a parse tree.
4281 static struct funcnode * copyfunc(union node *n)
4286 funcblocksize = offsetof(struct funcnode, n);
4289 blocksize = funcblocksize;
4290 f = ckmalloc(blocksize + funcstringsize);
4291 funcblock = (char *) f + offsetof(struct funcnode, n);
4292 funcstring = (char *) f + blocksize;
4299 * Define a shell function.
4303 defun(char *name, union node *func)
4305 struct cmdentry entry;
4308 entry.cmdtype = CMDFUNCTION;
4309 entry.u.func = copyfunc(func);
4310 addcmdentry(name, &entry);
4316 * Delete a function if it exists.
4320 unsetfunc(const char *name)
4322 struct tblentry *cmdp;
4324 cmdp = cmdlookup(name, 0);
4325 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
4330 * Locate and print what a word is...
4334 #if ENABLE_ASH_CMDCMD
4336 describe_command(char *command, int describe_command_verbose)
4338 #define describe_command_verbose 1
4340 describe_command(char *command)
4343 struct cmdentry entry;
4344 struct tblentry *cmdp;
4345 #if ENABLE_ASH_ALIAS
4346 const struct alias *ap;
4348 const char *path = pathval();
4350 if (describe_command_verbose) {
4354 /* First look at the keywords */
4355 if (findkwd(command)) {
4356 out1str(describe_command_verbose ? " is a shell keyword" : command);
4360 #if ENABLE_ASH_ALIAS
4361 /* Then look at the aliases */
4362 if ((ap = lookupalias(command, 0)) != NULL) {
4363 if (describe_command_verbose) {
4364 out1fmt(" is an alias for %s", ap->val);
4373 /* Then check if it is a tracked alias */
4374 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4375 entry.cmdtype = cmdp->cmdtype;
4376 entry.u = cmdp->param;
4378 /* Finally use brute force */
4379 find_command(command, &entry, DO_ABS, path);
4382 switch (entry.cmdtype) {
4384 int j = entry.u.index;
4390 p = padvance(&path, command);
4394 if (describe_command_verbose) {
4396 (cmdp ? " a tracked alias for" : nullstr), p
4405 if (describe_command_verbose) {
4406 out1str(" is a shell function");
4413 if (describe_command_verbose) {
4414 out1fmt(" is a %sshell builtin",
4415 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4416 "special " : nullstr
4424 if (describe_command_verbose) {
4425 out1str(": not found\n");
4431 outstr("\n", stdout);
4436 typecmd(int argc, char **argv)
4441 for (i = 1; i < argc; i++) {
4442 #if ENABLE_ASH_CMDCMD
4443 err |= describe_command(argv[i], 1);
4445 err |= describe_command(argv[i]);
4451 #if ENABLE_ASH_CMDCMD
4453 commandcmd(int argc, char **argv)
4461 while ((c = nextopt("pvV")) != '\0')
4463 verify |= VERIFY_VERBOSE;
4465 verify |= VERIFY_BRIEF;
4471 return describe_command(*argptr, verify - VERIFY_BRIEF);
4480 * Routines to expand arguments to commands. We have to deal with
4481 * backquotes, shell variables, and file metacharacters.
4487 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4488 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4489 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4490 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4491 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4494 * Structure specifying which parts of the string should be searched
4495 * for IFS characters.
4499 struct ifsregion *next; /* next region in list */
4500 int begoff; /* offset of start of region */
4501 int endoff; /* offset of end of region */
4502 int nulonly; /* search for nul bytes only */
4505 /* output of current string */
4506 static char *expdest;
4507 /* list of back quote expressions */
4508 static struct nodelist *argbackq;
4509 /* first struct in list of ifs regions */
4510 static struct ifsregion ifsfirst;
4511 /* last struct in list */
4512 static struct ifsregion *ifslastp;
4513 /* holds expanded arg list */
4514 static struct arglist exparg;
4516 static void argstr(char *, int);
4517 static char *exptilde(char *, char *, int);
4518 static void expbackq(union node *, int, int);
4519 static const char *subevalvar(char *, char *, int, int, int, int, int);
4520 static char *evalvar(char *, int);
4521 static void strtodest(const char *, int, int);
4522 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4523 static ssize_t varvalue(char *, int, int);
4524 static void recordregion(int, int, int);
4525 static void removerecordregions(int);
4526 static void ifsbreakup(char *, struct arglist *);
4527 static void ifsfree(void);
4528 static void expandmeta(struct strlist *, int);
4529 static int patmatch(char *, const char *);
4531 static int cvtnum(arith_t);
4532 static size_t esclen(const char *, const char *);
4533 static char *scanleft(char *, char *, char *, char *, int, int);
4534 static char *scanright(char *, char *, char *, char *, int, int);
4535 static void varunset(const char *, const char *, const char *, int)
4539 #define pmatch(a, b) !fnmatch((a), (b), 0)
4541 * Prepare a pattern for a expmeta (internal glob(3)) call.
4543 * Returns an stalloced string.
4546 static char * preglob(const char *pattern, int quoted, int flag) {
4547 flag |= RMESCAPE_GLOB;
4549 flag |= RMESCAPE_QUOTED;
4551 return _rmescapes((char *)pattern, flag);
4556 esclen(const char *start, const char *p) {
4559 while (p > start && *--p == CTLESC) {
4567 * Expand shell variables and backquotes inside a here document.
4570 static void expandhere(union node *arg, int fd)
4573 expandarg(arg, (struct arglist *)NULL, 0);
4574 full_write(fd, stackblock(), expdest - (char *)stackblock());
4579 * Perform variable substitution and command substitution on an argument,
4580 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4581 * perform splitting and file name expansion. When arglist is NULL, perform
4582 * here document expansion.
4586 expandarg(union node *arg, struct arglist *arglist, int flag)
4591 argbackq = arg->narg.backquote;
4592 STARTSTACKSTR(expdest);
4593 ifsfirst.next = NULL;
4595 argstr(arg->narg.text, flag);
4596 p = _STPUTC('\0', expdest);
4598 if (arglist == NULL) {
4599 return; /* here document expanded */
4601 p = grabstackstr(p);
4602 exparg.lastp = &exparg.list;
4606 if (flag & EXP_FULL) {
4607 ifsbreakup(p, &exparg);
4608 *exparg.lastp = NULL;
4609 exparg.lastp = &exparg.list;
4610 expandmeta(exparg.list, flag);
4612 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4614 sp = (struct strlist *)stalloc(sizeof(struct strlist));
4617 exparg.lastp = &sp->next;
4621 *exparg.lastp = NULL;
4623 *arglist->lastp = exparg.list;
4624 arglist->lastp = exparg.lastp;
4630 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4631 * characters to allow for further processing. Otherwise treat
4632 * $@ like $* since no splitting will be performed.
4636 argstr(char *p, int flag)
4638 static const char spclchars[] = {
4646 CTLBACKQ | CTLQUOTE,
4647 #if ENABLE_ASH_MATH_SUPPORT
4652 const char *reject = spclchars;
4654 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4655 int breakall = flag & EXP_WORD;
4660 if (!(flag & EXP_VARTILDE)) {
4662 } else if (flag & EXP_VARTILDE2) {
4667 if (flag & EXP_TILDE) {
4673 if (*q == CTLESC && (flag & EXP_QWORD))
4676 p = exptilde(p, q, flag);
4679 startloc = expdest - (char *)stackblock();
4681 length += strcspn(p + length, reject);
4683 if (c && (!(c & 0x80)
4684 #if ENABLE_ASH_MATH_SUPPORT
4688 /* c == '=' || c == ':' || c == CTLENDARI */
4693 expdest = stnputs(p, length, expdest);
4694 newloc = expdest - (char *)stackblock();
4695 if (breakall && !inquotes && newloc > startloc) {
4696 recordregion(startloc, newloc, 0);
4707 if (flag & EXP_VARTILDE2) {
4711 flag |= EXP_VARTILDE2;
4716 * sort of a hack - expand tildes in variable
4717 * assignments (after the first '=' and after ':'s).
4726 case CTLENDVAR: /* ??? */
4729 /* "$@" syntax adherence hack */
4732 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4733 (p[4] == CTLQUOTEMARK || (
4734 p[4] == CTLENDVAR &&
4735 p[5] == CTLQUOTEMARK
4738 p = evalvar(p + 1, flag) + 1;
4741 inquotes = !inquotes;
4754 p = evalvar(p, flag);
4758 case CTLBACKQ|CTLQUOTE:
4759 expbackq(argbackq->n, c, quotes);
4760 argbackq = argbackq->next;
4762 #if ENABLE_ASH_MATH_SUPPORT
4775 exptilde(char *startp, char *p, int flag)
4781 int quotes = flag & (EXP_FULL | EXP_CASE);
4786 while ((c = *++p) != '\0') {
4793 if (flag & EXP_VARTILDE)
4803 if (*name == '\0') {
4804 home = lookupvar(homestr);
4806 if ((pw = getpwnam(name)) == NULL)
4810 if (!home || !*home)
4813 startloc = expdest - (char *)stackblock();
4814 strtodest(home, SQSYNTAX, quotes);
4815 recordregion(startloc, expdest - (char *)stackblock(), 0);
4824 removerecordregions(int endoff)
4826 if (ifslastp == NULL)
4829 if (ifsfirst.endoff > endoff) {
4830 while (ifsfirst.next != NULL) {
4831 struct ifsregion *ifsp;
4833 ifsp = ifsfirst.next->next;
4834 ckfree(ifsfirst.next);
4835 ifsfirst.next = ifsp;
4838 if (ifsfirst.begoff > endoff)
4841 ifslastp = &ifsfirst;
4842 ifsfirst.endoff = endoff;
4847 ifslastp = &ifsfirst;
4848 while (ifslastp->next && ifslastp->next->begoff < endoff)
4849 ifslastp=ifslastp->next;
4850 while (ifslastp->next != NULL) {
4851 struct ifsregion *ifsp;
4853 ifsp = ifslastp->next->next;
4854 ckfree(ifslastp->next);
4855 ifslastp->next = ifsp;
4858 if (ifslastp->endoff > endoff)
4859 ifslastp->endoff = endoff;
4863 #if ENABLE_ASH_MATH_SUPPORT
4865 * Expand arithmetic expression. Backup to start of expression,
4866 * evaluate, place result in (backed up) result, adjust string position.
4879 * This routine is slightly over-complicated for
4880 * efficiency. Next we scan backwards looking for the
4881 * start of arithmetic.
4883 start = stackblock();
4890 while (*p != CTLARI) {
4894 sh_error("missing CTLARI (shouldn't happen)");
4899 esc = esclen(start, p);
4909 removerecordregions(begoff);
4918 len = cvtnum(dash_arith(p + 2));
4921 recordregion(begoff, begoff + len, 0);
4926 * Expand stuff in backwards quotes.
4930 expbackq(union node *cmd, int quoted, int quotes)
4938 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4939 struct stackmark smark;
4942 setstackmark(&smark);
4944 startloc = dest - (char *)stackblock();
4946 evalbackcmd(cmd, (struct backcmd *) &in);
4947 popstackmark(&smark);
4954 memtodest(p, i, syntax, quotes);
4958 i = safe_read(in.fd, buf, sizeof(buf));
4959 TRACE(("expbackq: read returns %d\n", i));
4969 back_exitstatus = waitforjob(in.jp);
4973 /* Eat all trailing newlines */
4975 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4980 recordregion(startloc, dest - (char *)stackblock(), 0);
4981 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4982 (dest - (char *)stackblock()) - startloc,
4983 (dest - (char *)stackblock()) - startloc,
4984 stackblock() + startloc));
4989 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5000 const char *s = loc2;
5006 match = pmatch(str, s);
5010 if (quotes && *loc == CTLESC)
5020 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5027 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5030 const char *s = loc2;
5035 match = pmatch(str, s);
5042 esc = esclen(startp, loc);
5054 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5058 int saveherefd = herefd;
5059 struct nodelist *saveargbackq = argbackq;
5061 char *rmesc, *rmescend;
5063 char *(*scan)(char *, char *, char *, char *, int , int);
5066 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5067 STPUTC('\0', expdest);
5068 herefd = saveherefd;
5069 argbackq = saveargbackq;
5070 startp = stackblock() + startloc;
5074 setvar(str, startp, 0);
5075 amount = startp - expdest;
5076 STADJUST(amount, expdest);
5080 varunset(p, str, startp, varflags);
5084 subtype -= VSTRIMRIGHT;
5086 if (subtype < 0 || subtype > 3)
5091 rmescend = stackblock() + strloc;
5093 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5094 if (rmesc != startp) {
5096 startp = stackblock() + startloc;
5100 str = stackblock() + strloc;
5101 preglob(str, varflags & VSQUOTE, 0);
5103 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5104 zero = subtype >> 1;
5105 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5106 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5108 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5111 memmove(startp, loc, str - loc);
5112 loc = startp + (str - loc) - 1;
5115 amount = loc - expdest;
5116 STADJUST(amount, expdest);
5123 * Expand a variable, and return a pointer to the next character in the
5127 evalvar(char *p, int flag)
5140 quotes = flag & (EXP_FULL | EXP_CASE);
5142 subtype = varflags & VSTYPE;
5143 quoted = varflags & VSQUOTE;
5145 easy = (!quoted || (*var == '@' && shellparam.nparam));
5146 startloc = expdest - (char *)stackblock();
5147 p = strchr(p, '=') + 1;
5150 varlen = varvalue(var, varflags, flag);
5151 if (varflags & VSNUL)
5154 if (subtype == VSPLUS) {
5155 varlen = -1 - varlen;
5159 if (subtype == VSMINUS) {
5163 p, flag | EXP_TILDE |
5164 (quoted ? EXP_QWORD : EXP_WORD)
5173 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5175 if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5178 * Remove any recorded regions beyond
5181 removerecordregions(startloc);
5191 if (varlen < 0 && uflag)
5192 varunset(p, var, 0, 0);
5194 if (subtype == VSLENGTH) {
5195 cvtnum(varlen > 0 ? varlen : 0);
5199 if (subtype == VSNORMAL) {
5203 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5212 case VSTRIMRIGHTMAX:
5221 * Terminate the string and start recording the pattern
5224 STPUTC('\0', expdest);
5225 patloc = expdest - (char *)stackblock();
5226 if (subevalvar(p, NULL, patloc, subtype,
5227 startloc, varflags, quotes) == 0) {
5228 int amount = expdest - (
5229 (char *)stackblock() + patloc - 1
5231 STADJUST(-amount, expdest);
5233 /* Remove any recorded regions beyond start of variable */
5234 removerecordregions(startloc);
5239 if (subtype != VSNORMAL) { /* skip to end of alternative */
5242 if ((c = *p++) == CTLESC)
5244 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5246 argbackq = argbackq->next;
5247 } else if (c == CTLVAR) {
5248 if ((*p++ & VSTYPE) != VSNORMAL)
5250 } else if (c == CTLENDVAR) {
5261 * Put a string on the stack.
5265 memtodest(const char *p, size_t len, int syntax, int quotes) {
5268 q = makestrspace(len * 2, q);
5271 int c = SC2INT(*p++);
5274 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5284 strtodest(const char *p, int syntax, int quotes)
5286 memtodest(p, strlen(p), syntax, quotes);
5291 * Add the value of a specialized variable to the stack string.
5295 varvalue(char *name, int varflags, int flags)
5305 int quoted = varflags & VSQUOTE;
5306 int subtype = varflags & VSTYPE;
5307 int quotes = flags & (EXP_FULL | EXP_CASE);
5309 if (quoted && (flags & EXP_FULL))
5310 sep = 1 << CHAR_BIT;
5312 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5321 num = shellparam.nparam;
5331 p = makestrspace(NOPTS, expdest);
5332 for (i = NOPTS - 1; i >= 0; i--) {
5334 USTPUTC(optletters(i), p);
5345 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5346 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5349 if (!(ap = shellparam.p))
5351 while ((p = *ap++)) {
5354 partlen = strlen(p);
5357 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5358 memtodest(p, partlen, syntax, quotes);
5364 if (subtype == VSPLUS || subtype == VSLENGTH) {
5386 if (num < 0 || num > shellparam.nparam)
5388 p = num ? shellparam.p[num - 1] : arg0;
5391 p = lookupvar(name);
5397 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5398 memtodest(p, len, syntax, quotes);
5402 if (subtype == VSPLUS || subtype == VSLENGTH)
5403 STADJUST(-len, expdest);
5409 * Record the fact that we have to scan this region of the
5410 * string for IFS characters.
5414 recordregion(int start, int end, int nulonly)
5416 struct ifsregion *ifsp;
5418 if (ifslastp == NULL) {
5422 ifsp = (struct ifsregion *)ckmalloc(sizeof(struct ifsregion));
5424 ifslastp->next = ifsp;
5428 ifslastp->begoff = start;
5429 ifslastp->endoff = end;
5430 ifslastp->nulonly = nulonly;
5435 * Break the argument string into pieces based upon IFS and add the
5436 * strings to the argument list. The regions of the string to be
5437 * searched for IFS characters have been stored by recordregion.
5440 ifsbreakup(char *string, struct arglist *arglist)
5442 struct ifsregion *ifsp;
5447 const char *ifs, *realifs;
5452 if (ifslastp != NULL) {
5455 realifs = ifsset() ? ifsval() : defifs;
5458 p = string + ifsp->begoff;
5459 nulonly = ifsp->nulonly;
5460 ifs = nulonly ? nullstr : realifs;
5462 while (p < string + ifsp->endoff) {
5466 if (strchr(ifs, *p)) {
5468 ifsspc = (strchr(defifs, *p) != NULL);
5469 /* Ignore IFS whitespace at start */
5470 if (q == start && ifsspc) {
5476 sp = (struct strlist *)stalloc(sizeof(*sp));
5478 *arglist->lastp = sp;
5479 arglist->lastp = &sp->next;
5483 if (p >= string + ifsp->endoff) {
5489 if (strchr(ifs, *p) == NULL ) {
5492 } else if (strchr(defifs, *p) == NULL) {
5508 } while ((ifsp = ifsp->next) != NULL);
5517 sp = (struct strlist *)stalloc(sizeof(*sp));
5519 *arglist->lastp = sp;
5520 arglist->lastp = &sp->next;
5526 struct ifsregion *p;
5531 struct ifsregion *ifsp;
5537 ifsfirst.next = NULL;
5541 static void expmeta(char *, char *);
5542 static struct strlist *expsort(struct strlist *);
5543 static struct strlist *msort(struct strlist *, int);
5545 static char *expdir;
5549 expandmeta(struct strlist *str, int flag)
5551 static const char metachars[] = {
5554 /* TODO - EXP_REDIR */
5557 struct strlist **savelastp;
5563 if (!strpbrk(str->text, metachars))
5565 savelastp = exparg.lastp;
5568 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5570 int i = strlen(str->text);
5571 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5579 if (exparg.lastp == savelastp) {
5584 *exparg.lastp = str;
5585 rmescapes(str->text);
5586 exparg.lastp = &str->next;
5588 *exparg.lastp = NULL;
5589 *savelastp = sp = expsort(*savelastp);
5590 while (sp->next != NULL)
5592 exparg.lastp = &sp->next;
5599 * Add a file name to the list.
5603 addfname(const char *name)
5607 sp = (struct strlist *)stalloc(sizeof(*sp));
5608 sp->text = sstrdup(name);
5610 exparg.lastp = &sp->next;
5615 * Do metacharacter (i.e. *, ?, [...]) expansion.
5619 expmeta(char *enddir, char *name)
5634 for (p = name; *p; p++) {
5635 if (*p == '*' || *p == '?')
5637 else if (*p == '[') {
5644 if (*q == '/' || *q == '\0')
5651 } else if (*p == '\\')
5653 else if (*p == '/') {
5660 if (metaflag == 0) { /* we've reached the end of the file name */
5661 if (enddir != expdir)
5669 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5680 } while (p < start);
5682 if (enddir == expdir) {
5684 } else if (enddir == expdir + 1 && *expdir == '/') {
5690 if ((dirp = opendir(cp)) == NULL)
5692 if (enddir != expdir)
5694 if (*endname == 0) {
5706 while (! intpending && (dp = readdir(dirp)) != NULL) {
5707 if (dp->d_name[0] == '.' && ! matchdot)
5709 if (pmatch(start, dp->d_name)) {
5711 scopy(dp->d_name, enddir);
5714 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
5717 expmeta(p, endname);
5727 * Sort the results of file name expansion. It calculates the number of
5728 * strings to sort and then calls msort (short for merge sort) to do the
5732 static struct strlist *
5733 expsort(struct strlist *str)
5739 for (sp = str ; sp ; sp = sp->next)
5741 return msort(str, len);
5745 static struct strlist *
5746 msort(struct strlist *list, int len)
5748 struct strlist *p, *q = NULL;
5749 struct strlist **lpp;
5757 for (n = half ; --n >= 0 ; ) {
5761 q->next = NULL; /* terminate first half of list */
5762 q = msort(list, half); /* sort first half of list */
5763 p = msort(p, len - half); /* sort second half */
5766 #if ENABLE_LOCALE_SUPPORT
5767 if (strcoll(p->text, q->text) < 0)
5769 if (strcmp(p->text, q->text) < 0)
5774 if ((p = *lpp) == NULL) {
5781 if ((q = *lpp) == NULL) {
5792 * Returns true if the pattern matches the string.
5795 static int patmatch(char *pattern, const char *string)
5797 return pmatch(preglob(pattern, 0, 0), string);
5802 * Remove any CTLESC characters from a string.
5806 _rmescapes(char *str, int flag)
5809 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5814 p = strpbrk(str, qchars);
5820 if (flag & RMESCAPE_ALLOC) {
5821 size_t len = p - str;
5822 size_t fulllen = len + strlen(p) + 1;
5824 if (flag & RMESCAPE_GROW) {
5825 r = makestrspace(fulllen, expdest);
5826 } else if (flag & RMESCAPE_HEAP) {
5827 r = ckmalloc(fulllen);
5829 r = stalloc(fulllen);
5833 q = memcpy(q, str, len) + len;
5836 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5837 globbing = flag & RMESCAPE_GLOB;
5838 notescaped = globbing;
5840 if (*p == CTLQUOTEMARK) {
5841 inquotes = ~inquotes;
5843 notescaped = globbing;
5847 /* naked back slash */
5853 if (notescaped && inquotes && *p != '/') {
5857 notescaped = globbing;
5862 if (flag & RMESCAPE_GROW) {
5864 STADJUST(q - r + 1, expdest);
5871 * See if a pattern matches in a case statement.
5875 casematch(union node *pattern, char *val)
5877 struct stackmark smark;
5880 setstackmark(&smark);
5881 argbackq = pattern->narg.backquote;
5882 STARTSTACKSTR(expdest);
5884 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5885 STACKSTRNUL(expdest);
5886 result = patmatch(stackblock(), val);
5887 popstackmark(&smark);
5900 expdest = makestrspace(32, expdest);
5901 #if ENABLE_ASH_MATH_SUPPORT_64
5902 len = fmtstr(expdest, 32, "%lld", (long long) num);
5904 len = fmtstr(expdest, 32, "%ld", num);
5906 STADJUST(len, expdest);
5911 varunset(const char *end, const char *var, const char *umsg, int varflags)
5917 msg = "parameter not set";
5919 if (*end == CTLENDVAR) {
5920 if (varflags & VSNUL)
5925 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5932 * This implements the input routines used by the parser.
5935 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5937 static void pushfile(void);
5940 * Read a character from the script, returning PEOF on end of file.
5941 * Nul characters in the input are silently discarded.
5945 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5947 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
5948 #define pgetc_macro() pgetc()
5952 return pgetc_as_macro();
5955 #define pgetc_macro() pgetc_as_macro()
5959 return pgetc_macro();
5965 * Same as pgetc(), but ignores PEOA.
5967 #if ENABLE_ASH_ALIAS
5968 static int pgetc2(void)
5974 } while (c == PEOA);
5978 static int pgetc2(void)
5980 return pgetc_macro();
5985 * Read a line from the script.
5988 static char * pfgets(char *line, int len)
5994 while (--nleft > 0) {
6010 #if ENABLE_FEATURE_EDITING
6011 static line_input_t *line_input_state;
6012 //static SKIP_ASH_EXPAND_PRMT(const) char *cmdedit_prompt;
6013 static const char *cmdedit_prompt;
6014 static void putprompt(const char *s)
6016 if (ENABLE_ASH_EXPAND_PRMT) {
6017 free((char*)cmdedit_prompt);
6018 cmdedit_prompt = xstrdup(s);
6024 static void putprompt(const char *s)
6030 #if ENABLE_FEATURE_EDITING_VI
6031 #define setvimode(on) do { \
6032 if (on) line_input_state->flags |= VI_MODE; \
6033 else line_input_state->flags &= ~VI_MODE; \
6036 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
6040 static int preadfd(void)
6043 char *buf = parsefile->buf;
6047 #if ENABLE_FEATURE_EDITING
6048 if (!iflag || parsefile->fd)
6049 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6051 #if ENABLE_FEATURE_TAB_COMPLETION
6052 line_input_state->path_lookup = pathval();
6054 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
6056 /* Ctrl+C pressed */
6065 if (nr < 0 && errno == 0) {
6066 /* Ctrl+D presend */
6071 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6075 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6076 int flags = fcntl(0, F_GETFL, 0);
6077 if (flags >= 0 && flags & O_NONBLOCK) {
6078 flags &=~ O_NONBLOCK;
6079 if (fcntl(0, F_SETFL, flags) >= 0) {
6080 out2str("sh: turning off NDELAY mode\n");
6090 * Refill the input buffer and return the next input character:
6092 * 1) If a string was pushed back on the input, pop it;
6093 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6094 * from a string so we can't refill the buffer, return EOF.
6095 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6096 * 4) Process input up to the next newline, deleting nul characters.
6106 while (parsefile->strpush) {
6107 #if ENABLE_ASH_ALIAS
6108 if (parsenleft == -1 && parsefile->strpush->ap &&
6109 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6114 if (--parsenleft >= 0)
6115 return SC2INT(*parsenextc++);
6117 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6124 if ((more = preadfd()) <= 0) {
6125 parselleft = parsenleft = EOF_NLEFT;
6132 /* delete nul characters */
6140 memmove(q, q + 1, more);
6144 parsenleft = q - parsenextc - 1;
6150 parsenleft = q - parsenextc - 1;
6162 out2str(parsenextc);
6167 return SC2INT(*parsenextc++);
6171 * Undo the last call to pgetc. Only one character may be pushed back.
6172 * PEOF may be pushed back.
6183 * Push a string back onto the input at this current parsefile level.
6184 * We handle aliases this way.
6187 pushstring(char *s, void *ap)
6194 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6195 if (parsefile->strpush) {
6196 sp = ckmalloc(sizeof(struct strpush));
6197 sp->prev = parsefile->strpush;
6198 parsefile->strpush = sp;
6200 sp = parsefile->strpush = &(parsefile->basestrpush);
6201 sp->prevstring = parsenextc;
6202 sp->prevnleft = parsenleft;
6203 #if ENABLE_ASH_ALIAS
6204 sp->ap = (struct alias *)ap;
6206 ((struct alias *)ap)->flag |= ALIASINUSE;
6218 struct strpush *sp = parsefile->strpush;
6221 #if ENABLE_ASH_ALIAS
6223 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6224 checkkwd |= CHKALIAS;
6226 if (sp->string != sp->ap->val) {
6229 sp->ap->flag &= ~ALIASINUSE;
6230 if (sp->ap->flag & ALIASDEAD) {
6231 unalias(sp->ap->name);
6235 parsenextc = sp->prevstring;
6236 parsenleft = sp->prevnleft;
6237 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6238 parsefile->strpush = sp->prev;
6239 if (sp != &(parsefile->basestrpush))
6245 * Set the input to take input from a file. If push is set, push the
6246 * old input onto the stack first.
6250 setinputfile(const char *fname, int flags)
6256 if ((fd = open(fname, O_RDONLY)) < 0) {
6257 if (flags & INPUT_NOFILE_OK)
6259 sh_error("Can't open %s", fname);
6262 fd2 = copyfd(fd, 10);
6265 sh_error("Out of file descriptors");
6268 setinputfd(fd, flags & INPUT_PUSH_FILE);
6276 * Like setinputfile, but takes an open file descriptor. Call this with
6281 setinputfd(int fd, int push)
6283 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6289 if (parsefile->buf == NULL)
6290 parsefile->buf = ckmalloc(IBUFSIZ);
6291 parselleft = parsenleft = 0;
6297 * Like setinputfile, but takes input from a string.
6301 setinputstring(char *string)
6305 parsenextc = string;
6306 parsenleft = strlen(string);
6307 parsefile->buf = NULL;
6314 * To handle the "." command, a stack of input files is used. Pushfile
6315 * adds a new entry to the stack and popfile restores the previous level.
6321 struct parsefile *pf;
6323 parsefile->nleft = parsenleft;
6324 parsefile->lleft = parselleft;
6325 parsefile->nextc = parsenextc;
6326 parsefile->linno = plinno;
6327 pf = (struct parsefile *)ckmalloc(sizeof(struct parsefile));
6328 pf->prev = parsefile;
6331 pf->basestrpush.prev = NULL;
6339 struct parsefile *pf = parsefile;
6348 parsefile = pf->prev;
6350 parsenleft = parsefile->nleft;
6351 parselleft = parsefile->lleft;
6352 parsenextc = parsefile->nextc;
6353 plinno = parsefile->linno;
6359 * Return to top level.
6365 while (parsefile != &basepf)
6371 * Close the file(s) that the shell is reading commands from. Called
6372 * after a fork is done.
6379 if (parsefile->fd > 0) {
6380 close(parsefile->fd);
6387 /* mode flags for set_curjob */
6388 #define CUR_DELETE 2
6389 #define CUR_RUNNING 1
6390 #define CUR_STOPPED 0
6392 /* mode flags for dowait */
6393 #define DOWAIT_NORMAL 0
6394 #define DOWAIT_BLOCK 1
6397 static struct job *jobtab;
6399 static unsigned njobs;
6401 /* pgrp of shell on invocation */
6402 static int initialpgrp;
6403 static int ttyfd = -1;
6406 static struct job *curjob;
6407 /* number of presumed living untracked jobs */
6410 static void set_curjob(struct job *, unsigned);
6412 static int restartjob(struct job *, int);
6413 static void xtcsetpgrp(int, pid_t);
6414 static char *commandtext(union node *);
6415 static void cmdlist(union node *, int);
6416 static void cmdtxt(union node *);
6417 static void cmdputs(const char *);
6418 static void showpipe(struct job *, FILE *);
6420 static int sprint_status(char *, int, int);
6421 static void freejob(struct job *);
6422 static struct job *getjob(const char *, int);
6423 static struct job *growjobtab(void);
6424 static void forkchild(struct job *, union node *, int);
6425 static void forkparent(struct job *, union node *, int, pid_t);
6426 static int dowait(int, struct job *);
6427 static int getstatus(struct job *);
6430 set_curjob(struct job *jp, unsigned mode)
6433 struct job **jpp, **curp;
6435 /* first remove from list */
6436 jpp = curp = &curjob;
6441 jpp = &jp1->prev_job;
6443 *jpp = jp1->prev_job;
6445 /* Then re-insert in correct position */
6453 /* job being deleted */
6456 /* newly created job or backgrounded job,
6457 put after all stopped jobs. */
6461 if (!jp1 || jp1->state != JOBSTOPPED)
6464 jpp = &jp1->prev_job;
6470 /* newly stopped job - becomes curjob */
6471 jp->prev_job = *jpp;
6479 * Turn job control on and off.
6481 * Note: This code assumes that the third arg to ioctl is a character
6482 * pointer, which is true on Berkeley systems but not System V. Since
6483 * System V doesn't have job control yet, this isn't a problem now.
6485 * Called with interrupts off.
6494 if (on == jobctl || rootshell == 0)
6498 ofd = fd = open(_PATH_TTY, O_RDWR);
6500 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
6501 * That sometimes helps to acquire controlling tty.
6502 * Obviously, a workaround for bugs when someone
6503 * failed to provide a controlling tty to bash! :) */
6505 while (!isatty(fd) && --fd >= 0)
6508 fd = fcntl(fd, F_DUPFD, 10);
6512 fcntl(fd, F_SETFD, FD_CLOEXEC);
6513 do { /* while we are in the background */
6514 if ((pgrp = tcgetpgrp(fd)) < 0) {
6516 sh_warnx("can't access tty; job control turned off");
6520 if (pgrp == getpgrp())
6531 xtcsetpgrp(fd, pgrp);
6533 /* turning job control off */
6536 xtcsetpgrp(fd, pgrp);
6550 killcmd(int argc, char **argv)
6561 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6562 "kill -l [exitstatus]"
6566 if (**++argv == '-') {
6567 signo = get_signum(*argv + 1);
6571 while ((c = nextopt("ls:")) != '\0')
6581 signo = get_signum(optionarg);
6584 "invalid signal number or name: %s",
6595 if (!list && signo < 0)
6598 if ((signo < 0 || !*argv) ^ list) {
6606 for (i = 1; i < NSIG; i++) {
6607 name = get_signame(i);
6609 out1fmt(snlfmt, name);
6613 name = get_signame(signo);
6615 out1fmt(snlfmt, name);
6617 sh_error("invalid signal number or exit status: %s", *argptr);
6623 if (**argv == '%') {
6624 jp = getjob(*argv, 0);
6625 pid = -jp->ps[0].pid;
6627 pid = **argv == '-' ?
6628 -number(*argv + 1) : number(*argv);
6630 if (kill(pid, signo) != 0) {
6631 sh_warnx("(%d) - %m", pid);
6642 jobno(const struct job *jp)
6644 return jp - jobtab + 1;
6650 fgcmd(int argc, char **argv)
6657 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6662 jp = getjob(*argv, 1);
6663 if (mode == FORK_BG) {
6664 set_curjob(jp, CUR_RUNNING);
6665 fprintf(out, "[%d] ", jobno(jp));
6667 outstr(jp->ps->cmd, out);
6669 retval = restartjob(jp, mode);
6670 } while (*argv && *++argv);
6674 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6678 restartjob(struct job *jp, int mode)
6680 struct procstat *ps;
6686 if (jp->state == JOBDONE)
6688 jp->state = JOBRUNNING;
6690 if (mode == FORK_FG)
6691 xtcsetpgrp(ttyfd, pgid);
6692 killpg(pgid, SIGCONT);
6696 if (WIFSTOPPED(ps->status)) {
6699 } while (ps++, --i);
6701 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6708 sprint_status(char *s, int status, int sigonly)
6714 if (!WIFEXITED(status)) {
6716 if (WIFSTOPPED(status))
6717 st = WSTOPSIG(status);
6720 st = WTERMSIG(status);
6722 if (st == SIGINT || st == SIGPIPE)
6725 if (WIFSTOPPED(status))
6730 col = fmtstr(s, 32, strsignal(st));
6731 if (WCOREDUMP(status)) {
6732 col += fmtstr(s + col, 16, " (core dumped)");
6734 } else if (!sigonly) {
6735 st = WEXITSTATUS(status);
6737 col = fmtstr(s, 16, "Done(%d)", st);
6739 col = fmtstr(s, 16, "Done");
6748 showjob(FILE *out, struct job *jp, int mode)
6750 struct procstat *ps;
6751 struct procstat *psend;
6758 if (mode & SHOW_PGID) {
6759 /* just output process (group) id of pipeline */
6760 fprintf(out, "%d\n", ps->pid);
6764 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6769 else if (curjob && jp == curjob->prev_job)
6772 if (mode & SHOW_PID)
6773 col += fmtstr(s + col, 16, "%d ", ps->pid);
6775 psend = ps + jp->nprocs;
6777 if (jp->state == JOBRUNNING) {
6778 scopy("Running", s + col);
6779 col += strlen("Running");
6781 int status = psend[-1].status;
6783 if (jp->state == JOBSTOPPED)
6784 status = jp->stopstatus;
6786 col += sprint_status(s + col, status, 0);
6792 /* for each process */
6793 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6796 fprintf(out, "%s%*c%s",
6797 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6799 if (!(mode & SHOW_PID)) {
6803 if (++ps == psend) {
6804 outcslow('\n', out);
6811 if (jp->state == JOBDONE) {
6812 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6819 jobscmd(int argc, char **argv)
6825 while ((m = nextopt("lp")))
6835 showjob(out, getjob(*argv,0), mode);
6838 showjobs(out, mode);
6845 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6846 * statuses have changed since the last call to showjobs.
6850 showjobs(FILE *out, int mode)
6854 TRACE(("showjobs(%x) called\n", mode));
6856 /* If not even one one job changed, there is nothing to do */
6857 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6860 for (jp = curjob; jp; jp = jp->prev_job) {
6861 if (!(mode & SHOW_CHANGED) || jp->changed)
6862 showjob(out, jp, mode);
6868 * Mark a job structure as unused.
6872 freejob(struct job *jp)
6874 struct procstat *ps;
6878 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6879 if (ps->cmd != nullstr)
6882 if (jp->ps != &jp->ps0)
6885 set_curjob(jp, CUR_DELETE);
6891 waitcmd(int argc, char **argv)
6904 /* wait for all jobs */
6909 /* no running procs */
6912 if (jp->state == JOBRUNNING)
6917 dowait(DOWAIT_BLOCK, 0);
6923 if (**argv != '%') {
6924 pid_t pid = number(*argv);
6928 if (job->ps[job->nprocs - 1].pid == pid)
6930 job = job->prev_job;
6936 job = getjob(*argv, 0);
6937 /* loop until process terminated or stopped */
6938 while (job->state == JOBRUNNING)
6939 dowait(DOWAIT_BLOCK, 0);
6941 retval = getstatus(job);
6952 * Convert a job name to a job structure.
6956 getjob(const char *name, int getctl)
6960 const char *err_msg = "No such job: %s";
6964 char *(*match)(const char *, const char *);
6979 if (c == '+' || c == '%') {
6981 err_msg = "No current job";
6983 } else if (c == '-') {
6986 err_msg = "No previous job";
6997 jp = jobtab + num - 1;
7014 if (match(jp->ps[0].cmd, p)) {
7018 err_msg = "%s: ambiguous";
7025 err_msg = "job %s not created under job control";
7026 if (getctl && jp->jobctl == 0)
7031 sh_error(err_msg, name);
7036 * Return a new job structure.
7037 * Called with interrupts off.
7041 makejob(union node *node, int nprocs)
7046 for (i = njobs, jp = jobtab ; ; jp++) {
7053 if (jp->state != JOBDONE || !jp->waited)
7062 memset(jp, 0, sizeof(*jp));
7067 jp->prev_job = curjob;
7072 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
7074 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7084 struct job *jp, *jq;
7086 len = njobs * sizeof(*jp);
7088 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7090 offset = (char *)jp - (char *)jq;
7092 /* Relocate pointers */
7095 jq = (struct job *)((char *)jq + l);
7099 #define joff(p) ((struct job *)((char *)(p) + l))
7100 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7101 if (xlikely(joff(jp)->ps == &jq->ps0))
7102 jmove(joff(jp)->ps);
7103 if (joff(jp)->prev_job)
7104 jmove(joff(jp)->prev_job);
7114 jp = (struct job *)((char *)jp + len);
7118 } while (--jq >= jp);
7124 * Fork off a subshell. If we are doing job control, give the subshell its
7125 * own process group. Jp is a job structure that the job is to be added to.
7126 * N is the command that will be evaluated by the child. Both jp and n may
7127 * be NULL. The mode parameter can be one of the following:
7128 * FORK_FG - Fork off a foreground process.
7129 * FORK_BG - Fork off a background process.
7130 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7131 * process group even if job control is on.
7133 * When job control is turned off, background processes have their standard
7134 * input redirected to /dev/null (except for the second and later processes
7137 * Called with interrupts off.
7140 static void forkchild(struct job *jp, union node *n, int mode)
7144 TRACE(("Child shell %d\n", getpid()));
7151 /* do job control only in root shell */
7153 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7156 if (jp->nprocs == 0)
7159 pgrp = jp->ps[0].pid;
7160 /* This can fail because we are doing it in the parent also */
7161 (void)setpgid(0, pgrp);
7162 if (mode == FORK_FG)
7163 xtcsetpgrp(ttyfd, pgrp);
7168 if (mode == FORK_BG) {
7171 if (jp->nprocs == 0) {
7173 if (open(bb_dev_null, O_RDONLY) != 0)
7174 sh_error("Can't open %s", bb_dev_null);
7177 if (!oldlvl && iflag) {
7182 for (jp = curjob; jp; jp = jp->prev_job)
7187 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7189 TRACE(("In parent shell: child = %d\n", pid));
7191 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7196 if (mode != FORK_NOJOB && jp->jobctl) {
7199 if (jp->nprocs == 0)
7202 pgrp = jp->ps[0].pid;
7203 /* This can fail because we are doing it in the child also */
7204 (void)setpgid(pid, pgrp);
7207 if (mode == FORK_BG) {
7208 backgndpid = pid; /* set $! */
7209 set_curjob(jp, CUR_RUNNING);
7212 struct procstat *ps = &jp->ps[jp->nprocs++];
7218 ps->cmd = commandtext(n);
7224 forkshell(struct job *jp, union node *n, int mode)
7228 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7231 TRACE(("Fork failed, errno=%d", errno));
7234 sh_error("Cannot fork");
7237 forkchild(jp, n, mode);
7239 forkparent(jp, n, mode, pid);
7244 * Wait for job to finish.
7246 * Under job control we have the problem that while a child process is
7247 * running interrupts generated by the user are sent to the child but not
7248 * to the shell. This means that an infinite loop started by an inter-
7249 * active user may be hard to kill. With job control turned off, an
7250 * interactive user may place an interactive program inside a loop. If
7251 * the interactive program catches interrupts, the user doesn't want
7252 * these interrupts to also abort the loop. The approach we take here
7253 * is to have the shell ignore interrupt signals while waiting for a
7254 * foreground process to terminate, and then send itself an interrupt
7255 * signal if the child process was terminated by an interrupt signal.
7256 * Unfortunately, some programs want to do a bit of cleanup and then
7257 * exit on interrupt; unless these processes terminate themselves by
7258 * sending a signal to themselves (instead of calling exit) they will
7259 * confuse this approach.
7261 * Called with interrupts off.
7265 waitforjob(struct job *jp)
7269 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7270 while (jp->state == JOBRUNNING) {
7271 dowait(DOWAIT_BLOCK, jp);
7276 xtcsetpgrp(ttyfd, rootpid);
7278 * This is truly gross.
7279 * If we're doing job control, then we did a TIOCSPGRP which
7280 * caused us (the shell) to no longer be in the controlling
7281 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7282 * intuit from the subprocess exit status whether a SIGINT
7283 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7288 if (jp->state == JOBDONE)
7296 * Do a wait system call. If job control is compiled in, we accept
7297 * stopped processes. If block is zero, we return a value of zero
7298 * rather than blocking.
7300 * System V doesn't have a non-blocking wait system call. It does
7301 * have a SIGCLD signal that is sent to a process when one of it's
7302 * children dies. The obvious way to use SIGCLD would be to install
7303 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7304 * was received, and have waitproc bump another counter when it got
7305 * the status of a process. Waitproc would then know that a wait
7306 * system call would not block if the two counters were different.
7307 * This approach doesn't work because if a process has children that
7308 * have not been waited for, System V will send it a SIGCLD when it
7309 * installs a signal handler for SIGCLD. What this means is that when
7310 * a child exits, the shell will be sent SIGCLD signals continuously
7311 * until is runs out of stack space, unless it does a wait call before
7312 * restoring the signal handler. The code below takes advantage of
7313 * this (mis)feature by installing a signal handler for SIGCLD and
7314 * then checking to see whether it was called. If there are any
7315 * children to be waited for, it will be.
7317 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7318 * waits at all. In this case, the user will not be informed when
7319 * a background process until the next time she runs a real program
7320 * (as opposed to running a builtin command or just typing return),
7321 * and the jobs command may give out of date information.
7324 static int waitproc(int block, int *status)
7334 return wait3(status, flags, (struct rusage *)NULL);
7338 * Wait for a process to terminate.
7342 dowait(int block, struct job *job)
7347 struct job *thisjob;
7350 TRACE(("dowait(%d) called\n", block));
7351 pid = waitproc(block, &status);
7352 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7357 for (jp = curjob; jp; jp = jp->prev_job) {
7358 struct procstat *sp;
7359 struct procstat *spend;
7360 if (jp->state == JOBDONE)
7363 spend = jp->ps + jp->nprocs;
7366 if (sp->pid == pid) {
7367 TRACE(("Job %d: changing status of proc %d "
7368 "from 0x%x to 0x%x\n",
7369 jobno(jp), pid, sp->status, status));
7370 sp->status = status;
7373 if (sp->status == -1)
7376 if (state == JOBRUNNING)
7378 if (WIFSTOPPED(sp->status)) {
7379 jp->stopstatus = sp->status;
7383 } while (++sp < spend);
7388 if (!WIFSTOPPED(status))
7395 if (state != JOBRUNNING) {
7396 thisjob->changed = 1;
7398 if (thisjob->state != state) {
7399 TRACE(("Job %d: changing state from %d to %d\n",
7400 jobno(thisjob), thisjob->state, state));
7401 thisjob->state = state;
7403 if (state == JOBSTOPPED) {
7404 set_curjob(thisjob, CUR_STOPPED);
7413 if (thisjob && thisjob == job) {
7417 len = sprint_status(s, status, 1);
7429 * return 1 if there are stopped jobs, otherwise 0
7442 if (jp && jp->state == JOBSTOPPED) {
7443 out2str("You have stopped jobs.\n");
7453 * Return a string identifying a command (to be printed by the
7458 static char *cmdnextc;
7461 commandtext(union node *n)
7465 STARTSTACKSTR(cmdnextc);
7467 name = stackblock();
7468 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7469 name, cmdnextc, cmdnextc));
7470 return savestr(name);
7474 cmdtxt(union node *n)
7477 struct nodelist *lp;
7489 lp = n->npipe.cmdlist;
7507 cmdtxt(n->nbinary.ch1);
7523 cmdtxt(n->nif.test);
7526 if (n->nif.elsepart) {
7529 n = n->nif.elsepart;
7545 cmdtxt(n->nbinary.ch1);
7555 cmdputs(n->nfor.var);
7557 cmdlist(n->nfor.args, 1);
7562 cmdputs(n->narg.text);
7566 cmdlist(n->ncmd.args, 1);
7567 cmdlist(n->ncmd.redirect, 0);
7580 cmdputs(n->ncase.expr->narg.text);
7582 for (np = n->ncase.cases; np; np = np->nclist.next) {
7583 cmdtxt(np->nclist.pattern);
7585 cmdtxt(np->nclist.body);
7611 s[0] = n->nfile.fd + '0';
7615 if (n->type == NTOFD || n->type == NFROMFD) {
7616 s[0] = n->ndup.dupfd + '0';
7627 cmdlist(union node *np, int sep)
7629 for (; np; np = np->narg.next) {
7633 if (sep && np->narg.next)
7639 cmdputs(const char *s)
7641 const char *p, *str;
7642 char c, cc[2] = " ";
7646 static const char vstype[VSTYPE + 1][4] = {
7647 "", "}", "-", "+", "?", "=",
7648 "%", "%%", "#", "##"
7650 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7652 while ((c = *p++) != 0) {
7660 if ((subtype & VSTYPE) == VSLENGTH)
7664 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7671 str = "\"}" + !(quoted & 1);
7678 case CTLBACKQ+CTLQUOTE:
7681 #if ENABLE_ASH_MATH_SUPPORT
7696 if ((subtype & VSTYPE) != VSNORMAL)
7698 str = vstype[subtype & VSTYPE];
7699 if (subtype & VSNUL)
7708 /* These can only happen inside quotes */
7721 while ((c = *str++)) {
7726 USTPUTC('"', nextc);
7734 showpipe(struct job *jp, FILE *out)
7736 struct procstat *sp;
7737 struct procstat *spend;
7739 spend = jp->ps + jp->nprocs;
7740 for (sp = jp->ps + 1; sp < spend; sp++)
7741 fprintf(out, " | %s", sp->cmd);
7742 outcslow('\n', out);
7747 xtcsetpgrp(int fd, pid_t pgrp)
7749 if (tcsetpgrp(fd, pgrp))
7750 sh_error("Cannot set tty process group (%m)");
7755 getstatus(struct job *job) {
7759 status = job->ps[job->nprocs - 1].status;
7760 retval = WEXITSTATUS(status);
7761 if (!WIFEXITED(status)) {
7763 retval = WSTOPSIG(status);
7764 if (!WIFSTOPPED(status))
7767 /* XXX: limits number of signals */
7768 retval = WTERMSIG(status);
7770 if (retval == SIGINT)
7776 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7777 jobno(job), job->nprocs, status, retval));
7785 * Routines to check for mail. (Perhaps make part of main.c?)
7788 #define MAXMBOXES 10
7790 /* times of mailboxes */
7791 static time_t mailtime[MAXMBOXES];
7792 /* Set if MAIL or MAILPATH is changed. */
7793 static int mail_var_path_changed;
7798 * Print appropriate message(s) if mail has arrived.
7799 * If mail_var_path_changed is set,
7800 * then the value of MAIL has mail_var_path_changed,
7801 * so we just update the values.
7811 struct stackmark smark;
7814 setstackmark(&smark);
7815 mpath = mpathset() ? mpathval() : mailval();
7816 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7817 p = padvance(&mpath, nullstr);
7822 for (q = p ; *q ; q++);
7827 q[-1] = '\0'; /* delete trailing '/' */
7828 if (stat(p, &statb) < 0) {
7832 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7835 pathopt ? pathopt : "you have mail"
7838 *mtp = statb.st_mtime;
7840 mail_var_path_changed = 0;
7841 popstackmark(&smark);
7846 changemail(const char *val)
7848 mail_var_path_changed++;
7851 #endif /* ASH_MAIL */
7857 static short profile_buf[16384];
7861 static int isloginsh;
7863 static void read_profile(const char *);
7866 * Main routine. We initialize things, parse the arguments, execute
7867 * profiles if we're a login shell, and then call cmdloop to execute
7868 * commands. The setjmp call sets up the location to jump to when an
7869 * exception occurs. When an exception occurs the variable "state"
7870 * is used to figure out how far we had gotten.
7873 int ash_main(int argc, char **argv);
7874 int ash_main(int argc, char **argv)
7878 struct jmploc jmploc;
7879 struct stackmark smark;
7882 dash_errno = __errno_location();
7886 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
7889 #if ENABLE_FEATURE_EDITING
7890 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
7893 if (setjmp(jmploc.loc)) {
7903 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7907 outcslow('\n', stderr);
7909 popstackmark(&smark);
7910 FORCEINTON; /* enable interrupts */
7923 trputs("Shell args: "); trargs(argv);
7927 #if ENABLE_ASH_RANDOM_SUPPORT
7928 rseed = rootpid + ((time_t)time((time_t *)0));
7931 setstackmark(&smark);
7932 procargs(argc, argv);
7933 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
7935 const char *hp = lookupvar("HISTFILE");
7938 hp = lookupvar("HOME");
7940 char *defhp = concat_path_file(hp, ".ash_history");
7941 setvar("HISTFILE", defhp, 0);
7947 if (argv[0] && argv[0][0] == '-')
7951 read_profile("/etc/profile");
7954 read_profile(".profile");
7960 getuid() == geteuid() && getgid() == getegid() &&
7964 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7965 read_profile(shinit);
7971 evalstring(minusc, 0);
7973 if (sflag || minusc == NULL) {
7974 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
7976 const char *hp = lookupvar("HISTFILE");
7979 line_input_state->hist_file = hp;
7982 state4: /* XXX ??? - why isn't this before the "if" statement */
7990 extern void _mcleanup(void);
8000 * Read and execute commands. "Top" is nonzero for the top level command
8001 * loop; it turns on prompting if the shell is interactive.
8008 struct stackmark smark;
8012 TRACE(("cmdloop(%d) called\n", top));
8016 setstackmark(&smark);
8019 showjobs(stderr, SHOW_CHANGED);
8028 n = parsecmd(inter);
8029 /* showtree(n); DEBUG */
8031 if (!top || numeof >= 50)
8033 if (!stoppedjobs()) {
8036 out2str("\nUse \"exit\" to leave shell.\n");
8039 } else if (nflag == 0) {
8040 job_warning = (job_warning == 2) ? 1 : 0;
8044 popstackmark(&smark);
8049 return skip & SKIPEVAL;
8058 * Read /etc/profile or .profile. Return on error.
8062 read_profile(const char *name)
8066 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8078 * Read a file containing shell functions.
8082 readcmdfile(char *name)
8084 setinputfile(name, INPUT_PUSH_FILE);
8091 * Take commands from a file. To be compatible we should do a path
8092 * search for the file, which is necessary to find sub-commands.
8095 static char * find_dot_file(char *name)
8098 const char *path = pathval();
8101 /* don't try this for absolute or relative paths */
8102 if (strchr(name, '/'))
8105 while ((fullname = padvance(&path, name)) != NULL) {
8106 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8108 * Don't bother freeing here, since it will
8109 * be freed by the caller.
8113 stunalloc(fullname);
8116 /* not found in the PATH */
8117 sh_error(not_found_msg, name);
8121 static int dotcmd(int argc, char **argv)
8124 volatile struct shparam saveparam;
8127 for (sp = cmdenviron; sp; sp = sp->next)
8128 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8130 if (argc >= 2) { /* That's what SVR2 does */
8133 fullname = find_dot_file(argv[1]);
8136 saveparam = shellparam;
8137 shellparam.malloc = 0;
8138 shellparam.nparam = argc - 2;
8139 shellparam.p = argv + 2;
8142 setinputfile(fullname, INPUT_PUSH_FILE);
8143 commandname = fullname;
8148 freeparam(&shellparam);
8149 shellparam = saveparam;
8151 status = exitstatus;
8158 exitcmd(int argc, char **argv)
8163 exitstatus = number(argv[1]);
8168 #if ENABLE_ASH_BUILTIN_ECHO
8170 echocmd(int argc, char **argv)
8172 return bb_echo(argv);
8176 #if ENABLE_ASH_BUILTIN_TEST
8178 testcmd(int argc, char **argv)
8180 return bb_test(argc, argv);
8187 * Same for malloc, realloc, but returns an error when out of space.
8191 ckrealloc(pointer p, size_t nbytes)
8193 p = realloc(p, nbytes);
8195 sh_error(bb_msg_memory_exhausted);
8200 ckmalloc(size_t nbytes)
8202 return ckrealloc(NULL, nbytes);
8206 * Make a copy of a string in safe storage.
8210 savestr(const char *s)
8212 char *p = strdup(s);
8214 sh_error(bb_msg_memory_exhausted);
8220 * Parse trees for commands are allocated in lifo order, so we use a stack
8221 * to make this more efficient, and also to avoid all sorts of exception
8222 * handling code to handle interrupts in the middle of a parse.
8224 * The size 504 was chosen because the Ultrix malloc handles that size
8230 stalloc(size_t nbytes)
8235 aligned = SHELL_ALIGN(nbytes);
8236 if (aligned > stacknleft) {
8239 struct stack_block *sp;
8241 blocksize = aligned;
8242 if (blocksize < MINSIZE)
8243 blocksize = MINSIZE;
8244 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8245 if (len < blocksize)
8246 sh_error(bb_msg_memory_exhausted);
8250 stacknxt = sp->space;
8251 stacknleft = blocksize;
8252 sstrend = stacknxt + blocksize;
8257 stacknxt += aligned;
8258 stacknleft -= aligned;
8264 stunalloc(pointer p)
8267 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8268 write(2, "stunalloc\n", 10);
8272 stacknleft += stacknxt - (char *)p;
8278 setstackmark(struct stackmark *mark)
8280 mark->stackp = stackp;
8281 mark->stacknxt = stacknxt;
8282 mark->stacknleft = stacknleft;
8283 mark->marknext = markp;
8289 popstackmark(struct stackmark *mark)
8291 struct stack_block *sp;
8294 markp = mark->marknext;
8295 while (stackp != mark->stackp) {
8300 stacknxt = mark->stacknxt;
8301 stacknleft = mark->stacknleft;
8302 sstrend = mark->stacknxt + mark->stacknleft;
8308 * When the parser reads in a string, it wants to stick the string on the
8309 * stack and only adjust the stack pointer when it knows how big the
8310 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8311 * of space on top of the stack and stackblocklen returns the length of
8312 * this block. Growstackblock will grow this space by at least one byte,
8313 * possibly moving it (like realloc). Grabstackblock actually allocates the
8314 * part of the block that has been used.
8318 growstackblock(void)
8322 newlen = stacknleft * 2;
8323 if (newlen < stacknleft)
8324 sh_error(bb_msg_memory_exhausted);
8328 if (stacknxt == stackp->space && stackp != &stackbase) {
8329 struct stack_block *oldstackp;
8330 struct stackmark *xmark;
8331 struct stack_block *sp;
8332 struct stack_block *prevstackp;
8338 prevstackp = sp->prev;
8339 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8340 sp = ckrealloc((pointer)sp, grosslen);
8341 sp->prev = prevstackp;
8343 stacknxt = sp->space;
8344 stacknleft = newlen;
8345 sstrend = sp->space + newlen;
8348 * Stack marks pointing to the start of the old block
8349 * must be relocated to point to the new block
8352 while (xmark != NULL && xmark->stackp == oldstackp) {
8353 xmark->stackp = stackp;
8354 xmark->stacknxt = stacknxt;
8355 xmark->stacknleft = stacknleft;
8356 xmark = xmark->marknext;
8360 char *oldspace = stacknxt;
8361 int oldlen = stacknleft;
8362 char *p = stalloc(newlen);
8364 /* free the space we just allocated */
8365 stacknxt = memcpy(p, oldspace, oldlen);
8366 stacknleft += newlen;
8370 static void grabstackblock(size_t len)
8372 len = SHELL_ALIGN(len);
8378 * The following routines are somewhat easier to use than the above.
8379 * The user declares a variable of type STACKSTR, which may be declared
8380 * to be a register. The macro STARTSTACKSTR initializes things. Then
8381 * the user uses the macro STPUTC to add characters to the string. In
8382 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8383 * grown as necessary. When the user is done, she can just leave the
8384 * string there and refer to it using stackblock(). Or she can allocate
8385 * the space for it using grabstackstr(). If it is necessary to allow
8386 * someone else to use the stack temporarily and then continue to grow
8387 * the string, the user should use grabstack to allocate the space, and
8388 * then call ungrabstr(p) to return to the previous mode of operation.
8390 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8391 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8392 * is space for at least one character.
8398 size_t len = stackblocksize();
8399 if (herefd >= 0 && len >= 1024) {
8400 full_write(herefd, stackblock(), len);
8401 return stackblock();
8404 return stackblock() + len;
8408 * Called from CHECKSTRSPACE.
8412 makestrspace(size_t newlen, char *p)
8414 size_t len = p - stacknxt;
8415 size_t size = stackblocksize();
8420 size = stackblocksize();
8422 if (nleft >= newlen)
8426 return stackblock() + len;
8430 stnputs(const char *s, size_t n, char *p)
8432 p = makestrspace(n, p);
8433 p = memcpy(p, s, n) + n;
8438 stputs(const char *s, char *p)
8440 return stnputs(s, strlen(s), p);
8448 * number(s) Convert a string of digits to an integer.
8449 * is_number(s) Return true if s is a string of digits.
8453 * prefix -- see if pfx is a prefix of string.
8457 prefix(const char *string, const char *pfx)
8460 if (*pfx++ != *string++)
8463 return (char *) string;
8468 * Convert a string of digits to an integer, printing an error message on
8473 number(const char *s)
8477 sh_error(illnum, s);
8483 * Check for a valid number. This should be elsewhere.
8487 is_number(const char *p)
8492 } while (*++p != '\0');
8498 * Produce a possibly single quoted string suitable as input to the shell.
8499 * The return string is allocated on the stack.
8503 single_quote(const char *s) {
8512 len = strchrnul(s, '\'') - s;
8514 q = p = makestrspace(len + 3, p);
8517 q = memcpy(q, s, len) + len;
8523 len = strspn(s, "'");
8527 q = p = makestrspace(len + 3, p);
8530 q = memcpy(q, s, len) + len;
8539 return stackblock();
8543 * Like strdup but works with the ash stack.
8547 sstrdup(const char *p)
8549 size_t len = strlen(p) + 1;
8550 return memcpy(stalloc(len), p, len);
8555 calcsize(union node *n)
8559 funcblocksize += nodesize[n->type];
8562 calcsize(n->ncmd.redirect);
8563 calcsize(n->ncmd.args);
8564 calcsize(n->ncmd.assign);
8567 sizenodelist(n->npipe.cmdlist);
8572 calcsize(n->nredir.redirect);
8573 calcsize(n->nredir.n);
8580 calcsize(n->nbinary.ch2);
8581 calcsize(n->nbinary.ch1);
8584 calcsize(n->nif.elsepart);
8585 calcsize(n->nif.ifpart);
8586 calcsize(n->nif.test);
8589 funcstringsize += strlen(n->nfor.var) + 1;
8590 calcsize(n->nfor.body);
8591 calcsize(n->nfor.args);
8594 calcsize(n->ncase.cases);
8595 calcsize(n->ncase.expr);
8598 calcsize(n->nclist.body);
8599 calcsize(n->nclist.pattern);
8600 calcsize(n->nclist.next);
8604 sizenodelist(n->narg.backquote);
8605 funcstringsize += strlen(n->narg.text) + 1;
8606 calcsize(n->narg.next);
8613 calcsize(n->nfile.fname);
8614 calcsize(n->nfile.next);
8618 calcsize(n->ndup.vname);
8619 calcsize(n->ndup.next);
8623 calcsize(n->nhere.doc);
8624 calcsize(n->nhere.next);
8627 calcsize(n->nnot.com);
8634 sizenodelist(struct nodelist *lp)
8637 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8645 copynode(union node *n)
8652 funcblock = (char *) funcblock + nodesize[n->type];
8656 new->ncmd.redirect = copynode(n->ncmd.redirect);
8657 new->ncmd.args = copynode(n->ncmd.args);
8658 new->ncmd.assign = copynode(n->ncmd.assign);
8661 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8662 new->npipe.backgnd = n->npipe.backgnd;
8667 new->nredir.redirect = copynode(n->nredir.redirect);
8668 new->nredir.n = copynode(n->nredir.n);
8675 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8676 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8679 new->nif.elsepart = copynode(n->nif.elsepart);
8680 new->nif.ifpart = copynode(n->nif.ifpart);
8681 new->nif.test = copynode(n->nif.test);
8684 new->nfor.var = nodesavestr(n->nfor.var);
8685 new->nfor.body = copynode(n->nfor.body);
8686 new->nfor.args = copynode(n->nfor.args);
8689 new->ncase.cases = copynode(n->ncase.cases);
8690 new->ncase.expr = copynode(n->ncase.expr);
8693 new->nclist.body = copynode(n->nclist.body);
8694 new->nclist.pattern = copynode(n->nclist.pattern);
8695 new->nclist.next = copynode(n->nclist.next);
8699 new->narg.backquote = copynodelist(n->narg.backquote);
8700 new->narg.text = nodesavestr(n->narg.text);
8701 new->narg.next = copynode(n->narg.next);
8708 new->nfile.fname = copynode(n->nfile.fname);
8709 new->nfile.fd = n->nfile.fd;
8710 new->nfile.next = copynode(n->nfile.next);
8714 new->ndup.vname = copynode(n->ndup.vname);
8715 new->ndup.dupfd = n->ndup.dupfd;
8716 new->ndup.fd = n->ndup.fd;
8717 new->ndup.next = copynode(n->ndup.next);
8721 new->nhere.doc = copynode(n->nhere.doc);
8722 new->nhere.fd = n->nhere.fd;
8723 new->nhere.next = copynode(n->nhere.next);
8726 new->nnot.com = copynode(n->nnot.com);
8729 new->type = n->type;
8734 static struct nodelist *
8735 copynodelist(struct nodelist *lp)
8737 struct nodelist *start;
8738 struct nodelist **lpp;
8743 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8744 (*lpp)->n = copynode(lp->n);
8746 lpp = &(*lpp)->next;
8754 nodesavestr(char *s)
8756 char *rtn = funcstring;
8758 strcpy(funcstring, s);
8759 funcstring += strlen(s) + 1;
8765 * Free a parse tree.
8769 freefunc(struct funcnode *f)
8771 if (f && --f->count < 0)
8776 static void options(int);
8777 static void setoption(int, int);
8781 * Process the shell command line arguments.
8785 procargs(int argc, char **argv)
8788 const char *xminusc;
8795 for (i = 0; i < NOPTS; i++)
8801 if (*xargv == NULL) {
8803 sh_error(bb_msg_requires_arg, "-c");
8806 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8810 for (i = 0; i < NOPTS; i++)
8811 if (optlist[i] == 2)
8816 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8821 } else if (!sflag) {
8822 setinputfile(*xargv, 0);
8828 shellparam.p = xargv;
8829 #if ENABLE_ASH_GETOPTS
8830 shellparam.optind = 1;
8831 shellparam.optoff = -1;
8833 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8835 shellparam.nparam++;
8848 setinteractive(iflag);
8853 static void minus_o(char *name, int val)
8858 out1str("Current option settings\n");
8859 for (i = 0; i < NOPTS; i++)
8860 out1fmt("%-16s%s\n", optnames(i),
8861 optlist[i] ? "on" : "off");
8863 for (i = 0; i < NOPTS; i++)
8864 if (equal(name, optnames(i))) {
8868 sh_error("Illegal option -o %s", name);
8873 * Process shell options. The global variable argptr contains a pointer
8874 * to the argument list; we advance it past the options.
8878 options(int cmdline)
8886 while ((p = *argptr) != NULL) {
8888 if ((c = *p++) == '-') {
8890 if (p[0] == '\0' || LONE_DASH(p)) {
8892 /* "-" means turn off -x and -v */
8895 /* "--" means reset params */
8896 else if (*argptr == NULL)
8899 break; /* "-" or "--" terminates options */
8901 } else if (c == '+') {
8907 while ((c = *p++) != '\0') {
8908 if (c == 'c' && cmdline) {
8909 minusc = p; /* command is after shell args*/
8910 } else if (c == 'o') {
8911 minus_o(*argptr, val);
8914 } else if (cmdline && (c == '-')) { // long options
8915 if (strcmp(p, "login") == 0)
8927 setoption(int flag, int val)
8931 for (i = 0; i < NOPTS; i++)
8932 if (optletters(i) == flag) {
8936 sh_error("Illegal option -%c", flag);
8942 * Set the shell parameters.
8946 setparam(char **argv)
8952 for (nparam = 0 ; argv[nparam] ; nparam++);
8953 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8955 *ap++ = savestr(*argv++);
8958 freeparam(&shellparam);
8959 shellparam.malloc = 1;
8960 shellparam.nparam = nparam;
8961 shellparam.p = newparam;
8962 #if ENABLE_ASH_GETOPTS
8963 shellparam.optind = 1;
8964 shellparam.optoff = -1;
8970 * Free the list of positional parameters.
8974 freeparam(volatile struct shparam *param)
8978 if (param->malloc) {
8979 for (ap = param->p ; *ap ; ap++)
8987 * The shift builtin command.
8991 shiftcmd(int argc, char **argv)
8998 n = number(argv[1]);
8999 if (n > shellparam.nparam)
9000 sh_error("can't shift that many");
9002 shellparam.nparam -= n;
9003 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9004 if (shellparam.malloc)
9008 while ((*ap2++ = *ap1++) != NULL);
9009 #if ENABLE_ASH_GETOPTS
9010 shellparam.optind = 1;
9011 shellparam.optoff = -1;
9019 * The set command builtin.
9023 setcmd(int argc, char **argv)
9026 return showvars(nullstr, 0, VUNSET);
9030 if (*argptr != NULL) {
9038 #if ENABLE_ASH_GETOPTS
9040 getoptsreset(const char *value)
9042 shellparam.optind = number(value);
9043 shellparam.optoff = -1;
9047 #if ENABLE_LOCALE_SUPPORT
9048 static void change_lc_all(const char *value)
9050 if (value != 0 && *value != 0)
9051 setlocale(LC_ALL, value);
9054 static void change_lc_ctype(const char *value)
9056 if (value != 0 && *value != 0)
9057 setlocale(LC_CTYPE, value);
9062 #if ENABLE_ASH_RANDOM_SUPPORT
9063 /* Roughly copied from bash.. */
9064 static void change_random(const char *value)
9066 if (value == NULL) {
9067 /* "get", generate */
9070 rseed = rseed * 1103515245 + 12345;
9071 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9072 /* set without recursion */
9073 setvar(vrandom.text, buf, VNOFUNC);
9074 vrandom.flags &= ~VNOFUNC;
9077 rseed = strtoul(value, (char **)NULL, 10);
9083 #if ENABLE_ASH_GETOPTS
9085 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9094 if (*param_optind < 1)
9096 optnext = optfirst + *param_optind - 1;
9098 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9101 p = optnext[-1] + *optoff;
9102 if (p == NULL || *p == '\0') {
9103 /* Current word is done, advance */
9105 if (p == NULL || *p != '-' || *++p == '\0') {
9112 if (LONE_DASH(p)) /* check for "--" */
9117 for (q = optstr; *q != c; ) {
9119 if (optstr[0] == ':') {
9122 err |= setvarsafe("OPTARG", s, 0);
9124 fprintf(stderr, "Illegal option -%c\n", c);
9125 (void) unsetvar("OPTARG");
9135 if (*p == '\0' && (p = *optnext) == NULL) {
9136 if (optstr[0] == ':') {
9139 err |= setvarsafe("OPTARG", s, 0);
9142 fprintf(stderr, "No arg for -%c option\n", c);
9143 (void) unsetvar("OPTARG");
9151 err |= setvarsafe("OPTARG", p, 0);
9154 err |= setvarsafe("OPTARG", nullstr, 0);
9157 *optoff = p ? p - *(optnext - 1) : -1;
9158 *param_optind = optnext - optfirst + 1;
9159 fmtstr(s, sizeof(s), "%d", *param_optind);
9160 err |= setvarsafe("OPTIND", s, VNOFUNC);
9163 err |= setvarsafe(optvar, s, 0);
9174 * The getopts builtin. Shellparam.optnext points to the next argument
9175 * to be processed. Shellparam.optptr points to the next character to
9176 * be processed in the current argument. If shellparam.optnext is NULL,
9177 * then it's the first time getopts has been called.
9181 getoptscmd(int argc, char **argv)
9186 sh_error("Usage: getopts optstring var [arg]");
9187 else if (argc == 3) {
9188 optbase = shellparam.p;
9189 if (shellparam.optind > shellparam.nparam + 1) {
9190 shellparam.optind = 1;
9191 shellparam.optoff = -1;
9196 if (shellparam.optind > argc - 2) {
9197 shellparam.optind = 1;
9198 shellparam.optoff = -1;
9202 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9203 &shellparam.optoff);
9205 #endif /* ASH_GETOPTS */
9208 * XXX - should get rid of. have all builtins use getopt(3). the
9209 * library getopt must have the BSD extension static variable "optreset"
9210 * otherwise it can't be used within the shell safely.
9212 * Standard option processing (a la getopt) for builtin routines. The
9213 * only argument that is passed to nextopt is the option string; the
9214 * other arguments are unnecessary. It return the character, or '\0' on
9219 nextopt(const char *optstring)
9225 if ((p = optptr) == NULL || *p == '\0') {
9227 if (p == NULL || *p != '-' || *++p == '\0')
9230 if (LONE_DASH(p)) /* check for "--" */
9234 for (q = optstring ; *q != c ; ) {
9236 sh_error("Illegal option -%c", c);
9241 if (*p == '\0' && (p = *argptr++) == NULL)
9242 sh_error("No arg for -%c option", c);
9254 outstr(const char *p, FILE *file)
9279 outcslow(int c, FILE *dest)
9289 out1fmt(const char *fmt, ...)
9296 r = vprintf(fmt, ap);
9304 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9311 ret = vsnprintf(outbuf, length, fmt, ap);
9322 * Shell command parser.
9325 #define EOFMARKLEN 79
9329 struct heredoc *next; /* next here document in list */
9330 union node *here; /* redirection node */
9331 char *eofmark; /* string indicating end of input */
9332 int striptabs; /* if set, strip leading tabs */
9337 static struct heredoc *heredoclist; /* list of here documents to read */
9340 static union node *list(int);
9341 static union node *andor(void);
9342 static union node *pipeline(void);
9343 static union node *command(void);
9344 static union node *simplecmd(void);
9345 static union node *makename(void);
9346 static void parsefname(void);
9347 static void parseheredoc(void);
9348 static char peektoken(void);
9349 static int readtoken(void);
9350 static int xxreadtoken(void);
9351 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9352 static int noexpand(char *);
9353 static void synexpect(int) ATTRIBUTE_NORETURN;
9354 static void synerror(const char *) ATTRIBUTE_NORETURN;
9355 static void setprompt(int);
9359 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9360 * valid parse tree indicating a blank line.)
9364 parsecmd(int interact)
9369 doprompt = interact;
9371 setprompt(doprompt);
9386 union node *n1, *n2, *n3;
9389 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9390 if (nlflag == 2 && peektoken())
9396 if (tok == TBACKGND) {
9397 if (n2->type == NPIPE) {
9398 n2->npipe.backgnd = 1;
9400 if (n2->type != NREDIR) {
9401 n3 = stalloc(sizeof(struct nredir));
9403 n3->nredir.redirect = NULL;
9406 n2->type = NBACKGND;
9413 n3 = (union node *)stalloc(sizeof(struct nbinary));
9415 n3->nbinary.ch1 = n1;
9416 n3->nbinary.ch2 = n2;
9432 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9440 pungetc(); /* push back EOF on input */
9455 union node *n1, *n2, *n3;
9460 if ((t = readtoken()) == TAND) {
9462 } else if (t == TOR) {
9468 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9470 n3 = (union node *)stalloc(sizeof(struct nbinary));
9472 n3->nbinary.ch1 = n1;
9473 n3->nbinary.ch2 = n2;
9482 union node *n1, *n2, *pipenode;
9483 struct nodelist *lp, *prev;
9487 TRACE(("pipeline: entered\n"));
9488 if (readtoken() == TNOT) {
9490 checkkwd = CHKKWD | CHKALIAS;
9494 if (readtoken() == TPIPE) {
9495 pipenode = (union node *)stalloc(sizeof(struct npipe));
9496 pipenode->type = NPIPE;
9497 pipenode->npipe.backgnd = 0;
9498 lp = (struct nodelist *)stalloc(sizeof(struct nodelist));
9499 pipenode->npipe.cmdlist = lp;
9503 lp = (struct nodelist *)stalloc(sizeof(struct nodelist));
9504 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9507 } while (readtoken() == TPIPE);
9513 n2 = (union node *)stalloc(sizeof(struct nnot));
9525 union node *n1, *n2;
9526 union node *ap, **app;
9527 union node *cp, **cpp;
9528 union node *redir, **rpp;
9535 switch (readtoken()) {
9540 n1 = (union node *)stalloc(sizeof(struct nif));
9542 n1->nif.test = list(0);
9543 if (readtoken() != TTHEN)
9545 n1->nif.ifpart = list(0);
9547 while (readtoken() == TELIF) {
9548 n2->nif.elsepart = (union node *)stalloc(sizeof(struct nif));
9549 n2 = n2->nif.elsepart;
9551 n2->nif.test = list(0);
9552 if (readtoken() != TTHEN)
9554 n2->nif.ifpart = list(0);
9556 if (lasttoken == TELSE)
9557 n2->nif.elsepart = list(0);
9559 n2->nif.elsepart = NULL;
9567 n1 = (union node *)stalloc(sizeof(struct nbinary));
9568 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9569 n1->nbinary.ch1 = list(0);
9570 if ((got=readtoken()) != TDO) {
9571 TRACE(("expecting DO got %s %s\n", tokname(got),
9572 got == TWORD ? wordtext : ""));
9575 n1->nbinary.ch2 = list(0);
9580 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9581 synerror("Bad for loop variable");
9582 n1 = (union node *)stalloc(sizeof(struct nfor));
9584 n1->nfor.var = wordtext;
9585 checkkwd = CHKKWD | CHKALIAS;
9586 if (readtoken() == TIN) {
9588 while (readtoken() == TWORD) {
9589 n2 = (union node *)stalloc(sizeof(struct narg));
9591 n2->narg.text = wordtext;
9592 n2->narg.backquote = backquotelist;
9594 app = &n2->narg.next;
9598 if (lasttoken != TNL && lasttoken != TSEMI)
9601 n2 = (union node *)stalloc(sizeof(struct narg));
9603 n2->narg.text = (char *)dolatstr;
9604 n2->narg.backquote = NULL;
9605 n2->narg.next = NULL;
9608 * Newline or semicolon here is optional (but note
9609 * that the original Bourne shell only allowed NL).
9611 if (lasttoken != TNL && lasttoken != TSEMI)
9614 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9615 if (readtoken() != TDO)
9617 n1->nfor.body = list(0);
9621 n1 = (union node *)stalloc(sizeof(struct ncase));
9623 if (readtoken() != TWORD)
9625 n1->ncase.expr = n2 = (union node *)stalloc(sizeof(struct narg));
9627 n2->narg.text = wordtext;
9628 n2->narg.backquote = backquotelist;
9629 n2->narg.next = NULL;
9631 checkkwd = CHKKWD | CHKALIAS;
9632 } while (readtoken() == TNL);
9633 if (lasttoken != TIN)
9635 cpp = &n1->ncase.cases;
9637 checkkwd = CHKNL | CHKKWD;
9639 while (t != TESAC) {
9640 if (lasttoken == TLP)
9642 *cpp = cp = (union node *)stalloc(sizeof(struct nclist));
9644 app = &cp->nclist.pattern;
9646 *app = ap = (union node *)stalloc(sizeof(struct narg));
9648 ap->narg.text = wordtext;
9649 ap->narg.backquote = backquotelist;
9650 if (readtoken() != TPIPE)
9652 app = &ap->narg.next;
9655 ap->narg.next = NULL;
9656 if (lasttoken != TRP)
9658 cp->nclist.body = list(2);
9660 cpp = &cp->nclist.next;
9662 checkkwd = CHKNL | CHKKWD;
9663 if ((t = readtoken()) != TESAC) {
9665 synexpect(TENDCASE);
9673 n1 = (union node *)stalloc(sizeof(struct nredir));
9674 n1->type = NSUBSHELL;
9675 n1->nredir.n = list(0);
9676 n1->nredir.redirect = NULL;
9689 if (readtoken() != t)
9693 /* Now check for redirection which may follow command */
9694 checkkwd = CHKKWD | CHKALIAS;
9696 while (readtoken() == TREDIR) {
9697 *rpp = n2 = redirnode;
9698 rpp = &n2->nfile.next;
9704 if (n1->type != NSUBSHELL) {
9705 n2 = (union node *)stalloc(sizeof(struct nredir));
9710 n1->nredir.redirect = redir;
9719 union node *args, **app;
9720 union node *n = NULL;
9721 union node *vars, **vpp;
9722 union node **rpp, *redir;
9732 savecheckkwd = CHKALIAS;
9734 checkkwd = savecheckkwd;
9735 switch (readtoken()) {
9737 n = (union node *)stalloc(sizeof(struct narg));
9739 n->narg.text = wordtext;
9740 n->narg.backquote = backquotelist;
9741 if (savecheckkwd && isassignment(wordtext)) {
9743 vpp = &n->narg.next;
9746 app = &n->narg.next;
9751 *rpp = n = redirnode;
9752 rpp = &n->nfile.next;
9753 parsefname(); /* read name of redirection file */
9757 args && app == &args->narg.next &&
9760 struct builtincmd *bcmd;
9763 /* We have a function */
9764 if (readtoken() != TRP)
9766 name = n->narg.text;
9768 !goodname(name) || (
9769 (bcmd = find_builtin(name)) &&
9770 IS_BUILTIN_SPECIAL(bcmd)
9773 synerror("Bad function name");
9775 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9776 n->narg.next = command();
9789 n = (union node *)stalloc(sizeof(struct ncmd));
9791 n->ncmd.args = args;
9792 n->ncmd.assign = vars;
9793 n->ncmd.redirect = redir;
9802 n = (union node *)stalloc(sizeof(struct narg));
9804 n->narg.next = NULL;
9805 n->narg.text = wordtext;
9806 n->narg.backquote = backquotelist;
9810 void fixredir(union node *n, const char *text, int err)
9812 TRACE(("Fix redir %s %d\n", text, err));
9814 n->ndup.vname = NULL;
9816 if (is_digit(text[0]) && text[1] == '\0')
9817 n->ndup.dupfd = digit_val(text[0]);
9818 else if (LONE_DASH(text))
9823 synerror("Bad fd number");
9825 n->ndup.vname = makename();
9833 union node *n = redirnode;
9835 if (readtoken() != TWORD)
9837 if (n->type == NHERE) {
9838 struct heredoc *here = heredoc;
9844 TRACE(("Here document %d\n", n->type));
9845 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9846 synerror("Illegal eof marker for << redirection");
9847 rmescapes(wordtext);
9848 here->eofmark = wordtext;
9850 if (heredoclist == NULL)
9853 for (p = heredoclist ; p->next ; p = p->next);
9856 } else if (n->type == NTOFD || n->type == NFROMFD) {
9857 fixredir(n, wordtext, 0);
9859 n->nfile.fname = makename();
9865 * Input any here documents.
9871 struct heredoc *here;
9881 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9882 here->eofmark, here->striptabs);
9883 n = (union node *)stalloc(sizeof(struct narg));
9884 n->narg.type = NARG;
9885 n->narg.next = NULL;
9886 n->narg.text = wordtext;
9887 n->narg.backquote = backquotelist;
9888 here->here->nhere.doc = n;
9893 static char peektoken(void)
9899 return tokname_array[t][0];
9907 int alreadyseen = tokpushback;
9910 #if ENABLE_ASH_ALIAS
9919 if (checkkwd & CHKNL) {
9926 if (t != TWORD || quoteflag) {
9931 * check for keywords
9933 if (checkkwd & CHKKWD) {
9934 const char *const *pp;
9936 if ((pp = findkwd(wordtext))) {
9937 lasttoken = t = pp - tokname_array;
9938 TRACE(("keyword %s recognized\n", tokname(t)));
9943 if (checkkwd & CHKALIAS) {
9944 #if ENABLE_ASH_ALIAS
9946 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9948 pushstring(ap->val, ap);
9958 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9960 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9967 * Read the next input token.
9968 * If the token is a word, we set backquotelist to the list of cmds in
9969 * backquotes. We set quoteflag to true if any part of the word was
9971 * If the token is TREDIR, then we set redirnode to a structure containing
9973 * In all cases, the variable startlinno is set to the number of the line
9974 * on which the token starts.
9976 * [Change comment: here documents and internal procedures]
9977 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9978 * word parsing code into a separate routine. In this case, readtoken
9979 * doesn't need to have any internal procedures, but parseword does.
9980 * We could also make parseoperator in essence the main routine, and
9981 * have parseword (readtoken1?) handle both words and redirection.]
9984 #define NEW_xxreadtoken
9985 #ifdef NEW_xxreadtoken
9987 /* singles must be first! */
9988 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9990 static const char xxreadtoken_tokens[] = {
9991 TNL, TLP, TRP, /* only single occurrence allowed */
9992 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9993 TEOF, /* corresponds to trailing nul */
9994 TAND, TOR, TENDCASE, /* if double occurrence */
9997 #define xxreadtoken_doubles \
9998 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9999 #define xxreadtoken_singles \
10000 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10002 static int xxreadtoken(void)
10013 startlinno = plinno;
10014 for (;;) { /* until token or start of word found */
10017 if ((c != ' ') && (c != '\t')
10018 #if ENABLE_ASH_ALIAS
10023 while ((c = pgetc()) != '\n' && c != PEOF);
10025 } else if (c == '\\') {
10026 if (pgetc() != '\n') {
10030 startlinno = ++plinno;
10035 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10040 needprompt = doprompt;
10043 p = strchr(xxreadtoken_chars, c);
10046 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10049 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10050 if (pgetc() == *p) { /* double occurrence? */
10051 p += xxreadtoken_doubles + 1;
10058 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10066 #define RETURN(token) return lasttoken = token
10080 startlinno = plinno;
10081 for (;;) { /* until token or start of word found */
10084 case ' ': case '\t':
10085 #if ENABLE_ASH_ALIAS
10090 while ((c = pgetc()) != '\n' && c != PEOF);
10094 if (pgetc() == '\n') {
10095 startlinno = ++plinno;
10104 needprompt = doprompt;
10109 if (pgetc() == '&')
10114 if (pgetc() == '|')
10119 if (pgetc() == ';')
10132 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10135 #endif /* NEW_xxreadtoken */
10139 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10140 * is not NULL, read a here document. In the latter case, eofmark is the
10141 * word which marks the end of the document and striptabs is true if
10142 * leading tabs should be stripped from the document. The argument firstc
10143 * is the first character of the input token or document.
10145 * Because C does not have internal subroutines, I have simulated them
10146 * using goto's to implement the subroutine linkage. The following macros
10147 * will run code that appears at the end of readtoken1.
10150 #define CHECKEND() {goto checkend; checkend_return:;}
10151 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10152 #define PARSESUB() {goto parsesub; parsesub_return:;}
10153 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10154 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10155 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10158 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10163 char line[EOFMARKLEN + 1];
10164 struct nodelist *bqlist = 0;
10167 int varnest = 0; /* levels of variables expansion */
10168 int arinest = 0; /* levels of arithmetic expansion */
10169 int parenlevel = 0; /* levels of parens in arithmetic */
10170 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10172 int prevsyntax = 0; /* syntax before arithmetic */
10174 /* Avoid longjmp clobbering */
10180 (void) &parenlevel;
10183 (void) &prevsyntax;
10187 startlinno = plinno;
10189 if (syntax == DQSYNTAX)
10198 STARTSTACKSTR(out);
10199 loop: { /* for each line, until end of word */
10200 CHECKEND(); /* set c to PEOF if at end of here document */
10201 for (;;) { /* until end of line or end of word */
10202 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10203 switch (SIT(c, syntax)) {
10204 case CNL: /* '\n' */
10205 if (syntax == BASESYNTAX)
10206 goto endword; /* exit outer loop */
10212 goto loop; /* continue outer loop */
10217 if (eofmark == NULL || dblquote)
10218 USTPUTC(CTLESC, out);
10221 case CBACK: /* backslash */
10224 USTPUTC(CTLESC, out);
10225 USTPUTC('\\', out);
10227 } else if (c == '\n') {
10232 c != '\\' && c != '`' &&
10237 USTPUTC(CTLESC, out);
10238 USTPUTC('\\', out);
10240 if (SIT(c, SQSYNTAX) == CCTL)
10241 USTPUTC(CTLESC, out);
10249 if (eofmark == NULL) {
10250 USTPUTC(CTLQUOTEMARK, out);
10258 if (eofmark != NULL && arinest == 0
10263 if (dqvarnest == 0) {
10264 syntax = BASESYNTAX;
10271 case CVAR: /* '$' */
10272 PARSESUB(); /* parse substitution */
10274 case CENDVAR: /* '}' */
10277 if (dqvarnest > 0) {
10280 USTPUTC(CTLENDVAR, out);
10285 #if ENABLE_ASH_MATH_SUPPORT
10286 case CLP: /* '(' in arithmetic */
10290 case CRP: /* ')' in arithmetic */
10291 if (parenlevel > 0) {
10295 if (pgetc() == ')') {
10296 if (--arinest == 0) {
10297 USTPUTC(CTLENDARI, out);
10298 syntax = prevsyntax;
10299 if (syntax == DQSYNTAX)
10307 * unbalanced parens
10308 * (don't 2nd guess - no error)
10316 case CBQUOTE: /* '`' */
10320 goto endword; /* exit outer loop */
10325 goto endword; /* exit outer loop */
10326 #if ENABLE_ASH_ALIAS
10336 #if ENABLE_ASH_MATH_SUPPORT
10337 if (syntax == ARISYNTAX)
10338 synerror("Missing '))'");
10340 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10341 synerror("Unterminated quoted string");
10342 if (varnest != 0) {
10343 startlinno = plinno;
10345 synerror("Missing '}'");
10347 USTPUTC('\0', out);
10348 len = out - (char *)stackblock();
10349 out = stackblock();
10350 if (eofmark == NULL) {
10351 if ((c == '>' || c == '<')
10354 && (*out == '\0' || is_digit(*out))) {
10356 return lasttoken = TREDIR;
10361 quoteflag = quotef;
10362 backquotelist = bqlist;
10363 grabstackblock(len);
10367 /* end of readtoken routine */
10371 * Check to see whether we are at the end of the here document. When this
10372 * is called, c is set to the first character of the next input line. If
10373 * we are at the end of the here document, this routine sets the c to PEOF.
10378 #if ENABLE_ASH_ALIAS
10384 while (c == '\t') {
10388 if (c == *eofmark) {
10389 if (pfgets(line, sizeof(line)) != NULL) {
10393 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10394 if (*p == '\n' && *q == '\0') {
10397 needprompt = doprompt;
10399 pushstring(line, NULL);
10404 goto checkend_return;
10409 * Parse a redirection operator. The variable "out" points to a string
10410 * specifying the fd to be redirected. The variable "c" contains the
10411 * first character of the redirection operator.
10418 np = (union node *)stalloc(sizeof(struct nfile));
10423 np->type = NAPPEND;
10425 np->type = NCLOBBER;
10432 } else { /* c == '<' */
10434 switch (c = pgetc()) {
10436 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10437 np = (union node *)stalloc(sizeof(struct nhere));
10441 heredoc = (struct heredoc *)stalloc(sizeof(struct heredoc));
10442 heredoc->here = np;
10443 if ((c = pgetc()) == '-') {
10444 heredoc->striptabs = 1;
10446 heredoc->striptabs = 0;
10452 np->type = NFROMFD;
10456 np->type = NFROMTO;
10466 np->nfile.fd = digit_val(fd);
10468 goto parseredir_return;
10473 * Parse a substitution. At this point, we have read the dollar sign
10474 * and nothing else.
10482 static const char types[] = "}-+?=";
10486 c <= PEOA_OR_PEOF ||
10487 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10491 } else if (c == '(') { /* $(command) or $((arith)) */
10492 if (pgetc() == '(') {
10493 #if ENABLE_ASH_MATH_SUPPORT
10496 synerror("We unsupport $((arith))");
10503 USTPUTC(CTLVAR, out);
10504 typeloc = out - (char *)stackblock();
10505 USTPUTC(VSNORMAL, out);
10506 subtype = VSNORMAL;
10510 if ((c = pgetc()) == '}')
10513 subtype = VSLENGTH;
10518 if (c > PEOA_OR_PEOF && is_name(c)) {
10522 } while (c > PEOA_OR_PEOF && is_in_name(c));
10523 } else if (is_digit(c)) {
10527 } while (is_digit(c));
10528 } else if (is_special(c)) {
10532 badsub: synerror("Bad substitution");
10536 if (subtype == 0) {
10543 p = strchr(types, c);
10546 subtype = p - types + VSNORMAL;
10552 subtype = c == '#' ? VSTRIMLEFT :
10565 if (dblquote || arinest)
10567 *((char *)stackblock() + typeloc) = subtype | flags;
10568 if (subtype != VSNORMAL) {
10570 if (dblquote || arinest) {
10575 goto parsesub_return;
10580 * Called to parse command substitutions. Newstyle is set if the command
10581 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10582 * list of commands (passed by reference), and savelen is the number of
10583 * characters on the top of the stack which must be preserved.
10587 struct nodelist **nlpp;
10590 char *volatile str;
10591 struct jmploc jmploc;
10592 struct jmploc *volatile savehandler;
10594 int saveprompt = 0;
10596 (void) &saveprompt;
10599 savepbq = parsebackquote;
10600 if (setjmp(jmploc.loc)) {
10603 parsebackquote = 0;
10604 handler = savehandler;
10605 longjmp(handler->loc, 1);
10609 savelen = out - (char *)stackblock();
10611 str = ckmalloc(savelen);
10612 memcpy(str, stackblock(), savelen);
10614 savehandler = handler;
10618 /* We must read until the closing backquote, giving special
10619 treatment to some slashes, and then push the string and
10620 reread it as input, interpreting it normally. */
10627 STARTSTACKSTR(pout);
10632 switch (pc = pgetc()) {
10637 if ((pc = pgetc()) == '\n') {
10642 * If eating a newline, avoid putting
10643 * the newline into the new character
10644 * stream (via the STPUTC after the
10649 if (pc != '\\' && pc != '`' && pc != '$'
10650 && (!dblquote || pc != '"'))
10651 STPUTC('\\', pout);
10652 if (pc > PEOA_OR_PEOF) {
10658 #if ENABLE_ASH_ALIAS
10661 startlinno = plinno;
10662 synerror("EOF in backquote substitution");
10666 needprompt = doprompt;
10675 STPUTC('\0', pout);
10676 psavelen = pout - (char *)stackblock();
10677 if (psavelen > 0) {
10678 pstr = grabstackstr(pout);
10679 setinputstring(pstr);
10684 nlpp = &(*nlpp)->next;
10685 *nlpp = (struct nodelist *)stalloc(sizeof(struct nodelist));
10686 (*nlpp)->next = NULL;
10687 parsebackquote = oldstyle;
10690 saveprompt = doprompt;
10697 doprompt = saveprompt;
10699 if (readtoken() != TRP)
10706 * Start reading from old file again, ignoring any pushed back
10707 * tokens left from the backquote parsing
10712 while (stackblocksize() <= savelen)
10714 STARTSTACKSTR(out);
10716 memcpy(out, str, savelen);
10717 STADJUST(savelen, out);
10723 parsebackquote = savepbq;
10724 handler = savehandler;
10725 if (arinest || dblquote)
10726 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10728 USTPUTC(CTLBACKQ, out);
10730 goto parsebackq_oldreturn;
10732 goto parsebackq_newreturn;
10735 #if ENABLE_ASH_MATH_SUPPORT
10737 * Parse an arithmetic expansion (indicate start of one and set state)
10740 if (++arinest == 1) {
10741 prevsyntax = syntax;
10742 syntax = ARISYNTAX;
10743 USTPUTC(CTLARI, out);
10750 * we collapse embedded arithmetic expansion to
10751 * parenthesis, which should be equivalent
10755 goto parsearith_return;
10759 } /* end of readtoken */
10763 * Returns true if the text contains nothing to expand (no dollar signs
10768 noexpand(char *text)
10774 while ((c = *p++) != '\0') {
10775 if (c == CTLQUOTEMARK)
10779 else if (SIT(c, BASESYNTAX) == CCTL)
10787 * Return of a legal variable name (a letter or underscore followed by zero or
10788 * more letters, underscores, and digits).
10792 endofname(const char *name)
10800 if (!is_in_name(*p))
10808 * Called when an unexpected token is read during the parse. The argument
10809 * is the token that is expected, or -1 if more than one type of token can
10810 * occur at this point.
10813 static void synexpect(int token)
10818 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10820 sprintf(msg + l, " (expecting %s)", tokname(token));
10826 synerror(const char *msg)
10828 sh_error("Syntax error: %s", msg);
10834 * called by editline -- any expansions to the prompt
10835 * should be added here.
10838 #if ENABLE_ASH_EXPAND_PRMT
10839 static const char *
10840 expandstr(const char *ps)
10844 /* XXX Fix (char *) cast. */
10845 setinputstring((char *)ps);
10846 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10849 n.narg.type = NARG;
10850 n.narg.next = NULL;
10851 n.narg.text = wordtext;
10852 n.narg.backquote = backquotelist;
10854 expandarg(&n, NULL, 0);
10855 return stackblock();
10859 static void setprompt(int whichprompt)
10861 const char *prompt;
10862 #if ENABLE_ASH_EXPAND_PRMT
10863 struct stackmark smark;
10868 switch (whichprompt) {
10878 #if ENABLE_ASH_EXPAND_PRMT
10879 setstackmark(&smark);
10880 stalloc(stackblocksize());
10882 putprompt(expandstr(prompt));
10883 #if ENABLE_ASH_EXPAND_PRMT
10884 popstackmark(&smark);
10889 static const char *const *findkwd(const char *s)
10891 return bsearch(s, tokname_array + KWDOFFSET,
10892 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10893 sizeof(const char *), pstrcmp);
10899 * Code for dealing with input/output redirection.
10902 #define EMPTY -2 /* marks an unused slot in redirtab */
10904 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10906 # define PIPESIZE PIPE_BUF
10910 * Open a file in noclobber mode.
10911 * The code was copied from bash.
10913 static int noclobberopen(const char *fname)
10916 struct stat finfo, finfo2;
10919 * If the file exists and is a regular file, return an error
10922 r = stat(fname, &finfo);
10923 if (r == 0 && S_ISREG(finfo.st_mode)) {
10929 * If the file was not present (r != 0), make sure we open it
10930 * exclusively so that if it is created before we open it, our open
10931 * will fail. Make sure that we do not truncate an existing file.
10932 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10933 * file was not a regular file, we leave O_EXCL off.
10936 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10937 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10939 /* If the open failed, return the file descriptor right away. */
10944 * OK, the open succeeded, but the file may have been changed from a
10945 * non-regular file to a regular file between the stat and the open.
10946 * We are assuming that the O_EXCL open handles the case where FILENAME
10947 * did not exist and is symlinked to an existing file between the stat
10952 * If we can open it and fstat the file descriptor, and neither check
10953 * revealed that it was a regular file, and the file has not been
10954 * replaced, return the file descriptor.
10956 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
10957 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10960 /* The file has been replaced. badness. */
10967 * Handle here documents. Normally we fork off a process to write the
10968 * data to a pipe. If the document is short, we can stuff the data in
10969 * the pipe without forking.
10972 static int openhere(union node *redir)
10978 sh_error("Pipe call failed");
10979 if (redir->type == NHERE) {
10980 len = strlen(redir->nhere.doc->narg.text);
10981 if (len <= PIPESIZE) {
10982 full_write(pip[1], redir->nhere.doc->narg.text, len);
10986 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10988 signal(SIGINT, SIG_IGN);
10989 signal(SIGQUIT, SIG_IGN);
10990 signal(SIGHUP, SIG_IGN);
10992 signal(SIGTSTP, SIG_IGN);
10994 signal(SIGPIPE, SIG_DFL);
10995 if (redir->type == NHERE)
10996 full_write(pip[1], redir->nhere.doc->narg.text, len);
10998 expandhere(redir->nhere.doc, pip[1]);
11007 openredirect(union node *redir)
11012 switch (redir->nfile.type) {
11014 fname = redir->nfile.expfname;
11015 if ((f = open(fname, O_RDONLY)) < 0)
11019 fname = redir->nfile.expfname;
11020 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11024 /* Take care of noclobber mode. */
11026 fname = redir->nfile.expfname;
11027 if ((f = noclobberopen(fname)) < 0)
11033 fname = redir->nfile.expfname;
11034 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11038 fname = redir->nfile.expfname;
11039 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11046 /* Fall through to eliminate warning. */
11053 f = openhere(redir);
11059 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11061 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11064 static void dupredirect(union node *redir, int f)
11066 int fd = redir->nfile.fd;
11068 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11069 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11070 copyfd(redir->ndup.dupfd, fd);
11082 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11083 * old file descriptors are stashed away so that the redirection can be
11084 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11085 * standard output, and the standard error if it becomes a duplicate of
11086 * stdout, is saved in memory.
11090 redirect(union node *redir, int flags)
11093 struct redirtab *sv;
11104 if (flags & REDIR_PUSH) {
11105 struct redirtab *q;
11106 q = ckmalloc(sizeof(struct redirtab));
11107 q->next = redirlist;
11109 q->nullredirs = nullredirs - 1;
11110 for (i = 0 ; i < 10 ; i++)
11111 q->renamed[i] = EMPTY;
11118 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
11119 && n->ndup.dupfd == fd)
11120 continue; /* redirect from/to same file descriptor */
11122 newfd = openredirect(n);
11125 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11126 i = fcntl(fd, F_DUPFD, 10);
11133 sh_error("%d: %m", fd);
11143 dupredirect(n, newfd);
11144 } while ((n = n->nfile.next));
11146 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11147 preverrout_fd = sv->renamed[2];
11152 * Undo the effects of the last redirection.
11158 struct redirtab *rp;
11161 if (--nullredirs >= 0)
11165 for (i = 0 ; i < 10 ; i++) {
11166 if (rp->renamed[i] != EMPTY) {
11169 copyfd(rp->renamed[i], i);
11171 close(rp->renamed[i]);
11174 redirlist = rp->next;
11175 nullredirs = rp->nullredirs;
11181 * Undo all redirections. Called on error or interrupt.
11185 * Discard all saved file descriptors.
11189 clearredir(int drop)
11201 * Copy a file descriptor to be >= to. Returns -1
11202 * if the source file descriptor is closed, EMPTY if there are no unused
11203 * file descriptors left.
11207 copyfd(int from, int to)
11211 newfd = fcntl(from, F_DUPFD, to);
11213 if (errno == EMFILE)
11216 sh_error("%d: %m", from);
11223 redirectsafe(union node *redir, int flags)
11226 volatile int saveint;
11227 struct jmploc *volatile savehandler = handler;
11228 struct jmploc jmploc;
11231 if (!(err = setjmp(jmploc.loc) * 2)) {
11233 redirect(redir, flags);
11235 handler = savehandler;
11236 if (err && exception != EXERROR)
11237 longjmp(handler->loc, 1);
11238 RESTOREINT(saveint);
11245 static void shtree(union node *, int, char *, FILE*);
11246 static void shcmd(union node *, FILE *);
11247 static void sharg(union node *, FILE *);
11248 static void indent(int, char *, FILE *);
11249 static void trstring(char *);
11253 showtree(union node *n)
11255 trputs("showtree called\n");
11256 shtree(n, 1, NULL, stdout);
11261 shtree(union node *n, int ind, char *pfx, FILE *fp)
11263 struct nodelist *lp;
11269 indent(ind, pfx, fp);
11280 shtree(n->nbinary.ch1, ind, NULL, fp);
11283 shtree(n->nbinary.ch2, ind, NULL, fp);
11291 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11296 if (n->npipe.backgnd)
11302 fprintf(fp, "<node type %d>", n->type);
11311 shcmd(union node *cmd, FILE *fp)
11319 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11325 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11328 switch (np->nfile.type) {
11329 case NTO: s = ">"; dftfd = 1; break;
11330 case NCLOBBER: s = ">|"; dftfd = 1; break;
11331 case NAPPEND: s = ">>"; dftfd = 1; break;
11332 case NTOFD: s = ">&"; dftfd = 1; break;
11333 case NFROM: s = "<"; dftfd = 0; break;
11334 case NFROMFD: s = "<&"; dftfd = 0; break;
11335 case NFROMTO: s = "<>"; dftfd = 0; break;
11336 default: s = "*error*"; dftfd = 0; break;
11338 if (np->nfile.fd != dftfd)
11339 fprintf(fp, "%d", np->nfile.fd);
11341 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11342 fprintf(fp, "%d", np->ndup.dupfd);
11344 sharg(np->nfile.fname, fp);
11352 sharg(union node *arg, FILE *fp)
11355 struct nodelist *bqlist;
11358 if (arg->type != NARG) {
11359 out1fmt("<node type %d>\n", arg->type);
11362 bqlist = arg->narg.backquote;
11363 for (p = arg->narg.text ; *p ; p++) {
11372 if (subtype == VSLENGTH)
11378 if (subtype & VSNUL)
11381 switch (subtype & VSTYPE) {
11400 case VSTRIMLEFTMAX:
11407 case VSTRIMRIGHTMAX:
11414 out1fmt("<subtype %d>", subtype);
11421 case CTLBACKQ|CTLQUOTE:
11424 shtree(bqlist->n, -1, NULL, fp);
11436 indent(int amount, char *pfx, FILE *fp)
11440 for (i = 0 ; i < amount ; i++) {
11441 if (pfx && i == amount - 1)
11461 putc(c, tracefile);
11465 trace(const char *fmt, ...)
11472 (void) vfprintf(tracefile, fmt, va);
11477 tracev(const char *fmt, va_list va)
11481 (void) vfprintf(tracefile, fmt, va);
11486 trputs(const char *s)
11490 fputs(s, tracefile);
11502 putc('"', tracefile);
11503 for (p = s ; *p ; p++) {
11505 case '\n': c = 'n'; goto backslash;
11506 case '\t': c = 't'; goto backslash;
11507 case '\r': c = 'r'; goto backslash;
11508 case '"': c = '"'; goto backslash;
11509 case '\\': c = '\\'; goto backslash;
11510 case CTLESC: c = 'e'; goto backslash;
11511 case CTLVAR: c = 'v'; goto backslash;
11512 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11513 case CTLBACKQ: c = 'q'; goto backslash;
11514 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11515 backslash: putc('\\', tracefile);
11516 putc(c, tracefile);
11519 if (*p >= ' ' && *p <= '~')
11520 putc(*p, tracefile);
11522 putc('\\', tracefile);
11523 putc(*p >> 6 & 03, tracefile);
11524 putc(*p >> 3 & 07, tracefile);
11525 putc(*p & 07, tracefile);
11530 putc('"', tracefile);
11542 putc(' ', tracefile);
11544 putc('\n', tracefile);
11560 /* leave open because libedit might be using it */
11563 scopy("./trace", s);
11565 if (!freopen(s, "a", tracefile)) {
11566 fprintf(stderr, "Can't re-open %s\n", s);
11571 if ((tracefile = fopen(s, "a")) == NULL) {
11572 fprintf(stderr, "Can't open %s\n", s);
11578 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11579 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11581 setlinebuf(tracefile);
11582 fputs("\nTracing started.\n", tracefile);
11590 * Sigmode records the current value of the signal handlers for the various
11591 * modes. A value of zero means that the current handler is not known.
11592 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11595 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11596 #define S_CATCH 2 /* signal is caught */
11597 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11598 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11599 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11603 * The trap builtin.
11607 trapcmd(int argc, char **argv)
11616 for (signo = 0 ; signo < NSIG ; signo++) {
11617 if (trap[signo] != NULL) {
11620 sn = get_signame(signo);
11621 out1fmt("trap -- %s %s\n",
11622 single_quote(trap[signo]), sn);
11632 if ((signo = get_signum(*ap)) < 0)
11633 sh_error("%s: bad trap", *ap);
11636 if (LONE_DASH(action))
11639 action = savestr(action);
11642 ckfree(trap[signo]);
11643 trap[signo] = action;
11654 * Clear traps on a fork.
11662 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11663 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11667 if (tp != &trap[0])
11668 setsignal(tp - trap);
11676 * Set the signal handler for the specified signal. The routine figures
11677 * out what it should be set to.
11681 setsignal(int signo)
11685 struct sigaction act;
11687 if ((t = trap[signo]) == NULL)
11689 else if (*t != '\0')
11693 if (rootshell && action == S_DFL) {
11696 if (iflag || minusc || sflag == 0)
11719 t = &sigmode[signo - 1];
11723 * current setting unknown
11725 if (sigaction(signo, 0, &act) == -1) {
11727 * Pretend it worked; maybe we should give a warning
11728 * here, but other shells don't. We don't alter
11729 * sigmode, so that we retry every time.
11733 if (act.sa_handler == SIG_IGN) {
11734 if (mflag && (signo == SIGTSTP || signo == SIGTTIN
11735 || signo == SIGTTOU)
11737 tsig = S_IGN; /* don't hard ignore these */
11741 tsig = S_RESET; /* force to be set */
11744 if (tsig == S_HARD_IGN || tsig == action)
11748 act.sa_handler = onsig;
11751 act.sa_handler = SIG_IGN;
11754 act.sa_handler = SIG_DFL;
11758 sigfillset(&act.sa_mask);
11759 sigaction(signo, &act, 0);
11767 ignoresig(int signo)
11769 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11770 signal(signo, SIG_IGN);
11772 sigmode[signo - 1] = S_HARD_IGN;
11783 gotsig[signo - 1] = 1;
11784 pendingsigs = signo;
11786 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11795 * Called to execute a trap. Perhaps we should avoid entering new trap
11796 * handlers while we are executing a trap handler.
11808 savestatus = exitstatus;
11812 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11820 skip = evalstring(p, SKIPEVAL);
11821 exitstatus = savestatus;
11831 * Controls whether the shell is interactive or not.
11835 setinteractive(int on)
11837 static int is_interactive;
11839 if (++on == is_interactive)
11841 is_interactive = on;
11843 setsignal(SIGQUIT);
11844 setsignal(SIGTERM);
11845 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11846 if (is_interactive > 1) {
11847 /* Looks like they want an interactive shell */
11848 static int do_banner;
11852 "\n\n%s Built-in shell (ash)\n"
11853 "Enter 'help' for a list of built-in commands.\n\n",
11862 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11863 /*** List the available builtins ***/
11865 static int helpcmd(int argc, char **argv)
11869 out1fmt("\nBuilt-in commands:\n-------------------\n");
11870 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11871 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11872 builtincmd[i].name + 1);
11878 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11879 for (i = 0; i < NUM_APPLETS; i++) {
11880 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11888 return EXIT_SUCCESS;
11890 #endif /* FEATURE_SH_EXTRA_QUIET */
11893 * Called to exit the shell.
11903 status = exitstatus;
11904 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11905 if (setjmp(loc.loc)) {
11906 if (exception == EXEXIT)
11907 /* dash bug: it just does _exit(exitstatus) here
11908 * but we have to do setjobctl(0) first!
11909 * (bug is still not fixed in dash-0.5.3 - if you run dash
11910 * under Midnight Commander, on exit from dash MC is backgrounded) */
11911 status = exitstatus;
11915 if ((p = trap[0])) {
11928 static struct var *vartab[VTABSIZE];
11930 static int vpcmp(const void *, const void *);
11931 static struct var **findvar(struct var **, const char *);
11934 * Initialize the variable symbol tables and import the environment
11938 #if ENABLE_ASH_GETOPTS
11940 * Safe version of setvar, returns 1 on success 0 on failure.
11944 setvarsafe(const char *name, const char *val, int flags)
11947 volatile int saveint;
11948 struct jmploc *volatile savehandler = handler;
11949 struct jmploc jmploc;
11952 if (setjmp(jmploc.loc))
11956 setvar(name, val, flags);
11959 handler = savehandler;
11960 RESTOREINT(saveint);
11966 * Set the value of a variable. The flags argument is ored with the
11967 * flags of the variable. If val is NULL, the variable is unset.
11971 setvar(const char *name, const char *val, int flags)
11978 q = endofname(name);
11979 p = strchrnul(q, '=');
11980 namelen = p - name;
11981 if (!namelen || p != q)
11982 sh_error("%.*s: bad variable name", namelen, name);
11987 vallen = strlen(val);
11990 nameeq = ckmalloc(namelen + vallen + 2);
11991 p = memcpy(nameeq, name, namelen) + namelen;
11994 p = memcpy(p, val, vallen) + vallen;
11997 setvareq(nameeq, flags | VNOSAVE);
12003 * Same as setvar except that the variable and value are passed in
12004 * the first argument as name=value. Since the first argument will
12005 * be actually stored in the table, it should not be a string that
12007 * Called with interrupts off.
12011 setvareq(char *s, int flags)
12013 struct var *vp, **vpp;
12016 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12017 vp = *findvar(vpp, s);
12019 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12022 if (flags & VNOSAVE)
12025 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12028 if (flags & VNOSET)
12031 if (vp->func && (flags & VNOFUNC) == 0)
12032 (*vp->func)(strchrnul(s, '=') + 1);
12034 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12037 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12039 if (flags & VNOSET)
12042 vp = ckmalloc(sizeof(*vp));
12047 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12055 * Process a linked list of variable assignments.
12059 listsetvar(struct strlist *list_set_var, int flags)
12061 struct strlist *lp = list_set_var;
12067 setvareq(lp->text, flags);
12068 } while ((lp = lp->next));
12074 * Find the value of a variable. Returns NULL if not set.
12078 lookupvar(const char *name)
12082 if ((v = *findvar(hashvar(name), name))) {
12085 * Dynamic variables are implemented roughly the same way they are
12086 * in bash. Namely, they're "special" so long as they aren't unset.
12087 * As soon as they're unset, they're no longer dynamic, and dynamic
12088 * lookup will no longer happen at that point. -- PFM.
12090 if ((v->flags & VDYNAMIC))
12093 if (!(v->flags & VUNSET))
12094 return strchrnul(v->text, '=') + 1;
12102 * Search the environment of a builtin command.
12106 bltinlookup(const char *name)
12108 struct strlist *sp;
12110 for (sp = cmdenviron ; sp ; sp = sp->next) {
12111 if (varequal(sp->text, name))
12112 return strchrnul(sp->text, '=') + 1;
12114 return lookupvar(name);
12119 * Generate a list of variables satisfying the given conditions.
12123 listvars(int on, int off, char ***end)
12134 for (vp = *vpp ; vp ; vp = vp->next)
12135 if ((vp->flags & mask) == on) {
12136 if (ep == stackstrend())
12137 ep = growstackstr();
12138 *ep++ = (char *) vp->text;
12140 } while (++vpp < vartab + VTABSIZE);
12141 if (ep == stackstrend())
12142 ep = growstackstr();
12146 return grabstackstr(ep);
12151 * POSIX requires that 'set' (but not export or readonly) output the
12152 * variables in lexicographic order - by the locale's collating order (sigh).
12153 * Maybe we could keep them in an ordered balanced binary tree
12154 * instead of hashed lists.
12155 * For now just roll 'em through qsort for printing...
12159 showvars(const char *sep_prefix, int on, int off)
12162 char **ep, **epend;
12164 ep = listvars(on, off, &epend);
12165 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12167 sep = *sep_prefix ? spcstr : sep_prefix;
12169 for (; ep < epend; ep++) {
12173 p = strchrnul(*ep, '=');
12176 q = single_quote(++p);
12178 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12186 * The export and readonly commands.
12190 exportcmd(int argc, char **argv)
12196 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12199 notp = nextopt("p") - 'p';
12200 if (notp && ((name = *(aptr = argptr)))) {
12202 if ((p = strchr(name, '=')) != NULL) {
12205 if ((vp = *findvar(hashvar(name), name))) {
12210 setvar(name, p, flag);
12211 } while ((name = *++aptr) != NULL);
12213 showvars(argv[0], flag, 0);
12220 * Make a variable a local variable. When a variable is made local, it's
12221 * value and flags are saved in a localvar structure. The saved values
12222 * will be restored when the shell function returns. We handle the name
12223 * "-" as a special case.
12226 static void mklocal(char *name)
12228 struct localvar *lvp;
12233 lvp = ckmalloc(sizeof(struct localvar));
12234 if (LONE_DASH(name)) {
12236 p = ckmalloc(sizeof(optlist));
12237 lvp->text = memcpy(p, optlist, sizeof(optlist));
12242 vpp = hashvar(name);
12243 vp = *findvar(vpp, name);
12244 eq = strchr(name, '=');
12247 setvareq(name, VSTRFIXED);
12249 setvar(name, NULL, VSTRFIXED);
12250 vp = *vpp; /* the new variable */
12251 lvp->flags = VUNSET;
12253 lvp->text = vp->text;
12254 lvp->flags = vp->flags;
12255 vp->flags |= VSTRFIXED|VTEXTFIXED;
12261 lvp->next = localvars;
12267 * The "local" command.
12271 localcmd(int argc, char **argv)
12276 while ((name = *argv++) != NULL) {
12284 * Called after a function returns.
12285 * Interrupts must be off.
12291 struct localvar *lvp;
12294 while ((lvp = localvars) != NULL) {
12295 localvars = lvp->next;
12297 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12298 if (vp == NULL) { /* $- saved */
12299 memcpy(optlist, lvp->text, sizeof(optlist));
12302 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12303 unsetvar(vp->text);
12306 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12307 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12309 vp->flags = lvp->flags;
12310 vp->text = lvp->text;
12318 * The unset builtin command. We unset the function before we unset the
12319 * variable to allow a function to be unset when there is a readonly variable
12320 * with the same name.
12324 unsetcmd(int argc, char **argv)
12331 while ((i = nextopt("vf")) != '\0') {
12335 for (ap = argptr; *ap ; ap++) {
12350 * Unset the specified variable.
12354 unsetvar(const char *s)
12360 vpp = findvar(hashvar(s), s);
12364 int flags = vp->flags;
12367 if (flags & VREADONLY)
12370 vp->flags &= ~VDYNAMIC;
12372 if (flags & VUNSET)
12374 if ((flags & VSTRFIXED) == 0) {
12376 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12383 vp->flags &= ~VEXPORT;
12395 * Find the appropriate entry in the hash table from the name.
12398 static struct var **
12399 hashvar(const char *p)
12401 unsigned int hashval;
12403 hashval = ((unsigned char) *p) << 4;
12404 while (*p && *p != '=')
12405 hashval += (unsigned char) *p++;
12406 return &vartab[hashval % VTABSIZE];
12411 * Compares two strings up to the first = or '\0'. The first
12412 * string must be terminated by '='; the second may be terminated by
12413 * either '=' or '\0'.
12417 varcmp(const char *p, const char *q)
12421 while ((c = *p) == (d = *q)) {
12422 if (!c || c == '=')
12436 vpcmp(const void *a, const void *b)
12438 return varcmp(*(const char **)a, *(const char **)b);
12441 static struct var **
12442 findvar(struct var **vpp, const char *name)
12444 for (; *vpp; vpp = &(*vpp)->next) {
12445 if (varequal((*vpp)->text, name)) {
12453 #include <sys/times.h>
12455 static const unsigned char timescmd_str[] = {
12456 ' ', offsetof(struct tms, tms_utime),
12457 '\n', offsetof(struct tms, tms_stime),
12458 ' ', offsetof(struct tms, tms_cutime),
12459 '\n', offsetof(struct tms, tms_cstime),
12463 static int timescmd(int ac, char **av)
12465 long int clk_tck, s, t;
12466 const unsigned char *p;
12469 clk_tck = sysconf(_SC_CLK_TCK);
12474 t = *(clock_t *)(((char *) &buf) + p[1]);
12476 out1fmt("%ldm%ld.%.3lds%c",
12478 ((t - s * clk_tck) * 1000) / clk_tck,
12480 } while (*(p += 2));
12485 #if ENABLE_ASH_MATH_SUPPORT
12487 dash_arith(const char *s)
12493 result = arith(s, &errcode);
12496 sh_error("exponent less than 0");
12497 else if (errcode == -2)
12498 sh_error("divide by zero");
12499 else if (errcode == -5)
12500 sh_error("expression recursion loop detected");
12511 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12512 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12514 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12518 letcmd(int argc, char **argv)
12525 sh_error("expression expected");
12526 for (ap = argv + 1; *ap; ap++) {
12527 i = dash_arith(*ap);
12532 #endif /* ASH_MATH_SUPPORT */
12537 * Miscellaneous builtins.
12542 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12543 typedef enum __rlimit_resource rlim_t;
12548 * The read builtin. The -e option causes backslashes to escape the
12549 * following character.
12551 * This uses unbuffered input, which may be avoidable in some cases.
12555 readcmd(int argc, char **argv)
12567 #if ENABLE_ASH_READ_NCHARS
12571 struct termios tty, old_tty;
12573 #if ENABLE_ASH_READ_TIMEOUT
12577 ts.tv_sec = ts.tv_usec = 0;
12582 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
12583 while ((i = nextopt("p:rt:n:s")) != '\0')
12584 #elif ENABLE_ASH_READ_NCHARS
12585 while ((i = nextopt("p:rn:s")) != '\0')
12586 #elif ENABLE_ASH_READ_TIMEOUT
12587 while ((i = nextopt("p:rt:")) != '\0')
12589 while ((i = nextopt("p:r")) != '\0')
12594 prompt = optionarg;
12596 #if ENABLE_ASH_READ_NCHARS
12598 nchars = strtol(optionarg, &p, 10);
12600 sh_error("invalid count");
12601 nch_flag = (nchars > 0);
12607 #if ENABLE_ASH_READ_TIMEOUT
12609 ts.tv_sec = strtol(optionarg, &p, 10);
12615 ts.tv_usec = strtol(p, &p2, 10);
12617 sh_error("invalid timeout");
12619 /* normalize to usec */
12621 sh_error("invalid timeout");
12622 while (scale++ < 6)
12626 sh_error("invalid timeout");
12628 if ( ! ts.tv_sec && ! ts.tv_usec)
12629 sh_error("invalid timeout");
12639 if (prompt && isatty(0)) {
12642 if (*(ap = argptr) == NULL)
12643 sh_error("arg count");
12644 if ((ifs = bltinlookup("IFS")) == NULL)
12646 #if ENABLE_ASH_READ_NCHARS
12647 if (nch_flag || silent) {
12648 tcgetattr(0, &tty);
12651 tty.c_lflag &= ~ICANON;
12652 tty.c_cc[VMIN] = nchars;
12655 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12658 tcsetattr(0, TCSANOW, &tty);
12661 #if ENABLE_ASH_READ_TIMEOUT
12662 if (ts.tv_sec || ts.tv_usec) {
12666 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
12668 #if ENABLE_ASH_READ_NCHARS
12670 tcsetattr(0, TCSANOW, &old_tty);
12680 #if ENABLE_ASH_READ_NCHARS
12681 while (!nch_flag || nchars--)
12686 if (read(0, &c, 1) != 1) {
12698 if (!rflag && c == '\\') {
12704 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12708 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12710 setvar(*ap, stackblock(), 0);
12719 #if ENABLE_ASH_READ_NCHARS
12720 if (nch_flag || silent)
12721 tcsetattr(0, TCSANOW, &old_tty);
12725 /* Remove trailing blanks */
12726 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12728 setvar(*ap, stackblock(), 0);
12729 while (*++ap != NULL)
12730 setvar(*ap, nullstr, 0);
12735 static int umaskcmd(int argc, char **argv)
12737 static const char permuser[3] = "ugo";
12738 static const char permmode[3] = "rwx";
12739 static const short int permmask[] = {
12740 S_IRUSR, S_IWUSR, S_IXUSR,
12741 S_IRGRP, S_IWGRP, S_IXGRP,
12742 S_IROTH, S_IWOTH, S_IXOTH
12748 int symbolic_mode = 0;
12750 while (nextopt("S") != '\0') {
12759 if ((ap = *argptr) == NULL) {
12760 if (symbolic_mode) {
12764 for (i = 0; i < 3; i++) {
12767 *p++ = permuser[i];
12769 for (j = 0; j < 3; j++) {
12770 if ((mask & permmask[3 * i + j]) == 0) {
12771 *p++ = permmode[j];
12779 out1fmt("%.4o\n", mask);
12782 if (is_digit((unsigned char) *ap)) {
12785 if (*ap >= '8' || *ap < '0')
12786 sh_error(illnum, argv[1]);
12787 mask = (mask << 3) + (*ap - '0');
12788 } while (*++ap != '\0');
12791 mask = ~mask & 0777;
12792 if (!bb_parse_mode(ap, &mask)) {
12793 sh_error("Illegal mode: %s", ap);
12795 umask(~mask & 0777);
12804 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12805 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12806 * ash by J.T. Conklin.
12814 int factor; /* multiply by to get rlim_{cur,max} values */
12818 static const struct limits limits[] = {
12820 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12822 #ifdef RLIMIT_FSIZE
12823 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12826 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12828 #ifdef RLIMIT_STACK
12829 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12832 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12835 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12837 #ifdef RLIMIT_MEMLOCK
12838 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12840 #ifdef RLIMIT_NPROC
12841 { "process", RLIMIT_NPROC, 1, 'p' },
12843 #ifdef RLIMIT_NOFILE
12844 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12847 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12849 #ifdef RLIMIT_LOCKS
12850 { "locks", RLIMIT_LOCKS, 1, 'w' },
12852 { (char *) 0, 0, 0, '\0' }
12855 enum limtype { SOFT = 0x1, HARD = 0x2 };
12857 static void printlim(enum limtype how, const struct rlimit *limit,
12858 const struct limits *l)
12862 val = limit->rlim_max;
12864 val = limit->rlim_cur;
12866 if (val == RLIM_INFINITY)
12867 out1fmt("unlimited\n");
12870 out1fmt("%lld\n", (long long) val);
12875 ulimitcmd(int argc, char **argv)
12879 enum limtype how = SOFT | HARD;
12880 const struct limits *l;
12883 struct rlimit limit;
12886 while ((optc = nextopt("HSa"
12890 #ifdef RLIMIT_FSIZE
12896 #ifdef RLIMIT_STACK
12905 #ifdef RLIMIT_MEMLOCK
12908 #ifdef RLIMIT_NPROC
12911 #ifdef RLIMIT_NOFILE
12917 #ifdef RLIMIT_LOCKS
12935 for (l = limits; l->option != what; l++)
12938 set = *argptr ? 1 : 0;
12942 if (all || argptr[1])
12943 sh_error("too many arguments");
12944 if (strncmp(p, "unlimited\n", 9) == 0)
12945 val = RLIM_INFINITY;
12949 while ((c = *p++) >= '0' && c <= '9') {
12950 val = (val * 10) + (long)(c - '0');
12951 if (val < (rlim_t) 0)
12955 sh_error("bad number");
12960 for (l = limits; l->name; l++) {
12961 getrlimit(l->cmd, &limit);
12962 out1fmt("%-20s ", l->name);
12963 printlim(how, &limit, l);
12968 getrlimit(l->cmd, &limit);
12971 limit.rlim_max = val;
12973 limit.rlim_cur = val;
12974 if (setrlimit(l->cmd, &limit) < 0)
12975 sh_error("error setting limit (%m)");
12977 printlim(how, &limit, l);
12983 #if ENABLE_ASH_MATH_SUPPORT
12985 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12987 Permission is hereby granted, free of charge, to any person obtaining
12988 a copy of this software and associated documentation files (the
12989 "Software"), to deal in the Software without restriction, including
12990 without limitation the rights to use, copy, modify, merge, publish,
12991 distribute, sublicense, and/or sell copies of the Software, and to
12992 permit persons to whom the Software is furnished to do so, subject to
12993 the following conditions:
12995 The above copyright notice and this permission notice shall be
12996 included in all copies or substantial portions of the Software.
12998 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12999 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13000 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13001 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13002 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13003 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13004 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13007 /* This is my infix parser/evaluator. It is optimized for size, intended
13008 * as a replacement for yacc-based parsers. However, it may well be faster
13009 * than a comparable parser written in yacc. The supported operators are
13010 * listed in #defines below. Parens, order of operations, and error handling
13011 * are supported. This code is thread safe. The exact expression format should
13012 * be that which POSIX specifies for shells. */
13014 /* The code uses a simple two-stack algorithm. See
13015 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13016 * for a detailed explanation of the infix-to-postfix algorithm on which
13017 * this is based (this code differs in that it applies operators immediately
13018 * to the stack instead of adding them to a queue to end up with an
13021 /* To use the routine, call it with an expression string and error return
13025 * Aug 24, 2001 Manuel Novoa III
13027 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13029 * 1) In arith_apply():
13030 * a) Cached values of *numptr and &(numptr[-1]).
13031 * b) Removed redundant test for zero denominator.
13034 * a) Eliminated redundant code for processing operator tokens by moving
13035 * to a table-based implementation. Also folded handling of parens
13037 * b) Combined all 3 loops which called arith_apply to reduce generated
13038 * code size at the cost of speed.
13040 * 3) The following expressions were treated as valid by the original code:
13041 * 1() , 0! , 1 ( *3 ) .
13042 * These bugs have been fixed by internally enclosing the expression in
13043 * parens and then checking that all binary ops and right parens are
13044 * preceded by a valid expression (NUM_TOKEN).
13046 * Note: It may be desirable to replace Aaron's test for whitespace with
13047 * ctype's isspace() if it is used by another busybox applet or if additional
13048 * whitespace chars should be considered. Look below the "#include"s for a
13049 * precompiler test.
13053 * Aug 26, 2001 Manuel Novoa III
13055 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13057 * Merge in Aaron's comments previously posted to the busybox list,
13058 * modified slightly to take account of my changes to the code.
13063 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13065 * - allow access to variable,
13066 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13067 * - realize assign syntax (VAR=expr, +=, *= etc)
13068 * - realize exponentiation (** operator)
13069 * - realize comma separated - expr, expr
13070 * - realise ++expr --expr expr++ expr--
13071 * - realise expr ? expr : expr (but, second expr calculate always)
13072 * - allow hexadecimal and octal numbers
13073 * - was restored loses XOR operator
13074 * - remove one goto label, added three ;-)
13075 * - protect $((num num)) as true zero expr (Manuel`s error)
13076 * - always use special isspace(), see comment from bash ;-)
13080 #define arith_isspace(arithval) \
13081 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13084 typedef unsigned char operator;
13086 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13087 * precedence, and 3 high bits are an ID unique across operators of that
13088 * precedence. The ID portion is so that multiple operators can have the
13089 * same precedence, ensuring that the leftmost one is evaluated first.
13090 * Consider * and /. */
13092 #define tok_decl(prec,id) (((id)<<5)|(prec))
13093 #define PREC(op) ((op) & 0x1F)
13095 #define TOK_LPAREN tok_decl(0,0)
13097 #define TOK_COMMA tok_decl(1,0)
13099 #define TOK_ASSIGN tok_decl(2,0)
13100 #define TOK_AND_ASSIGN tok_decl(2,1)
13101 #define TOK_OR_ASSIGN tok_decl(2,2)
13102 #define TOK_XOR_ASSIGN tok_decl(2,3)
13103 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13104 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13105 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13106 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13108 #define TOK_MUL_ASSIGN tok_decl(3,0)
13109 #define TOK_DIV_ASSIGN tok_decl(3,1)
13110 #define TOK_REM_ASSIGN tok_decl(3,2)
13112 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13113 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13115 /* conditional is right associativity too */
13116 #define TOK_CONDITIONAL tok_decl(4,0)
13117 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13119 #define TOK_OR tok_decl(5,0)
13121 #define TOK_AND tok_decl(6,0)
13123 #define TOK_BOR tok_decl(7,0)
13125 #define TOK_BXOR tok_decl(8,0)
13127 #define TOK_BAND tok_decl(9,0)
13129 #define TOK_EQ tok_decl(10,0)
13130 #define TOK_NE tok_decl(10,1)
13132 #define TOK_LT tok_decl(11,0)
13133 #define TOK_GT tok_decl(11,1)
13134 #define TOK_GE tok_decl(11,2)
13135 #define TOK_LE tok_decl(11,3)
13137 #define TOK_LSHIFT tok_decl(12,0)
13138 #define TOK_RSHIFT tok_decl(12,1)
13140 #define TOK_ADD tok_decl(13,0)
13141 #define TOK_SUB tok_decl(13,1)
13143 #define TOK_MUL tok_decl(14,0)
13144 #define TOK_DIV tok_decl(14,1)
13145 #define TOK_REM tok_decl(14,2)
13147 /* exponent is right associativity */
13148 #define TOK_EXPONENT tok_decl(15,1)
13150 /* For now unary operators. */
13151 #define UNARYPREC 16
13152 #define TOK_BNOT tok_decl(UNARYPREC,0)
13153 #define TOK_NOT tok_decl(UNARYPREC,1)
13155 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13156 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13158 #define PREC_PRE (UNARYPREC+2)
13160 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13161 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13163 #define PREC_POST (UNARYPREC+3)
13165 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13166 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13168 #define SPEC_PREC (UNARYPREC+4)
13170 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13171 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13173 #define NUMPTR (*numstackptr)
13175 static int tok_have_assign(operator op)
13177 operator prec = PREC(op);
13179 convert_prec_is_assing(prec);
13180 return (prec == PREC(TOK_ASSIGN) ||
13181 prec == PREC_PRE || prec == PREC_POST);
13184 static int is_right_associativity(operator prec)
13186 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13187 || prec == PREC(TOK_CONDITIONAL));
13191 typedef struct ARITCH_VAR_NUM {
13193 arith_t contidional_second_val;
13194 char contidional_second_val_initialized;
13195 char *var; /* if NULL then is regular number,
13196 else is variable name */
13200 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13202 struct CHK_VAR_RECURSIVE_LOOPED *next;
13203 } chk_var_recursive_looped_t;
13205 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13208 static int arith_lookup_val(v_n_t *t)
13211 const char * p = lookupvar(t->var);
13216 /* recursive try as expression */
13217 chk_var_recursive_looped_t *cur;
13218 chk_var_recursive_looped_t cur_save;
13220 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13221 if (strcmp(cur->var, t->var) == 0) {
13222 /* expression recursion loop detected */
13226 /* save current lookuped var name */
13227 cur = prev_chk_var_recursive;
13228 cur_save.var = t->var;
13229 cur_save.next = cur;
13230 prev_chk_var_recursive = &cur_save;
13232 t->val = arith (p, &errcode);
13233 /* restore previous ptr after recursiving */
13234 prev_chk_var_recursive = cur;
13237 /* allow undefined var as 0 */
13243 /* "applying" a token means performing it on the top elements on the integer
13244 * stack. For a unary operator it will only change the top element, but a
13245 * binary operator will pop two arguments and push a result */
13246 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13249 arith_t numptr_val, rez;
13250 int ret_arith_lookup_val;
13252 /* There is no operator that can work without arguments */
13253 if (NUMPTR == numstack) goto err;
13254 numptr_m1 = NUMPTR - 1;
13256 /* check operand is var with noninteger value */
13257 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13258 if (ret_arith_lookup_val)
13259 return ret_arith_lookup_val;
13261 rez = numptr_m1->val;
13262 if (op == TOK_UMINUS)
13264 else if (op == TOK_NOT)
13266 else if (op == TOK_BNOT)
13268 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13270 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13272 else if (op != TOK_UPLUS) {
13273 /* Binary operators */
13275 /* check and binary operators need two arguments */
13276 if (numptr_m1 == numstack) goto err;
13278 /* ... and they pop one */
13281 if (op == TOK_CONDITIONAL) {
13282 if (! numptr_m1->contidional_second_val_initialized) {
13283 /* protect $((expr1 ? expr2)) without ": expr" */
13286 rez = numptr_m1->contidional_second_val;
13287 } else if (numptr_m1->contidional_second_val_initialized) {
13288 /* protect $((expr1 : expr2)) without "expr ? " */
13291 numptr_m1 = NUMPTR - 1;
13292 if (op != TOK_ASSIGN) {
13293 /* check operand is var with noninteger value for not '=' */
13294 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13295 if (ret_arith_lookup_val)
13296 return ret_arith_lookup_val;
13298 if (op == TOK_CONDITIONAL) {
13299 numptr_m1->contidional_second_val = rez;
13301 rez = numptr_m1->val;
13302 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13304 else if (op == TOK_OR)
13305 rez = numptr_val || rez;
13306 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13308 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13310 else if (op == TOK_AND)
13311 rez = rez && numptr_val;
13312 else if (op == TOK_EQ)
13313 rez = (rez == numptr_val);
13314 else if (op == TOK_NE)
13315 rez = (rez != numptr_val);
13316 else if (op == TOK_GE)
13317 rez = (rez >= numptr_val);
13318 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13319 rez >>= numptr_val;
13320 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13321 rez <<= numptr_val;
13322 else if (op == TOK_GT)
13323 rez = (rez > numptr_val);
13324 else if (op == TOK_LT)
13325 rez = (rez < numptr_val);
13326 else if (op == TOK_LE)
13327 rez = (rez <= numptr_val);
13328 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13330 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13332 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13334 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13336 else if (op == TOK_CONDITIONAL_SEP) {
13337 if (numptr_m1 == numstack) {
13338 /* protect $((expr : expr)) without "expr ? " */
13341 numptr_m1->contidional_second_val_initialized = op;
13342 numptr_m1->contidional_second_val = numptr_val;
13344 else if (op == TOK_CONDITIONAL) {
13346 numptr_val : numptr_m1->contidional_second_val;
13348 else if (op == TOK_EXPONENT) {
13349 if (numptr_val < 0)
13350 return -3; /* exponent less than 0 */
13355 while (numptr_val--)
13360 else if (numptr_val==0) /* zero divisor check */
13362 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13364 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13367 if (tok_have_assign(op)) {
13370 if (numptr_m1->var == NULL) {
13374 /* save to shell variable */
13375 #if ENABLE_ASH_MATH_SUPPORT_64
13376 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13378 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13380 setvar(numptr_m1->var, buf, 0);
13381 /* after saving, make previous value for v++ or v-- */
13382 if (op == TOK_POST_INC)
13384 else if (op == TOK_POST_DEC)
13387 numptr_m1->val = rez;
13388 /* protect geting var value, is number now */
13389 numptr_m1->var = NULL;
13395 /* longest must first */
13396 static const char op_tokens[] = {
13397 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13398 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13399 '<','<', 0, TOK_LSHIFT,
13400 '>','>', 0, TOK_RSHIFT,
13401 '|','|', 0, TOK_OR,
13402 '&','&', 0, TOK_AND,
13403 '!','=', 0, TOK_NE,
13404 '<','=', 0, TOK_LE,
13405 '>','=', 0, TOK_GE,
13406 '=','=', 0, TOK_EQ,
13407 '|','=', 0, TOK_OR_ASSIGN,
13408 '&','=', 0, TOK_AND_ASSIGN,
13409 '*','=', 0, TOK_MUL_ASSIGN,
13410 '/','=', 0, TOK_DIV_ASSIGN,
13411 '%','=', 0, TOK_REM_ASSIGN,
13412 '+','=', 0, TOK_PLUS_ASSIGN,
13413 '-','=', 0, TOK_MINUS_ASSIGN,
13414 '-','-', 0, TOK_POST_DEC,
13415 '^','=', 0, TOK_XOR_ASSIGN,
13416 '+','+', 0, TOK_POST_INC,
13417 '*','*', 0, TOK_EXPONENT,
13421 '=', 0, TOK_ASSIGN,
13433 '?', 0, TOK_CONDITIONAL,
13434 ':', 0, TOK_CONDITIONAL_SEP,
13435 ')', 0, TOK_RPAREN,
13436 '(', 0, TOK_LPAREN,
13440 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13443 static arith_t arith(const char *expr, int *perrcode)
13445 char arithval; /* Current character under analysis */
13446 operator lasttok, op;
13449 const char *p = endexpression;
13452 size_t datasizes = strlen(expr) + 2;
13454 /* Stack of integers */
13455 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13456 * in any given correct or incorrect expression is left as an exercise to
13458 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13459 *numstackptr = numstack;
13460 /* Stack of operator tokens */
13461 operator *stack = alloca((datasizes) * sizeof(operator)),
13464 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13465 *perrcode = errcode = 0;
13468 if ((arithval = *expr) == 0) {
13469 if (p == endexpression) {
13470 /* Null expression. */
13474 /* This is only reached after all tokens have been extracted from the
13475 * input stream. If there are still tokens on the operator stack, they
13476 * are to be applied in order. At the end, there should be a final
13477 * result on the integer stack */
13479 if (expr != endexpression + 1) {
13480 /* If we haven't done so already, */
13481 /* append a closing right paren */
13482 expr = endexpression;
13483 /* and let the loop process it. */
13486 /* At this point, we're done with the expression. */
13487 if (numstackptr != numstack+1) {
13488 /* ... but if there isn't, it's bad */
13490 return (*perrcode = -1);
13492 if (numstack->var) {
13493 /* expression is $((var)) only, lookup now */
13494 errcode = arith_lookup_val(numstack);
13497 *perrcode = errcode;
13498 return numstack->val;
13501 /* Continue processing the expression. */
13502 if (arith_isspace(arithval)) {
13503 /* Skip whitespace */
13506 if ((p = endofname(expr)) != expr) {
13507 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13509 numstackptr->var = alloca(var_name_size);
13510 safe_strncpy(numstackptr->var, expr, var_name_size);
13513 numstackptr->contidional_second_val_initialized = 0;
13517 } else if (is_digit(arithval)) {
13518 numstackptr->var = NULL;
13519 #if ENABLE_ASH_MATH_SUPPORT_64
13520 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13522 numstackptr->val = strtol(expr, (char **) &expr, 0);
13526 for (p = op_tokens; ; p++) {
13530 /* strange operator not found */
13533 for (o = expr; *p && *o == *p; p++)
13540 /* skip tail uncompared token */
13543 /* skip zero delim */
13548 /* post grammar: a++ reduce to num */
13549 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13552 /* Plus and minus are binary (not unary) _only_ if the last
13553 * token was as number, or a right paren (which pretends to be
13554 * a number, since it evaluates to one). Think about it.
13555 * It makes sense. */
13556 if (lasttok != TOK_NUM) {
13572 /* We don't want a unary operator to cause recursive descent on the
13573 * stack, because there can be many in a row and it could cause an
13574 * operator to be evaluated before its argument is pushed onto the
13575 * integer stack. */
13576 /* But for binary operators, "apply" everything on the operator
13577 * stack until we find an operator with a lesser priority than the
13578 * one we have just extracted. */
13579 /* Left paren is given the lowest priority so it will never be
13580 * "applied" in this way.
13581 * if associativity is right and priority eq, applied also skip
13584 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13585 /* not left paren or unary */
13586 if (lasttok != TOK_NUM) {
13587 /* binary op must be preceded by a num */
13590 while (stackptr != stack) {
13591 if (op == TOK_RPAREN) {
13592 /* The algorithm employed here is simple: while we don't
13593 * hit an open paren nor the bottom of the stack, pop
13594 * tokens and apply them */
13595 if (stackptr[-1] == TOK_LPAREN) {
13597 /* Any operator directly after a */
13599 /* close paren should consider itself binary */
13603 operator prev_prec = PREC(stackptr[-1]);
13605 convert_prec_is_assing(prec);
13606 convert_prec_is_assing(prev_prec);
13607 if (prev_prec < prec)
13609 /* check right assoc */
13610 if (prev_prec == prec && is_right_associativity(prec))
13613 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13614 if (errcode) goto ret;
13616 if (op == TOK_RPAREN) {
13621 /* Push this operator to the stack and remember it. */
13622 *stackptr++ = lasttok = op;
13627 #endif /* ASH_MATH_SUPPORT */
13631 const char *applet_name = "debug stuff usage";
13632 int main(int argc, char **argv)
13634 return ash_main(argc, argv);
13639 * Copyright (c) 1989, 1991, 1993, 1994
13640 * The Regents of the University of California. All rights reserved.
13642 * This code is derived from software contributed to Berkeley by
13643 * Kenneth Almquist.
13645 * Redistribution and use in source and binary forms, with or without
13646 * modification, are permitted provided that the following conditions
13648 * 1. Redistributions of source code must retain the above copyright
13649 * notice, this list of conditions and the following disclaimer.
13650 * 2. Redistributions in binary form must reproduce the above copyright
13651 * notice, this list of conditions and the following disclaimer in the
13652 * documentation and/or other materials provided with the distribution.
13653 * 3. Neither the name of the University nor the names of its contributors
13654 * may be used to endorse or promote products derived from this software
13655 * without specific prior written permission.
13657 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13658 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13659 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13660 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13661 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13662 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13663 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13664 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13665 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13666 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF