📄 ash.c
字号:
/* vi: set sw=4 ts=4: *//* * ash shell port for busybox * * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * This version of ash is adapted from the source in Debian's ash 0.3.8-5 * package. * * Modified by Erik Andersen <andersee@debian.org> and * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox * * * Original copyright notice is retained at the end of this file. *//* These defines allow you to adjust the feature set to be compiled * into the ash shell. As a rule, enabling these options will make * ash get bigger... With all of these options off, ash adds about * 60k to busybox on an x86 system.*//* Enable job control. This allows you to run jobs in the background, * which is great when ash is being used as an interactive shell, but * it completely useless for is all you are doing is running scripts. * This adds about 2.5k on an x86 system. */#undef JOBS/* This enables alias support in ash. If you want to support things * like "alias ls='ls -l'" with ash, enable this. This is only useful * when ash is used as an intractive shell. This adds about 1.5k */#define ASH_ALIAS/* If you need ash to act as a full Posix shell, with full math * support, enable this. This adds a bit over 2k an x86 system. *///#undef ASH_MATH_SUPPORT#define ASH_MATH_SUPPORT/* Getopts is used by shell procedures to parse positional parameters. * You probably want to leave this disabled, and use the busybox getopt * applet if you want to do this sort of thing. There are some scripts * out there that use it, so if you need it, enable it. Most people will * leave this disabled. This adds 1k on an x86 system. */#undef ASH_GETOPTS/* This allows you to override shell builtins and use whatever is on * the filesystem. This is most useful when ash is acting as a * standalone shell. Adds about 272 bytes. */#undef ASH_CMDCMD/* Optimize size vs speed as size */#define ASH_OPTIMIZE_FOR_SIZE/* Enable this to compile in extra debugging noise. When debugging is * on, debugging info will be written to $HOME/trace and a quit signal * will generate a core dump. */#undef DEBUG/* These are here to work with glibc -- Don't change these... */#undef FNMATCH_BROKEN#undef GLOB_BROKEN#define IFS_BROKEN#include <assert.h>#include <ctype.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <paths.h>#include <pwd.h>#include <setjmp.h>#include <signal.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sysexits.h>#include <unistd.h>#include <sys/stat.h>#include <sys/cdefs.h>#include <sys/ioctl.h>#include <sys/param.h>#include <sys/resource.h>#include <sys/time.h>#include <sys/times.h>#include <sys/types.h>#include <sys/wait.h>#if !defined(FNMATCH_BROKEN)#include <fnmatch.h>#endif#if !defined(GLOB_BROKEN)#include <glob.h>#endif#ifdef JOBS#include <termios.h>#endif#include "busybox.h"#include "cmdedit.h"/* * This file was generated by the mksyntax program. *//* Syntax classes */#define CWORD 0 /* character is nothing special */#define CNL 1 /* newline character */#define CBACK 2 /* a backslash character */#define CSQUOTE 3 /* single quote */#define CDQUOTE 4 /* double quote */#define CENDQUOTE 5 /* a terminating quote */#define CBQUOTE 6 /* backwards single quote */#define CVAR 7 /* a dollar sign */#define CENDVAR 8 /* a '}' character */#define CLP 9 /* a left paren in arithmetic */#define CRP 10 /* a right paren in arithmetic */#define CENDFILE 11 /* end of file */#define CCTL 12 /* like CWORD, except it must be escaped */#define CSPCL 13 /* these terminate a word */#define CIGN 14 /* character should be ignored *//* Syntax classes for is_ functions */#define ISDIGIT 01 /* a digit */#define ISUPPER 02 /* an upper case letter */#define ISLOWER 04 /* a lower case letter */#define ISUNDER 010 /* an underscore */#define ISSPECL 020 /* the name of a special parameter */#define SYNBASE 130#define PEOF -130#define PEOA -129#define TEOF 0#define TNL 1#define TSEMI 2#define TBACKGND 3#define TAND 4#define TOR 5#define TPIPE 6#define TLP 7#define TRP 8#define TENDCASE 9#define TENDBQUOTE 10#define TREDIR 11#define TWORD 12#define TASSIGN 13#define TNOT 14#define TCASE 15#define TDO 16#define TDONE 17#define TELIF 18#define TELSE 19#define TESAC 20#define TFI 21#define TFOR 22#define TIF 23#define TIN 24#define TTHEN 25#define TUNTIL 26#define TWHILE 27#define TBEGIN 28#define TEND 29#define BASESYNTAX (basesyntax + SYNBASE)#define DQSYNTAX (dqsyntax + SYNBASE)#define SQSYNTAX (sqsyntax + SYNBASE)#define ARISYNTAX (arisyntax + SYNBASE)/* control characters in argument strings */#define CTLESC '\201'#define CTLVAR '\202'#define CTLENDVAR '\203'#define CTLBACKQ '\204'#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes *//* CTLBACKQ | CTLQUOTE == '\205' */#define CTLARI '\206'#define CTLENDARI '\207'#define CTLQUOTEMARK '\210'#define is_digit(c) ((c)>='0' && (c)<='9')#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))#define digit_val(c) ((c) - '0')#define _DIAGASSERT(x)#define S_DFL 1 /* default signal handling (SIG_DFL) */#define S_CATCH 2 /* signal is caught */#define S_IGN 3 /* signal is ignored (SIG_IGN) */#define S_HARD_IGN 4 /* signal is ignored permenantly */#define S_RESET 5 /* temporary - to reset a hard ignored sig *//* variable substitution byte (follows CTLVAR) */#define VSTYPE 0x0f /* type of variable substitution */#define VSNUL 0x10 /* colon--treat the empty string as unset */#define VSQUOTE 0x80 /* inside double quotes--suppress splitting *//* values of VSTYPE field */#define VSNORMAL 0x1 /* normal variable: $var or ${var} */#define VSMINUS 0x2 /* ${var-text} */#define VSPLUS 0x3 /* ${var+text} */#define VSQUESTION 0x4 /* ${var?message} */#define VSASSIGN 0x5 /* ${var=text} */#define VSTRIMLEFT 0x6 /* ${var#pattern} */#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */#define VSTRIMRIGHT 0x8 /* ${var%pattern} */#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */#define VSLENGTH 0xa /* ${#var} *//* flags passed to redirect */#define REDIR_PUSH 01 /* save previous values of file descriptors */#define REDIR_BACKQ 02 /* save the command output to pipe *//* * BSD setjmp saves the signal mask, which violates ANSI C and takes time, * so we use _setjmp instead. */#if defined(BSD)#define setjmp(jmploc) _setjmp(jmploc)#define longjmp(jmploc, val) _longjmp(jmploc, val)#endif/* * Most machines require the value returned from malloc to be aligned * in some way. The following macro will get this right on many machines. */#ifndef ALIGNunion align { int i; char *cp;};#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))#endif#ifdef BB_LOCALE_SUPPORT#include <locale.h>static void change_lc_all(const char *value);static void change_lc_ctype(const char *value);#endif/* * These macros allow the user to suspend the handling of interrupt signals * over a period of time. This is similar to SIGHOLD to or sigblock, but * much more efficient and portable. (But hacking the kernel is so much * more fun than worrying about efficiency and portability. :-)) */static void onint (void);static volatile int suppressint;static volatile int intpending;#define INTOFF suppressint++#ifndef ASH_OPTIMIZE_FOR_SIZE#define INTON { if (--suppressint == 0 && intpending) onint(); }#define FORCEINTON {suppressint = 0; if (intpending) onint();}#elsestatic void __inton (void);static void forceinton (void);#define INTON __inton()#define FORCEINTON forceinton()#endif#define CLEAR_PENDING_INT intpending = 0#define int_pending() intpendingtypedef void *pointer;#ifndef NULL#define NULL (void *)0#endifstatic inline pointer ckmalloc (int sz) { return xmalloc(sz); }static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }static inline char * savestr (const char *s) { return xstrdup(s); }static pointer stalloc (int);static void stunalloc (pointer);static void ungrabstackstr (char *, char *);static char * growstackstr(void);static char * makestrspace(size_t newlen);static char *sstrdup (const char *);/* * Parse trees for commands are allocated in lifo order, so we use a stack * to make this more efficient, and also to avoid all sorts of exception * handling code to handle interrupts in the middle of a parse. * * The size 504 was chosen because the Ultrix malloc handles that size * well. */#define MINSIZE 504 /* minimum size of a block */struct stack_block { struct stack_block *prev; char space[MINSIZE];};static struct stack_block stackbase;static struct stack_block *stackp = &stackbase;static struct stackmark *markp;static char *stacknxt = stackbase.space;static int stacknleft = MINSIZE;#define equal(s1, s2) (strcmp(s1, s2) == 0)#define stackblock() stacknxt#define stackblocksize() stacknleft#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))#define STUNPUTC(p) (++sstrnleft, --p)#define STTOPC(p) p[-1]#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)#define ckfree(p) free((pointer)(p))#ifdef DEBUG#define TRACE(param) trace paramtypedef union node unode;static void trace (const char *, ...);static void trargs (char **);static void showtree (unode *);static void trputc (int);static void trputs (const char *);static void opentrace (void);#else#define TRACE(param)#endif#define NSEMI 0#define NCMD 1#define NPIPE 2#define NREDIR 3#define NBACKGND 4#define NSUBSHELL 5#define NAND 6#define NOR 7#define NIF 8#define NWHILE 9#define NUNTIL 10#define NFOR 11#define NCASE 12#define NCLIST 13#define NDEFUN 14#define NARG 15#define NTO 16#define NFROM 17#define NFROMTO 18#define NAPPEND 19#define NTOOV 20#define NTOFD 21#define NFROMFD 22#define NHERE 23#define NXHERE 24#define NNOT 25/* * expandarg() flags */#define EXP_FULL 0x1 /* perform word splitting & file globbing */#define EXP_TILDE 0x2 /* do normal tilde expansion */#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */#define NOPTS 16static char optet_vals[NOPTS];static const char * const optlist[NOPTS] = { "e" "errexit", "f" "noglob", "I" "ignoreeof", "i" "interactive", "m" "monitor", "n" "noexec", "s" "stdin", "x" "xtrace", "v" "verbose", "V" "vi", "E" "emacs", "C" "noclobber", "a" "allexport", "b" "notify", "u" "nounset", "q" "quietprofile"};#define optent_name(optent) (optent+1)#define optent_letter(optent) optent[0]#define optent_val(optent) optet_vals[optent]#define eflag optent_val(0)#define fflag optent_val(1)#define Iflag optent_val(2)#define iflag optent_val(3)#define mflag optent_val(4)#define nflag optent_val(5)#define sflag optent_val(6)#define xflag optent_val(7)#define vflag optent_val(8)#define Vflag optent_val(9)#define Eflag optent_val(10)#define Cflag optent_val(11)#define aflag optent_val(12)#define bflag optent_val(13)#define uflag optent_val(14)#define qflag optent_val(15)/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */#define FORK_FG 0#define FORK_BG 1#define FORK_NOJOB 2struct nbinary { int type; union node *ch1; union node *ch2;};struct ncmd { int type; int backgnd; union node *assign; union node *args; union node *redirect;};struct npipe { int type; int backgnd; struct nodelist *cmdlist;};struct nredir { int type; union node *n; union node *redirect;};struct nif { int type; union node *test; union node *ifpart; union node *elsepart;};struct nfor { int type; union node *args; union node *body; char *var;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -