diff options
-rw-r--r-- | shell/ash.c | 1244 |
1 files changed, 597 insertions, 647 deletions
diff --git a/shell/ash.c b/shell/ash.c index 3107181a6..7ffecf43d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -65,36 +65,6 @@ #error "Do not even bother, ash will not run on uClinux" #endif -#if DEBUG -#define TRACE(param) trace param -#define TRACEV(param) tracev param -#else -#define TRACE(param) -#define TRACEV(param) -#endif - -#ifdef __GLIBC__ -/* glibc sucks */ -static int *dash_errno; -#undef errno -#define errno (*dash_errno) -#endif - - -#if ENABLE_ASH_ALIAS -#define ALIASINUSE 1 -#define ALIASDEAD 2 -struct alias { - struct alias *next; - char *name; - char *val; - int flag; -}; -static int aliascmd(int, char **); -static int unaliascmd(int, char **); -static void printalias(const struct alias *); -#endif - /* ============ Shell options */ @@ -148,6 +118,13 @@ static char optlist[NOPTS]; /* ============ Misc data */ +#ifdef __GLIBC__ +/* glibc sucks */ +static int *dash_errno; +#undef errno +#define errno (*dash_errno) +#endif + static char nullstr[1]; /* zero length string */ static const char homestr[] = "HOME"; static const char snlfmt[] = "%s\n"; @@ -256,14 +233,16 @@ raise_interrupt(void) } #if ENABLE_ASH_OPTIMIZE_FOR_SIZE -static void int_on(void) +static void +int_on(void) { if (--suppressint == 0 && intpending) { raise_interrupt(); } } #define INT_ON int_on() -static void force_int_on(void) +static void +force_int_on(void) { suppressint = 0; if (intpending) @@ -387,6 +366,485 @@ out2str(const char *p) } +/* ============ Parsing structures */ +#define NCMD 0 +#define NPIPE 1 +#define NREDIR 2 +#define NBACKGND 3 +#define NSUBSHELL 4 +#define NAND 5 +#define NOR 6 +#define NSEMI 7 +#define NIF 8 +#define NWHILE 9 +#define NUNTIL 10 +#define NFOR 11 +#define NCASE 12 +#define NCLIST 13 +#define NDEFUN 14 +#define NARG 15 +#define NTO 16 +#define NCLOBBER 17 +#define NFROM 18 +#define NFROMTO 19 +#define NAPPEND 20 +#define NTOFD 21 +#define NFROMFD 22 +#define NHERE 23 +#define NXHERE 24 +#define NNOT 25 + +union node; + +struct ncmd { + int type; + union node *assign; + union node *args; + union node *redirect; +}; + +struct npipe { + int type; + int backgnd; + struct nodelist *cmdlist; +}; + +struct nredir { + int type; + union node *n; + union node *redirect; +}; + +struct nbinary { + int type; + union node *ch1; + union node *ch2; +}; + +struct nif { + int type; + union node *test; + union node *ifpart; + union node *elsepart; +}; + +struct nfor { + int type; + union node *args; + union node *body; + char *var; +}; + +struct ncase { + int type; + union node *expr; + union node *cases; +}; + +struct nclist { + int type; + union node *next; + union node *pattern; + union node *body; +}; + +struct narg { + int type; + union node *next; + char *text; + struct nodelist *backquote; +}; + +struct nfile { + int type; + union node *next; + int fd; + union node *fname; + char *expfname; +}; + +struct ndup { + int type; + union node *next; + int fd; + int dupfd; + union node *vname; +}; + +struct nhere { + int type; + union node *next; + int fd; + union node *doc; +}; + +struct nnot { + int type; + union node *com; +}; + +union node { + int type; + struct ncmd ncmd; + struct npipe npipe; + struct nredir nredir; + struct nbinary nbinary; + struct nif nif; + struct nfor nfor; + struct ncase ncase; + struct nclist nclist; + struct narg narg; + struct nfile nfile; + struct ndup ndup; + struct nhere nhere; + struct nnot nnot; +}; + +struct nodelist { + struct nodelist *next; + union node *n; +}; + +struct funcnode { + int count; + union node n; +}; + + +/* ============ Debugging output */ + +#if DEBUG + +static FILE *tracefile; + +static void +trace_printf(const char *fmt, ...) +{ + va_list va; + + if (debug != 1) + return; + va_start(va, fmt); + vfprintf(tracefile, fmt, va); + va_end(va); +} + +static void +trace_vprintf(const char *fmt, va_list va) +{ + if (debug != 1) + return; + vfprintf(tracefile, fmt, va); +} + +static void +trace_puts(const char *s) +{ + if (debug != 1) + return; + fputs(s, tracefile); +} + +static void +trace_puts_quoted(char *s) +{ + char *p; + char c; + + if (debug != 1) + return; + putc('"', tracefile); + for (p = s; *p; p++) { + switch (*p) { + case '\n': c = 'n'; goto backslash; + case '\t': c = 't'; goto backslash; + case '\r': c = 'r'; goto backslash; + case '"': c = '"'; goto backslash; + case '\\': c = '\\'; goto backslash; + case CTLESC: c = 'e'; goto backslash; + case CTLVAR: c = 'v'; goto backslash; + case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; + case CTLBACKQ: c = 'q'; goto backslash; + case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; + backslash: + putc('\\', tracefile); + putc(c, tracefile); + break; + default: + if (*p >= ' ' && *p <= '~') + putc(*p, tracefile); + else { + putc('\\', tracefile); + putc(*p >> 6 & 03, tracefile); + putc(*p >> 3 & 07, tracefile); + putc(*p & 07, tracefile); + } + break; + } + } + putc('"', tracefile); +} + +static void +trace_puts_args(char **ap) +{ + if (debug != 1) + return; + if (!*ap) + return; + while (1) { + trace_puts_quoted(*ap); + if (!*++ap) { + putc('\n', tracefile); + break; + } + putc(' ', tracefile); + } +} + +static void +opentrace(void) +{ + char s[100]; +#ifdef O_APPEND + int flags; +#endif + + if (debug != 1) { + if (tracefile) + fflush(tracefile); + /* leave open because libedit might be using it */ + return; + } + strcpy(s, "./trace"); + if (tracefile) { + if (!freopen(s, "a", tracefile)) { + fprintf(stderr, "Can't re-open %s\n", s); + debug = 0; + return; + } + } else { + tracefile = fopen(s, "a"); + if (tracefile == NULL) { + fprintf(stderr, "Can't open %s\n", s); + debug = 0; + return; + } + } +#ifdef O_APPEND + flags = fcntl(fileno(tracefile), F_GETFL, 0); + if (flags >= 0) + fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); +#endif + setlinebuf(tracefile); + fputs("\nTracing started.\n", tracefile); +} + +static void +indent(int amount, char *pfx, FILE *fp) +{ + int i; + + for (i = 0; i < amount; i++) { + if (pfx && i == amount - 1) + fputs(pfx, fp); + putc('\t', fp); + } +} + +/* little circular references here... */ +static void shtree(union node *n, int ind, char *pfx, FILE *fp); + +static void +sharg(union node *arg, FILE *fp) +{ + char *p; + struct nodelist *bqlist; + int subtype; + + if (arg->type != NARG) { + out1fmt("<node type %d>\n", arg->type); + abort(); + } + bqlist = arg->narg.backquote; + for (p = arg->narg.text; *p; p++) { + switch (*p) { + case CTLESC: + putc(*++p, fp); + break; + case CTLVAR: + putc('$', fp); + putc('{', fp); + subtype = *++p; + if (subtype == VSLENGTH) + putc('#', fp); + + while (*p != '=') + putc(*p++, fp); + + if (subtype & VSNUL) + putc(':', fp); + + switch (subtype & VSTYPE) { + case VSNORMAL: + putc('}', fp); + break; + case VSMINUS: + putc('-', fp); + break; + case VSPLUS: + putc('+', fp); + break; + case VSQUESTION: + putc('?', fp); + break; + case VSASSIGN: + putc('=', fp); + break; + case VSTRIMLEFT: + putc('#', fp); + break; + case VSTRIMLEFTMAX: + putc('#', fp); + putc('#', fp); + break; + case VSTRIMRIGHT: + putc('%', fp); + break; + case VSTRIMRIGHTMAX: + putc('%', fp); + putc('%', fp); + break; + case VSLENGTH: + break; + default: + out1fmt("<subtype %d>", subtype); + } + break; + case CTLENDVAR: + putc('}', fp); + break; + case CTLBACKQ: + case CTLBACKQ|CTLQUOTE: + putc('$', fp); + putc('(', fp); + shtree(bqlist->n, -1, NULL, fp); + putc(')', fp); + break; + default: + putc(*p, fp); + break; + } + } +} + +static void +shcmd(union node *cmd, FILE *fp) +{ + union node *np; + int first; + const char *s; + int dftfd; + + first = 1; + for (np = cmd->ncmd.args; np; np = np->narg.next) { + if (! first) + putchar(' '); + sharg(np, fp); + first = 0; + } + for (np = cmd->ncmd.redirect; np; np = np->nfile.next) { + if (! first) + putchar(' '); + switch (np->nfile.type) { + case NTO: s = ">"; dftfd = 1; break; + case NCLOBBER: s = ">|"; dftfd = 1; break; + case NAPPEND: s = ">>"; dftfd = 1; break; + case NTOFD: s = ">&"; dftfd = 1; break; + case NFROM: s = "<"; dftfd = 0; break; + case NFROMFD: s = "<&"; dftfd = 0; break; + case NFROMTO: s = "<>"; dftfd = 0; break; + default: s = "*error*"; dftfd = 0; break; + } + if (np->nfile.fd != dftfd) + fprintf(fp, "%d", np->nfile.fd); + fputs(s, fp); + if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { + fprintf(fp, "%d", np->ndup.dupfd); + } else { + sharg(np->nfile.fname, fp); + } + first = 0; + } +} + +static void +shtree(union node *n, int ind, char *pfx, FILE *fp) +{ + struct nodelist *lp; + const char *s; + + if (n == NULL) + return; + + indent(ind, pfx, fp); + switch (n->type) { + case NSEMI: + s = "; "; + goto binop; + case NAND: + s = " && "; + goto binop; + case NOR: + s = " || "; + binop: + shtree(n->nbinary.ch1, ind, NULL, fp); + /* if (ind < 0) */ + fputs(s, fp); + shtree(n->nbinary.ch2, ind, NULL, fp); + break; + case NCMD: + shcmd(n, fp); + if (ind >= 0) + putc('\n', fp); + break; + case NPIPE: + for (lp = n->npipe.cmdlist; lp; lp = lp->next) { + shcmd(lp->n, fp); + if (lp->next) + fputs(" | ", fp); + } + if (n->npipe.backgnd) + fputs(" &", fp); + if (ind >= 0) + putc('\n', fp); + break; + default: + fprintf(fp, "<node type %d>", n->type); + if (ind >= 0) + putc('\n', fp); + break; + } +} + +static void +showtree(union node *n) +{ + trace_puts("showtree called\n"); + shtree(n, 1, NULL, stdout); +} + +#define TRACE(param) trace_printf param +#define TRACEV(param) trace_vprintf param + +#else + +#define TRACE(param) +#define TRACEV(param) + +#endif /* DEBUG */ + + /* ============ Parser data * * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up. @@ -397,6 +855,15 @@ struct strlist { char *text; }; +#if ENABLE_ASH_ALIAS +#define ALIASINUSE 1 +#define ALIASDEAD 2 +struct alias; +static int aliascmd(int, char **); +static int unaliascmd(int, char **); +static void printalias(const struct alias *); +#endif + struct strpush { struct strpush *prev; /* preceding string on stack */ char *prevstring; @@ -1882,7 +2349,6 @@ struct arglist { #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ -union node; static void expandarg(union node *, struct arglist *, int); #define rmescapes(p) _rmescapes((p), 0) static char *_rmescapes(char *, int); @@ -1903,152 +2369,6 @@ struct backcmd { /* result of evalbackcmd */ struct job *jp; /* job structure for command */ }; -/* - * This file was generated by the mknodes program. - */ - -#define NCMD 0 -#define NPIPE 1 -#define NREDIR 2 -#define NBACKGND 3 -#define NSUBSHELL 4 -#define NAND 5 -#define NOR 6 -#define NSEMI 7 -#define NIF 8 -#define NWHILE 9 -#define NUNTIL 10 -#define NFOR 11 -#define NCASE 12 -#define NCLIST 13 -#define NDEFUN 14 -#define NARG 15 -#define NTO 16 -#define NCLOBBER 17 -#define NFROM 18 -#define NFROMTO 19 -#define NAPPEND 20 -#define NTOFD 21 -#define NFROMFD 22 -#define NHERE 23 -#define NXHERE 24 -#define NNOT 25 - - -struct ncmd { - int type; - union node *assign; - union node *args; - union node *redirect; -}; - -struct npipe { - int type; - int backgnd; - struct nodelist *cmdlist; -}; - -struct nredir { - int type; - union node *n; - union node *redirect; -}; - -struct nbinary { - int type; - union node *ch1; - union node *ch2; -}; - -struct nif { - int type; - union node *test; - union node *ifpart; - union node *elsepart; -}; - -struct nfor { - int type; - union node *args; - union node *body; - char *var; -}; - -struct ncase { - int type; - union node *expr; - union node *cases; -}; - -struct nclist { - int type; - union node *next; - union node *pattern; - union node *body; -}; - -struct narg { - int type; - union node *next; - char *text; - struct nodelist *backquote; -}; - -struct nfile { - int type; - union node *next; - int fd; - union node *fname; - char *expfname; -}; - -struct ndup { - int type; - union node *next; - int fd; - int dupfd; - union node *vname; -}; - -struct nhere { - int type; - union node *next; - int fd; - union node *doc; -}; - -struct nnot { - int type; - union node *com; -}; - -union node { - int type; - struct ncmd ncmd; - struct npipe npipe; - struct nredir nredir; - struct nbinary nbinary; - struct nif nif; - struct nfor nfor; - struct ncase ncase; - struct nclist nclist; - struct narg narg; - struct nfile nfile; - struct ndup ndup; - struct nhere nhere; - struct nnot nnot; -}; - -struct nodelist { - struct nodelist *next; - union node *n; -}; - -struct funcnode { - int count; - union node n; -}; - static void freefunc(struct funcnode *); /* parser.h */ @@ -2736,7 +3056,7 @@ static int funcnest; /* depth of function calls */ */ #if JOBS -static int bgcmd(int, char **); +static int fg_bgcmd(int, char **); #endif static int breakcmd(int, char **); static int cdcmd(int, char **); @@ -2755,9 +3075,6 @@ static int execcmd(int, char **); static int exitcmd(int, char **); static int exportcmd(int, char **); static int falsecmd(int, char **); -#if JOBS -static int fgcmd(int, char **); -#endif #if ENABLE_ASH_GETOPTS static int getoptscmd(int, char **); #endif @@ -2840,7 +3157,7 @@ static const struct builtincmd builtincmd[] = { { BUILTIN_REG_ASSG "alias", aliascmd }, #endif #if JOBS - { BUILTIN_REGULAR "bg", bgcmd }, + { BUILTIN_REGULAR "bg", fg_bgcmd }, #endif { BUILTIN_SPEC_REG "break", breakcmd }, { BUILTIN_REGULAR "cd", cdcmd }, @@ -2858,7 +3175,7 @@ static const struct builtincmd builtincmd[] = { { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, { BUILTIN_REGULAR "false", falsecmd }, #if JOBS - { BUILTIN_REGULAR "fg", fgcmd }, + { BUILTIN_REGULAR "fg", fg_bgcmd }, #endif #if ENABLE_ASH_GETOPTS { BUILTIN_REGULAR "getopts", getoptscmd }, @@ -3033,25 +3350,12 @@ static void setjobctl(int); static void showjobs(FILE *, int); #endif -/* main.h */ +/* main.h */ static void readcmdfile(char *); -/* mystring.h */ - - -#define DOLATSTRLEN 4 - -static char *prefix(const char *, const char *); -static int number(const char *); -static int is_number(const char *); -static char *single_quote(const char *); - -#define equal(s1, s2) (strcmp(s1, s2) == 0) -#define scopy(s1, s2) ((void)strcpy(s2, s1)) - /* options.h */ static char *minusc; /* argument to -c option */ @@ -3076,22 +3380,8 @@ static void clearredir(int); static int copyfd(int, int); static int redirectsafe(union node *, int); -/* show.h */ - - -#if DEBUG -static void showtree(union node *); -static void trace(const char *, ...); -static void tracev(const char *, va_list); -static void trargs(char **); -static void trputc(int); -static void trputs(const char *); -static void opentrace(void); -#endif - /* trap.h */ - static void clear_traps(void); static void setsignal(int); static void ignoresig(int); @@ -3137,11 +3427,67 @@ static int is_safe_applet(char *name) #if ENABLE_ASH_ALIAS +struct alias { + struct alias *next; + char *name; + char *val; + int flag; +}; + static struct alias *atab[ATABSIZE]; -static void setalias(const char *, const char *); -static struct alias *freealias(struct alias *); -static struct alias **__lookupalias(const char *); +static struct alias ** +__lookupalias(const char *name) { + unsigned int hashval; + struct alias **app; + const char *p; + unsigned int ch; + + p = name; + + ch = (unsigned char)*p; + hashval = ch << 4; + while (ch) { + hashval += ch; + ch = (unsigned char)*++p; + } + app = &atab[hashval % ATABSIZE]; + + for (; *app; app = &(*app)->next) { + if (strcmp(name, (*app)->name) == 0) { + break; + } + } + + return app; +} + +static struct alias * +lookupalias(const char *name, int check) +{ + struct alias *ap = *__lookupalias(name); + + if (check && ap && (ap->flag & ALIASINUSE)) + return NULL; + return ap; +} + +static struct alias * +freealias(struct alias *ap) +{ + struct alias *next; + + if (ap->flag & ALIASINUSE) { + ap->flag |= ALIASDEAD; + return ap; + } + + next = ap->next; + free(ap->name); + free(ap->val); + free(ap); + return next; +} static void setalias(const char *name, const char *val) @@ -3205,16 +3551,6 @@ rmaliases(void) INT_ON; } -static struct alias * -lookupalias(const char *name, int check) -{ - struct alias *ap = *__lookupalias(name); - - if (check && ap && (ap->flag & ALIASINUSE)) - return NULL; - return ap; -} - /* * TODO - sort output */ @@ -3273,54 +3609,11 @@ unaliascmd(int argc, char **argv) return i; } -static struct alias * -freealias(struct alias *ap) -{ - struct alias *next; - - if (ap->flag & ALIASINUSE) { - ap->flag |= ALIASDEAD; - return ap; - } - - next = ap->next; - free(ap->name); - free(ap->val); - free(ap); - return next; -} - static void printalias(const struct alias *ap) { out1fmt("%s=%s\n", ap->name, single_quote(ap->val)); } - -static struct alias ** -__lookupalias(const char *name) { - unsigned int hashval; - struct alias **app; - const char *p; - unsigned int ch; - - p = name; - - ch = (unsigned char)*p; - hashval = ch << 4; - while (ch) { - hashval += ch; - ch = (unsigned char)*++p; - } - app = &atab[hashval % ATABSIZE]; - - for (; *app; app = &(*app)->next) { - if (equal(name, (*app)->name)) { - break; - } - } - - return app; -} #endif /* ASH_ALIAS */ /* eval.c */ @@ -3602,7 +3895,7 @@ evalsubshell(union node *n, int flags) flags |= EV_EXIT; if (backgnd) flags &=~ EV_TESTED; -nofork: + nofork: redirect(n->nredir.redirect, 0); evaltreenr(n->nredir.n, flags); /* never returns */ @@ -4789,7 +5082,7 @@ cmdlookup(const char *name, int add) hashval &= 0x7FFF; pp = &cmdtable[hashval % CMDTABLESIZE]; for (cmdp = *pp; cmdp; cmdp = cmdp->next) { - if (equal(cmdp->cmdname, name)) + if (strcmp(cmdp->cmdname, name) == 0) break; pp = &cmdp->next; } @@ -5292,7 +5585,7 @@ argstr(char *p, int flag) /* "$@" syntax adherence hack */ if ( !inquotes && - !memcmp(p, dolatstr, DOLATSTRLEN) && + !memcmp(p, dolatstr, 4) && (p[4] == CTLQUOTEMARK || ( p[4] == CTLENDVAR && p[5] == CTLQUOTEMARK @@ -6274,7 +6567,7 @@ expmeta(char *enddir, char *name) continue; if (pmatch(start, dp->d_name)) { if (atend) { - scopy(dp->d_name, enddir); + strcpy(enddir, dp->d_name); addfname(expdir); } else { for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) @@ -7186,7 +7479,7 @@ jobno(const struct job *jp) #if JOBS static int -fgcmd(int argc, char **argv) +fg_bgcmd(int argc, char **argv) { struct job *jp; FILE *out; @@ -7210,9 +7503,6 @@ fgcmd(int argc, char **argv) return retval; } -static int bgcmd(int, char **) __attribute__((__alias__("fgcmd"))); - - static int restartjob(struct job *jp, int mode) { @@ -7313,8 +7603,8 @@ showjob(FILE *out, struct job *jp, int mode) psend = ps + jp->nprocs; if (jp->state == JOBRUNNING) { - scopy("Running", s + col); - col += strlen("Running"); + strcpy(s + col, "Running"); + col += sizeof("Running") - 1; } else { int status = psend[-1].status; #if JOBS @@ -7359,19 +7649,20 @@ jobscmd(int argc, char **argv) FILE *out; mode = 0; - while ((m = nextopt("lp"))) + while ((m = nextopt("lp"))) { if (m == 'l') mode = SHOW_PID; else mode = SHOW_PGID; + } out = stdout; argv = argptr; - if (*argv) + if (*argv) { do showjob(out, getjob(*argv,0), mode); while (*++argv); - else + } else showjobs(out, mode); return 0; @@ -7515,7 +7806,8 @@ getjob(const char *name, int getctl) currentjob: err_msg = "No current job"; goto check; - } else if (c == '-') { + } + if (c == '-') { if (jp) jp = jp->prev_job; err_msg = "No previous job"; @@ -7571,7 +7863,6 @@ getjob(const char *name, int getctl) * Return a new job structure. * Called with interrupts off. */ - static struct job * makejob(union node *node, int nprocs) { @@ -7720,7 +8011,7 @@ static void forkchild(struct job *jp, union node *n, int mode) static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) { - TRACE(("In parent shell: child = %d\n", pid)); + TRACE(("In parent shell: child = %d\n", pid)); if (!jp) { while (jobless && dowait(DOWAIT_NORMAL, 0) > 0); jobless++; @@ -7735,7 +8026,7 @@ static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) else pgrp = jp->ps[0].pid; /* This can fail because we are doing it in the child also */ - (void)setpgid(pid, pgrp); + setpgid(pid, pgrp); } #endif if (mode == FORK_BG) { @@ -7854,7 +8145,8 @@ waitforjob(struct job *jp) * (as opposed to running a builtin command or just typing return), * and the jobs command may give out of date information. */ -static int waitproc(int block, int *status) +static int +waitproc(int block, int *status) { int flags = 0; @@ -8147,10 +8439,9 @@ cmdtxt(union node *n) s[0] = n->ndup.dupfd + '0'; p = s; goto dotail2; - } else { - n = n->nfile.fname; - goto donode; } + n = n->nfile.fname; + goto donode; } } @@ -8178,6 +8469,7 @@ cmdputs(const char *s) "", "}", "-", "+", "?", "=", "%", "%%", "#", "##" }; + nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); p = s; while ((c = *p++) != 0) { @@ -8192,11 +8484,10 @@ cmdputs(const char *s) str = "${#"; else str = "${"; - if (!(subtype & VSQUOTE) != !(quoted & 1)) { - quoted ^= 1; - c = '"'; - } else + if (!(subtype & VSQUOTE) == !(quoted & 1)) goto dostr; + quoted ^= 1; + c = '"'; break; case CTLENDVAR: str = "\"}" + !(quoted & 1); @@ -8650,7 +8941,7 @@ minus_o(char *name, int val) if (name) { for (i = 0; i < NOPTS; i++) { - if (equal(name, optnames(i))) { + if (strcmp(name, optnames(i)) == 0) { optlist[i] = val; return; } @@ -8859,13 +9150,15 @@ setcmd(int argc, char **argv) #if ENABLE_LOCALE_SUPPORT -static void change_lc_all(const char *value) +static void +change_lc_all(const char *value) { if (value && *value != '\0') setlocale(LC_ALL, value); } -static void change_lc_ctype(const char *value) +static void +change_lc_ctype(const char *value) { if (value && *value != '\0') setlocale(LC_CTYPE, value); @@ -8874,7 +9167,8 @@ static void change_lc_ctype(const char *value) #if ENABLE_ASH_RANDOM_SUPPORT /* Roughly copied from bash.. */ -static void change_random(const char *value) +static void +change_random(const char *value) { if (value == NULL) { /* "get", generate */ @@ -11036,349 +11330,6 @@ redirectsafe(union node *redir, int flags) return err; } -/* show.c */ - -#if DEBUG -static void shtree(union node *, int, char *, FILE*); -static void shcmd(union node *, FILE *); -static void sharg(union node *, FILE *); -static void indent(int, char *, FILE *); -static void trstring(char *); - -static void -showtree(union node *n) -{ - trputs("showtree called\n"); - shtree(n, 1, NULL, stdout); -} - -static void -shtree(union node *n, int ind, char *pfx, FILE *fp) -{ - struct nodelist *lp; - const char *s; - - if (n == NULL) - return; - - indent(ind, pfx, fp); - switch (n->type) { - case NSEMI: - s = "; "; - goto binop; - case NAND: - s = " && "; - goto binop; - case NOR: - s = " || "; - binop: - shtree(n->nbinary.ch1, ind, NULL, fp); - /* if (ind < 0) */ - fputs(s, fp); - shtree(n->nbinary.ch2, ind, NULL, fp); - break; - case NCMD: - shcmd(n, fp); - if (ind >= 0) - putc('\n', fp); - break; - case NPIPE: - for (lp = n->npipe.cmdlist; lp; lp = lp->next) { - shcmd(lp->n, fp); - if (lp->next) - fputs(" | ", fp); - } - if (n->npipe.backgnd) - fputs(" &", fp); - if (ind >= 0) - putc('\n', fp); - break; - default: - fprintf(fp, "<node type %d>", n->type); - if (ind >= 0) - putc('\n', fp); - break; - } -} - -static void -shcmd(union node *cmd, FILE *fp) -{ - union node *np; - int first; - const char *s; - int dftfd; - - first = 1; - for (np = cmd->ncmd.args; np; np = np->narg.next) { - if (! first) - putchar(' '); - sharg(np, fp); - first = 0; - } - for (np = cmd->ncmd.redirect; np; np = np->nfile.next) { - if (! first) - putchar(' '); - switch (np->nfile.type) { - case NTO: s = ">"; dftfd = 1; break; - case NCLOBBER: s = ">|"; dftfd = 1; break; - case NAPPEND: s = ">>"; dftfd = 1; break; - case NTOFD: s = ">&"; dftfd = 1; break; - case NFROM: s = "<"; dftfd = 0; break; - case NFROMFD: s = "<&"; dftfd = 0; break; - case NFROMTO: s = "<>"; dftfd = 0; break; - default: s = "*error*"; dftfd = 0; break; - } - if (np->nfile.fd != dftfd) - fprintf(fp, "%d", np->nfile.fd); - fputs(s, fp); - if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { - fprintf(fp, "%d", np->ndup.dupfd); - } else { - sharg(np->nfile.fname, fp); - } - first = 0; - } -} - -static void -sharg(union node *arg, FILE *fp) -{ - char *p; - struct nodelist *bqlist; - int subtype; - - if (arg->type != NARG) { - out1fmt("<node type %d>\n", arg->type); - abort(); - } - bqlist = arg->narg.backquote; - for (p = arg->narg.text; *p; p++) { - switch (*p) { - case CTLESC: - putc(*++p, fp); - break; - case CTLVAR: - putc('$', fp); - putc('{', fp); - subtype = *++p; - if (subtype == VSLENGTH) - putc('#', fp); - - while (*p != '=') - putc(*p++, fp); - - if (subtype & VSNUL) - putc(':', fp); - - switch (subtype & VSTYPE) { - case VSNORMAL: - putc('}', fp); - break; - case VSMINUS: - putc('-', fp); - break; - case VSPLUS: - putc('+', fp); - break; - case VSQUESTION: - putc('?', fp); - break; - case VSASSIGN: - putc('=', fp); - break; - case VSTRIMLEFT: - putc('#', fp); - break; - case VSTRIMLEFTMAX: - putc('#', fp); - putc('#', fp); - break; - case VSTRIMRIGHT: - putc('%', fp); - break; - case VSTRIMRIGHTMAX: - putc('%', fp); - putc('%', fp); - break; - case VSLENGTH: - break; - default: - out1fmt("<subtype %d>", subtype); - } - break; - case CTLENDVAR: - putc('}', fp); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - putc('$', fp); - putc('(', fp); - shtree(bqlist->n, -1, NULL, fp); - putc(')', fp); - break; - default: - putc(*p, fp); - break; - } - } -} - - -static void -indent(int amount, char *pfx, FILE *fp) -{ - int i; - - for (i = 0; i < amount; i++) { - if (pfx && i == amount - 1) - fputs(pfx, fp); - putc('\t', fp); - } -} - - -/* - * Debugging stuff. - */ - - -static FILE *tracefile; - - -static void -trputc(int c) -{ - if (debug != 1) - return; - putc(c, tracefile); -} - -static void -trace(const char *fmt, ...) -{ - va_list va; - - if (debug != 1) - return; - va_start(va, fmt); - (void) vfprintf(tracefile, fmt, va); - va_end(va); -} - -static void -tracev(const char *fmt, va_list va) -{ - if (debug != 1) - return; - (void) vfprintf(tracefile, fmt, va); -} - - -static void -trputs(const char *s) -{ - if (debug != 1) - return; - fputs(s, tracefile); -} - - -static void -trstring(char *s) -{ - char *p; - char c; - - if (debug != 1) - return; - putc('"', tracefile); - for (p = s; *p; p++) { - switch (*p) { - case '\n': c = 'n'; goto backslash; - case '\t': c = 't'; goto backslash; - case '\r': c = 'r'; goto backslash; - case '"': c = '"'; goto backslash; - case '\\': c = '\\'; goto backslash; - case CTLESC: c = 'e'; goto backslash; - case CTLVAR: c = 'v'; goto backslash; - case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; - case CTLBACKQ: c = 'q'; goto backslash; - case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; - backslash: - putc('\\', tracefile); - putc(c, tracefile); - break; - default: - if (*p >= ' ' && *p <= '~') - putc(*p, tracefile); - else { - putc('\\', tracefile); - putc(*p >> 6 & 03, tracefile); - putc(*p >> 3 & 07, tracefile); - putc(*p & 07, tracefile); - } - break; - } - } - putc('"', tracefile); -} - - -static void -trargs(char **ap) -{ - if (debug != 1) - return; - while (*ap) { - trstring(*ap++); - if (*ap) - putc(' ', tracefile); - else - putc('\n', tracefile); - } -} - - -static void -opentrace(void) -{ - char s[100]; -#ifdef O_APPEND - int flags; -#endif - - if (debug != 1) { - if (tracefile) - fflush(tracefile); - /* leave open because libedit might be using it */ - return; - } - scopy("./trace", s); - if (tracefile) { - if (!freopen(s, "a", tracefile)) { - fprintf(stderr, "Can't re-open %s\n", s); - debug = 0; - return; - } - } else { - tracefile = fopen(s, "a"); - if (tracefile == NULL) { - fprintf(stderr, "Can't open %s\n", s); - debug = 0; - return; - } - } -#ifdef O_APPEND - flags = fcntl(fileno(tracefile), F_GETFL, 0); - if (flags >= 0) - fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); -#endif - setlinebuf(tracefile); - fputs("\nTracing started.\n", tracefile); -} -#endif /* DEBUG */ - /* trap.c */ @@ -13215,18 +13166,17 @@ int ash_main(int argc, char **argv) FORCE_INT_ON; /* enable interrupts */ if (s == 1) goto state1; - else if (s == 2) + if (s == 2) goto state2; - else if (s == 3) + if (s == 3) goto state3; - else - goto state4; + goto state4; } exception_handler = &jmploc; #if DEBUG opentrace(); - trputs("Shell args: "); - trargs(argv); + trace_puts("Shell args: "); + trace_puts_args(argv); #endif rootpid = getpid(); |