@@ -60,12 +60,17 @@ static struct option long_options[] =
60
60
};
61
61
62
62
typedef struct pump_t {
63
+ struct pollfd * rpollfd ;
64
+ struct pollfd * wpollfd ;
63
65
void * base ;
64
66
size_t len ;
65
67
off_t offset ;
68
+ int rfd ;
69
+ int wfd ;
66
70
int read_closed :1 ;
67
71
int write_closed :1 ;
68
72
int exit_on_close :1 ;
73
+ int no_close :1 ;
69
74
int send_eof :1 ;
70
75
} pump_t ;
71
76
@@ -232,38 +237,44 @@ static int status_match(int status, const char *criteria)
232
237
return 1 ;
233
238
}
234
239
235
- static int pump (const char * name , pump_t * pumps , struct pollfd * fds )
240
+ static int pump (const char * name , pump_t * pumps )
236
241
{
237
- nfds_t nfds = PUMPS * 2 ;
238
242
int i ;
239
243
240
244
while (1 ) {
241
- int stay = 0 ;
245
+ nfds_t nfds = 0 ;
246
+ struct pollfd fds [PUMPS * 2 ] = { 0 };
242
247
243
248
for (i = 0 ; i < PUMPS ; i ++ ) {
244
249
245
- fds [ OFFSET ( i , READ_FD )]. events = 0 ;
246
- fds [ OFFSET ( i , WRITE_FD )]. events = 0 ;
250
+ pumps [ i ]. rpollfd = NULL ;
251
+ pumps [ i ]. wpollfd = NULL ;
247
252
248
253
if (!pumps [i ].read_closed ) {
249
- fds [OFFSET (i , READ_FD )].events = POLLIN ;
250
- stay = 1 ;
254
+ pumps [i ].rpollfd = fds + nfds ;
255
+ fds [nfds ].events = POLLIN ;
256
+ fds [nfds ].fd = pumps [i ].rfd ;
257
+ fds [nfds ].revents = 0 ;
258
+ nfds ++ ;
251
259
}
252
260
253
261
if (!pumps [i ].write_closed
254
262
&& (pumps [i ].send_eof || pumps [i ].len > pumps [i ].offset )) {
255
- fds [OFFSET (i , WRITE_FD )].events = POLLOUT ;
256
- stay = 1 ;
263
+ pumps [i ].wpollfd = fds + nfds ;
264
+ fds [nfds ].events = POLLOUT ;
265
+ fds [nfds ].fd = pumps [i ].wfd ;
266
+ fds [nfds ].revents = 0 ;
267
+ nfds ++ ;
257
268
}
258
269
259
270
if (pumps [i ].read_closed && pumps [i ].exit_on_close ) {
260
- stay = 0 ;
271
+ nfds = 0 ;
261
272
break ;
262
273
}
263
274
264
275
}
265
276
266
- if (!stay ) {
277
+ if (!nfds ) {
267
278
break ;
268
279
}
269
280
@@ -277,77 +288,88 @@ static int pump(const char *name, pump_t *pumps, struct pollfd *fds)
277
288
278
289
for (i = 0 ; i < PUMPS ; i ++ ) {
279
290
280
- if (fds [OFFSET (i , READ_FD )].revents & POLLIN ) {
281
- void * base ;
282
- ssize_t num ;
291
+ if (pumps [i ].rpollfd ) {
283
292
284
- base = realloc (pumps [i ].base , pumps [i ].len + BUFFER_SIZE );
285
- if (!base ) {
293
+ if (pumps [i ].rpollfd -> revents & POLLIN ) {
294
+ void * base ;
295
+ ssize_t num ;
286
296
287
- fprintf (stderr , "%s: Out of memory, giving up.\n" , name );
297
+ base = realloc (pumps [i ].base , pumps [i ].len + BUFFER_SIZE );
298
+ if (!base ) {
288
299
289
- return -1 ;
290
- }
291
- pumps [i ].base = base ;
300
+ fprintf (stderr , "%s: Out of memory, giving up.\n" ,
301
+ name );
302
+
303
+ return -1 ;
304
+ }
305
+ pumps [i ].base = base ;
306
+
307
+ num = read (pumps [i ].rfd , base + pumps [i ].len , BUFFER_SIZE );
292
308
293
- num = read ( fds [ OFFSET ( i , READ_FD )]. fd , base + pumps [ i ]. len , BUFFER_SIZE );
309
+ if ( num < 0 ) {
294
310
295
- if (num < 0 ) {
311
+ fprintf (stderr , "%s: Could not read, giving up: %s\n" ,
312
+ name , strerror (errno ));
296
313
297
- fprintf (stderr , "%s: Could not read, giving up: %s\n" , name ,
298
- strerror (errno ));
314
+ return -1 ;
315
+ } else if (num == 0 ) {
316
+ pumps [i ].read_closed = 1 ;
317
+ pumps [i ].send_eof = 1 ;
318
+ close (pumps [i ].rfd );
319
+ } else {
320
+ pumps [i ].len += num ;
321
+ }
299
322
300
- return -1 ;
301
323
}
302
- else if (num == 0 ) {
324
+
325
+ if ((pumps [i ].rpollfd -> revents & POLLHUP )
326
+ || (pumps [i ].rpollfd -> revents & POLLERR )
327
+ || (pumps [i ].rpollfd -> revents & POLLNVAL )) {
328
+
303
329
pumps [i ].read_closed = 1 ;
304
330
pumps [i ].send_eof = 1 ;
305
- }
306
- else {
307
- pumps [i ].len += num ;
331
+ close (pumps [i ].rfd );
332
+
308
333
}
309
334
310
335
}
311
336
312
- if ((fds [OFFSET (i , READ_FD )].revents & POLLHUP ) ||
313
- (fds [OFFSET (i , READ_FD )].revents & POLLERR ) ||
314
- (fds [OFFSET (i , READ_FD )].revents & POLLNVAL )) {
315
-
316
- pumps [i ].read_closed = 1 ;
317
- pumps [i ].send_eof = 1 ;
337
+ if (pumps [i ].wpollfd ) {
318
338
319
- }
339
+ if (pumps [i ].wpollfd -> revents & POLLOUT ) {
340
+ ssize_t num ;
320
341
321
- if ( fds [ OFFSET ( i , WRITE_FD )]. revents & POLLOUT ) {
322
- ssize_t num ;
342
+ num = write ( pumps [ i ]. wfd , pumps [ i ]. base + pumps [ i ]. offset ,
343
+ pumps [ i ]. len - pumps [ i ]. offset ) ;
323
344
324
- num = write (fds [OFFSET (i , WRITE_FD )].fd ,
325
- pumps [i ].base + pumps [i ].offset ,
326
- pumps [i ].len - pumps [i ].offset );
345
+ if (num < 0 ) {
327
346
328
- if (num < 0 ) {
347
+ fprintf (stderr , "%s: Could not write, giving up: %s\n" ,
348
+ name , strerror (errno ));
329
349
330
- fprintf (stderr , "%s: Could not write, giving up: %s\n" , name ,
331
- strerror (errno ));
350
+ return -1 ;
351
+ } else {
352
+ pumps [i ].offset += num ;
353
+ }
332
354
333
- return -1 ;
334
- }
335
- else {
336
- pumps [i ].offset += num ;
337
- }
355
+ if (pumps [i ].read_closed
356
+ && pumps [i ].offset == pumps [i ].len ) {
338
357
339
- if (pumps [i ].read_closed && pumps [i ].offset == pumps [i ].len ) {
358
+ pumps [i ].write_closed = 1 ;
359
+ close (pumps [i ].wfd );
340
360
341
- pumps [ i ]. write_closed = 1 ;
361
+ }
342
362
343
363
}
344
364
345
- }
365
+ if ((pumps [i ].wpollfd -> revents & POLLHUP )
366
+ || (pumps [i ].wpollfd -> revents & POLLERR )
367
+ || (pumps [i ].wpollfd -> revents & POLLNVAL )) {
346
368
347
- if (( fds [ OFFSET ( i , WRITE_FD )]. revents & POLLERR ) ||
348
- ( fds [ OFFSET ( i , WRITE_FD )]. revents & POLLNVAL )) {
369
+ pumps [ i ]. write_closed = 1 ;
370
+ close ( pumps [ i ]. wfd );
349
371
350
- pumps [ i ]. write_closed = 1 ;
372
+ }
351
373
352
374
}
353
375
@@ -476,18 +498,17 @@ int main (int argc, char **argv)
476
498
477
499
/* parent */
478
500
else {
479
- struct pollfd fds [PUMPS * 2 ];
480
501
481
502
/* handle stdin */
482
503
483
- fds [ OFFSET ( STDIN_FD , READ_FD )]. fd = STDIN_FD ;
484
- fds [ OFFSET ( STDIN_FD , WRITE_FD )]. fd = inpair [WRITE_FD ];
504
+ pumps [ STDIN_FD ]. rfd = dup ( STDIN_FD ) ;
505
+ pumps [ STDIN_FD ]. wfd = inpair [WRITE_FD ];
485
506
close (inpair [READ_FD ]);
486
507
487
508
/* handle stdout */
488
509
489
- fds [ OFFSET ( STDOUT_FD , READ_FD )]. fd = outpair [READ_FD ];
490
- fds [ OFFSET ( STDOUT_FD , WRITE_FD )]. fd = STDOUT_FD ;
510
+ pumps [ STDOUT_FD ]. rfd = outpair [READ_FD ];
511
+ pumps [ STDOUT_FD ]. wfd = dup ( STDOUT_FD ) ;
491
512
close (outpair [WRITE_FD ]);
492
513
493
514
/* prevent write to stdout, we will handle it later */
@@ -497,16 +518,19 @@ int main (int argc, char **argv)
497
518
pumps [STDOUT_FD ].exit_on_close = 1 ;
498
519
499
520
/* pump all data */
500
- if (pump (name , pumps , fds )) {
521
+ if (pump (name , pumps )) {
501
522
status = EXIT_FAILURE ;
502
523
break ;
503
524
}
504
525
505
526
close (inpair [WRITE_FD ]);
506
527
close (outpair [READ_FD ]);
528
+ close (pumps [STDIN_FD ].rfd );
529
+ close (pumps [STDOUT_FD ].wfd );
507
530
508
531
/* reset stdin in case we repeat the command */
509
532
pumps [STDIN_FD ].offset = 0 ;
533
+ pumps [STDIN_FD ].write_closed = 0 ;
510
534
511
535
/* wait for the child process to be done */
512
536
do {
@@ -543,6 +567,10 @@ int main (int argc, char **argv)
543
567
/* failure - write stdout to stderr */
544
568
fwrite (pumps [STDOUT_FD ].base , pumps [STDOUT_FD ].len , 1 , stderr );
545
569
570
+ /* reset stdout for a go-around */
571
+ free (pumps [STDOUT_FD ].base );
572
+ memset (& pumps [STDOUT_FD ], 0 , sizeof (pump_t ));
573
+
546
574
if (delay ) {
547
575
fprintf (stderr ,
548
576
"%s: '%s' returned %d, backing off for %ld second%s and trying again...\n" ,
0 commit comments