diff options
Diffstat (limited to 'pgm3/report.c')
| -rw-r--r-- | pgm3/report.c | 232 | 
1 files changed, 232 insertions, 0 deletions
| diff --git a/pgm3/report.c b/pgm3/report.c new file mode 100644 index 0000000..623de6f --- /dev/null +++ b/pgm3/report.c @@ -0,0 +1,232 @@ +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <unistd.h> + +#define FALSE 0 +#define FILE_BUFF 4096 +#define TRUE  1 + +int terminateFlag = 1; // Used with signal handler function. + +void sigHandler(int signum) { +    /* +     * sigHandler() waits for a SIGUSR1 signal. Upon receiving this signal it +     * decrements terminateFlag, lowering it to zero. +     */ + +    if (signum == SIGUSR1) { +        terminateFlag--; +    } + +} + +int main(int argc, char *argv[]) { +    /* +     * report takes in one required argument ("num") and two optional arguments. +     * -k specifies that output should be printed in kilobytes, not bytes +     * -d specifies a delay that should be waited before reading each filename +     * into the totalsize child process. +     * +     * Report takes in filenames on its stdin and then calls four child +     * processes. Two execute accessed, one with num as an arg and one with +     * -num as an arg. report writes its stdin to the stdin of the accessed +     * children. The accessed children then print their output to the stdin +     * of two more children that execute totalsize. These totalsize +     * children run through the filenames they're given and print out the +     * size of those files back into report. This is all done via pipes. +     * +     * report then prints out the results it receives from its children. +     */ +    char byteSum[10]; +    char delayStr[10]; +    char *envar = NULL; +    char filename[FILE_BUFF]; +    char numNeg[11]; +    char thisPID[10]; +    int accessedNum; +    int delay = 0; +    int i = 2; + +    // Go through args. +    if (argc < 2) { +        fprintf(stderr, "usage: ./report [num days] {-k} {-d} [delay]\n"); +        exit(1); +    } + +    // Fetch accessedNum parameter +    accessedNum = strtol(argv[1], NULL, 10); +    errno = 0; + +    if (accessedNum <= 0) { +        fprintf(stderr, "report: num must be positive, nonzero integer.\n"); +        exit(1); +    } +    else if (errno == ERANGE) { +        fprintf(stderr, "report: num must be of integer size.\n"); +        exit(1); +    } +    else if (errno == EINVAL) { +        fprintf(stderr, "report: num must be integer type.\n"); +        exit(1); +    } + +    // Set the second accessed num as negative. +    sprintf(numNeg, "%d", accessedNum * -1); + +    while (argv[i]) { + +        if (strcmp(argv[i], "-k") == 0) { +            setenv("UNITS", "k", 1); +        } +        else if (strcmp(argv[i], "-d") == 0) { +            delay = strtol(argv[i+1], NULL, 10); +            errno = 0; + +            if (delay <= 0) { +                fprintf(stderr, "report: delay must be positive, nonzero integer.\n"); +                exit(1); +            } +            else if (errno == ERANGE) { +                fprintf(stderr, "report: delay must be of integer size.\n"); +                exit(1); +            } +            else if (errno == EINVAL) { +                fprintf(stderr, "report: delay must be integer type.\n"); +                exit(1); +            } + +            sprintf(delayStr, "%d", delay); +            setenv("TSTALL", delayStr, 1); +            i++; +        } +        else { +            fprintf(stderr, "usage: ./report [num days] {-k} {-d} [delay]\n"); +            exit(1); +        } + +        i++; +    } + +    // Set up signal handling. +    sprintf(thisPID, "%d", getpid()); +    setenv("TMOM", thisPID, 1); +    signal(SIGUSR1, sigHandler); + +    // Set up pipes. +    int pipeRtoA1[2]; pipe(pipeRtoA1); +    int pipeRtoA2[2]; pipe(pipeRtoA2); +    int pipeA1toT1[2]; pipe(pipeA1toT1); +    int pipeA2toT2[2]; pipe(pipeA2toT2); +    int pipeT1toR[2]; pipe(pipeT1toR); +    int pipeT2toR[2]; pipe(pipeT2toR); + +    if (fork() == 0) { // accessed 1 +        // Close unneeded pipes ===================== +                                close(pipeRtoA1[1]); +        close(pipeRtoA2[0]);    close(pipeRtoA2[1]); +        close(pipeA1toT1[0]); +        close(pipeA2toT2[0]);   close(pipeA2toT2[1]); +        close(pipeT1toR[0]);    close(pipeT1toR[1]); +        close(pipeT2toR[0]);    close(pipeT2toR[1]); +        // ========================================== + +        // Dup read end to stdin and write end to stdout +        close(0); dup(pipeRtoA1[0]); close(pipeRtoA1[0]); +        close(1); dup(pipeA1toT1[1]); close(pipeA1toT1[1]); +        execl("accessed", "accessed", argv[1], NULL); +    } +    else if (fork() == 0) { // accessed 2 +        // Close unneeded pipes ===================== +        close(pipeRtoA1[0]);    close(pipeRtoA1[1]); +                                close(pipeRtoA2[1]); +        close(pipeA1toT1[0]);   close(pipeA1toT1[1]); +        close(pipeA2toT2[0]); +        close(pipeT1toR[0]);    close(pipeT1toR[1]); +        close(pipeT2toR[0]);    close(pipeT2toR[1]); +        // ========================================== + +        close(0); dup(pipeRtoA2[0]); close(pipeRtoA2[0]); +        close(1); dup(pipeA2toT2[1]); close(pipeA2toT2[1]); +        execl("accessed", "accessed", numNeg, NULL); +    } +    else if (fork() == 0) { // totalsize 1 +        // Close unneeded pipes ===================== +        close(pipeRtoA1[0]);    close(pipeRtoA1[1]); +        close(pipeRtoA2[0]);    close(pipeRtoA2[1]); +                                close(pipeA1toT1[1]); +        close(pipeA2toT2[0]);   close(pipeA2toT2[1]); +        close(pipeT1toR[0]); +        close(pipeT2toR[0]);    close(pipeT2toR[1]); +        // ========================================== + +        close(0); dup(pipeA1toT1[0]); close(pipeA1toT1[0]); +        close(1); dup(pipeT1toR[1]); close(pipeT1toR[1]); +        execl("totalsize", "totalsize", NULL); +    } +    else if (fork() == 0) { // totalsize 2 +        // Close unneeded pipes ===================== +        close(pipeRtoA1[0]);    close(pipeRtoA1[1]); +        close(pipeRtoA2[0]);    close(pipeRtoA2[1]); +        close(pipeA1toT1[0]);   close(pipeA1toT1[1]); +                                close(pipeA2toT2[1]); +        close(pipeT1toR[0]);    close(pipeT1toR[1]); +        close(pipeT2toR[0]); +        // ========================================== + +        close(0); dup(pipeA2toT2[0]); close(pipeA2toT2[0]); +        close(1); dup(pipeT2toR[1]); close(pipeT2toR[1]); +        execl("totalsize", "totalsize", NULL); +    } + +    // Close those pipes which parent report does not need +    close(pipeRtoA1[0]); +    close(pipeRtoA2[0]); +    close(pipeA1toT1[0]);   close(pipeA1toT1[1]); +    close(pipeA2toT2[0]);   close(pipeA2toT2[1]); +                            close(pipeT1toR[1]); +                            close(pipeT2toR[1]); + +    // Write stdin from report to accessed children +    while (scanf("%s", filename) == 1) { +        write(pipeRtoA1[1], strcat(filename, " "), strlen(filename) + 1); +        write(pipeRtoA2[1], strcat(filename, " "), strlen(filename) + 1); +    } + +    // Close remaining pipes. +    close(pipeRtoA1[1]);    close(pipeRtoA2[1]); + +    // Enter non-terminating loop to wait for children +    while (terminateFlag) { +        printf("*"); +        sleep(1); +    } + +    // Print results of first totalsize child +    read(pipeT1toR[0], byteSum, sizeof(byteSum)); close(pipeT1toR[0]); +    sscanf(byteSum, " %s ", byteSum); +    printf("\nA total of %s ", byteSum); + +    if ((envar = getenv("UNITS")) == NULL || !(envar[0] != 'k' || envar[0] != 'K')) { +        printf("bytes "); +    } + +    printf("are in regular files not accessed for %s days.\n----------\n", argv[1]); + +    // Print results of second totalsize child +    read(pipeT2toR[0], byteSum, sizeof(byteSum)); close(pipeT2toR[0]); +    sscanf(byteSum, " %s ", byteSum); +    printf("A total of %s ", byteSum); + +    if ((envar = getenv("UNITS")) == NULL || !(envar[0] != 'k' || envar[0] != 'K')) { +        printf("bytes "); +    } + +    printf("are in regular files accessed within %s days.\n\n", argv[1]); +    exit(0); +} |