summaryrefslogtreecommitdiff
path: root/dht/Presence/monitortty.c
diff options
context:
space:
mode:
authorJames Crayne <jim.crayne@gmail.com>2019-09-28 13:43:29 -0400
committerJoe Crayne <joe@jerkface.net>2020-01-01 19:27:53 -0500
commit11987749fc6e6d3e53ea737d46d5ab13a16faeb8 (patch)
tree5716463275c2d3e902889db619908ded2a73971c /dht/Presence/monitortty.c
parentadd2c76bced51fde5e9917e7449ef52be70faf87 (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.c182
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
15static 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
25static int
26is_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
35static int
36open_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
53int 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
74void 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
90int8_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
100void chvt(int tty_fd, int n) {
101 if (ioctl(tty_fd, VT_ACTIVATE, n)) {
102 perror ("chvt: VT_ACTIVATE");
103 }
104
105}
106
107pthread_mutex_t mu;
108pthread_t mt;
109int tty = -1;
110
111void *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.
150int 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
164void 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}