📄 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. *//* 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 CONFIG_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. */#define CONFIG_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 CONFIG_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 CONFIG_ASH_CMDCMD/* Check for mail */#undef CONFIG_ASH_MAIL/* Optimize size vs speed as size */#define CONFIG_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 <stddef.h>#include <ctype.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <paths.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>#include "busybox.h"#include "pwd_grp/pwd.h"#if !defined(FNMATCH_BROKEN)#include <fnmatch.h>#endif#if !defined(GLOB_BROKEN)#include <glob.h>#endif#ifdef BB_FEATURE_ASH_JOB_CONTROL#include <termios.h>#endif#include "cmdedit.h"#if defined(__uClinux__)#error "Do not even bother, ash will not run on uClinux"#endif/* * 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 */#define SYNBASE 130#define PEOF -130#define PEOA -129#define TEOF 0#define TNL 1#define TREDIR 2#define TWORD 3#define TASSIGN 4#define TSEMI 5#define TBACKGND 6#define TAND 7#define TOR 8#define TPIPE 9#define TLP 10#define TRP 11#define TENDCASE 12#define TENDBQUOTE 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/* 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_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))))/* * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise * (assuming ascii char codes, as the original implementation did) */#define is_special(c) \ ( (((unsigned int)c) - 33 < 32) \ && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))#define digit_val(c) ((c) - '0')#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 CONFIG_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 pointer stalloc(int);static void stunalloc(pointer);static void ungrabstackstr(char *, char *);static char *growstackstr(void);static char *makestrspace(size_t newlen);/* * 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)#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;};struct ncase { int type; union node *expr; union node *cases;};struct nclist { int type; union node *next; union node *pattern;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -