summaryrefslogtreecommitdiffstats
path: root/man2/tee.2
diff options
context:
space:
mode:
Diffstat (limited to 'man2/tee.2')
-rw-r--r--man2/tee.2199
1 files changed, 199 insertions, 0 deletions
diff --git a/man2/tee.2 b/man2/tee.2
new file mode 100644
index 0000000..7a3a6b1
--- /dev/null
+++ b/man2/tee.2
@@ -0,0 +1,199 @@
+.\" This manpage is Copyright (C) 2006 Jens Axboe
+.\" and Copyright (C) 2006 Michael Kerrisk <mtk.manpages@gmail.com>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH tee 2 2023-05-03 "Linux man-pages 6.05.01"
+.SH NAME
+tee \- duplicating pipe content
+.SH LIBRARY
+Standard C library
+.RI ( libc ", " \-lc )
+.SH SYNOPSIS
+.nf
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include <fcntl.h>
+.PP
+.BI "ssize_t tee(int " fd_in ", int " fd_out ", size_t " len \
+", unsigned int " flags );
+.fi
+.\" Return type was long before glibc 2.7
+.SH DESCRIPTION
+.\" Example programs http://brick.kernel.dk/snaps
+.\"
+.\"
+.\" add a "tee(in, out1, out2)" system call that duplicates the pages
+.\" (again, incrementing their reference count, not copying the data) from
+.\" one pipe to two other pipes.
+.BR tee ()
+duplicates up to
+.I len
+bytes of data from the pipe referred to by the file descriptor
+.I fd_in
+to the pipe referred to by the file descriptor
+.IR fd_out .
+It does not consume the data that is duplicated from
+.IR fd_in ;
+therefore, that data can be copied by a subsequent
+.BR splice (2).
+.PP
+.I flags
+is a bit mask that is composed by ORing together
+zero or more of the following values:
+.TP 1.9i
+.B SPLICE_F_MOVE
+Currently has no effect for
+.BR tee ();
+see
+.BR splice (2).
+.TP
+.B SPLICE_F_NONBLOCK
+Do not block on I/O; see
+.BR splice (2)
+for further details.
+.TP
+.B SPLICE_F_MORE
+Currently has no effect for
+.BR tee (),
+but may be implemented in the future; see
+.BR splice (2).
+.TP
+.B SPLICE_F_GIFT
+Unused for
+.BR tee ();
+see
+.BR vmsplice (2).
+.SH RETURN VALUE
+Upon successful completion,
+.BR tee ()
+returns the number of bytes that were duplicated between the input
+and output.
+A return value of 0 means that there was no data to transfer,
+and it would not make sense to block, because there are no
+writers connected to the write end of the pipe referred to by
+.IR fd_in .
+.PP
+On error,
+.BR tee ()
+returns \-1 and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EAGAIN
+.B SPLICE_F_NONBLOCK
+was specified in
+.I flags
+or one of the file descriptors had been marked as nonblocking
+.RB ( O_NONBLOCK ) ,
+and the operation would block.
+.TP
+.B EINVAL
+.I fd_in
+or
+.I fd_out
+does not refer to a pipe; or
+.I fd_in
+and
+.I fd_out
+refer to the same pipe.
+.TP
+.B ENOMEM
+Out of memory.
+.SH STANDARDS
+Linux.
+.SH HISTORY
+Linux 2.6.17,
+glibc 2.5.
+.SH NOTES
+Conceptually,
+.BR tee ()
+copies the data between the two pipes.
+In reality no real data copying takes place though:
+under the covers,
+.BR tee ()
+assigns data to the output by merely grabbing
+a reference to the input.
+.SH EXAMPLES
+The example below implements a basic
+.BR tee (1)
+program using the
+.BR tee ()
+system call.
+Here is an example of its use:
+.PP
+.in +4n
+.EX
+$ \fBdate | ./a.out out.log | cat\fP
+Tue Oct 28 10:06:00 CET 2014
+$ \fBcat out.log\fP
+Tue Oct 28 10:06:00 CET 2014
+.EE
+.in
+.SS Program source
+\&
+.\" SRC BEGIN (tee.c)
+.EX
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+\&
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ ssize_t len, slen;
+\&
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file>\en", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+\&
+ fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == \-1) {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+\&
+ for (;;) {
+ /*
+ * tee stdin to stdout.
+ */
+ len = tee(STDIN_FILENO, STDOUT_FILENO,
+ INT_MAX, SPLICE_F_NONBLOCK);
+ if (len < 0) {
+ if (errno == EAGAIN)
+ continue;
+ perror("tee");
+ exit(EXIT_FAILURE);
+ }
+ if (len == 0)
+ break;
+\&
+ /*
+ * Consume stdin by splicing it to a file.
+ */
+ while (len > 0) {
+ slen = splice(STDIN_FILENO, NULL, fd, NULL,
+ len, SPLICE_F_MOVE);
+ if (slen < 0) {
+ perror("splice");
+ exit(EXIT_FAILURE);
+ }
+ len \-= slen;
+ }
+ }
+\&
+ close(fd);
+ exit(EXIT_SUCCESS);
+}
+.EE
+.\" SRC END
+.SH SEE ALSO
+.BR splice (2),
+.BR vmsplice (2),
+.BR pipe (7)