[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]
Summary
tee - redirect output to multiple files or processes
Lines of code: 279
Principal syscall: fopen()
Support syscalls: fwrite(), fadvise()
Options: 8 (3 short, 5 long)
Descended from tee introduced in Version 5 UNIX (1974)
Added to Shellutils in November 1992 [First version]
Number of revisions: 131
tee_files()
- Performs the tee operation on the given file list
die()
- Exit with mandatory non-zero error and message to stderrerror()
- Outputs error message to standard error with possible process termination
Setup
tee sets up the options and argument values at global scope. It also declares operating mode flags including:
append
- Flag for appending output (-a)ignore_interrupts
- Flag to mask interrupts(-i)
main() defines two local variables:
ok
- Tracks the status results of the operationoptc
- The next option character to process
Parsing begins with the short options passed as a string literal:
"aip"
Parsing
The tee
utility needs the user to answer these questions:
- Should I/O append or overwrite?
- How should interrupts be handled?
- How should errors be handled?
Parsing failures
The only parsing error explicitly check is if an unknown option is used. The result is a short error message followed by the usage instructions.
Execution
The tee
execution path follows the aniticapted flow: Open targets, read standard input, write to all outputs (and STDIO). Close targets afterward.
There are a few more considerations. Consider this more detailed flow that picks up after parsing:
- If the user chose to ignore interrupts, replace the default hander -
signal (SIGINT, SIG_IGN);
- In most cases, the user won't want default SIGPIPE behavior so ignore -
signal (SIGPIPE, SIG_IGN);
- Open each target file with no buffering
- While STDIN has more data to read...
-
- Read in data to a buffer
- Write that data to each target, checking for failures
- Close all target files
The tee utility may fail in several ways. An EXIT_FAILURE status indicates a failure of tee, while EXIT_ENOENT or EXIT_CANNOT_INVOKE points to a problem with the target command.
Failure cases:
- STDIN did not close properly
- Unable to open a target
- Unable to read data in from STDIN
- A write error occurs as requested by the user
- Unable to close a target
All failures at this stage output an error message to STDERR and return without displaying usage help