diff options
author | James Crayne <jim.crayne@gmail.com> | 2019-09-28 13:43:29 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2020-01-01 19:27:53 -0500 |
commit | 11987749fc6e6d3e53ea737d46d5ab13a16faeb8 (patch) | |
tree | 5716463275c2d3e902889db619908ded2a73971c /dht/Presence/monitortty.c | |
parent | add2c76bced51fde5e9917e7449ef52be70faf87 (diff) |
Factor out some new libraries
word64-map:
Data.Word64Map
network-addr:
Network.Address
tox-crypto:
Crypto.Tox
lifted-concurrent:
Control.Concurrent.Lifted.Instrument
Control.Concurrent.Async.Lifted.Instrument
psq-wrap:
Data.Wrapper.PSQInt
Data.Wrapper.PSQ
minmax-psq:
Data.MinMaxPSQ
tasks:
Control.Concurrent.Tasks
kad:
Network.Kademlia
Network.Kademlia.Bootstrap
Network.Kademlia.Routing
Network.Kademlia.CommonAPI
Network.Kademlia.Persistence
Network.Kademlia.Search
Diffstat (limited to 'dht/Presence/monitortty.c')
-rw-r--r-- | dht/Presence/monitortty.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/dht/Presence/monitortty.c b/dht/Presence/monitortty.c new file mode 100644 index 00000000..7582aa56 --- /dev/null +++ b/dht/Presence/monitortty.c | |||
@@ -0,0 +1,182 @@ | |||
1 | // monitortty.c | ||
2 | |||
3 | #include <unistd.h> | ||
4 | #include <pthread.h> | ||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <stdint.h> | ||
8 | #include <errno.h> | ||
9 | #include <linux/vt.h> | ||
10 | #include <sys/ioctl.h> | ||
11 | #include <fcntl.h> | ||
12 | #include <linux/kd.h> | ||
13 | #include <stdlib.h> | ||
14 | |||
15 | static char *conspath[] = { | ||
16 | "/proc/self/fd/0", | ||
17 | "/dev/tty", | ||
18 | "/dev/tty0", | ||
19 | "/dev/vc/0", | ||
20 | "/dev/systty", | ||
21 | "/dev/console", | ||
22 | NULL | ||
23 | }; | ||
24 | |||
25 | static int | ||
26 | is_a_console(int fd) { | ||
27 | char arg; | ||
28 | |||
29 | arg = 0; | ||
30 | return (isatty (fd) | ||
31 | && ioctl(fd, KDGKBTYPE, &arg) == 0 | ||
32 | && ((arg == KB_101) || (arg == KB_84))); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | open_a_console(const char *fnam) { | ||
37 | int fd; | ||
38 | |||
39 | /* | ||
40 | * For ioctl purposes we only need some fd and permissions | ||
41 | * do not matter. But setfont:activatemap() does a write. | ||
42 | */ | ||
43 | fd = open(fnam, O_RDWR); | ||
44 | if (fd < 0) | ||
45 | fd = open(fnam, O_WRONLY); | ||
46 | if (fd < 0) | ||
47 | fd = open(fnam, O_RDONLY); | ||
48 | if (fd < 0) | ||
49 | return -1; | ||
50 | return fd; | ||
51 | } | ||
52 | |||
53 | int ttyfd() { | ||
54 | // We try several things because opening /dev/console will fail | ||
55 | // if someone else used X (which does a chown on /dev/console). | ||
56 | int i; | ||
57 | int fd; | ||
58 | for (i = 0; conspath[i]; i++) { | ||
59 | if ((fd = open_a_console(conspath[i])) >= 0) { | ||
60 | if (is_a_console(fd)) { | ||
61 | printf("using %s\n",conspath[i]); | ||
62 | return fd; | ||
63 | } | ||
64 | close(fd); | ||
65 | } | ||
66 | } | ||
67 | for (fd = 0; fd < 3; fd++) | ||
68 | if (is_a_console(fd)) | ||
69 | return fd; | ||
70 | printf("failed to find console fd\n"); | ||
71 | return -1; | ||
72 | } | ||
73 | |||
74 | void vt_wait(int tty_fd) { | ||
75 | struct vt_event vt; | ||
76 | memset(&vt,'\0',sizeof(vt)); | ||
77 | vt.event = VT_EVENT_SWITCH; | ||
78 | int res; | ||
79 | // printf("started wait\n"); | ||
80 | res = ioctl (tty_fd, VT_WAITEVENT, &vt); | ||
81 | if (res==-1) { | ||
82 | printf("vt_wait error fd=%i\n",tty_fd); | ||
83 | perror("vt_wait"); | ||
84 | // printf("vt_wait: %u - %s\n", errno, errmsg(errno)); | ||
85 | sleep(1); | ||
86 | } | ||
87 | // printf("finished wait\n"); | ||
88 | } | ||
89 | |||
90 | int8_t get_active(int tty_fd) { | ||
91 | struct vt_stat vtstat; | ||
92 | memset(&vtstat,'\0',sizeof(vtstat)); | ||
93 | if (ioctl(tty_fd, VT_GETSTATE, &vtstat)) { | ||
94 | perror ("get_active: VT_GETSTATE"); | ||
95 | return 7; | ||
96 | } | ||
97 | return vtstat.v_active; | ||
98 | } | ||
99 | |||
100 | void chvt(int tty_fd, int n) { | ||
101 | if (ioctl(tty_fd, VT_ACTIVATE, n)) { | ||
102 | perror ("chvt: VT_ACTIVATE"); | ||
103 | } | ||
104 | |||
105 | } | ||
106 | |||
107 | pthread_mutex_t mu; | ||
108 | pthread_t mt; | ||
109 | int tty = -1; | ||
110 | |||
111 | void *write_vtch(void *pfd) { | ||
112 | int fd = (int)(intptr_t)pfd; | ||
113 | printf("started VT_WAITEVENT loop fd=%i\n",fd); | ||
114 | pthread_mutex_lock(&mu); | ||
115 | tty = ttyfd(); | ||
116 | pthread_mutex_unlock(&mu); | ||
117 | int8_t active_tty = get_active(tty); | ||
118 | int8_t reported_tty; | ||
119 | ssize_t e; | ||
120 | |||
121 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | ||
122 | for (;;) { | ||
123 | // ssize_t write(int fd, const void *buf, size_t count); | ||
124 | e = write(fd, &active_tty, 1); | ||
125 | if (e<0 ) { | ||
126 | if( errno==EAGAIN) continue; | ||
127 | break; | ||
128 | } | ||
129 | else if(e==1) { | ||
130 | reported_tty = active_tty; | ||
131 | } | ||
132 | do { | ||
133 | vt_wait(tty); | ||
134 | // printf("vt_wait() finished. tty=%d fd=%d\n",tty,fd); | ||
135 | active_tty = get_active(tty); | ||
136 | } while (active_tty==reported_tty); | ||
137 | } | ||
138 | |||
139 | // TODO: | ||
140 | // use VT_GETSTATE | ||
141 | // use VT_WAITEVENT | ||
142 | printf("stopped VT_WAITEVENT loop\n"); | ||
143 | tty = -1; | ||
144 | pthread_mutex_destroy(&mu); | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | |||
149 | // Returns 0 on success. | ||
150 | int monitorTTY(int fd) { | ||
151 | int er = -1, dev = -1; | ||
152 | pthread_mutex_init(&mu,NULL); | ||
153 | // Ensure we can open a device before we bother forking a thread. | ||
154 | dev = ttyfd(); | ||
155 | if( dev != -1 ) { | ||
156 | er = pthread_create (&mt, NULL, write_vtch, (void*)(intptr_t)fd); | ||
157 | return er; | ||
158 | } | ||
159 | else { | ||
160 | return -1; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | void closeTTY() { | ||
165 | int fd = -1; | ||
166 | int active = 7; | ||
167 | pthread_mutex_lock(&mu); | ||
168 | active = get_active(tty); | ||
169 | fd = tty; | ||
170 | pthread_mutex_unlock(&mu); | ||
171 | #ifndef VTHACK | ||
172 | pthread_cancel(mt); | ||
173 | #endif | ||
174 | char cmd[40]; cmd[39] = '\0'; | ||
175 | // Hack to wake up from VT_WAITEVENT ioctl | ||
176 | #ifdef VTHACK | ||
177 | snprintf(cmd,39,"chvt %i;chvt %i",active+1,active); | ||
178 | system(cmd); | ||
179 | pthread_join(mt,NULL); | ||
180 | #endif | ||
181 | close(fd); | ||
182 | } | ||