4 #include <sys/select.h>
9 #define VSYS_PATH "/vsys"
17 char ctrl[2][MAXPATH]; /* paths of vsys.in & vsys.out */
19 static void mkpath(int dir, const char* vsys)
21 static const char *suffix[] = { "in", "out" };
24 if ( (n = snprintf(ctrl[dir], MAXPATH, "%s/%s.%s", VSYS_PATH, vsys, suffix[dir])) < 0) {
27 } else if (n >= MAXPATH) {
28 fprintf(stderr, "argument too long\n");
33 static int open_ctrl(int dir)
37 if ( (fd = open(ctrl[dir], (dir == IN ? O_WRONLY : O_RDONLY) | O_NONBLOCK)) < 0) {
45 static void set_nonblocking(int fd)
49 if ( (val = fcntl(fd, F_GETFL, 0)) < 0) {
50 perror("fcntl F_GETFL");
53 if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
54 perror("fcntl F_SETFL");
60 static void print_set(const char* name, int max, const fd_set* set)
63 fprintf(stderr, "%s: {", name);
64 for (i = 0; i < max; i++) {
65 if (FD_ISSET(i, set)) {
66 if (n++) fprintf(stderr, ", ");
67 fprintf(stderr, "%d", i);
70 fprintf(stderr, "}\n");
83 static int active_channels = 0;
85 static void channel_init(struct channel *c, const char* name, int rfd, int wfd)
96 static void channel_fdset(struct channel *c, fd_set* readset, fd_set* writeset)
101 FD_SET(c->wfd, writeset);
103 FD_SET(c->rfd, readset);
107 static void channel_run(struct channel *c, const fd_set* readset, const fd_set* writeset)
114 if (FD_ISSET(c->wfd, writeset)) {
115 if ( (n = write(c->wfd, c->wp, c->rp - c->wp)) < 0) {
120 if (c->wp == c->rp) {
121 c->wp = c->rp = c->buf;
126 if (FD_ISSET(c->rfd, readset)) {
127 if ( (n = read(c->rfd, c->rp, BUFSIZE)) < 0) {
144 static struct channel channels[2];
147 int main(int argc, char *argv[])
149 int fd[2]; /* fds of vsys.in & vsys.out */
152 fd_set readset, writeset;
155 fprintf(stderr, "Usage: %s <vsys>\n", argv[0]);
160 mkpath(OUT, argv[1]);
162 maxfd = (STDOUT_FILENO > STDIN_FILENO ? STDOUT_FILENO : STDIN_FILENO);
164 fd[OUT] = open_ctrl(OUT);
167 fd[IN] = open_ctrl(IN);
171 set_nonblocking(STDIN_FILENO);
172 set_nonblocking(STDOUT_FILENO);
174 channel_init(&channels[IN], "IN", STDIN_FILENO, fd[IN]);
175 channel_init(&channels[OUT], "OUT", fd[OUT], STDOUT_FILENO);
177 while (active_channels) {
180 channel_fdset(&channels[IN], &readset, &writeset);
181 channel_fdset(&channels[OUT], &readset, &writeset);
182 if (select(maxfd + 1, &readset, &writeset, NULL, NULL) < 0) {
186 channel_run(&channels[IN], &readset, &writeset);
187 channel_run(&channels[OUT], &readset, &writeset);