summaryrefslogtreecommitdiff
path: root/pgm3/totalsize.c
blob: c15a72d5792a91028f2b8d7b576d6320934ea2ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <errno.h>
#include <math.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 <time.h>
#include <unistd.h>

#define FALSE 0
#define FILE_BUFF 4096
#define TRUE  1

struct NODE {
    int inode;
    long size;
    struct NODE *next;
};

int main() {
    /*
     * totalsize takes in a list of filenames on its stdin and adds up the
     * total size of those files (using stat) and prints the results as
     * either bytes or kilobytes. It checks the UNITS environment variable to
     * know whether to print in bytes or kilobytes. It checks the TSTALL
     * environment variable for an integer to use as a delay before checking
     * for files. It also checks the TMOM environment variable for the
     * process ID of a parent process to send a SIGUSR1 signal to.
     *
     * totalsize builds a linked list out of the entered filenames and then
     * goes through the unique, regular files and uses stat() to grab
     * information about those files (inode, size).
     */
    char *envar = NULL;
    char filename[FILE_BUFF];
    int inList = FALSE;
    int sigPID;
    int sleepTime;
    long long byteSum = 0;
    struct NODE *currentNode = NULL;
    struct NODE *head = NULL;
    struct NODE *newNode = NULL;
    struct stat statData;

    // Check TSTALL for time delay
    errno = 0;

    if ((envar = getenv("TSTALL")) != NULL
            && (sleepTime = strtol(envar, NULL, 10)) > 0
            && errno == 0) {
        sleep(sleepTime);
    }

    // Take in standard input and build linked list.
    while (scanf(" %s", filename) == 1) {

        if (stat(filename, &statData) == 0 && S_ISREG(statData.st_mode)) {
            inList = FALSE;

            for (currentNode = head; currentNode != NULL; currentNode = currentNode->next) {

                if (currentNode->inode == statData.st_ino) {
                    inList = TRUE;
                }

            }

            if (!inList) {
                newNode = (struct NODE *) malloc(sizeof(struct NODE));
                newNode->inode = statData.st_ino;
                newNode->size = statData.st_size;
                newNode->next = head;
                head = newNode;
            }

        }

        // Check TSTALL for time delay
        errno = 0;

        if ((envar = getenv("TSTALL")) != NULL
                && (sleepTime = strtol(envar, NULL, 10)) > 0
                && errno == 0) {
            sleep(sleepTime);
        }

    }

    // Add up the number of bytes and print out the results
    byteSum = 0;

    for (currentNode = head; currentNode != NULL; currentNode = currentNode->next) {
        byteSum += currentNode->size;
    }

    if ((envar = getenv("UNITS")) != NULL
            && (envar[0] == 'k' || envar[0] == 'K')
            && envar[1] == '\0') {
        byteSum /= 1024;
        printf("%lldkB\n", byteSum);
    }
    else {
        printf("%lld\n", byteSum);
    }

    // Free list
    while (currentNode != NULL) {
        currentNode = head;
        head = head->next;
        free(currentNode);
    }

    errno = 0;

    // Send SIGNUSR1 signal to calling parent
    if ((envar = getenv("TMOM")) != NULL
            && (sigPID = strtol(envar, NULL, 10)) > 0
            && errno == 0) {
        kill(sigPID, SIGUSR1);
    }

    exit(0);
}