uvtd: vt: implement VT_GETMODE/SETMODE ioctl state-tracking
[platform/upstream/kmscon.git] / src / uterm_vt.c
1 /*
2  * uterm - Linux User-Space Terminal
3  *
4  * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /*
27  * Virtual Terminals
28  */
29
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <linux/kd.h>
33 #include <linux/major.h>
34 #include <linux/vt.h>
35 #include <signal.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/ioctl.h>
41 #include <sys/signalfd.h>
42 #include <sys/stat.h>
43 #include <termios.h>
44 #include <time.h>
45 #include <unistd.h>
46 #include <xkbcommon/xkbcommon-keysyms.h>
47 #include "eloop.h"
48 #include "shl_dlist.h"
49 #include "shl_log.h"
50 #include "shl_misc.h"
51 #include "uterm_input.h"
52 #include "uterm_vt.h"
53
54 #define LOG_SUBSYSTEM "vt"
55
56 struct uterm_vt {
57         unsigned long ref;
58         struct shl_dlist list;
59         struct uterm_vt_master *vtm;
60         struct uterm_input *input;
61         unsigned int mode;
62
63         uterm_vt_cb cb;
64         void *data;
65
66         bool active;
67         bool hup;
68
69         /* this is for *real* linux kernel VTs */
70         int real_fd;
71         int real_num;
72         int real_saved_num;
73         int real_kbmode;
74         struct ev_fd *real_efd;
75         bool real_delayed;
76         int real_target;
77         time_t real_target_time;
78 };
79
80 struct uterm_vt_master {
81         unsigned long ref;
82         struct ev_eloop *eloop;
83
84         struct shl_dlist vts;
85 };
86
87 static int vt_call(struct uterm_vt *vt, unsigned int event, int target,
88                    bool force)
89 {
90         int ret;
91         struct uterm_vt_event ev;
92
93         memset(&ev, 0, sizeof(ev));
94         ev.action = event;
95         ev.target = target;
96         if (force)
97                 ev.flags |= UTERM_VT_FORCE;
98
99         switch (event) {
100         case UTERM_VT_ACTIVATE:
101                 if (vt->active)
102                         return 0;
103                 if (!vt->cb)
104                         break;
105
106                 ret = vt->cb(vt, &ev, vt->data);
107                 if (ret)
108                         log_warning("vt event handler returned %d instead of 0 on activation",
109                                     ret);
110                 break;
111         case UTERM_VT_DEACTIVATE:
112                 if (!vt->active)
113                         return 0;
114                 if (!vt->cb)
115                         break;
116
117                 ret = vt->cb(vt, &ev, vt->data);
118                 if (ret) {
119                         if (force)
120                                 log_warning("vt event handler returned %d instead of 0 on forced deactivation",
121                                             ret);
122                         else
123                                 return ret;
124                 }
125                 break;
126         default:
127                 return -EINVAL;
128         }
129
130         vt->active = !vt->active;
131         return 0;
132 }
133
134 static void vt_call_activate(struct uterm_vt *vt)
135 {
136         vt_call(vt, UTERM_VT_ACTIVATE, vt->real_num, false);
137 }
138
139 static int vt_call_deactivate(struct uterm_vt *vt, bool force)
140 {
141         return vt_call(vt, UTERM_VT_DEACTIVATE, vt->real_target, force);
142 }
143
144 /*
145  * 'Real' VTs
146  * The linux kernel (used) to provide VTs via CONFIG_VT. These VTs are TTYs that
147  * the kernel runs a very limit VT102 compatible console on. They also provide a
148  * mechanism to switch between graphical user-applications.
149  * An application that opens a VT is notified via two signals whenever the user
150  * switches to or away from the VT. We catch these signals and forward a
151  * notification to the application via callbacks.
152  *
153  * Real VTs are only available on seat0 and should be avoided whenever possible
154  * as they have a horrible API, have synchronization issues and are inflexible.
155  *
156  * Also note that the VT API is asynchronous and requires acknowledgment of
157  * applications when switching VTs. That means, when a VT-switch is started, the
158  * currently-active VT is notified about this and needs to acknowledge this
159  * switch. If it allows it, the new VT is notified that it is now started up.
160  * This control-passing is very fragile. For instance if the currently-active VT
161  * is stuck or paused, the VT switch cannot take place as it is not acknowledged
162  * by the currently active VT.
163  * Furthermore, there are some race-conditions during a switch. If resources
164  * that are passed from one VT to another are acquired during this switch from a
165  * 3rd party application, then they can hijack the VT-switch and make the new
166  * VT fail acquiring the resources.
167  *
168  * There are a lot more issues. For instance VTs are not cleaned up when closed
169  * which can cause deadlocks if VT_SETMODE is not reset.
170  * All in all, real VTs are very fragile and should be avoided. They should only
171  * be used for backwards-compatibility.
172  */
173
174 static void real_delayed(struct ev_eloop *eloop, void *unused, void *data)
175 {
176         struct uterm_vt *vt = data;
177
178         log_debug("enter VT %d %p during startup", vt->real_num, vt);
179         vt->real_delayed = false;
180         ev_eloop_unregister_idle_cb(eloop, real_delayed, vt, EV_NORMAL);
181         vt_call_activate(vt);
182 }
183
184 static void real_sig_enter(struct uterm_vt *vt, struct signalfd_siginfo *info)
185 {
186         struct vt_stat vts;
187         int ret;
188
189         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
190         if (ret) {
191                 log_warning("cannot get current VT state (%d): %m", errno);
192                 return;
193         }
194
195         if (vts.v_active != vt->real_num)
196                 return;
197
198         if (vt->real_delayed) {
199                 vt->real_delayed = false;
200                 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
201                                             EV_NORMAL);
202         } else if (vt->active) {
203                 log_warning("activating VT %d even though it's already active",
204                             vt->real_num);
205         } else {
206                 uterm_input_wake_up(vt->input);
207         }
208
209         log_debug("enter VT %d %p due to VT signal", vt->real_num, vt);
210         ioctl(vt->real_fd, VT_RELDISP, VT_ACKACQ);
211         vt->real_target = -1;
212         vt_call_activate(vt);
213 }
214
215 static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info)
216 {
217         struct vt_stat vts;
218         int ret;
219         bool active;
220
221         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
222         if (ret) {
223                 log_warning("cannot get current VT state (%d): %m", errno);
224                 return;
225         }
226
227         if (vts.v_active != vt->real_num)
228                 return;
229
230         log_debug("leaving VT %d %p due to VT signal", vt->real_num, vt);
231         active = vt->active;
232         ret = vt_call_deactivate(vt, false);
233         if (ret) {
234                 ioctl(vt->real_fd, VT_RELDISP, 0);
235                 log_debug("not leaving VT %d %p: %d", vt->real_num, vt, ret);
236                 return;
237         }
238
239         if (vt->real_delayed) {
240                 vt->real_delayed = false;
241                 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
242                                             EV_NORMAL);
243                 uterm_input_sleep(vt->input);
244         } else if (!active) {
245                 log_warning("deactivating VT %d even though it's not active",
246                             vt->real_num);
247         } else {
248                 uterm_input_sleep(vt->input);
249         }
250
251         vt->real_target = -1;
252         ioctl(vt->real_fd, VT_RELDISP, 1);
253 }
254
255 static void real_vt_input(struct ev_fd *fd, int mask, void *data)
256 {
257         struct uterm_vt *vt = data;
258         struct uterm_vt_event ev;
259
260         /* we ignore input from the VT because we get it from evdev */
261         if (mask & EV_READABLE)
262                 tcflush(vt->real_fd, TCIFLUSH);
263
264         if (mask & (EV_HUP | EV_ERR)) {
265                 log_debug("HUP on VT %d", vt->real_num);
266                 ev_fd_disable(fd);
267                 vt->hup = true;
268                 if (vt->cb) {
269                         memset(&ev, 0, sizeof(ev));
270                         ev.action = UTERM_VT_HUP;
271                         vt->cb(vt, &ev, vt->data);
272                 }
273         }
274 }
275
276 static int open_tty(const char *dev, int *tty_fd, int *tty_num)
277 {
278         int fd, ret, id;
279         struct stat st;
280
281         if (!dev || !tty_fd || !tty_num)
282                 return -EINVAL;
283
284         log_notice("using tty %s", dev);
285
286         fd = open(dev, O_RDWR | O_NOCTTY | O_CLOEXEC);
287         if (fd < 0) {
288                 log_err("cannot open tty %s (%d): %m", dev, errno);
289                 return -errno;
290         }
291
292         ret = fstat(fd, &st);
293         if (ret) {
294                 log_error("cannot introspect tty %s (%d): %m", dev, errno);
295                 close(fd);
296                 return -errno;
297         }
298         id = minor(st.st_rdev);
299         log_debug("new tty ID is %d", id);
300
301         *tty_fd = fd;
302         *tty_num = id;
303         return 0;
304 }
305
306 static int real_open(struct uterm_vt *vt, const char *vt_name)
307 {
308         struct vt_mode mode;
309         struct vt_stat vts;
310         int ret, err;
311
312         log_debug("open vt %p", vt);
313
314         ret = open_tty(vt_name, &vt->real_fd, &vt->real_num);
315         if (ret)
316                 return ret;
317
318         ret = ev_eloop_new_fd(vt->vtm->eloop, &vt->real_efd, vt->real_fd,
319                               EV_READABLE, real_vt_input, vt);
320         if (ret)
321                 goto err_fd;
322
323         /* Get the number of the VT which is active now, so we have something
324          * to switch back to in uterm_vt_deactivate(). */
325         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
326         if (ret) {
327                 log_warn("cannot find the currently active VT (%d): %m", errno);
328                 ret = -EFAULT;
329                 goto err_eloop;
330         }
331         vt->real_saved_num = vts.v_active;
332         vt->real_target = -1;
333
334         if (ioctl(vt->real_fd, KDSETMODE, KD_GRAPHICS)) {
335                 log_err("cannot put VT in graphics mode (%d): %m", errno);
336                 ret = -errno;
337                 goto err_eloop;
338         }
339
340         memset(&mode, 0, sizeof(mode));
341         mode.mode = VT_PROCESS;
342         mode.acqsig = SIGUSR1;
343         mode.relsig = SIGUSR2;
344
345         if (ioctl(vt->real_fd, VT_SETMODE, &mode)) {
346                 log_err("cannot take control of vt handling (%d): %m", errno);
347                 ret = -errno;
348                 goto err_text;
349         }
350
351         ret = ioctl(vt->real_fd, KDGKBMODE, &vt->real_kbmode);
352         if (ret) {
353                 log_error("cannot retrieve VT KBMODE (%d): %m", errno);
354                 ret = -EFAULT;
355                 goto err_setmode;
356         }
357
358         log_debug("previous VT KBMODE was %d", vt->real_kbmode);
359         if (vt->real_kbmode == K_OFF) {
360                 log_warning("VT KBMODE was K_OFF, using K_UNICODE instead");
361                 vt->real_kbmode = K_UNICODE;
362         }
363
364         ret = ioctl(vt->real_fd, KDSKBMODE, K_RAW);
365         if (ret) {
366                 log_error("cannot set VT KBMODE to K_RAW (%d): %m", errno);
367                 ret = -EFAULT;
368                 goto err_setmode;
369         }
370
371         ret = ioctl(vt->real_fd, KDSKBMODE, K_OFF);
372         if (ret)
373                 log_warning("cannot set VT KBMODE to K_OFF (%d): %m", errno);
374
375         if (vts.v_active == vt->real_num) {
376                 ret = ev_eloop_register_idle_cb(vt->vtm->eloop, real_delayed,
377                                                 vt, EV_NORMAL);
378                 if (ret) {
379                         log_error("cannot register idle cb for VT switch");
380                         goto err_kbdmode;
381                 }
382                 vt->real_delayed = true;
383                 uterm_input_wake_up(vt->input);
384         }
385
386         return 0;
387
388 err_kbdmode:
389         err = ioctl(vt->real_fd, KDSKBMODE, vt->real_kbmode);
390         if (err)
391                 log_error("cannot reset VT KBMODE to %d (%d): %m",
392                           vt->real_kbmode, errno);
393 err_setmode:
394         memset(&mode, 0, sizeof(mode));
395         mode.mode = VT_AUTO;
396         err = ioctl(vt->real_fd, VT_SETMODE, &mode);
397         if (err)
398                 log_warning("cannot reset VT %d to VT_AUTO mode (%d): %m",
399                             vt->real_num, errno);
400 err_text:
401         err = ioctl(vt->real_fd, KDSETMODE, KD_TEXT);
402         if (err)
403                 log_warning("cannot reset VT %d to text-mode (%d): %m",
404                             vt->real_num, errno);
405 err_eloop:
406         ev_eloop_rm_fd(vt->real_efd);
407         vt->real_efd = NULL;
408 err_fd:
409         close(vt->real_fd);
410         return ret;
411 }
412
413 static void real_close(struct uterm_vt *vt)
414 {
415         struct vt_mode mode;
416         int ret;
417
418         log_debug("closing VT %d", vt->real_num);
419
420         if (vt->real_delayed) {
421                 vt->real_delayed = false;
422                 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
423                                             EV_NORMAL);
424                 uterm_input_sleep(vt->input);
425         } else if (vt->active) {
426                 uterm_input_sleep(vt->input);
427         }
428         vt_call_deactivate(vt, true);
429
430         ret = ioctl(vt->real_fd, KDSKBMODE, vt->real_kbmode);
431         if (ret && !vt->hup)
432                 log_error("cannot reset VT KBMODE to %d (%d): %m",
433                           vt->real_kbmode, errno);
434
435         memset(&mode, 0, sizeof(mode));
436         mode.mode = VT_AUTO;
437         ret = ioctl(vt->real_fd, VT_SETMODE, &mode);
438         if (ret && !vt->hup)
439                 log_warning("cannot reset VT %d to VT_AUTO mode (%d): %m",
440                             vt->real_num, errno);
441
442         ret = ioctl(vt->real_fd, KDSETMODE, KD_TEXT);
443         if (ret && !vt->hup)
444                 log_warning("cannot reset VT %d to text-mode (%d): %m",
445                             vt->real_num, errno);
446
447         ev_eloop_rm_fd(vt->real_efd);
448         vt->real_efd = NULL;
449         close(vt->real_fd);
450
451         vt->real_fd = -1;
452         vt->real_num = -1;
453         vt->real_saved_num = -1;
454         vt->real_target = -1;
455 }
456
457 /* Switch to this VT and make it the active VT. If we are already the active
458  * VT, then 0 is returned, if the VT_ACTIVATE ioctl is called to activate this
459  * VT, then -EINPROGRESS is returned and we will be activated when receiving the
460  * VT switch signal. The currently active VT may prevent this, though.
461  * On error a negative error code is returned other than -EINPROGRESS */
462 static int real_activate(struct uterm_vt *vt)
463 {
464         int ret;
465         struct vt_stat vts;
466
467         if (vt->hup)
468                 return -EPIPE;
469
470         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
471         if (ret)
472                 log_warn("cannot find current VT (%d): %m", errno);
473         else if (vts.v_active == vt->real_num)
474                 return 0;
475
476         if (vt->active)
477                 log_warning("activating VT %d even though it's already active",
478                             vt->real_num);
479
480         vt->real_target = -1;
481         ret = ioctl(vt->real_fd, VT_ACTIVATE, vt->real_num);
482         if (ret) {
483                 log_warn("cannot enter VT %d (%d): %m", vt->real_num, errno);
484                 return -EFAULT;
485         }
486
487         log_debug("entering VT %d on demand", vt->real_num);
488         return -EINPROGRESS;
489 }
490
491 /*
492  * Switch back to the VT from which we started.
493  * Note: The VT switch needs to be acknowledged by us so we need to react on
494  * SIGUSR. This function returns -EINPROGRESS if we started the VT switch but
495  * still needs to react on SIGUSR. Make sure you call the eloop dispatcher again
496  * if you get -EINPROGRESS here.
497  *
498  * Returns 0 if the previous VT is already active.
499  * Returns -EINPROGRESS if we started the VT switch. Returns <0 on failure.
500  *
501  * When run as a daemon, the VT where we were started on is often no longer a
502  * safe return-path when we shut-down. Therefore, you might want to avoid
503  * calling this when started as a long-running daemon.
504  */
505 static int real_deactivate(struct uterm_vt *vt)
506 {
507         int ret;
508         struct vt_stat vts;
509
510         if (vt->hup)
511                 return -EPIPE;
512
513         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
514         if (ret) {
515                 log_warn("cannot find current VT (%d): %m", errno);
516                 return -EFAULT;
517         }
518
519         if (vts.v_active != vt->real_num || vts.v_active == vt->real_saved_num)
520                 return 0;
521
522         if (!vt->active)
523                 log_warning("deactivating VT %d even though it's not active",
524                             vt->real_num);
525
526         vt->real_target = vt->real_saved_num;
527         vt->real_target_time = time(NULL);
528         ret = ioctl(vt->real_fd, VT_ACTIVATE, vt->real_saved_num);
529         if (ret) {
530                 log_warn("cannot leave VT %d to VT %d (%d): %m", vt->real_num,
531                          vt->real_saved_num, errno);
532                 return -EFAULT;
533         }
534
535         log_debug("leaving VT %d on demand to VT %d", vt->real_num,
536                   vt->real_saved_num);
537         return -EINPROGRESS;
538 }
539
540 static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev)
541 {
542         int id;
543         struct vt_stat vts;
544         int ret;
545
546         if (ev->handled || !vt->active || vt->hup)
547                 return;
548
549         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
550         if (ret) {
551                 log_warn("cannot find current VT (%d): %m", errno);
552                 return;
553         }
554
555         if (vts.v_active != vt->real_num)
556                 return;
557
558         id = 0;
559         if (SHL_HAS_BITS(ev->mods, SHL_CONTROL_MASK | SHL_ALT_MASK) &&
560             ev->keysyms[0] >= XKB_KEY_F1 && ev->keysyms[0] <= XKB_KEY_F12) {
561                 ev->handled = true;
562                 id = ev->keysyms[0] - XKB_KEY_F1 + 1;
563                 if (id == vt->real_num)
564                         return;
565         } else if (ev->keysyms[0] >= XKB_KEY_XF86Switch_VT_1 &&
566                    ev->keysyms[0] <= XKB_KEY_XF86Switch_VT_12) {
567                 ev->handled = true;
568                 id = ev->keysyms[0] - XKB_KEY_XF86Switch_VT_1 + 1;
569                 if (id == vt->real_num)
570                         return;
571         }
572
573         if (!id || id == vt->real_num)
574                 return;
575
576         log_debug("deactivating VT %d to %d due to user input", vt->real_num,
577                   id);
578
579         vt->real_target = id;
580         vt->real_target_time = time(NULL);
581         ret = ioctl(vt->real_fd, VT_ACTIVATE, id);
582         if (ret) {
583                 log_warn("cannot leave VT %d to %d (%d): %m", vt->real_num,
584                          id, errno);
585                 return;
586         }
587 }
588
589 static void real_retry(struct uterm_vt *vt)
590 {
591         struct vt_stat vts;
592         int ret;
593
594         if (vt->hup)
595                 return;
596
597         ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
598         if (ret) {
599                 log_warn("cannot find current VT (%d): %m", errno);
600                 return;
601         }
602
603         if (vts.v_active != vt->real_num || vt->real_target < 0)
604                 return;
605
606         /* hard limit of 2-3 seconds for asynchronous/pending VT-switches */
607         if (vt->real_target_time < time(NULL) - 3) {
608                 vt->real_target = -1;
609                 return;
610         }
611
612         if (!vt->active)
613                 log_warning("leaving VT %d even though it's not active",
614                             vt->real_num);
615
616         log_debug("deactivating VT %d to %d (retry)", vt->real_num,
617                   vt->real_target);
618
619         ret = ioctl(vt->real_fd, VT_ACTIVATE, vt->real_target);
620         if (ret) {
621                 log_warn("cannot leave VT %d to %d (%d): %m", vt->real_num,
622                          vt->real_target, errno);
623                 return;
624         }
625 }
626
627 /*
628  * Fake VT:
629  * For systems without CONFIG_VT or for all seats that have no real VTs (which
630  * is all seats except seat0), we support a fake-VT mechanism. This mechanism is
631  * only used for debugging and should not be used in production.
632  *
633  * Fake-VTs react on a key-press and activate themselves if not active. If they
634  * are already active, they deactivate themselves. To switch from one fake-VT to
635  * another, you first need to deactivate the current fake-VT and then activate
636  * the new fake-VT. This also means that you must use different hotkeys for each
637  * fake-VT.
638  * This is a very fragile infrastructure and should only be used for debugging.
639  *
640  * To avoid this bad situation, you simply activate a fake-VT during startup
641  * with uterm_vt_activate() and then do not use the hotkeys at all. This assumes
642  * that the fake-VT is the only application on this seat.
643  *
644  * If you use multiple fake-VTs on a seat without real-VTs, you should really
645  * use some other daemon that handles VT-switches. Otherwise, there is no sane
646  * way to communicate this between the fake-VTs. So please use fake-VTs only for
647  * debugging or if they are the only session on their seat.
648  */
649
650 static int fake_activate(struct uterm_vt *vt)
651 {
652         log_debug("activating fake VT due to user request");
653         vt_call_activate(vt);
654         return 0;
655 }
656
657 static int fake_deactivate(struct uterm_vt *vt)
658 {
659         log_debug("deactivating fake VT due to user request");
660         return vt_call_deactivate(vt, false);
661 }
662
663 static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
664 {
665         if (ev->handled)
666                 return;
667
668         if (SHL_HAS_BITS(ev->mods, SHL_CONTROL_MASK | SHL_LOGO_MASK) &&
669             ev->keysyms[0] == XKB_KEY_F12) {
670                 ev->handled = true;
671                 if (vt->active) {
672                         log_debug("deactivating fake VT due to user input");
673                         vt_call_deactivate(vt, false);
674                 } else {
675                         log_debug("activating fake VT due to user input");
676                         vt_call_activate(vt);
677                 }
678         }
679 }
680
681 static int fake_open(struct uterm_vt *vt)
682 {
683         uterm_input_wake_up(vt->input);
684         return 0;
685 }
686
687 static void fake_close(struct uterm_vt *vt)
688 {
689         vt_call_deactivate(vt, true);
690         uterm_input_sleep(vt->input);
691 }
692
693 /*
694  * Generic VT handling layer
695  * VTs are a historical concept. Technically, they actually are a VT102
696  * compatible terminal emulator, but with the invention of X11 and other
697  * graphics servers, VTs were mainly used to control which application is
698  * currently active.
699  * If an application is "active" it is allowed to read keyboard/mouse/etc input
700  * and access the output devices (like displays/monitors). If an application is
701  * not active (that is, inactive) it should not access these devices at all and
702  * leave them for other VTs so they can access them.
703  *
704  * The kernel VTs have a horrible API and thus should be avoided whenever
705  * possible. We provide a layer for this VT as "real_*" VTs here. If those are
706  * not available, we also provide a layer for "fake_*" VTs. See their
707  * description for more information.
708  *
709  * If you allocate a new VT with this API, it automatically chooses the right
710  * implementation for you. So you are notified whenever your VT becomes active
711  * and when it becomes inactive. You do not have to care for any other VT
712  * handling.
713  */
714
715 static void vt_input(struct uterm_input *input,
716                      struct uterm_input_event *ev,
717                      void *data)
718 {
719         struct uterm_vt *vt = data;
720
721         if (vt->mode == UTERM_VT_REAL)
722                 real_input(vt, ev);
723         else if (vt->mode == UTERM_VT_FAKE)
724                 fake_input(vt, ev);
725 }
726
727 static void vt_sigusr1(struct ev_eloop *eloop, struct signalfd_siginfo *info,
728                        void *data)
729 {
730         struct uterm_vt *vt = data;
731
732         if (vt->mode == UTERM_VT_REAL)
733                 real_sig_enter(vt, info);
734 }
735
736 static void vt_sigusr2(struct ev_eloop *eloop, struct signalfd_siginfo *info,
737                        void *data)
738 {
739         struct uterm_vt *vt = data;
740
741         if (vt->mode == UTERM_VT_REAL)
742                 real_sig_leave(vt, info);
743 }
744
745 static int seat_find_vt(const char *seat, char **out)
746 {
747         static const char def_vt[] = "/dev/tty0";
748         char *vt;
749         int ret, fd, err1, id;
750         struct stat st;
751
752         ret = asprintf(&vt, "/dev/ttyF%s", seat);
753         if (ret < 0)
754                 return -ENOMEM;
755
756         if (!access(vt, F_OK)) {
757                 log_debug("using fake-VT %s", vt);
758                 *out = vt;
759                 return 0;
760         }
761
762         free(vt);
763
764         if (!strcmp(seat, "seat0") && !access(def_vt, F_OK)) {
765                 /* First check whether our controlling terminal is a real VT. If
766                  * it is, use it but verify very hard that it really is. */
767                 ret = fstat(STDERR_FILENO, &st);
768                 if (!ret && major(st.st_rdev) == TTY_MAJOR &&
769                     minor(st.st_rdev) > 0) {
770                         ret = asprintf(&vt, "/dev/tty%d", minor(st.st_rdev));
771                         if (ret < 0)
772                                 return -ENOMEM;
773
774                         if (!access(vt, F_OK)) {
775                                 *out = vt;
776                                 return 0;
777                         }
778
779                         free(vt);
780                 }
781
782                 /* Otherwise, try to find a new terminal via the OPENQRY ioctl
783                  * on any existing VT. */
784                 fd = open(def_vt, O_NONBLOCK | O_NOCTTY | O_CLOEXEC);
785                 if (fd < 0) {
786                         err1 = errno;
787                         fd = open("/dev/tty1",
788                                   O_NONBLOCK | O_NOCTTY | O_CLOEXEC);
789                         if (fd < 0) {
790                                 log_error("cannot find parent tty (%d, %d): %m",
791                                           err1, errno);
792                                 return -EFAULT;
793                         }
794                 }
795
796                 errno = 0;
797                 if (ioctl(fd, VT_OPENQRY, &id) || id <= 0) {
798                         close(fd);
799                         log_err("cannot get unused tty (%d): %m", errno);
800                         return -EINVAL;
801                 }
802                 close(fd);
803
804                 ret = asprintf(&vt, "/dev/tty%d", id);
805                 if (ret < 0)
806                         return -ENOMEM;
807
808                 *out = vt;
809                 return 0;
810         }
811
812         *out = NULL;
813         return 0;
814 }
815
816 SHL_EXPORT
817 int uterm_vt_allocate(struct uterm_vt_master *vtm,
818                       struct uterm_vt **out,
819                       unsigned int allowed_types,
820                       const char *seat,
821                       struct uterm_input *input,
822                       const char *vt_name,
823                       uterm_vt_cb cb,
824                       void *data)
825 {
826         struct uterm_vt *vt;
827         int ret;
828         char *path;
829
830         if (!vtm || !out)
831                 return -EINVAL;
832         if (!seat)
833                 seat = "seat0";
834
835         vt = malloc(sizeof(*vt));
836         if (!vt)
837                 return -ENOMEM;
838         memset(vt, 0, sizeof(*vt));
839         vt->ref = 1;
840         vt->vtm = vtm;
841         vt->cb = cb;
842         vt->data = data;
843         vt->input = input;
844
845         vt->real_fd = -1;
846         vt->real_num = -1;
847         vt->real_saved_num = -1;
848
849         ret = ev_eloop_register_signal_cb(vtm->eloop, SIGUSR1, vt_sigusr1, vt);
850         if (ret)
851                 goto err_free;
852
853         ret = ev_eloop_register_signal_cb(vtm->eloop, SIGUSR2, vt_sigusr2, vt);
854         if (ret)
855                 goto err_sig1;
856
857         ret = uterm_input_register_cb(vt->input, vt_input, vt);
858         if (ret)
859                 goto err_sig2;
860
861         if (!vt_name) {
862                 ret = seat_find_vt(seat, &path);
863                 if (ret)
864                         goto err_input;
865         } else {
866                 path = NULL;
867         }
868
869         if (vt_name || path) {
870                 if (!(allowed_types & UTERM_VT_REAL)) {
871                         ret = -ERANGE;
872                         free(path);
873                         goto err_input;
874                 }
875                 vt->mode = UTERM_VT_REAL;
876                 ret = real_open(vt, vt_name ? vt_name : path);
877         } else {
878                 if (!(allowed_types & UTERM_VT_FAKE)) {
879                         ret = -ERANGE;
880                         free(path);
881                         goto err_input;
882                 }
883                 vt->mode = UTERM_VT_FAKE;
884                 ret = fake_open(vt);
885         }
886
887         free(path);
888         if (ret)
889                 goto err_input;
890
891         uterm_input_ref(vt->input);
892         shl_dlist_link(&vtm->vts, &vt->list);
893         *out = vt;
894         return 0;
895
896 err_input:
897         uterm_input_unregister_cb(vt->input, vt_input, vt);
898 err_sig2:
899         ev_eloop_unregister_signal_cb(vtm->eloop, SIGUSR2, vt_sigusr2, vt);
900 err_sig1:
901         ev_eloop_unregister_signal_cb(vtm->eloop, SIGUSR1, vt_sigusr1, vt);
902 err_free:
903         free(vt);
904         return ret;
905 }
906
907 SHL_EXPORT
908 void uterm_vt_deallocate(struct uterm_vt *vt)
909 {
910         if (!vt || !vt->vtm)
911                 return;
912
913         if (vt->mode == UTERM_VT_REAL)
914                 real_close(vt);
915         else if (vt->mode == UTERM_VT_FAKE)
916                 fake_close(vt);
917
918         ev_eloop_unregister_signal_cb(vt->vtm->eloop, SIGUSR2, vt_sigusr2, vt);
919         ev_eloop_unregister_signal_cb(vt->vtm->eloop, SIGUSR1, vt_sigusr1, vt);
920         shl_dlist_unlink(&vt->list);
921         uterm_input_unref(vt->input);
922         vt->vtm = NULL;
923         uterm_vt_unref(vt);
924 }
925
926 SHL_EXPORT
927 void uterm_vt_ref(struct uterm_vt *vt)
928 {
929         if (!vt || !vt->ref)
930                 return;
931
932         ++vt->ref;
933 }
934
935 SHL_EXPORT
936 void uterm_vt_unref(struct uterm_vt *vt)
937 {
938         if (!vt || !vt->ref || --vt->ref)
939                 return;
940
941         uterm_vt_deallocate(vt);
942         free(vt);
943 }
944
945 SHL_EXPORT
946 int uterm_vt_activate(struct uterm_vt *vt)
947 {
948         if (!vt || !vt->vtm)
949                 return -EINVAL;
950
951         if (vt->mode == UTERM_VT_REAL)
952                 return real_activate(vt);
953         else
954                 return fake_activate(vt);
955 }
956
957 SHL_EXPORT
958 int uterm_vt_deactivate(struct uterm_vt *vt)
959 {
960         if (!vt || !vt->vtm)
961                 return -EINVAL;
962
963         if (vt->mode == UTERM_VT_REAL)
964                 return real_deactivate(vt);
965         else
966                 return fake_deactivate(vt);
967 }
968
969 SHL_EXPORT
970 void uterm_vt_retry(struct uterm_vt *vt)
971 {
972         if (!vt || !vt->vtm)
973                 return;
974
975         if (vt->mode == UTERM_VT_REAL)
976                 real_retry(vt);
977 }
978
979 SHL_EXPORT
980 unsigned int uterm_vt_get_type(struct uterm_vt *vt)
981 {
982         if (!vt)
983                 return UTERM_VT_FAKE;
984
985         return vt->mode;
986 }
987
988 SHL_EXPORT
989 int uterm_vt_master_new(struct uterm_vt_master **out,
990                         struct ev_eloop *eloop)
991 {
992         struct uterm_vt_master *vtm;
993
994         if (!out || !eloop)
995                 return -EINVAL;
996
997         vtm = malloc(sizeof(*vtm));
998         if (!vtm)
999                 return -ENOMEM;
1000         memset(vtm, 0, sizeof(*vtm));
1001         vtm->ref = 1;
1002         vtm->eloop = eloop;
1003         shl_dlist_init(&vtm->vts);
1004
1005         ev_eloop_ref(vtm->eloop);
1006         *out = vtm;
1007         return 0;
1008 }
1009
1010 SHL_EXPORT
1011 void uterm_vt_master_ref(struct uterm_vt_master *vtm)
1012 {
1013         if (!vtm || !vtm->ref)
1014                 return;
1015
1016         ++vtm->ref;
1017 }
1018
1019 /* Drops a reference to the VT-master. If the reference drops to 0, all
1020  * allocated VTs are deallocated and the VT-master is destroyed. */
1021 SHL_EXPORT
1022 void uterm_vt_master_unref(struct uterm_vt_master *vtm)
1023 {
1024         struct uterm_vt *vt;
1025
1026         if (!vtm || !vtm->ref || --vtm->ref)
1027                 return;
1028
1029         while (vtm->vts.next != &vtm->vts) {
1030                 vt = shl_dlist_entry(vtm->vts.next,
1031                                         struct uterm_vt,
1032                                         list);
1033                 uterm_vt_deallocate(vt);
1034         }
1035
1036         ev_eloop_unref(vtm->eloop);
1037         free(vtm);
1038 }
1039
1040 /* Calls uterm_vt_activate() on all allocated VTs on this master. Returns
1041  * number of VTs that returned -EINPROGRESS or a negative error code on failure.
1042  * See uterm_vt_activate() for information. */
1043 SHL_EXPORT
1044 int uterm_vt_master_activate_all(struct uterm_vt_master *vtm)
1045 {
1046         struct uterm_vt *vt;
1047         struct shl_dlist *iter;
1048         int ret, res = 0;
1049         unsigned int in_progress = 0;
1050
1051         if (!vtm)
1052                 return -EINVAL;
1053
1054         shl_dlist_for_each(iter, &vtm->vts) {
1055                 vt = shl_dlist_entry(iter, struct uterm_vt, list);
1056                 ret = uterm_vt_activate(vt);
1057                 if (ret == -EINPROGRESS)
1058                         in_progress++;
1059                 else if (ret)
1060                         res = ret;
1061         }
1062
1063         if (in_progress)
1064                 return in_progress;
1065
1066         return res;
1067 }
1068
1069 /* Calls uterm_vt_deactivate() on all allocated VTs on this master. Returns
1070  * number of VTs that returned -EINPROGRESS or a negative error code on failure.
1071  * See uterm_vt_deactivate() for information. */
1072 SHL_EXPORT
1073 int uterm_vt_master_deactivate_all(struct uterm_vt_master *vtm)
1074 {
1075         struct uterm_vt *vt;
1076         struct shl_dlist *iter;
1077         int ret, res = 0;
1078         unsigned int in_progress = 0;
1079
1080         if (!vtm)
1081                 return -EINVAL;
1082
1083         shl_dlist_for_each(iter, &vtm->vts) {
1084                 vt = shl_dlist_entry(iter, struct uterm_vt, list);
1085                 ret = uterm_vt_deactivate(vt);
1086                 if (ret == -EINPROGRESS)
1087                         in_progress++;
1088                 else if (ret)
1089                         res = ret;
1090         }
1091
1092         if (in_progress)
1093                 return in_progress;
1094
1095         return res;
1096 }