1 /* tee - read from standard input and write to standard output and files.
2 Copyright (C) 1985-2023 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Mike Parker, Richard M. Stallman, and David MacKenzie */
20 #include <sys/types.h>
29 #include "xbinary-io.h"
32 /* The official name of this program (e.g., no 'g' prefix). */
33 #define PROGRAM_NAME "tee"
36 proper_name ("Mike Parker"), \
37 proper_name ("Richard M. Stallman"), \
38 proper_name ("David MacKenzie")
40 static bool tee_files (int nfiles
, char **files
, bool);
42 /* If true, append to output files rather than truncating them. */
45 /* If true, ignore interrupts. */
46 static bool ignore_interrupts
;
50 output_error_sigpipe
, /* traditional behavior, sigpipe enabled. */
51 output_error_warn
, /* warn on EPIPE, but continue. */
52 output_error_warn_nopipe
, /* ignore EPIPE, continue. */
53 output_error_exit
, /* exit on any output error. */
54 output_error_exit_nopipe
/* exit on any output error except EPIPE. */
57 static enum output_error output_error
;
59 static struct option
const long_options
[] =
61 {"append", no_argument
, nullptr, 'a'},
62 {"ignore-interrupts", no_argument
, nullptr, 'i'},
63 {"output-error", optional_argument
, nullptr, 'p'},
64 {GETOPT_HELP_OPTION_DECL
},
65 {GETOPT_VERSION_OPTION_DECL
},
66 {nullptr, 0, nullptr, 0}
69 static char const *const output_error_args
[] =
71 "warn", "warn-nopipe", "exit", "exit-nopipe", nullptr
73 static enum output_error
const output_error_types
[] =
75 output_error_warn
, output_error_warn_nopipe
,
76 output_error_exit
, output_error_exit_nopipe
78 ARGMATCH_VERIFY (output_error_args
, output_error_types
);
83 if (status
!= EXIT_SUCCESS
)
87 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
89 Copy standard input to each FILE, and also to standard output.\n\
91 -a, --append append to the given FILEs, do not overwrite\n\
92 -i, --ignore-interrupts ignore interrupt signals\n\
95 -p operate in a more appropriate MODE with pipes.\n\
96 --output-error[=MODE] set behavior on write error. See MODE below\n\
98 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
99 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
102 MODE determines behavior with write errors on the outputs:\n\
103 warn diagnose errors writing to any output\n\
104 warn-nopipe diagnose errors writing to any output not a pipe\n\
105 exit exit on error writing to any output\n\
106 exit-nopipe exit on error writing to any output not a pipe\n\
107 The default MODE for the -p option is 'warn-nopipe'.\n\
108 With \"nopipe\" MODEs, exit immediately if all outputs become broken pipes.\n\
109 The default operation when --output-error is not specified, is to\n\
110 exit immediately on error writing to a pipe, and diagnose errors\n\
111 writing to non pipe outputs.\n\
113 emit_ancillary_info (PROGRAM_NAME
);
119 main (int argc
, char **argv
)
121 initialize_main (&argc
, &argv
);
122 set_program_name (argv
[0]);
123 setlocale (LC_ALL
, "");
124 bindtextdomain (PACKAGE
, LOCALEDIR
);
125 textdomain (PACKAGE
);
127 atexit (close_stdout
);
130 ignore_interrupts
= false;
133 while ((optc
= getopt_long (argc
, argv
, "aip", long_options
, nullptr)) != -1)
142 ignore_interrupts
= true;
147 output_error
= XARGMATCH ("--output-error", optarg
,
148 output_error_args
, output_error_types
);
150 output_error
= output_error_warn_nopipe
;
153 case_GETOPT_HELP_CHAR
;
155 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
158 usage (EXIT_FAILURE
);
162 if (ignore_interrupts
)
163 signal (SIGINT
, SIG_IGN
);
165 if (output_error
!= output_error_sigpipe
)
166 signal (SIGPIPE
, SIG_IGN
);
168 /* Whether to detect and close a broken pipe output.
169 There is no need if the input is always ready for reading. */
170 bool pipe_check
= ((output_error
== output_error_warn_nopipe
171 || output_error
== output_error_exit_nopipe
)
172 && iopoll_input_ok (STDIN_FILENO
));
174 /* Do *not* warn if tee is given no file arguments.
175 POSIX requires that it work when given no arguments. */
177 bool ok
= tee_files (argc
- optind
, &argv
[optind
], pipe_check
);
178 if (close (STDIN_FILENO
) != 0)
179 error (EXIT_FAILURE
, errno
, "%s", _("standard input"));
181 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;
185 /* Return the index of the first non-null descriptor after idx,
186 or -1 if all are null. */
189 get_next_out (FILE **descriptors
, int nfiles
, int idx
)
191 for (idx
++; idx
<= nfiles
; idx
++)
192 if (descriptors
[idx
])
194 return -1; /* no outputs remaining */
197 /* Remove descriptors[i] due to write failure or broken pipe.
198 Return true if this indicates a reportable error. */
201 fail_output (FILE **descriptors
, char **files
, int i
)
204 bool fail
= errno
!= EPIPE
205 || output_error
== output_error_exit
206 || output_error
== output_error_warn
;
207 if (descriptors
[i
] == stdout
)
208 clearerr (stdout
); /* Avoid redundant close_stdout diagnostic. */
211 error (output_error
== output_error_exit
212 || output_error
== output_error_exit_nopipe
,
213 w_errno
, "%s", quotef (files
[i
]));
215 descriptors
[i
] = nullptr;
220 /* Copy the standard input into each of the NFILES files in FILES
221 and into the standard output. As a side effect, modify FILES[-1].
222 Return true if successful. */
225 tee_files (int nfiles
, char **files
, bool pipe_check
)
227 size_t n_outputs
= 0;
229 bool *out_pollable
IF_LINT ( = nullptr);
231 ssize_t bytes_read
= 0;
233 int first_out
= 0; /* idx of first non-null output in descriptors */
235 char const *mode_string
=
237 ? (append
? "ab" : "wb")
238 : (append
? "a" : "w"));
240 xset_binary_mode (STDIN_FILENO
, O_BINARY
);
241 xset_binary_mode (STDOUT_FILENO
, O_BINARY
);
242 fadvise (stdin
, FADVISE_SEQUENTIAL
);
244 /* Set up FILES[0 .. NFILES] and DESCRIPTORS[0 .. NFILES].
245 In both arrays, entry 0 corresponds to standard output. */
247 descriptors
= xnmalloc (nfiles
+ 1, sizeof *descriptors
);
249 out_pollable
= xnmalloc (nfiles
+ 1, sizeof *out_pollable
);
251 descriptors
[0] = stdout
;
253 out_pollable
[0] = iopoll_output_ok (fileno (descriptors
[0]));
254 files
[0] = bad_cast (_("standard output"));
255 setvbuf (stdout
, nullptr, _IONBF
, 0);
258 for (i
= 1; i
<= nfiles
; i
++)
260 /* Do not treat "-" specially - as mandated by POSIX. */
261 descriptors
[i
] = fopen (files
[i
], mode_string
);
262 if (descriptors
[i
] == nullptr)
265 out_pollable
[i
] = false;
266 error (output_error
== output_error_exit
267 || output_error
== output_error_exit_nopipe
,
268 errno
, "%s", quotef (files
[i
]));
274 out_pollable
[i
] = iopoll_output_ok (fileno (descriptors
[i
]));
275 setvbuf (descriptors
[i
], nullptr, _IONBF
, 0);
282 if (pipe_check
&& out_pollable
[first_out
])
284 /* Monitor for input, or errors on first valid output. */
285 int err
= iopoll (STDIN_FILENO
, fileno (descriptors
[first_out
]),
288 /* Close the output if it became a broken pipe. */
289 if (err
== IOPOLL_BROKEN_OUTPUT
)
291 errno
= EPIPE
; /* behave like write produced EPIPE */
292 if (fail_output (descriptors
, files
, first_out
))
295 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
298 else if (err
== IOPOLL_ERROR
)
300 error (0, errno
, _("iopoll error"));
305 bytes_read
= read (STDIN_FILENO
, buffer
, sizeof buffer
);
306 if (bytes_read
< 0 && errno
== EINTR
)
311 /* Write to all NFILES + 1 descriptors.
312 Standard output is the first one. */
313 for (i
= 0; i
<= nfiles
; i
++)
315 && ! fwrite_wait (buffer
, bytes_read
, descriptors
[i
]))
317 if (fail_output (descriptors
, files
, i
))
321 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
325 if (bytes_read
== -1)
327 error (0, errno
, _("read error"));
331 /* Close the files, but not standard output. */
332 for (i
= 1; i
<= nfiles
; i
++)
333 if (descriptors
[i
] && ! fclose_wait (descriptors
[i
]))
335 error (0, errno
, "%s", quotef (files
[i
]));