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) ℘#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) ℘ (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 + -
显示快捷键?