summaryrefslogtreecommitdiff
path: root/Presence/monitortty.c
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/monitortty.c')
-rw-r--r--Presence/monitortty.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/Presence/monitortty.c b/Presence/monitortty.c
new file mode 100644
index 00000000..90e23464
--- /dev/null
+++ b/Presence/monitortty.c
@@ -0,0 +1,167 @@
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("START write_vtch 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 active_tty = get_active(tty);
135 } while (active_tty==reported_tty);
136 }
137
138 // TODO:
139 // use VT_GETSTATE
140 // use VT_WAITEVENT
141 printf("QUIT write_vtch\n");
142 tty = -1;
143 pthread_mutex_destroy(&mu);
144 return NULL;
145}
146
147
148void monitorTTY(int fd) {
149 pthread_mutex_init(&mu,NULL);
150 printf ("Hello world.\n");
151 pthread_create (&mt, NULL, write_vtch, (void*)(intptr_t)fd);
152}
153
154void closeTTY() {
155 int fd = -1;
156 int active = 7;
157 pthread_mutex_lock(&mu);
158 active = get_active(tty);
159 fd = tty;
160 pthread_mutex_unlock(&mu);
161 pthread_cancel(mt);
162 char cmd[40]; cmd[39] = '\0';
163 snprintf(cmd,39,"chvt %i;chvt %i",active+1,active);
164 system(cmd);
165 pthread_join(mt,NULL);
166 close(fd);
167}