Skip to main content
1 of 7
Mike
  • 319
  • 1
  • 5

program that reads standard input, then writes its contents to standard output (`-a` option to add data to files)

How can I optimize the program? To make it more optimal? The program should be more optimal in terms of source code, compiled executable size, memory usage, speed, bugs etc. Please criticize the program from these points of view. The -a option adds text to the end of a file (if it exists). The program clones the tee functionality that reads the standard input, and then writes its contents to the standard output. The program clones the tee functionality that reads the standard input, and then writes its contents to the standard output.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "apue.h"

int writeAll(int fd, char *buf, int buflen);

int main(int argc, char* argv[])
{
    struct stat status;
    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 = (int *)malloc((numFileDescriptors + 1) * sizeof(int));
    char **fileNames = (char **)malloc((numFileDescriptors + 1) * sizeof(char *));

    int lastFileDescriptor = 0;
    fileDescriptors[0] = STDOUT_FILENO;
    fileNames[0] = "stdout";

    int flags = O_CREAT | O_WRONLY;
    if (append) {
        flags = flags | O_APPEND;
    } else {
        flags = flags | O_TRUNC;
    }

    for(int i=optind; i < argc; i++) {
        if (access(argv[i], F_OK) == 0) {
            if (access(argv[i], W_OK) < 0) {
                err_msg("%s: Permission denied", argv[i]);
                errCode = 1;
                continue;
            }
        }

        if (lstat(argv[i],&status) < 0) {
            status.st_mode=0;
        }

        if(S_ISDIR(status.st_mode)) {
            err_msg("%s: Is a directory",argv[i]);
            errCode = 1;
            continue;
        }

        int fd = open(argv[i], flags, 0644);
        if (fd < 0) {
            err_msg("%s: Failed to open", argv[i]);
            errCode = 1;
            continue;
        }

        lastFileDescriptor = lastFileDescriptor + 1;
        fileDescriptors[lastFileDescriptor] = fd;
        fileNames[lastFileDescriptor] = argv[i];
    }

    while(true) {
        size_t len = 0;
        ssize_t read = 0;
        char *line = NULL;

        read = getline(&line, &len, stdin);
        if (read == -1) {
            break;
        }

        for(int i=0; i <= lastFileDescriptor; i++) {
            int written = writeAll(fileDescriptors[i], line, strlen(line));
            if (written < 0) {
                err_msg("%s: Failed to write", fileNames[i]);
                errCode = 1;
            }
        }
    }

    for(int i=0; i <= lastFileDescriptor; i++) {
        close(fileDescriptors[i]);
    }

    free(fileDescriptors);
    free(fileNames);

    return errCode;
}

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;
} 
```
Mike
  • 319
  • 1
  • 5