summaryrefslogtreecommitdiff
path: root/tool/con.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tool/con.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/tool/con.c b/tool/con.c
new file mode 100644
index 0000000..8522786
--- /dev/null
+++ b/tool/con.c
@@ -0,0 +1,106 @@
1/* con device */
2
3#include <signal.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <fcntl.h>
8#include <termios.h>
9#include <unistd.h>
10
11struct termios save;
12
13void
14host(int fd)
15{
16 int cc;
17 char buf[128];
18
19 for (;;) {
20 cc = read(fd, buf, sizeof buf);
21#ifdef HEX
22 if (cc < 0)
23 break;
24 for (int i = 0; i < cc; ++i) {
25 char hex[3];
26 sprintf(hex, "%02X", (unsigned char) buf[i]);
27 write(1, hex, 2);
28 }
29#else
30 if (cc > 0)
31 write(1, buf, cc);
32 else if (cc < 0)
33 break;
34#endif
35 }
36}
37
38void
39hup(int signo)
40{
41 write(1, "HUP\n", 4);
42 tcsetattr(0, TCSADRAIN, &save);
43 _exit(0);
44}
45
46void
47user(int fd)
48{
49 char c, last = '\r';
50
51 signal(SIGHUP, hup);
52 for (;;)
53 while (read(0, &c, 1) > 0) {
54 if (c == '~' && (last == '\n' || last == '\r'
55 || last == 4)) {
56 read(0, &c, 1);
57 if (c == '.')
58 return;
59 }
60 write(fd, &c, 1);
61 last = c;
62 }
63}
64
65int
66main(int argc, char *argv[])
67{
68 int fd;
69 pid_t pid;
70 struct termios t;
71
72 if (argc != 2)
73 exit(1);
74
75 fd = open(argv[1], O_RDWR | O_NDELAY);
76 if (fd < 0)
77 exit(2);
78 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
79 tcgetattr(fd, &t);
80 t.c_cc[VMIN] = 1;
81 t.c_cc[VTIME] = 0;
82 tcsetattr(fd, TCSADRAIN, &t);
83
84 tcgetattr(0, &t);
85 save = t;
86 t.c_iflag = 0;
87 t.c_oflag = 0;
88 t.c_lflag = 0;
89 t.c_cc[VMIN] = 1;
90 t.c_cc[VTIME] = 0;
91 tcsetattr(0, TCSADRAIN, &t);
92
93 if ((pid = fork()) > 0) {
94 user(fd);
95 } else if (pid == 0) {
96 host(fd);
97 } else {
98 perror("fork");
99 _exit(EXIT_FAILURE);
100 }
101
102 tcsetattr(0, TCSADRAIN, &save);
103 kill(pid, SIGKILL);
104 close(fd);
105 _exit(EXIT_SUCCESS);
106}