-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtii.c
108 lines (91 loc) · 2.39 KB
/
tii.c
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
/*
* Tiny frontend for ii and ii-like programs.
* Inspired by sic from suckless
* http://tools.suckless.org/sic
* And by lchat from younix
* https://github.com/younix/lchat
* Although tii contains code from neither.
*/
#include <sys/types.h>
#include <sys/event.h> /* kqueue(2) */
#include <sys/time.h>
#include <err.h>
#include <fcntl.h> /* open(2) */
#include <stdio.h> /* printf(3) setvbuf(3) */
#include <stdlib.h> /* getenv(3) */
#include <string.h> /* strdup(3) */
#include <unistd.h> /* getopt(3) write(2) read(2) */
static void
usage(void)
{
fprintf(stderr, "tii [-h] [-i in] [-o out]\n");
exit(1);
}
int
main(int argc, char *argv[])
{
struct kevent chlist[2]; /* events to monitor */
int kq, ch, in_fd, out_fd;
char *in_file = NULL, *out_file = NULL;
in_file = strdup("./in");
out_file = strdup("./out");
while ((ch = getopt(argc, argv, "i:o:h")) != -1) {
switch (ch) {
case 'i':
in_file = strdup(optarg);
break;
case 'o':
out_file = strdup(optarg);
break;
case 'h':
default:
usage();
/* NOTREACHED */
}
}
if (argc - optind > 0)
usage();
if (in_file == NULL || out_file == NULL)
err(1, "strdup");
in_fd = open(in_file, O_WRONLY|O_APPEND);
out_fd = open(out_file, O_RDONLY);
if ((in_fd == -1 ) || (out_fd == -1))
err(1, "opening in out files");
free(in_file);
free(out_file);
if ((setvbuf(stdin, NULL, _IONBF, 0)) != 0)
err(1, "setvbuf stdin");
if ((setvbuf(stdout, NULL, _IONBF, 0)) != 0)
err(1, "setvbuf stdout");
if ((kq = kqueue()) == -1)
err(1, "kqueue()");
EV_SET(&chlist[0], out_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
EV_SET(&chlist[1], STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, 0);
for (;;) {
int i, nev;
struct kevent evlist[2]; /* events that were triggered */
nev = kevent(kq, chlist, 2, evlist, 2, NULL); /* block indefinitely */
if (nev == -1)
err(1, "kevent()");
for (i = 0; i < nev; i++) {
int res = 0;
char buf[512];
ssize_t bufl;
if (evlist[i].flags & EV_ERROR)
err(1, "evlist EV_ERROR");
if (evlist[i].data <= 0)
break; /* we only append */
bufl = read(evlist[i].ident, buf, sizeof buf);
if (bufl == -1 )
err(1, "read");
if (evlist[i].ident == out_fd) { /* can't switch-case, out_fd isn't static */
res = write(STDOUT_FILENO, buf, bufl);
} else if (evlist[i].ident == STDIN_FILENO) {
res = write(in_fd, buf, bufl);
}
if (res == -1)
err(1, "write");
}
}
return 0;
}