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 <vodz@usa.net> 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 * 62k to busybox on an x86 system.*/
43 /* Enable job control. This allows you to run jobs in the background,
44 * which is great when ash is being used as an interactive shell, but
45 * it completely useless for is all you are doing is running scripts.
46 * This adds about 2.5k on an x86 system. */
49 /* This enables alias support in ash. If you want to support things
50 * like "alias ls='ls -l'" with ash, enable this. This is only useful
51 * when ash is used as an intractive shell. This adds about 1.5k */
54 /* If you need ash to act as a full Posix shell, with full math
55 * support, enable this. This option needs some work, since it
56 * doesn't compile right now... */
57 #undef ASH_MATH_SUPPORT
59 /* This shell builtin is used to indicate how the shell would interpret
60 * what you give it. This command is only useful when debugging, and
61 * is obsolete anyways. Adds about 670 bytes... You probably want to
62 * leave this disabled. */
65 /* Getopts is used by shell procedures to parse positional parameters.
66 * You probably want to leave this disabled, and use the busybox getopt
67 * applet if you want to do this sort of thing. There are some scripts
68 * out there that use it, so it you need it, enable. Most people will
69 * leave this disabled. This adds 1k on an x86 system. */
72 /* This allows you to override shell builtins and use whatever is on
73 * the filesystem. This is most useful when ash is acting as a
74 * standalone shell. Adds about 320 bytes. */
77 /* This makes a few common apps that are usually part of busybox
78 * anyways to be used as builtins. This may cause these builtins to be
79 * a little bit faster, but leaving this disabled will save you 2k. */
80 #undef ASH_BBAPPS_AS_BUILTINS
82 /* Optimize size vs speed as size */
83 #define ASH_OPTIMIZE_FOR_SIZE
85 /* Enable this to compile in extra debugging noise. When debugging is
86 * on, debugging info will be written to $HOME/trace and a quit signal
87 * will generate a core dump. */
92 /* These are here to work with glibc -- Don't change these... */
112 #include <sysexits.h>
114 #include <sys/stat.h>
115 #include <sys/cdefs.h>
116 #include <sys/ioctl.h>
117 #include <sys/param.h>
118 #include <sys/resource.h>
119 #include <sys/time.h>
120 #include <sys/times.h>
121 #include <sys/types.h>
122 #include <sys/wait.h>
125 #if !defined(FNMATCH_BROKEN)
128 #if !defined(GLOB_BROKEN)
140 * This file was generated by the mksyntax program.
144 #define CWORD 0 /* character is nothing special */
145 #define CNL 1 /* newline character */
146 #define CBACK 2 /* a backslash character */
147 #define CSQUOTE 3 /* single quote */
148 #define CDQUOTE 4 /* double quote */
149 #define CENDQUOTE 5 /* a terminating quote */
150 #define CBQUOTE 6 /* backwards single quote */
151 #define CVAR 7 /* a dollar sign */
152 #define CENDVAR 8 /* a '}' character */
153 #define CLP 9 /* a left paren in arithmetic */
154 #define CRP 10 /* a right paren in arithmetic */
155 #define CENDFILE 11 /* end of file */
156 #define CCTL 12 /* like CWORD, except it must be escaped */
157 #define CSPCL 13 /* these terminate a word */
158 #define CIGN 14 /* character should be ignored */
160 /* Syntax classes for is_ functions */
161 #define ISDIGIT 01 /* a digit */
162 #define ISUPPER 02 /* an upper case letter */
163 #define ISLOWER 04 /* a lower case letter */
164 #define ISUNDER 010 /* an underscore */
165 #define ISSPECL 020 /* the name of a special parameter */
182 #define TENDBQUOTE 10
204 #define BASESYNTAX (basesyntax + SYNBASE)
205 #define DQSYNTAX (dqsyntax + SYNBASE)
206 #define SQSYNTAX (sqsyntax + SYNBASE)
207 #define ARISYNTAX (arisyntax + SYNBASE)
209 /* control characters in argument strings */
210 #define CTLESC '\201'
211 #define CTLVAR '\202'
212 #define CTLENDVAR '\203'
213 #define CTLBACKQ '\204'
214 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
215 /* CTLBACKQ | CTLQUOTE == '\205' */
216 #define CTLARI '\206'
217 #define CTLENDARI '\207'
218 #define CTLQUOTEMARK '\210'
220 #define is_digit(c) ((((unsigned char)(c)) - '0') <= 9)
221 #define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
222 #define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
223 #define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
224 #define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
225 #define digit_val(c) ((c) - '0')
228 #define _DIAGASSERT(x)
232 #define S_DFL 1 /* default signal handling (SIG_DFL) */
233 #define S_CATCH 2 /* signal is caught */
234 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
235 #define S_HARD_IGN 4 /* signal is ignored permenantly */
236 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
239 /* variable substitution byte (follows CTLVAR) */
240 #define VSTYPE 0x0f /* type of variable substitution */
241 #define VSNUL 0x10 /* colon--treat the empty string as unset */
242 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
244 /* values of VSTYPE field */
245 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
246 #define VSMINUS 0x2 /* ${var-text} */
247 #define VSPLUS 0x3 /* ${var+text} */
248 #define VSQUESTION 0x4 /* ${var?message} */
249 #define VSASSIGN 0x5 /* ${var=text} */
250 #define VSTRIMLEFT 0x6 /* ${var#pattern} */
251 #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
252 #define VSTRIMRIGHT 0x8 /* ${var%pattern} */
253 #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
254 #define VSLENGTH 0xa /* ${#var} */
256 /* flags passed to redirect */
257 #define REDIR_PUSH 01 /* save previous values of file descriptors */
258 #define REDIR_BACKQ 02 /* save the command output to pipe */
261 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
262 * so we use _setjmp instead.
265 #if !defined(__GLIBC__)
266 #define setjmp(jmploc) _setjmp(jmploc)
267 #define longjmp(jmploc, val) _longjmp(jmploc, val)
271 * Most machines require the value returned from malloc to be aligned
272 * in some way. The following macro will get this right on many machines.
281 #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
284 #ifdef BB_LOCALE_SUPPORT
286 static void change_lc_all(const char *value);
287 static void change_lc_ctype(const char *value);
291 * These macros allow the user to suspend the handling of interrupt signals
292 * over a period of time. This is similar to SIGHOLD to or sigblock, but
293 * much more efficient and portable. (But hacking the kernel is so much
294 * more fun than worrying about efficiency and portability. :-))
297 static void onint (void);
298 static volatile int suppressint;
299 static volatile int intpending;
301 #define INTOFF suppressint++
302 #ifndef ASH_OPTIMIZE_FOR_SIZE
303 #define INTON { if (--suppressint == 0 && intpending) onint(); }
304 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
306 static void __inton (void);
307 static void forceinton (void);
308 #define INTON __inton()
309 #define FORCEINTON forceinton()
312 #define CLEAR_PENDING_INT intpending = 0
313 #define int_pending() intpending
316 typedef void *pointer;
318 #define NULL (void *)0
321 static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
322 static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
323 static inline char * savestr (const char *s) { return xstrdup(s); }
325 static pointer stalloc (int);
326 static void stunalloc (pointer);
327 static void ungrabstackstr (char *, char *);
328 static char * growstackstr(void);
329 static char * makestrspace(size_t newlen);
330 static char *sstrdup (const char *);
333 * Parse trees for commands are allocated in lifo order, so we use a stack
334 * to make this more efficient, and also to avoid all sorts of exception
335 * handling code to handle interrupts in the middle of a parse.
337 * The size 504 was chosen because the Ultrix malloc handles that size
341 #define MINSIZE 504 /* minimum size of a block */
345 struct stack_block *prev;
349 static struct stack_block stackbase;
350 static struct stack_block *stackp = &stackbase;
351 static struct stackmark *markp;
352 static char *stacknxt = stackbase.space;
353 static int stacknleft = MINSIZE;
356 #define equal(s1, s2) (strcmp(s1, s2) == 0)
358 #define stackblock() stacknxt
359 #define stackblocksize() stacknleft
360 #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
362 #define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
363 #define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
364 #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
367 #define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
368 #define STUNPUTC(p) (++sstrnleft, --p)
369 #define STTOPC(p) p[-1]
370 #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
371 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
373 #define ckfree(p) free((pointer)(p))
377 #define TRACE(param) trace param
378 static void trace (const char *, ...);
379 static void trargs (char **);
380 static void showtree (union node *);
381 static void trputc (int);
382 static void trputs (const char *);
383 static void opentrace (void);
418 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
419 #define EXP_TILDE 0x2 /* do normal tilde expansion */
420 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
421 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
422 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
423 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
428 static char optet_vals[NOPTS];
430 static const char * const optlist[NOPTS] = {
449 #define optent_name(optent) (optent+1)
450 #define optent_letter(optent) optent[0]
451 #define optent_val(optent) optet_vals[optent]
453 #define eflag optent_val(0)
454 #define fflag optent_val(1)
455 #define Iflag optent_val(2)
456 #define iflag optent_val(3)
457 #define mflag optent_val(4)
458 #define nflag optent_val(5)
459 #define sflag optent_val(6)
460 #define xflag optent_val(7)
461 #define vflag optent_val(8)
462 #define Vflag optent_val(9)
463 #define Eflag optent_val(10)
464 #define Cflag optent_val(11)
465 #define aflag optent_val(12)
466 #define bflag optent_val(13)
467 #define uflag optent_val(14)
468 #define qflag optent_val(15)
471 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
489 union node *redirect;
496 struct nodelist *cmdlist;
503 union node *redirect;
511 union node *elsepart;
542 struct nodelist *backquote;
580 struct nbinary nbinary;
583 struct nredir nredir;
587 struct nclist nclist;
597 struct nodelist *next;
601 struct backcmd { /* result of evalbackcmd */
602 int fd; /* file descriptor to read from */
603 char *buf; /* buffer */
604 int nleft; /* number of chars in buffer */
605 struct job *jp; /* job structure for command */
613 const struct builtincmd *cmd;
618 struct strlist *next;
624 struct strlist *list;
625 struct strlist **lastp;
629 struct strpush *prev; /* preceding string on stack */
633 struct alias *ap; /* if push was associated with an alias */
635 char *string; /* remember the string since it may change */
639 struct parsefile *prev; /* preceding file on stack */
640 int linno; /* current line */
641 int fd; /* file descriptor (or -1 if string) */
642 int nleft; /* number of chars left in this line */
643 int lleft; /* number of chars left in this buffer */
644 char *nextc; /* next char in buffer */
645 char *buf; /* input buffer */
646 struct strpush *strpush; /* for pushing strings at this level */
647 struct strpush basestrpush; /* so pushing one is fast */
651 struct stack_block *stackp;
654 struct stackmark *marknext;
658 int nparam; /* # of positional parameters (without $0) */
659 unsigned char malloc; /* if parameter list dynamically allocated */
660 char **p; /* parameter list */
661 int optind; /* next parameter to be processed by getopts */
662 int optoff; /* used by getopts */
665 static void flushall (void);
666 static void out2fmt (const char *, ...)
667 __attribute__((__format__(__printf__,1,2)));
668 static void out1fmt (const char *, ...)
669 __attribute__((__format__(__printf__,1,2)));
670 static int xwrite (int, const char *, int);
672 static void outstr (const char *p, FILE *file) { fputs(p, file); }
673 static void out1str(const char *p) { outstr(p, stdout); }
674 static void out2str(const char *p) { outstr(p, stderr); }
676 #define out2c(c) putc((c), stderr)
678 /* syntax table used when not in quotes */
679 static const char basesyntax[257] = {
680 CENDFILE, CSPCL, CWORD, CCTL,
681 CCTL, CCTL, CCTL, CCTL,
682 CCTL, CCTL, CCTL, CWORD,
683 CWORD, CWORD, CWORD, CWORD,
684 CWORD, CWORD, CWORD, CWORD,
685 CWORD, CWORD, CWORD, CWORD,
686 CWORD, CWORD, CWORD, CWORD,
687 CWORD, CWORD, CWORD, CWORD,
688 CWORD, CWORD, CWORD, CWORD,
689 CWORD, CWORD, CWORD, CWORD,
690 CWORD, CWORD, CWORD, CWORD,
691 CWORD, CWORD, CWORD, CWORD,
692 CWORD, CWORD, CWORD, CWORD,
693 CWORD, CWORD, CWORD, CWORD,
694 CWORD, CWORD, CWORD, CWORD,
695 CWORD, CWORD, CWORD, CWORD,
696 CWORD, CWORD, CWORD, CWORD,
697 CWORD, CWORD, CWORD, CWORD,
698 CWORD, CWORD, CWORD, CWORD,
699 CWORD, CWORD, CWORD, CWORD,
700 CWORD, CWORD, CWORD, CWORD,
701 CWORD, CWORD, CWORD, CWORD,
702 CWORD, CWORD, CWORD, CWORD,
703 CWORD, CWORD, CWORD, CWORD,
704 CWORD, CWORD, CWORD, 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, CSPCL,
715 CNL, 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, CSPCL, CWORD,
721 CDQUOTE, CWORD, CVAR, CWORD,
722 CSPCL, CSQUOTE, CSPCL, CSPCL,
723 CWORD, CWORD, CWORD, CWORD,
724 CWORD, CWORD, CWORD, CWORD,
725 CWORD, CWORD, CWORD, CWORD,
726 CWORD, CWORD, CWORD, CWORD,
727 CWORD, CSPCL, CSPCL, CWORD,
728 CSPCL, 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, CBACK, CWORD,
736 CWORD, CWORD, CBQUOTE, CWORD,
737 CWORD, 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, CWORD, CWORD,
743 CWORD, CWORD, CSPCL, CENDVAR,
747 /* syntax table used when in double quotes */
748 static const char dqsyntax[257] = {
749 CENDFILE, CIGN, CWORD, CCTL,
750 CCTL, CCTL, CCTL, CCTL,
751 CCTL, CCTL, CCTL, 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, CWORD, CWORD,
758 CWORD, CWORD, CWORD, 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, CWORD, CWORD,
766 CWORD, CWORD, CWORD, CWORD,
767 CWORD, CWORD, CWORD, CWORD,
768 CWORD, CWORD, CWORD, CWORD,
769 CWORD, CWORD, CWORD, CWORD,
770 CWORD, CWORD, CWORD, CWORD,
771 CWORD, CWORD, CWORD, CWORD,
772 CWORD, CWORD, CWORD, CWORD,
773 CWORD, CWORD, CWORD, 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 CNL, 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, CCTL,
790 CENDQUOTE,CWORD, CVAR, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CCTL, CWORD, CWORD, CCTL,
793 CWORD, CCTL, CWORD, CWORD,
794 CWORD, CWORD, CWORD, CWORD,
795 CWORD, CWORD, CWORD, CWORD,
796 CCTL, CWORD, CWORD, CCTL,
797 CWORD, CCTL, 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, CCTL, CBACK, CCTL,
805 CWORD, CWORD, CBQUOTE, CWORD,
806 CWORD, 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, CWORD,
812 CWORD, CWORD, CWORD, CENDVAR,
816 /* syntax table used when in single quotes */
817 static const char sqsyntax[257] = {
818 CENDFILE, CIGN, CWORD, CCTL,
819 CCTL, CCTL, CCTL, CCTL,
820 CCTL, CCTL, CCTL, 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, CWORD, CWORD, CWORD,
827 CWORD, CWORD, CWORD, 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, CWORD,
835 CWORD, CWORD, CWORD, CWORD,
836 CWORD, CWORD, CWORD, CWORD,
837 CWORD, CWORD, CWORD, CWORD,
838 CWORD, CWORD, CWORD, CWORD,
839 CWORD, CWORD, CWORD, CWORD,
840 CWORD, CWORD, CWORD, CWORD,
841 CWORD, CWORD, CWORD, CWORD,
842 CWORD, CWORD, CWORD, 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 CNL, 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, CCTL,
859 CWORD, CWORD, CWORD, CWORD,
860 CWORD, CENDQUOTE,CWORD, CWORD,
861 CCTL, CWORD, CWORD, CCTL,
862 CWORD, CCTL, CWORD, CWORD,
863 CWORD, CWORD, CWORD, CWORD,
864 CWORD, CWORD, CWORD, CWORD,
865 CCTL, CWORD, CWORD, CCTL,
866 CWORD, CCTL, 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, CCTL, CCTL, CCTL,
874 CWORD, CWORD, CWORD, CWORD,
875 CWORD, 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, CWORD,
881 CWORD, CWORD, CWORD, CWORD,
885 /* syntax table used when in arithmetic */
886 static const char arisyntax[257] = {
887 CENDFILE, CIGN, CWORD, CCTL,
888 CCTL, CCTL, CCTL, CCTL,
889 CCTL, CCTL, CCTL, 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, CWORD, CWORD, CWORD,
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,
904 CWORD, CWORD, CWORD, CWORD,
905 CWORD, CWORD, CWORD, CWORD,
906 CWORD, CWORD, CWORD, CWORD,
907 CWORD, CWORD, CWORD, CWORD,
908 CWORD, CWORD, CWORD, CWORD,
909 CWORD, CWORD, CWORD, CWORD,
910 CWORD, CWORD, CWORD, CWORD,
911 CWORD, CWORD, CWORD, 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 CNL, 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 CDQUOTE, CWORD, CVAR, CWORD,
929 CWORD, CSQUOTE, CLP, CRP,
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, CBACK, CWORD,
943 CWORD, CWORD, CBQUOTE, CWORD,
944 CWORD, 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 CWORD, CWORD, CWORD, CENDVAR,
954 /* character classification table */
955 static const char is_type[257] = {
997 0, ISSPECL, ISSPECL, 0,
999 ISSPECL, 0, 0, ISSPECL,
1000 0, 0, ISDIGIT, ISDIGIT,
1001 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1002 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1004 0, ISSPECL, ISSPECL, ISUPPER,
1005 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1006 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1007 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1008 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1009 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1010 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1012 0, ISUNDER, 0, ISLOWER,
1013 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1014 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1015 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1016 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1017 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1018 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1023 /* Array indicating which tokens mark the end of a list */
1024 static const char tokendlist[] = {
1057 static const char *const tokname[] = {
1090 #define KWDOFFSET 14
1092 static const char *const parsekwd[] = {
1112 static int plinno = 1; /* input line number */
1114 static int parselleft; /* copy of parsefile->lleft */
1116 static struct parsefile basepf; /* top level input file */
1117 static char basebuf[BUFSIZ]; /* buffer for top level input file */
1118 static struct parsefile *parsefile = &basepf; /* current input file */
1121 * NEOF is returned by parsecmd when it encounters an end of file. It
1122 * must be distinct from NULL, so we use the address of a variable that
1123 * happens to be handy.
1126 static int tokpushback; /* last token pushed back */
1127 #define NEOF ((union node *)&tokpushback)
1128 static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1131 static void error (const char *, ...) __attribute__((__noreturn__));
1132 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1133 static void shellexec (char **, char **, const char *, int)
1134 __attribute__((noreturn));
1135 static void exitshell (int) __attribute__((noreturn));
1137 static int goodname(const char *);
1138 static void ignoresig (int);
1139 static void onsig (int);
1140 static void dotrap (void);
1141 static int decode_signal (const char *, int);
1143 static void shprocvar(void);
1144 static void deletefuncs(void);
1145 static void setparam (char **);
1146 static void freeparam (volatile struct shparam *);
1148 /* reasons for skipping commands (see comment on breakcmd routine) */
1154 /* values of cmdtype */
1155 #define CMDUNKNOWN -1 /* no entry in table for command */
1156 #define CMDNORMAL 0 /* command is an executable program */
1157 #define CMDBUILTIN 1 /* command is a shell builtin */
1158 #define CMDFUNCTION 2 /* command is a shell function */
1160 #define DO_ERR 1 /* find_command prints errors */
1161 #define DO_ABS 2 /* find_command checks absolute paths */
1162 #define DO_NOFUN 4 /* find_command ignores functions */
1163 #define DO_BRUTE 8 /* find_command ignores hash table */
1170 #define VEXPORT 0x01 /* variable is exported */
1171 #define VREADONLY 0x02 /* variable cannot be modified */
1172 #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1173 #define VTEXTFIXED 0x08 /* text is staticly allocated */
1174 #define VSTACK 0x10 /* text is allocated on the stack */
1175 #define VUNSET 0x20 /* the variable is not set */
1176 #define VNOFUNC 0x40 /* don't call the callback function */
1180 struct var *next; /* next entry in hash list */
1181 int flags; /* flags are defined above */
1182 char *text; /* name=value */
1183 void (*func) (const char *);
1184 /* function to be called when */
1185 /* the variable gets set/unset */
1189 struct localvar *next; /* next local variable in list */
1190 struct var *vp; /* the variable that was made local */
1191 int flags; /* saved flags */
1192 char *text; /* saved text */
1196 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
1197 #define rmescapes(p) _rmescapes((p), 0)
1198 static char *_rmescapes (char *, int);
1200 static void rmescapes (char *);
1203 static int casematch (union node *, const char *);
1204 static void clearredir(void);
1205 static void popstring(void);
1206 static void readcmdfile (const char *);
1208 static int number (const char *);
1209 static int is_number (const char *, int *num);
1210 static char *single_quote (const char *);
1211 static int nextopt (const char *);
1213 static void redirect (union node *, int);
1214 static void popredir (void);
1215 static int dup_as_newfd (int, int);
1217 static void changepath(const char *newval);
1218 static void getoptsreset(const char *value);
1221 static int parsenleft; /* copy of parsefile->nleft */
1222 static char *parsenextc; /* copy of parsefile->nextc */
1223 static int rootpid; /* pid of main shell */
1224 static int rootshell; /* true if we aren't a child of the main shell */
1226 static const char spcstr[] = " ";
1227 static const char snlfmt[] = "%s\n";
1229 static int sstrnleft;
1230 static int herefd = -1;
1232 static struct localvar *localvars;
1234 static struct var vifs;
1235 static struct var vmail;
1236 static struct var vmpath;
1237 static struct var vpath;
1238 static struct var vps1;
1239 static struct var vps2;
1240 static struct var voptind;
1241 #ifdef BB_LOCALE_SUPPORT
1242 static struct var vlc_all;
1243 static struct var vlc_ctype;
1250 void (*func) (const char *);
1253 static const char defpathvar[] =
1254 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1255 #define defpath (defpathvar + 5)
1258 static const char defifsvar[] = "IFS= \t\n";
1259 #define defifs (defifsvar + 4)
1261 static const char defifs[] = " \t\n";
1264 static const struct varinit varinit[] = {
1266 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1268 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1271 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1273 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1275 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1278 * vps1 depends on uid
1280 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1282 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1284 #ifdef BB_LOCALE_SUPPORT
1285 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1287 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1296 static struct var *vartab[VTABSIZE];
1299 * The following macros access the values of the above variables.
1300 * They have to skip over the name. They return the null string
1301 * for unset variables.
1304 #define ifsval() (vifs.text + 4)
1305 #define ifsset() ((vifs.flags & VUNSET) == 0)
1306 #define mailval() (vmail.text + 5)
1307 #define mpathval() (vmpath.text + 9)
1308 #define pathval() (vpath.text + 5)
1309 #define ps1val() (vps1.text + 4)
1310 #define ps2val() (vps2.text + 4)
1311 #define optindval() (voptind.text + 7)
1313 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1315 static void initvar (void);
1316 static void setvar (const char *, const char *, int);
1317 static void setvareq (char *, int);
1318 static void listsetvar (struct strlist *);
1319 static char *lookupvar (const char *);
1320 static char *bltinlookup (const char *);
1321 static char **environment (void);
1322 static int showvarscmd (int, char **);
1323 static void mklocal (char *);
1324 static void poplocalvars (void);
1325 static int unsetvar (const char *);
1326 static int varequal (const char *, const char *);
1329 static char *arg0; /* value of $0 */
1330 static struct shparam shellparam; /* current positional parameters */
1331 static char **argptr; /* argument list for builtin commands */
1332 static char *optionarg; /* set by nextopt (like getopt) */
1333 static char *optptr; /* used by nextopt */
1334 static char *minusc; /* argument to -c option */
1339 #define ALIASINUSE 1
1351 static struct alias *atab[ATABSIZE];
1353 static void setalias (char *, char *);
1354 static struct alias **hashalias (const char *);
1355 static struct alias *freealias (struct alias *);
1356 static struct alias **__lookupalias (const char *);
1362 struct alias *ap, **app;
1364 app = __lookupalias(name);
1368 if (!(ap->flag & ALIASINUSE)) {
1371 ap->val = savestr(val);
1372 ap->flag &= ~ALIASDEAD;
1375 ap = ckmalloc(sizeof (struct alias));
1376 ap->name = savestr(name);
1377 ap->val = savestr(val);
1390 app = __lookupalias(name);
1394 *app = freealias(*app);
1405 struct alias *ap, **app;
1409 for (i = 0; i < ATABSIZE; i++) {
1411 for (ap = *app; ap; ap = *app) {
1412 *app = freealias(*app);
1421 static struct alias *
1422 lookupalias(const char *name, int check)
1424 struct alias *ap = *__lookupalias(name);
1426 if (check && ap && (ap->flag & ALIASINUSE))
1432 printalias(const struct alias *ap) {
1435 p = single_quote(ap->val);
1436 out1fmt("alias %s=%s\n", ap->name, p);
1442 * TODO - sort output
1445 aliascmd(int argc, char **argv)
1454 for (i = 0; i < ATABSIZE; i++)
1455 for (ap = atab[i]; ap; ap = ap->next) {
1460 while ((n = *++argv) != NULL) {
1461 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1462 if ((ap = *__lookupalias(n)) == NULL) {
1463 out2fmt("%s: %s not found\n", "alias", n);
1478 unaliascmd(int argc, char **argv)
1482 while ((i = nextopt("a")) != '\0') {
1488 for (i = 0; *argptr; argptr++) {
1489 if (unalias(*argptr)) {
1490 out2fmt("%s: %s not found\n", "unalias", *argptr);
1498 static struct alias **
1502 unsigned int hashval;
1507 return &atab[hashval % ATABSIZE];
1510 static struct alias *
1511 freealias(struct alias *ap) {
1514 if (ap->flag & ALIASINUSE) {
1515 ap->flag |= ALIASDEAD;
1527 static struct alias **
1528 __lookupalias(const char *name) {
1529 struct alias **app = hashalias(name);
1531 for (; *app; app = &(*app)->next) {
1532 if (equal(name, (*app)->name)) {
1541 #ifdef ASH_MATH_SUPPORT
1542 /* The generated file arith.c has been snipped. If you want this
1543 * stuff back in, feel free to add it to your own copy. */
1544 #define ARITH_NUM 257
1545 #define ARITH_LPAREN 258
1546 #define ARITH_RPAREN 259
1547 #define ARITH_OR 260
1548 #define ARITH_AND 261
1549 #define ARITH_BOR 262
1550 #define ARITH_BXOR 263
1551 #define ARITH_BAND 264
1552 #define ARITH_EQ 265
1553 #define ARITH_NE 266
1554 #define ARITH_LT 267
1555 #define ARITH_GT 268
1556 #define ARITH_GE 269
1557 #define ARITH_LE 270
1558 #define ARITH_LSHIFT 271
1559 #define ARITH_RSHIFT 272
1560 #define ARITH_ADD 273
1561 #define ARITH_SUB 274
1562 #define ARITH_MUL 275
1563 #define ARITH_DIV 276
1564 #define ARITH_REM 277
1565 #define ARITH_UNARYMINUS 278
1566 #define ARITH_UNARYPLUS 279
1567 #define ARITH_NOT 280
1568 #define ARITH_BNOT 281
1570 static void expari (int);
1572 static int arith (const char *);
1573 static int expcmd (int , char **);
1574 static void arith_lex_reset (void);
1575 static int yylex (void);
1579 static char *trap[NSIG]; /* trap handler commands */
1580 static char sigmode[NSIG - 1]; /* current value of signal */
1581 static char gotsig[NSIG - 1]; /* indicates specified signal received */
1582 static int pendingsigs; /* indicates some signal received */
1585 * This file was generated by the mkbuiltins program.
1589 static int bgcmd (int, char **);
1590 static int fgcmd (int, char **);
1591 static int killcmd (int, char **);
1593 static int bltincmd (int, char **);
1594 static int cdcmd (int, char **);
1595 static int breakcmd (int, char **);
1597 static int commandcmd (int, char **);
1599 static int dotcmd (int, char **);
1600 static int evalcmd (int, char **);
1601 static int execcmd (int, char **);
1602 static int exitcmd (int, char **);
1603 static int exportcmd (int, char **);
1604 static int histcmd (int, char **);
1605 static int hashcmd (int, char **);
1606 static int helpcmd (int, char **);
1607 static int jobscmd (int, char **);
1608 static int localcmd (int, char **);
1610 static int pwdcmd (int, char **);
1612 static int readcmd (int, char **);
1613 static int returncmd (int, char **);
1614 static int setcmd (int, char **);
1615 static int setvarcmd (int, char **);
1616 static int shiftcmd (int, char **);
1617 static int trapcmd (int, char **);
1618 static int umaskcmd (int, char **);
1620 static int aliascmd (int, char **);
1621 static int unaliascmd (int, char **);
1623 static int unsetcmd (int, char **);
1624 static int waitcmd (int, char **);
1625 static int ulimitcmd (int, char **);
1626 static int timescmd (int, char **);
1627 #ifdef ASH_MATH_SUPPORT
1628 static int expcmd (int, char **);
1631 static int typecmd (int, char **);
1634 static int getoptscmd (int, char **);
1637 #ifndef BB_TRUE_FALSE
1638 # ifdef ASH_BBAPPS_AS_BUILTINS
1639 static int true_main (int, char **);
1640 static int false_main (int, char **);
1644 static void setpwd (const char *, int);
1647 #define BUILTIN_NOSPEC "0"
1648 #define BUILTIN_SPECIAL "1"
1649 #define BUILTIN_REGULAR "2"
1650 #define BUILTIN_ASSIGN "4"
1651 #define BUILTIN_SPEC_ASSG "5"
1652 #define BUILTIN_REG_ASSG "6"
1654 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1655 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1656 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1660 int (*const builtinfunc) (int, char **);
1665 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1666 * the binary search in find_builtin() will stop working. If you value
1667 * your kneecaps, you'll be sure to *make sure* that any changes made
1668 * to this array result in the listing remaining in ascii order. You
1671 static const struct builtincmd builtincmds[] = {
1672 { BUILTIN_SPECIAL ".", dotcmd },
1673 { BUILTIN_SPECIAL ":", true_main },
1675 { BUILTIN_REG_ASSG "alias", aliascmd },
1678 { BUILTIN_REGULAR "bg", bgcmd },
1680 { BUILTIN_SPECIAL "break", breakcmd },
1681 { BUILTIN_SPECIAL "builtin", bltincmd },
1682 { BUILTIN_REGULAR "cd", cdcmd },
1683 #ifdef ASH_BBAPPS_AS_BUILTINS
1684 { BUILTIN_NOSPEC "chdir", cdcmd },
1687 { BUILTIN_REGULAR "command", commandcmd },
1689 { BUILTIN_SPECIAL "continue", breakcmd },
1690 { BUILTIN_SPECIAL "eval", evalcmd },
1691 { BUILTIN_SPECIAL "exec", execcmd },
1692 { BUILTIN_SPECIAL "exit", exitcmd },
1693 #ifdef ASH_MATH_SUPPORT
1694 { BUILTIN_NOSPEC "exp", expcmd },
1696 { BUILTIN_SPEC_ASSG "export", exportcmd },
1697 #ifdef ASH_BBAPPS_AS_BUILTINS
1698 { BUILTIN_REGULAR "false", false_main },
1700 { BUILTIN_REGULAR "fc", histcmd },
1702 { BUILTIN_REGULAR "fg", fgcmd },
1705 { BUILTIN_REGULAR "getopts", getoptscmd },
1707 { BUILTIN_NOSPEC "hash", hashcmd },
1708 { BUILTIN_NOSPEC "help", helpcmd },
1709 { BUILTIN_REGULAR "jobs", jobscmd },
1711 { BUILTIN_REGULAR "kill", killcmd },
1713 #ifdef ASH_MATH_SUPPORT
1714 { BUILTIN_NOSPEC "let", expcmd },
1716 { BUILTIN_ASSIGN "local", localcmd },
1718 { BUILTIN_NOSPEC "pwd", pwdcmd },
1720 { BUILTIN_REGULAR "read", readcmd },
1721 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1722 { BUILTIN_SPECIAL "return", returncmd },
1723 { BUILTIN_SPECIAL "set", setcmd },
1724 { BUILTIN_NOSPEC "setvar", setvarcmd },
1725 { BUILTIN_SPECIAL "shift", shiftcmd },
1726 { BUILTIN_SPECIAL "times", timescmd },
1727 { BUILTIN_SPECIAL "trap", trapcmd },
1728 #ifdef ASH_BBAPPS_AS_BUILTINS
1729 { BUILTIN_REGULAR "true", true_main },
1732 { BUILTIN_NOSPEC "type", typecmd },
1734 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1735 { BUILTIN_REGULAR "umask", umaskcmd },
1737 { BUILTIN_REGULAR "unalias", unaliascmd },
1739 { BUILTIN_SPECIAL "unset", unsetcmd },
1740 { BUILTIN_REGULAR "wait", waitcmd },
1742 #define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1744 static const struct builtincmd *DOTCMD = &builtincmds[0];
1745 static struct builtincmd *BLTINCMD;
1746 static struct builtincmd *EXECCMD;
1747 static struct builtincmd *EVALCMD;
1750 #define JOBSTOPPED 1 /* all procs are stopped */
1751 #define JOBDONE 2 /* all procs are completed */
1754 * A job structure contains information about a job. A job is either a
1755 * single process or a set of processes contained in a pipeline. In the
1756 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1761 pid_t pid; /* process id */
1762 int status; /* status flags (defined above) */
1763 char *cmd; /* text of command being run */
1767 static int job_warning; /* user was warned about stopped jobs */
1770 static void setjobctl(int enable);
1772 #define setjobctl(on) /* do nothing */
1777 struct procstat ps0; /* status of process */
1778 struct procstat *ps; /* status or processes when more than one */
1779 short nprocs; /* number of processes */
1780 short pgrp; /* process group of this job */
1781 char state; /* true if job is finished */
1782 char used; /* true if this entry is in used */
1783 char changed; /* true if status has changed */
1785 char jobctl; /* job running under job control */
1789 static struct job *jobtab; /* array of jobs */
1790 static int njobs; /* size of array */
1791 static int backgndpid = -1; /* pid of last background process */
1793 static int initialpgrp; /* pgrp of shell on invocation */
1794 static int curjob; /* current job */
1797 static int intreceived;
1799 static struct job *makejob (union node *, int);
1800 static int forkshell (struct job *, union node *, int);
1801 static int waitforjob (struct job *);
1803 static int docd (char *, int);
1804 static char *getcomponent (void);
1805 static void updatepwd (const char *);
1806 static void getpwd (void);
1808 static char *padvance (const char **, const char *);
1810 static char nullstr[1]; /* zero length string */
1811 static char *curdir = nullstr; /* current working directory */
1812 static char *cdcomppath;
1826 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1827 error("HOME not set");
1830 if (dest[0] == '-' && dest[1] == '\0') {
1831 dest = bltinlookup("OLDPWD");
1832 if (!dest || !*dest) {
1841 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1843 while ((p = padvance(&path, dest)) != NULL) {
1844 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1849 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1851 print = strcmp(p, dest);
1853 if (docd(p, print) >= 0)
1858 error("can't cd to %s", dest);
1864 * Actually do the chdir. In an interactive shell, print the
1865 * directory name if "print" is nonzero.
1880 TRACE(("docd(\"%s\", %d) called\n", dest, print));
1883 * Check each component of the path. If we find a symlink or
1884 * something we can't stat, clear curdir to force a getcwd()
1885 * next time we get the value of the current directory.
1888 cdcomppath = sstrdup(dest);
1895 while ((q = getcomponent()) != NULL) {
1896 if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
1904 if (equal(component, ".."))
1907 if ((lstat(stackblock(), &statb) < 0)
1908 || (S_ISLNK(statb.st_mode))) {
1916 if (chdir(dest) < 0) {
1920 updatepwd(badstat ? NULL : dest);
1923 out1fmt(snlfmt, curdir);
1929 * Get the next component of the path name pointed to by cdcomppath.
1930 * This routine overwrites the string pointed to by cdcomppath.
1938 if ((p = cdcomppath) == NULL)
1941 while (*p != '/' && *p != '\0')
1955 * Update curdir (the name of the current directory) in response to a
1956 * cd command. We also call hashcd to let the routines in exec.c know
1957 * that the current directory has changed.
1960 static void hashcd (void);
1963 updatepwd(const char *dir)
1969 hashcd(); /* update command hash table */
1972 * If our argument is NULL, we don't know the current directory
1973 * any more because we traversed a symbolic link or something
1974 * we couldn't stat().
1976 if (dir == NULL || curdir == nullstr) {
1981 cdcomppath = sstrdup(dir);
1990 while ((p = getcomponent()) != NULL) {
1991 if (equal(p, "..")) {
1992 while (new > stackblock() && (STUNPUTC(new), *new) != '/');
1993 } else if (*p != '\0' && ! equal(p, ".")) {
1999 if (new == stackblock())
2002 setpwd(stackblock(), 1);
2012 out1fmt(snlfmt, curdir);
2018 * Find out what the current directory is. If we already know the current
2019 * directory, this routine returns immediately.
2024 curdir = xgetcwd(0);
2030 setpwd(const char *val, int setold)
2033 setvar("OLDPWD", curdir, VEXPORT);
2036 if (curdir != nullstr) {
2043 curdir = savestr(val);
2046 setvar("PWD", curdir, VEXPORT);
2050 * Errors and exceptions.
2054 * Code to handle exceptions in C.
2058 * We enclose jmp_buf in a structure so that we can declare pointers to
2059 * jump locations. The global variable handler contains the location to
2060 * jump to when an exception occurs, and the global variable exception
2061 * contains a code identifying the exeception. To implement nested
2062 * exception handlers, the user should save the value of handler on entry
2063 * to an inner scope, set handler to point to a jmploc structure for the
2064 * inner scope, and restore handler on exit from the scope.
2072 #define EXINT 0 /* SIGINT received */
2073 #define EXERROR 1 /* a generic error */
2074 #define EXSHELLPROC 2 /* execute a shell procedure */
2075 #define EXEXEC 3 /* command execution failed */
2077 static struct jmploc *handler;
2078 static int exception;
2080 static void exverror (int, const char *, va_list)
2081 __attribute__((__noreturn__));
2084 * Called to raise an exception. Since C doesn't include exceptions, we
2085 * just do a longjmp to the exception handler. The type of exception is
2086 * stored in the global variable "exception".
2089 static void exraise (int) __attribute__((__noreturn__));
2095 if (handler == NULL)
2099 longjmp(handler->loc, 1);
2104 * Called from trap.c when a SIGINT is received. (If the user specifies
2105 * that SIGINT is to be trapped or ignored using the trap builtin, then
2106 * this routine is not called.) Suppressint is nonzero when interrupts
2107 * are held using the INTOFF macro. The call to _exit is necessary because
2108 * there is a short period after a fork before the signal handlers are
2109 * set to the appropriate value for the child. (The test for iflag is
2110 * just defensive programming.)
2122 sigemptyset(&mysigset);
2123 sigprocmask(SIG_SETMASK, &mysigset, NULL);
2124 if (rootshell && iflag)
2127 signal(SIGINT, SIG_DFL);
2134 static char *commandname; /* currently executing command */
2137 * Exverror is called to raise the error exception. If the first argument
2138 * is not NULL then error prints an error message using printf style
2139 * formatting. It then raises the error exception.
2142 exverror(int cond, const char *msg, va_list ap)
2149 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
2151 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2155 out2fmt("%s: ", commandname);
2156 vfprintf(stderr, msg, ap);
2167 error(const char *msg, ...)
2182 msg = va_arg(ap, const char *);
2184 exverror(EXERROR, msg, ap);
2192 exerror(int cond, const char *msg, ...)
2208 cond = va_arg(ap, int);
2209 msg = va_arg(ap, const char *);
2211 exverror(cond, msg, ap);
2219 * Table of error messages.
2223 short errcode; /* error number */
2224 short action; /* operation which encountered the error */
2228 * Types of operations (passed to the errmsg routine).
2231 #define E_OPEN 01 /* opening a file */
2232 #define E_CREAT 02 /* creating a file */
2233 #define E_EXEC 04 /* executing a program */
2235 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2237 static const struct errname errormsg[] = {
2242 { ENOENT, E_CREAT },
2244 { ENOTDIR, E_OPEN },
2245 { ENOTDIR, E_CREAT },
2246 { ENOTDIR, E_EXEC },
2248 { EEXIST, E_CREAT },
2287 { ELIBACC, E_EXEC },
2291 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2294 * Return a string describing an error. The returned string may be a
2295 * pointer to a static buffer that will be overwritten on the next call.
2296 * Action describes the operation that got the error.
2300 errmsg(int e, int action)
2302 struct errname const *ep;
2303 static char buf[12];
2305 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2306 if (ep->errcode == e && (ep->action & action) != 0)
2310 snprintf(buf, sizeof buf, "error %d", e);
2315 #ifdef ASH_OPTIMIZE_FOR_SIZE
2318 if (--suppressint == 0 && intpending) {
2322 static void forceinton (void) {
2329 /* flags in argument to evaltree */
2330 #define EV_EXIT 01 /* exit after evaluating tree */
2331 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2332 #define EV_BACKCMD 04 /* command executing within back quotes */
2334 static int evalskip; /* set if we are skipping commands */
2335 static int skipcount; /* number of levels to skip */
2336 static int loopnest; /* current loop nesting level */
2337 static int funcnest; /* depth of function calls */
2341 static struct strlist *cmdenviron; /* environment for builtin command */
2342 static int exitstatus; /* exit status of last command */
2343 static int oexitstatus; /* saved exit status */
2346 static void evalloop (union node *, int);
2347 static void evalfor (union node *, int);
2348 static void evalcase (union node *, int);
2349 static void evalsubshell (union node *, int);
2350 static void expredir (union node *);
2351 static void evalpipe (union node *);
2352 static void evalcommand (union node *, int);
2353 static void prehash (union node *);
2354 static void eprintlist (struct strlist *);
2356 static union node *parsecmd(int);
2358 * Called to reset things after an exception.
2362 * The eval commmand.
2364 static void evalstring (char *, int);
2378 STARTSTACKSTR(concat);
2382 STPUTC(*p++, concat);
2383 if ((p = *ap++) == NULL)
2385 STPUTC(' ', concat);
2387 STPUTC('\0', concat);
2388 p = grabstackstr(concat);
2390 evalstring(p, EV_TESTED);
2396 * Execute a command or commands contained in a string.
2399 static void evaltree (union node *, int);
2400 static void setinputstring (char *);
2401 static void popfile (void);
2402 static void setstackmark(struct stackmark *mark);
2403 static void popstackmark(struct stackmark *mark);
2407 evalstring(char *s, int flag)
2410 struct stackmark smark;
2412 setstackmark(&smark);
2414 while ((n = parsecmd(0)) != NEOF) {
2416 popstackmark(&smark);
2419 popstackmark(&smark);
2423 * Evaluate a parse tree. The value is left in the global variable
2426 static struct builtincmd *find_builtin (const char *);
2427 static void defun (char *, union node *);
2436 TRACE(("evaltree(NULL) called\n"));
2439 TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2442 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2445 evaltree(n->nbinary.ch2, flags);
2448 evaltree(n->nbinary.ch1, EV_TESTED);
2449 if (evalskip || exitstatus != 0)
2451 evaltree(n->nbinary.ch2, flags);
2454 evaltree(n->nbinary.ch1, EV_TESTED);
2455 if (evalskip || exitstatus == 0)
2457 evaltree(n->nbinary.ch2, flags);
2460 expredir(n->nredir.redirect);
2461 redirect(n->nredir.redirect, REDIR_PUSH);
2462 evaltree(n->nredir.n, flags);
2466 evalsubshell(n, flags);
2469 evalsubshell(n, flags);
2472 evaltree(n->nif.test, EV_TESTED);
2475 if (exitstatus == 0)
2476 evaltree(n->nif.ifpart, flags);
2477 else if (n->nif.elsepart)
2478 evaltree(n->nif.elsepart, flags);
2494 struct builtincmd *bcmd;
2496 (bcmd = find_builtin(n->narg.text)) &&
2497 IS_BUILTIN_SPECIAL(bcmd)
2499 out2fmt("%s is a special built-in\n", n->narg.text);
2503 defun(n->narg.text, n->narg.next);
2508 evaltree(n->nnot.com, EV_TESTED);
2509 exitstatus = !exitstatus;
2517 evalcommand(n, flags);
2522 out1fmt("Node type = %d\n", n->type);
2531 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2533 exitshell(exitstatus);
2547 evaltree(n->nbinary.ch1, EV_TESTED);
2549 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2553 if (evalskip == SKIPBREAK && --skipcount <= 0)
2557 if (n->type == NWHILE) {
2558 if (exitstatus != 0)
2561 if (exitstatus == 0)
2564 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2565 status = exitstatus;
2570 exitstatus = status;
2573 static void expandarg (union node *, struct arglist *, int);
2574 static void fixredir(union node *n, const char *text, int err);
2581 struct arglist arglist;
2584 struct stackmark smark;
2586 setstackmark(&smark);
2587 arglist.lastp = &arglist.list;
2588 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2589 oexitstatus = exitstatus;
2590 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2594 *arglist.lastp = NULL;
2598 for (sp = arglist.list ; sp ; sp = sp->next) {
2599 setvar(n->nfor.var, sp->text, 0);
2600 evaltree(n->nfor.body, flags & EV_TESTED);
2602 if (evalskip == SKIPCONT && --skipcount <= 0) {
2606 if (evalskip == SKIPBREAK && --skipcount <= 0)
2613 popstackmark(&smark);
2624 struct arglist arglist;
2625 struct stackmark smark;
2627 setstackmark(&smark);
2628 arglist.lastp = &arglist.list;
2629 oexitstatus = exitstatus;
2630 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2631 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2632 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2633 if (casematch(patp, arglist.list->text)) {
2634 if (evalskip == 0) {
2635 evaltree(cp->nclist.body, flags);
2642 popstackmark(&smark);
2646 * Kick off a subshell to evaluate a tree.
2650 evalsubshell(n, flags)
2655 int backgnd = (n->type == NBACKGND);
2657 expredir(n->nredir.redirect);
2659 if (forkshell(jp, n, backgnd) == 0) {
2661 flags &=~ EV_TESTED;
2662 redirect(n->nredir.redirect, 0);
2663 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2667 exitstatus = waitforjob(jp);
2674 * Compute the names of the files in a redirection list.
2683 for (redir = n ; redir ; redir = redir->nfile.next) {
2685 fn.lastp = &fn.list;
2686 oexitstatus = exitstatus;
2687 switch (redir->type) {
2693 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2694 redir->nfile.expfname = fn.list->text;
2698 if (redir->ndup.vname) {
2699 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2700 fixredir(redir, fn.list->text, 1);
2708 * Evaluate a pipeline. All the processes in the pipeline are children
2709 * of the process creating the pipeline. (This differs from some versions
2710 * of the shell, which make the last process in a pipeline the parent
2719 struct nodelist *lp;
2724 TRACE(("evalpipe(0x%lx) called\n", (long)n));
2726 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2729 jp = makejob(n, pipelen);
2731 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2735 if (pipe(pip) < 0) {
2737 error("Pipe call failed");
2740 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2744 dup_as_newfd(prevfd, 0);
2756 dup_as_newfd(pip[1], 1);
2760 evaltree(lp->n, EV_EXIT);
2768 if (n->npipe.backgnd == 0) {
2770 exitstatus = waitforjob(jp);
2771 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2779 * Execute a command inside back quotes. If it's a builtin command, we
2780 * want to save its output in a block obtained from malloc. Otherwise
2781 * we fork off a subprocess and get the output of the command via a pipe.
2782 * Should be called with interrupts off.
2786 evalbackcmd(union node *n, struct backcmd *result)
2790 struct stackmark smark; /* unnecessary */
2792 setstackmark(&smark);
2803 error("Pipe call failed");
2805 if (forkshell(jp, n, FORK_NOJOB) == 0) {
2810 dup_as_newfd(pip[1], 1);
2814 evaltree(n, EV_EXIT);
2817 result->fd = pip[0];
2820 popstackmark(&smark);
2821 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2822 result->fd, result->buf, result->nleft, result->jp));
2828 * Execute a simple command.
2831 static void find_command (const char *, struct cmdentry *, int, const char *);
2834 isassignment(const char *word) {
2835 if (!is_name(*word)) {
2840 } while (is_in_name(*word));
2841 return *word == '=';
2845 evalcommand(union node *cmd, int flags)
2847 struct stackmark smark;
2849 struct arglist arglist;
2850 struct arglist varlist;
2856 struct cmdentry cmdentry;
2858 char *volatile savecmdname;
2859 volatile struct shparam saveparam;
2860 struct localvar *volatile savelocalvars;
2864 const struct builtincmd *firstbltin;
2865 struct jmploc *volatile savehandler;
2866 struct jmploc jmploc;
2868 /* Avoid longjmp clobbering */
2875 /* First expand the arguments. */
2876 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2877 setstackmark(&smark);
2878 arglist.lastp = &arglist.list;
2879 varlist.lastp = &varlist.list;
2881 oexitstatus = exitstatus;
2884 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2885 expandarg(argp, &varlist, EXP_VARTILDE);
2888 argp = cmd->ncmd.args; argp && !arglist.list;
2889 argp = argp->narg.next
2891 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2894 struct builtincmd *bcmd;
2896 bcmd = find_builtin(arglist.list->text);
2897 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2898 for (; argp; argp = argp->narg.next) {
2899 if (pseudovarflag && isassignment(argp->narg.text)) {
2900 expandarg(argp, &arglist, EXP_VARTILDE);
2903 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2906 *arglist.lastp = NULL;
2907 *varlist.lastp = NULL;
2908 expredir(cmd->ncmd.redirect);
2910 for (sp = arglist.list ; sp ; sp = sp->next)
2912 argv = stalloc(sizeof (char *) * (argc + 1));
2914 for (sp = arglist.list ; sp ; sp = sp->next) {
2915 TRACE(("evalcommand arg: %s\n", sp->text));
2920 if (iflag && funcnest == 0 && argc > 0)
2924 /* Print the command if xflag is set. */
2927 eprintlist(varlist.list);
2928 eprintlist(arglist.list);
2932 /* Now locate the command. */
2934 cmdentry.cmdtype = CMDBUILTIN;
2935 firstbltin = cmdentry.u.cmd = BLTINCMD;
2937 const char *oldpath;
2938 int findflag = DO_ERR;
2942 * Modify the command lookup path, if a PATH= assignment
2945 for (sp = varlist.list ; sp ; sp = sp->next)
2946 if (varequal(sp->text, defpathvar)) {
2947 path = sp->text + 5;
2948 findflag |= DO_BRUTE;
2951 oldfindflag = findflag;
2954 find_command(argv[0], &cmdentry, findflag, path);
2955 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
2959 /* implement bltin and command here */
2960 if (cmdentry.cmdtype != CMDBUILTIN) {
2964 firstbltin = cmdentry.u.cmd;
2966 if (cmdentry.u.cmd == BLTINCMD) {
2968 struct builtincmd *bcmd;
2973 if (!(bcmd = find_builtin(*argv))) {
2974 out2fmt("%s: not found\n", *argv);
2978 cmdentry.u.cmd = bcmd;
2979 if (bcmd != BLTINCMD)
2983 if (cmdentry.u.cmd == find_builtin("command")) {
2988 if (*argv[0] == '-') {
2989 if (!equal(argv[0], "-p")) {
2999 findflag |= DO_BRUTE;
3002 findflag = oldfindflag;
3004 findflag |= DO_NOFUN;
3012 /* Fork off a child process if necessary. */
3013 if (cmd->ncmd.backgnd
3014 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
3016 jp = makejob(cmd, 1);
3017 mode = cmd->ncmd.backgnd;
3018 if (forkshell(jp, cmd, mode) != 0)
3019 goto parent; /* at end of routine */
3023 /* This is the child process if a fork occurred. */
3024 /* Execute the command. */
3025 if (cmdentry.cmdtype == CMDFUNCTION) {
3027 trputs("Shell function: "); trargs(argv);
3029 exitstatus = oexitstatus;
3030 redirect(cmd->ncmd.redirect, REDIR_PUSH);
3031 saveparam = shellparam;
3032 shellparam.malloc = 0;
3033 shellparam.nparam = argc - 1;
3034 shellparam.p = argv + 1;
3036 savelocalvars = localvars;
3039 if (setjmp(jmploc.loc)) {
3040 if (exception == EXSHELLPROC) {
3041 freeparam((volatile struct shparam *)
3044 saveparam.optind = shellparam.optind;
3045 saveparam.optoff = shellparam.optoff;
3046 freeparam(&shellparam);
3047 shellparam = saveparam;
3050 localvars = savelocalvars;
3051 handler = savehandler;
3052 longjmp(handler->loc, 1);
3054 savehandler = handler;
3056 for (sp = varlist.list ; sp ; sp = sp->next)
3059 evaltree(cmdentry.u.func, flags & EV_TESTED);
3063 localvars = savelocalvars;
3064 saveparam.optind = shellparam.optind;
3065 saveparam.optoff = shellparam.optoff;
3066 freeparam(&shellparam);
3067 shellparam = saveparam;
3068 handler = savehandler;
3071 if (evalskip == SKIPFUNC) {
3075 if (flags & EV_EXIT)
3076 exitshell(exitstatus);
3077 } else if (cmdentry.cmdtype == CMDBUILTIN) {
3079 trputs("builtin command: "); trargs(argv);
3081 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
3082 redirect(cmd->ncmd.redirect, mode);
3083 savecmdname = commandname;
3084 if (IS_BUILTIN_SPECIAL(firstbltin)) {
3085 listsetvar(varlist.list);
3087 cmdenviron = varlist.list;
3090 if (setjmp(jmploc.loc)) {
3092 exitstatus = (e == EXINT)? SIGINT+128 : 2;
3095 savehandler = handler;
3097 commandname = argv[0];
3099 optptr = NULL; /* initialize nextopt */
3100 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
3104 if (e != EXSHELLPROC) {
3105 commandname = savecmdname;
3106 if (flags & EV_EXIT)
3107 exitshell(exitstatus);
3109 handler = savehandler;
3111 if ((e != EXERROR && e != EXEXEC)
3112 || cmdentry.u.cmd == BLTINCMD
3113 || cmdentry.u.cmd == DOTCMD
3114 || cmdentry.u.cmd == EVALCMD
3115 || cmdentry.u.cmd == EXECCMD)
3119 if (cmdentry.u.cmd != EXECCMD)
3123 trputs("normal command: "); trargs(argv);
3125 redirect(cmd->ncmd.redirect, 0);
3127 for (sp = varlist.list ; sp ; sp = sp->next)
3128 setvareq(sp->text, VEXPORT|VSTACK);
3129 envp = environment();
3130 shellexec(argv, envp, path, cmdentry.u.index);
3134 parent: /* parent process gets here (if we forked) */
3135 if (mode == 0) { /* argument to fork */
3137 exitstatus = waitforjob(jp);
3143 setvar("_", lastarg, 0);
3144 popstackmark(&smark);
3150 * Search for a command. This is called before we fork so that the
3151 * location of the command will be available in the parent as well as
3152 * the child. The check for "goodname" is an overly conservative
3153 * check that the name will not be subject to expansion.
3160 struct cmdentry entry;
3162 if (n->type == NCMD && n->ncmd.args)
3163 if (goodname(n->ncmd.args->narg.text))
3164 find_command(n->ncmd.args->narg.text, &entry, 0,
3171 * Builtin commands. Builtin commands whose functions are closely
3172 * tied to evaluation are implemented here.
3176 * No command given, or a bltin command with no arguments. Set the
3177 * specified variables.
3181 bltincmd(argc, argv)
3186 * Preserve exitstatus of a previous possible redirection
3194 * Handle break and continue commands. Break, continue, and return are
3195 * all handled by setting the evalskip flag. The evaluation routines
3196 * above all check this flag, and if it is set they start skipping
3197 * commands rather than executing them. The variable skipcount is
3198 * the number of loops to break/continue, or the number of function
3199 * levels to return. (The latter is always 1.) It should probably
3200 * be an error to break out of more loops than exist, but it isn't
3201 * in the standard shell so we don't make it one here.
3205 breakcmd(argc, argv)
3209 int n = argc > 1 ? number(argv[1]) : 1;
3214 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3222 * The return command.
3226 returncmd(argc, argv)
3230 int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3233 evalskip = SKIPFUNC;
3238 /* Do what ksh does; skip the rest of the file */
3239 evalskip = SKIPFILE;
3246 #ifndef BB_TRUE_FALSE
3247 #ifdef ASH_BBAPPS_AS_BUILTINS
3249 false_main(argc, argv)
3258 true_main(argc, argv)
3268 * Controls whether the shell is interactive or not.
3271 static void setsignal(int signo);
3272 static void chkmail(int silent);
3276 setinteractive(int on)
3278 static int is_interactive;
3279 static int do_banner=0;
3281 if (on == is_interactive)
3287 is_interactive = on;
3288 if (do_banner==0 && is_interactive) {
3289 /* Looks like they want an interactive shell */
3290 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3291 printf( "Enter 'help' for a list of built-in commands.\n\n");
3299 setinteractive(iflag);
3312 iflag = 0; /* exit on error */
3315 for (sp = cmdenviron; sp ; sp = sp->next)
3316 setvareq(sp->text, VEXPORT|VSTACK);
3317 shellexec(argv + 1, environment(), pathval(), 0);
3323 eprintlist(struct strlist *sp)
3325 for (; sp; sp = sp->next) {
3326 out2fmt(" %s",sp->text);
3330 * When commands are first encountered, they are entered in a hash table.
3331 * This ensures that a full path search will not have to be done for them
3332 * on each invocation.
3334 * We should investigate converting to a linear search, even though that
3335 * would make the command name "hash" a misnomer.
3337 #define CMDTABLESIZE 31 /* should be prime */
3338 #define ARB 1 /* actual size determined at run time */
3343 struct tblentry *next; /* next entry in hash chain */
3344 union param param; /* definition of builtin function */
3345 short cmdtype; /* index identifying command */
3346 char rehash; /* if set, cd done since entry created */
3347 char cmdname[ARB]; /* name of command */
3351 static struct tblentry *cmdtable[CMDTABLESIZE];
3352 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3353 static int exerrno = 0; /* Last exec error */
3356 static void tryexec (char *, char **, char **);
3357 static void printentry (struct tblentry *, int);
3358 static void clearcmdentry (int);
3359 static struct tblentry *cmdlookup (const char *, int);
3360 static void delete_cmd_entry (void);
3362 static int describe_command (char *, int);
3364 static int path_change (const char *, int *);
3368 * Exec a program. Never returns. If you change this routine, you may
3369 * have to change the find_command routine as well.
3372 static const char *pathopt; /* set by padvance */
3375 shellexec(argv, envp, path, idx)
3376 char **argv, **envp;
3383 if (strchr(argv[0], '/') != NULL) {
3384 tryexec(argv[0], argv, envp);
3388 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3389 if (--idx < 0 && pathopt == NULL) {
3390 tryexec(cmdname, argv, envp);
3391 if (errno != ENOENT && errno != ENOTDIR)
3398 /* Map to POSIX errors */
3410 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3415 * Clear traps on a fork.
3421 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3422 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3427 setsignal(tp - trap);
3435 initshellproc(void) {
3461 /* from options.c: */
3465 for (i = 0; i < NOPTS; i++)
3481 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3493 static int preadbuffer(void);
3494 static void pushfile (void);
3495 static int preadfd (void);
3498 * Read a character from the script, returning PEOF on end of file.
3499 * Nul characters in the input are silently discarded.
3502 #ifndef ASH_OPTIMIZE_FOR_SIZE
3503 #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3507 return pgetc_macro();
3513 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3519 return pgetc_macro();
3525 * Undo the last call to pgetc. Only one character may be pushed back.
3526 * PEOF may be pushed back.
3538 struct parsefile *pf = parsefile;
3547 parsefile = pf->prev;
3549 parsenleft = parsefile->nleft;
3550 parselleft = parsefile->lleft;
3551 parsenextc = parsefile->nextc;
3552 plinno = parsefile->linno;
3558 * Return to top level.
3563 while (parsefile != &basepf)
3568 * Close the file(s) that the shell is reading commands from. Called
3569 * after a fork is done.
3575 if (parsefile->fd > 0) {
3576 close(parsefile->fd);
3583 * Like setinputfile, but takes an open file descriptor. Call this with
3588 setinputfd(fd, push)
3591 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3597 while (parsefile->strpush)
3601 if (parsefile->buf == NULL)
3602 parsefile->buf = ckmalloc(BUFSIZ);
3603 parselleft = parsenleft = 0;
3609 * Set the input to take input from a file. If push is set, push the
3610 * old input onto the stack first.
3614 setinputfile(const char *fname, int push)
3620 if ((fd = open(fname, O_RDONLY)) < 0)
3621 error("Can't open %s", fname);
3623 myfileno2 = dup_as_newfd(fd, 10);
3626 error("Out of file descriptors");
3629 setinputfd(fd, push);
3635 tryexec(cmd, argv, envp)
3642 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3646 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
3647 name = get_last_path_component(name);
3650 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3653 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
3655 run_applet_by_name(name, argc_l, argv);
3657 execve(cmd, argv, envp);
3662 setinputfile(cmd, 0);
3663 commandname = arg0 = savestr(argv[0]);
3665 exraise(EXSHELLPROC);
3670 static char *commandtext (const union node *);
3673 * Do a path search. The variable path (passed by reference) should be
3674 * set to the start of the path before the first call; padvance will update
3675 * this value as it proceeds. Successive calls to padvance will return
3676 * the possible path expansions in sequence. If an option (indicated by
3677 * a percent sign) appears in the path entry then the global variable
3678 * pathopt will be set to point to it; otherwise pathopt will be set to
3682 static const char *pathopt;
3684 static void growstackblock(void);
3688 padvance(const char **path, const char *name)
3698 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3699 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3700 while (stackblocksize() < len)
3704 memcpy(q, start, p - start);
3712 while (*p && *p != ':') p++;
3718 return stalloc(len);
3723 /*** Command hashing code ***/
3731 struct tblentry **pp;
3732 struct tblentry *cmdp;
3735 struct cmdentry entry;
3739 while ((c = nextopt("rv")) != '\0') {
3743 } else if (c == 'v') {
3747 if (*argptr == NULL) {
3748 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3749 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3750 if (cmdp->cmdtype != CMDBUILTIN) {
3751 printentry(cmdp, verbose);
3758 while ((name = *argptr) != NULL) {
3759 if ((cmdp = cmdlookup(name, 0)) != NULL
3760 && (cmdp->cmdtype == CMDNORMAL
3761 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3763 find_command(name, &entry, DO_ERR, pathval());
3764 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3766 cmdp = cmdlookup(name, 0);
3767 if (cmdp) printentry(cmdp, verbose);
3777 printentry(cmdp, verbose)
3778 struct tblentry *cmdp;
3785 if (cmdp->cmdtype == CMDNORMAL) {
3786 idx = cmdp->param.index;
3789 name = padvance(&path, cmdp->cmdname);
3791 } while (--idx >= 0);
3793 } else if (cmdp->cmdtype == CMDBUILTIN) {
3794 out1fmt("builtin %s", cmdp->cmdname);
3795 } else if (cmdp->cmdtype == CMDFUNCTION) {
3796 out1fmt("function %s", cmdp->cmdname);
3799 name = commandtext(cmdp->param.func);
3800 out1fmt(" %s", name);
3806 error("internal error: cmdtype %d", cmdp->cmdtype);
3809 out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr);
3814 /*** List the available builtins ***/
3817 static int helpcmd(int argc, char** argv)
3820 const struct builtincmd *x;
3822 printf("\nBuilt-in commands:\n");
3823 printf("-------------------\n");
3824 for (col=0, i=0, x = builtincmds; i < NUMBUILTINS; x++, i++) {
3825 if (!x->name || ! (x->name+1))
3827 col += printf("%s%s", ((col == 0) ? "\t" : " "),
3834 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3836 const struct BB_applet *applet;
3837 extern const struct BB_applet applets[];
3838 extern const size_t NUM_APPLETS;
3840 for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
3844 col += printf("%s%s", ((col == 0) ? "\t" : " "),
3854 return EXIT_SUCCESS;
3860 * Resolve a command name. If you change this routine, you may have to
3861 * change the shellexec routine as well.
3864 static int prefix (const char *, const char *);
3867 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3869 struct tblentry *cmdp;
3879 struct builtincmd *bcmd;
3881 /* If name contains a slash, don't use the hash table */
3882 if (strchr(name, '/') != NULL) {
3884 while (stat(name, &statb) < 0) {
3885 if (errno != ENOENT && errno != ENOTDIR)
3887 entry->cmdtype = CMDUNKNOWN;
3888 entry->u.index = -1;
3891 entry->cmdtype = CMDNORMAL;
3892 entry->u.index = -1;
3895 entry->cmdtype = CMDNORMAL;
3901 if (act & DO_BRUTE) {
3902 firstchange = path_change(path, &bltin);
3908 /* If name is in the table, and not invalidated by cd, we're done */
3909 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3910 if (cmdp->cmdtype == CMDFUNCTION) {
3911 if (act & DO_NOFUN) {
3916 } else if (act & DO_BRUTE) {
3917 if ((cmdp->cmdtype == CMDNORMAL &&
3918 cmdp->param.index >= firstchange) ||
3919 (cmdp->cmdtype == CMDBUILTIN &&
3920 ((builtinloc < 0 && bltin >= 0) ?
3921 bltin : builtinloc) >= firstchange)) {
3922 /* need to recompute the entry */
3931 bcmd = find_builtin(name);
3932 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3935 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3938 } else if (act & DO_BRUTE) {
3939 if (firstchange == 0) {
3944 /* If %builtin not in path, check for builtin next */
3945 if (regular || (bltin < 0 && bcmd)) {
3948 entry->cmdtype = CMDBUILTIN;
3949 entry->u.cmd = bcmd;
3953 cmdp = cmdlookup(name, 1);
3954 cmdp->cmdtype = CMDBUILTIN;
3955 cmdp->param.cmd = bcmd;
3960 /* We have to search path. */
3961 prev = -1; /* where to start */
3962 if (cmdp && cmdp->rehash) { /* doing a rehash */
3963 if (cmdp->cmdtype == CMDBUILTIN)
3966 prev = cmdp->param.index;
3972 while ((fullname = padvance(&path, name)) != NULL) {
3973 stunalloc(fullname);
3975 if (idx >= firstchange) {
3979 if (prefix("builtin", pathopt)) {
3980 if ((bcmd = find_builtin(name))) {
3984 } else if (!(act & DO_NOFUN) &&
3985 prefix("func", pathopt)) {
3988 continue; /* ignore unimplemented options */
3991 /* if rehash, don't redo absolute path names */
3992 if (fullname[0] == '/' && idx <= prev &&
3993 idx < firstchange) {
3996 TRACE(("searchexec \"%s\": no change\n", name));
3999 while (stat(fullname, &statb) < 0) {
4000 if (errno != ENOENT && errno != ENOTDIR)
4004 e = EACCES; /* if we fail, this will be the error */
4005 if (!S_ISREG(statb.st_mode))
4007 if (pathopt) { /* this is a %func directory */
4008 stalloc(strlen(fullname) + 1);
4009 readcmdfile(fullname);
4010 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
4011 error("%s not defined in %s", name, fullname);
4012 stunalloc(fullname);
4015 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4016 /* If we aren't called with DO_BRUTE and cmdp is set, it must
4017 be a function and we're being called with DO_NOFUN */
4019 entry->cmdtype = CMDNORMAL;
4020 entry->u.index = idx;
4024 cmdp = cmdlookup(name, 1);
4025 cmdp->cmdtype = CMDNORMAL;
4026 cmdp->param.index = idx;
4031 /* We failed. If there was an entry for this command, delete it */
4032 if (cmdp && updatetbl)
4035 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
4036 entry->cmdtype = CMDUNKNOWN;
4041 entry->cmdtype = cmdp->cmdtype;
4042 entry->u = cmdp->param;
4048 * Search the table of builtin commands.
4052 bstrcmp(const void *name, const void *b)
4054 return strcmp((const char *)name, (*(const char *const *) b)+1);
4057 static struct builtincmd *
4058 find_builtin(const char *name)
4060 struct builtincmd *bp;
4062 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
4070 * Called when a cd is done. Marks all commands so the next time they
4071 * are executed they will be rehashed.
4076 struct tblentry **pp;
4077 struct tblentry *cmdp;
4079 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4080 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4081 if (cmdp->cmdtype == CMDNORMAL
4082 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
4091 * Called before PATH is changed. The argument is the new value of PATH;
4092 * pathval() still returns the old value at this point. Called with
4097 changepath(const char *newval)
4102 firstchange = path_change(newval, &bltin);
4103 if (builtinloc < 0 && bltin >= 0)
4104 builtinloc = bltin; /* zap builtins */
4105 clearcmdentry(firstchange);
4111 * Clear out command entries. The argument specifies the first entry in
4112 * PATH which has changed.
4116 clearcmdentry(firstchange)
4119 struct tblentry **tblp;
4120 struct tblentry **pp;
4121 struct tblentry *cmdp;
4124 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4126 while ((cmdp = *pp) != NULL) {
4127 if ((cmdp->cmdtype == CMDNORMAL &&
4128 cmdp->param.index >= firstchange)
4129 || (cmdp->cmdtype == CMDBUILTIN &&
4130 builtinloc >= firstchange)) {
4142 * Free a parse tree.
4146 freefunc(union node *n)
4154 * Delete all functions.
4159 struct tblentry **tblp;
4160 struct tblentry **pp;
4161 struct tblentry *cmdp;
4164 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4166 while ((cmdp = *pp) != NULL) {
4167 if (cmdp->cmdtype == CMDFUNCTION) {
4169 freefunc(cmdp->param.func);
4182 * Locate a command in the command hash table. If "add" is nonzero,
4183 * add the command to the table if it is not already present. The
4184 * variable "lastcmdentry" is set to point to the address of the link
4185 * pointing to the entry, so that delete_cmd_entry can delete the
4189 static struct tblentry **lastcmdentry;
4191 static struct tblentry *
4192 cmdlookup(const char *name, int add)
4196 struct tblentry *cmdp;
4197 struct tblentry **pp;
4204 pp = &cmdtable[hashval % CMDTABLESIZE];
4205 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4206 if (equal(cmdp->cmdname, name))
4210 if (add && cmdp == NULL) {
4212 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4213 + strlen(name) + 1);
4215 cmdp->cmdtype = CMDUNKNOWN;
4217 strcpy(cmdp->cmdname, name);
4225 * Delete the command entry returned on the last lookup.
4229 delete_cmd_entry() {
4230 struct tblentry *cmdp;
4233 cmdp = *lastcmdentry;
4234 *lastcmdentry = cmdp->next;
4242 * Add a new command entry, replacing any existing command entry for
4247 addcmdentry(char *name, struct cmdentry *entry)
4249 struct tblentry *cmdp;
4252 cmdp = cmdlookup(name, 1);
4253 if (cmdp->cmdtype == CMDFUNCTION) {
4254 freefunc(cmdp->param.func);
4256 cmdp->cmdtype = entry->cmdtype;
4257 cmdp->param = entry->u;
4263 * Define a shell function.
4266 static union node *copyfunc(union node *);
4269 defun(char *name, union node *func)
4271 struct cmdentry entry;
4273 entry.cmdtype = CMDFUNCTION;
4274 entry.u.func = copyfunc(func);
4275 addcmdentry(name, &entry);
4280 * Delete a function if it exists.
4284 unsetfunc(char *name)
4286 struct tblentry *cmdp;
4288 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4289 freefunc(cmdp->param.func);
4295 * Wrapper around strcmp for qsort/bsearch/...
4298 pstrcmp(const void *a, const void *b)
4300 return strcmp((const char *) a, *(const char *const *) b);
4304 * Find a keyword is in a sorted array.
4307 static const char *const *
4308 findkwd(const char *s)
4310 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
4311 sizeof(const char *), pstrcmp);
4316 * Locate and print what a word is...
4327 for (i = 1; i < argc; i++) {
4328 err |= describe_command(argv[i], 1);
4334 describe_command(char *command, int verbose)
4336 struct cmdentry entry;
4337 struct tblentry *cmdp;
4339 const struct alias *ap;
4341 const char *path = pathval();
4347 /* First look at the keywords */
4348 if (findkwd(command)) {
4349 out1str(verbose ? " is a shell keyword" : command);
4354 /* Then look at the aliases */
4355 if ((ap = lookupalias(command, 0)) != NULL) {
4357 out1fmt(" is an alias for %s", ap->val);
4364 /* Then check if it is a tracked alias */
4365 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4366 entry.cmdtype = cmdp->cmdtype;
4367 entry.u = cmdp->param;
4369 /* Finally use brute force */
4370 find_command(command, &entry, DO_ABS, path);
4373 switch (entry.cmdtype) {
4375 int j = entry.u.index;
4381 p = padvance(&path, command);
4388 cmdp ? " a tracked alias for" : nullstr, p
4398 out1str(" is a shell function");
4407 " is a %sshell builtin",
4408 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4409 "special " : nullstr
4418 out1str(": not found\n");
4431 commandcmd(argc, argv)
4436 int default_path = 0;
4437 int verify_only = 0;
4438 int verbose_verify_only = 0;
4440 while ((c = nextopt("pvV")) != '\0')
4449 verbose_verify_only = 1;
4453 "command: nextopt returned character code 0%o\n", c);
4457 if (default_path + verify_only + verbose_verify_only > 1 ||
4460 "command [-p] command [arg ...]\n");
4462 "command {-v|-V} command\n");
4467 if (verify_only || verbose_verify_only) {
4468 return describe_command(*argptr, verbose_verify_only);
4477 path_change(newval, bltin)
4481 const char *old, *new;
4487 firstchange = 9999; /* assume no change */
4493 if ((*old == '\0' && *new == ':')
4494 || (*old == ':' && *new == '\0'))
4496 old = new; /* ignore subsequent differences */
4500 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4507 if (builtinloc >= 0 && *bltin < 0)
4512 * Routines to expand arguments to commands. We have to deal with
4513 * backquotes, shell variables, and file metacharacters.
4518 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4519 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4522 * Structure specifying which parts of the string should be searched
4523 * for IFS characters.
4527 struct ifsregion *next; /* next region in list */
4528 int begoff; /* offset of start of region */
4529 int endoff; /* offset of end of region */
4530 int nulonly; /* search for nul bytes only */
4534 static char *expdest; /* output of current string */
4535 static struct nodelist *argbackq; /* list of back quote expressions */
4536 static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
4537 static struct ifsregion *ifslastp; /* last struct in list */
4538 static struct arglist exparg; /* holds expanded arg list */
4540 static void argstr (char *, int);
4541 static char *exptilde (char *, int);
4542 static void expbackq (union node *, int, int);
4543 static int subevalvar (char *, char *, int, int, int, int, int);
4544 static char *evalvar (char *, int);
4545 static int varisset (char *, int);
4546 static void strtodest (const char *, const char *, int);
4547 static void varvalue (char *, int, int);
4548 static void recordregion (int, int, int);
4549 static void removerecordregions (int);
4550 static void ifsbreakup (char *, struct arglist *);
4551 static void ifsfree (void);
4552 static void expandmeta (struct strlist *, int);
4553 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4554 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4555 #if !defined(GLOB_BROKEN)
4556 static void addglob (const glob_t *);
4559 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4560 static void expmeta (char *, char *);
4562 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4563 static struct strlist *expsort (struct strlist *);
4564 static struct strlist *msort (struct strlist *, int);
4566 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4567 static int patmatch (char *, char *, int);
4568 static int patmatch2 (char *, char *, int);
4570 static int pmatch (char *, char *, int);
4571 #define patmatch2 patmatch
4573 static char *cvtnum (int, char *);
4576 * Expand shell variables and backquotes inside a here document.
4579 /* arg: the document, fd: where to write the expanded version */
4581 expandhere(union node *arg, int fd)
4584 expandarg(arg, (struct arglist *)NULL, 0);
4585 xwrite(fd, stackblock(), expdest - stackblock());
4590 * Perform variable substitution and command substitution on an argument,
4591 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4592 * perform splitting and file name expansion. When arglist is NULL, perform
4593 * here document expansion.
4597 expandarg(arg, arglist, flag)
4599 struct arglist *arglist;
4605 argbackq = arg->narg.backquote;
4606 STARTSTACKSTR(expdest);
4607 ifsfirst.next = NULL;
4609 argstr(arg->narg.text, flag);
4610 if (arglist == NULL) {
4611 return; /* here document expanded */
4613 STPUTC('\0', expdest);
4614 p = grabstackstr(expdest);
4615 exparg.lastp = &exparg.list;
4619 if (flag & EXP_FULL) {
4620 ifsbreakup(p, &exparg);
4621 *exparg.lastp = NULL;
4622 exparg.lastp = &exparg.list;
4623 expandmeta(exparg.list, flag);
4625 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4627 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4630 exparg.lastp = &sp->next;
4633 *exparg.lastp = NULL;
4635 *arglist->lastp = exparg.list;
4636 arglist->lastp = exparg.lastp;
4643 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4644 * characters to allow for further processing. Otherwise treat
4645 * $@ like $* since no splitting will be performed.
4654 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4657 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4658 p = exptilde(p, flag);
4662 case CTLENDVAR: /* ??? */
4665 /* "$@" syntax adherence hack */
4666 if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4668 if ((flag & EXP_FULL) != 0)
4678 p = evalvar(p, flag);
4681 case CTLBACKQ|CTLQUOTE:
4682 expbackq(argbackq->n, c & CTLQUOTE, flag);
4683 argbackq = argbackq->next;
4685 #ifdef ASH_MATH_SUPPORT
4693 * sort of a hack - expand tildes in variable
4694 * assignments (after the first '=' and after ':'s).
4697 if (flag & EXP_VARTILDE && *p == '~') {
4704 p = exptilde(p, flag);
4720 char c, *startp = p;
4723 int quotes = flag & (EXP_FULL | EXP_CASE);
4725 while ((c = *p) != '\0') {
4732 if (flag & EXP_VARTILDE)
4742 if (*(startp+1) == '\0') {
4743 if ((home = lookupvar("HOME")) == NULL)
4746 if ((pw = getpwnam(startp+1)) == NULL)
4753 strtodest(home, SQSYNTAX, quotes);
4762 removerecordregions(int endoff)
4764 if (ifslastp == NULL)
4767 if (ifsfirst.endoff > endoff) {
4768 while (ifsfirst.next != NULL) {
4769 struct ifsregion *ifsp;
4771 ifsp = ifsfirst.next->next;
4772 ckfree(ifsfirst.next);
4773 ifsfirst.next = ifsp;
4776 if (ifsfirst.begoff > endoff)
4779 ifslastp = &ifsfirst;
4780 ifsfirst.endoff = endoff;
4785 ifslastp = &ifsfirst;
4786 while (ifslastp->next && ifslastp->next->begoff < endoff)
4787 ifslastp=ifslastp->next;
4788 while (ifslastp->next != NULL) {
4789 struct ifsregion *ifsp;
4791 ifsp = ifslastp->next->next;
4792 ckfree(ifslastp->next);
4793 ifslastp->next = ifsp;
4796 if (ifslastp->endoff > endoff)
4797 ifslastp->endoff = endoff;
4801 #ifdef ASH_MATH_SUPPORT
4803 * Expand arithmetic expression. Backup to start of expression,
4804 * evaluate, place result in (backed up) result, adjust string position.
4812 int quotes = flag & (EXP_FULL | EXP_CASE);
4818 * This routine is slightly over-complicated for
4819 * efficiency. First we make sure there is
4820 * enough space for the result, which may be bigger
4821 * than the expression if we add exponentation. Next we
4822 * scan backwards looking for the start of arithmetic. If the
4823 * next previous character is a CTLESC character, then we
4824 * have to rescan starting from the beginning since CTLESC
4825 * characters have to be processed left to right.
4827 CHECKSTRSPACE(10, expdest);
4828 USTPUTC('\0', expdest);
4829 start = stackblock();
4831 while (*p != CTLARI && p >= start)
4834 error("missing CTLARI (shouldn't happen)");
4835 if (p > start && *(p-1) == CTLESC)
4836 for (p = start; *p != CTLARI; p++)
4845 removerecordregions(begoff);
4848 result = arith(p+2);
4849 snprintf(p, 12, "%d", result);
4855 recordregion(begoff, p - 1 - start, 0);
4856 result = expdest - p + 1;
4857 STADJUST(-result, expdest);
4862 * Expand stuff in backwards quotes.
4866 expbackq(cmd, quoted, flag)
4871 volatile struct backcmd in;
4875 char *dest = expdest;
4876 volatile struct ifsregion saveifs;
4877 struct ifsregion *volatile savelastp;
4878 struct nodelist *volatile saveargbackq;
4880 int startloc = dest - stackblock();
4881 char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
4882 volatile int saveherefd;
4883 int quotes = flag & (EXP_FULL | EXP_CASE);
4884 struct jmploc jmploc;
4885 struct jmploc *volatile savehandler;
4889 /* Avoid longjmp clobbering */
4900 savelastp = ifslastp;
4901 saveargbackq = argbackq;
4902 saveherefd = herefd;
4904 if ((ex = setjmp(jmploc.loc))) {
4907 savehandler = handler;
4910 p = grabstackstr(dest);
4911 evalbackcmd(cmd, (struct backcmd *) &in);
4912 ungrabstackstr(p, dest);
4916 ifslastp = savelastp;
4917 argbackq = saveargbackq;
4918 herefd = saveherefd;
4926 if (--in.nleft < 0) {
4929 while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
4930 TRACE(("expbackq: read returns %d\n", i));
4937 if (lastc != '\0') {
4938 if (quotes && syntax[(int)lastc] == CCTL)
4939 STPUTC(CTLESC, dest);
4940 STPUTC(lastc, dest);
4944 /* Eat all trailing newlines */
4945 for (; dest > stackblock() && dest[-1] == '\n';)
4954 exitstatus = waitforjob(in.jp);
4955 handler = savehandler;
4957 longjmp(handler->loc, 1);
4960 recordregion(startloc, dest - stackblock(), 0);
4961 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4962 (dest - stackblock()) - startloc,
4963 (dest - stackblock()) - startloc,
4964 stackblock() + startloc));
4970 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
4983 int saveherefd = herefd;
4984 struct nodelist *saveargbackq = argbackq;
4988 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4989 STACKSTRNUL(expdest);
4990 herefd = saveherefd;
4991 argbackq = saveargbackq;
4992 startp = stackblock() + startloc;
4994 str = stackblock() + strloc;
4998 setvar(str, startp, 0);
4999 amount = startp - expdest;
5000 STADJUST(amount, expdest);
5007 if (*p != CTLENDVAR) {
5008 out2fmt(snlfmt, startp);
5009 error((char *)NULL);
5011 error("%.*s: parameter %snot set", p - str - 1,
5012 str, (varflags & VSNUL) ? "null or "
5017 for (loc = startp; loc < str; loc++) {
5020 if (patmatch2(str, startp, quotes))
5023 if (quotes && *loc == CTLESC)
5029 for (loc = str - 1; loc >= startp;) {
5032 if (patmatch2(str, startp, quotes))
5036 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5037 for (q = startp; q < loc; q++)
5047 for (loc = str - 1; loc >= startp;) {
5048 if (patmatch2(str, loc, quotes))
5051 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5052 for (q = startp; q < loc; q++)
5061 case VSTRIMRIGHTMAX:
5062 for (loc = startp; loc < str - 1; loc++) {
5063 if (patmatch2(str, loc, quotes))
5065 if (quotes && *loc == CTLESC)
5078 amount = ((str - 1) - (loc - startp)) - expdest;
5079 STADJUST(amount, expdest);
5080 while (loc != str - 1)
5085 amount = loc - expdest;
5086 STADJUST(amount, expdest);
5087 STPUTC('\0', expdest);
5088 STADJUST(-1, expdest);
5094 * Expand a variable, and return a pointer to the next character in the
5114 int quotes = flag & (EXP_FULL | EXP_CASE);
5117 subtype = varflags & VSTYPE;
5122 p = strchr(p, '=') + 1;
5123 again: /* jump here after setting a variable with ${var=text} */
5125 set = varisset(var, varflags & VSNUL);
5128 val = lookupvar(var);
5129 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
5136 startloc = expdest - stackblock();
5137 if (set && subtype != VSPLUS) {
5138 /* insert the value of the variable */
5140 varvalue(var, varflags & VSQUOTE, flag);
5141 if (subtype == VSLENGTH) {
5142 varlen = expdest - stackblock() - startloc;
5143 STADJUST(-varlen, expdest);
5146 if (subtype == VSLENGTH) {
5147 varlen = strlen(val);
5151 varflags & VSQUOTE ?
5152 DQSYNTAX : BASESYNTAX,
5159 if (subtype == VSPLUS)
5162 easy = ((varflags & VSQUOTE) == 0 ||
5163 (*var == '@' && shellparam.nparam != 1));
5168 expdest = cvtnum(varlen, expdest);
5175 recordregion(startloc, expdest - stackblock(),
5176 varflags & VSQUOTE);
5192 case VSTRIMRIGHTMAX:
5196 * Terminate the string and start recording the pattern
5199 STPUTC('\0', expdest);
5200 patloc = expdest - stackblock();
5201 if (subevalvar(p, NULL, patloc, subtype,
5202 startloc, varflags, quotes) == 0) {
5203 int amount = (expdest - stackblock() - patloc) + 1;
5204 STADJUST(-amount, expdest);
5206 /* Remove any recorded regions beyond start of variable */
5207 removerecordregions(startloc);
5213 if (subevalvar(p, var, 0, subtype, startloc,
5214 varflags, quotes)) {
5217 * Remove any recorded regions beyond
5220 removerecordregions(startloc);
5235 if (subtype != VSNORMAL) { /* skip to end of alternative */
5238 if ((c = *p++) == CTLESC)
5240 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5242 argbackq = argbackq->next;
5243 } else if (c == CTLVAR) {
5244 if ((*p++ & VSTYPE) != VSNORMAL)
5246 } else if (c == CTLENDVAR) {
5256 * Test whether a specialized variable is set.
5260 varisset(name, nulok)
5265 return backgndpid != -1;
5266 else if (*name == '@' || *name == '*') {
5267 if (*shellparam.p == NULL)
5273 for (av = shellparam.p; *av; av++)
5278 } else if (is_digit(*name)) {
5280 int num = atoi(name);
5282 if (num > shellparam.nparam)
5288 ap = shellparam.p[num - 1];
5290 if (nulok && (ap == NULL || *ap == '\0'))
5297 * Put a string on the stack.
5301 strtodest(p, syntax, quotes)
5307 if (quotes && syntax[(int) *p] == CCTL)
5308 STPUTC(CTLESC, expdest);
5309 STPUTC(*p++, expdest);
5314 * Add the value of a specialized variable to the stack string.
5318 varvalue(name, quoted, flags)
5330 int allow_split = flags & EXP_FULL;
5331 int quotes = flags & (EXP_FULL | EXP_CASE);
5333 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5342 num = shellparam.nparam;
5347 expdest = cvtnum(num, expdest);
5350 for (i = 0 ; i < NOPTS ; i++) {
5352 STPUTC(optent_letter(optlist[i]), expdest);
5356 if (allow_split && quoted) {
5357 sep = 1 << CHAR_BIT;
5362 sep = ifsset() ? ifsval()[0] : ' ';
5364 sepq = syntax[(int) sep] == CCTL;
5367 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5368 strtodest(p, syntax, quotes);
5371 STPUTC(CTLESC, expdest);
5372 STPUTC(sep, expdest);
5377 strtodest(arg0, syntax, quotes);
5381 if (num > 0 && num <= shellparam.nparam) {
5382 strtodest(shellparam.p[num - 1], syntax, quotes);
5390 * Record the fact that we have to scan this region of the
5391 * string for IFS characters.
5395 recordregion(start, end, nulonly)
5400 struct ifsregion *ifsp;
5402 if (ifslastp == NULL) {
5406 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5408 ifslastp->next = ifsp;
5412 ifslastp->begoff = start;
5413 ifslastp->endoff = end;
5414 ifslastp->nulonly = nulonly;
5420 * Break the argument string into pieces based upon IFS and add the
5421 * strings to the argument list. The regions of the string to be
5422 * searched for IFS characters have been stored by recordregion.
5425 ifsbreakup(string, arglist)
5427 struct arglist *arglist;
5429 struct ifsregion *ifsp;
5434 const char *ifs, *realifs;
5442 realifs = ifsset() ? ifsval() : defifs;
5443 if (ifslastp != NULL) {
5446 p = string + ifsp->begoff;
5447 nulonly = ifsp->nulonly;
5448 ifs = nulonly ? nullstr : realifs;
5450 while (p < string + ifsp->endoff) {
5454 if (strchr(ifs, *p)) {
5456 ifsspc = (strchr(defifs, *p) != NULL);
5457 /* Ignore IFS whitespace at start */
5458 if (q == start && ifsspc) {
5464 sp = (struct strlist *)stalloc(sizeof *sp);
5466 *arglist->lastp = sp;
5467 arglist->lastp = &sp->next;
5471 if (p >= string + ifsp->endoff) {
5477 if (strchr(ifs, *p) == NULL ) {
5480 } else if (strchr(defifs, *p) == NULL) {
5496 } while ((ifsp = ifsp->next) != NULL);
5497 if (!(*start || (!ifsspc && start > string && nulonly))) {
5502 sp = (struct strlist *)stalloc(sizeof *sp);
5504 *arglist->lastp = sp;
5505 arglist->lastp = &sp->next;
5511 while (ifsfirst.next != NULL) {
5512 struct ifsregion *ifsp;
5514 ifsp = ifsfirst.next->next;
5515 ckfree(ifsfirst.next);
5516 ifsfirst.next = ifsp;
5520 ifsfirst.next = NULL;
5524 * Add a file name to the list.
5528 addfname(const char *name)
5534 sp = (struct strlist *)stalloc(sizeof *sp);
5537 exparg.lastp = &sp->next;
5541 * Expand shell metacharacters. At this point, the only control characters
5542 * should be escapes. The results are stored in the list exparg.
5545 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5547 expandmeta(str, flag)
5548 struct strlist *str;
5553 /* TODO - EXP_REDIR */
5558 p = preglob(str->text);
5560 switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) {
5562 if (!(pglob.gl_flags & GLOB_MAGCHAR))
5573 *exparg.lastp = str;
5574 rmescapes(str->text);
5575 exparg.lastp = &str->next;
5577 default: /* GLOB_NOSPACE */
5578 error("Out of space");
5586 * Add the result of glob(3) to the list.
5591 const glob_t *pglob;
5593 char **p = pglob->gl_pathv;
5601 #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5602 static char *expdir;
5606 expandmeta(str, flag)
5607 struct strlist *str;
5611 struct strlist **savelastp;
5614 /* TODO - EXP_REDIR */
5620 for (;;) { /* fast check for meta chars */
5621 if ((c = *p++) == '\0')
5623 if (c == '*' || c == '?' || c == '[' || c == '!')
5626 savelastp = exparg.lastp;
5628 if (expdir == NULL) {
5629 int i = strlen(str->text);
5630 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5633 expmeta(expdir, str->text);
5637 if (exparg.lastp == savelastp) {
5642 *exparg.lastp = str;
5643 rmescapes(str->text);
5644 exparg.lastp = &str->next;
5646 *exparg.lastp = NULL;
5647 *savelastp = sp = expsort(*savelastp);
5648 while (sp->next != NULL)
5650 exparg.lastp = &sp->next;
5658 * Do metacharacter (i.e. *, ?, [...]) expansion.
5662 expmeta(enddir, name)
5680 for (p = name ; ; p++) {
5681 if (*p == '*' || *p == '?')
5683 else if (*p == '[') {
5688 while (*q == CTLQUOTEMARK)
5692 if (*q == '/' || *q == '\0')
5699 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5701 } else if (*p == '\0')
5703 else if (*p == CTLQUOTEMARK)
5705 else if (*p == CTLESC)
5713 if (metaflag == 0) { /* we've reached the end of the file name */
5714 if (enddir != expdir)
5716 for (p = name ; ; p++) {
5717 if (*p == CTLQUOTEMARK)
5725 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5730 if (start != name) {
5733 while (*p == CTLQUOTEMARK)
5740 if (enddir == expdir) {
5742 } else if (enddir == expdir + 1 && *expdir == '/') {
5748 if ((dirp = opendir(cp)) == NULL)
5750 if (enddir != expdir)
5752 if (*endname == 0) {
5760 while (*p == CTLQUOTEMARK)
5766 while (! int_pending() && (dp = readdir(dirp)) != NULL) {
5767 if (dp->d_name[0] == '.' && ! matchdot)
5769 if (patmatch(start, dp->d_name, 0)) {
5771 strcpy(enddir, dp->d_name);
5774 for (p = enddir, cp = dp->d_name;
5775 (*p++ = *cp++) != '\0';)
5778 expmeta(p, endname);
5786 #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5790 #if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5792 * Sort the results of file name expansion. It calculates the number of
5793 * strings to sort and then calls msort (short for merge sort) to do the
5797 static struct strlist *
5799 struct strlist *str;
5805 for (sp = str ; sp ; sp = sp->next)
5807 return msort(str, len);
5811 static struct strlist *
5813 struct strlist *list;
5816 struct strlist *p, *q = NULL;
5817 struct strlist **lpp;
5825 for (n = half ; --n >= 0 ; ) {
5829 q->next = NULL; /* terminate first half of list */
5830 q = msort(list, half); /* sort first half of list */
5831 p = msort(p, len - half); /* sort second half */
5834 if (strcmp(p->text, q->text) < 0) {
5837 if ((p = *lpp) == NULL) {
5844 if ((q = *lpp) == NULL) {
5857 * Returns true if the pattern matches the string.
5860 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
5861 /* squoted: string might have quote chars */
5863 patmatch(char *pattern, char *string, int squoted)
5868 p = preglob(pattern);
5869 q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5871 return !fnmatch(p, q, 0);
5876 patmatch2(char *pattern, char *string, int squoted)
5882 p = grabstackstr(expdest);
5883 res = patmatch(pattern, string, squoted);
5884 ungrabstackstr(p, expdest);
5889 patmatch(char *pattern, char *string, int squoted) {
5890 return pmatch(pattern, string, squoted);
5895 pmatch(char *pattern, char *string, int squoted)
5907 if (squoted && *q == CTLESC)
5915 if (squoted && *q == CTLESC)
5922 while (c == CTLQUOTEMARK || c == '*')
5924 if (c != CTLESC && c != CTLQUOTEMARK &&
5925 c != '?' && c != '*' && c != '[') {
5927 if (squoted && *q == CTLESC &&
5932 if (squoted && *q == CTLESC)
5938 if (pmatch(p, q, squoted))
5940 if (squoted && *q == CTLESC)
5942 } while (*q++ != '\0');
5953 while (*endp == CTLQUOTEMARK)
5956 goto dft; /* no matching ] */
5957 if (*endp == CTLESC)
5969 if (squoted && chr == CTLESC)
5975 if (c == CTLQUOTEMARK)
5979 if (*p == '-' && p[1] != ']') {
5981 while (*p == CTLQUOTEMARK)
5985 if (chr >= c && chr <= *p)
5992 } while ((c = *p++) != ']');
5993 if (found == invert)
5998 if (squoted && *q == CTLESC)
6015 * Remove any CTLESC characters from a string.
6018 #if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
6020 _rmescapes(char *str, int flag)
6023 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
6025 p = strpbrk(str, qchars);
6031 if (flag & RMESCAPE_ALLOC) {
6032 size_t len = p - str;
6033 q = r = stalloc(strlen(p) + len + 1);
6036 q = mempcpy(q, str, len);
6038 memcpy(q, str, len);
6044 if (*p == CTLQUOTEMARK) {
6050 if (flag & RMESCAPE_GLOB && *p != '/') {
6067 while (*p != CTLESC && *p != CTLQUOTEMARK) {
6073 if (*p == CTLQUOTEMARK) {
6088 * See if a pattern matches in a case statement.
6092 casematch(union node *pattern, const char *val)
6094 struct stackmark smark;
6098 setstackmark(&smark);
6099 argbackq = pattern->narg.backquote;
6100 STARTSTACKSTR(expdest);
6102 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6103 STPUTC('\0', expdest);
6104 p = grabstackstr(expdest);
6105 result = patmatch(p, (char *)val, 0);
6106 popstackmark(&smark);
6121 CHECKSTRSPACE(32, buf);
6122 len = sprintf(buf, "%d", num);
6127 * Editline and history functions (and glue).
6129 static int histcmd(argc, argv)
6133 error("not compiled with history support");
6138 static int whichprompt; /* 1 == PS1, 2 == PS2 */
6142 struct redirtab *next;
6146 static struct redirtab *redirlist;
6148 extern char **environ;
6153 * Initialization code.
6166 basepf.nextc = basepf.buf = basebuf;
6175 for (envp = environ ; *envp ; envp++) {
6176 if (strchr(*envp, '=')) {
6177 setvareq(*envp, VEXPORT|VTEXTFIXED);
6181 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
6182 setvar("PPID", ppid, 0);
6189 * This routine is called when an error or an interrupt occurs in an
6190 * interactive shell and control is returned to the main command loop.
6194 /* 1 == check for aliases, 2 == also check for assignments */
6195 static int checkalias;
6210 if (exception != EXSHELLPROC)
6211 parselleft = parsenleft = 0; /* clear input buffer */
6215 /* from parser.c: */
6235 * This file implements the input routines used by the parser.
6238 #ifdef BB_FEATURE_COMMAND_EDITING
6239 unsigned int shell_context;
6240 static const char * cmdedit_prompt;
6241 static inline void putprompt(const char *s) {
6245 static inline void putprompt(const char *s) {
6250 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
6255 * Same as pgetc(), but ignores PEOA.
6265 } while (c == PEOA);
6269 static inline int pgetc2() { return pgetc_macro(); }
6273 * Read a line from the script.
6277 pfgets(char *line, int len)
6283 while (--nleft > 0) {
6302 char *buf = parsefile->buf;
6306 #ifdef BB_FEATURE_COMMAND_EDITING
6309 nr = read(parsefile->fd, buf, BUFSIZ - 1);
6312 cmdedit_read_input((char*)cmdedit_prompt, buf);
6314 } while (nr <=0 || shell_context);
6315 cmdedit_terminate();
6319 nr = read(parsefile->fd, buf, BUFSIZ - 1);
6325 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6326 int flags = fcntl(0, F_GETFL, 0);
6327 if (flags >= 0 && flags & O_NONBLOCK) {
6328 flags &=~ O_NONBLOCK;
6329 if (fcntl(0, F_SETFL, flags) >= 0) {
6330 out2str("sh: turning off NDELAY mode\n");
6342 struct strpush *sp = parsefile->strpush;
6347 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6352 if (sp->string != sp->ap->val) {
6356 sp->ap->flag &= ~ALIASINUSE;
6357 if (sp->ap->flag & ALIASDEAD) {
6358 unalias(sp->ap->name);
6362 parsenextc = sp->prevstring;
6363 parsenleft = sp->prevnleft;
6364 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6365 parsefile->strpush = sp->prev;
6366 if (sp != &(parsefile->basestrpush))
6373 * Refill the input buffer and return the next input character:
6375 * 1) If a string was pushed back on the input, pop it;
6376 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6377 * from a string so we can't refill the buffer, return EOF.
6378 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6379 * 4) Process input up to the next newline, deleting nul characters.
6389 while (parsefile->strpush) {
6391 if (parsenleft == -1 && parsefile->strpush->ap &&
6392 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6397 if (--parsenleft >= 0)
6398 return (*parsenextc++);
6400 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6405 if (parselleft <= 0) {
6406 if ((parselleft = preadfd()) <= 0) {
6407 parselleft = parsenleft = EOF_NLEFT;
6414 /* delete nul characters */
6415 for (more = 1; more;) {
6423 parsenleft = q - parsenextc;
6424 more = 0; /* Stop processing here */
6430 if (--parselleft <= 0 && more) {
6431 parsenleft = q - parsenextc - 1;
6442 out2str(parsenextc);
6447 return *parsenextc++;
6452 * Push a string back onto the input at this current parsefile level.
6453 * We handle aliases this way.
6456 pushstring(char *s, int len, void *ap)
6461 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6462 if (parsefile->strpush) {
6463 sp = ckmalloc(sizeof (struct strpush));
6464 sp->prev = parsefile->strpush;
6465 parsefile->strpush = sp;
6467 sp = parsefile->strpush = &(parsefile->basestrpush);
6468 sp->prevstring = parsenextc;
6469 sp->prevnleft = parsenleft;
6471 sp->ap = (struct alias *)ap;
6473 ((struct alias *)ap)->flag |= ALIASINUSE;
6486 * Like setinputfile, but takes input from a string.
6490 setinputstring(string)
6495 parsenextc = string;
6496 parsenleft = strlen(string);
6497 parsefile->buf = NULL;
6505 * To handle the "." command, a stack of input files is used. Pushfile
6506 * adds a new entry to the stack and popfile restores the previous level.
6511 struct parsefile *pf;
6513 parsefile->nleft = parsenleft;
6514 parsefile->lleft = parselleft;
6515 parsefile->nextc = parsenextc;
6516 parsefile->linno = plinno;
6517 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6518 pf->prev = parsefile;
6521 pf->basestrpush.prev = NULL;
6526 static void restartjob (struct job *);
6528 static void freejob (struct job *);
6529 static struct job *getjob (const char *);
6530 static int dowait (int, struct job *);
6531 static int waitproc (int, int *);
6532 static void waitonint(int);
6536 * We keep track of whether or not fd0 has been redirected. This is for
6537 * background commands, where we want to redirect fd0 to /dev/null only
6538 * if it hasn't already been redirected.
6540 static int fd0_redirected = 0;
6542 /* Return true if fd 0 has already been redirected at least once. */
6544 fd0_redirected_p () {
6545 return fd0_redirected != 0;
6548 static int openredirect (union node *);
6549 static void dupredirect (union node *, int, char[10 ]);
6550 static int openhere (union node *);
6551 static int noclobberopen (const char *);
6557 * Turn job control on and off.
6559 * Note: This code assumes that the third arg to ioctl is a character
6560 * pointer, which is true on Berkeley systems but not System V. Since
6561 * System V doesn't have job control yet, this isn't a problem now.
6566 static void setjobctl(int enable)
6568 #ifdef OLD_TTY_DRIVER
6572 if (enable == jobctl || rootshell == 0)
6575 do { /* while we are in the background */
6576 #ifdef OLD_TTY_DRIVER
6577 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6579 initialpgrp = tcgetpgrp(2);
6580 if (initialpgrp < 0) {
6582 out2str("sh: can't access tty; job cenabletrol turned off\n");
6586 if (initialpgrp == -1)
6587 initialpgrp = getpgrp();
6588 else if (initialpgrp != getpgrp()) {
6589 killpg(initialpgrp, SIGTTIN);
6593 #ifdef OLD_TTY_DRIVER
6594 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6595 out2str("sh: need new tty driver to run job cenabletrol; job cenabletrol turned off\n");
6603 setpgid(0, rootpid);
6604 #ifdef OLD_TTY_DRIVER
6605 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6607 tcsetpgrp(2, rootpid);
6609 } else { /* turning job cenabletrol off */
6610 setpgid(0, initialpgrp);
6611 #ifdef OLD_TTY_DRIVER
6612 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6614 tcsetpgrp(2, initialpgrp);
6625 /* A translation list so we can be polite to our users. */
6626 static char *signal_names[NSIG + 2] = {
6712 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6713 "kill -l [exitstatus]"
6717 if (*argv[1] == '-') {
6718 signo = decode_signal(argv[1] + 1, 1);
6722 while ((c = nextopt("ls:")) != '\0')
6728 signo = decode_signal(optionarg, 1);
6731 "invalid signal number or name: %s",
6739 "nextopt returned character code 0%o", c);
6746 if (!list && signo < 0)
6749 if ((signo < 0 || !*argptr) ^ list) {
6756 for (i = 1; i < NSIG; i++) {
6757 out1fmt(snlfmt, signal_names[i] + 3);
6761 signo = atoi(*argptr);
6764 if (0 < signo && signo < NSIG)
6765 out1fmt(snlfmt, signal_names[signo] + 3);
6767 error("invalid signal number or exit status: %s",
6773 if (**argptr == '%') {
6774 jp = getjob(*argptr);
6775 if (jp->jobctl == 0)
6776 error("job %s not created under job control",
6778 pid = -jp->ps[0].pid;
6780 pid = atoi(*argptr);
6781 if (kill(pid, signo) != 0)
6782 error("%s: %m", *argptr);
6783 } while (*++argptr);
6797 jp = getjob(argv[1]);
6798 if (jp->jobctl == 0)
6799 error("job not created under job control");
6800 pgrp = jp->ps[0].pid;
6801 #ifdef OLD_TTY_DRIVER
6802 ioctl(2, TIOCSPGRP, (char *)&pgrp);
6808 status = waitforjob(jp);
6822 jp = getjob(*++argv);
6823 if (jp->jobctl == 0)
6824 error("job not created under job control");
6826 } while (--argc > 1);
6835 struct procstat *ps;
6838 if (jp->state == JOBDONE)
6841 killpg(jp->ps[0].pid, SIGCONT);
6842 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6843 if (WIFSTOPPED(ps->status)) {
6852 static void showjobs(int change);
6866 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6867 * statuses have changed since the last call to showjobs.
6869 * If the shell is interrupted in the process of creating a job, the
6870 * result may be a job structure containing zero processes. Such structures
6871 * will be freed here.
6882 struct procstat *ps;
6886 TRACE(("showjobs(%d) called\n", change));
6887 while (dowait(0, (struct job *)NULL) > 0);
6888 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6891 if (jp->nprocs == 0) {
6895 if (change && ! jp->changed)
6897 procno = jp->nprocs;
6898 for (ps = jp->ps ; ; ps++) { /* for each process */
6900 snprintf(s, 64, "[%d] %ld ", jobno,
6903 snprintf(s, 64, " %ld ",
6908 if (ps->status == -1) {
6909 /* don't print anything */
6910 } else if (WIFEXITED(ps->status)) {
6911 snprintf(s, 64, "Exit %d",
6912 WEXITSTATUS(ps->status));
6915 if (WIFSTOPPED(ps->status))
6916 i = WSTOPSIG(ps->status);
6917 else /* WIFSIGNALED(ps->status) */
6919 i = WTERMSIG(ps->status);
6920 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6921 strcpy(s, sys_siglist[i & 0x7F]);
6923 snprintf(s, 64, "Signal %d", i & 0x7F);
6924 if (WCOREDUMP(ps->status))
6925 strcat(s, " (core dumped)");
6930 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6937 if (jp->state == JOBDONE) {
6945 * Mark a job structure as unused.
6952 struct procstat *ps;
6956 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6957 if (ps->cmd != nullstr)
6960 if (jp->ps != &jp->ps0)
6964 if (curjob == jp - jobtab + 1)
6983 job = getjob(*++argv);
6987 for (;;) { /* loop until process terminated or stopped */
6990 status = job->ps[job->nprocs - 1].status;
6996 if (WIFEXITED(status))
6997 retval = WEXITSTATUS(status);
6999 else if (WIFSTOPPED(status))
7000 retval = WSTOPSIG(status) + 128;
7003 /* XXX: limits number of signals */
7004 retval = WTERMSIG(status) + 128;
7009 for (jp = jobtab ; ; jp++) {
7010 if (jp >= jobtab + njobs) { /* no running procs */
7013 if (jp->used && jp->state == 0)
7017 if (dowait(2, 0) < 0 && errno == EINTR) {
7026 * Convert a job name to a job structure.
7030 getjob(const char *name)
7040 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
7041 error("No current job");
7042 return &jobtab[jobno - 1];
7044 error("No current job");
7046 } else if (name[0] == '%') {
7047 if (is_digit(name[1])) {
7048 jobno = number(name + 1);
7049 if (jobno > 0 && jobno <= njobs
7050 && jobtab[jobno - 1].used != 0)
7051 return &jobtab[jobno - 1];
7053 } else if (name[1] == '%' && name[2] == '\0') {
7057 struct job *found = NULL;
7058 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
7059 if (jp->used && jp->nprocs > 0
7060 && prefix(name + 1, jp->ps[0].cmd)) {
7062 error("%s: ambiguous", name);
7069 } else if (is_number(name, &pid)) {
7070 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
7071 if (jp->used && jp->nprocs > 0
7072 && jp->ps[jp->nprocs - 1].pid == pid)
7076 error("No such job: %s", name);
7083 * Return a new job structure,
7087 makejob(node, nprocs)
7094 for (i = njobs, jp = jobtab ; ; jp++) {
7098 jobtab = ckmalloc(4 * sizeof jobtab[0]);
7100 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
7101 memcpy(jp, jobtab, njobs * sizeof jp[0]);
7102 /* Relocate `ps' pointers */
7103 for (i = 0; i < njobs; i++)
7104 if (jp[i].ps == &jobtab[i].ps0)
7105 jp[i].ps = &jp[i].ps0;
7109 jp = jobtab + njobs;
7110 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
7123 jp->jobctl = jobctl;
7126 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7131 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7138 * Fork of a subshell. If we are doing job control, give the subshell its
7139 * own process group. Jp is a job structure that the job is to be added to.
7140 * N is the command that will be evaluated by the child. Both jp and n may
7141 * be NULL. The mode parameter can be one of the following:
7142 * FORK_FG - Fork off a foreground process.
7143 * FORK_BG - Fork off a background process.
7144 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7145 * process group even if job control is on.
7147 * When job control is turned off, background processes have their standard
7148 * input redirected to /dev/null (except for the second and later processes
7155 forkshell(struct job *jp, union node *n, int mode)
7159 const char *devnull = _PATH_DEVNULL;
7160 const char *nullerr = "Can't open %s";
7162 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
7167 TRACE(("Fork failed, errno=%d\n", errno));
7169 error("Cannot fork");
7176 TRACE(("Child shell %d\n", getpid()));
7177 wasroot = rootshell;
7183 jobctl = 0; /* do job control only in root shell */
7184 if (wasroot && mode != FORK_NOJOB && mflag) {
7185 if (jp == NULL || jp->nprocs == 0)
7188 pgrp = jp->ps[0].pid;
7190 if (mode == FORK_FG) {
7191 /*** this causes superfluous TIOCSPGRPS ***/
7192 #ifdef OLD_TTY_DRIVER
7193 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
7194 error("TIOCSPGRP failed, errno=%d", errno);
7196 if (tcsetpgrp(2, pgrp) < 0)
7197 error("tcsetpgrp failed, errno=%d", errno);
7202 } else if (mode == FORK_BG) {
7205 if ((jp == NULL || jp->nprocs == 0) &&
7206 ! fd0_redirected_p ()) {
7208 if (open(devnull, O_RDONLY) != 0)
7209 error(nullerr, devnull);
7213 if (mode == FORK_BG) {
7216 if ((jp == NULL || jp->nprocs == 0) &&
7217 ! fd0_redirected_p ()) {
7219 if (open(devnull, O_RDONLY) != 0)
7220 error(nullerr, devnull);
7224 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
7227 if (wasroot && iflag) {
7234 if (rootshell && mode != FORK_NOJOB && mflag) {
7235 if (jp == NULL || jp->nprocs == 0)
7238 pgrp = jp->ps[0].pid;
7241 if (mode == FORK_BG)
7242 backgndpid = pid; /* set $! */
7244 struct procstat *ps = &jp->ps[jp->nprocs++];
7248 if (iflag && rootshell && n)
7249 ps->cmd = commandtext(n);
7252 TRACE(("In parent shell: child = %d\n", pid));
7259 * Wait for job to finish.
7261 * Under job control we have the problem that while a child process is
7262 * running interrupts generated by the user are sent to the child but not
7263 * to the shell. This means that an infinite loop started by an inter-
7264 * active user may be hard to kill. With job control turned off, an
7265 * interactive user may place an interactive program inside a loop. If
7266 * the interactive program catches interrupts, the user doesn't want
7267 * these interrupts to also abort the loop. The approach we take here
7268 * is to have the shell ignore interrupt signals while waiting for a
7269 * forground process to terminate, and then send itself an interrupt
7270 * signal if the child process was terminated by an interrupt signal.
7271 * Unfortunately, some programs want to do a bit of cleanup and then
7272 * exit on interrupt; unless these processes terminate themselves by
7273 * sending a signal to themselves (instead of calling exit) they will
7274 * confuse this approach.
7282 int mypgrp = getpgrp();
7286 struct sigaction act, oact;
7295 sigaction(SIGINT, 0, &act);
7296 act.sa_handler = waitonint;
7297 sigaction(SIGINT, &act, &oact);
7299 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7300 while (jp->state == 0) {
7308 sigaction(SIGINT, &oact, 0);
7309 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7313 #ifdef OLD_TTY_DRIVER
7314 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7315 error("TIOCSPGRP failed, errno=%d\n", errno);
7317 if (tcsetpgrp(2, mypgrp) < 0)
7318 error("tcsetpgrp failed, errno=%d\n", errno);
7321 if (jp->state == JOBSTOPPED)
7322 curjob = jp - jobtab + 1;
7324 status = jp->ps[jp->nprocs - 1].status;
7325 /* convert to 8 bits */
7326 if (WIFEXITED(status))
7327 st = WEXITSTATUS(status);
7329 else if (WIFSTOPPED(status))
7330 st = WSTOPSIG(status) + 128;
7333 st = WTERMSIG(status) + 128;
7337 * This is truly gross.
7338 * If we're doing job control, then we did a TIOCSPGRP which
7339 * caused us (the shell) to no longer be in the controlling
7340 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7341 * intuit from the subprocess exit status whether a SIGINT
7342 * occured, and if so interrupt ourselves. Yuck. - mycroft
7344 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7347 if (jp->state == JOBDONE)
7358 * Wait for a process to terminate.
7368 struct procstat *sp;
7370 struct job *thisjob;
7376 TRACE(("dowait(%d) called\n", block));
7378 pid = waitproc(block, &status);
7379 TRACE(("wait returns %d, status=%d\n", pid, status));
7380 } while (!(block & 2) && pid == -1 && errno == EINTR);
7385 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7389 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7392 if (sp->pid == pid) {
7393 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7394 sp->status = status;
7397 if (sp->status == -1)
7399 else if (WIFSTOPPED(sp->status))
7402 if (stopped) { /* stopped or done */
7403 int state = done? JOBDONE : JOBSTOPPED;
7404 if (jp->state != state) {
7405 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7408 if (done && curjob == jp - jobtab + 1)
7409 curjob = 0; /* no current job */
7416 if (! rootshell || ! iflag || (job && thisjob == job)) {
7417 core = WCOREDUMP(status);
7419 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7422 if (WIFEXITED(status)) sig = 0;
7423 else sig = WTERMSIG(status);
7425 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7427 out2fmt("%d: ", pid);
7429 if (sig == SIGTSTP && rootshell && iflag)
7431 (long)(job - jobtab + 1));
7433 if (sig < NSIG && sys_siglist[sig])
7434 out2str(sys_siglist[sig]);
7436 out2fmt("Signal %d", sig);
7438 out2str(" - core dumped");
7441 TRACE(("Not printing status: status=%d, sig=%d\n",
7445 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7447 thisjob->changed = 1;
7455 * Do a wait system call. If job control is compiled in, we accept
7456 * stopped processes. If block is zero, we return a value of zero
7457 * rather than blocking.
7459 * System V doesn't have a non-blocking wait system call. It does
7460 * have a SIGCLD signal that is sent to a process when one of it's
7461 * children dies. The obvious way to use SIGCLD would be to install
7462 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7463 * was received, and have waitproc bump another counter when it got
7464 * the status of a process. Waitproc would then know that a wait
7465 * system call would not block if the two counters were different.
7466 * This approach doesn't work because if a process has children that
7467 * have not been waited for, System V will send it a SIGCLD when it
7468 * installs a signal handler for SIGCLD. What this means is that when
7469 * a child exits, the shell will be sent SIGCLD signals continuously
7470 * until is runs out of stack space, unless it does a wait call before
7471 * restoring the signal handler. The code below takes advantage of
7472 * this (mis)feature by installing a signal handler for SIGCLD and
7473 * then checking to see whether it was called. If there are any
7474 * children to be waited for, it will be.
7479 waitproc(block, status)
7492 return wait3(status, flags, (struct rusage *)NULL);
7496 * return 1 if there are stopped jobs, otherwise 0
7506 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7509 if (jp->state == JOBSTOPPED) {
7510 out2str("You have stopped jobs.\n");
7520 * Return a string identifying a command (to be printed by the
7524 static char *cmdnextc;
7525 static int cmdnleft;
7526 #define MAXCMDTEXT 200
7529 cmdputs(const char *s)
7540 while ((c = *p++) != '\0') {
7543 else if (c == CTLVAR) {
7548 } else if (c == '=' && subtype != 0) {
7549 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7551 } else if (c == CTLENDVAR) {
7553 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7554 cmdnleft++; /* ignore it */
7557 if (--cmdnleft <= 0) {
7569 cmdtxt(const union node *n)
7572 struct nodelist *lp;
7581 cmdtxt(n->nbinary.ch1);
7583 cmdtxt(n->nbinary.ch2);
7586 cmdtxt(n->nbinary.ch1);
7588 cmdtxt(n->nbinary.ch2);
7591 cmdtxt(n->nbinary.ch1);
7593 cmdtxt(n->nbinary.ch2);
7596 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7604 cmdtxt(n->nredir.n);
7609 cmdtxt(n->nredir.n);
7613 cmdtxt(n->nif.test);
7615 cmdtxt(n->nif.ifpart);
7624 cmdtxt(n->nbinary.ch1);
7626 cmdtxt(n->nbinary.ch2);
7631 cmdputs(n->nfor.var);
7636 cmdputs(n->ncase.expr->narg.text);
7640 cmdputs(n->narg.text);
7644 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7649 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7655 cmdputs(n->narg.text);
7658 p = ">"; i = 1; goto redir;
7660 p = ">>"; i = 1; goto redir;
7662 p = ">&"; i = 1; goto redir;
7664 p = ">|"; i = 1; goto redir;
7666 p = "<"; i = 0; goto redir;
7668 p = "<&"; i = 0; goto redir;
7670 p = "<>"; i = 0; goto redir;
7672 if (n->nfile.fd != i) {
7673 s[0] = n->nfile.fd + '0';
7678 if (n->type == NTOFD || n->type == NFROMFD) {
7679 s[0] = n->ndup.dupfd + '0';
7683 cmdtxt(n->nfile.fname);
7698 commandtext(const union node *n)
7702 cmdnextc = name = ckmalloc(MAXCMDTEXT);
7703 cmdnleft = MAXCMDTEXT - 4;
7710 static void waitonint(int sig) {
7715 * Routines to check for mail. (Perhaps make part of main.c?)
7719 #define MAXMBOXES 10
7722 static int nmboxes; /* number of mailboxes */
7723 static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
7728 * Print appropriate message(s) if mail has arrived. If the argument is
7729 * nozero, then the value of MAIL has changed, so we just update the
7740 struct stackmark smark;
7747 setstackmark(&smark);
7748 mpath = mpathset()? mpathval() : mailval();
7749 for (i = 0 ; i < nmboxes ; i++) {
7750 p = padvance(&mpath, nullstr);
7755 for (q = p ; *q ; q++);
7760 q[-1] = '\0'; /* delete trailing '/' */
7761 if (stat(p, &statb) < 0)
7763 if (statb.st_size > mailtime[i] && ! silent) {
7765 pathopt? pathopt : "you have mail");
7767 mailtime[i] = statb.st_size;
7770 popstackmark(&smark);
7776 static short profile_buf[16384];
7780 static void read_profile (const char *);
7781 static char *find_dot_file (char *);
7782 static void cmdloop (int);
7783 static void options (int);
7784 static void minus_o (char *, int);
7785 static void setoption (int, int);
7786 static void procargs (int, char **);
7790 * Main routine. We initialize things, parse the arguments, execute
7791 * profiles if we're a login shell, and then call cmdloop to execute
7792 * commands. The setjmp call sets up the location to jump to when an
7793 * exception occurs. When an exception occurs the variable "state"
7794 * is used to figure out how far we had gotten.
7798 shell_main(argc, argv)
7802 struct jmploc jmploc;
7803 struct stackmark smark;
7807 DOTCMD = find_builtin(".");
7808 BLTINCMD = find_builtin("builtin");
7809 EXECCMD = find_builtin("exec");
7810 EVALCMD = find_builtin("eval");
7812 #ifndef BB_FEATURE_SH_FANCY_PROMPT
7818 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7820 #if defined(linux) || defined(__GNU__)
7821 signal(SIGCHLD, SIG_DFL);
7824 if (setjmp(jmploc.loc)) {
7827 * When a shell procedure is executed, we raise the
7828 * exception EXSHELLPROC to clean up before executing
7829 * the shell procedure.
7831 switch (exception) {
7840 exitstatus = exerrno;
7851 if (exception != EXSHELLPROC) {
7852 if (state == 0 || iflag == 0 || ! rootshell)
7853 exitshell(exitstatus);
7856 if (exception == EXINT) {
7859 popstackmark(&smark);
7860 FORCEINTON; /* enable interrupts */
7863 else if (state == 2)
7865 else if (state == 3)
7873 trputs("Shell args: "); trargs(argv);
7878 setstackmark(&smark);
7879 procargs(argc, argv);
7880 if (argv[0] && argv[0][0] == '-') {
7882 read_profile("/etc/profile");
7885 read_profile(".profile");
7890 if (getuid() == geteuid() && getgid() == getegid()) {
7892 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7894 read_profile(shinit);
7901 if (sflag == 0 || minusc) {
7902 static int sigs[] = {
7903 SIGINT, SIGQUIT, SIGHUP,
7909 #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
7912 for (i = 0; i < SIGSSIZE; i++)
7917 evalstring(minusc, 0);
7919 if (sflag || minusc == NULL) {
7920 state4: /* XXX ??? - why isn't this before the "if" statement */
7926 exitshell(exitstatus);
7932 * Read and execute commands. "Top" is nonzero for the top level command
7933 * loop; it turns on prompting if the shell is interactive.
7940 struct stackmark smark;
7944 TRACE(("cmdloop(%d) called\n", top));
7945 setstackmark(&smark);
7956 n = parsecmd(inter);
7957 /* showtree(n); DEBUG */
7959 if (!top || numeof >= 50)
7961 if (!stoppedjobs()) {
7964 out2str("\nUse \"exit\" to leave shell.\n");
7967 } else if (n != NULL && nflag == 0) {
7968 job_warning = (job_warning == 2) ? 1 : 0;
7972 popstackmark(&smark);
7973 setstackmark(&smark);
7974 if (evalskip == SKIPFILE) {
7979 popstackmark(&smark);
7985 * Read /etc/profile or .profile. Return on error.
7997 if ((fd = open(name, O_RDONLY)) >= 0)
8002 /* -q turns off -x and -v just when executing init files */
8005 xflag = 0, xflag_set = 1;
8007 vflag = 0, vflag_set = 1;
8022 * Read a file containing shell functions.
8026 readcmdfile(const char *name)
8031 if ((fd = open(name, O_RDONLY)) >= 0)
8034 error("Can't open %s", name);
8043 * Take commands from a file. To be compatable we should do a path
8044 * search for the file, which is necessary to find sub-commands.
8049 find_dot_file(mybasename)
8053 const char *path = pathval();
8056 /* don't try this for absolute or relative paths */
8057 if (strchr(mybasename, '/'))
8060 while ((fullname = padvance(&path, mybasename)) != NULL) {
8061 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8063 * Don't bother freeing here, since it will
8064 * be freed by the caller.
8068 stunalloc(fullname);
8071 /* not found in the PATH */
8072 error("%s: not found", mybasename);
8084 for (sp = cmdenviron; sp ; sp = sp->next)
8085 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
8087 if (argc >= 2) { /* That's what SVR2 does */
8089 struct stackmark smark;
8091 setstackmark(&smark);
8092 fullname = find_dot_file(argv[1]);
8093 setinputfile(fullname, 1);
8094 commandname = fullname;
8097 popstackmark(&smark);
8111 exitstatus = number(argv[1]);
8113 exitstatus = oexitstatus;
8114 exitshell(exitstatus);
8122 nbytes = ALIGN(nbytes);
8123 if (nbytes > stacknleft) {
8125 struct stack_block *sp;
8128 if (blocksize < MINSIZE)
8129 blocksize = MINSIZE;
8131 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
8133 stacknxt = sp->space;
8134 stacknleft = blocksize;
8140 stacknleft -= nbytes;
8146 stunalloc(pointer p)
8149 if (p == NULL) { /*DEBUG */
8150 write(2, "stunalloc\n", 10);
8154 if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
8157 stacknleft += stacknxt - (char *)p;
8163 setstackmark(struct stackmark *mark)
8165 mark->stackp = stackp;
8166 mark->stacknxt = stacknxt;
8167 mark->stacknleft = stacknleft;
8168 mark->marknext = markp;
8174 popstackmark(struct stackmark *mark)
8176 struct stack_block *sp;
8179 markp = mark->marknext;
8180 while (stackp != mark->stackp) {
8185 stacknxt = mark->stacknxt;
8186 stacknleft = mark->stacknleft;
8192 * When the parser reads in a string, it wants to stick the string on the
8193 * stack and only adjust the stack pointer when it knows how big the
8194 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8195 * of space on top of the stack and stackblocklen returns the length of
8196 * this block. Growstackblock will grow this space by at least one byte,
8197 * possibly moving it (like realloc). Grabstackblock actually allocates the
8198 * part of the block that has been used.
8202 growstackblock(void) {
8204 int newlen = ALIGN(stacknleft * 2 + 100);
8205 char *oldspace = stacknxt;
8206 int oldlen = stacknleft;
8207 struct stack_block *sp;
8208 struct stack_block *oldstackp;
8210 if (stacknxt == stackp->space && stackp != &stackbase) {
8215 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8218 stacknxt = sp->space;
8219 stacknleft = newlen;
8221 /* Stack marks pointing to the start of the old block
8222 * must be relocated to point to the new block
8224 struct stackmark *xmark;
8226 while (xmark != NULL && xmark->stackp == oldstackp) {
8227 xmark->stackp = stackp;
8228 xmark->stacknxt = stacknxt;
8229 xmark->stacknleft = stacknleft;
8230 xmark = xmark->marknext;
8235 p = stalloc(newlen);
8236 memcpy(p, oldspace, oldlen);
8237 stacknxt = p; /* free the space */
8238 stacknleft += newlen; /* we just allocated */
8245 grabstackblock(int len)
8255 * The following routines are somewhat easier to use that the above.
8256 * The user declares a variable of type STACKSTR, which may be declared
8257 * to be a register. The macro STARTSTACKSTR initializes things. Then
8258 * the user uses the macro STPUTC to add characters to the string. In
8259 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8260 * grown as necessary. When the user is done, she can just leave the
8261 * string there and refer to it using stackblock(). Or she can allocate
8262 * the space for it using grabstackstr(). If it is necessary to allow
8263 * someone else to use the stack temporarily and then continue to grow
8264 * the string, the user should use grabstack to allocate the space, and
8265 * then call ungrabstr(p) to return to the previous mode of operation.
8267 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8268 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8269 * is space for at least one character.
8274 growstackstr(void) {
8275 int len = stackblocksize();
8276 if (herefd >= 0 && len >= 1024) {
8277 xwrite(herefd, stackblock(), len);
8278 sstrnleft = len - 1;
8279 return stackblock();
8282 sstrnleft = stackblocksize() - len - 1;
8283 return stackblock() + len;
8288 * Called from CHECKSTRSPACE.
8292 makestrspace(size_t newlen) {
8293 int len = stackblocksize() - sstrnleft;
8296 sstrnleft = stackblocksize() - len;
8297 } while (sstrnleft < newlen);
8298 return stackblock() + len;
8304 ungrabstackstr(char *s, char *p)
8306 stacknleft += stacknxt - s;
8308 sstrnleft = stacknleft - (p - s);
8311 * Miscelaneous builtins.
8318 static mode_t getmode(const void *, mode_t);
8319 static void *setmode(const char *);
8321 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8322 typedef enum __rlimit_resource rlim_t;
8329 * The read builtin. The -e option causes backslashes to escape the
8330 * following character.
8332 * This uses unbuffered input, which may be avoidable in some cases.
8353 while ((i = nextopt("p:r")) != '\0') {
8359 if (prompt && isatty(0)) {
8363 if (*(ap = argptr) == NULL)
8365 if ((ifs = bltinlookup("IFS")) == NULL)
8372 if (read(0, &c, 1) != 1) {
8384 if (!rflag && c == '\\') {
8390 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8394 if (backslash && c == '\\') {
8395 if (read(0, &c, 1) != 1) {
8400 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8402 setvar(*ap, stackblock(), 0);
8411 /* Remove trailing blanks */
8412 while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8414 setvar(*ap, stackblock(), 0);
8415 while (*++ap != NULL)
8416 setvar(*ap, nullstr, 0);
8423 umaskcmd(argc, argv)
8430 int symbolic_mode = 0;
8432 while ((i = nextopt("S")) != '\0') {
8441 if ((ap = *argptr) == NULL) {
8442 if (symbolic_mode) {
8443 char u[4], g[4], o[4];
8446 if ((mask & S_IRUSR) == 0)
8448 if ((mask & S_IWUSR) == 0)
8450 if ((mask & S_IXUSR) == 0)
8455 if ((mask & S_IRGRP) == 0)
8457 if ((mask & S_IWGRP) == 0)
8459 if ((mask & S_IXGRP) == 0)
8464 if ((mask & S_IROTH) == 0)
8466 if ((mask & S_IWOTH) == 0)
8468 if ((mask & S_IXOTH) == 0)
8472 out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
8474 out1fmt("%.4o\n", mask);
8477 if (isdigit((unsigned char)*ap)) {
8480 if (*ap >= '8' || *ap < '0')
8481 error("Illegal number: %s", argv[1]);
8482 mask = (mask << 3) + (*ap - '0');
8483 } while (*++ap != '\0');
8489 if ((set = setmode(ap)) != 0) {
8490 mask = getmode(set, ~mask & 0777);
8495 error("Illegal mode: %s", ap);
8497 umask(~mask & 0777);
8506 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8507 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8508 * ash by J.T. Conklin.
8516 int factor; /* multiply by to get rlim_{cur,max} values */
8520 static const struct limits limits[] = {
8522 { "time(seconds)", RLIMIT_CPU, 1, 't' },
8525 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
8528 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
8531 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
8534 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
8537 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
8539 #ifdef RLIMIT_MEMLOCK
8540 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
8543 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
8545 #ifdef RLIMIT_NOFILE
8546 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
8549 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
8552 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
8554 { (char *) 0, 0, 0, '\0' }
8558 ulimitcmd(argc, argv)
8564 enum { SOFT = 0x1, HARD = 0x2 }
8566 const struct limits *l;
8569 struct rlimit limit;
8572 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
8587 for (l = limits; l->name && l->option != what; l++)
8590 error("internal error (%c)", what);
8592 set = *argptr ? 1 : 0;
8596 if (all || argptr[1])
8597 error("too many arguments");
8598 if (strcmp(p, "unlimited") == 0)
8599 val = RLIM_INFINITY;
8603 while ((c = *p++) >= '0' && c <= '9')
8605 val = (val * 10) + (long)(c - '0');
8606 if (val < (rlim_t) 0)
8610 error("bad number");
8615 for (l = limits; l->name; l++) {
8616 getrlimit(l->cmd, &limit);
8618 val = limit.rlim_cur;
8619 else if (how & HARD)
8620 val = limit.rlim_max;
8622 out1fmt("%-20s ", l->name);
8623 if (val == RLIM_INFINITY)
8624 out1fmt("unlimited\n");
8628 out1fmt("%lld\n", (long long) val);
8634 getrlimit(l->cmd, &limit);
8637 limit.rlim_max = val;
8639 limit.rlim_cur = val;
8640 if (setrlimit(l->cmd, &limit) < 0)
8641 error("error setting limit (%m)");
8644 val = limit.rlim_cur;
8645 else if (how & HARD)
8646 val = limit.rlim_max;
8648 if (val == RLIM_INFINITY)
8649 out1fmt("unlimited\n");
8653 out1fmt("%lld\n", (long long) val);
8659 * prefix -- see if pfx is a prefix of string.
8668 if (*pfx++ != *string++)
8675 * Return true if s is a string of digits, and save munber in intptr
8680 is_number(const char *p, int *intptr)
8688 ret += digit_val(*p);
8690 } while (*p != '\0');
8697 * Convert a string of digits to an integer, printing an error message on
8702 number(const char *s)
8705 if (! is_number(s, &i))
8706 error("Illegal number: %s", s);
8711 * Produce a possibly single quoted string suitable as input to the shell.
8712 * The return string is allocated on the stack.
8716 single_quote(const char *s) {
8723 size_t len1, len1p, len2, len2p;
8725 len1 = strcspn(s, "'");
8726 len2 = strspn(s + len1, "'");
8728 len1p = len1 ? len1 + 2 : len1;
8740 CHECKSTRSPACE(len1p + len2p + 1, p);
8745 q = mempcpy(p + 1, s, len1);
8748 memcpy(p + 1, s, len1);
8765 *(char *) mempcpy(q + 1, s, len2) = '"';
8768 memcpy(q + 1, s, len2);
8774 STADJUST(len1p + len2p, p);
8779 return grabstackstr(p);
8783 * Like strdup but works with the ash stack.
8787 sstrdup(const char *p)
8789 size_t len = strlen(p) + 1;
8790 return memcpy(stalloc(len), p, len);
8795 * This file was generated by the mknodes program.
8799 * Routine for dealing with parsed shell commands.
8803 static int funcblocksize; /* size of structures in function */
8804 static int funcstringsize; /* size of strings in node */
8805 static pointer funcblock; /* block to allocate function from */
8806 static char *funcstring; /* block to allocate strings from */
8808 static const short nodesize[26] = {
8809 ALIGN(sizeof (struct nbinary)),
8810 ALIGN(sizeof (struct ncmd)),
8811 ALIGN(sizeof (struct npipe)),
8812 ALIGN(sizeof (struct nredir)),
8813 ALIGN(sizeof (struct nredir)),
8814 ALIGN(sizeof (struct nredir)),
8815 ALIGN(sizeof (struct nbinary)),
8816 ALIGN(sizeof (struct nbinary)),
8817 ALIGN(sizeof (struct nif)),
8818 ALIGN(sizeof (struct nbinary)),
8819 ALIGN(sizeof (struct nbinary)),
8820 ALIGN(sizeof (struct nfor)),
8821 ALIGN(sizeof (struct ncase)),
8822 ALIGN(sizeof (struct nclist)),
8823 ALIGN(sizeof (struct narg)),
8824 ALIGN(sizeof (struct narg)),
8825 ALIGN(sizeof (struct nfile)),
8826 ALIGN(sizeof (struct nfile)),
8827 ALIGN(sizeof (struct nfile)),
8828 ALIGN(sizeof (struct nfile)),
8829 ALIGN(sizeof (struct nfile)),
8830 ALIGN(sizeof (struct ndup)),
8831 ALIGN(sizeof (struct ndup)),
8832 ALIGN(sizeof (struct nhere)),
8833 ALIGN(sizeof (struct nhere)),
8834 ALIGN(sizeof (struct nnot)),
8838 static void calcsize (union node *);
8839 static void sizenodelist (struct nodelist *);
8840 static union node *copynode (union node *);
8841 static struct nodelist *copynodelist (struct nodelist *);
8842 static char *nodesavestr (char *);
8847 * Make a copy of a parse tree.
8851 copyfunc(union node *n)
8858 funcblock = ckmalloc(funcblocksize + funcstringsize);
8859 funcstring = (char *) funcblock + funcblocksize;
8871 funcblocksize += nodesize[n->type];
8878 calcsize(n->nbinary.ch2);
8879 calcsize(n->nbinary.ch1);
8882 calcsize(n->ncmd.redirect);
8883 calcsize(n->ncmd.args);
8884 calcsize(n->ncmd.assign);
8887 sizenodelist(n->npipe.cmdlist);
8892 calcsize(n->nredir.redirect);
8893 calcsize(n->nredir.n);
8896 calcsize(n->nif.elsepart);
8897 calcsize(n->nif.ifpart);
8898 calcsize(n->nif.test);
8901 funcstringsize += strlen(n->nfor.var) + 1;
8902 calcsize(n->nfor.body);
8903 calcsize(n->nfor.args);
8906 calcsize(n->ncase.cases);
8907 calcsize(n->ncase.expr);
8910 calcsize(n->nclist.body);
8911 calcsize(n->nclist.pattern);
8912 calcsize(n->nclist.next);
8916 sizenodelist(n->narg.backquote);
8917 funcstringsize += strlen(n->narg.text) + 1;
8918 calcsize(n->narg.next);
8925 calcsize(n->nfile.fname);
8926 calcsize(n->nfile.next);
8930 calcsize(n->ndup.vname);
8931 calcsize(n->ndup.next);
8935 calcsize(n->nhere.doc);
8936 calcsize(n->nhere.next);
8939 calcsize(n->nnot.com);
8948 struct nodelist *lp;
8951 funcblocksize += ALIGN(sizeof(struct nodelist));
8968 funcblock = (char *) funcblock + nodesize[n->type];
8975 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8976 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8979 new->ncmd.redirect = copynode(n->ncmd.redirect);
8980 new->ncmd.args = copynode(n->ncmd.args);
8981 new->ncmd.assign = copynode(n->ncmd.assign);
8982 new->ncmd.backgnd = n->ncmd.backgnd;
8985 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8986 new->npipe.backgnd = n->npipe.backgnd;
8991 new->nredir.redirect = copynode(n->nredir.redirect);
8992 new->nredir.n = copynode(n->nredir.n);
8995 new->nif.elsepart = copynode(n->nif.elsepart);
8996 new->nif.ifpart = copynode(n->nif.ifpart);
8997 new->nif.test = copynode(n->nif.test);
9000 new->nfor.var = nodesavestr(n->nfor.var);
9001 new->nfor.body = copynode(n->nfor.body);
9002 new->nfor.args = copynode(n->nfor.args);
9005 new->ncase.cases = copynode(n->ncase.cases);
9006 new->ncase.expr = copynode(n->ncase.expr);
9009 new->nclist.body = copynode(n->nclist.body);
9010 new->nclist.pattern = copynode(n->nclist.pattern);
9011 new->nclist.next = copynode(n->nclist.next);
9015 new->narg.backquote = copynodelist(n->narg.backquote);
9016 new->narg.text = nodesavestr(n->narg.text);
9017 new->narg.next = copynode(n->narg.next);
9024 new->nfile.fname = copynode(n->nfile.fname);
9025 new->nfile.fd = n->nfile.fd;
9026 new->nfile.next = copynode(n->nfile.next);
9030 new->ndup.vname = copynode(n->ndup.vname);
9031 new->ndup.dupfd = n->ndup.dupfd;
9032 new->ndup.fd = n->ndup.fd;
9033 new->ndup.next = copynode(n->ndup.next);
9037 new->nhere.doc = copynode(n->nhere.doc);
9038 new->nhere.fd = n->nhere.fd;
9039 new->nhere.next = copynode(n->nhere.next);
9042 new->nnot.com = copynode(n->nnot.com);
9045 new->type = n->type;
9050 static struct nodelist *
9052 struct nodelist *lp;
9054 struct nodelist *start;
9055 struct nodelist **lpp;
9060 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
9061 (*lpp)->n = copynode(lp->n);
9063 lpp = &(*lpp)->next;
9076 char *rtn = funcstring;
9078 funcstring = stpcpy(funcstring, s) + 1;
9081 register char *p = s;
9082 register char *q = funcstring;
9083 char *rtn = funcstring;
9085 while ((*q++ = *p++) != '\0')
9093 static int getopts (char *, char *, char **, int *, int *);
9098 * Process the shell command line arguments.
9102 procargs(argc, argv)
9111 for (i = 0; i < NOPTS; i++)
9114 if (*argptr == NULL && minusc == NULL)
9116 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
9120 for (i = 0; i < NOPTS; i++)
9121 if (optent_val(i) == 2)
9124 if (sflag == 0 && minusc == NULL) {
9125 commandname = argv[0];
9127 setinputfile(arg0, 0);
9130 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
9131 if (argptr && minusc && *argptr)
9134 shellparam.p = argptr;
9135 shellparam.optind = 1;
9136 shellparam.optoff = -1;
9137 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
9139 shellparam.nparam++;
9148 * Process shell options. The global variable argptr contains a pointer
9149 * to the argument list; we advance it past the options.
9162 while ((p = *argptr) != NULL) {
9164 if ((c = *p++) == '-') {
9166 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
9168 /* "-" means turn off -x and -v */
9171 /* "--" means reset params */
9172 else if (*argptr == NULL)
9175 break; /* "-" or "--" terminates options */
9177 } else if (c == '+') {
9183 while ((c = *p++) != '\0') {
9184 if (c == 'c' && cmdline) {
9186 #ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
9190 if (q == NULL || minusc != NULL)
9191 error("Bad -c option");
9196 } else if (c == 'o') {
9197 minus_o(*argptr, val);
9215 out1str("Current option settings\n");
9216 for (i = 0; i < NOPTS; i++)
9217 out1fmt("%-16s%s\n", optent_name(optlist[i]),
9218 optent_val(i) ? "on" : "off");
9220 for (i = 0; i < NOPTS; i++)
9221 if (equal(name, optent_name(optlist[i]))) {
9222 setoption(optent_letter(optlist[i]), val);
9225 error("Illegal option -o %s", name);
9231 setoption(int flag, int val)
9235 for (i = 0; i < NOPTS; i++)
9236 if (optent_letter(optlist[i]) == flag) {
9237 optent_val(i) = val;
9239 /* #%$ hack for ksh semantics */
9242 else if (flag == 'E')
9247 error("Illegal option -%c", flag);
9254 * Set the shell parameters.
9258 setparam(char **argv)
9264 for (nparam = 0 ; argv[nparam] ; nparam++);
9265 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9267 *ap++ = savestr(*argv++);
9270 freeparam(&shellparam);
9271 shellparam.malloc = 1;
9272 shellparam.nparam = nparam;
9273 shellparam.p = newparam;
9274 shellparam.optind = 1;
9275 shellparam.optoff = -1;
9280 * Free the list of positional parameters.
9284 freeparam(volatile struct shparam *param)
9288 if (param->malloc) {
9289 for (ap = param->p ; *ap ; ap++)
9298 * The shift builtin command.
9302 shiftcmd(argc, argv)
9311 n = number(argv[1]);
9312 if (n > shellparam.nparam)
9313 error("can't shift that many");
9315 shellparam.nparam -= n;
9316 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9317 if (shellparam.malloc)
9321 while ((*ap2++ = *ap1++) != NULL);
9322 shellparam.optind = 1;
9323 shellparam.optoff = -1;
9331 * The set command builtin.
9340 return showvarscmd(argc, argv);
9344 if (*argptr != NULL) {
9353 getoptsreset(const char *value)
9355 shellparam.optind = number(value);
9356 shellparam.optoff = -1;
9359 #ifdef BB_LOCALE_SUPPORT
9360 static void change_lc_all(const char *value)
9362 if(value != 0 && *value != 0)
9363 setlocale(LC_ALL, value);
9366 static void change_lc_ctype(const char *value)
9368 if(value != 0 && *value != 0)
9369 setlocale(LC_CTYPE, value);
9376 * The getopts builtin. Shellparam.optnext points to the next argument
9377 * to be processed. Shellparam.optptr points to the next character to
9378 * be processed in the current argument. If shellparam.optnext is NULL,
9379 * then it's the first time getopts has been called.
9383 getoptscmd(argc, argv)
9390 error("Usage: getopts optstring var [arg]");
9391 else if (argc == 3) {
9392 optbase = shellparam.p;
9393 if (shellparam.optind > shellparam.nparam + 1) {
9394 shellparam.optind = 1;
9395 shellparam.optoff = -1;
9400 if (shellparam.optind > argc - 2) {
9401 shellparam.optind = 1;
9402 shellparam.optoff = -1;
9406 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9407 &shellparam.optoff);
9411 * Safe version of setvar, returns 1 on success 0 on failure.
9415 setvarsafe(name, val, flags)
9416 const char *name, *val;
9419 struct jmploc jmploc;
9420 struct jmploc *volatile savehandler = handler;
9426 if (setjmp(jmploc.loc))
9430 setvar(name, val, flags);
9432 handler = savehandler;
9437 getopts(optstr, optvar, optfirst, myoptind, optoff)
9449 char **optnext = optfirst + *myoptind - 1;
9451 if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9452 strlen(*(optnext - 1)) < *optoff)
9455 p = *(optnext - 1) + *optoff;
9456 if (p == NULL || *p == '\0') {
9457 /* Current word is done, advance */
9458 if (optnext == NULL)
9461 if (p == NULL || *p != '-' || *++p == '\0') {
9463 *myoptind = optnext - optfirst + 1;
9469 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9474 for (q = optstr; *q != c; ) {
9476 if (optstr[0] == ':') {
9479 err |= setvarsafe("OPTARG", s, 0);
9482 out2fmt("Illegal option -%c\n", c);
9483 (void) unsetvar("OPTARG");
9493 if (*p == '\0' && (p = *optnext) == NULL) {
9494 if (optstr[0] == ':') {
9497 err |= setvarsafe("OPTARG", s, 0);
9501 out2fmt("No arg for -%c option\n", c);
9502 (void) unsetvar("OPTARG");
9510 setvarsafe("OPTARG", p, 0);
9514 setvarsafe("OPTARG", "", 0);
9515 *myoptind = optnext - optfirst + 1;
9522 *optoff = p ? p - *(optnext - 1) : -1;
9523 snprintf(s, sizeof(s), "%d", *myoptind);
9524 err |= setvarsafe("OPTIND", s, VNOFUNC);
9527 err |= setvarsafe(optvar, s, 0);
9539 * XXX - should get rid of. have all builtins use getopt(3). the
9540 * library getopt must have the BSD extension static variable "optreset"
9541 * otherwise it can't be used within the shell safely.
9543 * Standard option processing (a la getopt) for builtin routines. The
9544 * only argument that is passed to nextopt is the option string; the
9545 * other arguments are unnecessary. It return the character, or '\0' on
9551 const char *optstring;
9557 if ((p = optptr) == NULL || *p == '\0') {
9559 if (p == NULL || *p != '-' || *++p == '\0')
9562 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9566 for (q = optstring ; *q != c ; ) {
9568 error("Illegal option -%c", c);
9573 if (*p == '\0' && (p = *argptr++) == NULL)
9574 error("No arg for -%c option", c);
9591 out2fmt(const char *fmt, ...)
9595 vfprintf(stderr, fmt, ap);
9601 out1fmt(const char *fmt, ...)
9605 vfprintf(stdout, fmt, ap);
9610 * Version of write which resumes after a signal is caught.
9614 xwrite(int fd, const char *buf, int nbytes)
9623 i = write(fd, buf, n);
9629 } else if (i == 0) {
9632 } else if (errno != EINTR) {
9640 * Shell command parser.
9643 #define EOFMARKLEN 79
9648 struct heredoc *next; /* next here document in list */
9649 union node *here; /* redirection node */
9650 char *eofmark; /* string indicating end of input */
9651 int striptabs; /* if set, strip leading tabs */
9654 static struct heredoc *heredoclist; /* list of here documents to read */
9655 static int parsebackquote; /* nonzero if we are inside backquotes */
9656 static int doprompt; /* if set, prompt the user */
9657 static int needprompt; /* true if interactive and at start of line */
9658 static int lasttoken; /* last token read */
9660 static char *wordtext; /* text of last word returned by readtoken */
9662 static struct nodelist *backquotelist;
9663 static union node *redirnode;
9664 struct heredoc *heredoc;
9665 static int quoteflag; /* set if (part of) last token was quoted */
9666 static int startlinno; /* line # where last token started */
9669 static union node *list (int);
9670 static union node *andor (void);
9671 static union node *pipeline (void);
9672 static union node *command (void);
9673 static union node *simplecmd (void);
9674 static void parsefname (void);
9675 static void parseheredoc (void);
9676 static int peektoken (void);
9677 static int readtoken (void);
9678 static int xxreadtoken (void);
9679 static int readtoken1 (int, char const *, char *, int);
9680 static int noexpand (char *);
9681 static void synexpect (int) __attribute__((noreturn));
9682 static void synerror (const char *) __attribute__((noreturn));
9683 static void setprompt (int);
9687 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9688 * valid parse tree indicating a blank line.)
9692 parsecmd(int interact)
9697 doprompt = interact;
9717 union node *n1, *n2, *n3;
9721 if (nlflag == 0 && tokendlist[peektoken()])
9727 if (tok == TBACKGND) {
9728 if (n2->type == NCMD || n2->type == NPIPE) {
9729 n2->ncmd.backgnd = 1;
9730 } else if (n2->type == NREDIR) {
9731 n2->type = NBACKGND;
9733 n3 = (union node *)stalloc(sizeof (struct nredir));
9734 n3->type = NBACKGND;
9736 n3->nredir.redirect = NULL;
9744 n3 = (union node *)stalloc(sizeof (struct nbinary));
9746 n3->nbinary.ch1 = n1;
9747 n3->nbinary.ch2 = n2;
9764 if (tokendlist[peektoken()])
9771 pungetc(); /* push back EOF on input */
9786 union node *n1, *n2, *n3;
9792 if ((t = readtoken()) == TAND) {
9794 } else if (t == TOR) {
9802 n3 = (union node *)stalloc(sizeof (struct nbinary));
9804 n3->nbinary.ch1 = n1;
9805 n3->nbinary.ch2 = n2;
9814 union node *n1, *n2, *pipenode;
9815 struct nodelist *lp, *prev;
9819 TRACE(("pipeline: entered\n"));
9820 if (readtoken() == TNOT) {
9826 if (readtoken() == TPIPE) {
9827 pipenode = (union node *)stalloc(sizeof (struct npipe));
9828 pipenode->type = NPIPE;
9829 pipenode->npipe.backgnd = 0;
9830 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9831 pipenode->npipe.cmdlist = lp;
9835 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9839 } while (readtoken() == TPIPE);
9845 n2 = (union node *)stalloc(sizeof (struct nnot));
9857 union node *n1, *n2;
9858 union node *ap, **app;
9859 union node *cp, **cpp;
9860 union node *redir, **rpp;
9867 switch (readtoken()) {
9869 n1 = (union node *)stalloc(sizeof (struct nif));
9871 n1->nif.test = list(0);
9872 if (readtoken() != TTHEN)
9874 n1->nif.ifpart = list(0);
9876 while (readtoken() == TELIF) {
9877 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9878 n2 = n2->nif.elsepart;
9880 n2->nif.test = list(0);
9881 if (readtoken() != TTHEN)
9883 n2->nif.ifpart = list(0);
9885 if (lasttoken == TELSE)
9886 n2->nif.elsepart = list(0);
9888 n2->nif.elsepart = NULL;
9891 if (readtoken() != TFI)
9898 n1 = (union node *)stalloc(sizeof (struct nbinary));
9899 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9900 n1->nbinary.ch1 = list(0);
9901 if ((got=readtoken()) != TDO) {
9902 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
9905 n1->nbinary.ch2 = list(0);
9906 if (readtoken() != TDONE)
9912 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9913 synerror("Bad for loop variable");
9914 n1 = (union node *)stalloc(sizeof (struct nfor));
9916 n1->nfor.var = wordtext;
9918 if (readtoken() == TIN) {
9920 while (readtoken() == TWORD) {
9921 n2 = (union node *)stalloc(sizeof (struct narg));
9923 n2->narg.text = wordtext;
9924 n2->narg.backquote = backquotelist;
9926 app = &n2->narg.next;
9930 if (lasttoken != TNL && lasttoken != TSEMI)
9933 static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9935 n2 = (union node *)stalloc(sizeof (struct narg));
9937 n2->narg.text = argvars;
9938 n2->narg.backquote = NULL;
9939 n2->narg.next = NULL;
9942 * Newline or semicolon here is optional (but note
9943 * that the original Bourne shell only allowed NL).
9945 if (lasttoken != TNL && lasttoken != TSEMI)
9949 if (readtoken() != TDO)
9951 n1->nfor.body = list(0);
9952 if (readtoken() != TDONE)
9957 n1 = (union node *)stalloc(sizeof (struct ncase));
9959 if (readtoken() != TWORD)
9961 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9963 n2->narg.text = wordtext;
9964 n2->narg.backquote = backquotelist;
9965 n2->narg.next = NULL;
9968 } while (readtoken() == TNL);
9969 if (lasttoken != TIN)
9970 synerror("expecting \"in\"");
9971 cpp = &n1->ncase.cases;
9972 checkkwd = 2, readtoken();
9974 if (lasttoken == TLP)
9976 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9978 app = &cp->nclist.pattern;
9980 *app = ap = (union node *)stalloc(sizeof (struct narg));
9982 ap->narg.text = wordtext;
9983 ap->narg.backquote = backquotelist;
9984 if (checkkwd = 2, readtoken() != TPIPE)
9986 app = &ap->narg.next;
9989 ap->narg.next = NULL;
9990 if (lasttoken != TRP)
9992 cp->nclist.body = list(0);
9995 if ((t = readtoken()) != TESAC) {
9997 synexpect(TENDCASE);
9999 checkkwd = 2, readtoken();
10001 cpp = &cp->nclist.next;
10002 } while(lasttoken != TESAC);
10007 n1 = (union node *)stalloc(sizeof (struct nredir));
10008 n1->type = NSUBSHELL;
10009 n1->nredir.n = list(0);
10010 n1->nredir.redirect = NULL;
10011 if (readtoken() != TRP)
10017 if (readtoken() != TEND)
10021 /* Handle an empty command like other simple commands. */
10030 * An empty command before a ; doesn't make much sense, and
10031 * should certainly be disallowed in the case of `if ;'.
10045 /* Now check for redirection which may follow command */
10046 while (readtoken() == TREDIR) {
10047 *rpp = n2 = redirnode;
10048 rpp = &n2->nfile.next;
10054 if (n1->type != NSUBSHELL) {
10055 n2 = (union node *)stalloc(sizeof (struct nredir));
10060 n1->nredir.redirect = redir;
10067 static union node *
10069 union node *args, **app;
10070 union node *n = NULL;
10071 union node *vars, **vpp;
10072 union node **rpp, *redir;
10085 switch (readtoken()) {
10088 n = (union node *)stalloc(sizeof (struct narg));
10090 n->narg.text = wordtext;
10091 n->narg.backquote = backquotelist;
10092 if (lasttoken == TWORD) {
10094 app = &n->narg.next;
10097 vpp = &n->narg.next;
10101 *rpp = n = redirnode;
10102 rpp = &n->nfile.next;
10103 parsefname(); /* read name of redirection file */
10107 args && app == &args->narg.next &&
10110 /* We have a function */
10111 if (readtoken() != TRP)
10115 n->narg.next = command();
10128 n = (union node *)stalloc(sizeof (struct ncmd));
10130 n->ncmd.backgnd = 0;
10131 n->ncmd.args = args;
10132 n->ncmd.assign = vars;
10133 n->ncmd.redirect = redir;
10137 static union node *
10141 n = (union node *)stalloc(sizeof (struct narg));
10143 n->narg.next = NULL;
10144 n->narg.text = wordtext;
10145 n->narg.backquote = backquotelist;
10149 static void fixredir(union node *n, const char *text, int err)
10151 TRACE(("Fix redir %s %d\n", text, err));
10153 n->ndup.vname = NULL;
10155 if (is_digit(text[0]) && text[1] == '\0')
10156 n->ndup.dupfd = digit_val(text[0]);
10157 else if (text[0] == '-' && text[1] == '\0')
10158 n->ndup.dupfd = -1;
10162 synerror("Bad fd number");
10164 n->ndup.vname = makename();
10171 union node *n = redirnode;
10173 if (readtoken() != TWORD)
10175 if (n->type == NHERE) {
10176 struct heredoc *here = heredoc;
10180 if (quoteflag == 0)
10182 TRACE(("Here document %d\n", n->type));
10183 if (here->striptabs) {
10184 while (*wordtext == '\t')
10187 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10188 synerror("Illegal eof marker for << redirection");
10189 rmescapes(wordtext);
10190 here->eofmark = wordtext;
10192 if (heredoclist == NULL)
10193 heredoclist = here;
10195 for (p = heredoclist ; p->next ; p = p->next);
10198 } else if (n->type == NTOFD || n->type == NFROMFD) {
10199 fixredir(n, wordtext, 0);
10201 n->nfile.fname = makename();
10207 * Input any here documents.
10212 struct heredoc *here;
10215 while (heredoclist) {
10216 here = heredoclist;
10217 heredoclist = here->next;
10222 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10223 here->eofmark, here->striptabs);
10224 n = (union node *)stalloc(sizeof (struct narg));
10225 n->narg.type = NARG;
10226 n->narg.next = NULL;
10227 n->narg.text = wordtext;
10228 n->narg.backquote = backquotelist;
10229 here->here->nhere.doc = n;
10246 int savecheckkwd = checkkwd;
10247 int savecheckalias = checkalias;
10252 int alreadyseen = tokpushback;
10262 checkalias = savecheckalias;
10269 if (checkkwd == 2) {
10278 * check for keywords
10280 if (t == TWORD && !quoteflag)
10282 const char *const *pp;
10284 if ((pp = findkwd(wordtext))) {
10285 lasttoken = t = pp - parsekwd + KWDOFFSET;
10286 TRACE(("keyword %s recognized\n", tokname[t]));
10297 } else if (checkalias == 2 && isassignment(wordtext)) {
10298 lasttoken = t = TASSIGN;
10299 } else if (checkalias) {
10300 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10302 pushstring(ap->val, strlen(ap->val), ap);
10304 checkkwd = savecheckkwd;
10313 TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10315 TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10322 * Read the next input token.
10323 * If the token is a word, we set backquotelist to the list of cmds in
10324 * backquotes. We set quoteflag to true if any part of the word was
10326 * If the token is TREDIR, then we set redirnode to a structure containing
10328 * In all cases, the variable startlinno is set to the number of the line
10329 * on which the token starts.
10331 * [Change comment: here documents and internal procedures]
10332 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10333 * word parsing code into a separate routine. In this case, readtoken
10334 * doesn't need to have any internal procedures, but parseword does.
10335 * We could also make parseoperator in essence the main routine, and
10336 * have parseword (readtoken1?) handle both words and redirection.]
10339 #define RETURN(token) return lasttoken = token
10353 startlinno = plinno;
10354 for (;;) { /* until token or start of word found */
10357 case ' ': case '\t':
10363 while ((c = pgetc()) != '\n' && c != PEOF);
10367 if (pgetc() == '\n') {
10368 startlinno = ++plinno;
10379 needprompt = doprompt;
10384 if (pgetc() == '&')
10389 if (pgetc() == '|')
10394 if (pgetc() == ';')
10407 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10414 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10415 * is not NULL, read a here document. In the latter case, eofmark is the
10416 * word which marks the end of the document and striptabs is true if
10417 * leading tabs should be stripped from the document. The argument firstc
10418 * is the first character of the input token or document.
10420 * Because C does not have internal subroutines, I have simulated them
10421 * using goto's to implement the subroutine linkage. The following macros
10422 * will run code that appears at the end of readtoken1.
10425 #define CHECKEND() {goto checkend; checkend_return:;}
10426 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10427 #define PARSESUB() {goto parsesub; parsesub_return:;}
10428 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10429 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10430 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10433 readtoken1(firstc, syntax, eofmark, striptabs)
10435 char const *syntax;
10442 char line[EOFMARKLEN + 1];
10443 struct nodelist *bqlist;
10446 int varnest; /* levels of variables expansion */
10447 int arinest; /* levels of arithmetic expansion */
10448 int parenlevel; /* levels of parens in arithmetic */
10449 int dqvarnest; /* levels of variables expansion within double quotes */
10451 char const *prevsyntax; /* syntax before arithmetic */
10453 /* Avoid longjmp clobbering */
10459 (void) &parenlevel;
10462 (void) &prevsyntax;
10466 startlinno = plinno;
10468 if (syntax == DQSYNTAX)
10477 STARTSTACKSTR(out);
10478 loop: { /* for each line, until end of word */
10479 CHECKEND(); /* set c to PEOF if at end of here document */
10480 for (;;) { /* until end of line or end of word */
10481 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10482 switch(syntax[c]) {
10483 case CNL: /* '\n' */
10484 if (syntax == BASESYNTAX)
10485 goto endword; /* exit outer loop */
10493 goto loop; /* continue outer loop */
10498 if ((eofmark == NULL || dblquote) &&
10500 USTPUTC(CTLESC, out);
10503 case CBACK: /* backslash */
10506 USTPUTC('\\', out);
10508 } else if (c == '\n') {
10514 if (dblquote && c != '\\' && c != '`' && c != '$'
10515 && (c != '"' || eofmark != NULL))
10516 USTPUTC('\\', out);
10517 if (SQSYNTAX[c] == CCTL)
10518 USTPUTC(CTLESC, out);
10519 else if (eofmark == NULL)
10520 USTPUTC(CTLQUOTEMARK, out);
10526 if (eofmark == NULL)
10527 USTPUTC(CTLQUOTEMARK, out);
10531 if (eofmark == NULL)
10532 USTPUTC(CTLQUOTEMARK, out);
10537 if (eofmark != NULL && arinest == 0 &&
10542 syntax = ARISYNTAX;
10544 } else if (eofmark == NULL &&
10546 syntax = BASESYNTAX;
10552 case CVAR: /* '$' */
10553 PARSESUB(); /* parse substitution */
10555 case CENDVAR: /* '}' */
10558 if (dqvarnest > 0) {
10561 USTPUTC(CTLENDVAR, out);
10566 #ifdef ASH_MATH_SUPPORT
10567 case CLP: /* '(' in arithmetic */
10571 case CRP: /* ')' in arithmetic */
10572 if (parenlevel > 0) {
10576 if (pgetc() == ')') {
10577 if (--arinest == 0) {
10578 USTPUTC(CTLENDARI, out);
10579 syntax = prevsyntax;
10580 if (syntax == DQSYNTAX)
10588 * unbalanced parens
10589 * (don't 2nd guess - no error)
10597 case CBQUOTE: /* '`' */
10601 goto endword; /* exit outer loop */
10606 goto endword; /* exit outer loop */
10617 if (syntax == ARISYNTAX)
10618 synerror("Missing '))'");
10619 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10620 synerror("Unterminated quoted string");
10621 if (varnest != 0) {
10622 startlinno = plinno;
10623 synerror("Missing '}'");
10625 USTPUTC('\0', out);
10626 len = out - stackblock();
10627 out = stackblock();
10628 if (eofmark == NULL) {
10629 if ((c == '>' || c == '<')
10632 && (*out == '\0' || is_digit(*out))) {
10634 return lasttoken = TREDIR;
10639 quoteflag = quotef;
10640 backquotelist = bqlist;
10641 grabstackblock(len);
10643 return lasttoken = TWORD;
10644 /* end of readtoken routine */
10649 * Check to see whether we are at the end of the here document. When this
10650 * is called, c is set to the first character of the next input line. If
10651 * we are at the end of the here document, this routine sets the c to PEOF.
10662 while (c == '\t') {
10666 if (c == *eofmark) {
10667 if (pfgets(line, sizeof line) != NULL) {
10671 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10672 if (*p == '\n' && *q == '\0') {
10675 needprompt = doprompt;
10677 pushstring(line, strlen(line), NULL);
10682 goto checkend_return;
10687 * Parse a redirection operator. The variable "out" points to a string
10688 * specifying the fd to be redirected. The variable "c" contains the
10689 * first character of the redirection operator.
10696 np = (union node *)stalloc(sizeof (struct nfile));
10701 np->type = NAPPEND;
10710 } else { /* c == '<' */
10712 switch (c = pgetc()) {
10714 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10715 np = (union node *)stalloc(sizeof (struct nhere));
10719 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10720 heredoc->here = np;
10721 if ((c = pgetc()) == '-') {
10722 heredoc->striptabs = 1;
10724 heredoc->striptabs = 0;
10730 np->type = NFROMFD;
10734 np->type = NFROMTO;
10744 np->nfile.fd = digit_val(fd);
10746 goto parseredir_return;
10751 * Parse a substitution. At this point, we have read the dollar sign
10752 * and nothing else.
10760 static const char types[] = "}-+?=";
10765 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10769 } else if (c == '(') { /* $(command) or $((arith)) */
10770 if (pgetc() == '(') {
10777 USTPUTC(CTLVAR, out);
10778 typeloc = out - stackblock();
10779 USTPUTC(VSNORMAL, out);
10780 subtype = VSNORMAL;
10784 if ((c = pgetc()) == '}')
10787 subtype = VSLENGTH;
10792 if (c > PEOA && is_name(c)) {
10796 } while (c > PEOA && is_in_name(c));
10797 } else if (is_digit(c)) {
10801 } while (is_digit(c));
10803 else if (is_special(c)) {
10808 badsub: synerror("Bad substitution");
10812 if (subtype == 0) {
10819 p = strchr(types, c);
10822 subtype = p - types + VSNORMAL;
10828 subtype = c == '#' ? VSTRIMLEFT :
10841 if (dblquote || arinest)
10843 *(stackblock() + typeloc) = subtype | flags;
10844 if (subtype != VSNORMAL) {
10851 goto parsesub_return;
10856 * Called to parse command substitutions. Newstyle is set if the command
10857 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10858 * list of commands (passed by reference), and savelen is the number of
10859 * characters on the top of the stack which must be preserved.
10863 struct nodelist **nlpp;
10866 char *volatile str;
10867 struct jmploc jmploc;
10868 struct jmploc *volatile savehandler;
10872 (void) &saveprompt;
10875 savepbq = parsebackquote;
10876 if (setjmp(jmploc.loc)) {
10879 parsebackquote = 0;
10880 handler = savehandler;
10881 longjmp(handler->loc, 1);
10885 savelen = out - stackblock();
10887 str = ckmalloc(savelen);
10888 memcpy(str, stackblock(), savelen);
10890 savehandler = handler;
10894 /* We must read until the closing backquote, giving special
10895 treatment to some slashes, and then push the string and
10896 reread it as input, interpreting it normally. */
10903 STARTSTACKSTR(pout);
10909 switch (pc = pgetc()) {
10914 if ((pc = pgetc()) == '\n') {
10921 * If eating a newline, avoid putting
10922 * the newline into the new character
10923 * stream (via the STPUTC after the
10928 if (pc != '\\' && pc != '`' && pc != '$'
10929 && (!dblquote || pc != '"'))
10930 STPUTC('\\', pout);
10940 startlinno = plinno;
10941 synerror("EOF in backquote substitution");
10945 needprompt = doprompt;
10954 STPUTC('\0', pout);
10955 psavelen = pout - stackblock();
10956 if (psavelen > 0) {
10957 pstr = grabstackstr(pout);
10958 setinputstring(pstr);
10963 nlpp = &(*nlpp)->next;
10964 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10965 (*nlpp)->next = NULL;
10966 parsebackquote = oldstyle;
10969 saveprompt = doprompt;
10976 doprompt = saveprompt;
10978 if (readtoken() != TRP)
10985 * Start reading from old file again, ignoring any pushed back
10986 * tokens left from the backquote parsing
10991 while (stackblocksize() <= savelen)
10993 STARTSTACKSTR(out);
10995 memcpy(out, str, savelen);
10996 STADJUST(savelen, out);
11002 parsebackquote = savepbq;
11003 handler = savehandler;
11004 if (arinest || dblquote)
11005 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11007 USTPUTC(CTLBACKQ, out);
11009 goto parsebackq_oldreturn;
11011 goto parsebackq_newreturn;
11015 * Parse an arithmetic expansion (indicate start of one and set state)
11019 if (++arinest == 1) {
11020 prevsyntax = syntax;
11021 syntax = ARISYNTAX;
11022 USTPUTC(CTLARI, out);
11029 * we collapse embedded arithmetic expansion to
11030 * parenthesis, which should be equivalent
11034 goto parsearith_return;
11037 } /* end of readtoken */
11041 * Returns true if the text contains nothing to expand (no dollar signs
11053 while ((c = *p++) != '\0') {
11054 if (c == CTLQUOTEMARK)
11058 else if (BASESYNTAX[(int)c] == CCTL)
11066 * Return true if the argument is a legal variable name (a letter or
11067 * underscore followed by zero or more letters, underscores, and digits).
11071 goodname(const char *name)
11079 if (! is_in_name(*p))
11087 * Called when an unexpected token is read during the parse. The argument
11088 * is the token that is expected, or -1 if more than one type of token can
11089 * occur at this point.
11099 snprintf(msg, 64, "%s unexpected (expecting %s)",
11100 tokname[lasttoken], tokname[token]);
11102 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
11110 synerror(const char *msg)
11113 out2fmt("%s: %d: ", commandname, startlinno);
11114 out2fmt("Syntax error: %s\n", msg);
11115 error((char *)NULL);
11121 * called by editline -- any expansions to the prompt
11122 * should be added here.
11124 static inline const char *
11125 getprompt(void *unused)
11127 switch (whichprompt) {
11135 return "<internal prompt error>";
11140 setprompt(int which)
11142 whichprompt = which;
11143 putprompt(getprompt(NULL));
11148 * Code for dealing with input/output redirection.
11151 #define EMPTY -2 /* marks an unused slot in redirtab */
11153 # define PIPESIZE 4096 /* amount of buffering in a pipe */
11155 # define PIPESIZE PIPE_BUF
11161 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11162 * old file descriptors are stashed away so that the redirection can be
11163 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11164 * standard output, and the standard error if it becomes a duplicate of
11169 redirect(redir, flags)
11174 struct redirtab *sv = NULL;
11179 char memory[10]; /* file descriptors to write to memory */
11181 for (i = 10 ; --i >= 0 ; )
11183 memory[1] = flags & REDIR_BACKQ;
11184 if (flags & REDIR_PUSH) {
11185 sv = ckmalloc(sizeof (struct redirtab));
11186 for (i = 0 ; i < 10 ; i++)
11187 sv->renamed[i] = EMPTY;
11188 sv->next = redirlist;
11191 for (n = redir ; n ; n = n->nfile.next) {
11194 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11195 n->ndup.dupfd == fd)
11196 continue; /* redirect from/to same file descriptor */
11199 newfd = openredirect(n);
11200 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11203 } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11207 dupredirect(n, newfd, memory);
11217 error("%d: %m", fd);
11223 if (flags & REDIR_PUSH) {
11224 sv->renamed[fd] = i;
11227 } else if (fd != newfd) {
11233 dupredirect(n, newfd, memory);
11240 openredirect(redir)
11246 switch (redir->nfile.type) {
11248 fname = redir->nfile.expfname;
11249 if ((f = open(fname, O_RDONLY)) < 0)
11253 fname = redir->nfile.expfname;
11254 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11258 /* Take care of noclobber mode. */
11260 fname = redir->nfile.expfname;
11261 if ((f = noclobberopen(fname)) < 0)
11266 fname = redir->nfile.expfname;
11268 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11271 if ((f = creat(fname, 0666)) < 0)
11276 fname = redir->nfile.expfname;
11278 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11281 if ((f = open(fname, O_WRONLY)) < 0
11282 && (f = creat(fname, 0666)) < 0)
11284 lseek(f, (off_t)0, 2);
11291 /* Fall through to eliminate warning. */
11298 f = openhere(redir);
11304 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11306 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11311 dupredirect(union node *redir, int f, char memory[10])
11313 int fd = redir->nfile.fd;
11316 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11317 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11318 if (memory[redir->ndup.dupfd])
11321 dup_as_newfd(redir->ndup.dupfd, fd);
11327 dup_as_newfd(f, fd);
11335 * Handle here documents. Normally we fork off a process to write the
11336 * data to a pipe. If the document is short, we can stuff the data in
11337 * the pipe without forking.
11348 error("Pipe call failed");
11349 if (redir->type == NHERE) {
11350 len = strlen(redir->nhere.doc->narg.text);
11351 if (len <= PIPESIZE) {
11352 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11356 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11358 signal(SIGINT, SIG_IGN);
11359 signal(SIGQUIT, SIG_IGN);
11360 signal(SIGHUP, SIG_IGN);
11362 signal(SIGTSTP, SIG_IGN);
11364 signal(SIGPIPE, SIG_DFL);
11365 if (redir->type == NHERE)
11366 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11368 expandhere(redir->nhere.doc, pip[1]);
11378 * Undo the effects of the last redirection.
11384 struct redirtab *rp = redirlist;
11388 for (i = 0 ; i < 10 ; i++) {
11389 if (rp->renamed[i] != EMPTY) {
11393 if (rp->renamed[i] >= 0) {
11394 dup_as_newfd(rp->renamed[i], i);
11395 close(rp->renamed[i]);
11399 redirlist = rp->next;
11405 * Discard all saved file descriptors.
11410 struct redirtab *rp;
11413 for (rp = redirlist ; rp ; rp = rp->next) {
11414 for (i = 0 ; i < 10 ; i++) {
11415 if (rp->renamed[i] >= 0) {
11416 close(rp->renamed[i]);
11418 rp->renamed[i] = EMPTY;
11425 * Copy a file descriptor to be >= to. Returns -1
11426 * if the source file descriptor is closed, EMPTY if there are no unused
11427 * file descriptors left.
11431 dup_as_newfd(from, to)
11437 newfd = fcntl(from, F_DUPFD, to);
11439 if (errno == EMFILE)
11442 error("%d: %m", from);
11448 * Open a file in noclobber mode.
11449 * The code was copied from bash.
11452 noclobberopen(const char *fname)
11455 struct stat finfo, finfo2;
11458 * If the file exists and is a regular file, return an error
11461 r = stat(fname, &finfo);
11462 if (r == 0 && S_ISREG(finfo.st_mode)) {
11468 * If the file was not present (r != 0), make sure we open it
11469 * exclusively so that if it is created before we open it, our open
11470 * will fail. Make sure that we do not truncate an existing file.
11471 * Note that we don't turn on O_EXCL unless the stat failed -- if the
11472 * file was not a regular file, we leave O_EXCL off.
11475 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11476 fd = open(fname, O_WRONLY|O_CREAT, 0666);
11478 /* If the open failed, return the file descriptor right away. */
11483 * OK, the open succeeded, but the file may have been changed from a
11484 * non-regular file to a regular file between the stat and the open.
11485 * We are assuming that the O_EXCL open handles the case where FILENAME
11486 * did not exist and is symlinked to an existing file between the stat
11491 * If we can open it and fstat the file descriptor, and neither check
11492 * revealed that it was a regular file, and the file has not been
11493 * replaced, return the file descriptor.
11495 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11496 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11499 /* The file has been replaced. badness. */
11504 /*#ifdef __weak_alias
11505 __weak_alias(getmode,_getmode)
11506 __weak_alias(setmode,_setmode)
11510 #define S_ISTXT __S_ISVTX
11513 #define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11514 #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11516 typedef struct bitcmd {
11522 #define CMD2_CLR 0x01
11523 #define CMD2_SET 0x02
11524 #define CMD2_GBITS 0x04
11525 #define CMD2_OBITS 0x08
11526 #define CMD2_UBITS 0x10
11528 static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11529 static void compress_mode (BITCMD *);
11530 #ifdef SETMODE_DEBUG
11531 static void dumpmode (BITCMD *);
11535 * Given the old mode and an array of bitcmd structures, apply the operations
11536 * described in the bitcmd structures to the old mode, and return the new mode.
11537 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11538 * bits) followed by a '+' (set bits).
11541 getmode(bbox, omode)
11546 mode_t clrval, newmode, value;
11548 _DIAGASSERT(bbox != NULL);
11550 set = (const BITCMD *)bbox;
11552 for (value = 0;; set++)
11555 * When copying the user, group or other bits around, we "know"
11556 * where the bits are in the mode so that we can do shifts to
11557 * copy them around. If we don't use shifts, it gets real
11558 * grundgy with lots of single bit checks and bit sets.
11561 value = (newmode & S_IRWXU) >> 6;
11565 value = (newmode & S_IRWXG) >> 3;
11569 value = newmode & S_IRWXO;
11570 common: if (set->cmd2 & CMD2_CLR) {
11572 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11573 if (set->cmd2 & CMD2_UBITS)
11574 newmode &= ~((clrval<<6) & set->bits);
11575 if (set->cmd2 & CMD2_GBITS)
11576 newmode &= ~((clrval<<3) & set->bits);
11577 if (set->cmd2 & CMD2_OBITS)
11578 newmode &= ~(clrval & set->bits);
11580 if (set->cmd2 & CMD2_SET) {
11581 if (set->cmd2 & CMD2_UBITS)
11582 newmode |= (value<<6) & set->bits;
11583 if (set->cmd2 & CMD2_GBITS)
11584 newmode |= (value<<3) & set->bits;
11585 if (set->cmd2 & CMD2_OBITS)
11586 newmode |= value & set->bits;
11591 newmode |= set->bits;
11595 newmode &= ~set->bits;
11599 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11600 newmode |= set->bits;
11605 #ifdef SETMODE_DEBUG
11606 (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11612 #define ADDCMD(a, b, c, d) do { \
11613 if (set >= endset) { \
11615 setlen += SET_LEN_INCR; \
11616 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11617 if (newset == NULL) { \
11621 set = newset + (set - saveset); \
11622 saveset = newset; \
11623 endset = newset + (setlen - 2); \
11625 set = addcmd(set, (a), (b), (c), (d)); \
11626 } while (/*CONSTCOND*/0)
11628 #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11636 BITCMD *set, *saveset, *endset;
11637 sigset_t mysigset, sigoset;
11639 int equalopdone = 0; /* pacify gcc */
11640 int permXbits, setlen;
11646 * Get a copy of the mask for the permissions that are mask relative.
11647 * Flip the bits, we want what's not set. Since it's possible that
11648 * the caller is opening files inside a signal handler, protect them
11651 sigfillset(&mysigset);
11652 (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11653 (void)umask(mask = umask(0));
11655 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11657 setlen = SET_LEN + 2;
11659 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11662 endset = set + (setlen - 2);
11665 * If an absolute number, get it and return; disallow non-octal digits
11668 if (isdigit((unsigned char)*p)) {
11669 perm = (mode_t)strtol(p, &ep, 8);
11670 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11674 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11680 * Build list of structures to set/clear/copy bits as described by
11681 * each clause of the symbolic mode.
11684 /* First, find out which bits might be modified. */
11685 for (who = 0;; ++p) {
11688 who |= STANDARD_BITS;
11691 who |= S_ISUID|S_IRWXU;
11694 who |= S_ISGID|S_IRWXG;
11704 getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11712 for (perm = 0, permXbits = 0;; ++p) {
11715 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11719 * If specific bits where requested and
11720 * only "other" bits ignore set-id.
11722 if (who == 0 || (who & ~S_IRWXO))
11723 perm |= S_ISUID|S_ISGID;
11727 * If specific bits where requested and
11728 * only "other" bits ignore set-id.
11730 if (who == 0 || (who & ~S_IRWXO)) {
11736 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11739 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11742 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11748 * When ever we hit 'u', 'g', or 'o', we have
11749 * to flush out any partial mode that we have,
11750 * and then do the copying of the mode bits.
11753 ADDCMD(op, who, perm, mask);
11758 if (op == '+' && permXbits) {
11759 ADDCMD('X', who, permXbits, mask);
11762 ADDCMD(*p, who, op, mask);
11767 * Add any permissions that we haven't already
11770 if (perm || (op == '=' && !equalopdone)) {
11773 ADDCMD(op, who, perm, mask);
11777 ADDCMD('X', who, permXbits, mask);
11791 #ifdef SETMODE_DEBUG
11792 (void)printf("Before compress_mode()\n");
11795 compress_mode(saveset);
11796 #ifdef SETMODE_DEBUG
11797 (void)printf("After compress_mode()\n");
11804 addcmd(set, op, who, oparg, mask)
11811 _DIAGASSERT(set != NULL);
11816 set->bits = who ? who : STANDARD_BITS;
11825 set->bits = (who ? who : mask) & oparg;
11833 set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11834 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11835 ((who & S_IROTH) ? CMD2_OBITS : 0);
11836 set->bits = (mode_t)~0;
11838 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11843 set->cmd2 |= CMD2_SET;
11844 else if (oparg == '-')
11845 set->cmd2 |= CMD2_CLR;
11846 else if (oparg == '=')
11847 set->cmd2 |= CMD2_SET|CMD2_CLR;
11853 #ifdef SETMODE_DEBUG
11859 _DIAGASSERT(set != NULL);
11861 for (; set->cmd; ++set)
11862 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11863 set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11864 set->cmd2 & CMD2_CLR ? " CLR" : "",
11865 set->cmd2 & CMD2_SET ? " SET" : "",
11866 set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11867 set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11868 set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11873 * Given an array of bitcmd structures, compress by compacting consecutive
11874 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11875 * 'g' and 'o' commands continue to be separate. They could probably be
11876 * compacted, but it's not worth the effort.
11883 int setbits, clrbits, Xbits, op;
11885 _DIAGASSERT(set != NULL);
11887 for (nset = set;;) {
11888 /* Copy over any 'u', 'g' and 'o' commands. */
11889 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11895 for (setbits = clrbits = Xbits = 0;; nset++) {
11896 if ((op = nset->cmd) == '-') {
11897 clrbits |= nset->bits;
11898 setbits &= ~nset->bits;
11899 Xbits &= ~nset->bits;
11900 } else if (op == '+') {
11901 setbits |= nset->bits;
11902 clrbits &= ~nset->bits;
11903 Xbits &= ~nset->bits;
11904 } else if (op == 'X')
11905 Xbits |= nset->bits & ~setbits;
11912 set->bits = clrbits;
11918 set->bits = setbits;
11930 static void shtree (union node *, int, char *, FILE*);
11931 static void shcmd (union node *, FILE *);
11932 static void sharg (union node *, FILE *);
11933 static void indent (int, char *, FILE *);
11934 static void trstring (char *);
11941 trputs("showtree called\n");
11942 shtree(n, 1, NULL, stdout);
11947 shtree(n, ind, pfx, fp)
11953 struct nodelist *lp;
11959 indent(ind, pfx, fp);
11970 shtree(n->nbinary.ch1, ind, NULL, fp);
11973 shtree(n->nbinary.ch2, ind, NULL, fp);
11981 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11986 if (n->npipe.backgnd)
11992 fprintf(fp, "<node type %d>", n->type);
12012 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
12018 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
12021 switch (np->nfile.type) {
12022 case NTO: s = ">"; dftfd = 1; break;
12023 case NAPPEND: s = ">>"; dftfd = 1; break;
12024 case NTOFD: s = ">&"; dftfd = 1; break;
12025 case NTOOV: s = ">|"; dftfd = 1; break;
12026 case NFROM: s = "<"; dftfd = 0; break;
12027 case NFROMFD: s = "<&"; dftfd = 0; break;
12028 case NFROMTO: s = "<>"; dftfd = 0; break;
12029 default: s = "*error*"; dftfd = 0; break;
12031 if (np->nfile.fd != dftfd)
12032 fprintf(fp, "%d", np->nfile.fd);
12034 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
12035 fprintf(fp, "%d", np->ndup.dupfd);
12037 sharg(np->nfile.fname, fp);
12051 struct nodelist *bqlist;
12054 if (arg->type != NARG) {
12055 printf("<node type %d>\n", arg->type);
12059 bqlist = arg->narg.backquote;
12060 for (p = arg->narg.text ; *p ; p++) {
12069 if (subtype == VSLENGTH)
12075 if (subtype & VSNUL)
12078 switch (subtype & VSTYPE) {
12097 case VSTRIMLEFTMAX:
12104 case VSTRIMRIGHTMAX:
12111 printf("<subtype %d>", subtype);
12118 case CTLBACKQ|CTLQUOTE:
12121 shtree(bqlist->n, -1, NULL, fp);
12133 indent(amount, pfx, fp)
12140 for (i = 0 ; i < amount ; i++) {
12141 if (pfx && i == amount - 1)
12159 static int debug = 1;
12161 static int debug = 0;
12169 if (tracefile == NULL)
12171 putc(c, tracefile);
12177 trace(const char *fmt, ...)
12185 fmt = va_arg(va, char *);
12187 if (tracefile != NULL) {
12188 (void) vfprintf(tracefile, fmt, va);
12189 if (strchr(fmt, '\n'))
12190 (void) fflush(tracefile);
12200 if (tracefile == NULL)
12202 fputs(s, tracefile);
12203 if (strchr(s, '\n'))
12215 if (tracefile == NULL)
12217 putc('"', tracefile);
12218 for (p = s ; *p ; p++) {
12220 case '\n': c = 'n'; goto backslash;
12221 case '\t': c = 't'; goto backslash;
12222 case '\r': c = 'r'; goto backslash;
12223 case '"': c = '"'; goto backslash;
12224 case '\\': c = '\\'; goto backslash;
12225 case CTLESC: c = 'e'; goto backslash;
12226 case CTLVAR: c = 'v'; goto backslash;
12227 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
12228 case CTLBACKQ: c = 'q'; goto backslash;
12229 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
12230 backslash: putc('\\', tracefile);
12231 putc(c, tracefile);
12234 if (*p >= ' ' && *p <= '~')
12235 putc(*p, tracefile);
12237 putc('\\', tracefile);
12238 putc(*p >> 6 & 03, tracefile);
12239 putc(*p >> 3 & 07, tracefile);
12240 putc(*p & 07, tracefile);
12245 putc('"', tracefile);
12253 if (tracefile == NULL)
12258 putc(' ', tracefile);
12260 putc('\n', tracefile);
12275 #ifdef not_this_way
12278 if ((p = getenv("HOME")) == NULL) {
12279 if (geteuid() == 0)
12285 strcat(s, "/trace");
12288 strcpy(s, "./trace");
12289 #endif /* not_this_way */
12290 if ((tracefile = fopen(s, "a")) == NULL) {
12291 fprintf(stderr, "Can't open %s\n", s);
12295 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
12296 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
12298 fputs("\nTracing started.\n", tracefile);
12305 * The trap builtin.
12309 trapcmd(argc, argv)
12318 for (signo = 0 ; signo < NSIG ; signo++) {
12319 if (trap[signo] != NULL) {
12322 p = single_quote(trap[signo]);
12323 out1fmt("trap -- %s %s\n", p,
12324 signal_names[signo] + (signo ? 3 : 0)
12337 if ((signo = decode_signal(*ap, 0)) < 0)
12338 error("%s: bad trap", *ap);
12341 if (action[0] == '-' && action[1] == '\0')
12344 action = savestr(action);
12347 ckfree(trap[signo]);
12348 trap[signo] = action;
12363 * Set the signal handler for the specified signal. The routine figures
12364 * out what it should be set to.
12368 setsignal(int signo)
12372 struct sigaction act;
12374 if ((t = trap[signo]) == NULL)
12376 else if (*t != '\0')
12380 if (rootshell && action == S_DFL) {
12383 if (iflag || minusc || sflag == 0)
12409 t = &sigmode[signo - 1];
12412 * current setting unknown
12414 if (sigaction(signo, 0, &act) == -1) {
12416 * Pretend it worked; maybe we should give a warning
12417 * here, but other shells don't. We don't alter
12418 * sigmode, so that we retry every time.
12422 if (act.sa_handler == SIG_IGN) {
12423 if (mflag && (signo == SIGTSTP ||
12424 signo == SIGTTIN || signo == SIGTTOU)) {
12425 *t = S_IGN; /* don't hard ignore these */
12429 *t = S_RESET; /* force to be set */
12432 if (*t == S_HARD_IGN || *t == action)
12436 act.sa_handler = onsig;
12439 act.sa_handler = SIG_IGN;
12442 act.sa_handler = SIG_DFL;
12446 sigemptyset(&act.sa_mask);
12447 sigaction(signo, &act, 0);
12458 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12459 signal(signo, SIG_IGN);
12461 sigmode[signo - 1] = S_HARD_IGN;
12472 if (signo == SIGINT && trap[SIGINT] == NULL) {
12476 gotsig[signo - 1] = 1;
12482 * Called to execute a trap. Perhaps we should avoid entering new trap
12483 * handlers while we are executing a trap handler.
12493 for (i = 1 ; ; i++) {
12500 savestatus=exitstatus;
12501 evalstring(trap[i], 0);
12502 exitstatus=savestatus;
12509 * Called to exit the shell.
12513 exitshell(int status)
12515 struct jmploc loc1, loc2;
12518 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12519 if (setjmp(loc1.loc)) {
12522 if (setjmp(loc2.loc)) {
12526 if ((p = trap[0]) != NULL && *p != '\0') {
12530 l1: handler = &loc2; /* probably unnecessary */
12539 static int decode_signal(const char *string, int minsig)
12543 if (is_number(string, &signo)) {
12544 if (signo >= NSIG) {
12554 for (; signo < NSIG; signo++) {
12555 if (!strcasecmp(string, &(signal_names[signo])[3])) {
12559 if (!strcasecmp(string, signal_names[signo])) {
12566 static struct var **hashvar (const char *);
12567 static void showvars (const char *, int, int);
12568 static struct var **findvar (struct var **, const char *);
12571 * Initialize the varable symbol tables and import the environment
12575 * This routine initializes the builtin variables. It is called when the
12576 * shell is initialized and again when a shell procedure is spawned.
12581 const struct varinit *ip;
12585 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12586 if ((vp->flags & VEXPORT) == 0) {
12587 vpp = hashvar(ip->text);
12590 vp->text = strdup(ip->text);
12591 vp->flags = ip->flags;
12592 vp->func = ip->func;
12596 * PS1 depends on uid
12598 if ((vps1.flags & VEXPORT) == 0) {
12599 vpp = hashvar("PS1=");
12602 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12603 vps1.flags = VSTRFIXED|VTEXTFIXED;
12608 * Set the value of a variable. The flags argument is ored with the
12609 * flags of the variable. If val is NULL, the variable is unset.
12613 setvar(name, val, flags)
12614 const char *name, *val;
12630 if (! is_in_name(*p)) {
12631 if (*p == '\0' || *p == '=')
12637 namelen = p - name;
12639 error("%.*s: bad variable name", namelen, name);
12640 len = namelen + 2; /* 2 is space for '=' and '\0' */
12644 len += vallen = strlen(val);
12647 nameeq = ckmalloc(len);
12648 memcpy(nameeq, name, namelen);
12649 nameeq[namelen] = '=';
12651 memcpy(nameeq + namelen + 1, val, vallen + 1);
12653 nameeq[namelen + 1] = '\0';
12655 setvareq(nameeq, flags);
12662 * Same as setvar except that the variable and value are passed in
12663 * the first argument as name=value. Since the first argument will
12664 * be actually stored in the table, it should not be a string that
12673 struct var *vp, **vpp;
12676 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12677 if ((vp = *findvar(vpp, s))) {
12678 if (vp->flags & VREADONLY) {
12679 size_t len = strchr(s, '=') - s;
12680 error("%.*s: is read only", len, s);
12684 if (vp->func && (flags & VNOFUNC) == 0)
12685 (*vp->func)(strchr(s, '=') + 1);
12687 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12690 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12691 vp->flags |= flags;
12695 * We could roll this to a function, to handle it as
12696 * a regular variable function callback, but why bother?
12698 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12704 vp = ckmalloc(sizeof (*vp));
12715 * Process a linked list of variable assignments.
12720 struct strlist *mylist;
12722 struct strlist *lp;
12725 for (lp = mylist ; lp ; lp = lp->next) {
12726 setvareq(savestr(lp->text), 0);
12734 * Find the value of a variable. Returns NULL if not set.
12743 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12744 return strchr(v->text, '=') + 1;
12752 * Search the environment of a builtin command.
12759 struct strlist *sp;
12761 for (sp = cmdenviron ; sp ; sp = sp->next) {
12762 if (varequal(sp->text, name))
12763 return strchr(sp->text, '=') + 1;
12765 return lookupvar(name);
12771 * Generate a list of exported variables. This routine is used to construct
12772 * the third argument to execve when executing a program.
12784 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12785 for (vp = *vpp ; vp ; vp = vp->next)
12786 if (vp->flags & VEXPORT)
12789 ep = env = stalloc((nenv + 1) * sizeof *env);
12790 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12791 for (vp = *vpp ; vp ; vp = vp->next)
12792 if (vp->flags & VEXPORT)
12801 * Called when a shell procedure is invoked to clear out nonexported
12802 * variables. It is also necessary to reallocate variables of with
12803 * VSTACK set since these are currently allocated on the stack.
12809 struct var *vp, **prev;
12811 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12812 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12813 if ((vp->flags & VEXPORT) == 0) {
12815 if ((vp->flags & VTEXTFIXED) == 0)
12817 if ((vp->flags & VSTRFIXED) == 0)
12820 if (vp->flags & VSTACK) {
12821 vp->text = savestr(vp->text);
12822 vp->flags &=~ VSTACK;
12834 * Command to list all variables which are set. Currently this command
12835 * is invoked from the set command when the set command is called without
12840 showvarscmd(argc, argv)
12844 showvars(nullstr, VUNSET, VUNSET);
12851 * The export and readonly commands.
12855 exportcmd(argc, argv)
12862 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12865 listsetvar(cmdenviron);
12866 pflag = (nextopt("p") == 'p');
12867 if (argc > 1 && !pflag) {
12868 while ((name = *argptr++) != NULL) {
12869 if ((p = strchr(name, '=')) != NULL) {
12872 if ((vp = *findvar(hashvar(name), name))) {
12877 setvar(name, p, flag);
12881 showvars(argv[0], flag, 0);
12888 * The "local" command.
12891 /* funcnest nonzero if we are currently evaluating a function */
12894 localcmd(argc, argv)
12901 error("Not in a function");
12902 while ((name = *argptr++) != NULL) {
12910 * Make a variable a local variable. When a variable is made local, it's
12911 * value and flags are saved in a localvar structure. The saved values
12912 * will be restored when the shell function returns. We handle the name
12913 * "-" as a special case.
12920 struct localvar *lvp;
12925 lvp = ckmalloc(sizeof (struct localvar));
12926 if (name[0] == '-' && name[1] == '\0') {
12928 p = ckmalloc(sizeof optet_vals);
12929 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12932 vpp = hashvar(name);
12933 vp = *findvar(vpp, name);
12935 if (strchr(name, '='))
12936 setvareq(savestr(name), VSTRFIXED);
12938 setvar(name, NULL, VSTRFIXED);
12939 vp = *vpp; /* the new variable */
12941 lvp->flags = VUNSET;
12943 lvp->text = vp->text;
12944 lvp->flags = vp->flags;
12945 vp->flags |= VSTRFIXED|VTEXTFIXED;
12946 if (strchr(name, '='))
12947 setvareq(savestr(name), 0);
12951 lvp->next = localvars;
12958 * Called after a function returns.
12963 struct localvar *lvp;
12966 while ((lvp = localvars) != NULL) {
12967 localvars = lvp->next;
12969 if (vp == NULL) { /* $- saved */
12970 memcpy(optet_vals, lvp->text, sizeof optet_vals);
12972 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12973 (void)unsetvar(vp->text);
12975 if ((vp->flags & VTEXTFIXED) == 0)
12977 vp->flags = lvp->flags;
12978 vp->text = lvp->text;
12986 setvarcmd(argc, argv)
12991 return unsetcmd(argc, argv);
12992 else if (argc == 3)
12993 setvar(argv[1], argv[2], 0);
12995 error("List assignment not implemented");
13001 * The unset builtin command. We unset the function before we unset the
13002 * variable to allow a function to be unset when there is a readonly variable
13003 * with the same name.
13007 unsetcmd(argc, argv)
13017 while ((i = nextopt("vf")) != '\0') {
13023 if (flg_func == 0 && flg_var == 0)
13026 for (ap = argptr; *ap ; ap++) {
13030 ret |= unsetvar(*ap);
13037 * Unset the specified variable.
13047 vpp = findvar(hashvar(s), s);
13050 if (vp->flags & VREADONLY)
13053 if (*(strchr(vp->text, '=') + 1) != '\0')
13054 setvar(s, nullstr, 0);
13055 vp->flags &= ~VEXPORT;
13056 vp->flags |= VUNSET;
13057 if ((vp->flags & VSTRFIXED) == 0) {
13058 if ((vp->flags & VTEXTFIXED) == 0)
13073 * Find the appropriate entry in the hash table from the name.
13076 static struct var **
13080 unsigned int hashval;
13082 hashval = ((unsigned char) *p) << 4;
13083 while (*p && *p != '=')
13084 hashval += (unsigned char) *p++;
13085 return &vartab[hashval % VTABSIZE];
13091 * Returns true if the two strings specify the same varable. The first
13092 * variable name is terminated by '='; the second may be terminated by
13093 * either '=' or '\0'.
13100 while (*p == *q++) {
13104 if (*p == '=' && *(q - 1) == '\0')
13110 showvars(const char *myprefix, int mask, int xor)
13114 const char *sep = myprefix == nullstr ? myprefix : spcstr;
13116 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
13117 for (vp = *vpp ; vp ; vp = vp->next) {
13118 if ((vp->flags & mask) ^ xor) {
13122 p = strchr(vp->text, '=') + 1;
13123 len = p - vp->text;
13124 p = single_quote(p);
13127 "%s%s%.*s%s\n", myprefix, sep, len,
13136 static struct var **
13137 findvar(struct var **vpp, const char *name)
13139 for (; *vpp; vpp = &(*vpp)->next) {
13140 if (varequal((*vpp)->text, name)) {
13148 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
13149 * This file contains code for the times builtin.
13150 * $Id: ash.c,v 1.7 2001/07/07 00:05:55 andersen Exp $
13152 static int timescmd (int argc, char **argv)
13155 long int clk_tck = sysconf(_SC_CLK_TCK);
13158 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
13159 (int) (buf.tms_utime / clk_tck / 60),
13160 ((double) buf.tms_utime) / clk_tck,
13161 (int) (buf.tms_stime / clk_tck / 60),
13162 ((double) buf.tms_stime) / clk_tck,
13163 (int) (buf.tms_cutime / clk_tck / 60),
13164 ((double) buf.tms_cutime) / clk_tck,
13165 (int) (buf.tms_cstime / clk_tck / 60),
13166 ((double) buf.tms_cstime) / clk_tck);
13172 * Copyright (c) 1989, 1991, 1993, 1994
13173 * The Regents of the University of California. All rights reserved.
13175 * This code is derived from software contributed to Berkeley by
13176 * Kenneth Almquist.
13178 * Redistribution and use in source and binary forms, with or without
13179 * modification, are permitted provided that the following conditions
13181 * 1. Redistributions of source code must retain the above copyright
13182 * notice, this list of conditions and the following disclaimer.
13183 * 2. Redistributions in binary form must reproduce the above copyright
13184 * notice, this list of conditions and the following disclaimer in the
13185 * documentation and/or other materials provided with the distribution.
13187 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
13188 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
13190 * 4. Neither the name of the University nor the names of its contributors
13191 * may be used to endorse or promote products derived from this software
13192 * without specific prior written permission.
13194 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13195 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13196 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13197 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13198 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13199 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13200 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13201 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13202 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13203 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF