396 |
assert (!p->pids); /* pipeline not started already */ |
assert (!p->pids); /* pipeline not started already */ |
397 |
p->pids = xmalloc (p->ncommands * sizeof *p->pids); |
p->pids = xmalloc (p->ncommands * sizeof *p->pids); |
398 |
|
|
399 |
if (p->want_in) { |
if (p->want_in < 0) { |
400 |
if (pipe (infd) < 0) |
if (pipe (infd) < 0) |
401 |
error (FATAL, errno, _("pipe failed")); |
error (FATAL, errno, _("pipe failed")); |
402 |
last_input = infd[0]; |
last_input = infd[0]; |
403 |
p->infd = infd[1]; |
p->infd = infd[1]; |
404 |
} |
} else if (p->want_in > 0) |
405 |
|
last_input = p->want_in; |
406 |
|
|
407 |
for (i = 0; i < p->ncommands; i++) { |
for (i = 0; i < p->ncommands; i++) { |
408 |
int pdes[2]; |
int pdes[2]; |
409 |
pid_t pid; |
pid_t pid; |
410 |
|
int output_read = -1, output_write = -1; |
411 |
|
|
412 |
if (i != p->ncommands - 1 || p->want_out) { |
if (i != p->ncommands - 1 || p->want_out < 0) { |
413 |
if (pipe (pdes) < 0) |
if (pipe (pdes) < 0) |
414 |
error (FATAL, errno, _("pipe failed")); |
error (FATAL, errno, _("pipe failed")); |
415 |
if (i == p->ncommands - 1) |
if (i == p->ncommands - 1) |
416 |
p->outfd = pdes[0]; |
p->outfd = pdes[0]; |
417 |
} |
output_read = pdes[0]; |
418 |
|
output_write = pdes[1]; |
419 |
|
} else if (i == p->ncommands - 1 && p->want_out > 0) |
420 |
|
output_write = p->want_out; |
421 |
|
|
422 |
pid = fork (); |
pid = fork (); |
423 |
if (pid < 0) |
if (pid < 0) |
426 |
/* child */ |
/* child */ |
427 |
pop_all_cleanups (); |
pop_all_cleanups (); |
428 |
|
|
429 |
|
/* input, reading side */ |
430 |
if (last_input != -1) { |
if (last_input != -1) { |
431 |
if (close (0) < 0) |
if (close (0) < 0) |
432 |
error (FATAL, errno, |
error (FATAL, errno, |
438 |
_("close failed")); |
_("close failed")); |
439 |
} |
} |
440 |
|
|
441 |
if (i != p->ncommands - 1 || p->want_out) { |
/* output, writing side */ |
442 |
|
if (output_write != -1) { |
443 |
if (close (1) < 0) |
if (close (1) < 0) |
444 |
error (FATAL, errno, |
error (FATAL, errno, |
445 |
_("close failed")); |
_("close failed")); |
446 |
if (dup (pdes[1]) < 0) |
if (dup (output_write) < 0) |
447 |
error (FATAL, errno, _("dup failed")); |
error (FATAL, errno, _("dup failed")); |
448 |
if (close (pdes[1]) < 0) |
if (close (output_write) < 0) |
449 |
error (FATAL, errno, |
error (FATAL, errno, |
450 |
_("close failed")); |
_("close failed")); |
451 |
if (close (pdes[0])) |
} |
452 |
|
|
453 |
|
/* output, reading side */ |
454 |
|
if (output_read != -1) |
455 |
|
if (close (output_read)) |
456 |
error (FATAL, errno, |
error (FATAL, errno, |
457 |
_("close failed")); |
_("close failed")); |
|
} |
|
458 |
|
|
459 |
|
/* input from first command, writing side; must close |
460 |
|
* it in every child because it has to be created |
461 |
|
* before forking anything |
462 |
|
*/ |
463 |
if (p->infd != -1) |
if (p->infd != -1) |
464 |
close (p->infd); |
if (close (p->infd)) |
465 |
|
error (FATAL, errno, |
466 |
|
_("close failed")); |
467 |
|
|
468 |
if (p->commands[i]->nice) |
if (p->commands[i]->nice) |
469 |
nice (p->commands[i]->nice); |
nice (p->commands[i]->nice); |
478 |
if (close (last_input) < 0) |
if (close (last_input) < 0) |
479 |
error (FATAL, errno, _("close failed")); |
error (FATAL, errno, _("close failed")); |
480 |
} |
} |
481 |
if (i != p->ncommands - 1 || p->want_out) { |
if (output_write != -1) { |
482 |
if (close (pdes[1]) < 0) |
if (close (output_write) < 0) |
483 |
error (FATAL, errno, _("close failed")); |
error (FATAL, errno, _("close failed")); |
|
last_input = pdes[0]; |
|
484 |
} |
} |
485 |
|
if (output_read != -1) |
486 |
|
last_input = output_read; |
487 |
p->pids[i] = pid; |
p->pids[i] = pid; |
488 |
} |
} |
489 |
} |
} |
491 |
/* TODO: Perhaps it would be useful to wait on multiple pipelines |
/* TODO: Perhaps it would be useful to wait on multiple pipelines |
492 |
* simultaneously? Then you could do: |
* simultaneously? Then you could do: |
493 |
* |
* |
494 |
* p1->want_out = 1; |
* p1->want_out = -1; |
495 |
* p2->want_in = 1; |
* p2->want_in = -1; |
496 |
* p3->want_in = 1; |
* p3->want_in = -1; |
497 |
* pipeline_start (p1); |
* pipeline_start (p1); |
498 |
* pipeline_start (p2); |
* pipeline_start (p2); |
499 |
* pipeline_start (p3); |
* pipeline_start (p3); |