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 * This code is derived from software contributed to Berkeley by
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5
28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
32 * Original copyright notice is retained at the end of this file.
36 /* These defines allow you to adjust the feature set to be compiled
37 * into the ash shell. As a rule, enabling these options will make
38 * ash get bigger... With all of these options off, ash adds about
39 * 60k to busybox on an x86 system.*/
42 /* Enable job control. This allows you to run jobs in the background,
43 * which is great when ash is being used as an interactive shell, but
44 * it completely useless for is all you are doing is running scripts.
45 * This adds about 2.5k on an x86 system. */
48 /* This enables alias support in ash. If you want to support things
49 * like "alias ls='ls -l'" with ash, enable this. This is only useful
50 * when ash is used as an intractive shell. This adds about 1.5k */
53 /* If you need ash to act as a full Posix shell, with full math
54 * support, enable this. This adds a bit over 2k an x86 system. */
55 //#undef ASH_MATH_SUPPORT
56 #define ASH_MATH_SUPPORT
58 /* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt
60 * applet if you want to do this sort of thing. There are some scripts
61 * out there that use it, so it you need it, enable. Most people will
62 * leave this disabled. This adds 1k on an x86 system. */
65 /* This allows you to override shell builtins and use whatever is on
66 * the filesystem. This is most useful when ash is acting as a
67 * standalone shell. Adds about 272 bytes. */
71 /* Optimize size vs speed as size */
72 #define ASH_OPTIMIZE_FOR_SIZE
74 /* Enable this to compile in extra debugging noise. When debugging is
75 * on, debugging info will be written to $HOME/trace and a quit signal
76 * will generate a core dump. */
79 /* These are here to work with glibc -- Don't change these... */
100 #include <sys/cdefs.h>
101 #include <sys/ioctl.h>
102 #include <sys/param.h>
103 #include <sys/resource.h>
104 #include <sys/time.h>
105 #include <sys/times.h>
106 #include <sys/types.h>
107 #include <sys/wait.h>
110 #if !defined(FNMATCH_BROKEN)
113 #if !defined(GLOB_BROKEN)
125 * This file was generated by the mksyntax program.
129 #define CWORD 0 /* character is nothing special */
130 #define CNL 1 /* newline character */
131 #define CBACK 2 /* a backslash character */
132 #define CSQUOTE 3 /* single quote */
133 #define CDQUOTE 4 /* double quote */
134 #define CENDQUOTE 5 /* a terminating quote */
135 #define CBQUOTE 6 /* backwards single quote */
136 #define CVAR 7 /* a dollar sign */
137 #define CENDVAR 8 /* a '}' character */
138 #define CLP 9 /* a left paren in arithmetic */
139 #define CRP 10 /* a right paren in arithmetic */
140 #define CENDFILE 11 /* end of file */
141 #define CCTL 12 /* like CWORD, except it must be escaped */
142 #define CSPCL 13 /* these terminate a word */
143 #define CIGN 14 /* character should be ignored */
145 /* Syntax classes for is_ functions */
146 #define ISDIGIT 01 /* a digit */
147 #define ISUPPER 02 /* an upper case letter */
148 #define ISLOWER 04 /* a lower case letter */
149 #define ISUNDER 010 /* an underscore */
150 #define ISSPECL 020 /* the name of a special parameter */
167 #define TENDBQUOTE 10
189 #define BASESYNTAX (basesyntax + SYNBASE)
190 #define DQSYNTAX (dqsyntax + SYNBASE)
191 #define SQSYNTAX (sqsyntax + SYNBASE)
192 #define ARISYNTAX (arisyntax + SYNBASE)
194 /* control characters in argument strings */
195 #define CTLESC '\201'
196 #define CTLVAR '\202'
197 #define CTLENDVAR '\203'
198 #define CTLBACKQ '\204'
199 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
200 /* CTLBACKQ | CTLQUOTE == '\205' */
201 #define CTLARI '\206'
202 #define CTLENDARI '\207'
203 #define CTLQUOTEMARK '\210'
205 #define is_digit(c) ((c)>='0' && (c)<='9')
206 #define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
207 #define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
208 #define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
209 #define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
210 #define digit_val(c) ((c) - '0')
213 #define _DIAGASSERT(x)
217 #define S_DFL 1 /* default signal handling (SIG_DFL) */
218 #define S_CATCH 2 /* signal is caught */
219 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
220 #define S_HARD_IGN 4 /* signal is ignored permenantly */
221 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
224 /* variable substitution byte (follows CTLVAR) */
225 #define VSTYPE 0x0f /* type of variable substitution */
226 #define VSNUL 0x10 /* colon--treat the empty string as unset */
227 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
229 /* values of VSTYPE field */
230 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
231 #define VSMINUS 0x2 /* ${var-text} */
232 #define VSPLUS 0x3 /* ${var+text} */
233 #define VSQUESTION 0x4 /* ${var?message} */
234 #define VSASSIGN 0x5 /* ${var=text} */
235 #define VSTRIMLEFT 0x6 /* ${var#pattern} */
236 #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
237 #define VSTRIMRIGHT 0x8 /* ${var%pattern} */
238 #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
239 #define VSLENGTH 0xa /* ${#var} */
241 /* flags passed to redirect */
242 #define REDIR_PUSH 01 /* save previous values of file descriptors */
243 #define REDIR_BACKQ 02 /* save the command output to pipe */
246 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
247 * so we use _setjmp instead.
251 #define setjmp(jmploc) _setjmp(jmploc)
252 #define longjmp(jmploc, val) _longjmp(jmploc, val)
256 * Most machines require the value returned from malloc to be aligned
257 * in some way. The following macro will get this right on many machines.
266 #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
269 #ifdef BB_LOCALE_SUPPORT
271 static void change_lc_all(const char *value);
272 static void change_lc_ctype(const char *value);
276 * These macros allow the user to suspend the handling of interrupt signals
277 * over a period of time. This is similar to SIGHOLD to or sigblock, but
278 * much more efficient and portable. (But hacking the kernel is so much
279 * more fun than worrying about efficiency and portability. :-))
282 static void onint (void);
283 static volatile int suppressint;
284 static volatile int intpending;
286 #define INTOFF suppressint++
287 #ifndef ASH_OPTIMIZE_FOR_SIZE
288 #define INTON { if (--suppressint == 0 && intpending) onint(); }
289 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
291 static void __inton (void);
292 static void forceinton (void);
293 #define INTON __inton()
294 #define FORCEINTON forceinton()
297 #define CLEAR_PENDING_INT intpending = 0
298 #define int_pending() intpending
301 typedef void *pointer;
303 #define NULL (void *)0
306 static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
307 static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
308 static inline char * savestr (const char *s) { return xstrdup(s); }
310 static pointer stalloc (int);
311 static void stunalloc (pointer);
312 static void ungrabstackstr (char *, char *);
313 static char * growstackstr(void);
314 static char * makestrspace(size_t newlen);
315 static char *sstrdup (const char *);
318 * Parse trees for commands are allocated in lifo order, so we use a stack
319 * to make this more efficient, and also to avoid all sorts of exception
320 * handling code to handle interrupts in the middle of a parse.
322 * The size 504 was chosen because the Ultrix malloc handles that size
326 #define MINSIZE 504 /* minimum size of a block */
330 struct stack_block *prev;
334 static struct stack_block stackbase;
335 static struct stack_block *stackp = &stackbase;
336 static struct stackmark *markp;
337 static char *stacknxt = stackbase.space;
338 static int stacknleft = MINSIZE;
341 #define equal(s1, s2) (strcmp(s1, s2) == 0)
343 #define stackblock() stacknxt
344 #define stackblocksize() stacknleft
345 #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
347 #define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
348 #define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
349 #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
352 #define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
353 #define STUNPUTC(p) (++sstrnleft, --p)
354 #define STTOPC(p) p[-1]
355 #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
356 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
358 #define ckfree(p) free((pointer)(p))
362 #define TRACE(param) trace param
363 static void trace (const char *, ...);
364 static void trargs (char **);
365 static void showtree (union node *);
366 static void trputc (int);
367 static void trputs (const char *);
368 static void opentrace (void);
403 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
404 #define EXP_TILDE 0x2 /* do normal tilde expansion */
405 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
406 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
407 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
408 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
413 static char optet_vals[NOPTS];
415 static const char * const optlist[NOPTS] = {
434 #define optent_name(optent) (optent+1)
435 #define optent_letter(optent) optent[0]
436 #define optent_val(optent) optet_vals[optent]
438 #define eflag optent_val(0)
439 #define fflag optent_val(1)
440 #define Iflag optent_val(2)
441 #define iflag optent_val(3)
442 #define mflag optent_val(4)
443 #define nflag optent_val(5)
444 #define sflag optent_val(6)
445 #define xflag optent_val(7)
446 #define vflag optent_val(8)
447 #define Vflag optent_val(9)
448 #define Eflag optent_val(10)
449 #define Cflag optent_val(11)
450 #define aflag optent_val(12)
451 #define bflag optent_val(13)
452 #define uflag optent_val(14)
453 #define qflag optent_val(15)
456 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
474 union node *redirect;
481 struct nodelist *cmdlist;
488 union node *redirect;
496 union node *elsepart;
527 struct nodelist *backquote;
565 struct nbinary nbinary;
568 struct nredir nredir;
572 struct nclist nclist;
582 struct nodelist *next;
586 struct backcmd { /* result of evalbackcmd */
587 int fd; /* file descriptor to read from */
588 char *buf; /* buffer */
589 int nleft; /* number of chars in buffer */
590 struct job *jp; /* job structure for command */
598 const struct builtincmd *cmd;
603 struct strlist *next;
609 struct strlist *list;
610 struct strlist **lastp;
614 struct strpush *prev; /* preceding string on stack */
618 struct alias *ap; /* if push was associated with an alias */
620 char *string; /* remember the string since it may change */
624 struct parsefile *prev; /* preceding file on stack */
625 int linno; /* current line */
626 int fd; /* file descriptor (or -1 if string) */
627 int nleft; /* number of chars left in this line */
628 int lleft; /* number of chars left in this buffer */
629 char *nextc; /* next char in buffer */
630 char *buf; /* input buffer */
631 struct strpush *strpush; /* for pushing strings at this level */
632 struct strpush basestrpush; /* so pushing one is fast */
636 struct stack_block *stackp;
639 struct stackmark *marknext;
643 int nparam; /* # of positional parameters (without $0) */
644 unsigned char malloc; /* if parameter list dynamically allocated */
645 char **p; /* parameter list */
646 int optind; /* next parameter to be processed by getopts */
647 int optoff; /* used by getopts */
651 * When commands are first encountered, they are entered in a hash table.
652 * This ensures that a full path search will not have to be done for them
653 * on each invocation.
655 * We should investigate converting to a linear search, even though that
656 * would make the command name "hash" a misnomer.
658 #define CMDTABLESIZE 31 /* should be prime */
659 #define ARB 1 /* actual size determined at run time */
664 struct tblentry *next; /* next entry in hash chain */
665 union param param; /* definition of builtin function */
666 short cmdtype; /* index identifying command */
667 char rehash; /* if set, cd done since entry created */
668 char cmdname[ARB]; /* name of command */
672 static struct tblentry *cmdtable[CMDTABLESIZE];
673 static int builtinloc = -1; /* index in path of %builtin, or -1 */
674 static int exerrno = 0; /* Last exec error */
677 static void tryexec (char *, char **, char **);
678 static void printentry (struct tblentry *, int);
679 static void clearcmdentry (int);
680 static struct tblentry *cmdlookup (const char *, int);
681 static void delete_cmd_entry (void);
682 static int path_change (const char *, int *);
685 static void flushall (void);
686 static void out2fmt (const char *, ...)
687 __attribute__((__format__(__printf__,1,2)));
688 static int xwrite (int, const char *, int);
690 static void outstr (const char *p, FILE *file) { fputs(p, file); }
691 static void out1str(const char *p) { outstr(p, stdout); }
692 static void out2str(const char *p) { outstr(p, stderr); }
694 #ifndef ASH_OPTIMIZE_FOR_SIZE
695 #define out2c(c) putc((c), stderr)
697 static void out2c(int c) { putc(c, stderr); }
700 /* syntax table used when not in quotes */
701 static const char basesyntax[257] = {
702 CENDFILE, CSPCL, CWORD, CCTL,
703 CCTL, CCTL, CCTL, CCTL,
704 CCTL, CCTL, CCTL, CWORD,
705 CWORD, CWORD, CWORD, CWORD,
706 CWORD, CWORD, CWORD, CWORD,
707 CWORD, CWORD, CWORD, CWORD,
708 CWORD, CWORD, CWORD, CWORD,
709 CWORD, CWORD, CWORD, CWORD,
710 CWORD, CWORD, CWORD, CWORD,
711 CWORD, CWORD, CWORD, CWORD,
712 CWORD, CWORD, CWORD, CWORD,
713 CWORD, CWORD, CWORD, CWORD,
714 CWORD, CWORD, CWORD, CWORD,
715 CWORD, CWORD, CWORD, CWORD,
716 CWORD, CWORD, CWORD, CWORD,
717 CWORD, CWORD, CWORD, CWORD,
718 CWORD, CWORD, CWORD, CWORD,
719 CWORD, CWORD, CWORD, CWORD,
720 CWORD, CWORD, CWORD, CWORD,
721 CWORD, CWORD, CWORD, CWORD,
722 CWORD, CWORD, CWORD, CWORD,
723 CWORD, CWORD, CWORD, CWORD,
724 CWORD, CWORD, CWORD, CWORD,
725 CWORD, CWORD, CWORD, CWORD,
726 CWORD, CWORD, CWORD, CWORD,
727 CWORD, CWORD, CWORD, CWORD,
728 CWORD, CWORD, CWORD, CWORD,
729 CWORD, CWORD, CWORD, CWORD,
730 CWORD, CWORD, CWORD, CWORD,
731 CWORD, CWORD, CWORD, CWORD,
732 CWORD, CWORD, CWORD, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CSPCL,
737 CNL, CWORD, CWORD, CWORD,
738 CWORD, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CSPCL, CWORD,
743 CDQUOTE, CWORD, CVAR, CWORD,
744 CSPCL, CSQUOTE, CSPCL, CSPCL,
745 CWORD, CWORD, CWORD, CWORD,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CSPCL, CSPCL, CWORD,
750 CSPCL, CWORD, CWORD, CWORD,
751 CWORD, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CBACK, CWORD,
758 CWORD, CWORD, CBQUOTE, CWORD,
759 CWORD, CWORD, CWORD, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CWORD,
765 CWORD, CWORD, CSPCL, CENDVAR,
769 /* syntax table used when in double quotes */
770 static const char dqsyntax[257] = {
771 CENDFILE, CIGN, CWORD, CCTL,
772 CCTL, CCTL, CCTL, CCTL,
773 CCTL, CCTL, CCTL, CWORD,
774 CWORD, CWORD, CWORD, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CWORD, CWORD, CWORD,
778 CWORD, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CWORD, CWORD,
786 CWORD, CWORD, CWORD, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CWORD, CWORD,
794 CWORD, CWORD, CWORD, CWORD,
795 CWORD, CWORD, CWORD, CWORD,
796 CWORD, CWORD, CWORD, CWORD,
797 CWORD, CWORD, CWORD, CWORD,
798 CWORD, CWORD, CWORD, CWORD,
799 CWORD, CWORD, CWORD, CWORD,
800 CWORD, CWORD, CWORD, CWORD,
801 CWORD, CWORD, CWORD, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CNL, CWORD, CWORD, CWORD,
807 CWORD, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CCTL,
812 CENDQUOTE,CWORD, CVAR, CWORD,
813 CWORD, CWORD, CWORD, CWORD,
814 CCTL, CWORD, CWORD, CCTL,
815 CWORD, CCTL, CWORD, CWORD,
816 CWORD, CWORD, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CCTL, CWORD, CWORD, CCTL,
819 CWORD, CCTL, CWORD, CWORD,
820 CWORD, CWORD, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CCTL, CBACK, CCTL,
827 CWORD, CWORD, CBQUOTE, CWORD,
828 CWORD, CWORD, CWORD, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CWORD, CWORD, CWORD, CENDVAR,
838 /* syntax table used when in single quotes */
839 static const char sqsyntax[257] = {
840 CENDFILE, CIGN, CWORD, CCTL,
841 CCTL, CCTL, CCTL, CCTL,
842 CCTL, CCTL, CCTL, CWORD,
843 CWORD, CWORD, CWORD, CWORD,
844 CWORD, CWORD, CWORD, CWORD,
845 CWORD, CWORD, CWORD, CWORD,
846 CWORD, CWORD, CWORD, CWORD,
847 CWORD, CWORD, CWORD, CWORD,
848 CWORD, CWORD, CWORD, CWORD,
849 CWORD, CWORD, CWORD, CWORD,
850 CWORD, CWORD, CWORD, CWORD,
851 CWORD, CWORD, CWORD, CWORD,
852 CWORD, CWORD, CWORD, CWORD,
853 CWORD, CWORD, CWORD, CWORD,
854 CWORD, CWORD, CWORD, CWORD,
855 CWORD, CWORD, CWORD, CWORD,
856 CWORD, CWORD, CWORD, CWORD,
857 CWORD, CWORD, CWORD, CWORD,
858 CWORD, CWORD, CWORD, CWORD,
859 CWORD, CWORD, CWORD, CWORD,
860 CWORD, CWORD, CWORD, CWORD,
861 CWORD, CWORD, CWORD, CWORD,
862 CWORD, CWORD, CWORD, CWORD,
863 CWORD, CWORD, CWORD, CWORD,
864 CWORD, CWORD, CWORD, CWORD,
865 CWORD, CWORD, CWORD, CWORD,
866 CWORD, CWORD, CWORD, CWORD,
867 CWORD, CWORD, CWORD, CWORD,
868 CWORD, CWORD, CWORD, CWORD,
869 CWORD, CWORD, CWORD, CWORD,
870 CWORD, CWORD, CWORD, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CNL, CWORD, CWORD, CWORD,
876 CWORD, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CCTL,
881 CWORD, CWORD, CWORD, CWORD,
882 CWORD, CENDQUOTE,CWORD, CWORD,
883 CCTL, CWORD, CWORD, CCTL,
884 CWORD, CCTL, CWORD, CWORD,
885 CWORD, CWORD, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CCTL, CWORD, CWORD, CCTL,
888 CWORD, CCTL, CWORD, CWORD,
889 CWORD, CWORD, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CCTL, CCTL, CCTL,
896 CWORD, CWORD, CWORD, CWORD,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CWORD, CWORD, CWORD, CWORD,
907 /* syntax table used when in arithmetic */
908 static const char arisyntax[257] = {
909 CENDFILE, CIGN, CWORD, CCTL,
910 CCTL, CCTL, CCTL, CCTL,
911 CCTL, CCTL, CCTL, CWORD,
912 CWORD, CWORD, CWORD, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CWORD, CWORD, CWORD, CWORD,
916 CWORD, CWORD, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CWORD, CWORD, CWORD,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CWORD, CWORD, CWORD, CWORD,
933 CWORD, CWORD, CWORD, CWORD,
934 CWORD, CWORD, CWORD, CWORD,
935 CWORD, CWORD, CWORD, CWORD,
936 CWORD, CWORD, CWORD, CWORD,
937 CWORD, CWORD, CWORD, CWORD,
938 CWORD, CWORD, CWORD, CWORD,
939 CWORD, CWORD, CWORD, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CNL, CWORD, CWORD, CWORD,
945 CWORD, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CDQUOTE, CWORD, CVAR, CWORD,
951 CWORD, CSQUOTE, CLP, CRP,
952 CWORD, CWORD, CWORD, CWORD,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CBACK, CWORD,
965 CWORD, CWORD, CBQUOTE, CWORD,
966 CWORD, CWORD, CWORD, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CWORD, CWORD, CWORD, CENDVAR,
976 /* character classification table */
977 static const char is_type[257] = {
1019 0, ISSPECL, ISSPECL, 0,
1021 ISSPECL, 0, 0, ISSPECL,
1022 0, 0, ISDIGIT, ISDIGIT,
1023 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1024 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1026 0, ISSPECL, ISSPECL, ISUPPER,
1027 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1028 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1029 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1030 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1031 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1032 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1034 0, ISUNDER, 0, ISLOWER,
1035 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1036 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1037 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1038 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1039 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1040 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1045 /* Array indicating which tokens mark the end of a list */
1046 static const char tokendlist[] = {
1079 static const char *const tokname[] = {
1112 #define KWDOFFSET 14
1114 static const char *const parsekwd[] = {
1134 static int plinno = 1; /* input line number */
1136 static int parselleft; /* copy of parsefile->lleft */
1138 static struct parsefile basepf; /* top level input file */
1139 static char basebuf[BUFSIZ]; /* buffer for top level input file */
1140 static struct parsefile *parsefile = &basepf; /* current input file */
1143 * NEOF is returned by parsecmd when it encounters an end of file. It
1144 * must be distinct from NULL, so we use the address of a variable that
1145 * happens to be handy.
1148 static int tokpushback; /* last token pushed back */
1149 #define NEOF ((union node *)&tokpushback)
1150 static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1153 static void error (const char *, ...) __attribute__((__noreturn__));
1154 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1155 static void shellexec (char **, char **, const char *, int)
1156 __attribute__((noreturn));
1157 static void exitshell (int) __attribute__((noreturn));
1159 static int goodname(const char *);
1160 static void ignoresig (int);
1161 static void onsig (int);
1162 static void dotrap (void);
1163 static int decode_signal (const char *, int);
1165 static void shprocvar(void);
1166 static void deletefuncs(void);
1167 static void setparam (char **);
1168 static void freeparam (volatile struct shparam *);
1170 /* reasons for skipping commands (see comment on breakcmd routine) */
1176 /* values of cmdtype */
1177 #define CMDUNKNOWN -1 /* no entry in table for command */
1178 #define CMDNORMAL 0 /* command is an executable program */
1179 #define CMDBUILTIN 1 /* command is a shell builtin */
1180 #define CMDFUNCTION 2 /* command is a shell function */
1182 #define DO_ERR 1 /* find_command prints errors */
1183 #define DO_ABS 2 /* find_command checks absolute paths */
1184 #define DO_NOFUN 4 /* find_command ignores functions */
1185 #define DO_BRUTE 8 /* find_command ignores hash table */
1192 #define VEXPORT 0x01 /* variable is exported */
1193 #define VREADONLY 0x02 /* variable cannot be modified */
1194 #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1195 #define VTEXTFIXED 0x08 /* text is staticly allocated */
1196 #define VSTACK 0x10 /* text is allocated on the stack */
1197 #define VUNSET 0x20 /* the variable is not set */
1198 #define VNOFUNC 0x40 /* don't call the callback function */
1202 struct var *next; /* next entry in hash list */
1203 int flags; /* flags are defined above */
1204 char *text; /* name=value */
1205 void (*func) (const char *);
1206 /* function to be called when */
1207 /* the variable gets set/unset */
1211 struct localvar *next; /* next local variable in list */
1212 struct var *vp; /* the variable that was made local */
1213 int flags; /* saved flags */
1214 char *text; /* saved text */
1218 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1219 #define rmescapes(p) _rmescapes((p), 0)
1220 static char *_rmescapes (char *, int);
1222 static void rmescapes (char *);
1225 static int casematch (union node *, const char *);
1226 static void clearredir(void);
1227 static void popstring(void);
1228 static void readcmdfile (const char *);
1230 static int number (const char *);
1231 static int is_number (const char *, int *num);
1232 static char *single_quote (const char *);
1233 static int nextopt (const char *);
1235 static void redirect (union node *, int);
1236 static void popredir (void);
1237 static int dup_as_newfd (int, int);
1239 static void changepath(const char *newval);
1240 static void getoptsreset(const char *value);
1243 static int parsenleft; /* copy of parsefile->nleft */
1244 static char *parsenextc; /* copy of parsefile->nextc */
1245 static int rootpid; /* pid of main shell */
1246 static int rootshell; /* true if we aren't a child of the main shell */
1248 static const char spcstr[] = " ";
1249 static const char snlfmt[] = "%s\n";
1251 static int sstrnleft;
1252 static int herefd = -1;
1254 static struct localvar *localvars;
1256 static struct var vifs;
1257 static struct var vmail;
1258 static struct var vmpath;
1259 static struct var vpath;
1260 static struct var vps1;
1261 static struct var vps2;
1262 static struct var voptind;
1263 #ifdef BB_LOCALE_SUPPORT
1264 static struct var vlc_all;
1265 static struct var vlc_ctype;
1272 void (*func) (const char *);
1275 static const char defpathvar[] =
1276 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1277 #define defpath (defpathvar + 5)
1280 static const char defifsvar[] = "IFS= \t\n";
1281 #define defifs (defifsvar + 4)
1283 static const char defifs[] = " \t\n";
1286 static const struct varinit varinit[] = {
1288 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1290 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1293 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1295 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1297 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1300 * vps1 depends on uid
1302 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1304 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1306 #ifdef BB_LOCALE_SUPPORT
1307 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1309 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1318 static struct var *vartab[VTABSIZE];
1321 * The following macros access the values of the above variables.
1322 * They have to skip over the name. They return the null string
1323 * for unset variables.
1326 #define ifsval() (vifs.text + 4)
1327 #define ifsset() ((vifs.flags & VUNSET) == 0)
1328 #define mailval() (vmail.text + 5)
1329 #define mpathval() (vmpath.text + 9)
1330 #define pathval() (vpath.text + 5)
1331 #define ps1val() (vps1.text + 4)
1332 #define ps2val() (vps2.text + 4)
1333 #define optindval() (voptind.text + 7)
1335 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1337 static void initvar (void);
1338 static void setvar (const char *, const char *, int);
1339 static void setvareq (char *, int);
1340 static void listsetvar (struct strlist *);
1341 static const char *lookupvar (const char *);
1342 static const char *bltinlookup (const char *);
1343 static char **environment (void);
1344 static int showvarscmd (int, char **);
1345 static void mklocal (char *);
1346 static void poplocalvars (void);
1347 static int unsetvar (const char *);
1348 static int varequal (const char *, const char *);
1351 static char *arg0; /* value of $0 */
1352 static struct shparam shellparam; /* current positional parameters */
1353 static char **argptr; /* argument list for builtin commands */
1354 static char *optionarg; /* set by nextopt (like getopt) */
1355 static char *optptr; /* used by nextopt */
1356 static char *minusc; /* argument to -c option */
1361 #define ALIASINUSE 1
1373 static struct alias *atab[ATABSIZE];
1375 static void setalias (char *, char *);
1376 static struct alias **hashalias (const char *);
1377 static struct alias *freealias (struct alias *);
1378 static struct alias **__lookupalias (const char *);
1384 struct alias *ap, **app;
1386 app = __lookupalias(name);
1390 if (!(ap->flag & ALIASINUSE)) {
1393 ap->val = savestr(val);
1394 ap->flag &= ~ALIASDEAD;
1397 ap = ckmalloc(sizeof (struct alias));
1398 ap->name = savestr(name);
1399 ap->val = savestr(val);
1412 app = __lookupalias(name);
1416 *app = freealias(*app);
1427 struct alias *ap, **app;
1431 for (i = 0; i < ATABSIZE; i++) {
1433 for (ap = *app; ap; ap = *app) {
1434 *app = freealias(*app);
1443 static struct alias *
1444 lookupalias(const char *name, int check)
1446 struct alias *ap = *__lookupalias(name);
1448 if (check && ap && (ap->flag & ALIASINUSE))
1454 printalias(const struct alias *ap) {
1457 p = single_quote(ap->val);
1458 printf("alias %s=%s\n", ap->name, p);
1464 * TODO - sort output
1467 aliascmd(int argc, char **argv)
1476 for (i = 0; i < ATABSIZE; i++)
1477 for (ap = atab[i]; ap; ap = ap->next) {
1482 while ((n = *++argv) != NULL) {
1483 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1484 if ((ap = *__lookupalias(n)) == NULL) {
1485 out2fmt("%s: %s not found\n", "alias", n);
1500 unaliascmd(int argc, char **argv)
1504 while ((i = nextopt("a")) != '\0') {
1510 for (i = 0; *argptr; argptr++) {
1511 if (unalias(*argptr)) {
1512 out2fmt("%s: %s not found\n", "unalias", *argptr);
1520 static struct alias **
1524 unsigned int hashval;
1529 return &atab[hashval % ATABSIZE];
1532 static struct alias *
1533 freealias(struct alias *ap) {
1536 if (ap->flag & ALIASINUSE) {
1537 ap->flag |= ALIASDEAD;
1549 static struct alias **
1550 __lookupalias(const char *name) {
1551 struct alias **app = hashalias(name);
1553 for (; *app; app = &(*app)->next) {
1554 if (equal(name, (*app)->name)) {
1563 #ifdef ASH_MATH_SUPPORT
1564 /* The generated file arith.c has been replaced with a custom hand
1565 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1566 * This is now part of libbb, so that it can be used by all the shells
1568 #define ARITH_NUM 257
1569 #define ARITH_LPAREN 258
1570 #define ARITH_RPAREN 259
1571 #define ARITH_OR 260
1572 #define ARITH_AND 261
1573 #define ARITH_BOR 262
1574 #define ARITH_BXOR 263
1575 #define ARITH_BAND 264
1576 #define ARITH_EQ 265
1577 #define ARITH_NE 266
1578 #define ARITH_LT 267
1579 #define ARITH_GT 268
1580 #define ARITH_GE 269
1581 #define ARITH_LE 270
1582 #define ARITH_LSHIFT 271
1583 #define ARITH_RSHIFT 272
1584 #define ARITH_ADD 273
1585 #define ARITH_SUB 274
1586 #define ARITH_MUL 275
1587 #define ARITH_DIV 276
1588 #define ARITH_REM 277
1589 #define ARITH_UNARYMINUS 278
1590 #define ARITH_UNARYPLUS 279
1591 #define ARITH_NOT 280
1592 #define ARITH_BNOT 281
1594 static void expari (int);
1597 static char *trap[NSIG]; /* trap handler commands */
1598 static char sigmode[NSIG - 1]; /* current value of signal */
1599 static char gotsig[NSIG - 1]; /* indicates specified signal received */
1600 static int pendingsigs; /* indicates some signal received */
1603 * This file was generated by the mkbuiltins program.
1607 static int bgcmd (int, char **);
1608 static int fgcmd (int, char **);
1609 static int killcmd (int, char **);
1611 static int bltincmd (int, char **);
1612 static int cdcmd (int, char **);
1613 static int breakcmd (int, char **);
1615 static int commandcmd (int, char **);
1617 static int dotcmd (int, char **);
1618 static int evalcmd (int, char **);
1619 static int execcmd (int, char **);
1620 static int exitcmd (int, char **);
1621 static int exportcmd (int, char **);
1622 static int histcmd (int, char **);
1623 static int hashcmd (int, char **);
1624 static int helpcmd (int, char **);
1625 static int jobscmd (int, char **);
1626 static int localcmd (int, char **);
1628 static int pwdcmd (int, char **);
1630 static int readcmd (int, char **);
1631 static int returncmd (int, char **);
1632 static int setcmd (int, char **);
1633 static int setvarcmd (int, char **);
1634 static int shiftcmd (int, char **);
1635 static int trapcmd (int, char **);
1636 static int umaskcmd (int, char **);
1638 static int aliascmd (int, char **);
1639 static int unaliascmd (int, char **);
1641 static int unsetcmd (int, char **);
1642 static int waitcmd (int, char **);
1643 static int ulimitcmd (int, char **);
1644 static int timescmd (int, char **);
1645 #ifdef ASH_MATH_SUPPORT
1646 static int letcmd (int, char **);
1648 static int typecmd (int, char **);
1650 static int getoptscmd (int, char **);
1653 #ifndef BB_TRUE_FALSE
1654 static int true_main (int, char **);
1655 static int false_main (int, char **);
1658 static void setpwd (const char *, int);
1661 #define BUILTIN_NOSPEC "0"
1662 #define BUILTIN_SPECIAL "1"
1663 #define BUILTIN_REGULAR "2"
1664 #define BUILTIN_ASSIGN "4"
1665 #define BUILTIN_SPEC_ASSG "5"
1666 #define BUILTIN_REG_ASSG "6"
1668 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1669 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1670 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1674 int (*const builtinfunc) (int, char **);
1679 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1680 * the binary search in find_builtin() will stop working. If you value
1681 * your kneecaps, you'll be sure to *make sure* that any changes made
1682 * to this array result in the listing remaining in ascii order. You
1685 static const struct builtincmd builtincmds[] = {
1686 { BUILTIN_SPECIAL ".", dotcmd }, /* first, see declare DOTCMD */
1687 { BUILTIN_SPECIAL ":", true_main },
1689 { BUILTIN_REG_ASSG "alias", aliascmd },
1692 { BUILTIN_REGULAR "bg", bgcmd },
1694 { BUILTIN_SPECIAL "break", breakcmd },
1695 { BUILTIN_SPECIAL "builtin", bltincmd },
1696 { BUILTIN_REGULAR "cd", cdcmd },
1697 { BUILTIN_NOSPEC "chdir", cdcmd },
1699 { BUILTIN_REGULAR "command", commandcmd },
1701 { BUILTIN_SPECIAL "continue", breakcmd },
1702 { BUILTIN_SPECIAL "eval", evalcmd },
1703 { BUILTIN_SPECIAL "exec", execcmd },
1704 { BUILTIN_SPECIAL "exit", exitcmd },
1705 { BUILTIN_SPEC_ASSG "export", exportcmd },
1706 { BUILTIN_REGULAR "false", false_main },
1707 { BUILTIN_REGULAR "fc", histcmd },
1709 { BUILTIN_REGULAR "fg", fgcmd },
1712 { BUILTIN_REGULAR "getopts", getoptscmd },
1714 { BUILTIN_NOSPEC "hash", hashcmd },
1715 { BUILTIN_NOSPEC "help", helpcmd },
1716 { BUILTIN_REGULAR "jobs", jobscmd },
1718 { BUILTIN_REGULAR "kill", killcmd },
1720 #ifdef ASH_MATH_SUPPORT
1721 { BUILTIN_REGULAR "let", letcmd },
1723 { BUILTIN_ASSIGN "local", localcmd },
1725 { BUILTIN_NOSPEC "pwd", pwdcmd },
1727 { BUILTIN_REGULAR "read", readcmd },
1728 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1729 { BUILTIN_SPECIAL "return", returncmd },
1730 { BUILTIN_SPECIAL "set", setcmd },
1731 { BUILTIN_NOSPEC "setvar", setvarcmd },
1732 { BUILTIN_SPECIAL "shift", shiftcmd },
1733 { BUILTIN_SPECIAL "times", timescmd },
1734 { BUILTIN_SPECIAL "trap", trapcmd },
1735 { BUILTIN_REGULAR "true", true_main },
1736 { BUILTIN_NOSPEC "type", typecmd },
1737 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1738 { BUILTIN_REGULAR "umask", umaskcmd },
1740 { BUILTIN_REGULAR "unalias", unaliascmd },
1742 { BUILTIN_SPECIAL "unset", unsetcmd },
1743 { BUILTIN_REGULAR "wait", waitcmd },
1745 #define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1747 static const struct builtincmd *DOTCMD = &builtincmds[0];
1748 static struct builtincmd *BLTINCMD;
1749 static struct builtincmd *EXECCMD;
1750 static struct builtincmd *EVALCMD;
1753 #define JOBSTOPPED 1 /* all procs are stopped */
1754 #define JOBDONE 2 /* all procs are completed */
1757 * A job structure contains information about a job. A job is either a
1758 * single process or a set of processes contained in a pipeline. In the
1759 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1764 pid_t pid; /* process id */
1765 int status; /* status flags (defined above) */
1766 char *cmd; /* text of command being run */
1770 static int job_warning; /* user was warned about stopped jobs */
1773 static void setjobctl(int enable);
1775 #define setjobctl(on) /* do nothing */
1780 struct procstat ps0; /* status of process */
1781 struct procstat *ps; /* status or processes when more than one */
1782 short nprocs; /* number of processes */
1783 short pgrp; /* process group of this job */
1784 char state; /* true if job is finished */
1785 char used; /* true if this entry is in used */
1786 char changed; /* true if status has changed */
1788 char jobctl; /* job running under job control */
1792 static struct job *jobtab; /* array of jobs */
1793 static int njobs; /* size of array */
1794 static int backgndpid = -1; /* pid of last background process */
1796 static int initialpgrp; /* pgrp of shell on invocation */
1797 static int curjob; /* current job */
1800 static int intreceived;
1802 static struct job *makejob (const union node *, int);
1803 static int forkshell (struct job *, const union node *, int);
1804 static int waitforjob (struct job *);
1806 static int docd (char *, int);
1807 static char *getcomponent (void);
1808 static void updatepwd (const char *);
1809 static void getpwd (void);
1811 static char *padvance (const char **, const char *);
1813 static char nullstr[1]; /* zero length string */
1814 static char *curdir = nullstr; /* current working directory */
1815 static char *cdcomppath;
1829 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1830 error("HOME not set");
1833 if (dest[0] == '-' && dest[1] == '\0') {
1834 dest = bltinlookup("OLDPWD");
1835 if (!dest || !*dest) {
1844 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1846 while ((p = padvance(&path, dest)) != NULL) {
1847 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1852 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1854 print = strcmp(p, dest);
1856 if (docd(p, print) >= 0)
1861 error("can't cd to %s", dest);
1867 * Actually do the chdir. In an interactive shell, print the
1868 * directory name if "print" is nonzero.
1883 TRACE(("docd(\"%s\", %d) called\n", dest, print));
1886 * Check each component of the path. If we find a symlink or
1887 * something we can't stat, clear curdir to force a getcwd()
1888 * next time we get the value of the current directory.
1891 cdcomppath = sstrdup(dest);
1898 while ((q = getcomponent()) != NULL) {
1899 if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
1907 if (equal(component, ".."))
1910 if ((lstat(stackblock(), &statb) < 0)
1911 || (S_ISLNK(statb.st_mode))) {
1919 if (chdir(dest) < 0) {
1923 updatepwd(badstat ? NULL : dest);
1926 printf(snlfmt, curdir);
1932 * Get the next component of the path name pointed to by cdcomppath.
1933 * This routine overwrites the string pointed to by cdcomppath.
1941 if ((p = cdcomppath) == NULL)
1944 while (*p != '/' && *p != '\0')
1958 * Update curdir (the name of the current directory) in response to a
1959 * cd command. We also call hashcd to let the routines in exec.c know
1960 * that the current directory has changed.
1963 static void hashcd (void);
1966 updatepwd(const char *dir)
1972 hashcd(); /* update command hash table */
1975 * If our argument is NULL, we don't know the current directory
1976 * any more because we traversed a symbolic link or something
1977 * we couldn't stat().
1979 if (dir == NULL || curdir == nullstr) {
1984 cdcomppath = sstrdup(dir);
1993 while ((p = getcomponent()) != NULL) {
1994 if (equal(p, "..")) {
1995 while (new > stackblock() && (STUNPUTC(new), *new) != '/');
1996 } else if (*p != '\0' && ! equal(p, ".")) {
2002 if (new == stackblock())
2005 setpwd(stackblock(), 1);
2015 printf(snlfmt, curdir);
2021 * Find out what the current directory is. If we already know the current
2022 * directory, this routine returns immediately.
2027 curdir = xgetcwd(0);
2033 setpwd(const char *val, int setold)
2036 setvar("OLDPWD", curdir, VEXPORT);
2039 if (curdir != nullstr) {
2046 curdir = savestr(val);
2049 setvar("PWD", curdir, VEXPORT);
2053 * Errors and exceptions.
2057 * Code to handle exceptions in C.
2061 * We enclose jmp_buf in a structure so that we can declare pointers to
2062 * jump locations. The global variable handler contains the location to
2063 * jump to when an exception occurs, and the global variable exception
2064 * contains a code identifying the exeception. To implement nested
2065 * exception handlers, the user should save the value of handler on entry
2066 * to an inner scope, set handler to point to a jmploc structure for the
2067 * inner scope, and restore handler on exit from the scope.
2075 #define EXINT 0 /* SIGINT received */
2076 #define EXERROR 1 /* a generic error */
2077 #define EXSHELLPROC 2 /* execute a shell procedure */
2078 #define EXEXEC 3 /* command execution failed */
2080 static struct jmploc *handler;
2081 static int exception;
2083 static void exverror (int, const char *, va_list)
2084 __attribute__((__noreturn__));
2087 * Called to raise an exception. Since C doesn't include exceptions, we
2088 * just do a longjmp to the exception handler. The type of exception is
2089 * stored in the global variable "exception".
2092 static void exraise (int) __attribute__((__noreturn__));
2098 if (handler == NULL)
2103 longjmp(handler->loc, 1);
2108 * Called from trap.c when a SIGINT is received. (If the user specifies
2109 * that SIGINT is to be trapped or ignored using the trap builtin, then
2110 * this routine is not called.) Suppressint is nonzero when interrupts
2111 * are held using the INTOFF macro. The call to _exit is necessary because
2112 * there is a short period after a fork before the signal handlers are
2113 * set to the appropriate value for the child. (The test for iflag is
2114 * just defensive programming.)
2126 sigemptyset(&mysigset);
2127 sigprocmask(SIG_SETMASK, &mysigset, NULL);
2128 if (rootshell && iflag)
2131 signal(SIGINT, SIG_DFL);
2138 static char *commandname; /* currently executing command */
2141 * Exverror is called to raise the error exception. If the first argument
2142 * is not NULL then error prints an error message using printf style
2143 * formatting. It then raises the error exception.
2146 exverror(int cond, const char *msg, va_list ap)
2153 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
2155 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2159 out2fmt("%s: ", commandname);
2160 vfprintf(stderr, msg, ap);
2169 error(const char *msg, ...)
2173 exverror(EXERROR, msg, ap);
2180 exerror(int cond, const char *msg, ...)
2184 exverror(cond, msg, ap);
2192 * Table of error messages.
2196 short errcode; /* error number */
2197 char action; /* operation which encountered the error */
2201 * Types of operations (passed to the errmsg routine).
2204 #define E_OPEN 01 /* opening a file */
2205 #define E_CREAT 02 /* creating a file */
2206 #define E_EXEC 04 /* executing a program */
2208 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2210 static const struct errname errormsg[] = {
2215 { ENOENT, E_CREAT },
2217 { ENOTDIR, E_OPEN },
2218 { ENOTDIR, E_CREAT },
2219 { ENOTDIR, E_EXEC },
2221 { EEXIST, E_CREAT },
2260 { ELIBACC, E_EXEC },
2264 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2267 * Return a string describing an error. The returned string may be a
2268 * pointer to a static buffer that will be overwritten on the next call.
2269 * Action describes the operation that got the error.
2273 errmsg(int e, int action)
2275 struct errname const *ep;
2276 static char buf[12];
2278 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2279 if (ep->errcode == e && (ep->action & action) != 0)
2283 snprintf(buf, sizeof buf, "error %d", e);
2288 #ifdef ASH_OPTIMIZE_FOR_SIZE
2291 if (--suppressint == 0 && intpending) {
2295 static void forceinton (void) {
2302 /* flags in argument to evaltree */
2303 #define EV_EXIT 01 /* exit after evaluating tree */
2304 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2305 #define EV_BACKCMD 04 /* command executing within back quotes */
2307 static int evalskip; /* set if we are skipping commands */
2308 static int skipcount; /* number of levels to skip */
2309 static int loopnest; /* current loop nesting level */
2310 static int funcnest; /* depth of function calls */
2313 static struct strlist *cmdenviron; /* environment for builtin command */
2314 static int exitstatus; /* exit status of last command */
2315 static int oexitstatus; /* saved exit status */
2317 static void evalsubshell (const union node *, int);
2318 static void expredir (union node *);
2319 static void prehash (union node *);
2320 static void eprintlist (struct strlist *);
2322 static union node *parsecmd(int);
2324 * Called to reset things after an exception.
2328 * The eval commmand.
2330 static void evalstring (char *, int);
2344 STARTSTACKSTR(concat);
2348 STPUTC(*p++, concat);
2349 if ((p = *ap++) == NULL)
2351 STPUTC(' ', concat);
2353 STPUTC('\0', concat);
2354 p = grabstackstr(concat);
2356 evalstring(p, EV_TESTED);
2362 * Execute a command or commands contained in a string.
2365 static void evaltree (union node *, int);
2366 static void setinputstring (char *);
2367 static void popfile (void);
2368 static void setstackmark(struct stackmark *mark);
2369 static void popstackmark(struct stackmark *mark);
2373 evalstring(char *s, int flag)
2376 struct stackmark smark;
2378 setstackmark(&smark);
2380 while ((n = parsecmd(0)) != NEOF) {
2382 popstackmark(&smark);
2385 popstackmark(&smark);
2388 static struct builtincmd *find_builtin (const char *);
2389 static void expandarg (union node *, struct arglist *, int);
2390 static void calcsize (const union node *);
2391 static union node *copynode (const union node *);
2394 * Make a copy of a parse tree.
2397 static int funcblocksize; /* size of structures in function */
2398 static int funcstringsize; /* size of strings in node */
2399 static pointer funcblock; /* block to allocate function from */
2400 static char *funcstring; /* block to allocate strings from */
2403 static inline union node *
2404 copyfunc(union node *n)
2411 funcblock = ckmalloc(funcblocksize + funcstringsize);
2412 funcstring = (char *) funcblock + funcblocksize;
2417 * Free a parse tree.
2421 freefunc(union node *n)
2429 * Add a new command entry, replacing any existing command entry for
2434 addcmdentry(char *name, struct cmdentry *entry)
2436 struct tblentry *cmdp;
2439 cmdp = cmdlookup(name, 1);
2440 if (cmdp->cmdtype == CMDFUNCTION) {
2441 freefunc(cmdp->param.func);
2443 cmdp->cmdtype = entry->cmdtype;
2444 cmdp->param = entry->u;
2449 evalloop(const union node *n, int flags)
2456 evaltree(n->nbinary.ch1, EV_TESTED);
2458 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2462 if (evalskip == SKIPBREAK && --skipcount <= 0)
2466 if (n->type == NWHILE) {
2467 if (exitstatus != 0)
2470 if (exitstatus == 0)
2473 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2474 status = exitstatus;
2479 exitstatus = status;
2483 evalfor(const union node *n, int flags)
2485 struct arglist arglist;
2488 struct stackmark smark;
2490 setstackmark(&smark);
2491 arglist.lastp = &arglist.list;
2492 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2493 oexitstatus = exitstatus;
2494 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2498 *arglist.lastp = NULL;
2502 for (sp = arglist.list ; sp ; sp = sp->next) {
2503 setvar(n->nfor.var, sp->text, 0);
2504 evaltree(n->nfor.body, flags & EV_TESTED);
2506 if (evalskip == SKIPCONT && --skipcount <= 0) {
2510 if (evalskip == SKIPBREAK && --skipcount <= 0)
2517 popstackmark(&smark);
2521 evalcase(const union node *n, int flags)
2525 struct arglist arglist;
2526 struct stackmark smark;
2528 setstackmark(&smark);
2529 arglist.lastp = &arglist.list;
2530 oexitstatus = exitstatus;
2531 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2532 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2533 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2534 if (casematch(patp, arglist.list->text)) {
2535 if (evalskip == 0) {
2536 evaltree(cp->nclist.body, flags);
2543 popstackmark(&smark);
2547 * Evaluate a pipeline. All the processes in the pipeline are children
2548 * of the process creating the pipeline. (This differs from some versions
2549 * of the shell, which make the last process in a pipeline the parent
2558 struct nodelist *lp;
2563 TRACE(("evalpipe(0x%lx) called\n", (long)n));
2565 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2568 jp = makejob(n, pipelen);
2570 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2574 if (pipe(pip) < 0) {
2576 error("Pipe call failed");
2579 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2583 dup_as_newfd(prevfd, 0);
2595 dup_as_newfd(pip[1], 1);
2599 evaltree(lp->n, EV_EXIT);
2607 if (n->npipe.backgnd == 0) {
2609 exitstatus = waitforjob(jp);
2610 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2615 static void find_command (const char *, struct cmdentry *, int, const char *);
2618 isassignment(const char *word) {
2619 if (!is_name(*word)) {
2624 } while (is_in_name(*word));
2625 return *word == '=';
2630 evalcommand(union node *cmd, int flags)
2632 struct stackmark smark;
2634 struct arglist arglist;
2635 struct arglist varlist;
2641 struct cmdentry cmdentry;
2643 char *volatile savecmdname;
2644 volatile struct shparam saveparam;
2645 struct localvar *volatile savelocalvars;
2649 const struct builtincmd *firstbltin;
2650 struct jmploc *volatile savehandler;
2651 struct jmploc jmploc;
2653 /* Avoid longjmp clobbering */
2660 /* First expand the arguments. */
2661 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2662 setstackmark(&smark);
2663 arglist.lastp = &arglist.list;
2664 varlist.lastp = &varlist.list;
2666 oexitstatus = exitstatus;
2669 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2670 expandarg(argp, &varlist, EXP_VARTILDE);
2673 argp = cmd->ncmd.args; argp && !arglist.list;
2674 argp = argp->narg.next
2676 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2679 struct builtincmd *bcmd;
2681 bcmd = find_builtin(arglist.list->text);
2682 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2683 for (; argp; argp = argp->narg.next) {
2684 if (pseudovarflag && isassignment(argp->narg.text)) {
2685 expandarg(argp, &arglist, EXP_VARTILDE);
2688 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2691 *arglist.lastp = NULL;
2692 *varlist.lastp = NULL;
2693 expredir(cmd->ncmd.redirect);
2695 for (sp = arglist.list ; sp ; sp = sp->next)
2697 argv = stalloc(sizeof (char *) * (argc + 1));
2699 for (sp = arglist.list ; sp ; sp = sp->next) {
2700 TRACE(("evalcommand arg: %s\n", sp->text));
2705 if (iflag && funcnest == 0 && argc > 0)
2709 /* Print the command if xflag is set. */
2712 eprintlist(varlist.list);
2713 eprintlist(arglist.list);
2717 /* Now locate the command. */
2719 cmdentry.cmdtype = CMDBUILTIN;
2720 firstbltin = cmdentry.u.cmd = BLTINCMD;
2722 const char *oldpath;
2723 int findflag = DO_ERR;
2727 * Modify the command lookup path, if a PATH= assignment
2730 for (sp = varlist.list ; sp ; sp = sp->next)
2731 if (varequal(sp->text, defpathvar)) {
2732 path = sp->text + 5;
2733 findflag |= DO_BRUTE;
2736 oldfindflag = findflag;
2739 find_command(argv[0], &cmdentry, findflag, path);
2740 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
2744 /* implement bltin and command here */
2745 if (cmdentry.cmdtype != CMDBUILTIN) {
2749 firstbltin = cmdentry.u.cmd;
2751 if (cmdentry.u.cmd == BLTINCMD) {
2753 struct builtincmd *bcmd;
2758 if (!(bcmd = find_builtin(*argv))) {
2759 out2fmt("%s: not found\n", *argv);
2763 cmdentry.u.cmd = bcmd;
2764 if (bcmd != BLTINCMD)
2768 if (cmdentry.u.cmd == find_builtin("command")) {
2773 if (*argv[0] == '-') {
2774 if (!equal(argv[0], "-p")) {
2784 findflag |= DO_BRUTE;
2787 findflag = oldfindflag;
2789 findflag |= DO_NOFUN;
2797 /* Fork off a child process if necessary. */
2798 if (cmd->ncmd.backgnd
2799 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2801 jp = makejob(cmd, 1);
2802 mode = cmd->ncmd.backgnd;
2803 if (forkshell(jp, cmd, mode) != 0)
2804 goto parent; /* at end of routine */
2808 /* This is the child process if a fork occurred. */
2809 /* Execute the command. */
2810 if (cmdentry.cmdtype == CMDFUNCTION) {
2812 trputs("Shell function: "); trargs(argv);
2814 exitstatus = oexitstatus;
2815 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2816 saveparam = shellparam;
2817 shellparam.malloc = 0;
2818 shellparam.nparam = argc - 1;
2819 shellparam.p = argv + 1;
2821 savelocalvars = localvars;
2824 if (setjmp(jmploc.loc)) {
2825 if (exception == EXSHELLPROC) {
2826 freeparam((volatile struct shparam *)
2829 saveparam.optind = shellparam.optind;
2830 saveparam.optoff = shellparam.optoff;
2831 freeparam(&shellparam);
2832 shellparam = saveparam;
2835 localvars = savelocalvars;
2836 handler = savehandler;
2837 longjmp(handler->loc, 1);
2839 savehandler = handler;
2841 for (sp = varlist.list ; sp ; sp = sp->next)
2844 evaltree(cmdentry.u.func, flags & EV_TESTED);
2848 localvars = savelocalvars;
2849 saveparam.optind = shellparam.optind;
2850 saveparam.optoff = shellparam.optoff;
2851 freeparam(&shellparam);
2852 shellparam = saveparam;
2853 handler = savehandler;
2856 if (evalskip == SKIPFUNC) {
2860 if (flags & EV_EXIT)
2861 exitshell(exitstatus);
2862 } else if (cmdentry.cmdtype == CMDBUILTIN) {
2864 trputs("builtin command: "); trargs(argv);
2866 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
2867 redirect(cmd->ncmd.redirect, mode);
2868 savecmdname = commandname;
2869 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2870 listsetvar(varlist.list);
2872 cmdenviron = varlist.list;
2875 if (setjmp(jmploc.loc)) {
2877 exitstatus = (e == EXINT)? SIGINT+128 : 2;
2880 savehandler = handler;
2882 commandname = argv[0];
2884 optptr = NULL; /* initialize nextopt */
2885 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
2889 if (e != EXSHELLPROC) {
2890 commandname = savecmdname;
2891 if (flags & EV_EXIT)
2892 exitshell(exitstatus);
2894 handler = savehandler;
2896 if ((e != EXERROR && e != EXEXEC)
2897 || cmdentry.u.cmd == BLTINCMD
2898 || cmdentry.u.cmd == DOTCMD
2899 || cmdentry.u.cmd == EVALCMD
2900 || cmdentry.u.cmd == EXECCMD)
2904 if (cmdentry.u.cmd != EXECCMD)
2908 trputs("normal command: "); trargs(argv);
2910 redirect(cmd->ncmd.redirect, 0);
2912 for (sp = varlist.list ; sp ; sp = sp->next)
2913 setvareq(sp->text, VEXPORT|VSTACK);
2914 envp = environment();
2915 shellexec(argv, envp, path, cmdentry.u.index);
2919 parent: /* parent process gets here (if we forked) */
2920 if (mode == 0) { /* argument to fork */
2922 exitstatus = waitforjob(jp);
2928 setvar("_", lastarg, 0);
2929 popstackmark(&smark);
2933 * Evaluate a parse tree. The value is left in the global variable
2943 TRACE(("evaltree(NULL) called\n"));
2946 TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2949 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2952 evaltree(n->nbinary.ch2, flags);
2955 evaltree(n->nbinary.ch1, EV_TESTED);
2956 if (evalskip || exitstatus != 0)
2958 evaltree(n->nbinary.ch2, flags);
2961 evaltree(n->nbinary.ch1, EV_TESTED);
2962 if (evalskip || exitstatus == 0)
2964 evaltree(n->nbinary.ch2, flags);
2967 expredir(n->nredir.redirect);
2968 redirect(n->nredir.redirect, REDIR_PUSH);
2969 evaltree(n->nredir.n, flags);
2973 evalsubshell(n, flags);
2976 evalsubshell(n, flags);
2979 evaltree(n->nif.test, EV_TESTED);
2982 if (exitstatus == 0)
2983 evaltree(n->nif.ifpart, flags);
2984 else if (n->nif.elsepart)
2985 evaltree(n->nif.elsepart, flags);
3001 struct builtincmd *bcmd;
3002 struct cmdentry entry;
3004 (bcmd = find_builtin(n->narg.text)) &&
3005 IS_BUILTIN_SPECIAL(bcmd)
3007 out2fmt("%s is a special built-in\n", n->narg.text);
3011 entry.cmdtype = CMDFUNCTION;
3012 entry.u.func = copyfunc(n->narg.next);
3013 addcmdentry(n->narg.text, &entry);
3018 evaltree(n->nnot.com, EV_TESTED);
3019 exitstatus = !exitstatus;
3027 evalcommand(n, flags);
3032 printf("Node type = %d\n", n->type);
3041 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
3043 exitshell(exitstatus);
3047 * Kick off a subshell to evaluate a tree.
3051 evalsubshell(const union node *n, int flags)
3054 int backgnd = (n->type == NBACKGND);
3056 expredir(n->nredir.redirect);
3058 if (forkshell(jp, n, backgnd) == 0) {
3060 flags &=~ EV_TESTED;
3061 redirect(n->nredir.redirect, 0);
3062 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
3066 exitstatus = waitforjob(jp);
3072 * Compute the names of the files in a redirection list.
3075 static void fixredir(union node *n, const char *text, int err);
3078 expredir(union node *n)
3082 for (redir = n ; redir ; redir = redir->nfile.next) {
3084 fn.lastp = &fn.list;
3085 oexitstatus = exitstatus;
3086 switch (redir->type) {
3092 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3093 redir->nfile.expfname = fn.list->text;
3097 if (redir->ndup.vname) {
3098 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3099 fixredir(redir, fn.list->text, 1);
3108 * Execute a command inside back quotes. If it's a builtin command, we
3109 * want to save its output in a block obtained from malloc. Otherwise
3110 * we fork off a subprocess and get the output of the command via a pipe.
3111 * Should be called with interrupts off.
3115 evalbackcmd(union node *n, struct backcmd *result)
3119 struct stackmark smark; /* unnecessary */
3121 setstackmark(&smark);
3132 error("Pipe call failed");
3134 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3139 dup_as_newfd(pip[1], 1);
3143 evaltree(n, EV_EXIT);
3146 result->fd = pip[0];
3149 popstackmark(&smark);
3150 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3151 result->fd, result->buf, result->nleft, result->jp));
3156 * Execute a simple command.
3160 * Search for a command. This is called before we fork so that the
3161 * location of the command will be available in the parent as well as
3162 * the child. The check for "goodname" is an overly conservative
3163 * check that the name will not be subject to expansion.
3170 struct cmdentry entry;
3172 if (n->type == NCMD && n->ncmd.args)
3173 if (goodname(n->ncmd.args->narg.text))
3174 find_command(n->ncmd.args->narg.text, &entry, 0,
3180 * Builtin commands. Builtin commands whose functions are closely
3181 * tied to evaluation are implemented here.
3185 * No command given, or a bltin command with no arguments. Set the
3186 * specified variables.
3190 bltincmd(argc, argv)
3195 * Preserve exitstatus of a previous possible redirection
3203 * Handle break and continue commands. Break, continue, and return are
3204 * all handled by setting the evalskip flag. The evaluation routines
3205 * above all check this flag, and if it is set they start skipping
3206 * commands rather than executing them. The variable skipcount is
3207 * the number of loops to break/continue, or the number of function
3208 * levels to return. (The latter is always 1.) It should probably
3209 * be an error to break out of more loops than exist, but it isn't
3210 * in the standard shell so we don't make it one here.
3214 breakcmd(argc, argv)
3218 int n = argc > 1 ? number(argv[1]) : 1;
3223 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3231 * The return command.
3235 returncmd(argc, argv)
3239 int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3242 evalskip = SKIPFUNC;
3247 /* Do what ksh does; skip the rest of the file */
3248 evalskip = SKIPFILE;
3255 #ifndef BB_TRUE_FALSE
3257 false_main(argc, argv)
3266 true_main(argc, argv)
3275 * Controls whether the shell is interactive or not.
3278 static void setsignal(int signo);
3279 static void chkmail(int silent);
3283 setinteractive(int on)
3285 static int is_interactive;
3286 static int do_banner=0;
3288 if (on == is_interactive)
3294 is_interactive = on;
3295 if (do_banner==0 && is_interactive) {
3296 /* Looks like they want an interactive shell */
3297 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3298 printf( "Enter 'help' for a list of built-in commands.\n\n");
3306 setinteractive(iflag);
3319 iflag = 0; /* exit on error */
3322 for (sp = cmdenviron; sp ; sp = sp->next)
3323 setvareq(sp->text, VEXPORT|VSTACK);
3324 shellexec(argv + 1, environment(), pathval(), 0);
3330 eprintlist(struct strlist *sp)
3332 for (; sp; sp = sp->next) {
3333 out2fmt(" %s",sp->text);
3338 * Exec a program. Never returns. If you change this routine, you may
3339 * have to change the find_command routine as well.
3342 static const char *pathopt; /* set by padvance */
3345 shellexec(argv, envp, path, idx)
3346 char **argv, **envp;
3353 if (strchr(argv[0], '/') != NULL) {
3354 tryexec(argv[0], argv, envp);
3358 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3359 if (--idx < 0 && pathopt == NULL) {
3360 tryexec(cmdname, argv, envp);
3361 if (errno != ENOENT && errno != ENOTDIR)
3368 /* Map to POSIX errors */
3380 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3385 * Clear traps on a fork.
3391 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3392 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3397 setsignal(tp - trap);
3405 initshellproc(void) {
3431 /* from options.c: */
3435 for (i = 0; i < NOPTS; i++)
3451 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3463 static int preadbuffer(void);
3464 static void pushfile (void);
3467 * Read a character from the script, returning PEOF on end of file.
3468 * Nul characters in the input are silently discarded.
3471 #ifndef ASH_OPTIMIZE_FOR_SIZE
3472 #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3476 return pgetc_macro();
3482 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3488 return pgetc_macro();
3494 * Undo the last call to pgetc. Only one character may be pushed back.
3495 * PEOF may be pushed back.
3507 struct parsefile *pf = parsefile;
3516 parsefile = pf->prev;
3518 parsenleft = parsefile->nleft;
3519 parselleft = parsefile->lleft;
3520 parsenextc = parsefile->nextc;
3521 plinno = parsefile->linno;
3527 * Return to top level.
3532 while (parsefile != &basepf)
3537 * Close the file(s) that the shell is reading commands from. Called
3538 * after a fork is done.
3544 if (parsefile->fd > 0) {
3545 close(parsefile->fd);
3552 * Like setinputfile, but takes an open file descriptor. Call this with
3557 setinputfd(fd, push)
3560 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3566 while (parsefile->strpush)
3570 if (parsefile->buf == NULL)
3571 parsefile->buf = ckmalloc(BUFSIZ);
3572 parselleft = parsenleft = 0;
3578 * Set the input to take input from a file. If push is set, push the
3579 * old input onto the stack first.
3583 setinputfile(const char *fname, int push)
3589 if ((fd = open(fname, O_RDONLY)) < 0)
3590 error("Can't open %s", fname);
3592 myfileno2 = dup_as_newfd(fd, 10);
3595 error("Out of file descriptors");
3598 setinputfd(fd, push);
3604 tryexec(char *cmd, char **argv, char **envp)
3608 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3612 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
3613 name = get_last_path_component(name);
3616 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3619 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3621 run_applet_by_name(name, argc_l, argv);
3623 execve(cmd, argv, envp);
3628 setinputfile(cmd, 0);
3629 commandname = arg0 = savestr(argv[0]);
3631 exraise(EXSHELLPROC);
3636 static char *commandtext (const union node *);
3639 * Do a path search. The variable path (passed by reference) should be
3640 * set to the start of the path before the first call; padvance will update
3641 * this value as it proceeds. Successive calls to padvance will return
3642 * the possible path expansions in sequence. If an option (indicated by
3643 * a percent sign) appears in the path entry then the global variable
3644 * pathopt will be set to point to it; otherwise pathopt will be set to
3648 static const char *pathopt;
3650 static void growstackblock(void);
3654 padvance(const char **path, const char *name)
3664 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3665 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3666 while (stackblocksize() < len)
3670 memcpy(q, start, p - start);
3678 while (*p && *p != ':') p++;
3684 return stalloc(len);
3688 * Wrapper around strcmp for qsort/bsearch/...
3691 pstrcmp(const void *a, const void *b)
3693 return strcmp((const char *) a, *(const char *const *) b);
3697 * Find a keyword is in a sorted array.
3700 static const char *const *
3701 findkwd(const char *s)
3703 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
3704 sizeof(const char *), pstrcmp);
3708 /*** Command hashing code ***/
3716 struct tblentry **pp;
3717 struct tblentry *cmdp;
3720 struct cmdentry entry;
3723 const struct alias *ap;
3727 while ((c = nextopt("rvV")) != '\0') {
3731 } else if (c == 'v' || c == 'V') {
3735 if (*argptr == NULL) {
3736 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3737 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3738 if (cmdp->cmdtype != CMDBUILTIN) {
3739 printentry(cmdp, verbose);
3746 while ((name = *argptr++) != NULL) {
3747 if ((cmdp = cmdlookup(name, 0)) != NULL
3748 && (cmdp->cmdtype == CMDNORMAL
3749 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3752 /* Then look at the aliases */
3753 if ((ap = lookupalias(name, 0)) != NULL) {
3755 printf("%s is an alias for %s\n", name, ap->val);
3761 /* First look at the keywords */
3762 if (findkwd(name)!=0) {
3764 printf("%s is a shell keyword\n", name);
3766 printf(snlfmt, name);
3770 find_command(name, &entry, DO_ERR, pathval());
3771 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3773 cmdp = cmdlookup(name, 0);
3774 if (cmdp) printentry(cmdp, verbose=='v');
3782 printentry(cmdp, verbose)
3783 struct tblentry *cmdp;
3790 printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3791 if (cmdp->cmdtype == CMDNORMAL) {
3792 idx = cmdp->param.index;
3795 name = padvance(&path, cmdp->cmdname);
3797 } while (--idx >= 0);
3800 } else if (cmdp->cmdtype == CMDBUILTIN) {
3802 out1str("a shell builtin");
3803 } else if (cmdp->cmdtype == CMDFUNCTION) {
3806 out1str("a function\n");
3807 name = commandtext(cmdp->param.func);
3808 printf("%s() {\n %s\n}", cmdp->cmdname, name);
3814 error("internal error: cmdtype %d", cmdp->cmdtype);
3817 printf(snlfmt, cmdp->rehash ? "*" : nullstr);
3822 /*** List the available builtins ***/
3825 static int helpcmd(int argc, char** argv)
3829 printf("\nBuilt-in commands:\n-------------------\n");
3830 for (col=0, i=0; i < NUMBUILTINS; i++) {
3831 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3832 builtincmds[i].name+1);
3838 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3840 extern const struct BB_applet applets[];
3841 extern const size_t NUM_APPLETS;
3843 for (i=0; i < NUM_APPLETS; i++) {
3845 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3855 return EXIT_SUCCESS;
3859 * Resolve a command name. If you change this routine, you may have to
3860 * change the shellexec routine as well.
3863 static int prefix (const char *, const char *);
3866 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3868 struct tblentry *cmdp;
3878 struct builtincmd *bcmd;
3880 /* If name contains a slash, don't use the hash table */
3881 if (strchr(name, '/') != NULL) {
3883 while (stat(name, &statb) < 0) {
3884 if (errno != ENOENT && errno != ENOTDIR)
3886 entry->cmdtype = CMDUNKNOWN;
3887 entry->u.index = -1;
3890 entry->cmdtype = CMDNORMAL;
3891 entry->u.index = -1;
3894 entry->cmdtype = CMDNORMAL;
3900 if (act & DO_BRUTE) {
3901 firstchange = path_change(path, &bltin);
3907 /* If name is in the table, and not invalidated by cd, we're done */
3908 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3909 if (cmdp->cmdtype == CMDFUNCTION) {
3910 if (act & DO_NOFUN) {
3915 } else if (act & DO_BRUTE) {
3916 if ((cmdp->cmdtype == CMDNORMAL &&
3917 cmdp->param.index >= firstchange) ||
3918 (cmdp->cmdtype == CMDBUILTIN &&
3919 ((builtinloc < 0 && bltin >= 0) ?
3920 bltin : builtinloc) >= firstchange)) {
3921 /* need to recompute the entry */
3930 bcmd = find_builtin(name);
3931 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3934 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3937 } else if (act & DO_BRUTE) {
3938 if (firstchange == 0) {
3943 /* If %builtin not in path, check for builtin next */
3944 if (regular || (bltin < 0 && bcmd)) {
3947 entry->cmdtype = CMDBUILTIN;
3948 entry->u.cmd = bcmd;
3952 cmdp = cmdlookup(name, 1);
3953 cmdp->cmdtype = CMDBUILTIN;
3954 cmdp->param.cmd = bcmd;
3959 /* We have to search path. */
3960 prev = -1; /* where to start */
3961 if (cmdp && cmdp->rehash) { /* doing a rehash */
3962 if (cmdp->cmdtype == CMDBUILTIN)
3965 prev = cmdp->param.index;
3971 while ((fullname = padvance(&path, name)) != NULL) {
3972 stunalloc(fullname);
3974 if (idx >= firstchange) {
3978 if (prefix("builtin", pathopt)) {
3979 if ((bcmd = find_builtin(name))) {
3983 } else if (!(act & DO_NOFUN) &&
3984 prefix("func", pathopt)) {
3987 continue; /* ignore unimplemented options */
3990 /* if rehash, don't redo absolute path names */
3991 if (fullname[0] == '/' && idx <= prev &&
3992 idx < firstchange) {
3995 TRACE(("searchexec \"%s\": no change\n", name));
3998 while (stat(fullname, &statb) < 0) {
3999 if (errno != ENOENT && errno != ENOTDIR)
4003 e = EACCES; /* if we fail, this will be the error */
4004 if (!S_ISREG(statb.st_mode))
4006 if (pathopt) { /* this is a %func directory */
4007 stalloc(strlen(fullname) + 1);
4008 readcmdfile(fullname);
4009 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
4010 error("%s not defined in %s", name, fullname);
4011 stunalloc(fullname);
4014 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4015 /* If we aren't called with DO_BRUTE and cmdp is set, it must
4016 be a function and we're being called with DO_NOFUN */
4018 entry->cmdtype = CMDNORMAL;
4019 entry->u.index = idx;
4023 cmdp = cmdlookup(name, 1);
4024 cmdp->cmdtype = CMDNORMAL;
4025 cmdp->param.index = idx;
4030 /* We failed. If there was an entry for this command, delete it */
4031 if (cmdp && updatetbl)
4034 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
4035 entry->cmdtype = CMDUNKNOWN;
4040 entry->cmdtype = cmdp->cmdtype;
4041 entry->u = cmdp->param;
4047 * Search the table of builtin commands.
4051 bstrcmp(const void *name, const void *b)
4053 return strcmp((const char *)name, (*(const char *const *) b)+1);
4056 static struct builtincmd *
4057 find_builtin(const char *name)
4059 struct builtincmd *bp;
4061 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
4069 * Called when a cd is done. Marks all commands so the next time they
4070 * are executed they will be rehashed.
4075 struct tblentry **pp;
4076 struct tblentry *cmdp;
4078 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4079 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4080 if (cmdp->cmdtype == CMDNORMAL
4081 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
4090 * Called before PATH is changed. The argument is the new value of PATH;
4091 * pathval() still returns the old value at this point. Called with
4096 changepath(const char *newval)
4101 firstchange = path_change(newval, &bltin);
4102 if (builtinloc < 0 && bltin >= 0)
4103 builtinloc = bltin; /* zap builtins */
4104 clearcmdentry(firstchange);
4110 * Clear out command entries. The argument specifies the first entry in
4111 * PATH which has changed.
4115 clearcmdentry(firstchange)
4118 struct tblentry **tblp;
4119 struct tblentry **pp;
4120 struct tblentry *cmdp;
4123 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4125 while ((cmdp = *pp) != NULL) {
4126 if ((cmdp->cmdtype == CMDNORMAL &&
4127 cmdp->param.index >= firstchange)
4128 || (cmdp->cmdtype == CMDBUILTIN &&
4129 builtinloc >= firstchange)) {
4142 * Delete all functions.
4147 struct tblentry **tblp;
4148 struct tblentry **pp;
4149 struct tblentry *cmdp;
4152 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4154 while ((cmdp = *pp) != NULL) {
4155 if (cmdp->cmdtype == CMDFUNCTION) {
4157 freefunc(cmdp->param.func);
4170 * Locate a command in the command hash table. If "add" is nonzero,
4171 * add the command to the table if it is not already present. The
4172 * variable "lastcmdentry" is set to point to the address of the link
4173 * pointing to the entry, so that delete_cmd_entry can delete the
4177 static struct tblentry **lastcmdentry;
4179 static struct tblentry *
4180 cmdlookup(const char *name, int add)
4184 struct tblentry *cmdp;
4185 struct tblentry **pp;
4192 pp = &cmdtable[hashval % CMDTABLESIZE];
4193 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4194 if (equal(cmdp->cmdname, name))
4198 if (add && cmdp == NULL) {
4200 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4201 + strlen(name) + 1);
4203 cmdp->cmdtype = CMDUNKNOWN;
4205 strcpy(cmdp->cmdname, name);
4213 * Delete the command entry returned on the last lookup.
4217 delete_cmd_entry() {
4218 struct tblentry *cmdp;
4221 cmdp = *lastcmdentry;
4222 *lastcmdentry = cmdp->next;
4231 static const short nodesize[26] = {
4232 ALIGN(sizeof (struct nbinary)),
4233 ALIGN(sizeof (struct ncmd)),
4234 ALIGN(sizeof (struct npipe)),
4235 ALIGN(sizeof (struct nredir)),
4236 ALIGN(sizeof (struct nredir)),
4237 ALIGN(sizeof (struct nredir)),
4238 ALIGN(sizeof (struct nbinary)),
4239 ALIGN(sizeof (struct nbinary)),
4240 ALIGN(sizeof (struct nif)),
4241 ALIGN(sizeof (struct nbinary)),
4242 ALIGN(sizeof (struct nbinary)),
4243 ALIGN(sizeof (struct nfor)),
4244 ALIGN(sizeof (struct ncase)),
4245 ALIGN(sizeof (struct nclist)),
4246 ALIGN(sizeof (struct narg)),
4247 ALIGN(sizeof (struct narg)),
4248 ALIGN(sizeof (struct nfile)),
4249 ALIGN(sizeof (struct nfile)),
4250 ALIGN(sizeof (struct nfile)),
4251 ALIGN(sizeof (struct nfile)),
4252 ALIGN(sizeof (struct nfile)),
4253 ALIGN(sizeof (struct ndup)),
4254 ALIGN(sizeof (struct ndup)),
4255 ALIGN(sizeof (struct nhere)),
4256 ALIGN(sizeof (struct nhere)),
4257 ALIGN(sizeof (struct nnot)),
4263 * Delete a function if it exists.
4267 unsetfunc(char *name)
4269 struct tblentry *cmdp;
4271 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4272 freefunc(cmdp->param.func);
4279 * Locate and print what a word is...
4283 typecmd(int argc, char **argv)
4291 for (i = 1; i < argc; i++) {
4292 argv_a[0] = argv[i];
4295 err |= hashcmd(argc, argv);
4302 commandcmd(argc, argv)
4307 int default_path = 0;
4308 int verify_only = 0;
4309 int verbose_verify_only = 0;
4311 while ((c = nextopt("pvV")) != '\0')
4320 verbose_verify_only = 1;
4324 if (default_path + verify_only + verbose_verify_only > 1 ||
4327 "command [-p] command [arg ...]\n"
4328 "command {-v|-V} command\n");
4332 if (verify_only || verbose_verify_only) {
4336 argv_a[0] = *argptr;
4338 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
4339 return hashcmd(argc, argv);
4347 path_change(newval, bltin)
4351 const char *old, *new;
4357 firstchange = 9999; /* assume no change */
4363 if ((*old == '\0' && *new == ':')
4364 || (*old == ':' && *new == '\0'))
4366 old = new; /* ignore subsequent differences */
4370 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4377 if (builtinloc >= 0 && *bltin < 0)
4382 * Routines to expand arguments to commands. We have to deal with
4383 * backquotes, shell variables, and file metacharacters.
4388 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4389 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4392 * Structure specifying which parts of the string should be searched
4393 * for IFS characters.
4397 struct ifsregion *next; /* next region in list */
4398 int begoff; /* offset of start of region */
4399 int endoff; /* offset of end of region */
4400 int nulonly; /* search for nul bytes only */
4404 static char *expdest; /* output of current string */
4405 static struct nodelist *argbackq; /* list of back quote expressions */
4406 static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
4407 static struct ifsregion *ifslastp; /* last struct in list */
4408 static struct arglist exparg; /* holds expanded arg list */
4410 static void argstr (char *, int);
4411 static char *exptilde (char *, int);
4412 static void expbackq (union node *, int, int);
4413 static int subevalvar (char *, char *, int, int, int, int, int);
4414 static int varisset (char *, int);
4415 static void strtodest (const char *, const char *, int);
4416 static void varvalue (char *, int, int);
4417 static void recordregion (int, int, int);
4418 static void removerecordregions (int);
4419 static void ifsbreakup (char *, struct arglist *);
4420 static void ifsfree (void);
4421 static void expandmeta (struct strlist *, int);
4422 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4423 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4424 #if !defined(GLOB_BROKEN)
4425 static void addglob (const glob_t *);
4428 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4429 static void expmeta (char *, char *);
4431 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4432 static struct strlist *expsort (struct strlist *);
4433 static struct strlist *msort (struct strlist *, int);
4435 static int patmatch (char *, char *, int);
4436 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4437 static int patmatch2 (char *, char *, int);
4439 static int pmatch (char *, char *, int);
4440 #define patmatch2 patmatch
4442 static char *cvtnum (int, char *);
4445 * Expand shell variables and backquotes inside a here document.
4448 /* arg: the document, fd: where to write the expanded version */
4450 expandhere(union node *arg, int fd)
4453 expandarg(arg, (struct arglist *)NULL, 0);
4454 xwrite(fd, stackblock(), expdest - stackblock());
4459 * Perform variable substitution and command substitution on an argument,
4460 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4461 * perform splitting and file name expansion. When arglist is NULL, perform
4462 * here document expansion.
4466 expandarg(arg, arglist, flag)
4468 struct arglist *arglist;
4474 argbackq = arg->narg.backquote;
4475 STARTSTACKSTR(expdest);
4476 ifsfirst.next = NULL;
4478 argstr(arg->narg.text, flag);
4479 if (arglist == NULL) {
4480 return; /* here document expanded */
4482 STPUTC('\0', expdest);
4483 p = grabstackstr(expdest);
4484 exparg.lastp = &exparg.list;
4488 if (flag & EXP_FULL) {
4489 ifsbreakup(p, &exparg);
4490 *exparg.lastp = NULL;
4491 exparg.lastp = &exparg.list;
4492 expandmeta(exparg.list, flag);
4494 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4496 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4499 exparg.lastp = &sp->next;
4502 *exparg.lastp = NULL;
4504 *arglist->lastp = exparg.list;
4505 arglist->lastp = exparg.lastp;
4511 * Expand a variable, and return a pointer to the next character in the
4515 static inline char *
4531 int quotes = flag & (EXP_FULL | EXP_CASE);
4534 subtype = varflags & VSTYPE;
4539 p = strchr(p, '=') + 1;
4540 again: /* jump here after setting a variable with ${var=text} */
4542 set = varisset(var, varflags & VSNUL);
4545 val = lookupvar(var);
4546 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4553 startloc = expdest - stackblock();
4554 if (set && subtype != VSPLUS) {
4555 /* insert the value of the variable */
4557 varvalue(var, varflags & VSQUOTE, flag);
4558 if (subtype == VSLENGTH) {
4559 varlen = expdest - stackblock() - startloc;
4560 STADJUST(-varlen, expdest);
4563 if (subtype == VSLENGTH) {
4564 varlen = strlen(val);
4568 varflags & VSQUOTE ?
4569 DQSYNTAX : BASESYNTAX,
4576 if (subtype == VSPLUS)
4579 easy = ((varflags & VSQUOTE) == 0 ||
4580 (*var == '@' && shellparam.nparam != 1));
4585 expdest = cvtnum(varlen, expdest);
4592 recordregion(startloc, expdest - stackblock(),
4593 varflags & VSQUOTE);
4609 case VSTRIMRIGHTMAX:
4613 * Terminate the string and start recording the pattern
4616 STPUTC('\0', expdest);
4617 patloc = expdest - stackblock();
4618 if (subevalvar(p, NULL, patloc, subtype,
4619 startloc, varflags, quotes) == 0) {
4620 int amount = (expdest - stackblock() - patloc) + 1;
4621 STADJUST(-amount, expdest);
4623 /* Remove any recorded regions beyond start of variable */
4624 removerecordregions(startloc);
4630 if (subevalvar(p, var, 0, subtype, startloc,
4631 varflags, quotes)) {
4634 * Remove any recorded regions beyond
4637 removerecordregions(startloc);
4652 if (subtype != VSNORMAL) { /* skip to end of alternative */
4655 if ((c = *p++) == CTLESC)
4657 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
4659 argbackq = argbackq->next;
4660 } else if (c == CTLVAR) {
4661 if ((*p++ & VSTYPE) != VSNORMAL)
4663 } else if (c == CTLENDVAR) {
4674 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4675 * characters to allow for further processing. Otherwise treat
4676 * $@ like $* since no splitting will be performed.
4685 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4688 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4689 p = exptilde(p, flag);
4693 case CTLENDVAR: /* ??? */
4696 /* "$@" syntax adherence hack */
4697 if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4699 if ((flag & EXP_FULL) != 0)
4709 p = evalvar(p, flag);
4712 case CTLBACKQ|CTLQUOTE:
4713 expbackq(argbackq->n, c & CTLQUOTE, flag);
4714 argbackq = argbackq->next;
4716 #ifdef ASH_MATH_SUPPORT
4724 * sort of a hack - expand tildes in variable
4725 * assignments (after the first '=' and after ':'s).
4728 if (flag & EXP_VARTILDE && *p == '~') {
4735 p = exptilde(p, flag);
4751 char c, *startp = p;
4754 int quotes = flag & (EXP_FULL | EXP_CASE);
4756 while ((c = *p) != '\0') {
4763 if (flag & EXP_VARTILDE)
4773 if (*(startp+1) == '\0') {
4774 if ((home = lookupvar("HOME")) == NULL)
4777 if ((pw = getpwnam(startp+1)) == NULL)
4784 strtodest(home, SQSYNTAX, quotes);
4793 removerecordregions(int endoff)
4795 if (ifslastp == NULL)
4798 if (ifsfirst.endoff > endoff) {
4799 while (ifsfirst.next != NULL) {
4800 struct ifsregion *ifsp;
4802 ifsp = ifsfirst.next->next;
4803 ckfree(ifsfirst.next);
4804 ifsfirst.next = ifsp;
4807 if (ifsfirst.begoff > endoff)
4810 ifslastp = &ifsfirst;
4811 ifsfirst.endoff = endoff;
4816 ifslastp = &ifsfirst;
4817 while (ifslastp->next && ifslastp->next->begoff < endoff)
4818 ifslastp=ifslastp->next;
4819 while (ifslastp->next != NULL) {
4820 struct ifsregion *ifsp;
4822 ifsp = ifslastp->next->next;
4823 ckfree(ifslastp->next);
4824 ifslastp->next = ifsp;
4827 if (ifslastp->endoff > endoff)
4828 ifslastp->endoff = endoff;
4832 #ifdef ASH_MATH_SUPPORT
4834 * Expand arithmetic expression. Backup to start of expression,
4835 * evaluate, place result in (backed up) result, adjust string position.
4844 int quotes = flag & (EXP_FULL | EXP_CASE);
4850 * This routine is slightly over-complicated for
4851 * efficiency. First we make sure there is
4852 * enough space for the result, which may be bigger
4853 * than the expression if we add exponentation. Next we
4854 * scan backwards looking for the start of arithmetic. If the
4855 * next previous character is a CTLESC character, then we
4856 * have to rescan starting from the beginning since CTLESC
4857 * characters have to be processed left to right.
4859 CHECKSTRSPACE(10, expdest);
4860 USTPUTC('\0', expdest);
4861 start = stackblock();
4863 while (*p != CTLARI && p >= start)
4866 error("missing CTLARI (shouldn't happen)");
4867 if (p > start && *(p-1) == CTLESC)
4868 for (p = start; *p != CTLARI; p++)
4877 removerecordregions(begoff);
4880 result = arith(p+2, &errcode);
4883 error("divide by zero");
4885 error("syntax error: \"%s\"\n", p+2);
4887 snprintf(p, 12, "%d", result);
4893 recordregion(begoff, p - 1 - start, 0);
4894 result = expdest - p + 1;
4895 STADJUST(-result, expdest);
4900 * Expand stuff in backwards quotes.
4904 expbackq(cmd, quoted, flag)
4909 volatile struct backcmd in;
4913 char *dest = expdest;
4914 volatile struct ifsregion saveifs;
4915 struct ifsregion *volatile savelastp;
4916 struct nodelist *volatile saveargbackq;
4918 int startloc = dest - stackblock();
4919 char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
4920 volatile int saveherefd;
4921 int quotes = flag & (EXP_FULL | EXP_CASE);
4922 struct jmploc jmploc;
4923 struct jmploc *volatile savehandler;
4927 /* Avoid longjmp clobbering */
4938 savelastp = ifslastp;
4939 saveargbackq = argbackq;
4940 saveherefd = herefd;
4942 if ((ex = setjmp(jmploc.loc))) {
4945 savehandler = handler;
4948 p = grabstackstr(dest);
4949 evalbackcmd(cmd, (struct backcmd *) &in);
4950 ungrabstackstr(p, dest);
4954 ifslastp = savelastp;
4955 argbackq = saveargbackq;
4956 herefd = saveherefd;
4964 if (--in.nleft < 0) {
4967 i = safe_read(in.fd, buf, sizeof buf);
4968 TRACE(("expbackq: read returns %d\n", i));
4975 if (lastc != '\0') {
4976 if (quotes && syntax[(int)lastc] == CCTL)
4977 STPUTC(CTLESC, dest);
4978 STPUTC(lastc, dest);
4982 /* Eat all trailing newlines */
4983 for (; dest > stackblock() && dest[-1] == '\n';)
4992 exitstatus = waitforjob(in.jp);
4993 handler = savehandler;
4995 longjmp(handler->loc, 1);
4998 recordregion(startloc, dest - stackblock(), 0);
4999 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5000 (dest - stackblock()) - startloc,
5001 (dest - stackblock()) - startloc,
5002 stackblock() + startloc));
5008 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
5021 int saveherefd = herefd;
5022 struct nodelist *saveargbackq = argbackq;
5026 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5027 STACKSTRNUL(expdest);
5028 herefd = saveherefd;
5029 argbackq = saveargbackq;
5030 startp = stackblock() + startloc;
5032 str = stackblock() + strloc;
5036 setvar(str, startp, 0);
5037 amount = startp - expdest;
5038 STADJUST(amount, expdest);
5045 if (*p != CTLENDVAR) {
5046 out2fmt(snlfmt, startp);
5047 error((char *)NULL);
5049 error("%.*s: parameter %snot set", p - str - 1,
5050 str, (varflags & VSNUL) ? "null or "
5055 for (loc = startp; loc < str; loc++) {
5058 if (patmatch2(str, startp, quotes))
5061 if (quotes && *loc == CTLESC)
5067 for (loc = str - 1; loc >= startp;) {
5070 if (patmatch2(str, startp, quotes))
5074 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5075 for (q = startp; q < loc; q++)
5085 for (loc = str - 1; loc >= startp;) {
5086 if (patmatch2(str, loc, quotes))
5089 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5090 for (q = startp; q < loc; q++)
5099 case VSTRIMRIGHTMAX:
5100 for (loc = startp; loc < str - 1; loc++) {
5101 if (patmatch2(str, loc, quotes))
5103 if (quotes && *loc == CTLESC)
5116 amount = ((str - 1) - (loc - startp)) - expdest;
5117 STADJUST(amount, expdest);
5118 while (loc != str - 1)
5123 amount = loc - expdest;
5124 STADJUST(amount, expdest);
5125 STPUTC('\0', expdest);
5126 STADJUST(-1, expdest);
5132 * Test whether a specialized variable is set.
5136 varisset(name, nulok)
5141 return backgndpid != -1;
5142 else if (*name == '@' || *name == '*') {
5143 if (*shellparam.p == NULL)
5149 for (av = shellparam.p; *av; av++)
5154 } else if (is_digit(*name)) {
5156 int num = atoi(name);
5158 if (num > shellparam.nparam)
5164 ap = shellparam.p[num - 1];
5166 if (nulok && (ap == NULL || *ap == '\0'))
5173 * Put a string on the stack.
5177 strtodest(p, syntax, quotes)
5183 if (quotes && syntax[(int) *p] == CCTL)
5184 STPUTC(CTLESC, expdest);
5185 STPUTC(*p++, expdest);
5190 * Add the value of a specialized variable to the stack string.
5194 varvalue(name, quoted, flags)
5206 int allow_split = flags & EXP_FULL;
5207 int quotes = flags & (EXP_FULL | EXP_CASE);
5209 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5218 num = shellparam.nparam;
5223 expdest = cvtnum(num, expdest);
5226 for (i = 0 ; i < NOPTS ; i++) {
5228 STPUTC(optent_letter(optlist[i]), expdest);
5232 if (allow_split && quoted) {
5233 sep = 1 << CHAR_BIT;
5238 sep = ifsset() ? ifsval()[0] : ' ';
5240 sepq = syntax[(int) sep] == CCTL;
5243 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5244 strtodest(p, syntax, quotes);
5247 STPUTC(CTLESC, expdest);
5248 STPUTC(sep, expdest);
5253 strtodest(arg0, syntax, quotes);
5257 if (num > 0 && num <= shellparam.nparam) {
5258 strtodest(shellparam.p[num - 1], syntax, quotes);
5266 * Record the fact that we have to scan this region of the
5267 * string for IFS characters.
5271 recordregion(start, end, nulonly)
5276 struct ifsregion *ifsp;
5278 if (ifslastp == NULL) {
5282 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5284 ifslastp->next = ifsp;
5288 ifslastp->begoff = start;
5289 ifslastp->endoff = end;
5290 ifslastp->nulonly = nulonly;
5296 * Break the argument string into pieces based upon IFS and add the
5297 * strings to the argument list. The regions of the string to be
5298 * searched for IFS characters have been stored by recordregion.
5301 ifsbreakup(string, arglist)
5303 struct arglist *arglist;
5305 struct ifsregion *ifsp;
5310 const char *ifs, *realifs;
5318 realifs = ifsset() ? ifsval() : defifs;
5319 if (ifslastp != NULL) {
5322 p = string + ifsp->begoff;
5323 nulonly = ifsp->nulonly;
5324 ifs = nulonly ? nullstr : realifs;
5326 while (p < string + ifsp->endoff) {
5330 if (strchr(ifs, *p)) {
5332 ifsspc = (strchr(defifs, *p) != NULL);
5333 /* Ignore IFS whitespace at start */
5334 if (q == start && ifsspc) {
5340 sp = (struct strlist *)stalloc(sizeof *sp);
5342 *arglist->lastp = sp;
5343 arglist->lastp = &sp->next;
5347 if (p >= string + ifsp->endoff) {
5353 if (strchr(ifs, *p) == NULL ) {
5356 } else if (strchr(defifs, *p) == NULL) {
5372 } while ((ifsp = ifsp->next) != NULL);
5373 if (!(*start || (!ifsspc && start > string && nulonly))) {
5378 sp = (struct strlist *)stalloc(sizeof *sp);
5380 *arglist->lastp = sp;
5381 arglist->lastp = &sp->next;
5387 while (ifsfirst.next != NULL) {
5388 struct ifsregion *ifsp;
5390 ifsp = ifsfirst.next->next;
5391 ckfree(ifsfirst.next);
5392 ifsfirst.next = ifsp;
5396 ifsfirst.next = NULL;
5400 * Add a file name to the list.
5404 addfname(const char *name)
5410 sp = (struct strlist *)stalloc(sizeof *sp);
5413 exparg.lastp = &sp->next;
5417 * Expand shell metacharacters. At this point, the only control characters
5418 * should be escapes. The results are stored in the list exparg.
5421 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5423 expandmeta(str, flag)
5424 struct strlist *str;
5429 /* TODO - EXP_REDIR */
5434 p = preglob(str->text);
5436 switch (glob(p, 0, 0, &pglob)) {
5438 if(pglob.gl_pathv[1]==0 && !strcmp(p, pglob.gl_pathv[0]))
5449 *exparg.lastp = str;
5450 rmescapes(str->text);
5451 exparg.lastp = &str->next;
5453 default: /* GLOB_NOSPACE */
5454 error("Out of space");
5462 * Add the result of glob(3) to the list.
5467 const glob_t *pglob;
5469 char **p = pglob->gl_pathv;
5477 #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5478 static char *expdir;
5482 expandmeta(str, flag)
5483 struct strlist *str;
5487 struct strlist **savelastp;
5490 /* TODO - EXP_REDIR */
5496 for (;;) { /* fast check for meta chars */
5497 if ((c = *p++) == '\0')
5499 if (c == '*' || c == '?' || c == '[' || c == '!')
5502 savelastp = exparg.lastp;
5504 if (expdir == NULL) {
5505 int i = strlen(str->text);
5506 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5509 expmeta(expdir, str->text);
5513 if (exparg.lastp == savelastp) {
5518 *exparg.lastp = str;
5519 rmescapes(str->text);
5520 exparg.lastp = &str->next;
5522 *exparg.lastp = NULL;
5523 *savelastp = sp = expsort(*savelastp);
5524 while (sp->next != NULL)
5526 exparg.lastp = &sp->next;
5534 * Do metacharacter (i.e. *, ?, [...]) expansion.
5538 expmeta(enddir, name)
5556 for (p = name ; ; p++) {
5557 if (*p == '*' || *p == '?')
5559 else if (*p == '[') {
5564 while (*q == CTLQUOTEMARK)
5568 if (*q == '/' || *q == '\0')
5575 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5577 } else if (*p == '\0')
5579 else if (*p == CTLQUOTEMARK)
5581 else if (*p == CTLESC)
5589 if (metaflag == 0) { /* we've reached the end of the file name */
5590 if (enddir != expdir)
5592 for (p = name ; ; p++) {
5593 if (*p == CTLQUOTEMARK)
5601 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5606 if (start != name) {
5609 while (*p == CTLQUOTEMARK)
5616 if (enddir == expdir) {
5618 } else if (enddir == expdir + 1 && *expdir == '/') {
5624 if ((dirp = opendir(cp)) == NULL)
5626 if (enddir != expdir)
5628 if (*endname == 0) {
5636 while (*p == CTLQUOTEMARK)
5642 while (! int_pending() && (dp = readdir(dirp)) != NULL) {
5643 if (dp->d_name[0] == '.' && ! matchdot)
5645 if (patmatch(start, dp->d_name, 0)) {
5647 strcpy(enddir, dp->d_name);
5650 for (p = enddir, cp = dp->d_name;
5651 (*p++ = *cp++) != '\0';)
5654 expmeta(p, endname);
5662 #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5666 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5668 * Sort the results of file name expansion. It calculates the number of
5669 * strings to sort and then calls msort (short for merge sort) to do the
5673 static struct strlist *
5675 struct strlist *str;
5681 for (sp = str ; sp ; sp = sp->next)
5683 return msort(str, len);
5687 static struct strlist *
5689 struct strlist *list;
5692 struct strlist *p, *q = NULL;
5693 struct strlist **lpp;
5701 for (n = half ; --n >= 0 ; ) {
5705 q->next = NULL; /* terminate first half of list */
5706 q = msort(list, half); /* sort first half of list */
5707 p = msort(p, len - half); /* sort second half */
5710 if (strcmp(p->text, q->text) < 0) {
5713 if ((p = *lpp) == NULL) {
5720 if ((q = *lpp) == NULL) {
5733 * Returns true if the pattern matches the string.
5736 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5737 /* squoted: string might have quote chars */
5739 patmatch(char *pattern, char *string, int squoted)
5744 p = preglob(pattern);
5745 q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5747 return !fnmatch(p, q, 0);
5752 patmatch2(char *pattern, char *string, int squoted)
5758 p = grabstackstr(expdest);
5759 res = patmatch(pattern, string, squoted);
5760 ungrabstackstr(p, expdest);
5765 patmatch(char *pattern, char *string, int squoted) {
5766 return pmatch(pattern, string, squoted);
5771 pmatch(char *pattern, char *string, int squoted)
5783 if (squoted && *q == CTLESC)
5791 if (squoted && *q == CTLESC)
5798 while (c == CTLQUOTEMARK || c == '*')
5800 if (c != CTLESC && c != CTLQUOTEMARK &&
5801 c != '?' && c != '*' && c != '[') {
5803 if (squoted && *q == CTLESC &&
5808 if (squoted && *q == CTLESC)
5814 if (pmatch(p, q, squoted))
5816 if (squoted && *q == CTLESC)
5818 } while (*q++ != '\0');
5829 while (*endp == CTLQUOTEMARK)
5832 goto dft; /* no matching ] */
5833 if (*endp == CTLESC)
5845 if (squoted && chr == CTLESC)
5851 if (c == CTLQUOTEMARK)
5855 if (*p == '-' && p[1] != ']') {
5857 while (*p == CTLQUOTEMARK)
5861 if (chr >= c && chr <= *p)
5868 } while ((c = *p++) != ']');
5869 if (found == invert)
5874 if (squoted && *q == CTLESC)
5891 * Remove any CTLESC characters from a string.
5894 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5896 _rmescapes(char *str, int flag)
5899 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5901 p = strpbrk(str, qchars);
5907 if (flag & RMESCAPE_ALLOC) {
5908 size_t len = p - str;
5909 q = r = stalloc(strlen(p) + len + 1);
5911 memcpy(q, str, len);
5916 if (*p == CTLQUOTEMARK) {
5922 if (flag & RMESCAPE_GLOB && *p != '/') {
5939 while (*p != CTLESC && *p != CTLQUOTEMARK) {
5945 if (*p == CTLQUOTEMARK) {
5960 * See if a pattern matches in a case statement.
5964 casematch(union node *pattern, const char *val)
5966 struct stackmark smark;
5970 setstackmark(&smark);
5971 argbackq = pattern->narg.backquote;
5972 STARTSTACKSTR(expdest);
5974 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5975 STPUTC('\0', expdest);
5976 p = grabstackstr(expdest);
5977 result = patmatch(p, (char *)val, 0);
5978 popstackmark(&smark);
5993 CHECKSTRSPACE(32, buf);
5994 len = sprintf(buf, "%d", num);
5999 * Editline and history functions (and glue).
6001 static int histcmd(argc, argv)
6005 error("not compiled with history support");
6011 struct redirtab *next;
6012 short renamed[10]; /* Current ash support only 0-9 descriptors */
6013 /* char on arm (and others) can't be negative */
6016 static struct redirtab *redirlist;
6018 extern char **environ;
6023 * Initialization code.
6036 basepf.nextc = basepf.buf = basebuf;
6045 for (envp = environ ; *envp ; envp++) {
6046 if (strchr(*envp, '=')) {
6047 setvareq(*envp, VEXPORT|VTEXTFIXED);
6051 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
6052 setvar("PPID", ppid, 0);
6059 * This routine is called when an error or an interrupt occurs in an
6060 * interactive shell and control is returned to the main command loop.
6063 /* 1 == check for aliases, 2 == also check for assignments */
6064 static int checkalias; /* also used in no alias mode for check assignments */
6078 if (exception != EXSHELLPROC)
6079 parselleft = parsenleft = 0; /* clear input buffer */
6083 /* from parser.c: */
6101 * This file implements the input routines used by the parser.
6104 #ifdef BB_FEATURE_COMMAND_EDITING
6105 static const char * cmdedit_prompt;
6106 static inline void putprompt(const char *s) {
6110 static inline void putprompt(const char *s) {
6115 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
6120 * Same as pgetc(), but ignores PEOA.
6130 } while (c == PEOA);
6134 static inline int pgetc2() { return pgetc_macro(); }
6138 * Read a line from the script.
6141 static inline char *
6142 pfgets(char *line, int len)
6148 while (--nleft > 0) {
6167 char *buf = parsefile->buf;
6171 #ifdef BB_FEATURE_COMMAND_EDITING
6173 if (!iflag || parsefile->fd)
6174 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6176 nr = cmdedit_read_input((char*)cmdedit_prompt, buf);
6180 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6184 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6185 int flags = fcntl(0, F_GETFL, 0);
6186 if (flags >= 0 && flags & O_NONBLOCK) {
6187 flags &=~ O_NONBLOCK;
6188 if (fcntl(0, F_SETFL, flags) >= 0) {
6189 out2str("sh: turning off NDELAY mode\n");
6201 struct strpush *sp = parsefile->strpush;
6206 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6211 if (sp->string != sp->ap->val) {
6215 sp->ap->flag &= ~ALIASINUSE;
6216 if (sp->ap->flag & ALIASDEAD) {
6217 unalias(sp->ap->name);
6221 parsenextc = sp->prevstring;
6222 parsenleft = sp->prevnleft;
6223 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6224 parsefile->strpush = sp->prev;
6225 if (sp != &(parsefile->basestrpush))
6232 * Refill the input buffer and return the next input character:
6234 * 1) If a string was pushed back on the input, pop it;
6235 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6236 * from a string so we can't refill the buffer, return EOF.
6237 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6238 * 4) Process input up to the next newline, deleting nul characters.
6248 while (parsefile->strpush) {
6250 if (parsenleft == -1 && parsefile->strpush->ap &&
6251 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6256 if (--parsenleft >= 0)
6257 return (*parsenextc++);
6259 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6264 if (parselleft <= 0) {
6265 if ((parselleft = preadfd()) <= 0) {
6266 parselleft = parsenleft = EOF_NLEFT;
6273 /* delete nul characters */
6274 for (more = 1; more;) {
6282 parsenleft = q - parsenextc;
6283 more = 0; /* Stop processing here */
6289 if (--parselleft <= 0 && more) {
6290 parsenleft = q - parsenextc - 1;
6301 out2str(parsenextc);
6306 return *parsenextc++;
6311 * Push a string back onto the input at this current parsefile level.
6312 * We handle aliases this way.
6315 pushstring(char *s, int len, void *ap)
6320 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6321 if (parsefile->strpush) {
6322 sp = ckmalloc(sizeof (struct strpush));
6323 sp->prev = parsefile->strpush;
6324 parsefile->strpush = sp;
6326 sp = parsefile->strpush = &(parsefile->basestrpush);
6327 sp->prevstring = parsenextc;
6328 sp->prevnleft = parsenleft;
6330 sp->ap = (struct alias *)ap;
6332 ((struct alias *)ap)->flag |= ALIASINUSE;
6343 * Like setinputfile, but takes input from a string.
6347 setinputstring(char *string)
6351 parsenextc = string;
6352 parsenleft = strlen(string);
6353 parsefile->buf = NULL;
6361 * To handle the "." command, a stack of input files is used. Pushfile
6362 * adds a new entry to the stack and popfile restores the previous level.
6367 struct parsefile *pf;
6369 parsefile->nleft = parsenleft;
6370 parsefile->lleft = parselleft;
6371 parsefile->nextc = parsenextc;
6372 parsefile->linno = plinno;
6373 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6374 pf->prev = parsefile;
6377 pf->basestrpush.prev = NULL;
6382 static void restartjob (struct job *);
6384 static void freejob (struct job *);
6385 static struct job *getjob (const char *);
6386 static int dowait (int, struct job *);
6387 static void waitonint(int);
6391 * We keep track of whether or not fd0 has been redirected. This is for
6392 * background commands, where we want to redirect fd0 to /dev/null only
6393 * if it hasn't already been redirected.
6395 static int fd0_redirected = 0;
6397 /* Return true if fd 0 has already been redirected at least once. */
6399 fd0_redirected_p () {
6400 return fd0_redirected != 0;
6403 static void dupredirect (const union node *, int, int fd1dup);
6407 * Turn job control on and off.
6409 * Note: This code assumes that the third arg to ioctl is a character
6410 * pointer, which is true on Berkeley systems but not System V. Since
6411 * System V doesn't have job control yet, this isn't a problem now.
6416 static void setjobctl(int enable)
6418 #ifdef OLD_TTY_DRIVER
6422 if (enable == jobctl || rootshell == 0)
6425 do { /* while we are in the background */
6426 #ifdef OLD_TTY_DRIVER
6427 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6429 initialpgrp = tcgetpgrp(2);
6430 if (initialpgrp < 0) {
6432 out2str("sh: can't access tty; job control turned off\n");
6436 if (initialpgrp == -1)
6437 initialpgrp = getpgrp();
6438 else if (initialpgrp != getpgrp()) {
6439 killpg(initialpgrp, SIGTTIN);
6443 #ifdef OLD_TTY_DRIVER
6444 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6445 out2str("sh: need new tty driver to run job control; job control turned off\n");
6453 setpgid(0, rootpid);
6454 #ifdef OLD_TTY_DRIVER
6455 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6457 tcsetpgrp(2, rootpid);
6459 } else { /* turning job control off */
6460 setpgid(0, initialpgrp);
6461 #ifdef OLD_TTY_DRIVER
6462 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6464 tcsetpgrp(2, initialpgrp);
6490 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6491 "kill -l [exitstatus]"
6495 if (*argv[1] == '-') {
6496 signo = decode_signal(argv[1] + 1, 1);
6500 while ((c = nextopt("ls:")) != '\0')
6506 signo = decode_signal(optionarg, 1);
6509 "invalid signal number or name: %s",
6517 "nextopt returned character code 0%o", c);
6524 if (!list && signo < 0)
6527 if ((signo < 0 || !*argptr) ^ list) {
6536 for (i = 1; i < NSIG; i++) {
6537 name = u_signal_names(0, &i, 1);
6539 printf(snlfmt, name);
6543 name = u_signal_names(*argptr, &signo, -1);
6545 printf(snlfmt, name);
6547 error("invalid signal number or exit status: %s",
6553 if (**argptr == '%') {
6554 jp = getjob(*argptr);
6555 if (jp->jobctl == 0)
6556 error("job %s not created under job control",
6558 pid = -jp->ps[0].pid;
6560 pid = atoi(*argptr);
6561 if (kill(pid, signo) != 0)
6562 error("%s: %m", *argptr);
6563 } while (*++argptr);
6577 jp = getjob(argv[1]);
6578 if (jp->jobctl == 0)
6579 error("job not created under job control");
6580 pgrp = jp->ps[0].pid;
6581 #ifdef OLD_TTY_DRIVER
6582 ioctl(2, TIOCSPGRP, (char *)&pgrp);
6588 status = waitforjob(jp);
6602 jp = getjob(*++argv);
6603 if (jp->jobctl == 0)
6604 error("job not created under job control");
6606 } while (--argc > 1);
6615 struct procstat *ps;
6618 if (jp->state == JOBDONE)
6621 killpg(jp->ps[0].pid, SIGCONT);
6622 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6623 if (WIFSTOPPED(ps->status)) {
6632 static void showjobs(int change);
6646 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6647 * statuses have changed since the last call to showjobs.
6649 * If the shell is interrupted in the process of creating a job, the
6650 * result may be a job structure containing zero processes. Such structures
6651 * will be freed here.
6662 struct procstat *ps;
6666 TRACE(("showjobs(%d) called\n", change));
6667 while (dowait(0, (struct job *)NULL) > 0);
6668 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6671 if (jp->nprocs == 0) {
6675 if (change && ! jp->changed)
6677 procno = jp->nprocs;
6678 for (ps = jp->ps ; ; ps++) { /* for each process */
6680 snprintf(s, 64, "[%d] %ld ", jobno,
6683 snprintf(s, 64, " %ld ",
6688 if (ps->status == -1) {
6689 /* don't print anything */
6690 } else if (WIFEXITED(ps->status)) {
6691 snprintf(s, 64, "Exit %d",
6692 WEXITSTATUS(ps->status));
6695 if (WIFSTOPPED(ps->status))
6696 i = WSTOPSIG(ps->status);
6697 else /* WIFSIGNALED(ps->status) */
6699 i = WTERMSIG(ps->status);
6700 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6701 strcpy(s, sys_siglist[i & 0x7F]);
6703 snprintf(s, 64, "Signal %d", i & 0x7F);
6704 if (WCOREDUMP(ps->status))
6705 strcat(s, " (core dumped)");
6710 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6717 if (jp->state == JOBDONE) {
6725 * Mark a job structure as unused.
6729 freejob(struct job *jp)
6731 const struct procstat *ps;
6735 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6736 if (ps->cmd != nullstr)
6739 if (jp->ps != &jp->ps0)
6743 if (curjob == jp - jobtab + 1)
6762 job = getjob(*++argv);
6766 for (;;) { /* loop until process terminated or stopped */
6769 status = job->ps[job->nprocs - 1].status;
6775 if (WIFEXITED(status))
6776 retval = WEXITSTATUS(status);
6778 else if (WIFSTOPPED(status))
6779 retval = WSTOPSIG(status) + 128;
6782 /* XXX: limits number of signals */
6783 retval = WTERMSIG(status) + 128;
6788 for (jp = jobtab ; ; jp++) {
6789 if (jp >= jobtab + njobs) { /* no running procs */
6792 if (jp->used && jp->state == 0)
6796 if (dowait(2, 0) < 0 && errno == EINTR) {
6805 * Convert a job name to a job structure.
6809 getjob(const char *name)
6819 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6820 error("No current job");
6821 return &jobtab[jobno - 1];
6823 error("No current job");
6825 } else if (name[0] == '%') {
6826 if (is_digit(name[1])) {
6827 jobno = number(name + 1);
6828 if (jobno > 0 && jobno <= njobs
6829 && jobtab[jobno - 1].used != 0)
6830 return &jobtab[jobno - 1];
6832 } else if (name[1] == '%' && name[2] == '\0') {
6836 struct job *found = NULL;
6837 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6838 if (jp->used && jp->nprocs > 0
6839 && prefix(name + 1, jp->ps[0].cmd)) {
6841 error("%s: ambiguous", name);
6848 } else if (is_number(name, &pid)) {
6849 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6850 if (jp->used && jp->nprocs > 0
6851 && jp->ps[jp->nprocs - 1].pid == pid)
6855 error("No such job: %s", name);
6862 * Return a new job structure,
6866 makejob(const union node *node, int nprocs)
6871 for (i = njobs, jp = jobtab ; ; jp++) {
6875 jobtab = ckmalloc(4 * sizeof jobtab[0]);
6877 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
6878 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6879 /* Relocate `ps' pointers */
6880 for (i = 0; i < njobs; i++)
6881 if (jp[i].ps == &jobtab[i].ps0)
6882 jp[i].ps = &jp[i].ps0;
6886 jp = jobtab + njobs;
6887 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
6900 jp->jobctl = jobctl;
6903 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
6908 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
6915 * Fork of a subshell. If we are doing job control, give the subshell its
6916 * own process group. Jp is a job structure that the job is to be added to.
6917 * N is the command that will be evaluated by the child. Both jp and n may
6918 * be NULL. The mode parameter can be one of the following:
6919 * FORK_FG - Fork off a foreground process.
6920 * FORK_BG - Fork off a background process.
6921 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
6922 * process group even if job control is on.
6924 * When job control is turned off, background processes have their standard
6925 * input redirected to /dev/null (except for the second and later processes
6932 forkshell(struct job *jp, const union node *n, int mode)
6938 const char *devnull = _PATH_DEVNULL;
6939 const char *nullerr = "Can't open %s";
6941 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
6946 TRACE(("Fork failed, errno=%d\n", errno));
6948 error("Cannot fork");
6955 TRACE(("Child shell %d\n", getpid()));
6956 wasroot = rootshell;
6962 jobctl = 0; /* do job control only in root shell */
6963 if (wasroot && mode != FORK_NOJOB && mflag) {
6964 if (jp == NULL || jp->nprocs == 0)
6967 pgrp = jp->ps[0].pid;
6969 if (mode == FORK_FG) {
6970 /*** this causes superfluous TIOCSPGRPS ***/
6971 #ifdef OLD_TTY_DRIVER
6972 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
6973 error("TIOCSPGRP failed, errno=%d", errno);
6975 if (tcsetpgrp(2, pgrp) < 0)
6976 error("tcsetpgrp failed, errno=%d", errno);
6981 } else if (mode == FORK_BG) {
6984 if ((jp == NULL || jp->nprocs == 0) &&
6985 ! fd0_redirected_p ()) {
6987 if (open(devnull, O_RDONLY) != 0)
6988 error(nullerr, devnull);
6992 if (mode == FORK_BG) {
6995 if ((jp == NULL || jp->nprocs == 0) &&
6996 ! fd0_redirected_p ()) {
6998 if (open(devnull, O_RDONLY) != 0)
6999 error(nullerr, devnull);
7003 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
7006 if (wasroot && iflag) {
7014 if (rootshell && mode != FORK_NOJOB && mflag) {
7015 if (jp == NULL || jp->nprocs == 0)
7018 pgrp = jp->ps[0].pid;
7022 if (mode == FORK_BG)
7023 backgndpid = pid; /* set $! */
7025 struct procstat *ps = &jp->ps[jp->nprocs++];
7029 if (iflag && rootshell && n)
7030 ps->cmd = commandtext(n);
7033 TRACE(("In parent shell: child = %d\n", pid));
7040 * Wait for job to finish.
7042 * Under job control we have the problem that while a child process is
7043 * running interrupts generated by the user are sent to the child but not
7044 * to the shell. This means that an infinite loop started by an inter-
7045 * active user may be hard to kill. With job control turned off, an
7046 * interactive user may place an interactive program inside a loop. If
7047 * the interactive program catches interrupts, the user doesn't want
7048 * these interrupts to also abort the loop. The approach we take here
7049 * is to have the shell ignore interrupt signals while waiting for a
7050 * forground process to terminate, and then send itself an interrupt
7051 * signal if the child process was terminated by an interrupt signal.
7052 * Unfortunately, some programs want to do a bit of cleanup and then
7053 * exit on interrupt; unless these processes terminate themselves by
7054 * sending a signal to themselves (instead of calling exit) they will
7055 * confuse this approach.
7059 waitforjob(struct job *jp)
7062 int mypgrp = getpgrp();
7066 struct sigaction act, oact;
7075 sigaction(SIGINT, 0, &act);
7076 act.sa_handler = waitonint;
7077 sigaction(SIGINT, &act, &oact);
7079 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7080 while (jp->state == 0) {
7088 sigaction(SIGINT, &oact, 0);
7089 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7093 #ifdef OLD_TTY_DRIVER
7094 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7095 error("TIOCSPGRP failed, errno=%d\n", errno);
7097 if (tcsetpgrp(2, mypgrp) < 0)
7098 error("tcsetpgrp failed, errno=%d\n", errno);
7101 if (jp->state == JOBSTOPPED)
7102 curjob = jp - jobtab + 1;
7104 status = jp->ps[jp->nprocs - 1].status;
7105 /* convert to 8 bits */
7106 if (WIFEXITED(status))
7107 st = WEXITSTATUS(status);
7109 else if (WIFSTOPPED(status))
7110 st = WSTOPSIG(status) + 128;
7113 st = WTERMSIG(status) + 128;
7117 * This is truly gross.
7118 * If we're doing job control, then we did a TIOCSPGRP which
7119 * caused us (the shell) to no longer be in the controlling
7120 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7121 * intuit from the subprocess exit status whether a SIGINT
7122 * occured, and if so interrupt ourselves. Yuck. - mycroft
7124 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7127 if (jp->state == JOBDONE)
7138 * Wait for a process to terminate.
7142 * Do a wait system call. If job control is compiled in, we accept
7143 * stopped processes. If block is zero, we return a value of zero
7144 * rather than blocking.
7146 * System V doesn't have a non-blocking wait system call. It does
7147 * have a SIGCLD signal that is sent to a process when one of it's
7148 * children dies. The obvious way to use SIGCLD would be to install
7149 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7150 * was received, and have waitproc bump another counter when it got
7151 * the status of a process. Waitproc would then know that a wait
7152 * system call would not block if the two counters were different.
7153 * This approach doesn't work because if a process has children that
7154 * have not been waited for, System V will send it a SIGCLD when it
7155 * installs a signal handler for SIGCLD. What this means is that when
7156 * a child exits, the shell will be sent SIGCLD signals continuously
7157 * until is runs out of stack space, unless it does a wait call before
7158 * restoring the signal handler. The code below takes advantage of
7159 * this (mis)feature by installing a signal handler for SIGCLD and
7160 * then checking to see whether it was called. If there are any
7161 * children to be waited for, it will be.
7166 waitproc(int block, int *status)
7177 return wait3(status, flags, (struct rusage *)NULL);
7181 dowait(int block, struct job *job)
7185 struct procstat *sp;
7187 struct job *thisjob;
7193 TRACE(("dowait(%d) called\n", block));
7195 pid = waitproc(block, &status);
7196 TRACE(("wait returns %d, status=%d\n", pid, status));
7197 } while (!(block & 2) && pid == -1 && errno == EINTR);
7202 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7206 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7209 if (sp->pid == pid) {
7210 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7211 sp->status = status;
7214 if (sp->status == -1)
7216 else if (WIFSTOPPED(sp->status))
7219 if (stopped) { /* stopped or done */
7220 int state = done? JOBDONE : JOBSTOPPED;
7221 if (jp->state != state) {
7222 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7225 if (done && curjob == jp - jobtab + 1)
7226 curjob = 0; /* no current job */
7233 if (! rootshell || ! iflag || (job && thisjob == job)) {
7234 core = WCOREDUMP(status);
7236 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7239 if (WIFEXITED(status)) sig = 0;
7240 else sig = WTERMSIG(status);
7242 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7244 out2fmt("%d: ", pid);
7246 if (sig == SIGTSTP && rootshell && iflag)
7248 (long)(job - jobtab + 1));
7250 if (sig < NSIG && sys_siglist[sig])
7251 out2str(sys_siglist[sig]);
7253 out2fmt("Signal %d", sig);
7255 out2str(" - core dumped");
7258 TRACE(("Not printing status: status=%d, sig=%d\n",
7262 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7264 thisjob->changed = 1;
7273 * return 1 if there are stopped jobs, otherwise 0
7283 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7286 if (jp->state == JOBSTOPPED) {
7287 out2str("You have stopped jobs.\n");
7297 * Return a string identifying a command (to be printed by the
7301 static char *cmdnextc;
7302 static int cmdnleft;
7303 #define MAXCMDTEXT 200
7306 cmdputs(const char *s)
7317 while ((c = *p++) != '\0') {
7320 else if (c == CTLVAR) {
7325 } else if (c == '=' && subtype != 0) {
7326 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7328 } else if (c == CTLENDVAR) {
7330 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7331 cmdnleft++; /* ignore it */
7334 if (--cmdnleft <= 0) {
7346 cmdtxt(const union node *n)
7349 struct nodelist *lp;
7358 cmdtxt(n->nbinary.ch1);
7360 cmdtxt(n->nbinary.ch2);
7363 cmdtxt(n->nbinary.ch1);
7365 cmdtxt(n->nbinary.ch2);
7368 cmdtxt(n->nbinary.ch1);
7370 cmdtxt(n->nbinary.ch2);
7373 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7381 cmdtxt(n->nredir.n);
7386 cmdtxt(n->nredir.n);
7390 cmdtxt(n->nif.test);
7392 cmdtxt(n->nif.ifpart);
7401 cmdtxt(n->nbinary.ch1);
7403 cmdtxt(n->nbinary.ch2);
7408 cmdputs(n->nfor.var);
7413 cmdputs(n->ncase.expr->narg.text);
7417 cmdputs(n->narg.text);
7421 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7426 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7432 cmdputs(n->narg.text);
7435 p = ">"; i = 1; goto redir;
7437 p = ">>"; i = 1; goto redir;
7439 p = ">&"; i = 1; goto redir;
7441 p = ">|"; i = 1; goto redir;
7443 p = "<"; i = 0; goto redir;
7445 p = "<&"; i = 0; goto redir;
7447 p = "<>"; i = 0; goto redir;
7449 if (n->nfile.fd != i) {
7450 s[0] = n->nfile.fd + '0';
7455 if (n->type == NTOFD || n->type == NFROMFD) {
7456 s[0] = n->ndup.dupfd + '0';
7460 cmdtxt(n->nfile.fname);
7475 commandtext(const union node *n)
7479 cmdnextc = name = ckmalloc(MAXCMDTEXT);
7480 cmdnleft = MAXCMDTEXT - 4;
7487 static void waitonint(int sig) {
7492 * Routines to check for mail. (Perhaps make part of main.c?)
7496 #define MAXMBOXES 10
7499 static int nmboxes; /* number of mailboxes */
7500 static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
7505 * Print appropriate message(s) if mail has arrived. If the argument is
7506 * nozero, then the value of MAIL has changed, so we just update the
7517 struct stackmark smark;
7524 setstackmark(&smark);
7525 mpath = mpathset()? mpathval() : mailval();
7526 for (i = 0 ; i < nmboxes ; i++) {
7527 p = padvance(&mpath, nullstr);
7532 for (q = p ; *q ; q++);
7537 q[-1] = '\0'; /* delete trailing '/' */
7538 if (stat(p, &statb) < 0)
7540 if (statb.st_size > mailtime[i] && ! silent) {
7542 pathopt? pathopt : "you have mail");
7544 mailtime[i] = statb.st_size;
7547 popstackmark(&smark);
7553 static short profile_buf[16384];
7557 static void read_profile (const char *);
7558 static void cmdloop (int);
7559 static void options (int);
7560 static void setoption (int, int);
7561 static void procargs (int, char **);
7565 * Main routine. We initialize things, parse the arguments, execute
7566 * profiles if we're a login shell, and then call cmdloop to execute
7567 * commands. The setjmp call sets up the location to jump to when an
7568 * exception occurs. When an exception occurs the variable "state"
7569 * is used to figure out how far we had gotten.
7573 ash_main(argc, argv)
7577 struct jmploc jmploc;
7578 struct stackmark smark;
7582 BLTINCMD = find_builtin("builtin");
7583 EXECCMD = find_builtin("exec");
7584 EVALCMD = find_builtin("eval");
7586 #ifndef BB_FEATURE_SH_FANCY_PROMPT
7592 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7594 #if defined(linux) || defined(__GNU__)
7595 signal(SIGCHLD, SIG_DFL);
7598 if (setjmp(jmploc.loc)) {
7601 * When a shell procedure is executed, we raise the
7602 * exception EXSHELLPROC to clean up before executing
7603 * the shell procedure.
7605 switch (exception) {
7614 exitstatus = exerrno;
7625 if (exception != EXSHELLPROC) {
7626 if (state == 0 || iflag == 0 || ! rootshell)
7627 exitshell(exitstatus);
7630 if (exception == EXINT) {
7633 popstackmark(&smark);
7634 FORCEINTON; /* enable interrupts */
7637 else if (state == 2)
7639 else if (state == 3)
7647 trputs("Shell args: "); trargs(argv);
7652 setstackmark(&smark);
7653 procargs(argc, argv);
7654 if (argv[0] && argv[0][0] == '-') {
7656 read_profile("/etc/profile");
7659 read_profile(".profile");
7664 if (getuid() == geteuid() && getgid() == getegid()) {
7666 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7668 read_profile(shinit);
7675 if (sflag == 0 || minusc) {
7676 static int sigs[] = {
7677 SIGINT, SIGQUIT, SIGHUP,
7683 #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
7686 for (i = 0; i < SIGSSIZE; i++)
7691 evalstring(minusc, 0);
7693 if (sflag || minusc == NULL) {
7694 state4: /* XXX ??? - why isn't this before the "if" statement */
7700 exitshell(exitstatus);
7706 * Read and execute commands. "Top" is nonzero for the top level command
7707 * loop; it turns on prompting if the shell is interactive.
7714 struct stackmark smark;
7718 TRACE(("cmdloop(%d) called\n", top));
7719 setstackmark(&smark);
7730 n = parsecmd(inter);
7731 /* showtree(n); DEBUG */
7733 if (!top || numeof >= 50)
7735 if (!stoppedjobs()) {
7738 out2str("\nUse \"exit\" to leave shell.\n");
7741 } else if (n != NULL && nflag == 0) {
7742 job_warning = (job_warning == 2) ? 1 : 0;
7746 popstackmark(&smark);
7747 setstackmark(&smark);
7748 if (evalskip == SKIPFILE) {
7753 popstackmark(&smark);
7759 * Read /etc/profile or .profile. Return on error.
7771 if ((fd = open(name, O_RDONLY)) >= 0)
7776 /* -q turns off -x and -v just when executing init files */
7779 xflag = 0, xflag_set = 1;
7781 vflag = 0, vflag_set = 1;
7796 * Read a file containing shell functions.
7800 readcmdfile(const char *name)
7805 if ((fd = open(name, O_RDONLY)) >= 0)
7808 error("Can't open %s", name);
7817 * Take commands from a file. To be compatable we should do a path
7818 * search for the file, which is necessary to find sub-commands.
7822 static inline char *
7823 find_dot_file(mybasename)
7827 const char *path = pathval();
7830 /* don't try this for absolute or relative paths */
7831 if (strchr(mybasename, '/'))
7834 while ((fullname = padvance(&path, mybasename)) != NULL) {
7835 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7837 * Don't bother freeing here, since it will
7838 * be freed by the caller.
7842 stunalloc(fullname);
7845 /* not found in the PATH */
7846 error("%s: not found", mybasename);
7858 for (sp = cmdenviron; sp ; sp = sp->next)
7859 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7861 if (argc >= 2) { /* That's what SVR2 does */
7863 struct stackmark smark;
7865 setstackmark(&smark);
7866 fullname = find_dot_file(argv[1]);
7867 setinputfile(fullname, 1);
7868 commandname = fullname;
7871 popstackmark(&smark);
7885 exitstatus = number(argv[1]);
7887 exitstatus = oexitstatus;
7888 exitshell(exitstatus);
7897 nbytes = ALIGN(nbytes);
7898 if (nbytes > stacknleft) {
7900 struct stack_block *sp;
7903 if (blocksize < MINSIZE)
7904 blocksize = MINSIZE;
7906 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7908 stacknxt = sp->space;
7909 stacknleft = blocksize;
7915 stacknleft -= nbytes;
7921 stunalloc(pointer p)
7924 if (p == NULL) { /*DEBUG */
7925 write(2, "stunalloc\n", 10);
7929 if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
7932 stacknleft += stacknxt - (char *)p;
7938 setstackmark(struct stackmark *mark)
7940 mark->stackp = stackp;
7941 mark->stacknxt = stacknxt;
7942 mark->stacknleft = stacknleft;
7943 mark->marknext = markp;
7949 popstackmark(struct stackmark *mark)
7951 struct stack_block *sp;
7954 markp = mark->marknext;
7955 while (stackp != mark->stackp) {
7960 stacknxt = mark->stacknxt;
7961 stacknleft = mark->stacknleft;
7967 * When the parser reads in a string, it wants to stick the string on the
7968 * stack and only adjust the stack pointer when it knows how big the
7969 * string is. Stackblock (defined in stack.h) returns a pointer to a block
7970 * of space on top of the stack and stackblocklen returns the length of
7971 * this block. Growstackblock will grow this space by at least one byte,
7972 * possibly moving it (like realloc). Grabstackblock actually allocates the
7973 * part of the block that has been used.
7977 growstackblock(void) {
7979 int newlen = ALIGN(stacknleft * 2 + 100);
7980 char *oldspace = stacknxt;
7981 int oldlen = stacknleft;
7982 struct stack_block *sp;
7983 struct stack_block *oldstackp;
7985 if (stacknxt == stackp->space && stackp != &stackbase) {
7990 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
7993 stacknxt = sp->space;
7994 stacknleft = newlen;
7996 /* Stack marks pointing to the start of the old block
7997 * must be relocated to point to the new block
7999 struct stackmark *xmark;
8001 while (xmark != NULL && xmark->stackp == oldstackp) {
8002 xmark->stackp = stackp;
8003 xmark->stacknxt = stacknxt;
8004 xmark->stacknleft = stacknleft;
8005 xmark = xmark->marknext;
8010 p = stalloc(newlen);
8011 memcpy(p, oldspace, oldlen);
8012 stacknxt = p; /* free the space */
8013 stacknleft += newlen; /* we just allocated */
8020 grabstackblock(int len)
8030 * The following routines are somewhat easier to use that the above.
8031 * The user declares a variable of type STACKSTR, which may be declared
8032 * to be a register. The macro STARTSTACKSTR initializes things. Then
8033 * the user uses the macro STPUTC to add characters to the string. In
8034 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8035 * grown as necessary. When the user is done, she can just leave the
8036 * string there and refer to it using stackblock(). Or she can allocate
8037 * the space for it using grabstackstr(). If it is necessary to allow
8038 * someone else to use the stack temporarily and then continue to grow
8039 * the string, the user should use grabstack to allocate the space, and
8040 * then call ungrabstr(p) to return to the previous mode of operation.
8042 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8043 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8044 * is space for at least one character.
8049 growstackstr(void) {
8050 int len = stackblocksize();
8051 if (herefd >= 0 && len >= 1024) {
8052 xwrite(herefd, stackblock(), len);
8053 sstrnleft = len - 1;
8054 return stackblock();
8057 sstrnleft = stackblocksize() - len - 1;
8058 return stackblock() + len;
8063 * Called from CHECKSTRSPACE.
8067 makestrspace(size_t newlen) {
8068 int len = stackblocksize() - sstrnleft;
8071 sstrnleft = stackblocksize() - len;
8072 } while (sstrnleft < newlen);
8073 return stackblock() + len;
8079 ungrabstackstr(char *s, char *p)
8081 stacknleft += stacknxt - s;
8083 sstrnleft = stacknleft - (p - s);
8086 * Miscelaneous builtins.
8093 static mode_t getmode(const void *, mode_t);
8094 static void *setmode(const char *);
8097 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8098 typedef long rlim_t;
8104 * The read builtin. The -e option causes backslashes to escape the
8105 * following character.
8107 * This uses unbuffered input, which may be avoidable in some cases.
8128 while ((i = nextopt("p:r")) != '\0') {
8134 if (prompt && isatty(0)) {
8138 if (*(ap = argptr) == NULL)
8140 if ((ifs = bltinlookup("IFS")) == NULL)
8147 if (read(0, &c, 1) != 1) {
8159 if (!rflag && c == '\\') {
8165 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8169 if (backslash && c == '\\') {
8170 if (read(0, &c, 1) != 1) {
8175 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8177 setvar(*ap, stackblock(), 0);
8186 /* Remove trailing blanks */
8187 while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8189 setvar(*ap, stackblock(), 0);
8190 while (*++ap != NULL)
8191 setvar(*ap, nullstr, 0);
8198 umaskcmd(argc, argv)
8205 int symbolic_mode = 0;
8207 while (nextopt("S") != '\0') {
8216 if ((ap = *argptr) == NULL) {
8217 if (symbolic_mode) {
8218 char u[4], g[4], o[4];
8221 if ((mask & S_IRUSR) == 0)
8223 if ((mask & S_IWUSR) == 0)
8225 if ((mask & S_IXUSR) == 0)
8230 if ((mask & S_IRGRP) == 0)
8232 if ((mask & S_IWGRP) == 0)
8234 if ((mask & S_IXGRP) == 0)
8239 if ((mask & S_IROTH) == 0)
8241 if ((mask & S_IWOTH) == 0)
8243 if ((mask & S_IXOTH) == 0)
8247 printf("u=%s,g=%s,o=%s\n", u, g, o);
8249 printf("%.4o\n", mask);
8252 if (is_digit((unsigned char)*ap)) {
8255 if (*ap >= '8' || *ap < '0')
8256 error("Illegal number: %s", argv[1]);
8257 mask = (mask << 3) + (*ap - '0');
8258 } while (*++ap != '\0');
8264 if ((set = setmode(ap)) != 0) {
8265 mask = getmode(set, ~mask & 0777);
8270 error("Illegal mode: %s", ap);
8272 umask(~mask & 0777);
8281 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8282 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8283 * ash by J.T. Conklin.
8291 int factor; /* multiply by to get rlim_{cur,max} values */
8295 static const struct limits limits[] = {
8297 { "time(seconds)", RLIMIT_CPU, 1, 't' },
8300 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
8303 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
8306 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
8309 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
8312 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
8314 #ifdef RLIMIT_MEMLOCK
8315 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
8318 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
8320 #ifdef RLIMIT_NOFILE
8321 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
8324 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
8327 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
8329 { (char *) 0, 0, 0, '\0' }
8333 ulimitcmd(argc, argv)
8339 enum { SOFT = 0x1, HARD = 0x2 }
8341 const struct limits *l;
8344 struct rlimit limit;
8347 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
8362 for (l = limits; l->name && l->option != what; l++)
8365 error("internal error (%c)", what);
8367 set = *argptr ? 1 : 0;
8371 if (all || argptr[1])
8372 error("too many arguments");
8373 if (strcmp(p, "unlimited") == 0)
8374 val = RLIM_INFINITY;
8378 while ((c = *p++) >= '0' && c <= '9')
8380 val = (val * 10) + (long)(c - '0');
8381 if (val < (rlim_t) 0)
8385 error("bad number");
8390 for (l = limits; l->name; l++) {
8391 getrlimit(l->cmd, &limit);
8393 val = limit.rlim_cur;
8394 else if (how & HARD)
8395 val = limit.rlim_max;
8397 printf("%-20s ", l->name);
8398 if (val == RLIM_INFINITY)
8399 printf("unlimited\n");
8403 printf("%lld\n", (long long) val);
8409 getrlimit(l->cmd, &limit);
8412 limit.rlim_max = val;
8414 limit.rlim_cur = val;
8415 if (setrlimit(l->cmd, &limit) < 0)
8416 error("error setting limit (%m)");
8419 val = limit.rlim_cur;
8420 else if (how & HARD)
8421 val = limit.rlim_max;
8423 if (val == RLIM_INFINITY)
8424 printf("unlimited\n");
8428 printf("%lld\n", (long long) val);
8434 * prefix -- see if pfx is a prefix of string.
8438 prefix(char const *pfx, char const *string)
8441 if (*pfx++ != *string++)
8448 * Return true if s is a string of digits, and save munber in intptr
8453 is_number(const char *p, int *intptr)
8461 ret += digit_val(*p);
8463 } while (*p != '\0');
8470 * Convert a string of digits to an integer, printing an error message on
8475 number(const char *s)
8478 if (! is_number(s, &i))
8479 error("Illegal number: %s", s);
8484 * Produce a possibly single quoted string suitable as input to the shell.
8485 * The return string is allocated on the stack.
8489 single_quote(const char *s) {
8496 size_t len1, len1p, len2, len2p;
8498 len1 = strcspn(s, "'");
8499 len2 = strspn(s + len1, "'");
8501 len1p = len1 ? len1 + 2 : len1;
8513 CHECKSTRSPACE(len1p + len2p + 1, p);
8518 memcpy(p + 1, s, len1);
8534 memcpy(q + 1, s, len2);
8539 STADJUST(len1p + len2p, p);
8544 return grabstackstr(p);
8548 * Like strdup but works with the ash stack.
8552 sstrdup(const char *p)
8554 size_t len = strlen(p) + 1;
8555 return memcpy(stalloc(len), p, len);
8560 * Routine for dealing with parsed shell commands.
8564 static void sizenodelist (const struct nodelist *);
8565 static struct nodelist *copynodelist (const struct nodelist *);
8566 static char *nodesavestr (const char *);
8569 calcsize(const union node *n)
8573 funcblocksize += nodesize[n->type];
8580 calcsize(n->nbinary.ch2);
8581 calcsize(n->nbinary.ch1);
8584 calcsize(n->ncmd.redirect);
8585 calcsize(n->ncmd.args);
8586 calcsize(n->ncmd.assign);
8589 sizenodelist(n->npipe.cmdlist);
8594 calcsize(n->nredir.redirect);
8595 calcsize(n->nredir.n);
8598 calcsize(n->nif.elsepart);
8599 calcsize(n->nif.ifpart);
8600 calcsize(n->nif.test);
8603 funcstringsize += strlen(n->nfor.var) + 1;
8604 calcsize(n->nfor.body);
8605 calcsize(n->nfor.args);
8608 calcsize(n->ncase.cases);
8609 calcsize(n->ncase.expr);
8612 calcsize(n->nclist.body);
8613 calcsize(n->nclist.pattern);
8614 calcsize(n->nclist.next);
8618 sizenodelist(n->narg.backquote);
8619 funcstringsize += strlen(n->narg.text) + 1;
8620 calcsize(n->narg.next);
8627 calcsize(n->nfile.fname);
8628 calcsize(n->nfile.next);
8632 calcsize(n->ndup.vname);
8633 calcsize(n->ndup.next);
8637 calcsize(n->nhere.doc);
8638 calcsize(n->nhere.next);
8641 calcsize(n->nnot.com);
8647 sizenodelist(const struct nodelist *lp)
8650 funcblocksize += ALIGN(sizeof(struct nodelist));
8658 copynode(const union node *n)
8665 funcblock = (char *) funcblock + nodesize[n->type];
8672 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8673 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8676 new->ncmd.redirect = copynode(n->ncmd.redirect);
8677 new->ncmd.args = copynode(n->ncmd.args);
8678 new->ncmd.assign = copynode(n->ncmd.assign);
8679 new->ncmd.backgnd = n->ncmd.backgnd;
8682 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8683 new->npipe.backgnd = n->npipe.backgnd;
8688 new->nredir.redirect = copynode(n->nredir.redirect);
8689 new->nredir.n = copynode(n->nredir.n);
8692 new->nif.elsepart = copynode(n->nif.elsepart);
8693 new->nif.ifpart = copynode(n->nif.ifpart);
8694 new->nif.test = copynode(n->nif.test);
8697 new->nfor.var = nodesavestr(n->nfor.var);
8698 new->nfor.body = copynode(n->nfor.body);
8699 new->nfor.args = copynode(n->nfor.args);
8702 new->ncase.cases = copynode(n->ncase.cases);
8703 new->ncase.expr = copynode(n->ncase.expr);
8706 new->nclist.body = copynode(n->nclist.body);
8707 new->nclist.pattern = copynode(n->nclist.pattern);
8708 new->nclist.next = copynode(n->nclist.next);
8712 new->narg.backquote = copynodelist(n->narg.backquote);
8713 new->narg.text = nodesavestr(n->narg.text);
8714 new->narg.next = copynode(n->narg.next);
8721 new->nfile.fname = copynode(n->nfile.fname);
8722 new->nfile.fd = n->nfile.fd;
8723 new->nfile.next = copynode(n->nfile.next);
8727 new->ndup.vname = copynode(n->ndup.vname);
8728 new->ndup.dupfd = n->ndup.dupfd;
8729 new->ndup.fd = n->ndup.fd;
8730 new->ndup.next = copynode(n->ndup.next);
8734 new->nhere.doc = copynode(n->nhere.doc);
8735 new->nhere.fd = n->nhere.fd;
8736 new->nhere.next = copynode(n->nhere.next);
8739 new->nnot.com = copynode(n->nnot.com);
8742 new->type = n->type;
8747 static struct nodelist *
8748 copynodelist(const struct nodelist *lp)
8750 struct nodelist *start;
8751 struct nodelist **lpp;
8756 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8757 (*lpp)->n = copynode(lp->n);
8759 lpp = &(*lpp)->next;
8767 nodesavestr(const char *s)
8770 char *q = funcstring;
8771 char *rtn = funcstring;
8773 while ((*q++ = *p++) != '\0')
8780 static int getopts (char *, char *, char **, int *, int *);
8785 * Process the shell command line arguments.
8789 procargs(argc, argv)
8798 for (i = 0; i < NOPTS; i++)
8801 if (*argptr == NULL && minusc == NULL)
8803 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8807 for (i = 0; i < NOPTS; i++)
8808 if (optent_val(i) == 2)
8811 if (sflag == 0 && minusc == NULL) {
8812 commandname = argv[0];
8814 setinputfile(arg0, 0);
8817 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8818 if (argptr && minusc && *argptr)
8821 shellparam.p = argptr;
8822 shellparam.optind = 1;
8823 shellparam.optoff = -1;
8824 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8826 shellparam.nparam++;
8835 * Process shell options. The global variable argptr contains a pointer
8836 * to the argument list; we advance it past the options.
8840 minus_o(const char *name, int val)
8845 out1str("Current option settings\n");
8846 for (i = 0; i < NOPTS; i++)
8847 printf("%-16s%s\n", optent_name(optlist[i]),
8848 optent_val(i) ? "on" : "off");
8850 for (i = 0; i < NOPTS; i++)
8851 if (equal(name, optent_name(optlist[i]))) {
8852 setoption(optent_letter(optlist[i]), val);
8855 error("Illegal option -o %s", name);
8861 options(int cmdline)
8869 while ((p = *argptr) != NULL) {
8871 if ((c = *p++) == '-') {
8873 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8875 /* "-" means turn off -x and -v */
8878 /* "--" means reset params */
8879 else if (*argptr == NULL)
8882 break; /* "-" or "--" terminates options */
8884 } else if (c == '+') {
8890 while ((c = *p++) != '\0') {
8891 if (c == 'c' && cmdline) {
8893 #ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
8897 if (q == NULL || minusc != NULL)
8898 error("Bad -c option");
8903 } else if (c == 'o') {
8904 minus_o(*argptr, val);
8916 setoption(int flag, int val)
8920 for (i = 0; i < NOPTS; i++)
8921 if (optent_letter(optlist[i]) == flag) {
8922 optent_val(i) = val;
8924 /* #%$ hack for ksh semantics */
8927 else if (flag == 'E')
8932 error("Illegal option -%c", flag);
8939 * Set the shell parameters.
8943 setparam(char **argv)
8949 for (nparam = 0 ; argv[nparam] ; nparam++);
8950 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8952 *ap++ = savestr(*argv++);
8955 freeparam(&shellparam);
8956 shellparam.malloc = 1;
8957 shellparam.nparam = nparam;
8958 shellparam.p = newparam;
8959 shellparam.optind = 1;
8960 shellparam.optoff = -1;
8965 * Free the list of positional parameters.
8969 freeparam(volatile struct shparam *param)
8973 if (param->malloc) {
8974 for (ap = param->p ; *ap ; ap++)
8983 * The shift builtin command.
8987 shiftcmd(argc, argv)
8996 n = number(argv[1]);
8997 if (n > shellparam.nparam)
8998 error("can't shift that many");
9000 shellparam.nparam -= n;
9001 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9002 if (shellparam.malloc)
9006 while ((*ap2++ = *ap1++) != NULL);
9007 shellparam.optind = 1;
9008 shellparam.optoff = -1;
9016 * The set command builtin.
9025 return showvarscmd(argc, argv);
9029 if (*argptr != NULL) {
9038 getoptsreset(const char *value)
9040 shellparam.optind = number(value);
9041 shellparam.optoff = -1;
9044 #ifdef BB_LOCALE_SUPPORT
9045 static void change_lc_all(const char *value)
9047 if(value != 0 && *value != 0)
9048 setlocale(LC_ALL, value);
9051 static void change_lc_ctype(const char *value)
9053 if(value != 0 && *value != 0)
9054 setlocale(LC_CTYPE, value);
9061 * The getopts builtin. Shellparam.optnext points to the next argument
9062 * to be processed. Shellparam.optptr points to the next character to
9063 * be processed in the current argument. If shellparam.optnext is NULL,
9064 * then it's the first time getopts has been called.
9068 getoptscmd(argc, argv)
9075 error("Usage: getopts optstring var [arg]");
9076 else if (argc == 3) {
9077 optbase = shellparam.p;
9078 if (shellparam.optind > shellparam.nparam + 1) {
9079 shellparam.optind = 1;
9080 shellparam.optoff = -1;
9085 if (shellparam.optind > argc - 2) {
9086 shellparam.optind = 1;
9087 shellparam.optoff = -1;
9091 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9092 &shellparam.optoff);
9096 * Safe version of setvar, returns 1 on success 0 on failure.
9100 setvarsafe(name, val, flags)
9101 const char *name, *val;
9104 struct jmploc jmploc;
9105 struct jmploc *volatile savehandler = handler;
9111 if (setjmp(jmploc.loc))
9115 setvar(name, val, flags);
9117 handler = savehandler;
9122 getopts(optstr, optvar, optfirst, myoptind, optoff)
9134 char **optnext = optfirst + *myoptind - 1;
9136 if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9137 strlen(*(optnext - 1)) < *optoff)
9140 p = *(optnext - 1) + *optoff;
9141 if (p == NULL || *p == '\0') {
9142 /* Current word is done, advance */
9143 if (optnext == NULL)
9146 if (p == NULL || *p != '-' || *++p == '\0') {
9148 *myoptind = optnext - optfirst + 1;
9154 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9159 for (q = optstr; *q != c; ) {
9161 if (optstr[0] == ':') {
9164 err |= setvarsafe("OPTARG", s, 0);
9167 out2fmt("Illegal option -%c\n", c);
9168 (void) unsetvar("OPTARG");
9178 if (*p == '\0' && (p = *optnext) == NULL) {
9179 if (optstr[0] == ':') {
9182 err |= setvarsafe("OPTARG", s, 0);
9186 out2fmt("No arg for -%c option\n", c);
9187 (void) unsetvar("OPTARG");
9195 setvarsafe("OPTARG", p, 0);
9199 setvarsafe("OPTARG", "", 0);
9200 *myoptind = optnext - optfirst + 1;
9207 *optoff = p ? p - *(optnext - 1) : -1;
9208 snprintf(s, sizeof(s), "%d", *myoptind);
9209 err |= setvarsafe("OPTIND", s, VNOFUNC);
9212 err |= setvarsafe(optvar, s, 0);
9223 * XXX - should get rid of. have all builtins use getopt(3). the
9224 * library getopt must have the BSD extension static variable "optreset"
9225 * otherwise it can't be used within the shell safely.
9227 * Standard option processing (a la getopt) for builtin routines. The
9228 * only argument that is passed to nextopt is the option string; the
9229 * other arguments are unnecessary. It return the character, or '\0' on
9234 nextopt(const char *optstring)
9240 if ((p = optptr) == NULL || *p == '\0') {
9242 if (p == NULL || *p != '-' || *++p == '\0')
9245 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9249 for (q = optstring ; *q != c ; ) {
9251 error("Illegal option -%c", c);
9256 if (*p == '\0' && (p = *argptr++) == NULL)
9257 error("No arg for -%c option", c);
9274 out2fmt(const char *fmt, ...)
9278 vfprintf(stderr, fmt, ap);
9283 * Version of write which resumes after a signal is caught.
9287 xwrite(int fd, const char *buf, int nbytes)
9296 i = write(fd, buf, n);
9302 } else if (i == 0) {
9305 } else if (errno != EINTR) {
9313 * Shell command parser.
9316 #define EOFMARKLEN 79
9321 struct heredoc *next; /* next here document in list */
9322 union node *here; /* redirection node */
9323 char *eofmark; /* string indicating end of input */
9324 int striptabs; /* if set, strip leading tabs */
9327 static struct heredoc *heredoclist; /* list of here documents to read */
9328 static int parsebackquote; /* nonzero if we are inside backquotes */
9329 static int doprompt; /* if set, prompt the user */
9330 static int needprompt; /* true if interactive and at start of line */
9331 static int lasttoken; /* last token read */
9333 static char *wordtext; /* text of last word returned by readtoken */
9335 static struct nodelist *backquotelist;
9336 static union node *redirnode;
9337 static struct heredoc *heredoc;
9338 static int quoteflag; /* set if (part of) last token was quoted */
9339 static int startlinno; /* line # where last token started */
9342 static union node *list (int);
9343 static union node *andor (void);
9344 static union node *pipeline (void);
9345 static union node *command (void);
9346 static union node *simplecmd (void);
9347 static void parsefname (void);
9348 static void parseheredoc (void);
9349 static int peektoken (void);
9350 static int readtoken (void);
9351 static int xxreadtoken (void);
9352 static int readtoken1 (int, char const *, char *, int);
9353 static int noexpand (char *);
9354 static void synexpect (int) __attribute__((noreturn));
9355 static void synerror (const char *) __attribute__((noreturn));
9356 static void setprompt (int);
9360 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9361 * valid parse tree indicating a blank line.)
9365 parsecmd(int interact)
9370 doprompt = interact;
9390 union node *n1, *n2, *n3;
9394 if (nlflag == 0 && tokendlist[peektoken()])
9400 if (tok == TBACKGND) {
9401 if (n2->type == NCMD || n2->type == NPIPE) {
9402 n2->ncmd.backgnd = 1;
9403 } else if (n2->type == NREDIR) {
9404 n2->type = NBACKGND;
9406 n3 = (union node *)stalloc(sizeof (struct nredir));
9407 n3->type = NBACKGND;
9409 n3->nredir.redirect = NULL;
9417 n3 = (union node *)stalloc(sizeof (struct nbinary));
9419 n3->nbinary.ch1 = n1;
9420 n3->nbinary.ch2 = n2;
9437 if (tokendlist[peektoken()])
9444 pungetc(); /* push back EOF on input */
9459 union node *n1, *n2, *n3;
9465 if ((t = readtoken()) == TAND) {
9467 } else if (t == TOR) {
9475 n3 = (union node *)stalloc(sizeof (struct nbinary));
9477 n3->nbinary.ch1 = n1;
9478 n3->nbinary.ch2 = n2;
9487 union node *n1, *n2, *pipenode;
9488 struct nodelist *lp, *prev;
9492 TRACE(("pipeline: entered\n"));
9493 if (readtoken() == TNOT) {
9499 if (readtoken() == TPIPE) {
9500 pipenode = (union node *)stalloc(sizeof (struct npipe));
9501 pipenode->type = NPIPE;
9502 pipenode->npipe.backgnd = 0;
9503 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9504 pipenode->npipe.cmdlist = lp;
9508 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9512 } while (readtoken() == TPIPE);
9518 n2 = (union node *)stalloc(sizeof (struct nnot));
9530 union node *n1, *n2;
9531 union node *ap, **app;
9532 union node *cp, **cpp;
9533 union node *redir, **rpp;
9540 switch (readtoken()) {
9542 n1 = (union node *)stalloc(sizeof (struct nif));
9544 n1->nif.test = list(0);
9545 if (readtoken() != TTHEN)
9547 n1->nif.ifpart = list(0);
9549 while (readtoken() == TELIF) {
9550 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9551 n2 = n2->nif.elsepart;
9553 n2->nif.test = list(0);
9554 if (readtoken() != TTHEN)
9556 n2->nif.ifpart = list(0);
9558 if (lasttoken == TELSE)
9559 n2->nif.elsepart = list(0);
9561 n2->nif.elsepart = NULL;
9564 if (readtoken() != TFI)
9571 n1 = (union node *)stalloc(sizeof (struct nbinary));
9572 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9573 n1->nbinary.ch1 = list(0);
9574 if ((got=readtoken()) != TDO) {
9575 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
9578 n1->nbinary.ch2 = list(0);
9579 if (readtoken() != TDONE)
9585 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9586 synerror("Bad for loop variable");
9587 n1 = (union node *)stalloc(sizeof (struct nfor));
9589 n1->nfor.var = wordtext;
9591 if (readtoken() == TIN) {
9593 while (readtoken() == TWORD) {
9594 n2 = (union node *)stalloc(sizeof (struct narg));
9596 n2->narg.text = wordtext;
9597 n2->narg.backquote = backquotelist;
9599 app = &n2->narg.next;
9603 if (lasttoken != TNL && lasttoken != TSEMI)
9606 static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9608 n2 = (union node *)stalloc(sizeof (struct narg));
9610 n2->narg.text = argvars;
9611 n2->narg.backquote = NULL;
9612 n2->narg.next = NULL;
9615 * Newline or semicolon here is optional (but note
9616 * that the original Bourne shell only allowed NL).
9618 if (lasttoken != TNL && lasttoken != TSEMI)
9622 if (readtoken() != TDO)
9624 n1->nfor.body = list(0);
9625 if (readtoken() != TDONE)
9630 n1 = (union node *)stalloc(sizeof (struct ncase));
9632 if (readtoken() != TWORD)
9634 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9636 n2->narg.text = wordtext;
9637 n2->narg.backquote = backquotelist;
9638 n2->narg.next = NULL;
9641 } while (readtoken() == TNL);
9642 if (lasttoken != TIN)
9643 synerror("expecting \"in\"");
9644 cpp = &n1->ncase.cases;
9645 checkkwd = 2, readtoken();
9647 if (lasttoken == TLP)
9649 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9651 app = &cp->nclist.pattern;
9653 *app = ap = (union node *)stalloc(sizeof (struct narg));
9655 ap->narg.text = wordtext;
9656 ap->narg.backquote = backquotelist;
9657 if (checkkwd = 2, readtoken() != TPIPE)
9659 app = &ap->narg.next;
9662 ap->narg.next = NULL;
9663 if (lasttoken != TRP)
9665 cp->nclist.body = list(0);
9668 if ((t = readtoken()) != TESAC) {
9670 synexpect(TENDCASE);
9672 checkkwd = 2, readtoken();
9674 cpp = &cp->nclist.next;
9675 } while(lasttoken != TESAC);
9680 n1 = (union node *)stalloc(sizeof (struct nredir));
9681 n1->type = NSUBSHELL;
9682 n1->nredir.n = list(0);
9683 n1->nredir.redirect = NULL;
9684 if (readtoken() != TRP)
9690 if (readtoken() != TEND)
9694 /* Handle an empty command like other simple commands. */
9703 * An empty command before a ; doesn't make much sense, and
9704 * should certainly be disallowed in the case of `if ;'.
9718 /* Now check for redirection which may follow command */
9719 while (readtoken() == TREDIR) {
9720 *rpp = n2 = redirnode;
9721 rpp = &n2->nfile.next;
9727 if (n1->type != NSUBSHELL) {
9728 n2 = (union node *)stalloc(sizeof (struct nredir));
9733 n1->nredir.redirect = redir;
9742 union node *args, **app;
9743 union node *n = NULL;
9744 union node *vars, **vpp;
9745 union node **rpp, *redir;
9756 switch (readtoken()) {
9759 n = (union node *)stalloc(sizeof (struct narg));
9761 n->narg.text = wordtext;
9762 n->narg.backquote = backquotelist;
9763 if (lasttoken == TWORD) {
9765 app = &n->narg.next;
9768 vpp = &n->narg.next;
9772 *rpp = n = redirnode;
9773 rpp = &n->nfile.next;
9774 parsefname(); /* read name of redirection file */
9778 args && app == &args->narg.next &&
9781 /* We have a function */
9782 if (readtoken() != TRP)
9786 n->narg.next = command();
9799 n = (union node *)stalloc(sizeof (struct ncmd));
9801 n->ncmd.backgnd = 0;
9802 n->ncmd.args = args;
9803 n->ncmd.assign = vars;
9804 n->ncmd.redirect = redir;
9812 n = (union node *)stalloc(sizeof (struct narg));
9814 n->narg.next = NULL;
9815 n->narg.text = wordtext;
9816 n->narg.backquote = backquotelist;
9820 static void fixredir(union node *n, const char *text, int err)
9822 TRACE(("Fix redir %s %d\n", text, err));
9824 n->ndup.vname = NULL;
9826 if (is_digit(text[0]) && text[1] == '\0')
9827 n->ndup.dupfd = digit_val(text[0]);
9828 else if (text[0] == '-' && text[1] == '\0')
9833 synerror("Bad fd number");
9835 n->ndup.vname = makename();
9842 union node *n = redirnode;
9844 if (readtoken() != TWORD)
9846 if (n->type == NHERE) {
9847 struct heredoc *here = heredoc;
9853 TRACE(("Here document %d\n", n->type));
9854 if (here->striptabs) {
9855 while (*wordtext == '\t')
9858 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9859 synerror("Illegal eof marker for << redirection");
9860 rmescapes(wordtext);
9861 here->eofmark = wordtext;
9863 if (heredoclist == NULL)
9866 for (p = heredoclist ; p->next ; p = p->next);
9869 } else if (n->type == NTOFD || n->type == NFROMFD) {
9870 fixredir(n, wordtext, 0);
9872 n->nfile.fname = makename();
9878 * Input any here documents.
9883 struct heredoc *here;
9886 while (heredoclist) {
9888 heredoclist = here->next;
9893 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9894 here->eofmark, here->striptabs);
9895 n = (union node *)stalloc(sizeof (struct narg));
9896 n->narg.type = NARG;
9897 n->narg.next = NULL;
9898 n->narg.text = wordtext;
9899 n->narg.backquote = backquotelist;
9900 here->here->nhere.doc = n;
9918 int savecheckalias = checkalias;
9919 int savecheckkwd = checkkwd;
9924 int alreadyseen = tokpushback;
9934 checkalias = savecheckalias;
9941 if (checkkwd == 2) {
9950 * check for keywords
9952 if (t == TWORD && !quoteflag)
9954 const char *const *pp;
9956 if ((pp = findkwd(wordtext))) {
9957 lasttoken = t = pp - parsekwd + KWDOFFSET;
9958 TRACE(("keyword %s recognized\n", tokname[t]));
9969 } else if (checkalias == 2 && isassignment(wordtext)) {
9970 lasttoken = t = TASSIGN;
9972 } else if (checkalias) {
9973 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
9975 pushstring(ap->val, strlen(ap->val), ap);
9977 checkkwd = savecheckkwd;
9986 TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
9988 TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
9995 * Read the next input token.
9996 * If the token is a word, we set backquotelist to the list of cmds in
9997 * backquotes. We set quoteflag to true if any part of the word was
9999 * If the token is TREDIR, then we set redirnode to a structure containing
10001 * In all cases, the variable startlinno is set to the number of the line
10002 * on which the token starts.
10004 * [Change comment: here documents and internal procedures]
10005 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10006 * word parsing code into a separate routine. In this case, readtoken
10007 * doesn't need to have any internal procedures, but parseword does.
10008 * We could also make parseoperator in essence the main routine, and
10009 * have parseword (readtoken1?) handle both words and redirection.]
10012 #define RETURN(token) return lasttoken = token
10026 startlinno = plinno;
10027 for (;;) { /* until token or start of word found */
10030 case ' ': case '\t':
10036 while ((c = pgetc()) != '\n' && c != PEOF);
10040 if (pgetc() == '\n') {
10041 startlinno = ++plinno;
10052 needprompt = doprompt;
10057 if (pgetc() == '&')
10062 if (pgetc() == '|')
10067 if (pgetc() == ';')
10080 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10087 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10088 * is not NULL, read a here document. In the latter case, eofmark is the
10089 * word which marks the end of the document and striptabs is true if
10090 * leading tabs should be stripped from the document. The argument firstc
10091 * is the first character of the input token or document.
10093 * Because C does not have internal subroutines, I have simulated them
10094 * using goto's to implement the subroutine linkage. The following macros
10095 * will run code that appears at the end of readtoken1.
10098 #define CHECKEND() {goto checkend; checkend_return:;}
10099 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10100 #define PARSESUB() {goto parsesub; parsesub_return:;}
10101 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10102 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10103 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10106 readtoken1(firstc, syntax, eofmark, striptabs)
10108 char const *syntax;
10115 char line[EOFMARKLEN + 1];
10116 struct nodelist *bqlist;
10119 int varnest; /* levels of variables expansion */
10120 int arinest; /* levels of arithmetic expansion */
10121 int parenlevel; /* levels of parens in arithmetic */
10122 int dqvarnest; /* levels of variables expansion within double quotes */
10124 char const *prevsyntax; /* syntax before arithmetic */
10126 /* Avoid longjmp clobbering */
10132 (void) &parenlevel;
10135 (void) &prevsyntax;
10139 startlinno = plinno;
10141 if (syntax == DQSYNTAX)
10150 STARTSTACKSTR(out);
10151 loop: { /* for each line, until end of word */
10152 CHECKEND(); /* set c to PEOF if at end of here document */
10153 for (;;) { /* until end of line or end of word */
10154 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10155 switch(syntax[c]) {
10156 case CNL: /* '\n' */
10157 if (syntax == BASESYNTAX)
10158 goto endword; /* exit outer loop */
10166 goto loop; /* continue outer loop */
10171 if ((eofmark == NULL || dblquote) &&
10173 USTPUTC(CTLESC, out);
10176 case CBACK: /* backslash */
10179 USTPUTC('\\', out);
10181 } else if (c == '\n') {
10187 if (dblquote && c != '\\' && c != '`' && c != '$'
10188 && (c != '"' || eofmark != NULL))
10189 USTPUTC('\\', out);
10190 if (SQSYNTAX[c] == CCTL)
10191 USTPUTC(CTLESC, out);
10192 else if (eofmark == NULL)
10193 USTPUTC(CTLQUOTEMARK, out);
10199 if (eofmark == NULL)
10200 USTPUTC(CTLQUOTEMARK, out);
10204 if (eofmark == NULL)
10205 USTPUTC(CTLQUOTEMARK, out);
10210 if (eofmark != NULL && arinest == 0 &&
10215 syntax = ARISYNTAX;
10217 } else if (eofmark == NULL &&
10219 syntax = BASESYNTAX;
10225 case CVAR: /* '$' */
10226 PARSESUB(); /* parse substitution */
10228 case CENDVAR: /* '}' */
10231 if (dqvarnest > 0) {
10234 USTPUTC(CTLENDVAR, out);
10239 #ifdef ASH_MATH_SUPPORT
10240 case CLP: /* '(' in arithmetic */
10244 case CRP: /* ')' in arithmetic */
10245 if (parenlevel > 0) {
10249 if (pgetc() == ')') {
10250 if (--arinest == 0) {
10251 USTPUTC(CTLENDARI, out);
10252 syntax = prevsyntax;
10253 if (syntax == DQSYNTAX)
10261 * unbalanced parens
10262 * (don't 2nd guess - no error)
10270 case CBQUOTE: /* '`' */
10274 goto endword; /* exit outer loop */
10279 goto endword; /* exit outer loop */
10290 if (syntax == ARISYNTAX)
10291 synerror("Missing '))'");
10292 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10293 synerror("Unterminated quoted string");
10294 if (varnest != 0) {
10295 startlinno = plinno;
10296 synerror("Missing '}'");
10298 USTPUTC('\0', out);
10299 len = out - stackblock();
10300 out = stackblock();
10301 if (eofmark == NULL) {
10302 if ((c == '>' || c == '<')
10305 && (*out == '\0' || is_digit(*out))) {
10307 return lasttoken = TREDIR;
10312 quoteflag = quotef;
10313 backquotelist = bqlist;
10314 grabstackblock(len);
10316 return lasttoken = TWORD;
10317 /* end of readtoken routine */
10322 * Check to see whether we are at the end of the here document. When this
10323 * is called, c is set to the first character of the next input line. If
10324 * we are at the end of the here document, this routine sets the c to PEOF.
10335 while (c == '\t') {
10339 if (c == *eofmark) {
10340 if (pfgets(line, sizeof line) != NULL) {
10344 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10345 if (*p == '\n' && *q == '\0') {
10348 needprompt = doprompt;
10350 pushstring(line, strlen(line), NULL);
10355 goto checkend_return;
10360 * Parse a redirection operator. The variable "out" points to a string
10361 * specifying the fd to be redirected. The variable "c" contains the
10362 * first character of the redirection operator.
10369 np = (union node *)stalloc(sizeof (struct nfile));
10374 np->type = NAPPEND;
10383 } else { /* c == '<' */
10385 switch (c = pgetc()) {
10387 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10388 np = (union node *)stalloc(sizeof (struct nhere));
10392 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10393 heredoc->here = np;
10394 if ((c = pgetc()) == '-') {
10395 heredoc->striptabs = 1;
10397 heredoc->striptabs = 0;
10403 np->type = NFROMFD;
10407 np->type = NFROMTO;
10417 np->nfile.fd = digit_val(fd);
10419 goto parseredir_return;
10424 * Parse a substitution. At this point, we have read the dollar sign
10425 * and nothing else.
10433 static const char types[] = "}-+?=";
10438 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10442 } else if (c == '(') { /* $(command) or $((arith)) */
10443 if (pgetc() == '(') {
10450 USTPUTC(CTLVAR, out);
10451 typeloc = out - stackblock();
10452 USTPUTC(VSNORMAL, out);
10453 subtype = VSNORMAL;
10457 if ((c = pgetc()) == '}')
10460 subtype = VSLENGTH;
10465 if (c > PEOA && is_name(c)) {
10469 } while (c > PEOA && is_in_name(c));
10470 } else if (is_digit(c)) {
10474 } while (is_digit(c));
10476 else if (is_special(c)) {
10481 badsub: synerror("Bad substitution");
10485 if (subtype == 0) {
10492 p = strchr(types, c);
10495 subtype = p - types + VSNORMAL;
10501 subtype = c == '#' ? VSTRIMLEFT :
10514 if (dblquote || arinest)
10516 *(stackblock() + typeloc) = subtype | flags;
10517 if (subtype != VSNORMAL) {
10524 goto parsesub_return;
10529 * Called to parse command substitutions. Newstyle is set if the command
10530 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10531 * list of commands (passed by reference), and savelen is the number of
10532 * characters on the top of the stack which must be preserved.
10536 struct nodelist **nlpp;
10539 char *volatile str;
10540 struct jmploc jmploc;
10541 struct jmploc *volatile savehandler;
10545 (void) &saveprompt;
10548 savepbq = parsebackquote;
10549 if (setjmp(jmploc.loc)) {
10552 parsebackquote = 0;
10553 handler = savehandler;
10554 longjmp(handler->loc, 1);
10558 savelen = out - stackblock();
10560 str = ckmalloc(savelen);
10561 memcpy(str, stackblock(), savelen);
10563 savehandler = handler;
10567 /* We must read until the closing backquote, giving special
10568 treatment to some slashes, and then push the string and
10569 reread it as input, interpreting it normally. */
10576 STARTSTACKSTR(pout);
10582 switch (pc = pgetc()) {
10587 if ((pc = pgetc()) == '\n') {
10594 * If eating a newline, avoid putting
10595 * the newline into the new character
10596 * stream (via the STPUTC after the
10601 if (pc != '\\' && pc != '`' && pc != '$'
10602 && (!dblquote || pc != '"'))
10603 STPUTC('\\', pout);
10613 startlinno = plinno;
10614 synerror("EOF in backquote substitution");
10618 needprompt = doprompt;
10627 STPUTC('\0', pout);
10628 psavelen = pout - stackblock();
10629 if (psavelen > 0) {
10630 pstr = grabstackstr(pout);
10631 setinputstring(pstr);
10636 nlpp = &(*nlpp)->next;
10637 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10638 (*nlpp)->next = NULL;
10639 parsebackquote = oldstyle;
10642 saveprompt = doprompt;
10649 doprompt = saveprompt;
10651 if (readtoken() != TRP)
10658 * Start reading from old file again, ignoring any pushed back
10659 * tokens left from the backquote parsing
10664 while (stackblocksize() <= savelen)
10666 STARTSTACKSTR(out);
10668 memcpy(out, str, savelen);
10669 STADJUST(savelen, out);
10675 parsebackquote = savepbq;
10676 handler = savehandler;
10677 if (arinest || dblquote)
10678 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10680 USTPUTC(CTLBACKQ, out);
10682 goto parsebackq_oldreturn;
10684 goto parsebackq_newreturn;
10688 * Parse an arithmetic expansion (indicate start of one and set state)
10692 if (++arinest == 1) {
10693 prevsyntax = syntax;
10694 syntax = ARISYNTAX;
10695 USTPUTC(CTLARI, out);
10702 * we collapse embedded arithmetic expansion to
10703 * parenthesis, which should be equivalent
10707 goto parsearith_return;
10710 } /* end of readtoken */
10714 * Returns true if the text contains nothing to expand (no dollar signs
10726 while ((c = *p++) != '\0') {
10727 if (c == CTLQUOTEMARK)
10731 else if (BASESYNTAX[(int)c] == CCTL)
10739 * Return true if the argument is a legal variable name (a letter or
10740 * underscore followed by zero or more letters, underscores, and digits).
10744 goodname(const char *name)
10752 if (! is_in_name(*p))
10760 * Called when an unexpected token is read during the parse. The argument
10761 * is the token that is expected, or -1 if more than one type of token can
10762 * occur at this point.
10772 snprintf(msg, 64, "%s unexpected (expecting %s)",
10773 tokname[lasttoken], tokname[token]);
10775 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
10783 synerror(const char *msg)
10786 out2fmt("%s: %d: ", commandname, startlinno);
10787 out2fmt("Syntax error: %s\n", msg);
10788 error((char *)NULL);
10794 * called by editline -- any expansions to the prompt
10795 * should be added here.
10798 setprompt(int whichprompt)
10801 switch (whichprompt) {
10816 * Code for dealing with input/output redirection.
10819 #define EMPTY -2 /* marks an unused slot in redirtab */
10821 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10823 # define PIPESIZE PIPE_BUF
10828 * Open a file in noclobber mode.
10829 * The code was copied from bash.
10832 noclobberopen(const char *fname)
10835 struct stat finfo, finfo2;
10838 * If the file exists and is a regular file, return an error
10841 r = stat(fname, &finfo);
10842 if (r == 0 && S_ISREG(finfo.st_mode)) {
10848 * If the file was not present (r != 0), make sure we open it
10849 * exclusively so that if it is created before we open it, our open
10850 * will fail. Make sure that we do not truncate an existing file.
10851 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10852 * file was not a regular file, we leave O_EXCL off.
10855 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10856 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10858 /* If the open failed, return the file descriptor right away. */
10863 * OK, the open succeeded, but the file may have been changed from a
10864 * non-regular file to a regular file between the stat and the open.
10865 * We are assuming that the O_EXCL open handles the case where FILENAME
10866 * did not exist and is symlinked to an existing file between the stat
10871 * If we can open it and fstat the file descriptor, and neither check
10872 * revealed that it was a regular file, and the file has not been
10873 * replaced, return the file descriptor.
10875 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10876 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10879 /* The file has been replaced. badness. */
10886 * Handle here documents. Normally we fork off a process to write the
10887 * data to a pipe. If the document is short, we can stuff the data in
10888 * the pipe without forking.
10892 openhere(const union node *redir)
10898 error("Pipe call failed");
10899 if (redir->type == NHERE) {
10900 len = strlen(redir->nhere.doc->narg.text);
10901 if (len <= PIPESIZE) {
10902 xwrite(pip[1], redir->nhere.doc->narg.text, len);
10906 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10908 signal(SIGINT, SIG_IGN);
10909 signal(SIGQUIT, SIG_IGN);
10910 signal(SIGHUP, SIG_IGN);
10912 signal(SIGTSTP, SIG_IGN);
10914 signal(SIGPIPE, SIG_DFL);
10915 if (redir->type == NHERE)
10916 xwrite(pip[1], redir->nhere.doc->narg.text, len);
10918 expandhere(redir->nhere.doc, pip[1]);
10928 openredirect(const union node *redir)
10933 switch (redir->nfile.type) {
10935 fname = redir->nfile.expfname;
10936 if ((f = open(fname, O_RDONLY)) < 0)
10940 fname = redir->nfile.expfname;
10941 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
10945 /* Take care of noclobber mode. */
10947 fname = redir->nfile.expfname;
10948 if ((f = noclobberopen(fname)) < 0)
10953 fname = redir->nfile.expfname;
10955 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
10958 if ((f = creat(fname, 0666)) < 0)
10963 fname = redir->nfile.expfname;
10965 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
10968 if ((f = open(fname, O_WRONLY)) < 0
10969 && (f = creat(fname, 0666)) < 0)
10971 lseek(f, (off_t)0, 2);
10978 /* Fall through to eliminate warning. */
10985 f = openhere(redir);
10991 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
10993 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
10998 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
10999 * old file descriptors are stashed away so that the redirection can be
11000 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11001 * standard output, and the standard error if it becomes a duplicate of
11006 redirect(union node *redir, int flags)
11009 struct redirtab *sv = NULL;
11014 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11016 if (flags & REDIR_PUSH) {
11017 sv = ckmalloc(sizeof (struct redirtab));
11018 for (i = 0 ; i < 10 ; i++)
11019 sv->renamed[i] = EMPTY;
11020 sv->next = redirlist;
11023 for (n = redir ; n ; n = n->nfile.next) {
11026 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11027 n->ndup.dupfd == fd)
11028 continue; /* redirect from/to same file descriptor */
11031 newfd = openredirect(n);
11032 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11035 } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11039 dupredirect(n, newfd, fd1dup);
11049 error("%d: %m", fd);
11055 if (flags & REDIR_PUSH) {
11056 sv->renamed[fd] = i;
11059 } else if (fd != newfd) {
11065 dupredirect(n, newfd, fd1dup);
11072 dupredirect(const union node *redir, int f, int fd1dup)
11074 int fd = redir->nfile.fd;
11078 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11079 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11080 if (redir->ndup.dupfd!=1 || fd1dup!=1)
11081 dup_as_newfd(redir->ndup.dupfd, fd);
11087 dup_as_newfd(f, fd);
11096 * Undo the effects of the last redirection.
11102 struct redirtab *rp = redirlist;
11106 for (i = 0 ; i < 10 ; i++) {
11107 if (rp->renamed[i] != EMPTY) {
11111 if (rp->renamed[i] >= 0) {
11112 dup_as_newfd(rp->renamed[i], i);
11113 close(rp->renamed[i]);
11117 redirlist = rp->next;
11123 * Discard all saved file descriptors.
11128 struct redirtab *rp;
11131 for (rp = redirlist ; rp ; rp = rp->next) {
11132 for (i = 0 ; i < 10 ; i++) {
11133 if (rp->renamed[i] >= 0) {
11134 close(rp->renamed[i]);
11136 rp->renamed[i] = EMPTY;
11143 * Copy a file descriptor to be >= to. Returns -1
11144 * if the source file descriptor is closed, EMPTY if there are no unused
11145 * file descriptors left.
11149 dup_as_newfd(from, to)
11155 newfd = fcntl(from, F_DUPFD, to);
11157 if (errno == EMFILE)
11160 error("%d: %m", from);
11165 /*#ifdef __weak_alias
11166 __weak_alias(getmode,_getmode)
11167 __weak_alias(setmode,_setmode)
11171 #if defined(__GLIBC__) && __GLIBC__ >= 2
11172 #define S_ISTXT __S_ISVTX
11174 #define S_ISTXT S_ISVTX
11178 #define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11179 #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11181 typedef struct bitcmd {
11187 #define CMD2_CLR 0x01
11188 #define CMD2_SET 0x02
11189 #define CMD2_GBITS 0x04
11190 #define CMD2_OBITS 0x08
11191 #define CMD2_UBITS 0x10
11193 static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11194 static void compress_mode (BITCMD *);
11195 #ifdef SETMODE_DEBUG
11196 static void dumpmode (BITCMD *);
11200 * Given the old mode and an array of bitcmd structures, apply the operations
11201 * described in the bitcmd structures to the old mode, and return the new mode.
11202 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11203 * bits) followed by a '+' (set bits).
11206 getmode(bbox, omode)
11211 mode_t clrval, newmode, value;
11213 _DIAGASSERT(bbox != NULL);
11215 set = (const BITCMD *)bbox;
11217 for (value = 0;; set++)
11220 * When copying the user, group or other bits around, we "know"
11221 * where the bits are in the mode so that we can do shifts to
11222 * copy them around. If we don't use shifts, it gets real
11223 * grundgy with lots of single bit checks and bit sets.
11226 value = (newmode & S_IRWXU) >> 6;
11230 value = (newmode & S_IRWXG) >> 3;
11234 value = newmode & S_IRWXO;
11235 common: if (set->cmd2 & CMD2_CLR) {
11237 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11238 if (set->cmd2 & CMD2_UBITS)
11239 newmode &= ~((clrval<<6) & set->bits);
11240 if (set->cmd2 & CMD2_GBITS)
11241 newmode &= ~((clrval<<3) & set->bits);
11242 if (set->cmd2 & CMD2_OBITS)
11243 newmode &= ~(clrval & set->bits);
11245 if (set->cmd2 & CMD2_SET) {
11246 if (set->cmd2 & CMD2_UBITS)
11247 newmode |= (value<<6) & set->bits;
11248 if (set->cmd2 & CMD2_GBITS)
11249 newmode |= (value<<3) & set->bits;
11250 if (set->cmd2 & CMD2_OBITS)
11251 newmode |= value & set->bits;
11256 newmode |= set->bits;
11260 newmode &= ~set->bits;
11264 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11265 newmode |= set->bits;
11270 #ifdef SETMODE_DEBUG
11271 (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11277 #define ADDCMD(a, b, c, d) do { \
11278 if (set >= endset) { \
11280 setlen += SET_LEN_INCR; \
11281 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11282 if (newset == NULL) { \
11286 set = newset + (set - saveset); \
11287 saveset = newset; \
11288 endset = newset + (setlen - 2); \
11290 set = addcmd(set, (a), (b), (c), (d)); \
11291 } while (/*CONSTCOND*/0)
11293 #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11301 BITCMD *set, *saveset, *endset;
11302 sigset_t mysigset, sigoset;
11304 int equalopdone = 0; /* pacify gcc */
11305 int permXbits, setlen;
11311 * Get a copy of the mask for the permissions that are mask relative.
11312 * Flip the bits, we want what's not set. Since it's possible that
11313 * the caller is opening files inside a signal handler, protect them
11316 sigfillset(&mysigset);
11317 (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11318 (void)umask(mask = umask(0));
11320 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11322 setlen = SET_LEN + 2;
11324 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11327 endset = set + (setlen - 2);
11330 * If an absolute number, get it and return; disallow non-octal digits
11333 if (is_digit((unsigned char)*p)) {
11334 perm = (mode_t)strtol(p, &ep, 8);
11335 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11339 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11345 * Build list of structures to set/clear/copy bits as described by
11346 * each clause of the symbolic mode.
11349 /* First, find out which bits might be modified. */
11350 for (who = 0;; ++p) {
11353 who |= STANDARD_BITS;
11356 who |= S_ISUID|S_IRWXU;
11359 who |= S_ISGID|S_IRWXG;
11369 getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11377 for (perm = 0, permXbits = 0;; ++p) {
11380 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11384 * If specific bits where requested and
11385 * only "other" bits ignore set-id.
11387 if (who == 0 || (who & ~S_IRWXO))
11388 perm |= S_ISUID|S_ISGID;
11392 * If specific bits where requested and
11393 * only "other" bits ignore set-id.
11395 if (who == 0 || (who & ~S_IRWXO)) {
11401 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11404 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11407 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11413 * When ever we hit 'u', 'g', or 'o', we have
11414 * to flush out any partial mode that we have,
11415 * and then do the copying of the mode bits.
11418 ADDCMD(op, who, perm, mask);
11423 if (op == '+' && permXbits) {
11424 ADDCMD('X', who, permXbits, mask);
11427 ADDCMD(*p, who, op, mask);
11432 * Add any permissions that we haven't already
11435 if (perm || (op == '=' && !equalopdone)) {
11438 ADDCMD(op, who, perm, mask);
11442 ADDCMD('X', who, permXbits, mask);
11456 #ifdef SETMODE_DEBUG
11457 (void)printf("Before compress_mode()\n");
11460 compress_mode(saveset);
11461 #ifdef SETMODE_DEBUG
11462 (void)printf("After compress_mode()\n");
11469 addcmd(set, op, who, oparg, mask)
11476 _DIAGASSERT(set != NULL);
11481 set->bits = who ? who : STANDARD_BITS;
11490 set->bits = (who ? who : mask) & oparg;
11498 set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11499 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11500 ((who & S_IROTH) ? CMD2_OBITS : 0);
11501 set->bits = (mode_t)~0;
11503 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11508 set->cmd2 |= CMD2_SET;
11509 else if (oparg == '-')
11510 set->cmd2 |= CMD2_CLR;
11511 else if (oparg == '=')
11512 set->cmd2 |= CMD2_SET|CMD2_CLR;
11518 #ifdef SETMODE_DEBUG
11524 _DIAGASSERT(set != NULL);
11526 for (; set->cmd; ++set)
11527 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11528 set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11529 set->cmd2 & CMD2_CLR ? " CLR" : "",
11530 set->cmd2 & CMD2_SET ? " SET" : "",
11531 set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11532 set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11533 set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11538 * Given an array of bitcmd structures, compress by compacting consecutive
11539 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11540 * 'g' and 'o' commands continue to be separate. They could probably be
11541 * compacted, but it's not worth the effort.
11548 int setbits, clrbits, Xbits, op;
11550 _DIAGASSERT(set != NULL);
11552 for (nset = set;;) {
11553 /* Copy over any 'u', 'g' and 'o' commands. */
11554 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11560 for (setbits = clrbits = Xbits = 0;; nset++) {
11561 if ((op = nset->cmd) == '-') {
11562 clrbits |= nset->bits;
11563 setbits &= ~nset->bits;
11564 Xbits &= ~nset->bits;
11565 } else if (op == '+') {
11566 setbits |= nset->bits;
11567 clrbits &= ~nset->bits;
11568 Xbits &= ~nset->bits;
11569 } else if (op == 'X')
11570 Xbits |= nset->bits & ~setbits;
11577 set->bits = clrbits;
11583 set->bits = setbits;
11595 static void shtree (union node *, int, char *, FILE*);
11596 static void shcmd (union node *, FILE *);
11597 static void sharg (union node *, FILE *);
11598 static void indent (int, char *, FILE *);
11599 static void trstring (char *);
11606 trputs("showtree called\n");
11607 shtree(n, 1, NULL, stdout);
11612 shtree(n, ind, pfx, fp)
11618 struct nodelist *lp;
11624 indent(ind, pfx, fp);
11635 shtree(n->nbinary.ch1, ind, NULL, fp);
11638 shtree(n->nbinary.ch2, ind, NULL, fp);
11646 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11651 if (n->npipe.backgnd)
11657 fprintf(fp, "<node type %d>", n->type);
11677 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11683 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11686 switch (np->nfile.type) {
11687 case NTO: s = ">"; dftfd = 1; break;
11688 case NAPPEND: s = ">>"; dftfd = 1; break;
11689 case NTOFD: s = ">&"; dftfd = 1; break;
11690 case NTOOV: s = ">|"; dftfd = 1; break;
11691 case NFROM: s = "<"; dftfd = 0; break;
11692 case NFROMFD: s = "<&"; dftfd = 0; break;
11693 case NFROMTO: s = "<>"; dftfd = 0; break;
11694 default: s = "*error*"; dftfd = 0; break;
11696 if (np->nfile.fd != dftfd)
11697 fprintf(fp, "%d", np->nfile.fd);
11699 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11700 fprintf(fp, "%d", np->ndup.dupfd);
11702 sharg(np->nfile.fname, fp);
11716 struct nodelist *bqlist;
11719 if (arg->type != NARG) {
11720 printf("<node type %d>\n", arg->type);
11724 bqlist = arg->narg.backquote;
11725 for (p = arg->narg.text ; *p ; p++) {
11734 if (subtype == VSLENGTH)
11740 if (subtype & VSNUL)
11743 switch (subtype & VSTYPE) {
11762 case VSTRIMLEFTMAX:
11769 case VSTRIMRIGHTMAX:
11776 printf("<subtype %d>", subtype);
11783 case CTLBACKQ|CTLQUOTE:
11786 shtree(bqlist->n, -1, NULL, fp);
11798 indent(amount, pfx, fp)
11805 for (i = 0 ; i < amount ; i++) {
11806 if (pfx && i == amount - 1)
11824 static int debug = 1;
11826 static int debug = 0;
11834 if (tracefile == NULL)
11836 putc(c, tracefile);
11842 trace(const char *fmt, ...)
11846 if (tracefile != NULL) {
11847 (void) vfprintf(tracefile, fmt, va);
11848 if (strchr(fmt, '\n'))
11849 (void) fflush(tracefile);
11859 if (tracefile == NULL)
11861 fputs(s, tracefile);
11862 if (strchr(s, '\n'))
11874 if (tracefile == NULL)
11876 putc('"', tracefile);
11877 for (p = s ; *p ; p++) {
11879 case '\n': c = 'n'; goto backslash;
11880 case '\t': c = 't'; goto backslash;
11881 case '\r': c = 'r'; goto backslash;
11882 case '"': c = '"'; goto backslash;
11883 case '\\': c = '\\'; goto backslash;
11884 case CTLESC: c = 'e'; goto backslash;
11885 case CTLVAR: c = 'v'; goto backslash;
11886 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11887 case CTLBACKQ: c = 'q'; goto backslash;
11888 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11889 backslash: putc('\\', tracefile);
11890 putc(c, tracefile);
11893 if (*p >= ' ' && *p <= '~')
11894 putc(*p, tracefile);
11896 putc('\\', tracefile);
11897 putc(*p >> 6 & 03, tracefile);
11898 putc(*p >> 3 & 07, tracefile);
11899 putc(*p & 07, tracefile);
11904 putc('"', tracefile);
11912 if (tracefile == NULL)
11917 putc(' ', tracefile);
11919 putc('\n', tracefile);
11934 #ifdef not_this_way
11937 if ((p = getenv("HOME")) == NULL) {
11938 if (geteuid() == 0)
11944 strcat(s, "/trace");
11947 strcpy(s, "./trace");
11948 #endif /* not_this_way */
11949 if ((tracefile = fopen(s, "a")) == NULL) {
11950 fprintf(stderr, "Can't open %s\n", s);
11954 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11955 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11957 fputs("\nTracing started.\n", tracefile);
11964 * The trap builtin.
11968 trapcmd(argc, argv)
11977 for (signo = 0 ; signo < NSIG ; signo++) {
11978 if (trap[signo] != NULL) {
11982 p = single_quote(trap[signo]);
11983 sn = sys_siglist[signo];
11985 sn = u_signal_names(0, &signo, 0);
11988 printf("trap -- %s %s\n", p, sn);
12000 if ((signo = decode_signal(*ap, 0)) < 0)
12001 error("%s: bad trap", *ap);
12004 if (action[0] == '-' && action[1] == '\0')
12007 action = savestr(action);
12010 ckfree(trap[signo]);
12011 trap[signo] = action;
12026 * Set the signal handler for the specified signal. The routine figures
12027 * out what it should be set to.
12031 setsignal(int signo)
12035 struct sigaction act;
12037 if ((t = trap[signo]) == NULL)
12039 else if (*t != '\0')
12043 if (rootshell && action == S_DFL) {
12046 if (iflag || minusc || sflag == 0)
12072 t = &sigmode[signo - 1];
12075 * current setting unknown
12077 if (sigaction(signo, 0, &act) == -1) {
12079 * Pretend it worked; maybe we should give a warning
12080 * here, but other shells don't. We don't alter
12081 * sigmode, so that we retry every time.
12085 if (act.sa_handler == SIG_IGN) {
12086 if (mflag && (signo == SIGTSTP ||
12087 signo == SIGTTIN || signo == SIGTTOU)) {
12088 *t = S_IGN; /* don't hard ignore these */
12092 *t = S_RESET; /* force to be set */
12095 if (*t == S_HARD_IGN || *t == action)
12099 act.sa_handler = onsig;
12102 act.sa_handler = SIG_IGN;
12105 act.sa_handler = SIG_DFL;
12109 sigemptyset(&act.sa_mask);
12110 sigaction(signo, &act, 0);
12121 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12122 signal(signo, SIG_IGN);
12124 sigmode[signo - 1] = S_HARD_IGN;
12135 if (signo == SIGINT && trap[SIGINT] == NULL) {
12139 gotsig[signo - 1] = 1;
12145 * Called to execute a trap. Perhaps we should avoid entering new trap
12146 * handlers while we are executing a trap handler.
12156 for (i = 1 ; ; i++) {
12163 savestatus=exitstatus;
12164 evalstring(trap[i], 0);
12165 exitstatus=savestatus;
12172 * Called to exit the shell.
12176 exitshell(int status)
12178 struct jmploc loc1, loc2;
12181 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12182 if (setjmp(loc1.loc)) {
12185 if (setjmp(loc2.loc)) {
12189 if ((p = trap[0]) != NULL && *p != '\0') {
12193 l1: handler = &loc2; /* probably unnecessary */
12202 static int decode_signal(const char *string, int minsig)
12205 const char *name = u_signal_names(string, &signo, minsig);
12207 return name ? signo : -1;
12210 static struct var **hashvar (const char *);
12211 static void showvars (const char *, int, int);
12212 static struct var **findvar (struct var **, const char *);
12215 * Initialize the varable symbol tables and import the environment
12219 * This routine initializes the builtin variables. It is called when the
12220 * shell is initialized and again when a shell procedure is spawned.
12225 const struct varinit *ip;
12229 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12230 if ((vp->flags & VEXPORT) == 0) {
12231 vpp = hashvar(ip->text);
12234 vp->text = strdup(ip->text);
12235 vp->flags = ip->flags;
12236 vp->func = ip->func;
12240 * PS1 depends on uid
12242 if ((vps1.flags & VEXPORT) == 0) {
12243 vpp = hashvar("PS1=");
12246 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12247 vps1.flags = VSTRFIXED|VTEXTFIXED;
12252 * Set the value of a variable. The flags argument is ored with the
12253 * flags of the variable. If val is NULL, the variable is unset.
12257 setvar(name, val, flags)
12258 const char *name, *val;
12274 if (! is_in_name(*p)) {
12275 if (*p == '\0' || *p == '=')
12281 namelen = p - name;
12283 error("%.*s: bad variable name", namelen, name);
12284 len = namelen + 2; /* 2 is space for '=' and '\0' */
12288 len += vallen = strlen(val);
12291 nameeq = ckmalloc(len);
12292 memcpy(nameeq, name, namelen);
12293 nameeq[namelen] = '=';
12295 memcpy(nameeq + namelen + 1, val, vallen + 1);
12297 nameeq[namelen + 1] = '\0';
12299 setvareq(nameeq, flags);
12306 * Same as setvar except that the variable and value are passed in
12307 * the first argument as name=value. Since the first argument will
12308 * be actually stored in the table, it should not be a string that
12317 struct var *vp, **vpp;
12320 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12321 if ((vp = *findvar(vpp, s))) {
12322 if (vp->flags & VREADONLY) {
12323 size_t len = strchr(s, '=') - s;
12324 error("%.*s: is read only", len, s);
12328 if (vp->func && (flags & VNOFUNC) == 0)
12329 (*vp->func)(strchr(s, '=') + 1);
12331 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12334 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12335 vp->flags |= flags;
12339 * We could roll this to a function, to handle it as
12340 * a regular variable function callback, but why bother?
12342 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12348 vp = ckmalloc(sizeof (*vp));
12359 * Process a linked list of variable assignments.
12364 struct strlist *mylist;
12366 struct strlist *lp;
12369 for (lp = mylist ; lp ; lp = lp->next) {
12370 setvareq(savestr(lp->text), 0);
12378 * Find the value of a variable. Returns NULL if not set.
12381 static const char *
12387 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12388 return strchr(v->text, '=') + 1;
12396 * Search the environment of a builtin command.
12399 static const char *
12400 bltinlookup(const char *name)
12402 const struct strlist *sp;
12404 for (sp = cmdenviron ; sp ; sp = sp->next) {
12405 if (varequal(sp->text, name))
12406 return strchr(sp->text, '=') + 1;
12408 return lookupvar(name);
12414 * Generate a list of exported variables. This routine is used to construct
12415 * the third argument to execve when executing a program.
12427 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12428 for (vp = *vpp ; vp ; vp = vp->next)
12429 if (vp->flags & VEXPORT)
12432 ep = env = stalloc((nenv + 1) * sizeof *env);
12433 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12434 for (vp = *vpp ; vp ; vp = vp->next)
12435 if (vp->flags & VEXPORT)
12444 * Called when a shell procedure is invoked to clear out nonexported
12445 * variables. It is also necessary to reallocate variables of with
12446 * VSTACK set since these are currently allocated on the stack.
12452 struct var *vp, **prev;
12454 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12455 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12456 if ((vp->flags & VEXPORT) == 0) {
12458 if ((vp->flags & VTEXTFIXED) == 0)
12460 if ((vp->flags & VSTRFIXED) == 0)
12463 if (vp->flags & VSTACK) {
12464 vp->text = savestr(vp->text);
12465 vp->flags &=~ VSTACK;
12477 * Command to list all variables which are set. Currently this command
12478 * is invoked from the set command when the set command is called without
12483 showvarscmd(argc, argv)
12487 showvars(nullstr, VUNSET, VUNSET);
12494 * The export and readonly commands.
12498 exportcmd(argc, argv)
12505 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12508 listsetvar(cmdenviron);
12509 pflag = (nextopt("p") == 'p');
12510 if (argc > 1 && !pflag) {
12511 while ((name = *argptr++) != NULL) {
12512 if ((p = strchr(name, '=')) != NULL) {
12515 if ((vp = *findvar(hashvar(name), name))) {
12520 setvar(name, p, flag);
12524 showvars(argv[0], flag, 0);
12531 * The "local" command.
12534 /* funcnest nonzero if we are currently evaluating a function */
12537 localcmd(argc, argv)
12544 error("Not in a function");
12545 while ((name = *argptr++) != NULL) {
12553 * Make a variable a local variable. When a variable is made local, it's
12554 * value and flags are saved in a localvar structure. The saved values
12555 * will be restored when the shell function returns. We handle the name
12556 * "-" as a special case.
12563 struct localvar *lvp;
12568 lvp = ckmalloc(sizeof (struct localvar));
12569 if (name[0] == '-' && name[1] == '\0') {
12571 p = ckmalloc(sizeof optet_vals);
12572 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12575 vpp = hashvar(name);
12576 vp = *findvar(vpp, name);
12578 if (strchr(name, '='))
12579 setvareq(savestr(name), VSTRFIXED);
12581 setvar(name, NULL, VSTRFIXED);
12582 vp = *vpp; /* the new variable */
12584 lvp->flags = VUNSET;
12586 lvp->text = vp->text;
12587 lvp->flags = vp->flags;
12588 vp->flags |= VSTRFIXED|VTEXTFIXED;
12589 if (strchr(name, '='))
12590 setvareq(savestr(name), 0);
12594 lvp->next = localvars;
12601 * Called after a function returns.
12606 struct localvar *lvp;
12609 while ((lvp = localvars) != NULL) {
12610 localvars = lvp->next;
12612 if (vp == NULL) { /* $- saved */
12613 memcpy(optet_vals, lvp->text, sizeof optet_vals);
12615 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12616 (void)unsetvar(vp->text);
12618 if ((vp->flags & VTEXTFIXED) == 0)
12620 vp->flags = lvp->flags;
12621 vp->text = lvp->text;
12629 setvarcmd(argc, argv)
12634 return unsetcmd(argc, argv);
12635 else if (argc == 3)
12636 setvar(argv[1], argv[2], 0);
12638 error("List assignment not implemented");
12644 * The unset builtin command. We unset the function before we unset the
12645 * variable to allow a function to be unset when there is a readonly variable
12646 * with the same name.
12650 unsetcmd(argc, argv)
12660 while ((i = nextopt("vf")) != '\0') {
12666 if (flg_func == 0 && flg_var == 0)
12669 for (ap = argptr; *ap ; ap++) {
12673 ret |= unsetvar(*ap);
12680 * Unset the specified variable.
12684 unsetvar(const char *s)
12689 vpp = findvar(hashvar(s), s);
12692 if (vp->flags & VREADONLY)
12695 if (*(strchr(vp->text, '=') + 1) != '\0')
12696 setvar(s, nullstr, 0);
12697 vp->flags &= ~VEXPORT;
12698 vp->flags |= VUNSET;
12699 if ((vp->flags & VSTRFIXED) == 0) {
12700 if ((vp->flags & VTEXTFIXED) == 0)
12715 * Find the appropriate entry in the hash table from the name.
12718 static struct var **
12719 hashvar(const char *p)
12721 unsigned int hashval;
12723 hashval = ((unsigned char) *p) << 4;
12724 while (*p && *p != '=')
12725 hashval += (unsigned char) *p++;
12726 return &vartab[hashval % VTABSIZE];
12732 * Returns true if the two strings specify the same varable. The first
12733 * variable name is terminated by '='; the second may be terminated by
12734 * either '=' or '\0'.
12738 varequal(const char *p, const char *q)
12740 while (*p == *q++) {
12744 if (*p == '=' && *(q - 1) == '\0')
12750 showvars(const char *myprefix, int mask, int xor)
12754 const char *sep = myprefix == nullstr ? myprefix : spcstr;
12756 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12757 for (vp = *vpp ; vp ; vp = vp->next) {
12758 if ((vp->flags & mask) ^ xor) {
12762 p = strchr(vp->text, '=') + 1;
12763 len = p - vp->text;
12764 p = single_quote(p);
12766 printf("%s%s%.*s%s\n", myprefix, sep, len,
12774 static struct var **
12775 findvar(struct var **vpp, const char *name)
12777 for (; *vpp; vpp = &(*vpp)->next) {
12778 if (varequal((*vpp)->text, name)) {
12786 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12787 * This file contains code for the times builtin.
12788 * $Id: ash.c,v 1.17 2001/08/02 05:02:45 andersen Exp $
12790 static int timescmd (int argc, char **argv)
12793 long int clk_tck = sysconf(_SC_CLK_TCK);
12796 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12797 (int) (buf.tms_utime / clk_tck / 60),
12798 ((double) buf.tms_utime) / clk_tck,
12799 (int) (buf.tms_stime / clk_tck / 60),
12800 ((double) buf.tms_stime) / clk_tck,
12801 (int) (buf.tms_cutime / clk_tck / 60),
12802 ((double) buf.tms_cutime) / clk_tck,
12803 (int) (buf.tms_cstime / clk_tck / 60),
12804 ((double) buf.tms_cstime) / clk_tck);
12808 #ifdef ASH_MATH_SUPPORT
12809 /* The let builtin. */
12810 int letcmd(int argc, char **argv)
12815 char *tmp, *expression, p[13];
12816 expression = strchr(argv[1], '=');
12818 /* Cannot use 'error()' here, or the return code
12819 * will be incorrect */
12820 out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12823 *expression = '\0';
12824 tmp = ++expression;
12825 result = arith(tmp, &errcode);
12827 /* Cannot use 'error()' here, or the return code
12828 * will be incorrect */
12829 out2fmt("sh: let: ");
12831 out2fmt("divide by zero");
12833 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12836 snprintf(p, 12, "%ld", result);
12837 setvar(argv[1], savestr(p), 0);
12838 } else if (argc >= 3)
12839 synerror("invalid operand");
12847 * Copyright (c) 1989, 1991, 1993, 1994
12848 * The Regents of the University of California. All rights reserved.
12850 * This code is derived from software contributed to Berkeley by
12851 * Kenneth Almquist.
12853 * Redistribution and use in source and binary forms, with or without
12854 * modification, are permitted provided that the following conditions
12856 * 1. Redistributions of source code must retain the above copyright
12857 * notice, this list of conditions and the following disclaimer.
12858 * 2. Redistributions in binary form must reproduce the above copyright
12859 * notice, this list of conditions and the following disclaimer in the
12860 * documentation and/or other materials provided with the distribution.
12862 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12863 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12865 * 4. Neither the name of the University nor the names of its contributors
12866 * may be used to endorse or promote products derived from this software
12867 * without specific prior written permission.
12869 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12870 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12871 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12872 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12873 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12874 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12875 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12876 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12877 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12878 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF