aboutsummaryrefslogtreecommitdiff
path: root/src/rsvr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rsvr.c')
-rw-r--r--src/rsvr.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/rsvr.c b/src/rsvr.c
new file mode 100644
index 0000000..01fa845
--- /dev/null
+++ b/src/rsvr.c
@@ -0,0 +1,60 @@
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+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 <command and argument>\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;
+}