📄 ash.c
字号:
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ISSPECL, 0, ISSPECL, ISSPECL, 0, 0, 0, 0, 0, ISSPECL, 0, 0, ISSPECL, 0, 0, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT, 0, 0, 0, 0, 0, ISSPECL, ISSPECL, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, ISUPPER, 0, 0, 0, 0, ISUNDER, 0, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, ISLOWER, 0, 0, 0, 0};/* Array indicating which tokens mark the end of a list */static const char tokendlist[] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1,};static const char *const tokname[] = { "end of file", "newline", "\";\"", "\"&\"", "\"&&\"", "\"||\"", "\"|\"", "\"(\"", "\")\"", "\";;\"", "\"`\"", "redirection", "word", "assignment", "\"!\"", "\"case\"", "\"do\"", "\"done\"", "\"elif\"", "\"else\"", "\"esac\"", "\"fi\"", "\"for\"", "\"if\"", "\"in\"", "\"then\"", "\"until\"", "\"while\"", "\"{\"", "\"}\"",};#define KWDOFFSET 14static const char *const parsekwd[] = { "!", "case", "do", "done", "elif", "else", "esac", "fi", "for", "if", "in", "then", "until", "while", "{", "}"};static int plinno = 1; /* input line number */static int parselleft; /* copy of parsefile->lleft */static struct parsefile basepf; /* top level input file */static char basebuf[BUFSIZ]; /* buffer for top level input file */static struct parsefile *parsefile = &basepf; /* current input file *//* * NEOF is returned by parsecmd when it encounters an end of file. It * must be distinct from NULL, so we use the address of a variable that * happens to be handy. */static int tokpushback; /* last token pushed back */#define NEOF ((union node *)&tokpushback)static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */static void error (const char *, ...) __attribute__((__noreturn__));static void exerror (int, const char *, ...) __attribute__((__noreturn__));static void shellexec (char **, char **, const char *, int) __attribute__((noreturn));static void exitshell (int) __attribute__((noreturn));static int goodname(const char *);static void ignoresig (int);static void onsig (int);static void dotrap (void);static int decode_signal (const char *, int);static void shprocvar(void);static void deletefuncs(void);static void setparam (char **);static void freeparam (volatile struct shparam *);/* reasons for skipping commands (see comment on breakcmd routine) */#define SKIPBREAK 1#define SKIPCONT 2#define SKIPFUNC 3#define SKIPFILE 4/* values of cmdtype */#define CMDUNKNOWN -1 /* no entry in table for command */#define CMDNORMAL 0 /* command is an executable program */#define CMDBUILTIN 1 /* command is a shell builtin */#define CMDFUNCTION 2 /* command is a shell function */#define DO_ERR 1 /* find_command prints errors */#define DO_ABS 2 /* find_command checks absolute paths */#define DO_NOFUN 4 /* find_command ignores functions */#define DO_BRUTE 8 /* find_command ignores hash table *//* * Shell variables. *//* flags */#define VEXPORT 0x01 /* variable is exported */#define VREADONLY 0x02 /* variable cannot be modified */#define VSTRFIXED 0x04 /* variable struct is staticly allocated */#define VTEXTFIXED 0x08 /* text is staticly allocated */#define VSTACK 0x10 /* text is allocated on the stack */#define VUNSET 0x20 /* the variable is not set */#define VNOFUNC 0x40 /* don't call the callback function */struct var { struct var *next; /* next entry in hash list */ int flags; /* flags are defined above */ char *text; /* name=value */ void (*func) (const char *); /* function to be called when */ /* the variable gets set/unset */};struct localvar { struct localvar *next; /* next local variable in list */ struct var *vp; /* the variable that was made local */ int flags; /* saved flags */ char *text; /* saved text */};#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)#define rmescapes(p) _rmescapes((p), 0)static char *_rmescapes (char *, int);#elsestatic void rmescapes (char *);#endifstatic int casematch (union node *, const char *);static void clearredir(void);static void popstring(void);static void readcmdfile (const char *);static int number (const char *);static int is_number (const char *, int *num);static char *single_quote (const char *);static int nextopt (const char *);static void redirect (union node *, int);static void popredir (void);static int dup_as_newfd (int, int);static void changepath(const char *newval);static void getoptsreset(const char *value);static int parsenleft; /* copy of parsefile->nleft */static char *parsenextc; /* copy of parsefile->nextc */static int rootpid; /* pid of main shell */static int rootshell; /* true if we aren't a child of the main shell */static const char spcstr[] = " ";static const char snlfmt[] = "%s\n";static int sstrnleft;static int herefd = -1;static struct localvar *localvars;static struct var vifs;static struct var vmail;static struct var vmpath;static struct var vpath;static struct var vps1;static struct var vps2;static struct var voptind;#ifdef BB_LOCALE_SUPPORTstatic struct var vlc_all;static struct var vlc_ctype;#endifstruct varinit { struct var *var; int flags; const char *text; void (*func) (const char *);};static const char defpathvar[] = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";#define defpath (defpathvar + 5)#ifdef IFS_BROKENstatic const char defifsvar[] = "IFS= \t\n";#define defifs (defifsvar + 4)#elsestatic const char defifs[] = " \t\n";#endifstatic const struct varinit varinit[] = {#ifdef IFS_BROKEN { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,#else { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",#endif NULL }, { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", NULL }, { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", NULL }, { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, /* * vps1 depends on uid */ { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL }, { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },#ifdef BB_LOCALE_SUPPORT { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=", change_lc_all }, { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=", change_lc_ctype },#endif { NULL, 0, NULL, NULL }};#define VTABSIZE 39static struct var *vartab[VTABSIZE];/* * The following macros access the values of the above variables. * They have to skip over the name. They return the null string * for unset variables. */#define ifsval() (vifs.text + 4)#define ifsset() ((vifs.flags & VUNSET) == 0)#define mailval() (vmail.text + 5)#define mpathval() (vmpath.text + 9)#define pathval() (vpath.text + 5)#define ps1val() (vps1.text + 4)#define ps2val() (vps2.text + 4)#define optindval() (voptind.text + 7)#define mpathset() ((vmpath.flags & VUNSET) == 0)static void initvar (void);static void setvar (const char *, const char *, int);static void setvareq (char *, int);static void listsetvar (struct strlist *);static const char *lookupvar (const char *);static const char *bltinlookup (const char *);static char **environment (void);static int showvarscmd (int, char **);static void mklocal (char *);static void poplocalvars (void);static int unsetvar (const char *);static int varequal (const char *, const char *);static char *arg0; /* value of $0 */static struct shparam shellparam; /* current positional parameters */static char **argptr; /* argument list for builtin commands */static char *optionarg; /* set by nextopt (like getopt) */static char *optptr; /* used by nextopt */static char *minusc; /* argument to -c option */#ifdef ASH_ALIAS#define ALIASINUSE 1#define ALIASDEAD 2#define ATABSIZE 39struct alias { struct alias *next; char *name; char *val; int flag;};static struct alias *atab[ATABSIZE];static void setalias (char *, char *);static struct alias **hashalias (const char *);static struct alias *freealias (struct alias *);static struct alias **__lookupalias (const char *);static voidsetalias(name, val) char *name, *val;{ struct alias *ap, **app; app = __lookupalias(name); ap = *app; INTOFF; if (ap) { if (!(ap->flag & ALIASINUSE)) { ckfree(ap->val); } ap->val = savestr(val); ap->flag &= ~ALIASDEAD; } else { /* not found */ ap = ckmalloc(sizeof (struct alias)); ap->name = savestr(name); ap->val = savestr(val); ap->flag = 0; ap->next = 0; *app = ap; } INTON;}static intunalias(char *name){ struct alias **app; app = __lookupalias(name); if (*app) { INTOFF; *app = freealias(*app); INTON; return (0); } return (1);}static voidrmaliases(void){ struct alias *ap, **app; int i; INTOFF; for (i = 0; i < ATABSIZE; i++) { app = &atab[i]; for (ap = *app; ap; ap = *app) { *app = freealias(*app); if (ap == *app) { app = &ap->next; } } } INTON;}static struct alias *lookupalias(const char *name, int check){ struct alias *ap = *__lookupalias(name); if (check && ap && (ap->flag & ALIASINUSE)) return (NULL); return (ap);}static voidprintalias(const struct alias *ap) { char *p; p = single_quote(ap->val); printf("alias %s=%s\n", ap->name, p); stunalloc(p);}/* * TODO - sort output */static intaliascmd(int argc, char **argv){ char *n, *v; int ret = 0; struct alias *ap; if (argc == 1) { int i; for (i = 0; i < ATABSIZE; i++) for (ap = atab[i]; ap; ap = ap->next) { printalias(ap); } return (0); } while ((n = *++argv) != NULL) { if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ if ((ap = *__lookupalias(n)) == NULL) { out2fmt("%s: %s not found\n", "alias", n); ret = 1; } else printalias(ap); } else { *v++ = '\0'; setalias(n, v); } } return (ret);}static intunaliascmd(int argc, char **argv){ int i; while ((i = nextopt("a")) != '\0') { if (i == 'a') { rmaliases(); return (0); } } for (i = 0; *argptr; argptr++) { if (unalias(*argptr)) { out2fmt("%s: %s not found\n", "unalias", *argptr); i = 1; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -