summaryrefslogtreecommitdiff
path: root/src/commands/tee.c
blob: ced5b064f4f3a4c6cd347669de1f8e4eb3e55264 (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
#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[file_count]) {
    char c;
    while((c = getchar()) != EOF) {
        for (int i = 0; i < file_count; i++) {
            fwrite(&c, 1, 1, files[i]);
            fflush(files[i]);
        }
        putchar(c);
    }
    for (int 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:
            error("error: unkown option: %c", c);
    }
    return ARG_UNUSED;
}

COMMAND(tee) {

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

    int 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;
    }

    FILE* files[argc - start];
    for (int 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;
}