We have modified the tee
program with your suggestions from the previous pull request. Did I implement well? I would like to optimize the program even more, what else could I improve? What other possible issues are being implemented?
previous question Implementation of the "tee" utility program
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include "apue.h"
int writeAll(int fd, char *buf, int buflen) {
ssize_t written = 0;
while(written < buflen) {
int writtenThisTime = write(fd, buf + written, buflen - written);
if (writtenThisTime < 0) {
return writtenThisTime;
}
written = written + writtenThisTime;
}
return written;
}
int main(int argc, char* argv[])
{
int option;
bool append = false;
int errCode = 0;
while((option=getopt(argc,argv,"a"))!=-1) {
switch(option)
{
case 'a':
append = true;
break;
}
}
// We need to write in all the files given as parameter AND stdout.
int numFileDescriptors = argc - optind + 1;
int *fileDescriptors = malloc((numFileDescriptors) * sizeof(*fileDescriptors));
if (fileDescriptors == NULL) {
err_msg("Memory allocation failed");
return 1;
}
char **fileNames = malloc((numFileDescriptors) * sizeof(*fileNames));
if (fileNames == NULL) {
err_msg("Memory allocation failed");
return 1;
}
int lastFileDescriptor = 0;
fileDescriptors[0] = STDOUT_FILENO;
fileNames[0] = "stdout";
int flags = O_CREAT | O_WRONLY;
flags |= (append) ? O_APPEND : O_TRUNC;
for(int i=optind; i < argc; i++) {
int fd = open(argv[i], flags, 0644);
if (fd < 0) {
err_msg("%s: %s", argv[i], strerror(errno));
errCode = 1;
continue;
}
lastFileDescriptor++;
fileDescriptors[lastFileDescriptor] = fd;
fileNames[lastFileDescriptor] = argv[i];
}
while(true) {
char line[MAXLINE];
size_t len = 0;
int c;
while (len < sizeof(line) && ((c = getchar()) != EOF)) {
if ((line[len++] = c) == '\n')
break;
}
for(int i=0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, len);
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
return 1;
}
}
if (c == EOF)
break;
}
for(int i=0; i <= lastFileDescriptor; i++) {
close(fileDescriptors[i]);
}
free(fileDescriptors);
free(fileNames);
return errCode;
}
Update: a small question About what @pacmaninbw said. Possible reported bug:"you don't want to enter the following loop if the variable errCode is already set.."
I failed to reply to an error in this case. What I tried was to reduce the permissions on a file while using the tee. Example:
terminal 1:
tee file1.txt file2.txt
some input
terminal 2:
chmod 000 file1.txt
1 (still in tee):
some input 2
Close tee (no error).
chmod 664 file1.txt
diff file1.txt file2.txt
At diff, the files are identical.
man tee
indicates the following ways in which errors can be treated:
MODE determines behavior with write errors on the outputs:
'warn' diagnose errors writing to any output
'warn-nopipe'
diagnose errors writing to any output not a pipe
'exit' exit on error writing to any output
'exit-nopipe'
exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'. The default oper‐
ation when --output-error is not specified, is to exit immediately on
error writing to a pipe, and diagnose errors writing to non pipe out‐
puts.
Is it ok to implement the exit
mode (the simplest) in which error is returned if any write fails?