X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fmsh.c;h=60fc1dc347e29168719552ed3dda73fb7b899bf9;hb=008c01915b69b006da92b986dd6fea6edb3c3097;hp=66c3d54d34518de8a18b4acc5203b3f0eb4013e8;hpb=ff9eee475f61800fe33bd60ac12b8b29015cbcdd;p=oweals%2Fbusybox.git diff --git a/shell/msh.c b/shell/msh.c index 66c3d54d3..60fc1dc34 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -52,6 +52,7 @@ #define LINELIM 2100 #define NPUSH 8 /* limit to input nesting */ +#undef NOFILE #define NOFILE 20 /* Number of open files */ #define NUFILE 10 /* Number of user-accessible files */ #define FDBASE 10 /* First file usable by Shell */ @@ -143,7 +144,7 @@ static int newfile(char *s); static char *findeq(char *cp); static char *cclass(char *p, int sub); static void initarea(void); -extern int shell_main(int argc, char **argv); +extern int msh_main(int argc, char **argv); struct brkcon { @@ -213,7 +214,8 @@ static char *elinep; /* * other functions */ -static int (*inbuilt(char *s ))(void); +static int(*inbuilt(char *s))(struct op *); + static char *rexecve (char *c , char **v, char **envp ); static char *space (int n ); @@ -394,7 +396,7 @@ struct ioarg { /* an input generator's state */ struct io { - int (*iofn)(); + int (*iofn)(struct ioarg *, struct io *); struct ioarg *argp; int peekc; char prev; /* previous character read by readc() */ @@ -429,7 +431,7 @@ static void freehere (int area ); static void gethere (void); static void markhere (char *s, struct ioword *iop ); static int herein (char *hname, int xdoll ); -static int run (struct ioarg *argp, int (*f)()); +static int run (struct ioarg *argp, int (*f)(struct ioarg *)); /* * IO functions @@ -446,7 +448,7 @@ static void closeall (void); /* * IO control */ -static void pushio (struct ioarg *argp, int (*fn)()); +static void pushio (struct ioarg *argp, int (*f)(struct ioarg *)); static int remap (int fd ); static int openpipe (int *pv ); static void closepipe (int *pv ); @@ -496,7 +498,8 @@ static void echo(char **wp ); static struct op **find1case (struct op *t, char *w ); static struct op *findcase (struct op *t, char *w ); static void brkset(struct brkcon *bc ); -static int dolabel(void); +static int dolabel(struct op *t ); +static int dohelp(struct op *t ); static int dochdir(struct op *t ); static int doshift(struct op *t ); static int dologin(struct op *t ); @@ -508,7 +511,7 @@ 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 void setsig (int n, sighandler_t f); static int getn(char *as ); static int dobreak(struct op *t ); static int docontinue(struct op *t ); @@ -516,11 +519,11 @@ 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 rdexp (char **wp, void (*f)(struct var *), int key); static void badid(char *s ); static int doset(struct op *t ); static void varput (char *s, int out ); -static int dotimes(void); +static int dotimes(struct op *t ); static int expand (char *cp, struct wdblock **wbp, int f ); static char *blank(int f ); static int dollar(int quoted ); @@ -534,7 +537,7 @@ static void glob1 (char *base, char *lim ); static void glob2 (char *i, char *j ); static void glob3 (char *i, char *j, char *k ); static void readhere (char **name, char *s, int ec ); -static void pushio(struct ioarg *argp, int (*fn)()); +static void pushio (struct ioarg *argp, int (*f)(struct ioarg *)); static int xxchar(struct ioarg *ap ); struct here { @@ -592,30 +595,31 @@ static struct res restab[] = { }; -struct builtin { - char *command; - int (*fn)(); +struct builtincmd { + const char *name; + int (*builtinfunc)(struct op *t); }; -static struct builtin builtin[] = { +static const struct builtincmd builtincmds[] = { + {".", dodot}, {":", dolabel}, - {"cd", dochdir}, - {"shift", doshift}, - {"exec", doexec}, - {"wait", dowait}, - {"read", doread}, - {"eval", doeval}, - {"trap", dotrap}, {"break", dobreak}, + {"cd", dochdir}, {"continue",docontinue}, + {"eval", doeval}, + {"exec", doexec}, {"exit", doexit}, {"export", doexport}, - {"readonly",doreadonly}, - {"set", doset}, - {".", dodot}, - {"umask", doumask}, + {"help", dohelp}, {"login", dologin}, {"newgrp", dologin}, + {"read", doread}, + {"readonly",doreadonly}, + {"set", doset}, + {"shift", doshift}, {"times", dotimes}, + {"trap", dotrap}, + {"umask", doumask}, + {"wait", dowait}, {0,0} }; @@ -679,9 +683,8 @@ static void * brktop; static void * brkaddr; -#ifdef BB_FEATURE_COMMAND_EDITING -char * current_prompt; -unsigned int shell_context; +#ifdef CONFIG_FEATURE_COMMAND_EDITING +static char * current_prompt; #endif @@ -691,13 +694,13 @@ unsigned int shell_context; */ -extern int shell_main(int argc, char **argv) +extern int msh_main(int argc, char **argv) { register int f; register char *s; int cflag; char *name, **ap; - int (*iof)(); + int (*iof)(struct ioarg *); initarea(); if ((ap = environ) != NULL) { @@ -731,14 +734,18 @@ extern int shell_main(int argc, char **argv) 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; @@ -794,8 +801,13 @@ extern int shell_main(int argc, char **argv) setdash(); if (e.iop < iostack) { PUSHIO(afile, 0, iof); - if (isatty(0) && isatty(1) && !cflag) + 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] == '-') { @@ -825,13 +837,15 @@ extern int shell_main(int argc, char **argv) for (;;) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#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); } } @@ -1062,8 +1076,7 @@ int n; } static void -next(f) -int f; +next(int f) { PUSHIO(afile, f, filechar); } @@ -1253,7 +1266,7 @@ static void ronly(vp) struct var *vp; { - if (isalpha(vp->name[0])) /* not an internal symbol ($# etc) */ + if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */ vp->status |= RONLY; } @@ -1261,10 +1274,10 @@ static int isassign(s) register char *s; { - if (!isalpha((int)*s)) + if (!isalpha((int)*s) && *s != '_') return(0); for (; *s != '='; s++) - if (*s == 0 || !isalnum(*s)) + if (*s == 0 || (!isalnum(*s) && *s != '_')) return(0); return(1); } @@ -1277,10 +1290,10 @@ int cf; register char *cp; struct var *vp; - if (!isalpha(*s)) + if (!isalpha(*s) && *s != '_') return(0); for (cp = s; *cp != '='; cp++) - if (*cp == 0 || !isalnum(*cp)) + if (*cp == 0 || (!isalnum(*cp) && *cp != '_')) return(0); vp = lookup(s); nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); @@ -1293,10 +1306,10 @@ static int checkname(cp) register char *cp; { - if (!isalpha(*cp++)) + if (!isalpha(*cp++) && *(cp-1) != '_') return(0); while (*cp) - if (!isalnum(*cp++)) + if (!isalnum(*cp++) && *(cp-1) != '_') return(0); return(1); } @@ -1308,7 +1321,7 @@ register int f, out; register struct var *vp; for (vp = vlist; vp; vp = vp->next) - if (vp->status & f && isalpha(*vp->name)) { + if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) { if (vp->status & EXPORT) write(out, "export ", 7); if (vp->status & RONLY) @@ -2161,7 +2174,7 @@ loop: startl = 1; if (multiline || cf & CONTIN) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value); @@ -2214,7 +2227,7 @@ register int c, c1; return(YYERRCODE); } if (interactive && c == '\n' && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value); @@ -2314,14 +2327,14 @@ int act; switch(t->type) { case TPAREN: case TCOM: - { - int child; - rv = forkexec(t, pin, pout, act, wp, &child); - if (child) { - exstat = rv; - leave(); + { + int child; + rv = forkexec(t, pin, pout, act, wp, &child); + if (child) { + exstat = rv; + leave(); + } } - } break; case TPIPE: @@ -2466,7 +2479,7 @@ static int forkexec( register struct op *t, int *pin, int *pout, int act, char **wp, int *pforked) { int i, rv; - int (*shcom)() = NULL; + int (*shcom)(struct op *) = NULL; register int f; char *cp = NULL; struct ioword **iopp; @@ -2828,6 +2841,21 @@ char *c, **v, **envp; register char *sp, *tp; int eacces = 0, asis = 0; +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL + char *name = c; +#ifdef CONFIG_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') { @@ -2842,6 +2870,7 @@ char *c, **v, **envp; *tp++ = '/'; for (i = 0; (*tp++ = c[i++]) != '\0';) ; + execve(e.linep, v, envp); switch (errno) { case ENOEXEC: @@ -2871,9 +2900,7 @@ char *c, **v, **envp; * applied to stream `arg'. */ static int -run(argp, f) -struct ioarg *argp; -int (*f)(); +run(struct ioarg *argp, int (*f)(struct ioarg *)) { struct op *otree; struct wdblock *swdlist; @@ -2917,8 +2944,50 @@ int (*f)(); * built-in commands: doX */ -static int -dolabel() +static int dohelp(struct op *t ) +{ + int col; + const struct builtincmd *x; + + printf("\nBuilt-in commands:\n"); + printf("-------------------\n"); + + for (col=0, x = builtincmds; x->builtinfunc != NULL; x++) { + if (!x->name) + continue; + col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name); + if (col > 60) { + printf("\n"); + col = 0; + } + } +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL + { + int i; + const struct BB_applet *applet; + extern const struct BB_applet applets[]; + extern const size_t NUM_APPLETS; + + for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) { + if (!applet->name) + continue; + + col += printf("%s%s", ((col == 0) ? "\t" : " "), + applet->name); + if (col > 60) { + printf("\n"); + col = 0; + } + } + } +#endif + printf("\n\n"); + return EXIT_SUCCESS; +} + + + +static int dolabel(struct op *t ) { return(0); } @@ -3155,7 +3224,7 @@ char *s; } static void -setsig( register int n, void (*f)(int)) +setsig( register int n, sighandler_t f) { if (n == 0) return; @@ -3256,18 +3325,22 @@ struct op *t; return(0); } -static void -rdexp(wp, f, key) -register char **wp; -void (*f)(); -int key; +static void rdexp (char **wp, void (*f)(struct var *), int key) { if (*wp != NULL) { - for (; *wp != NULL; wp++) + for (; *wp != NULL; wp++) { + if (isassign(*wp)) { + char *cp; + assign(*wp, COPYV); + for (cp = *wp; *cp != '='; cp++) + ; + *cp = '\0'; + } if (checkname(*wp)) (*f)(lookup(*wp)); else badid(*wp); + } } else putvlist(key, 1); } @@ -3331,7 +3404,7 @@ varput(s, out) register char *s; int out; { - if (isalnum(*s)) { + if (isalnum(*s) || *s == '_') { write(out, s, strlen(s)); write(out, "\n", 1); } @@ -3341,9 +3414,8 @@ int out; /* * Copyright (c) 1999 Herbert Xu * This file contains code for the times builtin. - * $Id: msh.c,v 1.1 2001/06/29 04:57:14 andersen Exp $ */ -static int dotimes () +static int dotimes(struct op *t ) { struct tms buf; long int clk_tck = sysconf(_SC_CLK_TCK); @@ -3362,15 +3434,15 @@ static int dotimes () } -static int (*inbuilt(s))() -register char *s; +static int(*inbuilt(char *s))(struct op *) { - register struct builtin *bp; + const struct builtincmd *bp; + + for (bp = builtincmds; bp->name != NULL; bp++) + if (strcmp(bp->name, s) == 0) + return(bp->builtinfunc); - for (bp = builtin; bp->command != NULL; bp++) - if (strcmp(bp->command, s) == 0) - return(bp->fn); - return((int(*)())NULL); + return(NULL); } /* -------- eval.c -------- */ @@ -3539,7 +3611,7 @@ loop: c = 0; } unget(c); - if (!isalpha(c)) + if (!isalpha(c) && c != '_') scanequals = 0; for (;;) { c = subgetc('"', foundequals); @@ -3557,7 +3629,7 @@ loop: foundequals = 1; scanequals = 0; } - else if (!isalnum(c)) + else if (!isalnum(c) && c != '_') scanequals = 0; } *e.linep++ = c; @@ -3610,8 +3682,8 @@ int quoted; s = e.linep; if (c != '{') { *e.linep++ = c; - if (isalpha(c)) { - while ((c = readc())!=0 && isalnum(c)) + if (isalpha(c) || c == '_') { + while ((c = readc())!=0 && (isalnum(c) || c == '_')) if (e.linep < elinep) *e.linep++ = c; unget(c); @@ -3725,7 +3797,7 @@ int quoted; if (i != 0) { e.iop->argp->aword = ++cp; close(pf[1]); - PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar); + PUSHIO(afile, remap(pf[0]), (int(*)(struct ioarg *))((quoted)? qgravechar: gravechar)); return(1); } *cp = 0; @@ -4180,7 +4252,7 @@ readc() if (multiline) return e.iop->prev = 0; if (interactive && e.iop == iostack+1) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=prompt->value; #else prs(prompt->value); @@ -4204,9 +4276,7 @@ char c; } static void -pushio(argp, fn) -struct ioarg *argp; -int (*fn)(); +pushio(struct ioarg *argp, int (*fn)(struct ioarg *)) { if (++e.iop >= &iostack[NPUSH]) { e.iop--; @@ -4214,7 +4284,7 @@ int (*fn)(); gflg++; return; } - e.iop->iofn = fn; + e.iop->iofn = (int (*)(struct ioarg *, struct io *))fn; if (argp->afid != AFID_NOBUF) e.iop->argp = argp; @@ -4237,7 +4307,7 @@ int (*fn)(); e.iop->nlcount = 0; if (fn == filechar || fn == linechar) e.iop->task = XIO; - else if (fn == gravechar || fn == qgravechar) + else if (fn == (int(*)(struct ioarg *))gravechar || fn == (int(*)(struct ioarg *))qgravechar) e.iop->task = XGRAVE; else e.iop->task = XOTHER; @@ -4374,9 +4444,7 @@ register struct ioarg *ap; if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) { if (i) lseek(ap->afile, ap->afpos, 0); - do { - i = read(ap->afile, bp->buf, sizeof(bp->buf)); - } while (i < 0 && errno == EINTR); + i = safe_read(ap->afile, bp->buf, sizeof(bp->buf)); if (i <= 0) { closef(ap->afile); return 0; @@ -4388,14 +4456,13 @@ register struct ioarg *ap; return *bp->bufp++ & 0177; } -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING if (interactive) { static char mycommand[BUFSIZ]; static int position = 0, size = 0; while (size == 0 || position >= size) { cmdedit_read_input(current_prompt, mycommand); - cmdedit_terminate(); size = strlen(mycommand); position = 0; } @@ -4405,9 +4472,7 @@ register struct ioarg *ap; } else #endif { - do { - i = read(ap->afile, &c, sizeof(c)); - } while (i < 0 && errno == EINTR); + i = safe_read(ap->afile, &c, sizeof(c)); return(i == sizeof(c)? c&0177: (closef(ap->afile), 0)); } } @@ -4646,11 +4711,11 @@ int ec; if (newenv(setjmp(errpt = ev)) != 0) unlink(tname); else { - pushio(e.iop->argp, e.iop->iofn); + pushio(e.iop->argp, (int(*)(struct ioarg *))e.iop->iofn); e.iobase = e.iop; for (;;) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value);