| 228 | Return true if successful. */ |
| 229 | |
| 230 | static bool |
| 231 | tee_files (int nfiles, char **files, bool pipe_check) |
| 232 | { |
| 233 | size_t n_outputs = 0; |
| 234 | int *descriptors; |
| 235 | bool *out_pollable IF_LINT ( = NULL); |
| 236 | char buffer[BUFSIZ]; |
| 237 | ssize_t bytes_read = 0; |
| 238 | int first_out = 0; /* idx of first non-null output in descriptors */ |
| 239 | bool ok = true; |
| 240 | int flags = O_WRONLY | O_CREAT | O_BINARY | (append ? O_APPEND : O_TRUNC); |
| 241 | |
| 242 | xset_binary_mode (STDIN_FILENO, O_BINARY); |
| 243 | xset_binary_mode (STDOUT_FILENO, O_BINARY); |
| 244 | fadvise (stdin, FADVISE_SEQUENTIAL); |
| 245 | |
| 246 | /* Set up FILES[0 .. NFILES] and DESCRIPTORS[0 .. NFILES]. |
| 247 | In both arrays, entry 0 corresponds to standard output. */ |
| 248 | |
| 249 | descriptors = xnmalloc (nfiles + 1, sizeof *descriptors); |
| 250 | if (pipe_check) |
| 251 | out_pollable = xnmalloc (nfiles + 1, sizeof *out_pollable); |
| 252 | files--; |
| 253 | descriptors[0] = STDOUT_FILENO; |
| 254 | if (pipe_check) |
| 255 | out_pollable[0] = iopoll_output_ok (descriptors[0]); |
| 256 | files[0] = bad_cast (_("standard output")); |
| 257 | n_outputs++; |
| 258 | |
| 259 | for (int i = 1; i <= nfiles; i++) |
| 260 | { |
| 261 | /* Do not treat "-" specially - as mandated by POSIX. */ |
| 262 | descriptors[i] = open (files[i], flags, MODE_RW_UGO); |
| 263 | if (descriptors[i] < 0) |
| 264 | { |
| 265 | if (pipe_check) |
| 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])); |
| 270 | ok = false; |
| 271 | } |
| 272 | else |
| 273 | { |
| 274 | if (pipe_check) |
| 275 | out_pollable[i] = iopoll_output_ok (descriptors[i]); |
| 276 | n_outputs++; |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | while (n_outputs) |
| 281 | { |
| 282 | if (pipe_check && out_pollable[first_out]) |
| 283 | { |
| 284 | /* Monitor for input, or errors on first valid output. */ |
| 285 | int err = iopoll (STDIN_FILENO, descriptors[first_out], true); |
| 286 | |
| 287 | /* Close the output if it became a broken pipe. */ |
no test coverage detected