X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fmsh.c;h=dffacf02adac12befb6f19d093b60b185f532ce5;hb=e19e1935a33b117e2ee6daf9b2d79c00603333c7;hp=fd287f16e574f4b18935a4adc98333fdec7af1ec;hpb=284d0faed6a1ec2adcc4b7aea31ae3d05b3b70d9;p=oweals%2Fbusybox.git diff --git a/shell/msh.c b/shell/msh.c index fd287f16e..dffacf02a 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -12,7 +12,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ - #include #include @@ -35,16 +34,16 @@ # include # define bb_dev_null "/dev/null" # define DEFAULT_SHELL "/proc/self/exe" -# define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe" # define bb_banner "busybox standalone" # define ENABLE_FEATURE_SH_STANDALONE 0 # define bb_msg_memory_exhausted "memory exhausted" # define xmalloc(size) malloc(size) # define msh_main(argc,argv) main(argc,argv) # define safe_read(fd,buf,count) read(fd,buf,count) +# define nonblock_safe_read(fd,buf,count) read(fd,buf,count) # define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1]) # define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1]) -# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# define NORETURN __attribute__ ((__noreturn__)) static int find_applet_by_name(const char *applet) { return -1; @@ -89,21 +88,21 @@ static char *itoa(int n) //#define MSHDEBUG 4 #ifdef MSHDEBUG -int mshdbg = MSHDEBUG; - -#define DBGPRINTF(x) if (mshdbg>0) printf x -#define DBGPRINTF0(x) if (mshdbg>0) printf x -#define DBGPRINTF1(x) if (mshdbg>1) printf x -#define DBGPRINTF2(x) if (mshdbg>2) printf x -#define DBGPRINTF3(x) if (mshdbg>3) printf x -#define DBGPRINTF4(x) if (mshdbg>4) printf x -#define DBGPRINTF5(x) if (mshdbg>5) printf x -#define DBGPRINTF6(x) if (mshdbg>6) printf x -#define DBGPRINTF7(x) if (mshdbg>7) printf x -#define DBGPRINTF8(x) if (mshdbg>8) printf x -#define DBGPRINTF9(x) if (mshdbg>9) printf x - -int mshdbg_rc = 0; +static int mshdbg = MSHDEBUG; + +#define DBGPRINTF(x) if (mshdbg > 0) printf x +#define DBGPRINTF0(x) if (mshdbg > 0) printf x +#define DBGPRINTF1(x) if (mshdbg > 1) printf x +#define DBGPRINTF2(x) if (mshdbg > 2) printf x +#define DBGPRINTF3(x) if (mshdbg > 3) printf x +#define DBGPRINTF4(x) if (mshdbg > 4) printf x +#define DBGPRINTF5(x) if (mshdbg > 5) printf x +#define DBGPRINTF6(x) if (mshdbg > 6) printf x +#define DBGPRINTF7(x) if (mshdbg > 7) printf x +#define DBGPRINTF8(x) if (mshdbg > 8) printf x +#define DBGPRINTF9(x) if (mshdbg > 9) printf x + +static int mshdbg_rc = 0; #define RCPRINTF(x) if (mshdbg_rc) printf x @@ -123,7 +122,7 @@ int mshdbg_rc = 0; #define RCPRINTF(x) ((void)0) -#endif /* MSHDEBUG */ +#endif /* MSHDEBUG */ #if ENABLE_FEATURE_EDITING_FANCY_PROMPT @@ -140,13 +139,13 @@ int mshdbg_rc = 0; * shell */ -#define LINELIM 2100 -#define NPUSH 8 /* limit to input nesting */ +#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 */ +#define NOFILE 20 /* Number of open files */ +#define NUFILE 10 /* Number of user-accessible files */ +#define FDBASE 10 /* First file usable by Shell */ /* * values returned by wait @@ -158,7 +157,7 @@ int mshdbg_rc = 0; /* * library and system definitions */ -typedef void xint; /* base type of jmp_buf, for not broken compilers */ +typedef void xint; /* base type of jmp_buf, for not broken compilers */ /* * shell components @@ -172,8 +171,8 @@ typedef void xint; /* base type of jmp_buf, for not broken * redirection */ struct ioword { - short io_unit; /* unit affected */ - short io_flag; /* action (below) */ + smallint io_flag; /* action (below) */ + int io_fd; /* fd affected */ char *io_name; /* file name */ }; @@ -185,7 +184,7 @@ struct ioword { #define IODUP 32 /* >&digit */ #define IOCLOSE 64 /* >&- */ -#define IODEFAULT (-1) /* token for default IO unit */ +#define IODEFAULT (-1) /* "default" IO fd */ /* @@ -193,8 +192,8 @@ struct ioword { * Might eventually use a union. */ struct op { - smallint type; /* operation type, see Txxxx below */ - char **words; /* arguments to a command */ + smallint op_type; /* operation type, see Txxxx below */ + char **op_words; /* arguments to a command */ struct ioword **ioact; /* IO actions (eg, < > >>) */ struct op *left; struct op *right; @@ -488,36 +487,37 @@ static char **getwords(struct wdblock *wb); /* -------- misc stuff -------- */ +static int dolabel(struct op *t, char **args); +static int dohelp(struct op *t, char **args); +static int dochdir(struct op *t, char **args); +static int doshift(struct op *t, char **args); +static int dologin(struct op *t, char **args); +static int doumask(struct op *t, char **args); +static int doexec(struct op *t, char **args); +static int dodot(struct op *t, char **args); +static int dowait(struct op *t, char **args); +static int doread(struct op *t, char **args); +static int doeval(struct op *t, char **args); +static int dotrap(struct op *t, char **args); +static int dobreak(struct op *t, char **args); +static int doexit(struct op *t, char **args); +static int doexport(struct op *t, char **args); +static int doreadonly(struct op *t, char **args); +static int doset(struct op *t, char **args); +static int dotimes(struct op *t, char **args); +static int docontinue(struct op *t, char **args); + static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp); static int execute(struct op *t, int *pin, int *pout, int no_fork); static int iosetup(struct ioword *iop, int pipein, int pipeout); static void brkset(struct brkcon *bc); -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); -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, sighandler_t 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) (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(struct op *t); static int expand(const char *cp, struct wdblock **wbp, int f); static char *blank(int f); static int dollar(int quoted); @@ -525,9 +525,6 @@ static int grave(int quoted); static void globname(char *we, char *pp); static char *generate(char *start1, char *end1, char *middle, char *end); static int anyspcl(struct wdblock *wb); -static int xstrcmp(char *p1, char *p2); -static void glob0(char *a0, unsigned a1, int a2, - int (*a3) (char *, char *)); static void readhere(char **name, char *s, int ec); static int xxchar(struct ioarg *ap); @@ -558,7 +555,7 @@ static const char *const signame[] = { }; -typedef int (*builtin_func_ptr)(struct op *); +typedef int (*builtin_func_ptr)(struct op *, char **); struct builtincmd { const char *name; @@ -589,14 +586,13 @@ static const struct builtincmd builtincmds[] = { { NULL , NULL }, }; -static struct op *scantree(struct op *); -static struct op *dowholefile(int, int); +static struct op *dowholefile(int /*, int*/); /* Globals */ static char **dolv; static int dolc; -static int exstat; +static uint8_t exstat; static smallint gflg; /* (seems to be a parse error indicator) */ static smallint interactive; /* Is this an interactive shell */ static smallint execflg; @@ -704,7 +700,7 @@ struct globals { #define child_cmd (G.child_cmd ) #define iostack (G.iostack ) #define INIT_G() do { \ - PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ global_env.linep = line; \ global_env.iobase = iostack; \ global_env.iop = iostack - 1; \ @@ -720,24 +716,14 @@ struct globals { #define RUN(what, arg, gen) ((temparg.what = (arg)), run(&temparg, (gen))) #ifdef MSHDEBUG -void print_t(struct op *t) -{ - DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t, - T_CMD_NAMES[t->type], t->words, t->ioact)); - - if (t->words) { - DBGPRINTF(("T: W1: %s", t->words[0])); - } -} - -void print_tree(struct op *head) +static void print_tree(struct op *head) { if (head == NULL) { DBGPRINTF(("PRINT_TREE: no tree\n")); return; } - DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left, + DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left, head->right)); if (head->left) @@ -755,7 +741,7 @@ void print_tree(struct op *head) static void prs(const char *s) { if (*s) - write(2, s, strlen(s)); + xwrite_str(STDERR_FILENO, s); } static void prn(unsigned u) @@ -792,7 +778,7 @@ static void closeall(void) /* fail but return to process next command */ -static void fail(void) ATTRIBUTE_NORETURN; +static void fail(void) NORETURN; static void fail(void) { longjmp(failpt, 1); @@ -800,7 +786,7 @@ static void fail(void) } /* abort shell (or fail in subshell) */ -static void leave(void) ATTRIBUTE_NORETURN; +static void leave(void) NORETURN; static void leave(void) { DBGPRINTF(("LEAVE: leave called!\n")); @@ -818,7 +804,8 @@ static void warn(const char *s) { if (*s) { prs(s); - exstat = -1; + if (!exstat) + exstat = 255; } prs("\n"); if (FLAG['e']) @@ -1000,7 +987,7 @@ static void garbage(void) #endif } -static char *space(int n) +static void *get_space(int n) { char *cp; @@ -1014,7 +1001,7 @@ static char *strsave(const char *s, int a) { char *cp; - cp = space(strlen(s) + 1); + cp = get_space(strlen(s) + 1); if (cp == NULL) { // FIXME: I highly doubt this is good. return (char*)""; @@ -1072,8 +1059,8 @@ static struct var *lookup(const char *n) return vp; cp = findeq(n); - vp = (struct var *) space(sizeof(*vp)); - if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) { + vp = get_space(sizeof(*vp)); + if (vp == 0 || (vp->name = get_space((int) (cp - n) + 2)) == NULL) { dummy.name = dummy.value = (char*)""; return &dummy; } @@ -1114,7 +1101,7 @@ static void nameval(struct var *vp, const char *val, const char *name) } fl = 0; if (name == NULL) { - xp = space(strlen(vp->name) + strlen(val) + 2); + xp = get_space(strlen(vp->name) + strlen(val) + 2); if (xp == NULL) return; /* make string: name=value */ @@ -1279,7 +1266,7 @@ static int newfile(char *s) f = open(s, O_RDONLY); if (f < 0) { prs(s); - err(": cannot open"); + err(": can't open"); return 1; } } @@ -1289,6 +1276,7 @@ static int newfile(char *s) } +#ifdef UNUSED struct op *scantree(struct op *head) { struct op *dotnode; @@ -1308,18 +1296,19 @@ struct op *scantree(struct op *head) return dotnode; } - if (head->words == NULL) + if (head->op_words == NULL) return NULL; DBGPRINTF5(("SCANTREE: checking node %p\n", head)); - if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) { + if ((head->op_type != TDOT) && LONE_CHAR(head->op_words[0], '.')) { DBGPRINTF5(("SCANTREE: dot found in node %p\n", head)); return head; } return NULL; } +#endif static void onecommand(void) @@ -1336,9 +1325,9 @@ static void onecommand(void) freehere(areanum); freearea(areanum); garbage(); - wdlist = 0; - iolist = 0; - global_env.errpt = 0; + wdlist = NULL; + iolist = NULL; + global_env.errpt = NULL; global_env.linep = line; yynerrs = 0; multiline = 0; @@ -1396,7 +1385,7 @@ static int newenv(int f) return 1; } - ep = (struct env *) space(sizeof(*ep)); + ep = get_space(sizeof(*ep)); if (ep == NULL) { while (global_env.oenv) quitenv(); @@ -1459,7 +1448,7 @@ static void next(int f) PUSHIO(afile, f, filechar); } -static void onintr(int s) /* ANSI C requires a parameter */ +static void onintr(int s UNUSED_PARAM) /* ANSI C requires a parameter */ { signal(SIGINT, onintr); intr = 1; @@ -1554,7 +1543,7 @@ static int gmatch(const char *s, const char *p) * shell: syntax (C version) */ -static void yyerror(const char *s) ATTRIBUTE_NORETURN; +static void yyerror(const char *s) NORETURN; static void yyerror(const char *s) { yynerrs = 1; @@ -1567,7 +1556,7 @@ static void yyerror(const char *s) fail(); } -static void zzerr(void) ATTRIBUTE_NORETURN; +static void zzerr(void) NORETURN; static void zzerr(void) { yyerror("syntax error"); @@ -1604,7 +1593,7 @@ static struct op *pipeline(int cf) zzerr(); } - if (t->type != TPAREN && t->type != TCOM) { + if (t->op_type != TPAREN && t->op_type != TCOM) { /* shell statement */ t = block(TPAREN, t, NOBLOCK, NOWORDS); } @@ -1638,7 +1627,7 @@ static struct op *andor(void) } t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS); - } /* WHILE */ + } peeksym = c; } @@ -1662,8 +1651,8 @@ static struct op *c_list(void) t = block(TASYNC, t, NOBLOCK, NOWORDS); while ((c = yylex(0)) == ';' || c == '&' - || (multiline && c == '\n')) { - + || (multiline && c == '\n') + ) { p = andor(); if (p== NULL) return t; @@ -1734,7 +1723,7 @@ static struct op *simple(void) case WORD: if (t == NULL) { t = newtp(); - t->type = TCOM; + t->op_type = TCOM; } peeksym = 0; word(yylval.cp); @@ -1786,7 +1775,7 @@ static struct op *command(int cf) if (iolist == NULL) return NULL; t = newtp(); - t->type = TCOM; + t->op_type = TCOM; } break; @@ -1800,12 +1789,12 @@ static struct op *command(int cf) case FOR: t = newtp(); - t->type = TFOR; + t->op_type = TFOR; musthave(WORD, 0); startl = 1; t->str = yylval.cp; multiline++; - t->words = wordlist(); + t->op_words = wordlist(); c = yylex(0); if (c != '\n' && c != ';') peeksym = c; @@ -1817,16 +1806,16 @@ static struct op *command(int cf) case UNTIL: multiline++; t = newtp(); - t->type = (c == WHILE ? TWHILE : TUNTIL); + t->op_type = (c == WHILE ? TWHILE : TUNTIL); t->left = c_list(); t->right = dogroup(1); - t->words = NULL; + /* t->op_words = NULL; - newtp() did this */ multiline--; break; case CASE: t = newtp(); - t->type = TCASE; + t->op_type = TCASE; musthave(WORD, 0); t->str = yylval.cp; startl++; @@ -1843,7 +1832,7 @@ static struct op *command(int cf) case IF: multiline++; t = newtp(); - t->type = TIF; + t->op_type = TIF; t->left = c_list(); t->right = thenpart(); musthave(FI, 0); @@ -1852,19 +1841,20 @@ static struct op *command(int cf) case DOT: t = newtp(); - t->type = TDOT; + t->op_type = TDOT; - musthave(WORD, 0); /* gets name of file */ + musthave(WORD, 0); /* gets name of file */ DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp)); - word(yylval.cp); /* add word to wdlist */ - word(NOWORD); /* terminate wdlist */ - t->words = copyw(); /* dup wdlist */ + word(yylval.cp); /* add word to wdlist */ + word(NOWORD); /* terminate wdlist */ + t->op_words = copyw(); /* dup wdlist */ break; } - while (synio(0)); + while (synio(0)) + continue; t = namelist(t); iolist = iosave; @@ -1874,11 +1864,11 @@ static struct op *command(int cf) return t; } -static struct op *dowholefile(int type, int mark) +static struct op *dowholefile(int type /*, int mark*/) { struct op *t; - DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark)); + DBGPRINTF(("DOWHOLEFILE: enter, type=%d\n", type /*, mark*/)); multiline++; t = c_list(); @@ -1914,7 +1904,7 @@ static struct op *thenpart(void) return NULL; } t = newtp(); - /*t->type = 0; - newtp() did this */ + /*t->op_type = 0; - newtp() did this */ t->left = c_list(); if (t->left == NULL) zzerr(); @@ -1936,7 +1926,7 @@ static struct op *elsepart(void) case ELIF: t = newtp(); - t->type = TELIF; + t->op_type = TELIF; t->left = c_list(); t->right = thenpart(); return t; @@ -1968,8 +1958,8 @@ static struct op *casepart(void) DBGPRINTF7(("CASEPART: enter...\n")); t = newtp(); - t->type = TPAT; - t->words = pattern(); + t->op_type = TPAT; + t->op_words = pattern(); musthave(')', 0); t->left = c_list(); peeksym = yylex(CONTIN); @@ -2037,10 +2027,10 @@ static struct op *block(int type, struct op *t1, struct op *t2, char **wp) DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type])); t = newtp(); - t->type = type; + t->op_type = type; t->left = t1; t->right = t2; - t->words = wp; + t->op_words = wp; DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1, t2)); @@ -2106,7 +2096,7 @@ static struct op *newtp(void) static struct op *namelist(struct op *t) { DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t, - T_CMD_NAMES[t->type], iolist)); + T_CMD_NAMES[t->op_type], iolist)); if (iolist) { iolist = addword((char *) NULL, iolist); @@ -2114,8 +2104,8 @@ static struct op *namelist(struct op *t) } else t->ioact = NULL; - if (t->type != TCOM) { - if (t->type != TPAREN && t->ioact != NULL) { + if (t->op_type != TCOM) { + if (t->op_type != TPAREN && t->ioact != NULL) { t = block(TPAREN, t, NOBLOCK, NOWORDS); t->ioact = t->left->ioact; t->left->ioact = NULL; @@ -2124,7 +2114,7 @@ static struct op *namelist(struct op *t) } word(NOWORD); - t->words = copyw(); + t->op_words = copyw(); return t; } @@ -2134,7 +2124,7 @@ static char **copyw(void) char **wd; wd = getwords(wdlist); - wdlist = 0; + wdlist = NULL; return wd; } @@ -2148,7 +2138,7 @@ static struct ioword **copyio(void) struct ioword **iop; iop = (struct ioword **) getwords(iolist); - iolist = 0; + iolist = NULL; return iop; } @@ -2157,7 +2147,7 @@ static struct ioword *io(int u, int f, char *cp) struct ioword *iop; iop = (struct ioword *) tree(sizeof(*iop)); - iop->io_unit = u; + iop->io_fd = u; iop->io_flag = f; iop->io_name = cp; iolist = addword((char *) iop, iolist); @@ -2188,7 +2178,7 @@ static int yylex(int cf) loop: while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */ - ; + continue; switch (c) { default: @@ -2204,8 +2194,9 @@ static int yylex(int cf) } break; - case '#': /* Comment, skip to next newline or End-of-string */ - while ((c = my_getc(0)) != '\0' && c != '\n'); + case '#': /* Comment, skip to next newline or End-of-string */ + while ((c = my_getc(0)) != '\0' && c != '\n') + continue; unget(c); goto loop; @@ -2409,10 +2400,10 @@ static struct op **find1case(struct op *t, const char *w) return NULL; } - DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type, - T_CMD_NAMES[t->type])); + DBGPRINTF3(("FIND1CASE: enter, t->op_type=%d (%s)\n", t->op_type, + T_CMD_NAMES[t->op_type])); - if (t->type == TLIST) { + if (t->op_type == TLIST) { tp = find1case(t->left, w); if (tp != NULL) { DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp)); @@ -2422,7 +2413,7 @@ static struct op **find1case(struct op *t, const char *w) } else t1 = t; - for (wp = t1->words; *wp;) { + for (wp = t1->op_words; *wp;) { cp = evalstr(*wp++, DOSUB); if (cp && gmatch(w, cp)) { DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n", @@ -2467,26 +2458,26 @@ static int execute(struct op *t, int *pin, int *pout, int no_fork) return 0; } - DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t, - t->type, T_CMD_NAMES[t->type], - ((t->words == NULL) ? "NULL" : t->words[0]))); + DBGPRINTF(("EXECUTE: t=%p, t->op_type=%d (%s), t->op_words is %s\n", t, + t->op_type, T_CMD_NAMES[t->op_type], + ((t->op_words == NULL) ? "NULL" : t->op_words[0]))); rv = 0; a = areanum++; - wp2 = t->words; + wp2 = t->op_words; wp = (wp2 != NULL) - ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY) + ? eval(wp2, t->op_type == TCOM ? DOALL : DOALL & ~DOKEY) : NULL; - switch (t->type) { + switch (t->op_type) { case TDOT: DBGPRINTF3(("EXECUTE: TDOT\n")); outtree_save = outtree; - newfile(evalstr(t->words[0], DOALL)); + newfile(evalstr(t->op_words[0], DOALL)); - t->left = dowholefile(TLIST, 0); + t->left = dowholefile(TLIST /*, 0*/); t->right = NULL; outtree = outtree_save; @@ -2561,7 +2552,7 @@ static int execute(struct op *t, int *pin, int *pout, int no_fork) case TAND: rv = execute(t->left, pin, pout, /* no_fork: */ 0); t1 = t->right; - if (t1 != NULL && (rv == 0) == (t->type == TAND)) + if (t1 != NULL && (rv == 0) == (t->op_type == TAND)) rv = execute(t1, pin, pout, /* no_fork: */ 0); break; @@ -2573,12 +2564,17 @@ static int execute(struct op *t, int *pin, int *pout, int no_fork) i = 0; } else { i = -1; - while (*wp++ != NULL); + while (*wp++ != NULL) + continue; } vp = lookup(t->str); while (setjmp(bc.brkpt)) if (isbreak) goto broken; + /* Restore areanum value. It may be incremented by execute() + * below, and then "continue" may jump back to setjmp above */ + areanum = a + 1; + freearea(areanum + 1); brkset(&bc); for (t1 = t->left; i-- && *wp != NULL;) { setval(vp, *wp++); @@ -2592,9 +2588,13 @@ static int execute(struct op *t, int *pin, int *pout, int no_fork) while (setjmp(bc.brkpt)) if (isbreak) goto broken; + /* Restore areanum value. It may be incremented by execute() + * below, and then "continue" may jump back to setjmp above */ + areanum = a + 1; + freearea(areanum + 1); brkset(&bc); t1 = t->left; - while ((execute(t1, pin, pout, /* no_fork: */ 0) == 0) == (t->type == TWHILE)) + while ((execute(t1, pin, pout, /* no_fork: */ 0) == 0) == (t->op_type == TWHILE)) rv = execute(t->right, pin, pout, /* no_fork: */ 0); brklist = brklist->nextlev; break; @@ -2646,7 +2646,9 @@ static int execute(struct op *t, int *pin, int *pout, int no_fork) }; broken: - t->words = wp2; +// Restoring op_words is most likely not needed now: see comment in forkexec() +// (also take a look at exec builtin (doexec) - it touches t->op_words) + t->op_words = wp2; isbreak = 0; freehere(areanum); freearea(areanum); @@ -2709,11 +2711,11 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, no_fork %d\n", t, pin, pout, no_fork)); - DBGPRINTF7(("FORKEXEC: t->words is %s\n", - ((t->words == NULL) ? "NULL" : t->words[0]))); + DBGPRINTF7(("FORKEXEC: t->op_words is %s\n", + ((t->op_words == NULL) ? "NULL" : t->op_words[0]))); owp = wp; resetsig = 0; - if (t->type == TCOM) { + if (t->op_type == TCOM) { while (*wp++ != NULL) continue; cp = *wp; @@ -2740,7 +2742,13 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) } forked = 0; - t->words = wp; + // We were pointing t->op_words to temporary (expanded) arg list: + // t->op_words = wp; + // and restored it later (in execute()), but "break" + // longjmps away (at "Run builtin" below), leaving t->op_words clobbered! + // See http://bugs.busybox.net/view.php?id=846. + // Now we do not touch t->op_words, but separately pass wp as param list + // to builtins DBGPRINTF(("FORKEXEC: bltin %p, no_fork %d, owp %p\n", bltin, no_fork, owp)); /* Don't fork if it is a lone builtin (not in pipe) @@ -2760,7 +2768,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) DBGPRINTF3(("FORKEXEC: calling vfork()...\n")); newpid = vfork(); if (newpid == -1) { - DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n")); + DBGPRINTF(("FORKEXEC: ERROR, can't vfork()!\n")); return -1; } @@ -2810,7 +2818,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) if (iopp) { if (bltin && bltin != doexec) { prs(bltin_name); - err(": cannot redirect shell command"); + err(": can't redirect shell command"); if (forked) _exit(-1); return -1; @@ -2830,12 +2838,13 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) /* Builtin in pipe: disallowed */ /* TODO: allow "exec"? */ prs(bltin_name); - err(": cannot run builtin as part of pipe"); + err(": can't run builtin as part of pipe"); if (forked) _exit(-1); return -1; } - i = setstatus(bltin(t)); + /* Run builtin */ + i = setstatus(bltin(t, wp)); if (forked) _exit(i); DBGPRINTF(("FORKEXEC: returning i=%d\n", i)); @@ -2850,10 +2859,10 @@ static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) signal(SIGQUIT, SIG_DFL); } - if (t->type == TPAREN) + if (t->op_type == TPAREN) _exit(execute(t->left, NOPIPE, NOPIPE, /* no_fork: */ 1)); if (wp[0] == NULL) - _exit(0); + _exit(EXIT_SUCCESS); cp = rexecve(wp[0], wp, makenv(0, NULL)); prs(wp[0]); @@ -2882,13 +2891,13 @@ static int iosetup(struct ioword *iop, int pipein, int pipeout) DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop, pipein, pipeout)); - if (iop->io_unit == IODEFAULT) /* take default */ - iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1; + if (iop->io_fd == IODEFAULT) /* take default */ + iop->io_fd = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1; - if (pipein && iop->io_unit == 0) + if (pipein && iop->io_fd == 0) return 0; - if (pipeout && iop->io_unit == 1) + if (pipeout && iop->io_fd == 1) return 0; msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create"; @@ -2934,24 +2943,21 @@ static int iosetup(struct ioword *iop, int pipein, int pipeout) break; case IODUP: - u = dup2(*cp - '0', iop->io_unit); + u = dup2(*cp - '0', iop->io_fd); break; case IOCLOSE: - close(iop->io_unit); + close(iop->io_fd); return 0; } if (u < 0) { prs(cp); - prs(": cannot "); + prs(": can't "); warn(msg); return 1; } - if (u != iop->io_unit) { - dup2(u, iop->io_unit); - close(u); - } + xmove_fd(u, iop->io_fd); return 0; } @@ -3008,7 +3014,7 @@ static int waitfor(int lastpid, int canintr) prs(" - core dumped"); if (rv >= ARRAY_SIZE(signame) || signame[rv]) prs("\n"); - rv = -1; + rv |= 0x80; } else rv = WAITVAL(s); } @@ -3041,7 +3047,6 @@ static int setstatus(int s) */ static const char *rexecve(char *c, char **v, char **envp) { - int i; const char *sp; char *tp; int asis = 0; @@ -3072,7 +3077,7 @@ static const char *rexecve(char *c, char **v, char **envp) } if (tp != global_env.linep) *tp++ = '/'; - for (i = 0; (*tp++ = c[i++]) != '\0';); + strcpy(tp, c); DBGPRINTF3(("REXECVE: global_env.linep is %s\n", global_env.linep)); @@ -3080,12 +3085,16 @@ static const char *rexecve(char *c, char **v, char **envp) switch (errno) { case ENOEXEC: + /* File is executable but file format isnt recognized */ + /* Run it as a shell script */ + /* (execve above didnt do it itself, unlike execvp) */ *v = global_env.linep; - tp = *--v; - *v = global_env.linep; + v--; + tp = *v; + *v = (char*)DEFAULT_SHELL; execve(DEFAULT_SHELL, v, envp); *v = tp; - return "no Shell"; + return "no shell"; case ENOMEM: return (char *) bb_msg_memory_exhausted; @@ -3094,7 +3103,12 @@ static const char *rexecve(char *c, char **v, char **envp) return "argument list too long"; } } - return errno == ENOENT ? "not found" : "cannot execute"; + if (errno == ENOENT) { + exstat = 127; /* standards require this */ + return "not found"; + } + exstat = 126; /* mimic bash */ + return "can't execute"; } /* @@ -3127,8 +3141,8 @@ static int run(struct ioarg *argp, int (*f) (struct ioarg *)) errpt = ev; if (newenv(setjmp(errpt)) == 0) { - wdlist = 0; - iolist = 0; + wdlist = NULL; + iolist = NULL; pushio(argp, f); global_env.iobase = global_env.iop; yynerrs = 0; @@ -3155,13 +3169,14 @@ static int run(struct ioarg *argp, int (*f) (struct ioarg *)) * built-in commands: doX */ -static int dohelp(struct op *t) +static int dohelp(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM) { int col; const struct builtincmd *x; - puts("\nBuilt-in commands:\n" - "-------------------"); + printf("\n" + "Built-in commands:\n" + "------------------\n"); col = 0; x = builtincmds; @@ -3191,16 +3206,16 @@ static int dohelp(struct op *t) return EXIT_SUCCESS; } -static int dolabel(struct op *t) +static int dolabel(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM) { return 0; } -static int dochdir(struct op *t) +static int dochdir(struct op *t UNUSED_PARAM, char **args) { const char *cp, *er; - cp = t->words[1]; + cp = args[1]; if (cp == NULL) { cp = homedir->value; if (cp != NULL) @@ -3217,11 +3232,11 @@ static int dochdir(struct op *t) return 1; } -static int doshift(struct op *t) +static int doshift(struct op *t UNUSED_PARAM, char **args) { int n; - n = t->words[1] ? getn(t->words[1]) : 1; + n = args[1] ? getn(args[1]) : 1; if (dolc < n) { err("nothing to shift"); return 1; @@ -3236,7 +3251,7 @@ static int doshift(struct op *t) /* * execute login and newgrp directly */ -static int dologin(struct op *t) +static int dologin(struct op *t UNUSED_PARAM, char **args) { const char *cp; @@ -3244,19 +3259,19 @@ static int dologin(struct op *t) signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); } - cp = rexecve(t->words[0], t->words, makenv(0, NULL)); - prs(t->words[0]); + cp = rexecve(args[0], args, makenv(0, NULL)); + prs(args[0]); prs(": "); err(cp); return 1; } -static int doumask(struct op *t) +static int doumask(struct op *t UNUSED_PARAM, char **args) { int i; char *cp; - cp = t->words[1]; + cp = args[1]; if (cp == NULL) { i = umask(0); umask(i); @@ -3272,28 +3287,36 @@ static int doumask(struct op *t) return 0; } -static int doexec(struct op *t) +static int doexec(struct op *t, char **args) { - int i; jmp_buf ex; xint *ofail; + char **sv_words; t->ioact = NULL; - for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++) - continue; - if (i == 0) + if (!args[1]) return 1; + execflg = 1; ofail = failpt; failpt = ex; + + sv_words = t->op_words; + t->op_words = args + 1; +// TODO: test what will happen with "exec break" - +// will it leave t->op_words pointing to garbage? +// (see http://bugs.busybox.net/view.php?id=846) if (setjmp(failpt) == 0) execute(t, NOPIPE, NOPIPE, /* no_fork: */ 1); + t->op_words = sv_words; + failpt = ofail; execflg = 0; + return 1; } -static int dodot(struct op *t) +static int dodot(struct op *t UNUSED_PARAM, char **args) { int i; const char *sp; @@ -3304,7 +3327,7 @@ static int dodot(struct op *t) DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, global_env.linep is %s\n", t, t->left, t->right, ((global_env.linep == NULL) ? "NULL" : global_env.linep))); - cp = t->words[1]; + cp = args[1]; if (cp == NULL) { DBGPRINTF(("DODOT: bad args, ret 0\n")); return 0; @@ -3323,8 +3346,7 @@ static int dodot(struct op *t) tp++; if (tp != global_env.linep) *tp++ = '/'; - - for (i = 0; (*tp++ = cp[i++]) != '\0';); + strcpy(tp, cp); /* Original code */ i = open(global_env.linep, O_RDONLY); @@ -3348,12 +3370,12 @@ static int dodot(struct op *t) return -1; } -static int dowait(struct op *t) +static int dowait(struct op *t UNUSED_PARAM, char **args) { int i; char *cp; - cp = t->words[1]; + cp = args[1]; if (cp != NULL) { i = getn(cp); if (i == 0) @@ -3364,19 +3386,19 @@ static int dowait(struct op *t) return 0; } -static int doread(struct op *t) +static int doread(struct op *t UNUSED_PARAM, char **args) { char *cp, **wp; int nb = 0; int nl = 0; - if (t->words[1] == NULL) { + if (args[1] == NULL) { err("Usage: read name ..."); return 1; } - for (wp = t->words + 1; *wp; wp++) { + for (wp = args + 1; *wp; wp++) { for (cp = global_env.linep; !nl && cp < elinep - 1; cp++) { - nb = read(0, cp, sizeof(*cp)); + nb = nonblock_safe_read(STDIN_FILENO, cp, sizeof(*cp)); if (nb != sizeof(*cp)) break; nl = (*cp == '\n'); @@ -3391,17 +3413,17 @@ static int doread(struct op *t) return nb <= 0; } -static int doeval(struct op *t) +static int doeval(struct op *t UNUSED_PARAM, char **args) { - return RUN(awordlist, t->words + 1, wdchar); + return RUN(awordlist, args + 1, wdchar); } -static int dotrap(struct op *t) +static int dotrap(struct op *t UNUSED_PARAM, char **args) { int n, i; int resetsig; - if (t->words[1] == NULL) { + if (args[1] == NULL) { for (i = 0; i <= _NSIG; i++) if (trap[i]) { prn(i); @@ -3411,14 +3433,14 @@ static int dotrap(struct op *t) } return 0; } - resetsig = isdigit(*t->words[1]); - for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) { - n = getsig(t->words[i]); + resetsig = isdigit(args[1][0]); + for (i = resetsig ? 1 : 2; args[i] != NULL; ++i) { + n = getsig(args[i]); freecell(trap[n]); trap[n] = 0; if (!resetsig) { - if (*t->words[1] != '\0') { - trap[n] = strsave(t->words[1], 0); + if (args[1][0] != '\0') { + trap[n] = strsave(args[1], 0); setsig(n, sig); } else setsig(n, SIG_IGN); @@ -3477,14 +3499,14 @@ static int getn(char *as) return n * m; } -static int dobreak(struct op *t) +static int dobreak(struct op *t UNUSED_PARAM, char **args) { - return brkcontin(t->words[1], 1); + return brkcontin(args[1], 1); } -static int docontinue(struct op *t) +static int docontinue(struct op *t UNUSED_PARAM, char **args) { - return brkcontin(t->words[1], 0); + return brkcontin(args[1], 0); } static int brkcontin(char *cp, int val) @@ -3510,12 +3532,12 @@ static int brkcontin(char *cp, int val) /* NOTREACHED */ } -static int doexit(struct op *t) +static int doexit(struct op *t UNUSED_PARAM, char **args) { char *cp; execflg = 0; - cp = t->words[1]; + cp = args[1]; if (cp != NULL) setstatus(getn(cp)); @@ -3526,15 +3548,15 @@ static int doexit(struct op *t) return 0; } -static int doexport(struct op *t) +static int doexport(struct op *t UNUSED_PARAM, char **args) { - rdexp(t->words + 1, export, EXPORT); + rdexp(args + 1, export, EXPORT); return 0; } -static int doreadonly(struct op *t) +static int doreadonly(struct op *t UNUSED_PARAM, char **args) { - rdexp(t->words + 1, ronly, RONLY); + rdexp(args + 1, ronly, RONLY); return 0; } @@ -3549,7 +3571,8 @@ static void rdexp(char **wp, void (*f) (struct var *), int key) char *cp; assign(*wp, COPYV); - for (cp = *wp; *cp != '='; cp++); + for (cp = *wp; *cp != '='; cp++) + continue; *cp = '\0'; } if (checkname(*wp)) @@ -3567,21 +3590,20 @@ static void badid(char *s) err(": bad identifier"); } -static int doset(struct op *t) +static int doset(struct op *t UNUSED_PARAM, char **args) { struct var *vp; char *cp; int n; - cp = t->words[1]; + cp = args[1]; if (cp == NULL) { for (vp = vlist; vp; vp = vp->next) - varput(vp->name, 1); + varput(vp->name, STDOUT_FILENO); return 0; } if (*cp == '-') { - /* bad: t->words++; */ - for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++); + args++; if (*++cp == 0) FLAG['x'] = FLAG['v'] = 0; else { @@ -3601,12 +3623,12 @@ static int doset(struct op *t) } setdash(); } - if (t->words[1]) { - t->words[0] = dolv[0]; - for (n = 1; t->words[n]; n++) - setarea((char *) t->words[n], 0); + if (args[1]) { + args[0] = dolv[0]; + for (n = 1; args[n]; n++) + setarea((char *) args[n], 0); dolc = n - 1; - dolv = t->words; + dolv = args; setval(lookup("#"), putn(dolc)); setarea((char *) (dolv - 1), 0); } @@ -3616,8 +3638,8 @@ static int doset(struct op *t) static void varput(char *s, int out) { if (isalnum(*s) || *s == '_') { - write(out, s, strlen(s)); - write(out, "\n", 1); + xwrite_str(out, s); + xwrite(out, "\n", 1); } } @@ -3626,21 +3648,40 @@ static void varput(char *s, int out) * Copyright (c) 1999 Herbert Xu * This file contains code for the times builtin. */ -static int dotimes(struct op *t) +static void times_fmt(char *buf, clock_t val, unsigned clk_tck) +{ + unsigned min, sec; + if (sizeof(val) > sizeof(int)) + sec = ((unsigned long)val) / clk_tck; + else + sec = ((unsigned)val) / clk_tck; + min = sec / 60; +#if ENABLE_DESKTOP + sprintf(buf, "%um%u.%03us", min, (sec - min * 60), + /* msec: */ ((unsigned)(val - (clock_t)sec * clk_tck)) * 1000 / clk_tck + ); +#else + sprintf(buf, "%um%us", min, (sec - min * 60)); +#endif +} + +static int dotimes(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM) { struct tms buf; - long clk_tck = sysconf(_SC_CLK_TCK); + unsigned clk_tck = sysconf(_SC_CLK_TCK); + /* How much do we need for "NmN.NNNs" ? */ + enum { TIMEBUF_SIZE = sizeof(int)*3 + sizeof(int)*3 + 6 }; + char u[TIMEBUF_SIZE], s[TIMEBUF_SIZE]; + char cu[TIMEBUF_SIZE], cs[TIMEBUF_SIZE]; times(&buf); - printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", - (int) (buf.tms_utime / clk_tck / 60), - ((double) buf.tms_utime) / clk_tck, - (int) (buf.tms_stime / clk_tck / 60), - ((double) buf.tms_stime) / clk_tck, - (int) (buf.tms_cutime / clk_tck / 60), - ((double) buf.tms_cutime) / clk_tck, - (int) (buf.tms_cstime / clk_tck / 60), - ((double) buf.tms_cstime) / clk_tck); + + times_fmt(u, buf.tms_utime, clk_tck); + times_fmt(s, buf.tms_stime, clk_tck); + times_fmt(cu, buf.tms_cutime, clk_tck); + times_fmt(cs, buf.tms_cstime, clk_tck); + + printf("%s %s\n%s %s\n", u, s, cu, cs); return 0; } @@ -3954,7 +3995,7 @@ static int dollar(int quoted) switch (c) { case '=': if (isdigit(*s)) { - err("cannot use ${...=...} with $n"); + err("can't use ${...=...} with $n"); gflg = 1; break; } @@ -4138,7 +4179,8 @@ static int grave(int quoted) if (openpipe(pf) < 0) return 0; - while ((i = vfork()) == -1 && errno == EAGAIN); + while ((i = vfork()) == -1 && errno == EAGAIN) + continue; DBGPRINTF3(("GRAVE: i is %p\n", io)); @@ -4179,7 +4221,7 @@ static int grave(int quoted) prs(argument_list[0]); prs(": "); err(cp); - _exit(1); + _exit(EXIT_FAILURE); } @@ -4236,10 +4278,10 @@ static struct wdblock *glob(char *cp, struct wdblock *wb) DELETE(cl->w_words[i]); DELETE(cl); } - for (i = 0; i < cl->w_nword; i++) - unquote(cl->w_words[i]); - glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp); if (cl->w_nword) { + for (i = 0; i < cl->w_nword; i++) + unquote(cl->w_words[i]); + qsort_string_vector(cl->w_words, cl->w_nword); for (i = 0; i < cl->w_nword; i++) wb = addword(cl->w_words[i], wb); DELETE(cl); @@ -4263,11 +4305,13 @@ static void globname(char *we, char *pp) for (np = we; np != pp; pp--) if (pp[-1] == '/') break; - for (dp = cp = space((int) (pp - np) + 3); np < pp;) + dp = cp = get_space((int) (pp - np) + 3); + while (np < pp) *cp++ = *np++; *cp++ = '.'; *cp = '\0'; - for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';) + gp = cp = get_space(strlen(pp) + 1); + while (*np && *np != '/') *cp++ = *np++; *cp = '\0'; dirp = opendir(dp); @@ -4279,9 +4323,7 @@ static void globname(char *we, char *pp) dname[NAME_MAX] = '\0'; while ((de = readdir(dirp)) != NULL) { /* XXX Hmmm... What this could be? (abial) */ - /* - if (ent[j].d_ino == 0) - continue; + /* if (ent[j].d_ino == 0) continue; */ strncpy(dname, de->d_name, NAME_MAX); if (dname[0] == '.') @@ -4316,12 +4358,14 @@ static char *generate(char *start1, char *end1, char *middle, char *end) char *p; char *op, *xp; - p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2); - for (xp = start1; xp != end1;) + p = op = get_space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2); + xp = start1; + while (xp != end1) + *op++ = *xp++; + xp = middle; + while (*xp != '\0') *op++ = *xp++; - for (xp = middle; (*op++ = *xp++) != '\0';); - op--; - for (xp = end; (*op++ = *xp++) != '\0';); + strcpy(op, end); return p; } @@ -4337,11 +4381,6 @@ static int anyspcl(struct wdblock *wb) return 0; } -static int xstrcmp(char *p1, char *p2) -{ - return strcmp(*(char **) p1, *(char **) p2); -} - /* -------- word.c -------- */ @@ -4349,7 +4388,7 @@ static struct wdblock *newword(int nw) { struct wdblock *wb; - wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *)); + wb = get_space(sizeof(*wb) + nw * sizeof(char *)); wb->w_bsize = nw; wb->w_nword = 0; return wb; @@ -4386,129 +4425,13 @@ static char **getwords(struct wdblock *wb) DELETE(wb); return NULL; } - wd = (char **) space(nb = sizeof(*wd) * wb->w_nword); - memcpy((char *) wd, (char *) wb->w_words, nb); - DELETE(wb); /* perhaps should done by caller */ + nb = sizeof(*wd) * wb->w_nword; + wd = get_space(nb); + memcpy(wd, wb->w_words, nb); + DELETE(wb); /* perhaps should done by caller */ return wd; } -static int (*func) (char *, char *); -static int globv; - -static void glob3(char *i, char *j, char *k) -{ - char *index1, *index2, *index3; - int c; - int m; - - m = globv; - index1 = i; - index2 = j; - index3 = k; - do { - c = *index1; - *index1++ = *index3; - *index3++ = *index2; - *index2++ = c; - } while (--m); -} - -static void glob2(char *i, char *j) -{ - char *index1, *index2, c; - int m; - - m = globv; - index1 = i; - index2 = j; - do { - c = *index1; - *index1++ = *index2; - *index2++ = c; - } while (--m); -} - -static void glob1(char *base, char *lim) -{ - char *i, *j; - int v2; - char *lptr, *hptr; - int c; - unsigned n; - - v2 = globv; - - top: - n = (int) (lim - base); - if (n <= v2) - return; - n = v2 * (n / (2 * v2)); - hptr = lptr = base + n; - i = base; - j = lim - v2; - for (;;) { - if (i < lptr) { - c = (*func) (i, lptr); - if (c == 0) { - lptr -= v2; - glob2(i, lptr); - continue; - } - if (c < 0) { - i += v2; - continue; - } - } - - begin: - if (j > hptr) { - c = (*func) (hptr, j); - if (c == 0) { - hptr += v2; - glob2(hptr, j); - goto begin; - } - if (c > 0) { - if (i == lptr) { - hptr += v2; - glob3(i, hptr, j); - i = (lptr += v2); - goto begin; - } - glob2(i, j); - j -= v2; - i += v2; - continue; - } - j -= v2; - goto begin; - } - - - if (i == lptr) { - if (lptr - base >= lim - hptr) { - glob1(hptr + v2, lim); - lim = lptr; - } else { - glob1(base, lptr); - base = hptr + v2; - } - goto top; - } - - lptr -= v2; - glob3(j, lptr, i); - j = (hptr -= v2); - } -} - -static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *)) -{ - func = a3; - globv = a2; - glob1(a0, a0 + a1 * a2); -} - /* -------- io.c -------- */ @@ -4521,7 +4444,8 @@ static int my_getc(int ec) int c; if (global_env.linep > elinep) { - while ((c = readc()) != '\n' && c); + while ((c = readc()) != '\n' && c) + continue; err("input line too long"); gflg = 1; return c; @@ -4572,7 +4496,7 @@ static int readc(void) if (global_env.iop == iostack) ioecho(c); global_env.iop->prev = c; - return global_env.iop->prev; + return c; } if (global_env.iop->task == XIO && global_env.iop->prev != '\n') { global_env.iop->prev = 0; @@ -4584,7 +4508,7 @@ static int readc(void) if (global_env.iop->task == XIO) { if (multiline) { global_env.iop->prev = 0; - return global_env.iop->prev; + return 0; } if (interactive && global_env.iop == iostack + 1) { #if ENABLE_FEATURE_EDITING @@ -4610,7 +4534,7 @@ static int readc(void) static void ioecho(char c) { if (FLAG['v']) - write(2, &c, sizeof c); + write(STDERR_FILENO, &c, sizeof c); } static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *)) @@ -4670,7 +4594,7 @@ static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *)) if (fn == filechar || fn == linechar) global_env.iop->task = XIO; else if (fn == (int (*)(struct ioarg *)) gravechar - || fn == (int (*)(struct ioarg *)) qgravechar) + || fn == (int (*)(struct ioarg *)) qgravechar) global_env.iop->task = XGRAVE; else global_env.iop->task = XOTHER; @@ -4690,16 +4614,16 @@ static struct io *setbase(struct io *ip) */ /* - * Produce the characters of a string, then a newline, then EOF. + * Produce the characters of a string, then a newline, then NUL. */ static int nlchar(struct ioarg *ap) { - int c; + char c; if (ap->aword == NULL) - return 0; + return '\0'; c = *ap->aword++; - if (c == 0) { + if (c == '\0') { ap->aword = NULL; return '\n'; } @@ -4799,7 +4723,7 @@ static int filechar(struct ioarg *ap) if (i) lseek(ap->afile, ap->afpos, SEEK_SET); - i = safe_read(ap->afile, bp->buf, sizeof(bp->buf)); + i = nonblock_safe_read(ap->afile, bp->buf, sizeof(bp->buf)); if (i <= 0) { closef(ap->afile); return 0; @@ -4821,7 +4745,7 @@ static int filechar(struct ioarg *ap) while (size == 0 || position >= size) { size = read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state); if (size < 0) /* Error/EOF */ - exit(0); + exit(EXIT_SUCCESS); position = 0; /* if Ctrl-C, size == 0 and loop will repeat */ } @@ -4830,7 +4754,7 @@ static int filechar(struct ioarg *ap) return c; } #endif - i = safe_read(ap->afile, &c, sizeof(c)); + i = nonblock_safe_read(ap->afile, &c, sizeof(c)); return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0); } @@ -4841,7 +4765,7 @@ static int herechar(struct ioarg *ap) { char c; - if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) { + if (nonblock_safe_read(ap->afile, &c, sizeof(c)) != sizeof(c)) { close(ap->afile); c = '\0'; } @@ -4906,7 +4830,7 @@ static int linechar(struct ioarg *ap) } /* - * remap fd into Shell's fd space + * Remap fd into shell's fd space */ static int remap(int fd) { @@ -4968,7 +4892,7 @@ static void markhere(char *s, struct ioword *iop) DBGPRINTF7(("MARKHERE: enter, s=%p\n", s)); - h = (struct here *) space(sizeof(struct here)); + h = get_space(sizeof(struct here)); if (h == NULL) return; @@ -5143,7 +5067,7 @@ static void freehere(int area) DBGPRINTF6(("FREEHERE: enter, area=%d\n", area)); hl = NULL; - for (h = acthere; h != NULL; h = h->h_next) + for (h = acthere; h != NULL; h = h->h_next) { if (getarea((char *) h) >= area) { if (h->h_iop->io_name != NULL) unlink(h->h_iop->io_name); @@ -5151,8 +5075,10 @@ static void freehere(int area) acthere = h->h_next; else hl->h_next = h->h_next; - } else + } else { hl = h; + } + } } @@ -5290,7 +5216,7 @@ int msh_main(int argc, char **argv) /* Shell is non-interactive, activate printf-based debug */ #ifdef MSHDEBUG - mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0'); + mshdbg = mshdbg_var->value[0] - '0'; if (mshdbg < 0) mshdbg = 0; #endif @@ -5298,7 +5224,7 @@ int msh_main(int argc, char **argv) name = *++argv; if (newfile(name)) - exit(1); /* Exit on error */ + exit(EXIT_FAILURE); /* Exit on error */ } }