aboutsummaryrefslogtreecommitdiff
path: root/tee.c
blob: 4df507430742a39c43ed4af2de0fc5157e02bc2c (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
#define _POSIX_C_SOURCE 2 // getopt
#define _XOPEN_SOURCE 500 // sigaction
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#define BUFFER_SIZE 2048

char	*g_name = "tee";

int		main(int argc, char **argv)
{
	int		option;
	bool	append = false;

	g_name = argv[0];

	struct sigaction action;
	action.sa_handler = SIG_IGN;
	action.sa_flags = SA_NODEFER;

	while ((option = getopt(argc, argv, "ai")) != -1)
	{
		switch (option)
		{
			case 'a':
				append = true;
				break;
			case 'i':
				sigaction(SIGINT, &action, NULL);
				break;
		}
	}

	size_t	files_num = argc - optind;
	FILE	**files = calloc(files_num, sizeof(FILE*));
	if (files == NULL)
		return EXIT_FAILURE;

	for (size_t i = 0; i < files_num; i++)
	{
		files[i] = fopen(argv[optind + i], append ? "a" : "w");
		if (files[i] == NULL)
		{
			fprintf(stderr, "%s: %s: %s\n", g_name, argv[optind + i], strerror(errno));
			i--;
			files_num--;
		}
	}

	char	buf[BUFFER_SIZE + 1] = {0};
	size_t	read_size = 0;
	while ((read_size = fread(buf, 1, BUFFER_SIZE, stdin)) > 0)
	{
		fwrite(buf, 1, read_size, stdout);
		for (size_t i = 0; i < files_num; i++)
			fwrite(buf, 1, read_size, files[i]);
	}

	for (size_t i = 0; i < files_num; i++)
		fclose(files[i]);
	free(files);
	return EXIT_SUCCESS;
}