1 /* tee - read from standard input and write to standard output and files.
2 Copyright (C) 1985-2024 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. */
190 get_next_out (FILE **descriptors
, int nfiles
, int idx
)
192 for (idx
++; idx
<= nfiles
; idx
++)
193 if (descriptors
[idx
])
195 return -1; /* no outputs remaining */
198 /* Remove descriptors[i] due to write failure or broken pipe.
199 Return true if this indicates a reportable error. */
202 fail_output (FILE **descriptors
, char **files
, int i
)
205 bool fail
= errno
!= EPIPE
206 || output_error
== output_error_exit
207 || output_error
== output_error_warn
;
208 if (descriptors
[i
] == stdout
)
209 clearerr (stdout
); /* Avoid redundant close_stdout diagnostic. */
212 error (output_error
== output_error_exit
213 || output_error
== output_error_exit_nopipe
,
214 w_errno
, "%s", quotef (files
[i
]));
216 descriptors
[i
] = nullptr;
221 /* Copy the standard input into each of the NFILES files in FILES
222 and into the standard output. As a side effect, modify FILES[-1].
223 Return true if successful. */
226 tee_files (int nfiles
, char **files
, bool pipe_check
)
228 size_t n_outputs
= 0;
230 bool *out_pollable
IF_LINT ( = nullptr);
232 ssize_t bytes_read
= 0;
234 int first_out
= 0; /* idx of first non-null output in descriptors */
236 char const *mode_string
=
238 ? (append
? "ab" : "wb")
239 : (append
? "a" : "w"));
241 xset_binary_mode (STDIN_FILENO
, O_BINARY
);
242 xset_binary_mode (STDOUT_FILENO
, O_BINARY
);
243 fadvise (stdin
, FADVISE_SEQUENTIAL
);
245 /* Set up FILES[0 .. NFILES] and DESCRIPTORS[0 .. NFILES].
246 In both arrays, entry 0 corresponds to standard output. */
248 descriptors
= xnmalloc (nfiles
+ 1, sizeof *descriptors
);
250 out_pollable
= xnmalloc (nfiles
+ 1, sizeof *out_pollable
);
252 descriptors
[0] = stdout
;
254 out_pollable
[0] = iopoll_output_ok (fileno (descriptors
[0]));
255 files
[0] = bad_cast (_("standard output"));
256 setvbuf (stdout
, nullptr, _IONBF
, 0);
259 for (i
= 1; i
<= nfiles
; i
++)
261 /* Do not treat "-" specially - as mandated by POSIX. */
262 descriptors
[i
] = fopen (files
[i
], mode_string
);
263 if (descriptors
[i
] == nullptr)
266 out_pollable
[i
] = false;
267 error (output_error
== output_error_exit
268 || output_error
== output_error_exit_nopipe
,
269 errno
, "%s", quotef (files
[i
]));
275 out_pollable
[i
] = iopoll_output_ok (fileno (descriptors
[i
]));
276 setvbuf (descriptors
[i
], nullptr, _IONBF
, 0);
283 if (pipe_check
&& out_pollable
[first_out
])
285 /* Monitor for input, or errors on first valid output. */
286 int err
= iopoll (STDIN_FILENO
, fileno (descriptors
[first_out
]),
289 /* Close the output if it became a broken pipe. */
290 if (err
== IOPOLL_BROKEN_OUTPUT
)
292 errno
= EPIPE
; /* behave like write produced EPIPE */
293 if (fail_output (descriptors
, files
, first_out
))
296 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
299 else if (err
== IOPOLL_ERROR
)
301 error (0, errno
, _("iopoll error"));
306 bytes_read
= read (STDIN_FILENO
, buffer
, sizeof buffer
);
307 if (bytes_read
< 0 && errno
== EINTR
)
312 /* Write to all NFILES + 1 descriptors.
313 Standard output is the first one. */
314 for (i
= 0; i
<= nfiles
; i
++)
316 && ! fwrite_wait (buffer
, bytes_read
, descriptors
[i
]))
318 if (fail_output (descriptors
, files
, i
))
322 first_out
= get_next_out (descriptors
, nfiles
, first_out
);
326 if (bytes_read
== -1)
328 error (0, errno
, _("read error"));
332 /* Close the files, but not standard output. */
333 for (i
= 1; i
<= nfiles
; i
++)
334 if (descriptors
[i
] && ! fclose_wait (descriptors
[i
]))
336 error (0, errno
, "%s", quotef (files
[i
]));