summaryrefslogtreecommitdiff
path: root/src/commands/tee.c
blob: b9b31be31ef6e36ba7c6c63a5bd4f5c350563104 (plain)
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
#include "../command.h"

#include <signal.h>

static struct {
    bool append;
    bool handle_sigint;
} flags;

static void help(void) {
    printf("Usage: tee [-ai] [FILE]...\n\n");
    printf("Copy stdin to each FILE, and also to stdout\n\n");
	printf("\t-a	Append to the given FILEs, don't overwrite\n");
	printf("\t-i	Ignore interrupt signals (SIGINT)\n");
    exit(EXIT_SUCCESS);
}

static void handle(int dummy){UNUSED(dummy);}

static void run_tee(int file_count, FILE** files) {
    char c;
    int i;

    while((c = getchar()) != EOF) {
        int i;
        for (i = 0; i < file_count; i++) {
            fwrite(&c, 1, 1, files[i]);
            fflush(files[i]);
        }
        putchar(c);
    }

    for (i = 0; i < file_count; i++) {
        fclose(files[i]);
    }
}

static int short_arg(char c, char* next) {
    UNUSED(next);
    switch (c) {
        case 'a':
            flags.append = true;
            break;
        case 'i':
            flags.handle_sigint = true;
            break;
        default:
            return ARG_INVALID;
    }
    return ARG_UNUSED;
}

COMMAND(tee) {

    int start, i;
    FILE** files;

    flags.append = false;
    flags.handle_sigint = false;

    start = parse_args(argc, argv, help, short_arg, NULL);

    if (flags.handle_sigint) {
        signal(SIGINT, handle);
    }

    if (argc - start < 1) {
        run_tee(0, NULL);
        return EXIT_SUCCESS;
    }

    files = malloc(sizeof(FILE*) * (argc - start));

    for (i = start; i < argc; i++) {
        FILE* file = get_file(argv[i], flags.append ? "a" : "w");
        files[i - start] = file;
    }

    run_tee(argc - start, files);
    return EXIT_SUCCESS;
}