[PATCH] ktee-net: Add ktee-net
authorJens Axboe <axboe@suse.de>
Thu, 20 Apr 2006 13:26:06 +0000 (15:26 +0200)
committerJens Axboe <axboe@suse.de>
Thu, 20 Apr 2006 13:26:06 +0000 (15:26 +0200)
This dupes data from stdin to a network host and stdout.

Makefile
ktee-net.c [new file with mode: 0755]
ktee.c

index e820dce07bc6b3a57ba612056ee4e7e6e735a731..29d76a4cdc6374ea36d2273ea57d4a1b6f2a8bd4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CC     = gcc
 CFLAGS = -Wall -O2 -g -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-PROGS  = ktee splice-cp splice-in splice-out splice-net splice-test4c splice-test4s
+PROGS  = ktee ktee-net splice-cp splice-in splice-out splice-net splice-test4c splice-test4s
 
 all: depend $(PROGS)
 
diff --git a/ktee-net.c b/ktee-net.c
new file mode 100755 (executable)
index 0000000..e2ebde0
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * A tee implementation using sys_tee. Sends out the data received over
+ * stdin to the given host:port and over stdout.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "splice.h"
+
+static int do_splice(int infd, int outfd, unsigned int len, char *msg)
+{
+       while (len) {
+               int written = splice(infd, NULL, outfd, NULL, len, 0);
+
+               if (written <= 0)
+                       return error(msg);
+
+               len -= written;
+       }
+
+       return 0;
+}
+
+static int usage(char *name)
+{
+       fprintf(stderr, "%s: hostname:port\n", name);
+       return 1;
+}
+
+int main(int argc, char *argv[])
+{
+       struct sockaddr_in addr;
+       char *p, *hname;
+       struct stat sb;
+       int fd;
+
+       if (argc < 2)
+               return usage(argv[0]);
+
+       if (fstat(STDIN_FILENO, &sb) < 0)
+               return error("stat");
+       if (!S_ISFIFO(sb.st_mode)) {
+               fprintf(stderr, "stdin must be a pipe\n");
+               return 1;
+       }
+
+       hname = strdup(argv[1]);
+       p = strstr(hname, ":");
+       if (!p)
+               return usage(argv[0]);
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(atoi(p + 1));
+       *p = '\0';
+
+       if (inet_aton(hname, &addr.sin_addr) != 1) {
+               struct hostent *hent = gethostbyname(hname);
+
+               if (!hent)
+                       return error("gethostbyname");
+
+               memcpy(&addr.sin_addr, hent->h_addr, 4);
+       }
+
+       fd = socket(AF_INET, SOCK_STREAM, 0);
+       if (fd < 0)
+               return error("socket");
+
+       fprintf(stderr, "connecting to %s, port %x\n", hname, addr.sin_port);
+
+       if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+               return error("connect");
+
+       do {
+               int tee_len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
+
+               if (tee_len < 0) {
+                       if (errno == EAGAIN) {
+                               usleep(1000);
+                               continue;
+                       }
+                       return error("tee");
+               } else if (!tee_len)
+                       break;
+
+               /*
+                * Send output to file, also consumes input pipe.
+                */
+               if (do_splice(STDIN_FILENO, fd, tee_len, "splice-net"))
+                       break;
+       } while (1);
+
+       close(fd);
+       return 0;
+}
diff --git a/ktee.c b/ktee.c
index 7b05361170c2d522e8344a14ce22a83d27813cb6..1b934d58cfcc68f8b7f169d609f0cf519fca97e9 100644 (file)
--- a/ktee.c
+++ b/ktee.c
@@ -1,9 +1,6 @@
 /*
- * A tee implementation using sys_tee. If only one argument is given,
- * stdin output is stored in that file and sent to stdout as well. If a
- * second argument is given, that must be in the form if host:port - in
- * that case, output is stored in file and sent over the network to the
- * given host at given port.
+ * A tee implementation using sys_tee. Stores stdin input in the given file
+ * and duplicates that to stdout.
  */
 #include <stdio.h>
 #include <stdlib.h>