msh.c

来自「手机嵌入式Linux下可用的busybox源码」· C语言 代码 · 共 3,606 行 · 第 1/5 页

C
3,606
字号
static int dolabel(void);static int dochdir(struct op *t);static int doshift(struct op *t);static int dologin(struct op *t);static int doumask(struct op *t);static int doexec(struct op *t);static int dodot(struct op *t);static int dowait(struct op *t);static int doread(struct op *t);static int doeval(struct op *t);static int dotrap(struct op *t);static int getsig(char *s);static void setsig(int n, void (*f) ());static int getn(char *as);static int dobreak(struct op *t);static int docontinue(struct op *t);static int brkcontin(char *cp, int val);static int doexit(struct op *t);static int doexport(struct op *t);static int doreadonly(struct op *t);static void rdexp(char **wp, void (*f) (), int key);static void badid(char *s);static int doset(struct op *t);static void varput(char *s, int out);static int dotimes(void);int execute(t, pin, pout, act)register struct op *t;int *pin, *pout;int act;{	register struct op *t1;	int i, pv[2], rv, child, a;	char *cp, **wp, **wp2;	struct var *vp;	struct brkcon bc;#if __GNUC__	/* Avoid longjmp clobbering */	(void) &i;	(void) &rv;	(void) &wp;#endif	if (t == NULL)		return (0);	rv = 0;	a = areanum++;	wp = (wp2 = t->words) != NULL		? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)		: NULL;	switch (t->type) {	case TPAREN:	case TCOM:		rv = forkexec(t, pin, pout, act, wp, &child);		if (child) {			exstat = rv;			leave();		}		break;	case TPIPE:		if ((rv = openpipe(pv)) < 0)			break;		pv[0] = remap(pv[0]);		pv[1] = remap(pv[1]);		(void) execute(t->left, pin, pv, 0);		rv = execute(t->right, pv, pout, 0);		break;	case TLIST:		(void) execute(t->left, pin, pout, 0);		rv = execute(t->right, pin, pout, 0);		break;	case TASYNC:	{	        /* save global vars altered by child */		int hinteractive = interactive;		i = parent();		if (i != 0) {		        /* restore global vars */			interactive = hinteractive;			if (i != -1) {				setval(lookup("!"), putn(i));				if (pin != NULL)					closepipe(pin);				if (interactive) {					prs(putn(i));					prs("\n");				}			} else				rv = -1;			setstatus(rv);		} else {			signal(SIGINT, SIG_IGN);			signal(SIGQUIT, SIG_IGN);			if (interactive)				signal(SIGTERM, SIG_DFL);			interactive = 0;			if (pin == NULL) {				close(0);				open("/dev/null", 0);			}			_exit(execute(t->left, pin, pout, FEXEC));		}		break;	}	case TOR:	case TAND:		rv = execute(t->left, pin, pout, 0);		if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND))			rv = execute(t1, pin, pout, 0);		break;	case TFOR:		if (wp == NULL) {			wp = dolv + 1;			if ((i = dolc) < 0)				i = 0;		} else {			i = -1;			while (*wp++ != NULL);		}		vp = lookup(t->str);		while (setjmp(bc.brkpt))			if (isbreak)				goto broken;		brkset(&bc);		for (t1 = t->left; i-- && *wp != NULL;) {			setval(vp, *wp++);			rv = execute(t1, pin, pout, 0);		}		brklist = brklist->nextlev;		break;	case TWHILE:	case TUNTIL:		while (setjmp(bc.brkpt))			if (isbreak)				goto broken;		brkset(&bc);		t1 = t->left;		while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))			rv = execute(t->right, pin, pout, 0);		brklist = brklist->nextlev;		break;	case TIF:	case TELIF:		if (t->right != NULL) {			rv = !execute(t->left, pin, pout, 0) ?				execute(t->right->left, pin, pout, 0) :				execute(t->right->right, pin, pout, 0);		}		break;	case TCASE:		if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0)			cp = "";		if ((t1 = findcase(t->left, cp)) != NULL)			rv = execute(t1, pin, pout, 0);		break;	case TBRACE:/*		if (iopp = t->ioact)			while (*iopp)				if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {					rv = -1;					break;				}*/		if (rv >= 0 && (t1 = t->left))			rv = execute(t1, pin, pout, 0);		break;	}  broken:	t->words = wp2;	isbreak = 0;	freehere(areanum);	freearea(areanum);	areanum = a;	if (interactive && intr) {		closeall();		fail();	}	if ((i = trapset) != 0) {		trapset = 0;		runtrap(i);	}	return (rv);}static int forkexec(t, pin, pout, act, wp, pforked)register struct op *t;int *pin, *pout;int act;char **wp;int *pforked;{	int i, rv, (*shcom) ();	register int f;	char *cp = NULL;	struct ioword **iopp;	int resetsig;	char **owp;	int *hpin = pin;	int *hpout = pout;	int hforked;	char *hwp;	int hinteractive;	int hintr;	struct brkcon * hbrklist;	int hexecflg;#if __GNUC__	/* Avoid longjmp clobbering */	(void) &pin;	(void) &pout;	(void) &wp;	(void) &shcom;	(void) &cp;	(void) &resetsig;	(void) &owp;#endif		owp = wp;	resetsig = 0;	*pforked = 0;	shcom = NULL;	rv = -1;					/* system-detected error */	if (t->type == TCOM) {		while ((cp = *wp++) != NULL);		cp = *wp;		/* strip all initial assignments */		/* not correct wrt PATH=yyy command  etc */		if (flag['x'])			echo(cp ? wp : owp);		if (cp == NULL && t->ioact == NULL) {			while ((cp = *owp++) != NULL && assign(cp, COPYV));			return (setstatus(0));		} else if (cp != NULL)			shcom = inbuilt(cp);	}	t->words = wp;	f = act;	if (shcom == NULL && (f & FEXEC) == 0) {	        /* save vars altered by child (needed by vfork) */		hpin = pin;		hpout = pout;		hforked = *pforked;		hwp = *wp;		hinteractive = interactive;		hintr = intr;		hbrklist = brklist;		hexecflg = execflg;			i = parent();		if (i != 0) {		        /* restore vars altered by child (needed by vfork) */			pin = hpin;			pout = hpout;			*pforked = hforked;			*wp = hwp;			interactive = hinteractive;			intr = hintr;			brklist = hbrklist;			execflg = hexecflg;			*pforked = 0;			if (i == -1)				return (rv);			if (pin != NULL)				closepipe(pin);			return (pout == NULL ? setstatus(waitfor(i, 0)) : 0);		}		if (interactive) {			signal(SIGINT, SIG_IGN);			signal(SIGQUIT, SIG_IGN);			resetsig = 1;		}		interactive = 0;		intr = 0;		(*pforked)++;		brklist = 0;		execflg = 0;	}	if (owp != NULL)		while ((cp = *owp++) != NULL && assign(cp, COPYV))			if (shcom == NULL)				export(lookup(cp));#ifdef COMPIPE	if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {		err("piping to/from shell builtins not yet done");		return (-1);	}#endif	if (pin != NULL) {		dup2(pin[0], 0);		closepipe(pin);	}	if (pout != NULL) {		dup2(pout[1], 1);		closepipe(pout);	}	if ((iopp = t->ioact) != NULL) {		if (shcom != NULL && shcom != doexec) {			prs(cp);			err(": cannot redirect shell command");			return (-1);		}		while (*iopp)			if (iosetup(*iopp++, pin != NULL, pout != NULL))				return (rv);	}	if (shcom)		return (setstatus((*shcom) (t)));	/* should use FIOCEXCL */	for (i = FDBASE; i < NOFILE; i++)		close(i);	if (resetsig) {		signal(SIGINT, SIG_DFL);		signal(SIGQUIT, SIG_DFL);	}	if (t->type == TPAREN)		_exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));	if (wp[0] == NULL)		_exit(0);	cp = rexecve(wp[0], wp, makenv(0));	prs(wp[0]);	prs(": ");	warn(cp);	if (!execflg)		trap[0] = NULL;#ifdef __uClinux__	_exit(1);#else	leave();#endif	/* NOTREACHED */}/* * 0< 1> are ignored as required * within pipelines. */int iosetup(iop, pipein, pipeout)register struct ioword *iop;int pipein, pipeout;{	int u;	char *msg;	char *cp = NULL;	if (iop->io_unit == IODEFAULT)	/* take default */		iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;	if (pipein && iop->io_unit == 0)		return (0);	if (pipeout && iop->io_unit == 1)		return (0);	msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";	if ((iop->io_flag & IOHERE) == 0) {		cp = iop->io_name;		if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)			return (1);	}	if (iop->io_flag & IODUP) {		if (cp[1] || (!digit(*cp) && *cp != '-')) {			prs(cp);			err(": illegal >& argument");			return (1);		}		if (*cp == '-')			iop->io_flag = IOCLOSE;		iop->io_flag &= ~(IOREAD | IOWRITE);	}	switch (iop->io_flag) {	case IOREAD:		u = open(cp, 0);		break;	case IOHERE:	case IOHERE | IOXHERE:		u = herein(iop->io_name, iop->io_flag & IOXHERE);		cp = "here file ";		break;	case IOWRITE | IOCAT:		if ((u = open(cp, 1)) >= 0) {			lseek(u, (long) 0, 2);			break;		}	case IOWRITE:		u = creat(cp, 0666);		break;	case IODUP:		u = dup2(*cp - '0', iop->io_unit);		break;	case IOCLOSE:		close(iop->io_unit);		return (0);	default:		u = -1;		break;	}	if (u < 0) {		int sav_err = errno;		prs(cp);		if (iop->io_flag & IOHERE)			prs(iop->io_name);		prs(": cannot ");		prs(msg);		prs(" (");		prs(strerror(sav_err));		warn(")");		return (1);	} else {		if (u != iop->io_unit) {			dup2(u, iop->io_unit);			close(u);		}	}	return (0);}static void echo(wp)register char **wp;{	int i;	prs("+");	for (i = 0; wp[i]; i++) {		if (i)			prs(" ");		prs(wp[i]);	}	prs("\n");}static struct op **find1case(t, w)struct op *t;char *w;{	register struct op *t1;	struct op **tp;	register char **wp, *cp;	if (t == NULL)		return ((struct op **) NULL);	if (t->type == TLIST) {		if ((tp = find1case(t->left, w)) != NULL)			return (tp);		t1 = t->right;			/* TPAT */	} else		t1 = t;	for (wp = t1->words; *wp;)		if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))			return (&t1->left);	return ((struct op **) NULL);}static struct op *findcase(t, w)struct op *t;char *w;{	register struct op **tp;	return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL);}/* * Enter a new loop level (marked for break/continue). */static void brkset(bc)struct brkcon *bc;{	bc->nextlev = brklist;	brklist = bc;}/* * Wait for the last process created. * Print a message for each process found * that was killed by a signal. * Ignore interrupt signals while waiting * unless `canintr' is true. */int waitfor(lastpid, canintr)register int lastpid;int canintr;{	register int pid, rv;	int s;	int oheedint = heedint;	heedint = 0;	rv = 0;	do {		pid = wait(&s);		if (pid == -1) {			if (errno != EINTR || canintr)				break;		} else {			if ((rv = WAITSIG(s)) != 0) {				if (rv < NSIGNAL) {					if (signame[rv] != NULL) {						if (pid != lastpid) {							prn(pid);							prs(": ");						}						prs(signame[rv]);					}				} else {					if (pid != lastpid) {						prn(pid);						prs(": ");					}					prs("Signal ");					prn(rv);					prs(" ");				}				if (WAITCORE(s))					prs(" - core dumped");				if (rv >= NSIGNAL || signame[rv])					prs("\n");				rv = -1;			} else				rv = WAITVAL(s);		}	} while (pid != lastpid);	heedint = oheedint;	if (intr) {		if (interactive) {			if (canintr)				intr = 0;		} else {			if (exstat == 0)				exstat = rv;			onintr(0);		}	}	return (rv);}int setstatus(s)register int s;{	exstat = s;	setval(lookup("?"), putn(s));	return (s);}/* * PATH-searching interface to execve. * If getenv("PATH") were kept up-to-date, * execvp might be used. */char *rexecve(c, v, envp)char *c, **v, **envp;{	register int i;	register char *sp, *tp;	int eacces = 0, asis = 0;#ifdef BB_FEATURE_SH_STANDALONE_SHELL	char *name = c;#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN	name = get_last_path_component(name);#endif	optind = 1;	if (find_applet_by_name(name)) {		/* We have to exec here since we vforked.  Running 		 * run_applet_by_name() won't work and bad things		 * will happen. */		execve("/proc/self/exe", v, envp);		execve("busybox", v, envp);	}#endif	sp = any('/', c)? "": path->value;	asis = *sp == '\0';	while (asis || *sp != '\0') {		asis = 0;		tp = e.linep;		for (; *sp != '\0'; tp++)			if ((*tp = *sp++) == ':') {				asis = *sp == '\0';				break;			}		if (tp != e.linep)			*tp++ = '/';		for (i = 0; (*tp++ = c[i++]) != '\0';);		execve(e.linep, v, envp);		switch (errno) {		case ENOEXEC:			*v = e.linep;			tp = *--v;			*v = e.linep;			execve("/bin/sh", v, envp);			*v = tp;			return ("no Shell");		case ENOMEM:			return ("program too big");		case E2BIG:			return ("argument list too long");		case EACCES:			eacces++;			break;		}	}	return (errno == ENOENT ? "not found" : "cannot execute");}/* * Run the command produced by generator `f' * applied to stream `arg'. */int run(argp, f)struct ioarg *argp;int (*f) ();{	struct op *otree;	struct wdblock *swdlist;	struct wdblock *siolist;	jmp_buf ev, rt;	xint *ofail;	int rv;#if __GNUC__	/* Avoid longjmp clobbering */	(void) &rv;#endif	areanum++;	swdlist = wdlist;	siolist = iolist;	otree = outtree;	ofail = failpt;	rv = -1;	if (newenv(setjmp(errpt = ev)) == 0) {		wdlist = 0;		iolist = 0;		pushio(argp, f);		e.iobase = e.iop;		yynerrs = 0;		if (setjmp(failpt = rt) == 0 && yyparse() == 0)			rv = execute(outtree, NOPIPE, NOPIPE, 0);		quitenv();	}	wdlist = swdlist;	iolist = siolist;	failpt = ofail;	outtree = otree;	freearea(areanum--);	return (rv);}/* -------- do.c -------- *//* * built-in commands: doX */static intdolabel(){	return (0);}static intdochdir(t)register struct op *t;{	register char *cp, *er;	if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)		er = ": no home directory";	else if (chdir(cp) < 0)		er = ": bad directory";	else {#ifdef TEST_NEW_VERSION#ifdef BB_FEATURE_SH_FANCY_PROMPT		char *cated = NULL;		if (*cp != '/')			cp = cated = concat_path_file(cwd, cp);		if (cwd != unknown)			free(cwd);		cwd = simplify_path(cp);		free(cated);#endif#endif		return (0);	}	prs(cp != NULL ? cp : "cd");	err(er);	return (1);}int doshift(t)register struct op *t;{	int n;	n = t->words[1] ? getn(t->words[1]) : 1;	if (dolc < n) {		err("nothing to shift");		return (1);	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?