| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: eval.c,v 1.140.2.4 2018/08/25 11:45:40 martin Exp $ */ | | 1 | /* $NetBSD: eval.c,v 1.140.2.5 2018/08/25 14:22:49 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1993 | | 4 | * Copyright (c) 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. | | 8 | * Kenneth Almquist. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | #ifndef lint | | 36 | #ifndef lint |
37 | #if 0 | | 37 | #if 0 |
38 | static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; | | 38 | static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; |
39 | #else | | 39 | #else |
40 | __RCSID("$NetBSD: eval.c,v 1.140.2.4 2018/08/25 11:45:40 martin Exp $"); | | 40 | __RCSID("$NetBSD: eval.c,v 1.140.2.5 2018/08/25 14:22:49 martin Exp $"); |
41 | #endif | | 41 | #endif |
42 | #endif /* not lint */ | | 42 | #endif /* not lint */ |
43 | | | 43 | |
44 | #include <stdbool.h> | | 44 | #include <stdbool.h> |
45 | #include <stdlib.h> | | 45 | #include <stdlib.h> |
46 | #include <signal.h> | | 46 | #include <signal.h> |
47 | #include <stdio.h> | | 47 | #include <stdio.h> |
48 | #include <string.h> | | 48 | #include <string.h> |
49 | #include <errno.h> | | 49 | #include <errno.h> |
50 | #include <limits.h> | | 50 | #include <limits.h> |
51 | #include <unistd.h> | | 51 | #include <unistd.h> |
52 | #include <sys/fcntl.h> | | 52 | #include <sys/fcntl.h> |
53 | #include <sys/stat.h> | | 53 | #include <sys/stat.h> |
| @@ -211,27 +211,27 @@ evalcmd(int argc, char **argv) | | | @@ -211,27 +211,27 @@ evalcmd(int argc, char **argv) |
211 | | | 211 | |
212 | void | | 212 | void |
213 | evalstring(char *s, int flag) | | 213 | evalstring(char *s, int flag) |
214 | { | | 214 | { |
215 | union node *n; | | 215 | union node *n; |
216 | struct stackmark smark; | | 216 | struct stackmark smark; |
217 | | | 217 | |
218 | setstackmark(&smark); | | 218 | setstackmark(&smark); |
219 | setinputstring(s, 1, line_number); | | 219 | setinputstring(s, 1, line_number); |
220 | | | 220 | |
221 | while ((n = parsecmd(0)) != NEOF) { | | 221 | while ((n = parsecmd(0)) != NEOF) { |
222 | XTRACE(DBG_EVAL, ("evalstring: "), showtree(n)); | | 222 | XTRACE(DBG_EVAL, ("evalstring: "), showtree(n)); |
223 | if (n && nflag == 0) | | 223 | if (n && nflag == 0) |
224 | evaltree(n, flag | EV_MORE); | | 224 | evaltree(n, flag); |
225 | popstackmark(&smark); | | 225 | popstackmark(&smark); |
226 | } | | 226 | } |
227 | popfile(); | | 227 | popfile(); |
228 | popstackmark(&smark); | | 228 | popstackmark(&smark); |
229 | } | | 229 | } |
230 | | | 230 | |
231 | | | 231 | |
232 | | | 232 | |
233 | /* | | 233 | /* |
234 | * Evaluate a parse tree. The value is left in the global variable | | 234 | * Evaluate a parse tree. The value is left in the global variable |
235 | * exitstatus. | | 235 | * exitstatus. |
236 | */ | | 236 | */ |
237 | | | 237 | |
| @@ -246,74 +246,73 @@ evaltree(union node *n, int flags) | | | @@ -246,74 +246,73 @@ evaltree(union node *n, int flags) |
246 | VTRACE(DBG_EVAL, ("evaltree(%s) called\n", | | 246 | VTRACE(DBG_EVAL, ("evaltree(%s) called\n", |
247 | n == NULL ? "NULL" : "-n")); | | 247 | n == NULL ? "NULL" : "-n")); |
248 | if (nflag == 0) | | 248 | if (nflag == 0) |
249 | exitstatus = 0; | | 249 | exitstatus = 0; |
250 | goto out; | | 250 | goto out; |
251 | } | | 251 | } |
252 | #ifndef SMALL | | 252 | #ifndef SMALL |
253 | displayhist = 1; /* show history substitutions done with fc */ | | 253 | displayhist = 1; /* show history substitutions done with fc */ |
254 | #endif | | 254 | #endif |
255 | CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n", | | 255 | CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n", |
256 | getpid(), n, NODETYPENAME(n->type), n->type, flags)); | | 256 | getpid(), n, NODETYPENAME(n->type), n->type, flags)); |
257 | switch (n->type) { | | 257 | switch (n->type) { |
258 | case NSEMI: | | 258 | case NSEMI: |
259 | evaltree(n->nbinary.ch1, (sflags & EV_TESTED) | | | 259 | evaltree(n->nbinary.ch1, flags & EV_TESTED); |
260 | (n->nbinary.ch2 ? EV_MORE : 0)); | | | |
261 | if (nflag || evalskip) | | 260 | if (nflag || evalskip) |
262 | goto out; | | 261 | goto out; |
263 | evaltree(n->nbinary.ch2, flags); | | 262 | evaltree(n->nbinary.ch2, flags); |
264 | break; | | 263 | break; |
265 | case NAND: | | 264 | case NAND: |
266 | evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE); | | 265 | evaltree(n->nbinary.ch1, EV_TESTED); |
267 | if (nflag || evalskip || exitstatus != 0) | | 266 | if (nflag || evalskip || exitstatus != 0) |
268 | goto out; | | 267 | goto out; |
269 | evaltree(n->nbinary.ch2, flags); | | 268 | evaltree(n->nbinary.ch2, flags); |
270 | break; | | 269 | break; |
271 | case NOR: | | 270 | case NOR: |
272 | evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE); | | 271 | evaltree(n->nbinary.ch1, EV_TESTED); |
273 | if (nflag || evalskip || exitstatus == 0) | | 272 | if (nflag || evalskip || exitstatus == 0) |
274 | goto out; | | 273 | goto out; |
275 | evaltree(n->nbinary.ch2, flags); | | 274 | evaltree(n->nbinary.ch2, flags); |
276 | break; | | 275 | break; |
277 | case NREDIR: | | 276 | case NREDIR: |
278 | expredir(n->nredir.redirect); | | 277 | expredir(n->nredir.redirect); |
279 | if (xflag && n->nredir.redirect) { | | 278 | if (xflag && n->nredir.redirect) { |
280 | union node *rn; | | 279 | union node *rn; |
281 | | | 280 | |
282 | out2str(expandstr(ps4val(), line_number)); | | 281 | out2str(expandstr(ps4val(), line_number)); |
283 | out2str("using redirections:"); | | 282 | out2str("using redirections:"); |
284 | for (rn = n->nredir.redirect; rn; rn = rn->nfile.next) | | 283 | for (rn = n->nredir.redirect; rn; rn = rn->nfile.next) |
285 | (void) outredir(&errout, rn, ' '); | | 284 | (void) outredir(&errout, rn, ' '); |
286 | out2str(" do\n"); | | 285 | out2str(" do\n"); |
287 | flushout(&errout); | | 286 | flushout(&errout); |
288 | } | | 287 | } |
289 | redirect(n->nredir.redirect, REDIR_PUSH | REDIR_KEEP); | | 288 | redirect(n->nredir.redirect, REDIR_PUSH | REDIR_KEEP); |
290 | evaltree(n->nredir.n, flags); | | 289 | evaltree(n->nredir.n, flags); |
291 | popredir(); | | 290 | popredir(); |
292 | if (xflag && n->nredir.redirect) { | | 291 | if (xflag && n->nredir.redirect) { |
293 | out2str(expandstr(ps4val(), line_number)); | | 292 | out2str(expandstr(ps4val(), line_number)); |
294 | out2str("done\n"); | | 293 | out2str("done\n"); |
295 | flushout(&errout); | | 294 | flushout(&errout); |
296 | } | | 295 | } |
297 | break; | | 296 | break; |
298 | case NSUBSHELL: | | 297 | case NSUBSHELL: |
299 | evalsubshell(n, flags & ~EV_MORE); | | 298 | evalsubshell(n, flags); |
300 | do_etest = !(flags & EV_TESTED); | | 299 | do_etest = !(flags & EV_TESTED); |
301 | break; | | 300 | break; |
302 | case NBACKGND: | | 301 | case NBACKGND: |
303 | evalsubshell(n, flags & ~EV_MORE); | | 302 | evalsubshell(n, flags); |
304 | break; | | 303 | break; |
305 | case NIF: { | | 304 | case NIF: { |
306 | evaltree(n->nif.test, EV_TESTED | EV_MORE); | | 305 | evaltree(n->nif.test, EV_TESTED); |
307 | if (nflag || evalskip) | | 306 | if (nflag || evalskip) |
308 | goto out; | | 307 | goto out; |
309 | if (exitstatus == 0) | | 308 | if (exitstatus == 0) |
310 | evaltree(n->nif.ifpart, flags); | | 309 | evaltree(n->nif.ifpart, flags); |
311 | else if (n->nif.elsepart) | | 310 | else if (n->nif.elsepart) |
312 | evaltree(n->nif.elsepart, flags); | | 311 | evaltree(n->nif.elsepart, flags); |
313 | else | | 312 | else |
314 | exitstatus = 0; | | 313 | exitstatus = 0; |
315 | break; | | 314 | break; |
316 | } | | 315 | } |
317 | case NWHILE: | | 316 | case NWHILE: |
318 | case NUNTIL: | | 317 | case NUNTIL: |
319 | evalloop(n, sflags); | | 318 | evalloop(n, sflags); |
| @@ -321,31 +320,31 @@ evaltree(union node *n, int flags) | | | @@ -321,31 +320,31 @@ evaltree(union node *n, int flags) |
321 | case NFOR: | | 320 | case NFOR: |
322 | evalfor(n, sflags); | | 321 | evalfor(n, sflags); |
323 | break; | | 322 | break; |
324 | case NCASE: | | 323 | case NCASE: |
325 | evalcase(n, sflags); | | 324 | evalcase(n, sflags); |
326 | break; | | 325 | break; |
327 | case NDEFUN: | | 326 | case NDEFUN: |
328 | CTRACE(DBG_EVAL, ("Defining fn %s @%d%s\n", n->narg.text, | | 327 | CTRACE(DBG_EVAL, ("Defining fn %s @%d%s\n", n->narg.text, |
329 | n->narg.lineno, fnline1 ? " LINENO=1" : "")); | | 328 | n->narg.lineno, fnline1 ? " LINENO=1" : "")); |
330 | defun(n->narg.text, n->narg.next, n->narg.lineno); | | 329 | defun(n->narg.text, n->narg.next, n->narg.lineno); |
331 | exitstatus = 0; | | 330 | exitstatus = 0; |
332 | break; | | 331 | break; |
333 | case NNOT: | | 332 | case NNOT: |
334 | evaltree(n->nnot.com, (sflags & EV_MORE) | EV_TESTED); | | 333 | evaltree(n->nnot.com, EV_TESTED); |
335 | exitstatus = !exitstatus; | | 334 | exitstatus = !exitstatus; |
336 | break; | | 335 | break; |
337 | case NDNOT: | | 336 | case NDNOT: |
338 | evaltree(n->nnot.com, (sflags & EV_MORE) | EV_TESTED); | | 337 | evaltree(n->nnot.com, EV_TESTED); |
339 | if (exitstatus != 0) | | 338 | if (exitstatus != 0) |
340 | exitstatus = 1; | | 339 | exitstatus = 1; |
341 | break; | | 340 | break; |
342 | case NPIPE: | | 341 | case NPIPE: |
343 | evalpipe(n); | | 342 | evalpipe(n); |
344 | do_etest = !(flags & EV_TESTED); | | 343 | do_etest = !(flags & EV_TESTED); |
345 | break; | | 344 | break; |
346 | case NCMD: | | 345 | case NCMD: |
347 | evalcommand(n, flags, NULL); | | 346 | evalcommand(n, flags, NULL); |
348 | do_etest = !(flags & EV_TESTED); | | 347 | do_etest = !(flags & EV_TESTED); |
349 | break; | | 348 | break; |
350 | default: | | 349 | default: |
351 | #ifdef NODETYPENAME | | 350 | #ifdef NODETYPENAME |
| @@ -369,46 +368,46 @@ evalloop(union node *n, int flags) | | | @@ -369,46 +368,46 @@ evalloop(union node *n, int flags) |
369 | { | | 368 | { |
370 | int status; | | 369 | int status; |
371 | | | 370 | |
372 | loopnest++; | | 371 | loopnest++; |
373 | status = 0; | | 372 | status = 0; |
374 | | | 373 | |
375 | CTRACE(DBG_EVAL, ("evalloop %s:", NODETYPENAME(n->type))); | | 374 | CTRACE(DBG_EVAL, ("evalloop %s:", NODETYPENAME(n->type))); |
376 | VXTRACE(DBG_EVAL, (" "), showtree(n->nbinary.ch1)); | | 375 | VXTRACE(DBG_EVAL, (" "), showtree(n->nbinary.ch1)); |
377 | VXTRACE(DBG_EVAL, ("evalloop do: "), showtree(n->nbinary.ch2)); | | 376 | VXTRACE(DBG_EVAL, ("evalloop do: "), showtree(n->nbinary.ch2)); |
378 | VTRACE(DBG_EVAL, ("evalloop done\n")); | | 377 | VTRACE(DBG_EVAL, ("evalloop done\n")); |
379 | CTRACE(DBG_EVAL, ("\n")); | | 378 | CTRACE(DBG_EVAL, ("\n")); |
380 | | | 379 | |
381 | for (;;) { | | 380 | for (;;) { |
382 | evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE); | | 381 | evaltree(n->nbinary.ch1, EV_TESTED); |
383 | if (nflag) | | 382 | if (nflag) |
384 | break; | | 383 | break; |
385 | if (evalskip) { | | 384 | if (evalskip) { |
386 | skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { | | 385 | skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { |
387 | evalskip = SKIPNONE; | | 386 | evalskip = SKIPNONE; |
388 | continue; | | 387 | continue; |
389 | } | | 388 | } |
390 | if (evalskip == SKIPBREAK && --skipcount <= 0) | | 389 | if (evalskip == SKIPBREAK && --skipcount <= 0) |
391 | evalskip = SKIPNONE; | | 390 | evalskip = SKIPNONE; |
392 | break; | | 391 | break; |
393 | } | | 392 | } |
394 | if (n->type == NWHILE) { | | 393 | if (n->type == NWHILE) { |
395 | if (exitstatus != 0) | | 394 | if (exitstatus != 0) |
396 | break; | | 395 | break; |
397 | } else { | | 396 | } else { |
398 | if (exitstatus == 0) | | 397 | if (exitstatus == 0) |
399 | break; | | 398 | break; |
400 | } | | 399 | } |
401 | evaltree(n->nbinary.ch2, (flags & EV_TESTED) | EV_MORE); | | 400 | evaltree(n->nbinary.ch2, flags & EV_TESTED); |
402 | status = exitstatus; | | 401 | status = exitstatus; |
403 | if (evalskip) | | 402 | if (evalskip) |
404 | goto skipping; | | 403 | goto skipping; |
405 | } | | 404 | } |
406 | loopnest--; | | 405 | loopnest--; |
407 | exitstatus = status; | | 406 | exitstatus = status; |
408 | } | | 407 | } |
409 | | | 408 | |
410 | | | 409 | |
411 | | | 410 | |
412 | STATIC void | | 411 | STATIC void |
413 | evalfor(union node *n, int flags) | | 412 | evalfor(union node *n, int flags) |
414 | { | | 413 | { |
| @@ -421,43 +420,38 @@ evalfor(union node *n, int flags) | | | @@ -421,43 +420,38 @@ evalfor(union node *n, int flags) |
421 | status = nflag ? exitstatus : 0; | | 420 | status = nflag ? exitstatus : 0; |
422 | | | 421 | |
423 | setstackmark(&smark); | | 422 | setstackmark(&smark); |
424 | arglist.lastp = &arglist.list; | | 423 | arglist.lastp = &arglist.list; |
425 | for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { | | 424 | for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { |
426 | expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); | | 425 | expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); |
427 | if (evalskip) | | 426 | if (evalskip) |
428 | goto out; | | 427 | goto out; |
429 | } | | 428 | } |
430 | *arglist.lastp = NULL; | | 429 | *arglist.lastp = NULL; |
431 | | | 430 | |
432 | loopnest++; | | 431 | loopnest++; |
433 | for (sp = arglist.list ; sp ; sp = sp->next) { | | 432 | for (sp = arglist.list ; sp ; sp = sp->next) { |
434 | int f = flags & (EV_TESTED | EV_MORE); | | | |
435 | | | | |
436 | if (sp->next) | | | |
437 | f |= EV_MORE; | | | |
438 | | | | |
439 | if (xflag) { | | 433 | if (xflag) { |
440 | out2str(expandstr(ps4val(), line_number)); | | 434 | out2str(expandstr(ps4val(), line_number)); |
441 | out2str("for "); | | 435 | out2str("for "); |
442 | out2str(n->nfor.var); | | 436 | out2str(n->nfor.var); |
443 | out2c('='); | | 437 | out2c('='); |
444 | out2shstr(sp->text); | | 438 | out2shstr(sp->text); |
445 | out2c('\n'); | | 439 | out2c('\n'); |
446 | flushout(&errout); | | 440 | flushout(&errout); |
447 | } | | 441 | } |
448 | | | 442 | |
449 | setvar(n->nfor.var, sp->text, 0); | | 443 | setvar(n->nfor.var, sp->text, 0); |
450 | evaltree(n->nfor.body, f); | | 444 | evaltree(n->nfor.body, flags & EV_TESTED); |
451 | status = exitstatus; | | 445 | status = exitstatus; |
452 | if (nflag) | | 446 | if (nflag) |
453 | break; | | 447 | break; |
454 | if (evalskip) { | | 448 | if (evalskip) { |
455 | if (evalskip == SKIPCONT && --skipcount <= 0) { | | 449 | if (evalskip == SKIPCONT && --skipcount <= 0) { |
456 | evalskip = SKIPNONE; | | 450 | evalskip = SKIPNONE; |
457 | continue; | | 451 | continue; |
458 | } | | 452 | } |
459 | if (evalskip == SKIPBREAK && --skipcount <= 0) | | 453 | if (evalskip == SKIPBREAK && --skipcount <= 0) |
460 | evalskip = SKIPNONE; | | 454 | evalskip = SKIPNONE; |
461 | break; | | 455 | break; |
462 | } | | 456 | } |
463 | } | | 457 | } |
| @@ -483,28 +477,27 @@ evalcase(union node *n, int flags) | | | @@ -483,28 +477,27 @@ evalcase(union node *n, int flags) |
483 | line_number = n->ncase.lineno; | | 477 | line_number = n->ncase.lineno; |
484 | expandarg(n->ncase.expr, &arglist, EXP_TILDE); | | 478 | expandarg(n->ncase.expr, &arglist, EXP_TILDE); |
485 | for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) { | | 479 | for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) { |
486 | for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) { | | 480 | for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) { |
487 | line_number = patp->narg.lineno; | | 481 | line_number = patp->narg.lineno; |
488 | if (casematch(patp, arglist.list->text)) { | | 482 | if (casematch(patp, arglist.list->text)) { |
489 | while (cp != NULL && evalskip == 0 && | | 483 | while (cp != NULL && evalskip == 0 && |
490 | nflag == 0) { | | 484 | nflag == 0) { |
491 | if (cp->type == NCLISTCONT) | | 485 | if (cp->type == NCLISTCONT) |
492 | ncp = cp->nclist.next; | | 486 | ncp = cp->nclist.next; |
493 | else | | 487 | else |
494 | ncp = NULL; | | 488 | ncp = NULL; |
495 | line_number = cp->nclist.lineno; | | 489 | line_number = cp->nclist.lineno; |
496 | evaltree(cp->nclist.body, | | 490 | evaltree(cp->nclist.body, flags); |
497 | ncp ? (flags | EV_MORE) : flags); | | | |
498 | status = exitstatus; | | 491 | status = exitstatus; |
499 | cp = ncp; | | 492 | cp = ncp; |
500 | } | | 493 | } |
501 | goto out; | | 494 | goto out; |
502 | } | | 495 | } |
503 | } | | 496 | } |
504 | } | | 497 | } |
505 | out: | | 498 | out: |
506 | exitstatus = status; | | 499 | exitstatus = status; |
507 | popstackmark(&smark); | | 500 | popstackmark(&smark); |
508 | } | | 501 | } |
509 | | | 502 | |
510 | | | 503 | |
| @@ -955,28 +948,26 @@ evalcommand(union node *cmd, int flgs, s | | | @@ -955,28 +948,26 @@ evalcommand(union node *cmd, int flgs, s |
955 | } | | 948 | } |
956 | | | 949 | |
957 | /* Fork off a child process if necessary. */ | | 950 | /* Fork off a child process if necessary. */ |
958 | if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0) | | 951 | if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0) |
959 | || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) | | 952 | || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) |
960 | && (flags & EV_EXIT) == 0) | | 953 | && (flags & EV_EXIT) == 0) |
961 | || ((flags & EV_BACKCMD) != 0 && | | 954 | || ((flags & EV_BACKCMD) != 0 && |
962 | ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) | | 955 | ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) |
963 | || cmdentry.u.bltin == dotcmd | | 956 | || cmdentry.u.bltin == dotcmd |
964 | || cmdentry.u.bltin == evalcmd))) { | | 957 | || cmdentry.u.bltin == evalcmd))) { |
965 | INTOFF; | | 958 | INTOFF; |
966 | jp = makejob(cmd, 1); | | 959 | jp = makejob(cmd, 1); |
967 | mode = cmd->ncmd.backgnd; | | 960 | mode = cmd->ncmd.backgnd; |
968 | if (mode) | | | |
969 | flags &= ~EV_MORE; | | | |
970 | if (flags & EV_BACKCMD) { | | 961 | if (flags & EV_BACKCMD) { |
971 | mode = FORK_NOJOB; | | 962 | mode = FORK_NOJOB; |
972 | if (sh_pipe(pip) < 0) | | 963 | if (sh_pipe(pip) < 0) |
973 | error("Pipe call failed"); | | 964 | error("Pipe call failed"); |
974 | } | | 965 | } |
975 | #ifdef DO_SHAREDVFORK | | 966 | #ifdef DO_SHAREDVFORK |
976 | /* It is essential that if DO_SHAREDVFORK is defined that the | | 967 | /* It is essential that if DO_SHAREDVFORK is defined that the |
977 | * child's address space is actually shared with the parent as | | 968 | * child's address space is actually shared with the parent as |
978 | * we rely on this. | | 969 | * we rely on this. |
979 | */ | | 970 | */ |
980 | if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) { | | 971 | if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) { |
981 | pid_t pid; | | 972 | pid_t pid; |
982 | int serrno; | | 973 | int serrno; |
| @@ -1058,26 +1049,27 @@ evalcommand(union node *cmd, int flgs, s | | | @@ -1058,26 +1049,27 @@ evalcommand(union node *cmd, int flgs, s |
1058 | } | | 1049 | } |
1059 | close(pip[0]); | | 1050 | close(pip[0]); |
1060 | movefd(pip[1], 1); | | 1051 | movefd(pip[1], 1); |
1061 | } | | 1052 | } |
1062 | flags |= EV_EXIT; | | 1053 | flags |= EV_EXIT; |
1063 | } | | 1054 | } |
1064 | | | 1055 | |
1065 | /* This is the child process if a fork occurred. */ | | 1056 | /* This is the child process if a fork occurred. */ |
1066 | /* Execute the command. */ | | 1057 | /* Execute the command. */ |
1067 | switch (cmdentry.cmdtype) { | | 1058 | switch (cmdentry.cmdtype) { |
1068 | case CMDFUNCTION: | | 1059 | case CMDFUNCTION: |
1069 | VXTRACE(DBG_EVAL, ("Shell function: "), trargs(argv)); | | 1060 | VXTRACE(DBG_EVAL, ("Shell function: "), trargs(argv)); |
1070 | redirect(cmd->ncmd.redirect, flags & EV_MORE ? REDIR_PUSH : 0); | | 1061 | redirect(cmd->ncmd.redirect, flags & EV_MORE ? REDIR_PUSH : 0); |
| | | 1062 | redirect(cmd->ncmd.redirect, REDIR_PUSH); |
1071 | saveparam = shellparam; | | 1063 | saveparam = shellparam; |
1072 | shellparam.malloc = 0; | | 1064 | shellparam.malloc = 0; |
1073 | shellparam.reset = 1; | | 1065 | shellparam.reset = 1; |
1074 | shellparam.nparam = argc - 1; | | 1066 | shellparam.nparam = argc - 1; |
1075 | shellparam.p = argv + 1; | | 1067 | shellparam.p = argv + 1; |
1076 | shellparam.optnext = NULL; | | 1068 | shellparam.optnext = NULL; |
1077 | INTOFF; | | 1069 | INTOFF; |
1078 | savelocalvars = localvars; | | 1070 | savelocalvars = localvars; |
1079 | localvars = NULL; | | 1071 | localvars = NULL; |
1080 | reffunc(cmdentry.u.func); | | 1072 | reffunc(cmdentry.u.func); |
1081 | INTON; | | 1073 | INTON; |
1082 | if (setjmp(jmploc.loc)) { | | 1074 | if (setjmp(jmploc.loc)) { |
1083 | if (exception == EXSHELLPROC) { | | 1075 | if (exception == EXSHELLPROC) { |
| @@ -1116,28 +1108,27 @@ evalcommand(union node *cmd, int flgs, s | | | @@ -1116,28 +1108,27 @@ evalcommand(union node *cmd, int flgs, s |
1116 | if (++funcnest > 1000) | | 1108 | if (++funcnest > 1000) |
1117 | error("too many nested function calls"); | | 1109 | error("too many nested function calls"); |
1118 | evaltree(getfuncnode(cmdentry.u.func), flags & EV_TESTED); | | 1110 | evaltree(getfuncnode(cmdentry.u.func), flags & EV_TESTED); |
1119 | funcnest--; | | 1111 | funcnest--; |
1120 | INTOFF; | | 1112 | INTOFF; |
1121 | unreffunc(cmdentry.u.func); | | 1113 | unreffunc(cmdentry.u.func); |
1122 | poplocalvars(); | | 1114 | poplocalvars(); |
1123 | localvars = savelocalvars; | | 1115 | localvars = savelocalvars; |
1124 | funclinebase = savefuncline; | | 1116 | funclinebase = savefuncline; |
1125 | funclineabs = savefuncabs; | | 1117 | funclineabs = savefuncabs; |
1126 | freeparam(&shellparam); | | 1118 | freeparam(&shellparam); |
1127 | shellparam = saveparam; | | 1119 | shellparam = saveparam; |
1128 | handler = savehandler; | | 1120 | handler = savehandler; |
1129 | if (flags & EV_MORE) | | 1121 | popredir(); |
1130 | popredir(); | | | |
1131 | INTON; | | 1122 | INTON; |
1132 | if (evalskip == SKIPFUNC) { | | 1123 | if (evalskip == SKIPFUNC) { |
1133 | evalskip = SKIPNONE; | | 1124 | evalskip = SKIPNONE; |
1134 | skipcount = 0; | | 1125 | skipcount = 0; |
1135 | } | | 1126 | } |
1136 | if (flags & EV_EXIT) | | 1127 | if (flags & EV_EXIT) |
1137 | exitshell(exitstatus); | | 1128 | exitshell(exitstatus); |
1138 | break; | | 1129 | break; |
1139 | | | 1130 | |
1140 | case CMDBUILTIN: | | 1131 | case CMDBUILTIN: |
1141 | case CMDSPLBLTIN: | | 1132 | case CMDSPLBLTIN: |
1142 | VXTRACE(DBG_EVAL, ("builtin command: "), trargs(argv)); | | 1133 | VXTRACE(DBG_EVAL, ("builtin command: "), trargs(argv)); |
1143 | mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; | | 1134 | mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; |