ash.c

来自「为samsung2410 ARM移植的busybox工具包」· C语言 代码 · 共 2,530 行 · 第 1/5 页

C
2,530
字号
      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 + =
减小字号Ctrl + -
显示快捷键?