📄 msh.c
字号:
if (shell->value == null) setval(shell, DEFAULT_SHELL); export(shell); homedir = lookup("HOME"); if (homedir->value == null) setval(homedir, "/"); export(homedir); setval(lookup("$"), putn(getpid())); path = lookup("PATH"); if (path->value == null) { if (geteuid() == 0) setval(path, "/sbin:/bin:/usr/sbin:/usr/bin"); else setval(path, "/bin:/usr/bin"); } export(path); ifs = lookup("IFS"); if (ifs->value == null) setval(ifs, " \t\n"); prompt = lookup("PS1");#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT if (prompt->value == null)#endif setval(prompt, "$ "); if (geteuid() == 0) { setval(prompt, "# "); prompt->status &= ~EXPORT; } cprompt = lookup("PS2");#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT if (cprompt->value == null)#endif setval(cprompt, "> "); iof = filechar; cflag = 0; name = *argv++; if (--argc >= 1) { if(argv[0][0] == '-' && argv[0][1] != '\0') { for (s = argv[0]+1; *s; s++) switch (*s) { case 'c': prompt->status &= ~EXPORT; cprompt->status &= ~EXPORT; setval(prompt, ""); setval(cprompt, ""); cflag = 1; if (--argc > 0) PUSHIO(aword, *++argv, iof = nlchar); break; case 'q': qflag = SIG_DFL; break; case 's': /* standard input */ break; case 't': prompt->status &= ~EXPORT; setval(prompt, ""); iof = linechar; break; case 'i': interactive++; default: if (*s>='a' && *s<='z') flag[(int)*s]++; } } else { argv--; argc++; } if (iof == filechar && --argc > 0) { setval(prompt, ""); setval(cprompt, ""); prompt->status &= ~EXPORT; cprompt->status &= ~EXPORT; if (newfile(name = *++argv)) exit(1); } } setdash(); if (e.iop < iostack) { PUSHIO(afile, 0, iof); if (isatty(0) && isatty(1) && !cflag) { interactive++;#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET printf( "\n\n" BB_BANNER " Built-in shell (msh)\n"); printf( "Enter 'help' for a list of built-in commands.\n\n");#endif } } signal(SIGQUIT, qflag); if (name && name[0] == '-') { interactive++; if ((f = open(".profile", 0)) >= 0) next(remap(f)); if ((f = open("/etc/profile", 0)) >= 0) next(remap(f)); } if (interactive) signal(SIGTERM, sig); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); dolv = argv; dolc = argc; dolv[0] = name; if (dolc > 1) { for (ap = ++argv; --argc > 0;) { if (assign(*ap = *argv++, !COPYV)) { dolc--; /* keyword */ } else { ap++; } } } setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); for (;;) { if (interactive && e.iop <= iostack) {#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=prompt->value;#else prs(prompt->value);#endif } onecommand(); /* Ensure that getenv("PATH") stays current */ setenv("PATH", path->value, 1); }}static voidsetdash(){ register char *cp; register int c; char m['z'-'a'+1]; cp = m; for (c='a'; c<='z'; c++) if (flag[(int)c]) *cp++ = c; *cp = 0; setval(lookup("-"), m);}static intnewfile(s)register char *s;{ register int f; if (strcmp(s, "-") != 0) { f = open(s, 0); if (f < 0) { prs(s); err(": cannot open"); return(1); } } else f = 0; next(remap(f)); return(0);}static voidonecommand(){ register int i; jmp_buf m1; while (e.oenv) quitenv(); areanum = 1; freehere(areanum); freearea(areanum); garbage(); wdlist = 0; iolist = 0; e.errpt = 0; e.linep = line; yynerrs = 0; multiline = 0; inparse = 1; intr = 0; execflg = 0; setjmp(failpt = m1); /* Bruce Evans' fix */ if (setjmp(failpt = m1) || yyparse() || intr) { while (e.oenv) quitenv(); scraphere(); if (!interactive && intr) leave(); inparse = 0; intr = 0; return; } inparse = 0; brklist = 0; intr = 0; execflg = 0; if (!flag['n']) execute(outtree, NOPIPE, NOPIPE, 0); if (!interactive && intr) { execflg = 0; leave(); } if ((i = trapset) != 0) { trapset = 0; runtrap(i); }}static voidfail(){ longjmp(failpt, 1); /* NOTREACHED */}static voidleave(){ if (execflg) fail(); scraphere(); freehere(1); runtrap(0); exit(exstat); /* NOTREACHED */}static voidwarn(s)register char *s;{ if(*s) { prs(s); exstat = -1; } prs("\n"); if (flag['e']) leave();}static voiderr(s)char *s;{ warn(s); if (flag['n']) return; if (!interactive) leave(); if (e.errpt) longjmp(e.errpt, 1); closeall(); e.iop = e.iobase = iostack;}static intnewenv(f)int f;{ register struct env *ep; if (f) { quitenv(); return(1); } ep = (struct env *) space(sizeof(*ep)); if (ep == NULL) { while (e.oenv) quitenv(); fail(); } *ep = e; e.oenv = ep; e.errpt = errpt; return(0);}static voidquitenv(){ register struct env *ep; register int fd; if ((ep = e.oenv) != NULL) { fd = e.iofd; e = *ep; /* should close `'d files */ DELETE(ep); while (--fd >= e.iofd) close(fd); }}/* * Is any character from s1 in s2? */static intanys(s1, s2)register char *s1, *s2;{ while (*s1) if (any(*s1++, s2)) return(1); return(0);}/* * Is character c in s? */static intany(c, s)register int c;register char *s;{ while (*s) if (*s++ == c) return(1); return(0);}static char *putn(n)register int n;{ return(itoa(n));}static char *itoa(n)register int n;{ static char s[20]; snprintf(s, sizeof(s), "%u", n); return(s);}static voidnext(int f){ PUSHIO(afile, f, filechar);}static voidonintr(s)int s; /* ANSI C requires a parameter */{ signal(SIGINT, onintr); intr = 1; if (interactive) { if (inparse) { prs("\n"); fail(); } } else if (heedint) { execflg = 0; leave(); }}static char *space(n)int n;{ register char *cp; if ((cp = getcell(n)) == 0) err("out of string space"); return(cp);}static char *strsave(s, a)register char *s;int a;{ register char *cp, *xp; if ((cp = space(strlen(s)+1)) != NULL) { setarea((char *)cp, a); for (xp = cp; (*xp++ = *s++) != '\0';) ; return(cp); } return("");}/* * trap handling */static voidsig(i)register int i;{ trapset = i; signal(i, sig);}static void runtrap(i)int i;{ char *trapstr; if ((trapstr = trap[i]) == NULL) return; if (i == 0) trap[i] = 0; RUN(aword, trapstr, nlchar);}/* -------- var.c -------- *//* * Find the given name in the dictionary * and return its value. If the name was * not previously there, enter it now and * return a null value. */static struct var *lookup(n)register char *n;{ register struct var *vp; register char *cp; register int c; static struct var dummy; if (isdigit(*n)) { dummy.name = n; for (c = 0; isdigit(*n) && c < 1000; n++) c = c*10 + *n-'0'; dummy.status = RONLY; dummy.value = c <= dolc? dolv[c]: null; return(&dummy); } for (vp = vlist; vp; vp = vp->next) if (eqname(vp->name, n)) return(vp); cp = findeq(n); vp = (struct var *)space(sizeof(*vp)); if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) { dummy.name = dummy.value = ""; return(&dummy); } for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++) ; if (*cp == 0) *cp = '='; *++cp = 0; setarea((char *)vp, 0); setarea((char *)vp->name, 0); vp->value = null; vp->next = vlist; vp->status = GETCELL; vlist = vp; return(vp);}/* * give variable at `vp' the value `val'. */static voidsetval(vp, val)struct var *vp;char *val;{ nameval(vp, val, (char *)NULL);}/* * if name is not NULL, it must be * a prefix of the space `val', * and end with `='. * this is all so that exporting * values is reasonably painless. */static voidnameval(vp, val, name)register struct var *vp;char *val, *name;{ register char *cp, *xp; char *nv; int fl; if (vp->status & RONLY) { for (xp = vp->name; *xp && *xp != '=';) putc(*xp++, stderr); err(" is read-only"); return; } fl = 0; if (name == NULL) { xp = space(strlen(vp->name)+strlen(val)+2); if (xp == 0) return; /* make string: name=value */ setarea((char *)xp, 0); name = xp; for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++) ; if (*xp++ == 0) xp[-1] = '='; nv = xp; for (cp = val; (*xp++ = *cp++) != '\0';) ; val = nv; fl = GETCELL; } if (vp->status & GETCELL) freecell(vp->name); /* form new string `name=value' */ vp->name = name; vp->value = val; vp->status |= fl;}static voidexport(vp)struct var *vp;{ vp->status |= EXPORT;}static voidronly(vp)struct var *vp;{ if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */ vp->status |= RONLY;}static intisassign(s)register char *s;{ if (!isalpha((int)*s) && *s != '_') return(0); for (; *s != '='; s++) if (*s == 0 || (!isalnum(*s) && *s != '_')) return(0); return(1);}static intassign(s, cf)register char *s;int cf;{ register char *cp; struct var *vp; if (!isalpha(*s) && *s != '_') return(0); for (cp = s; *cp != '='; cp++) if (*cp == 0 || (!isalnum(*cp) && *cp != '_')) return(0); vp = lookup(s); nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); if (cf != COPYV) vp->status &= ~GETCELL; return(1);}static intcheckname(cp)register char *cp;{ if (!isalpha(*cp++) && *(cp-1) != '_') return(0); while (*cp) if (!isalnum(*cp++) && *(cp-1) != '_') return(0); return(1);}static voidputvlist(f, out)register int f, out;{ register struct var *vp; for (vp = vlist; vp; vp = vp->next) if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) { if (vp->status & EXPORT) write(out, "export ", 7); if (vp->status & RONLY) write(out, "readonly ", 9); write(out, vp->name, (int)(findeq(vp->name) - vp->name)); write(out, "\n", 1); }}static inteqname(n1, n2)register char *n1, *n2;{ for (; *n1 != '=' && *n1 != 0; n1++) if (*n2++ != *n1) return(0); return(*n2 == 0 || *n2 == '=');}static char *findeq(cp)register char *cp;{ while (*cp != '\0' && *cp != '=') cp++; return(cp);}/* -------- gmatch.c -------- *//* * int gmatch(string, pattern) * char *string, *pattern; * * Match a pattern as in sh(1). */#define CMASK 0377#define QUOTE 0200#define QMASK (CMASK&~QUOTE)#define NOT '!' /* might use ^ */static intgmatch(s, p)register char *s, *p;{ register int sc, pc; if (s == NULL || p == NULL) return(0); while ((pc = *p++ & CMASK) != '\0') { sc = *s++ & QMASK; switch (pc) { case '[': if ((p = cclass(p, sc)) == NULL) return(0); break; case '?': if (sc == 0) return(0); break; case '*': s--; do { if (*p == '\0' || gmatch(s, p)) return(1); } while (*s++ != '\0'); return(0); default: if (sc != (pc&~QUOTE)) return(0); } } return(*s == 0);}static char *cclass(p, sub)register char *p;register int sub;{ register int c, d, not, found; if ((not = *p == NOT) != 0) p++; found = not; do { if (*p == '\0') return((char *)NULL); c = *p & CMASK; if (p[1] == '-' && p[2] != ']') { d = p[2] & CMASK; p++; } else d = c; if (c == sub || (c <= sub && sub <= d)) found = !not; } while (*++p != ']'); return(found? p+1: (char *)NULL);}/* -------- area.c -------- *//* * All memory between (char *)areabot and (char *)(areatop+1) is * exclusively administered by the area management routines. * It is assumed that sbrk() and brk() manipulate the high end. */#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})static voidinitarea(){ brkaddr = malloc(65000); brktop = brkaddr + 65000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -