--- /dev/null
+/*
+ * 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;
+}
/*
- * 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>