diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-23 01:05:15 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-23 01:05:15 +0000 |
| commit | a6704933dde751bfccf85b632361034367ad6ec5 (patch) | |
| tree | d9ee0c6d801217d342a21052fa001d0720a5e466 /shell | |
| parent | 5c67e3ed90f559b61b02aa013ad4dd7d57fce772 (diff) | |
| download | busybox-w32-a6704933dde751bfccf85b632361034367ad6ec5.tar.gz busybox-w32-a6704933dde751bfccf85b632361034367ad6ec5.tar.bz2 busybox-w32-a6704933dde751bfccf85b632361034367ad6ec5.zip | |
ash: cleanup part 6
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 577 |
1 files changed, 283 insertions, 294 deletions
diff --git a/shell/ash.c b/shell/ash.c index 54fc8ea48..69b8ab0b9 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -3664,7 +3664,6 @@ printalias(const struct alias *ap) | |||
| 3664 | #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ | 3664 | #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ |
| 3665 | #define EV_BACKCMD 04 /* command executing within back quotes */ | 3665 | #define EV_BACKCMD 04 /* command executing within back quotes */ |
| 3666 | 3666 | ||
| 3667 | |||
| 3668 | static void evalloop(union node *, int); | 3667 | static void evalloop(union node *, int); |
| 3669 | static void evalfor(union node *, int); | 3668 | static void evalfor(union node *, int); |
| 3670 | static void evalcase(union node *, int); | 3669 | static void evalcase(union node *, int); |
| @@ -3677,13 +3676,11 @@ static int evalfun(struct funcnode *, int, char **, int); | |||
| 3677 | static void prehash(union node *); | 3676 | static void prehash(union node *); |
| 3678 | static int bltincmd(int, char **); | 3677 | static int bltincmd(int, char **); |
| 3679 | 3678 | ||
| 3680 | |||
| 3681 | static const struct builtincmd bltin = { | 3679 | static const struct builtincmd bltin = { |
| 3682 | "\0\0", bltincmd | 3680 | "\0\0", bltincmd |
| 3683 | }; | 3681 | }; |
| 3684 | 3682 | ||
| 3685 | 3683 | ||
| 3686 | |||
| 3687 | /* | 3684 | /* |
| 3688 | * Evaluate a parse tree. The value is left in the global variable | 3685 | * Evaluate a parse tree. The value is left in the global variable |
| 3689 | * exitstatus. | 3686 | * exitstatus. |
| @@ -7277,13 +7274,6 @@ static struct job *curjob; | |||
| 7277 | /* number of presumed living untracked jobs */ | 7274 | /* number of presumed living untracked jobs */ |
| 7278 | static int jobless; | 7275 | static int jobless; |
| 7279 | 7276 | ||
| 7280 | #if JOBS | ||
| 7281 | static char *commandtext(union node *); | ||
| 7282 | static void cmdlist(union node *, int); | ||
| 7283 | static void cmdtxt(union node *); | ||
| 7284 | static void cmdputs(const char *); | ||
| 7285 | #endif | ||
| 7286 | |||
| 7287 | static void | 7277 | static void |
| 7288 | set_curjob(struct job *jp, unsigned mode) | 7278 | set_curjob(struct job *jp, unsigned mode) |
| 7289 | { | 7279 | { |
| @@ -7887,10 +7877,8 @@ showjob(FILE *out, struct job *jp, int mode) | |||
| 7887 | col += sizeof("Running") - 1; | 7877 | col += sizeof("Running") - 1; |
| 7888 | } else { | 7878 | } else { |
| 7889 | int status = psend[-1].status; | 7879 | int status = psend[-1].status; |
| 7890 | #if JOBS | ||
| 7891 | if (jp->state == JOBSTOPPED) | 7880 | if (jp->state == JOBSTOPPED) |
| 7892 | status = jp->stopstatus; | 7881 | status = jp->stopstatus; |
| 7893 | #endif | ||
| 7894 | col += sprint_status(s + col, status, 0); | 7882 | col += sprint_status(s + col, status, 0); |
| 7895 | } | 7883 | } |
| 7896 | 7884 | ||
| @@ -8143,6 +8131,288 @@ makejob(union node *node, int nprocs) | |||
| 8143 | return jp; | 8131 | return jp; |
| 8144 | } | 8132 | } |
| 8145 | 8133 | ||
| 8134 | #if JOBS | ||
| 8135 | /* | ||
| 8136 | * Return a string identifying a command (to be printed by the | ||
| 8137 | * jobs command). | ||
| 8138 | */ | ||
| 8139 | static char *cmdnextc; | ||
| 8140 | |||
| 8141 | static void | ||
| 8142 | cmdputs(const char *s) | ||
| 8143 | { | ||
| 8144 | const char *p, *str; | ||
| 8145 | char c, cc[2] = " "; | ||
| 8146 | char *nextc; | ||
| 8147 | int subtype = 0; | ||
| 8148 | int quoted = 0; | ||
| 8149 | static const char vstype[VSTYPE + 1][4] = { | ||
| 8150 | "", "}", "-", "+", "?", "=", | ||
| 8151 | "%", "%%", "#", "##" | ||
| 8152 | }; | ||
| 8153 | |||
| 8154 | nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); | ||
| 8155 | p = s; | ||
| 8156 | while ((c = *p++) != 0) { | ||
| 8157 | str = 0; | ||
| 8158 | switch (c) { | ||
| 8159 | case CTLESC: | ||
| 8160 | c = *p++; | ||
| 8161 | break; | ||
| 8162 | case CTLVAR: | ||
| 8163 | subtype = *p++; | ||
| 8164 | if ((subtype & VSTYPE) == VSLENGTH) | ||
| 8165 | str = "${#"; | ||
| 8166 | else | ||
| 8167 | str = "${"; | ||
| 8168 | if (!(subtype & VSQUOTE) == !(quoted & 1)) | ||
| 8169 | goto dostr; | ||
| 8170 | quoted ^= 1; | ||
| 8171 | c = '"'; | ||
| 8172 | break; | ||
| 8173 | case CTLENDVAR: | ||
| 8174 | str = "\"}" + !(quoted & 1); | ||
| 8175 | quoted >>= 1; | ||
| 8176 | subtype = 0; | ||
| 8177 | goto dostr; | ||
| 8178 | case CTLBACKQ: | ||
| 8179 | str = "$(...)"; | ||
| 8180 | goto dostr; | ||
| 8181 | case CTLBACKQ+CTLQUOTE: | ||
| 8182 | str = "\"$(...)\""; | ||
| 8183 | goto dostr; | ||
| 8184 | #if ENABLE_ASH_MATH_SUPPORT | ||
| 8185 | case CTLARI: | ||
| 8186 | str = "$(("; | ||
| 8187 | goto dostr; | ||
| 8188 | case CTLENDARI: | ||
| 8189 | str = "))"; | ||
| 8190 | goto dostr; | ||
| 8191 | #endif | ||
| 8192 | case CTLQUOTEMARK: | ||
| 8193 | quoted ^= 1; | ||
| 8194 | c = '"'; | ||
| 8195 | break; | ||
| 8196 | case '=': | ||
| 8197 | if (subtype == 0) | ||
| 8198 | break; | ||
| 8199 | if ((subtype & VSTYPE) != VSNORMAL) | ||
| 8200 | quoted <<= 1; | ||
| 8201 | str = vstype[subtype & VSTYPE]; | ||
| 8202 | if (subtype & VSNUL) | ||
| 8203 | c = ':'; | ||
| 8204 | else | ||
| 8205 | goto checkstr; | ||
| 8206 | break; | ||
| 8207 | case '\'': | ||
| 8208 | case '\\': | ||
| 8209 | case '"': | ||
| 8210 | case '$': | ||
| 8211 | /* These can only happen inside quotes */ | ||
| 8212 | cc[0] = c; | ||
| 8213 | str = cc; | ||
| 8214 | c = '\\'; | ||
| 8215 | break; | ||
| 8216 | default: | ||
| 8217 | break; | ||
| 8218 | } | ||
| 8219 | USTPUTC(c, nextc); | ||
| 8220 | checkstr: | ||
| 8221 | if (!str) | ||
| 8222 | continue; | ||
| 8223 | dostr: | ||
| 8224 | while ((c = *str++)) { | ||
| 8225 | USTPUTC(c, nextc); | ||
| 8226 | } | ||
| 8227 | } | ||
| 8228 | if (quoted & 1) { | ||
| 8229 | USTPUTC('"', nextc); | ||
| 8230 | } | ||
| 8231 | *nextc = 0; | ||
| 8232 | cmdnextc = nextc; | ||
| 8233 | } | ||
| 8234 | |||
| 8235 | /* cmdtxt() and cmdlist() call each other */ | ||
| 8236 | static void cmdtxt(union node *n); | ||
| 8237 | |||
| 8238 | static void | ||
| 8239 | cmdlist(union node *np, int sep) | ||
| 8240 | { | ||
| 8241 | for (; np; np = np->narg.next) { | ||
| 8242 | if (!sep) | ||
| 8243 | cmdputs(spcstr); | ||
| 8244 | cmdtxt(np); | ||
| 8245 | if (sep && np->narg.next) | ||
| 8246 | cmdputs(spcstr); | ||
| 8247 | } | ||
| 8248 | } | ||
| 8249 | |||
| 8250 | static void | ||
| 8251 | cmdtxt(union node *n) | ||
| 8252 | { | ||
| 8253 | union node *np; | ||
| 8254 | struct nodelist *lp; | ||
| 8255 | const char *p; | ||
| 8256 | char s[2]; | ||
| 8257 | |||
| 8258 | if (!n) | ||
| 8259 | return; | ||
| 8260 | switch (n->type) { | ||
| 8261 | default: | ||
| 8262 | #if DEBUG | ||
| 8263 | abort(); | ||
| 8264 | #endif | ||
| 8265 | case NPIPE: | ||
| 8266 | lp = n->npipe.cmdlist; | ||
| 8267 | for (;;) { | ||
| 8268 | cmdtxt(lp->n); | ||
| 8269 | lp = lp->next; | ||
| 8270 | if (!lp) | ||
| 8271 | break; | ||
| 8272 | cmdputs(" | "); | ||
| 8273 | } | ||
| 8274 | break; | ||
| 8275 | case NSEMI: | ||
| 8276 | p = "; "; | ||
| 8277 | goto binop; | ||
| 8278 | case NAND: | ||
| 8279 | p = " && "; | ||
| 8280 | goto binop; | ||
| 8281 | case NOR: | ||
| 8282 | p = " || "; | ||
| 8283 | binop: | ||
| 8284 | cmdtxt(n->nbinary.ch1); | ||
| 8285 | cmdputs(p); | ||
| 8286 | n = n->nbinary.ch2; | ||
| 8287 | goto donode; | ||
| 8288 | case NREDIR: | ||
| 8289 | case NBACKGND: | ||
| 8290 | n = n->nredir.n; | ||
| 8291 | goto donode; | ||
| 8292 | case NNOT: | ||
| 8293 | cmdputs("!"); | ||
| 8294 | n = n->nnot.com; | ||
| 8295 | donode: | ||
| 8296 | cmdtxt(n); | ||
| 8297 | break; | ||
| 8298 | case NIF: | ||
| 8299 | cmdputs("if "); | ||
| 8300 | cmdtxt(n->nif.test); | ||
| 8301 | cmdputs("; then "); | ||
| 8302 | n = n->nif.ifpart; | ||
| 8303 | if (n->nif.elsepart) { | ||
| 8304 | cmdtxt(n); | ||
| 8305 | cmdputs("; else "); | ||
| 8306 | n = n->nif.elsepart; | ||
| 8307 | } | ||
| 8308 | p = "; fi"; | ||
| 8309 | goto dotail; | ||
| 8310 | case NSUBSHELL: | ||
| 8311 | cmdputs("("); | ||
| 8312 | n = n->nredir.n; | ||
| 8313 | p = ")"; | ||
| 8314 | goto dotail; | ||
| 8315 | case NWHILE: | ||
| 8316 | p = "while "; | ||
| 8317 | goto until; | ||
| 8318 | case NUNTIL: | ||
| 8319 | p = "until "; | ||
| 8320 | until: | ||
| 8321 | cmdputs(p); | ||
| 8322 | cmdtxt(n->nbinary.ch1); | ||
| 8323 | n = n->nbinary.ch2; | ||
| 8324 | p = "; done"; | ||
| 8325 | dodo: | ||
| 8326 | cmdputs("; do "); | ||
| 8327 | dotail: | ||
| 8328 | cmdtxt(n); | ||
| 8329 | goto dotail2; | ||
| 8330 | case NFOR: | ||
| 8331 | cmdputs("for "); | ||
| 8332 | cmdputs(n->nfor.var); | ||
| 8333 | cmdputs(" in "); | ||
| 8334 | cmdlist(n->nfor.args, 1); | ||
| 8335 | n = n->nfor.body; | ||
| 8336 | p = "; done"; | ||
| 8337 | goto dodo; | ||
| 8338 | case NDEFUN: | ||
| 8339 | cmdputs(n->narg.text); | ||
| 8340 | p = "() { ... }"; | ||
| 8341 | goto dotail2; | ||
| 8342 | case NCMD: | ||
| 8343 | cmdlist(n->ncmd.args, 1); | ||
| 8344 | cmdlist(n->ncmd.redirect, 0); | ||
| 8345 | break; | ||
| 8346 | case NARG: | ||
| 8347 | p = n->narg.text; | ||
| 8348 | dotail2: | ||
| 8349 | cmdputs(p); | ||
| 8350 | break; | ||
| 8351 | case NHERE: | ||
| 8352 | case NXHERE: | ||
| 8353 | p = "<<..."; | ||
| 8354 | goto dotail2; | ||
| 8355 | case NCASE: | ||
| 8356 | cmdputs("case "); | ||
| 8357 | cmdputs(n->ncase.expr->narg.text); | ||
| 8358 | cmdputs(" in "); | ||
| 8359 | for (np = n->ncase.cases; np; np = np->nclist.next) { | ||
| 8360 | cmdtxt(np->nclist.pattern); | ||
| 8361 | cmdputs(") "); | ||
| 8362 | cmdtxt(np->nclist.body); | ||
| 8363 | cmdputs(";; "); | ||
| 8364 | } | ||
| 8365 | p = "esac"; | ||
| 8366 | goto dotail2; | ||
| 8367 | case NTO: | ||
| 8368 | p = ">"; | ||
| 8369 | goto redir; | ||
| 8370 | case NCLOBBER: | ||
| 8371 | p = ">|"; | ||
| 8372 | goto redir; | ||
| 8373 | case NAPPEND: | ||
| 8374 | p = ">>"; | ||
| 8375 | goto redir; | ||
| 8376 | case NTOFD: | ||
| 8377 | p = ">&"; | ||
| 8378 | goto redir; | ||
| 8379 | case NFROM: | ||
| 8380 | p = "<"; | ||
| 8381 | goto redir; | ||
| 8382 | case NFROMFD: | ||
| 8383 | p = "<&"; | ||
| 8384 | goto redir; | ||
| 8385 | case NFROMTO: | ||
| 8386 | p = "<>"; | ||
| 8387 | redir: | ||
| 8388 | s[0] = n->nfile.fd + '0'; | ||
| 8389 | s[1] = '\0'; | ||
| 8390 | cmdputs(s); | ||
| 8391 | cmdputs(p); | ||
| 8392 | if (n->type == NTOFD || n->type == NFROMFD) { | ||
| 8393 | s[0] = n->ndup.dupfd + '0'; | ||
| 8394 | p = s; | ||
| 8395 | goto dotail2; | ||
| 8396 | } | ||
| 8397 | n = n->nfile.fname; | ||
| 8398 | goto donode; | ||
| 8399 | } | ||
| 8400 | } | ||
| 8401 | |||
| 8402 | static char * | ||
| 8403 | commandtext(union node *n) | ||
| 8404 | { | ||
| 8405 | char *name; | ||
| 8406 | |||
| 8407 | STARTSTACKSTR(cmdnextc); | ||
| 8408 | cmdtxt(n); | ||
| 8409 | name = stackblock(); | ||
| 8410 | TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", | ||
| 8411 | name, cmdnextc, cmdnextc)); | ||
| 8412 | return ckstrdup(name); | ||
| 8413 | } | ||
| 8414 | #endif /* JOBS */ | ||
| 8415 | |||
| 8146 | /* | 8416 | /* |
| 8147 | * Fork off a subshell. If we are doing job control, give the subshell its | 8417 | * Fork off a subshell. If we are doing job control, give the subshell its |
| 8148 | * own process group. Jp is a job structure that the job is to be added to. | 8418 | * own process group. Jp is a job structure that the job is to be added to. |
| @@ -8332,289 +8602,10 @@ stoppedjobs(void) | |||
| 8332 | job_warning = 2; | 8602 | job_warning = 2; |
| 8333 | retval++; | 8603 | retval++; |
| 8334 | } | 8604 | } |
| 8335 | 8605 | out: | |
| 8336 | out: | ||
| 8337 | return retval; | 8606 | return retval; |
| 8338 | } | 8607 | } |
| 8339 | 8608 | ||
| 8340 | /* | ||
| 8341 | * Return a string identifying a command (to be printed by the | ||
| 8342 | * jobs command). | ||
| 8343 | */ | ||
| 8344 | #if JOBS | ||
| 8345 | static char *cmdnextc; | ||
| 8346 | |||
| 8347 | static char * | ||
| 8348 | commandtext(union node *n) | ||
| 8349 | { | ||
| 8350 | char *name; | ||
| 8351 | |||
| 8352 | STARTSTACKSTR(cmdnextc); | ||
| 8353 | cmdtxt(n); | ||
| 8354 | name = stackblock(); | ||
| 8355 | TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", | ||
| 8356 | name, cmdnextc, cmdnextc)); | ||
| 8357 | return ckstrdup(name); | ||
| 8358 | } | ||
| 8359 | |||
| 8360 | static void | ||
| 8361 | cmdtxt(union node *n) | ||
| 8362 | { | ||
| 8363 | union node *np; | ||
| 8364 | struct nodelist *lp; | ||
| 8365 | const char *p; | ||
| 8366 | char s[2]; | ||
| 8367 | |||
| 8368 | if (!n) | ||
| 8369 | return; | ||
| 8370 | switch (n->type) { | ||
| 8371 | default: | ||
| 8372 | #if DEBUG | ||
| 8373 | abort(); | ||
| 8374 | #endif | ||
| 8375 | case NPIPE: | ||
| 8376 | lp = n->npipe.cmdlist; | ||
| 8377 | for (;;) { | ||
| 8378 | cmdtxt(lp->n); | ||
| 8379 | lp = lp->next; | ||
| 8380 | if (!lp) | ||
| 8381 | break; | ||
| 8382 | cmdputs(" | "); | ||
| 8383 | } | ||
| 8384 | break; | ||
| 8385 | case NSEMI: | ||
| 8386 | p = "; "; | ||
| 8387 | goto binop; | ||
| 8388 | case NAND: | ||
| 8389 | p = " && "; | ||
| 8390 | goto binop; | ||
| 8391 | case NOR: | ||
| 8392 | p = " || "; | ||
| 8393 | binop: | ||
| 8394 | cmdtxt(n->nbinary.ch1); | ||
| 8395 | cmdputs(p); | ||
| 8396 | n = n->nbinary.ch2; | ||
| 8397 | goto donode; | ||
| 8398 | case NREDIR: | ||
| 8399 | case NBACKGND: | ||
| 8400 | n = n->nredir.n; | ||
| 8401 | goto donode; | ||
| 8402 | case NNOT: | ||
| 8403 | cmdputs("!"); | ||
| 8404 | n = n->nnot.com; | ||
| 8405 | donode: | ||
| 8406 | cmdtxt(n); | ||
| 8407 | break; | ||
| 8408 | case NIF: | ||
| 8409 | cmdputs("if "); | ||
| 8410 | cmdtxt(n->nif.test); | ||
| 8411 | cmdputs("; then "); | ||
| 8412 | n = n->nif.ifpart; | ||
| 8413 | if (n->nif.elsepart) { | ||
| 8414 | cmdtxt(n); | ||
| 8415 | cmdputs("; else "); | ||
| 8416 | n = n->nif.elsepart; | ||
| 8417 | } | ||
| 8418 | p = "; fi"; | ||
| 8419 | goto dotail; | ||
| 8420 | case NSUBSHELL: | ||
| 8421 | cmdputs("("); | ||
| 8422 | n = n->nredir.n; | ||
| 8423 | p = ")"; | ||
| 8424 | goto dotail; | ||
| 8425 | case NWHILE: | ||
| 8426 | p = "while "; | ||
| 8427 | goto until; | ||
| 8428 | case NUNTIL: | ||
| 8429 | p = "until "; | ||
| 8430 | until: | ||
| 8431 | cmdputs(p); | ||
| 8432 | cmdtxt(n->nbinary.ch1); | ||
| 8433 | n = n->nbinary.ch2; | ||
| 8434 | p = "; done"; | ||
| 8435 | dodo: | ||
| 8436 | cmdputs("; do "); | ||
| 8437 | dotail: | ||
| 8438 | cmdtxt(n); | ||
| 8439 | goto dotail2; | ||
| 8440 | case NFOR: | ||
| 8441 | cmdputs("for "); | ||
| 8442 | cmdputs(n->nfor.var); | ||
| 8443 | cmdputs(" in "); | ||
| 8444 | cmdlist(n->nfor.args, 1); | ||
| 8445 | n = n->nfor.body; | ||
| 8446 | p = "; done"; | ||
| 8447 | goto dodo; | ||
| 8448 | case NDEFUN: | ||
| 8449 | cmdputs(n->narg.text); | ||
| 8450 | p = "() { ... }"; | ||
| 8451 | goto dotail2; | ||
| 8452 | case NCMD: | ||
| 8453 | cmdlist(n->ncmd.args, 1); | ||
| 8454 | cmdlist(n->ncmd.redirect, 0); | ||
| 8455 | break; | ||
| 8456 | case NARG: | ||
| 8457 | p = n->narg.text; | ||
| 8458 | dotail2: | ||
| 8459 | cmdputs(p); | ||
| 8460 | break; | ||
| 8461 | case NHERE: | ||
| 8462 | case NXHERE: | ||
| 8463 | p = "<<..."; | ||
| 8464 | goto dotail2; | ||
| 8465 | case NCASE: | ||
| 8466 | cmdputs("case "); | ||
| 8467 | cmdputs(n->ncase.expr->narg.text); | ||
| 8468 | cmdputs(" in "); | ||
| 8469 | for (np = n->ncase.cases; np; np = np->nclist.next) { | ||
| 8470 | cmdtxt(np->nclist.pattern); | ||
| 8471 | cmdputs(") "); | ||
| 8472 | cmdtxt(np->nclist.body); | ||
| 8473 | cmdputs(";; "); | ||
| 8474 | } | ||
| 8475 | p = "esac"; | ||
| 8476 | goto dotail2; | ||
| 8477 | case NTO: | ||
| 8478 | p = ">"; | ||
| 8479 | goto redir; | ||
| 8480 | case NCLOBBER: | ||
| 8481 | p = ">|"; | ||
| 8482 | goto redir; | ||
| 8483 | case NAPPEND: | ||
| 8484 | p = ">>"; | ||
| 8485 | goto redir; | ||
| 8486 | case NTOFD: | ||
| 8487 | p = ">&"; | ||
| 8488 | goto redir; | ||
| 8489 | case NFROM: | ||
| 8490 | p = "<"; | ||
| 8491 | goto redir; | ||
| 8492 | case NFROMFD: | ||
| 8493 | p = "<&"; | ||
| 8494 | goto redir; | ||
| 8495 | case NFROMTO: | ||
| 8496 | p = "<>"; | ||
| 8497 | redir: | ||
| 8498 | s[0] = n->nfile.fd + '0'; | ||
| 8499 | s[1] = '\0'; | ||
| 8500 | cmdputs(s); | ||
| 8501 | cmdputs(p); | ||
| 8502 | if (n->type == NTOFD || n->type == NFROMFD) { | ||
| 8503 | s[0] = n->ndup.dupfd + '0'; | ||
| 8504 | p = s; | ||
| 8505 | goto dotail2; | ||
| 8506 | } | ||
| 8507 | n = n->nfile.fname; | ||
| 8508 | goto donode; | ||
| 8509 | } | ||
| 8510 | } | ||
| 8511 | |||
| 8512 | static void | ||
| 8513 | cmdlist(union node *np, int sep) | ||
| 8514 | { | ||
| 8515 | for (; np; np = np->narg.next) { | ||
| 8516 | if (!sep) | ||
| 8517 | cmdputs(spcstr); | ||
| 8518 | cmdtxt(np); | ||
| 8519 | if (sep && np->narg.next) | ||
| 8520 | cmdputs(spcstr); | ||
| 8521 | } | ||
| 8522 | } | ||
| 8523 | |||
| 8524 | static void | ||
| 8525 | cmdputs(const char *s) | ||
| 8526 | { | ||
| 8527 | const char *p, *str; | ||
| 8528 | char c, cc[2] = " "; | ||
| 8529 | char *nextc; | ||
| 8530 | int subtype = 0; | ||
| 8531 | int quoted = 0; | ||
| 8532 | static const char vstype[VSTYPE + 1][4] = { | ||
| 8533 | "", "}", "-", "+", "?", "=", | ||
| 8534 | "%", "%%", "#", "##" | ||
| 8535 | }; | ||
| 8536 | |||
| 8537 | nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); | ||
| 8538 | p = s; | ||
| 8539 | while ((c = *p++) != 0) { | ||
| 8540 | str = 0; | ||
| 8541 | switch (c) { | ||
| 8542 | case CTLESC: | ||
| 8543 | c = *p++; | ||
| 8544 | break; | ||
| 8545 | case CTLVAR: | ||
| 8546 | subtype = *p++; | ||
| 8547 | if ((subtype & VSTYPE) == VSLENGTH) | ||
| 8548 | str = "${#"; | ||
| 8549 | else | ||
| 8550 | str = "${"; | ||
| 8551 | if (!(subtype & VSQUOTE) == !(quoted & 1)) | ||
| 8552 | goto dostr; | ||
| 8553 | quoted ^= 1; | ||
| 8554 | c = '"'; | ||
| 8555 | break; | ||
| 8556 | case CTLENDVAR: | ||
| 8557 | str = "\"}" + !(quoted & 1); | ||
| 8558 | quoted >>= 1; | ||
| 8559 | subtype = 0; | ||
| 8560 | goto dostr; | ||
| 8561 | case CTLBACKQ: | ||
| 8562 | str = "$(...)"; | ||
| 8563 | goto dostr; | ||
| 8564 | case CTLBACKQ+CTLQUOTE: | ||
| 8565 | str = "\"$(...)\""; | ||
| 8566 | goto dostr; | ||
| 8567 | #if ENABLE_ASH_MATH_SUPPORT | ||
| 8568 | case CTLARI: | ||
| 8569 | str = "$(("; | ||
| 8570 | goto dostr; | ||
| 8571 | case CTLENDARI: | ||
| 8572 | str = "))"; | ||
| 8573 | goto dostr; | ||
| 8574 | #endif | ||
| 8575 | case CTLQUOTEMARK: | ||
| 8576 | quoted ^= 1; | ||
| 8577 | c = '"'; | ||
| 8578 | break; | ||
| 8579 | case '=': | ||
| 8580 | if (subtype == 0) | ||
| 8581 | break; | ||
| 8582 | if ((subtype & VSTYPE) != VSNORMAL) | ||
| 8583 | quoted <<= 1; | ||
| 8584 | str = vstype[subtype & VSTYPE]; | ||
| 8585 | if (subtype & VSNUL) | ||
| 8586 | c = ':'; | ||
| 8587 | else | ||
| 8588 | goto checkstr; | ||
| 8589 | break; | ||
| 8590 | case '\'': | ||
| 8591 | case '\\': | ||
| 8592 | case '"': | ||
| 8593 | case '$': | ||
| 8594 | /* These can only happen inside quotes */ | ||
| 8595 | cc[0] = c; | ||
| 8596 | str = cc; | ||
| 8597 | c = '\\'; | ||
| 8598 | break; | ||
| 8599 | default: | ||
| 8600 | break; | ||
| 8601 | } | ||
| 8602 | USTPUTC(c, nextc); | ||
| 8603 | checkstr: | ||
| 8604 | if (!str) | ||
| 8605 | continue; | ||
| 8606 | dostr: | ||
| 8607 | while ((c = *str++)) { | ||
| 8608 | USTPUTC(c, nextc); | ||
| 8609 | } | ||
| 8610 | } | ||
| 8611 | if (quoted & 1) { | ||
| 8612 | USTPUTC('"', nextc); | ||
| 8613 | } | ||
| 8614 | *nextc = 0; | ||
| 8615 | cmdnextc = nextc; | ||
| 8616 | } | ||
| 8617 | #endif /* JOBS */ | ||
| 8618 | 8609 | ||
| 8619 | #if ENABLE_ASH_MAIL | 8610 | #if ENABLE_ASH_MAIL |
| 8620 | /* mail.c */ | 8611 | /* mail.c */ |
| @@ -11348,8 +11339,6 @@ redirectsafe(union node *redir, int flags) | |||
| 11348 | 11339 | ||
| 11349 | /* trap.c */ | 11340 | /* trap.c */ |
| 11350 | 11341 | ||
| 11351 | |||
| 11352 | |||
| 11353 | /* | 11342 | /* |
| 11354 | * The trap builtin. | 11343 | * The trap builtin. |
| 11355 | */ | 11344 | */ |
