#define _GNU_SOURCE #include #include #include #include #include #include #include char buf[128*1024]; int main(int argc, char *argv[]) { if( 2 > argc ){ fprintf(stderr, "Read stdin into a memfd reservoir file and use this as stdin for a subsequently executed command.\n" "usage: %s \n", (argc ? argv[0] : "rsvr") ); return EXIT_FAILURE; } int rsvr_fd = memfd_create("reservoiur", MFD_CLOEXEC); if( 0 > rsvr_fd ){ perror("memfd_create('reservoiur', MFD_CLOEXEC)"); return EXIT_FAILURE; } ssize_t rb = 0, wb = 0; do { rb = read(0, buf, sizeof(buf)); if( 0 >= rb ){ continue; } for( ssize_t cb = 0 ; 0 <= wb && (cb < rb) ; cb += ((0 < wb) ? wb : 0) ){ wb = write(rsvr_fd, (buf+cb), (rb-cb)); if( (0 > wb) && (EINTR == errno) ){ wb = 0; } } } while( (0 < rb) || (0 > rb) && EINTR == errno ); if( 0 > rb ){ perror("read(stdin)"); } if( 0 > wb ){ perror("write(reservoir)"); } if( 0 > rb || 0 > wb ){ return EXIT_FAILURE; } if( 0 > dup2(rsvr_fd, 0) ){ perror("dup2(reservoir, stdin)"); return EXIT_FAILURE; } close(rsvr_fd); memmove(argv, argv+1, sizeof(*argv)*(argc-1)); argv[argc-1] = NULL; if( 0 > execvp(argv[0], argv) ){ perror("exec(...)"); } return EXIT_FAILURE; }