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>
31 #include "xbinary-io.h"
34 /* The official name of this program (e.g., no 'g' prefix). */
35 #define PROGRAM_NAME "tee"
38 proper_name ("Mike Parker"), \
39 proper_name ("Richard M. Stallman"), \
40 proper_name ("David MacKenzie")
42 static bool tee_files (int nfiles
, char **files
, bool);
44 /* If true, append to output files rather than truncating them. */
47 /* If true, ignore interrupts. */
48 static bool ignore_interrupts
;
52 output_error_sigpipe
, /* traditional behavior, sigpipe enabled. */
53 output_error_warn
, /* warn on EPIPE, but continue. */
54 output_error_warn_nopipe
, /* ignore EPIPE, continue. */
55 output_error_exit
, /* exit on any output error. */
56 output_error_exit_nopipe
/* exit on any output error except EPIPE. */
59 static enum output_error output_error
;
61 static struct option
const long_options
[] =
63 {"append", no_argument
, nullptr, 'a'},
64 {"ignore-interrupts", no_argument
, nullptr, 'i'},
65 {"output-error", optional_argument
, nullptr, 'p'},
66 {GETOPT_HELP_OPTION_DECL
},
67 {GETOPT_VERSION_OPTION_DECL
},
68 {nullptr, 0, nullptr, 0}
71 static char const *const output_error_args
[] =
73 "warn", "warn-nopipe", "exit", "exit-nopipe", nullptr
75 static enum output_error
const output_error_types
[] =
77 output_error_warn
, output_error_warn_nopipe
,
78 output_error_exit
, output_error_exit_nopipe
80 ARGMATCH_VERIFY (output_error_args
, output_error_types
);
85 if (status
!= EXIT_SUCCESS
)
89 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
91 Copy standard input to each FILE, and also to standard output.\n\
93 -a, --append append to the given FILEs, do not overwrite\n\
94 -i, --ignore-interrupts ignore interrupt signals\n\
97 -p operate in a more appropriate MODE with pipes.\n\
98 --output-error[=MODE] set behavior on write error. See MODE below\n\
100 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
101 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
104 MODE determines behavior with write errors on the outputs:\n\
105 warn diagnose errors writing to any output\n\
106 warn-nopipe diagnose errors writing to any output not a pipe\n\
107 exit exit on error writing to any output\n\
108 exit-nopipe exit on error writing to any output not a pipe\n\
109 The default MODE for the -p option is 'warn-nopipe'.\n\
110 With \"nopipe\" MODEs, exit immediately if all outputs become broken pipes.\n\
111 The default operation when --output-error is not specified, is to\n\
112 exit immediately on error writing to a pipe, and diagnose errors\n\
113 writing to non pipe outputs.\n\
115 emit_ancillary_info (PROGRAM_NAME
);
121 main (int argc
, char **argv
)
123 initialize_main (&argc
, &argv
);
124 set_program_name (argv
[0]);
125 setlocale (LC_ALL
, "");
126 bindtextdomain (PACKAGE
, LOCALEDIR
);
127 textdomain (PACKAGE
);
129 atexit (close_stdout
);
132 ignore_interrupts
= false;
135 while ((optc
= getopt_long (argc
, argv
, "aip", long_options
, nullptr)) != -1)
144 ignore_interrupts
= true;
149 output_error
= XARGMATCH ("--output-error", optarg
,
150 output_error_args
, output_error_types
);
152 output_error
= output_error_warn_nopipe
;
155 case_GETOPT_HELP_CHAR
;
157 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
160 usage (EXIT_FAILURE
);
164 if (ignore_interrupts
)
165 signal (SIGINT
, SIG_IGN
);
167 if (output_error
!= output_error_sigpipe
)
168 signal (SIGPIPE
, SIG_IGN
);
170 /* Whether to detect and close a broken pipe output.
171 There is no need if the input is always ready for reading. */
172 bool pipe_check
= ((output_error
== output_error_warn_nopipe
173 || output_error
== output_error_exit_nopipe
)
174 && iopoll_input_ok (STDIN_FILENO
));
176 /* Do *not* warn if tee is given no file arguments.
177 POSIX requires that it work when given no arguments. */
179 bool ok
= tee_files (argc
- optind
, &argv
[optind
], pipe_check
);
180 if (close (STDIN_FILENO
) != 0)
181 die (EXIT_FAILURE
, errno
, "%s", _("standard input"));
183 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;
187 /* Return the index of the first non-null descriptor after idx,
188 or -1 if all are null. */
191 get_next_out (FILE **descriptors
, int nfiles
, int idx
)
193 for (idx
++; idx
<= nfiles
; idx
++)
194 if (descriptors
[idx
])
196 return -1; /* no outputs remaining */
199 /* Remove descriptors[i] due to write failure or broken pipe.
200 Return true if this indicates a reportable error. */
203 fail_output (FILE **descriptors
, char **files
, int i
)
206 bool fail
= errno
!= EPIPE
207 || output_error
== output_error_exit
208 || output_error
== output_error_warn
;
209 if (descriptors
[i
] == stdout
)
210 clearerr (stdout
); /* Avoid redundant close_stdout diagnostic. */
213 error (output_error
== output_error_exit
214 || output_error
== output_error_exit_nopipe
,
215 w_errno
, "%s", quotef (files
[i
]));
217 descriptors
[i
] = nullptr;
222 /* Copy the standard input into each of the NFILES files in FILES
223 and into the standard output. As a side effect, modify FILES[-1].
224 Return true if successful. */
227 tee_files (int nfiles
, char **files
, bool pipe_check
)
229 size_t n_outputs
= 0;
231 bool *out_pollable
IF_LINT ( = nullptr);
233 ssize_t bytes_read
= 0;
235 int first_out
= 0; /* idx of first non-null output in descriptors */
237 char const *mode_string
=
239 ? (append
? "ab" : "wb")
240 : (append
? "a" : "w"));
242 xset_binary_mode (STDIN_FILENO
, O_BINARY
);
243 xset_binary_mode (STDOUT_FILENO
, O_BINARY
);
244 fadvise (stdin
, FADVISE_SEQUENTIAL
);
246 /* Set up FILES[0 .. NFILES] and DESCRIPTORS[0 .. NFILES].
247 In both arrays, entry 0 corresponds to standard output. */
249 descriptors
= xnmalloc (nfiles
+ 1, sizeof *descriptors
);
251 out_pollable
= xnmalloc (nfiles
+ 1, sizeof *out_pollable
);
253 descriptors
[0] = stdout
;
255 out_pollable
[0] = iopoll_output_ok (fileno (descriptors
[0]));
256 files
[0] = bad_cast (_("standard output"));
257 setvbuf (stdout
, nullptr, _IONBF
, 0);
260 for (i
= 1; i
<= nfiles
; i
++)
262 /* Do not treat "-" specially - as mandated by POSIX. */
263 descriptors
[i
] = fopen (files
[i
], mode_string
);
264 if (descriptors
[i
] == nullptr)
267 out_pollable
[i
] = false;
268 error (output_error
== output_error_exit
269 || output_error
== output_error_exit_nopipe
,
270 errno
, "%s", quotef (files
[i
]));
276 out_pollable
[i
] = iopoll_output_ok (fileno (descriptors
[i
]));
277 setvbuf (descriptors
[i
], nullptr, _IONBF
, 0);
284 if (pipe_check
&& out_pollable
[first_out
])
286 /* Monitor for input, or errors on first valid output. */
287 int err
= iopoll (STDIN_FILENO
, fileno (descriptors
[first_out
]),
290 /* Close the output if it became a broken pipe. */
291 if (err
== IOPOLL_BROKEN_OUTPUT
)
293 errno
= EPIPE
; /* behave like write produced EPIPE */
294 if (fail_output (descriptors
, files
, first_out
))
297 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
300 else if (err
== IOPOLL_ERROR
)
302 error (0, errno
, _("iopoll error"));
307 bytes_read
= read (STDIN_FILENO
, buffer
, sizeof buffer
);
308 if (bytes_read
< 0 && errno
== EINTR
)
313 /* Write to all NFILES + 1 descriptors.
314 Standard output is the first one. */
315 for (i
= 0; i
<= nfiles
; i
++)
317 && ! fwrite_wait (buffer
, bytes_read
, descriptors
[i
]))
319 if (fail_output (descriptors
, files
, i
))
323 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
327 if (bytes_read
== -1)
329 error (0, errno
, _("read error"));
333 /* Close the files, but not standard output. */
334 for (i
= 1; i
<= nfiles
; i
++)
335 if (descriptors
[i
] && ! fclose_wait (descriptors
[i
]))
337 error (0, errno
, "%s", quotef (files
[i
]));