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