Finito con {{{tee}}}, spostati un po' di TODO, messo il placeholder
[gapil.git] / listati / tee.c
diff --git a/listati/tee.c b/listati/tee.c
new file mode 100644 (file)
index 0000000..51df9f6
--- /dev/null
@@ -0,0 +1,60 @@
+#define _GNU_SOURCE
+#include <fcntl.h>       /* file control functions */
+...
+int main(int argc, char *argv[])
+{
+    size_t size = 4096;
+    int fd, len, nwrite;
+    struct stat fdata;
+    ...
+    /* check argument, open destination file and check stdin and stdout */
+    if ((argc - optind) != 1) { /* There must be one argument */
+        printf("Wrong number of arguments %d\n", argc - optind);
+        usage();
+    }
+    fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd == -1) {
+        printf("opening file %s falied: %s", argv[1], strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+    if (fstat(STDIN_FILENO, &fdata) < 0) {
+       perror("cannot stat stdin");
+       exit(EXIT_FAILURE);
+    }
+    if (!S_ISFIFO(fdata.st_mode)) {
+       fprintf(stderr, "stdin must be a pipe\n");
+       exit(EXIT_FAILURE);
+    }
+    if (fstat(STDOUT_FILENO, &fdata) < 0) {
+       perror("cannot stat stdout");
+       exit(EXIT_FAILURE);
+    }
+    if (!S_ISFIFO(fdata.st_mode)) {
+       fprintf(stderr, "stdout must be a pipe\n");
+       exit(EXIT_FAILURE);
+    }
+    /* tee loop */
+    while (1) {
+        /* copy stdin to stdout */
+        len = tee(STDIN_FILENO, STDOUT_FILENO, size, SPLICE_F_NONBLOCK);
+       if (len == 0) break;
+        if (len < 0) {
+            if (errno == EAGAIN) {
+               continue;
+           } else {
+               perror("error on tee stdin to stdout");
+               exit(EXIT_FAILURE);
+           }
+       }
+        /* write data to the file using splice */
+        while (len > 0) {
+            nwrite = splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE);
+            if (nwrite < 0) {
+                perror("error on splice stdin to file");
+                break;
+            }
+            len -= nwrite;
+        }
+    }
+    exit(EXIT_SUCCESS);
+}