📄 ash.c
字号:
/* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD, /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD, /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD, /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD, /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD, /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD, /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD, /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD, /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD, /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD, /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD, /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD, /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK, /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD, /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD, /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD, /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE, /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD, /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD, /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD, /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD, /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD, /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD, /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD, /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD, /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD, /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD, /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD, /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD, /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD, /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD, /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD, /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD, /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD, /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD, /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD, /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD, /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD, /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD, /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD, /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD, /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD, /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD, /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD, /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD, /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR, /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD, /* 257 127 */ CWORD_CWORD_CWORD_CWORD,};#endif /* USE_SIT_FUNCTION *//* first char is indicating which tokens mark the end of a list */static const char *const tokname_array[] = { "\1end of file", "\0newline", "\0redirection", "\0word", "\0assignment", "\0;", "\0&", "\0&&", "\0||", "\0|", "\0(", "\1)", "\1;;", "\1`",#define KWDOFFSET 14 /* the following are keywords */ "\0!", "\0case", "\1do", "\1done", "\1elif", "\1else", "\1esac", "\1fi", "\0for", "\0if", "\0in", "\1then", "\0until", "\0while", "\0{", "\1}",};static const char *tokname(int tok){ static char buf[16]; if(tok>=TSEMI) buf[0] = '"'; sprintf(buf+(tok>=TSEMI), "%s%c", tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0)); return buf;}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 *);static void find_command (const char *, struct cmdentry *, int, const char *);static inline void hashcd (void);/* 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 CONFIG_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 },#if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT) { &vps1, VSTRFIXED|VTEXTFIXED, "PS1=\\w \\$ ", NULL },#endif /* else vps1 depends on uid */ { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL }, { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },#ifdef CONFIG_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 CONFIG_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(char *name, char *val){ struct alias *ap, **app; app = __lookupalias(name); ap = *app; INTOFF; if (ap) { if (!(ap->flag & ALIASINUSE)) { ckfree(ap->val); } ap->val = xstrdup(val); ap->flag &= ~ALIASDEAD; } else { /* not found */ ap = xmalloc(sizeof (struct alias)); ap->name = xstrdup(name); ap->val = xstrdup(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 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -