2 * uterm - Linux User-Space Terminal
4 * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
33 #include <linux/major.h>
40 #include <sys/ioctl.h>
41 #include <sys/signalfd.h>
46 #include <xkbcommon/xkbcommon-keysyms.h>
48 #include "shl_dlist.h"
51 #include "uterm_input.h"
54 #define LOG_SUBSYSTEM "vt"
58 struct shl_dlist list;
59 struct uterm_vt_master *vtm;
60 struct uterm_input *input;
69 /* this is for *real* linux kernel VTs */
74 struct ev_fd *real_efd;
77 time_t real_target_time;
80 struct uterm_vt_master {
82 struct ev_eloop *eloop;
87 static int vt_call(struct uterm_vt *vt, unsigned int event, int target,
91 struct uterm_vt_event ev;
93 memset(&ev, 0, sizeof(ev));
97 ev.flags |= UTERM_VT_FORCE;
100 case UTERM_VT_ACTIVATE:
106 ret = vt->cb(vt, &ev, vt->data);
108 log_warning("vt event handler returned %d instead of 0 on activation",
111 case UTERM_VT_DEACTIVATE:
117 ret = vt->cb(vt, &ev, vt->data);
120 log_warning("vt event handler returned %d instead of 0 on forced deactivation",
130 vt->active = !vt->active;
134 static void vt_call_activate(struct uterm_vt *vt)
136 vt_call(vt, UTERM_VT_ACTIVATE, vt->real_num, false);
139 static int vt_call_deactivate(struct uterm_vt *vt, bool force)
141 return vt_call(vt, UTERM_VT_DEACTIVATE, vt->real_target, force);
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.
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.
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.
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.
174 static void real_delayed(struct ev_eloop *eloop, void *unused, void *data)
176 struct uterm_vt *vt = data;
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);
184 static void real_sig_enter(struct uterm_vt *vt, struct signalfd_siginfo *info)
189 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
191 log_warning("cannot get current VT state (%d): %m", errno);
195 if (vts.v_active != vt->real_num)
198 if (vt->real_delayed) {
199 vt->real_delayed = false;
200 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
202 } else if (vt->active) {
203 log_warning("activating VT %d even though it's already active",
206 uterm_input_wake_up(vt->input);
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);
215 static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info)
221 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
223 log_warning("cannot get current VT state (%d): %m", errno);
227 if (vts.v_active != vt->real_num)
230 log_debug("leaving VT %d %p due to VT signal", vt->real_num, vt);
232 ret = vt_call_deactivate(vt, false);
234 ioctl(vt->real_fd, VT_RELDISP, 0);
235 log_debug("not leaving VT %d %p: %d", vt->real_num, vt, ret);
239 if (vt->real_delayed) {
240 vt->real_delayed = false;
241 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
243 uterm_input_sleep(vt->input);
244 } else if (!active) {
245 log_warning("deactivating VT %d even though it's not active",
248 uterm_input_sleep(vt->input);
251 vt->real_target = -1;
252 ioctl(vt->real_fd, VT_RELDISP, 1);
255 static void real_vt_input(struct ev_fd *fd, int mask, void *data)
257 struct uterm_vt *vt = data;
258 struct uterm_vt_event ev;
260 /* we ignore input from the VT because we get it from evdev */
261 if (mask & EV_READABLE)
262 tcflush(vt->real_fd, TCIFLUSH);
264 if (mask & (EV_HUP | EV_ERR)) {
265 log_debug("HUP on VT %d", vt->real_num);
269 memset(&ev, 0, sizeof(ev));
270 ev.action = UTERM_VT_HUP;
271 vt->cb(vt, &ev, vt->data);
276 static int open_tty(const char *dev, int *tty_fd, int *tty_num)
281 if (!dev || !tty_fd || !tty_num)
284 log_notice("using tty %s", dev);
286 fd = open(dev, O_RDWR | O_NOCTTY | O_CLOEXEC);
288 log_err("cannot open tty %s (%d): %m", dev, errno);
292 ret = fstat(fd, &st);
294 log_error("cannot introspect tty %s (%d): %m", dev, errno);
298 id = minor(st.st_rdev);
299 log_debug("new tty ID is %d", id);
306 static int real_open(struct uterm_vt *vt, const char *vt_name)
312 log_debug("open vt %p", vt);
314 ret = open_tty(vt_name, &vt->real_fd, &vt->real_num);
318 ret = ev_eloop_new_fd(vt->vtm->eloop, &vt->real_efd, vt->real_fd,
319 EV_READABLE, real_vt_input, vt);
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);
327 log_warn("cannot find the currently active VT (%d): %m", errno);
331 vt->real_saved_num = vts.v_active;
332 vt->real_target = -1;
334 if (ioctl(vt->real_fd, KDSETMODE, KD_GRAPHICS)) {
335 log_err("cannot put VT in graphics mode (%d): %m", errno);
340 memset(&mode, 0, sizeof(mode));
341 mode.mode = VT_PROCESS;
342 mode.acqsig = SIGUSR1;
343 mode.relsig = SIGUSR2;
345 if (ioctl(vt->real_fd, VT_SETMODE, &mode)) {
346 log_err("cannot take control of vt handling (%d): %m", errno);
351 ret = ioctl(vt->real_fd, KDGKBMODE, &vt->real_kbmode);
353 log_error("cannot retrieve VT KBMODE (%d): %m", errno);
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;
364 ret = ioctl(vt->real_fd, KDSKBMODE, K_RAW);
366 log_error("cannot set VT KBMODE to K_RAW (%d): %m", errno);
371 ret = ioctl(vt->real_fd, KDSKBMODE, K_OFF);
373 log_warning("cannot set VT KBMODE to K_OFF (%d): %m", errno);
375 if (vts.v_active == vt->real_num) {
376 ret = ev_eloop_register_idle_cb(vt->vtm->eloop, real_delayed,
379 log_error("cannot register idle cb for VT switch");
382 vt->real_delayed = true;
383 uterm_input_wake_up(vt->input);
389 err = ioctl(vt->real_fd, KDSKBMODE, vt->real_kbmode);
391 log_error("cannot reset VT KBMODE to %d (%d): %m",
392 vt->real_kbmode, errno);
394 memset(&mode, 0, sizeof(mode));
396 err = ioctl(vt->real_fd, VT_SETMODE, &mode);
398 log_warning("cannot reset VT %d to VT_AUTO mode (%d): %m",
399 vt->real_num, errno);
401 err = ioctl(vt->real_fd, KDSETMODE, KD_TEXT);
403 log_warning("cannot reset VT %d to text-mode (%d): %m",
404 vt->real_num, errno);
406 ev_eloop_rm_fd(vt->real_efd);
413 static void real_close(struct uterm_vt *vt)
418 log_debug("closing VT %d", vt->real_num);
420 if (vt->real_delayed) {
421 vt->real_delayed = false;
422 ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt,
424 uterm_input_sleep(vt->input);
425 } else if (vt->active) {
426 uterm_input_sleep(vt->input);
428 vt_call_deactivate(vt, true);
430 ret = ioctl(vt->real_fd, KDSKBMODE, vt->real_kbmode);
432 log_error("cannot reset VT KBMODE to %d (%d): %m",
433 vt->real_kbmode, errno);
435 memset(&mode, 0, sizeof(mode));
437 ret = ioctl(vt->real_fd, VT_SETMODE, &mode);
439 log_warning("cannot reset VT %d to VT_AUTO mode (%d): %m",
440 vt->real_num, errno);
442 ret = ioctl(vt->real_fd, KDSETMODE, KD_TEXT);
444 log_warning("cannot reset VT %d to text-mode (%d): %m",
445 vt->real_num, errno);
447 ev_eloop_rm_fd(vt->real_efd);
453 vt->real_saved_num = -1;
454 vt->real_target = -1;
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)
470 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
472 log_warn("cannot find current VT (%d): %m", errno);
473 else if (vts.v_active == vt->real_num)
477 log_warning("activating VT %d even though it's already active",
480 vt->real_target = -1;
481 ret = ioctl(vt->real_fd, VT_ACTIVATE, vt->real_num);
483 log_warn("cannot enter VT %d (%d): %m", vt->real_num, errno);
487 log_debug("entering VT %d on demand", vt->real_num);
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.
498 * Returns 0 if the previous VT is already active.
499 * Returns -EINPROGRESS if we started the VT switch. Returns <0 on failure.
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.
505 static int real_deactivate(struct uterm_vt *vt)
513 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
515 log_warn("cannot find current VT (%d): %m", errno);
519 if (vts.v_active != vt->real_num || vts.v_active == vt->real_saved_num)
523 log_warning("deactivating VT %d even though it's not active",
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);
530 log_warn("cannot leave VT %d to VT %d (%d): %m", vt->real_num,
531 vt->real_saved_num, errno);
535 log_debug("leaving VT %d on demand to VT %d", vt->real_num,
540 static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev)
546 if (ev->handled || !vt->active || vt->hup)
549 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
551 log_warn("cannot find current VT (%d): %m", errno);
555 if (vts.v_active != vt->real_num)
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) {
562 id = ev->keysyms[0] - XKB_KEY_F1 + 1;
563 if (id == vt->real_num)
565 } else if (ev->keysyms[0] >= XKB_KEY_XF86Switch_VT_1 &&
566 ev->keysyms[0] <= XKB_KEY_XF86Switch_VT_12) {
568 id = ev->keysyms[0] - XKB_KEY_XF86Switch_VT_1 + 1;
569 if (id == vt->real_num)
573 if (!id || id == vt->real_num)
576 log_debug("deactivating VT %d to %d due to user input", vt->real_num,
579 vt->real_target = id;
580 vt->real_target_time = time(NULL);
581 ret = ioctl(vt->real_fd, VT_ACTIVATE, id);
583 log_warn("cannot leave VT %d to %d (%d): %m", vt->real_num,
589 static void real_retry(struct uterm_vt *vt)
597 ret = ioctl(vt->real_fd, VT_GETSTATE, &vts);
599 log_warn("cannot find current VT (%d): %m", errno);
603 if (vts.v_active != vt->real_num || vt->real_target < 0)
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;
613 log_warning("leaving VT %d even though it's not active",
616 log_debug("deactivating VT %d to %d (retry)", vt->real_num,
619 ret = ioctl(vt->real_fd, VT_ACTIVATE, vt->real_target);
621 log_warn("cannot leave VT %d to %d (%d): %m", vt->real_num,
622 vt->real_target, errno);
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.
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
638 * This is a very fragile infrastructure and should only be used for debugging.
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.
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.
650 static int fake_activate(struct uterm_vt *vt)
652 log_debug("activating fake VT due to user request");
653 vt_call_activate(vt);
657 static int fake_deactivate(struct uterm_vt *vt)
659 log_debug("deactivating fake VT due to user request");
660 return vt_call_deactivate(vt, false);
663 static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
668 if (SHL_HAS_BITS(ev->mods, SHL_CONTROL_MASK | SHL_LOGO_MASK) &&
669 ev->keysyms[0] == XKB_KEY_F12) {
672 log_debug("deactivating fake VT due to user input");
673 vt_call_deactivate(vt, false);
675 log_debug("activating fake VT due to user input");
676 vt_call_activate(vt);
681 static int fake_open(struct uterm_vt *vt)
683 uterm_input_wake_up(vt->input);
687 static void fake_close(struct uterm_vt *vt)
689 vt_call_deactivate(vt, true);
690 uterm_input_sleep(vt->input);
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
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.
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.
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
715 static void vt_input(struct uterm_input *input,
716 struct uterm_input_event *ev,
719 struct uterm_vt *vt = data;
721 if (vt->mode == UTERM_VT_REAL)
723 else if (vt->mode == UTERM_VT_FAKE)
727 static void vt_sigusr1(struct ev_eloop *eloop, struct signalfd_siginfo *info,
730 struct uterm_vt *vt = data;
732 if (vt->mode == UTERM_VT_REAL)
733 real_sig_enter(vt, info);
736 static void vt_sigusr2(struct ev_eloop *eloop, struct signalfd_siginfo *info,
739 struct uterm_vt *vt = data;
741 if (vt->mode == UTERM_VT_REAL)
742 real_sig_leave(vt, info);
745 static int seat_find_vt(const char *seat, char **out)
747 static const char def_vt[] = "/dev/tty0";
749 int ret, fd, err1, id;
752 ret = asprintf(&vt, "/dev/ttyF%s", seat);
756 if (!access(vt, F_OK)) {
757 log_debug("using fake-VT %s", vt);
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));
774 if (!access(vt, F_OK)) {
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);
787 fd = open("/dev/tty1",
788 O_NONBLOCK | O_NOCTTY | O_CLOEXEC);
790 log_error("cannot find parent tty (%d, %d): %m",
797 if (ioctl(fd, VT_OPENQRY, &id) || id <= 0) {
799 log_err("cannot get unused tty (%d): %m", errno);
804 ret = asprintf(&vt, "/dev/tty%d", id);
817 int uterm_vt_allocate(struct uterm_vt_master *vtm,
818 struct uterm_vt **out,
819 unsigned int allowed_types,
821 struct uterm_input *input,
835 vt = malloc(sizeof(*vt));
838 memset(vt, 0, sizeof(*vt));
847 vt->real_saved_num = -1;
849 ret = ev_eloop_register_signal_cb(vtm->eloop, SIGUSR1, vt_sigusr1, vt);
853 ret = ev_eloop_register_signal_cb(vtm->eloop, SIGUSR2, vt_sigusr2, vt);
857 ret = uterm_input_register_cb(vt->input, vt_input, vt);
862 ret = seat_find_vt(seat, &path);
869 if (vt_name || path) {
870 if (!(allowed_types & UTERM_VT_REAL)) {
875 vt->mode = UTERM_VT_REAL;
876 ret = real_open(vt, vt_name ? vt_name : path);
878 if (!(allowed_types & UTERM_VT_FAKE)) {
883 vt->mode = UTERM_VT_FAKE;
891 uterm_input_ref(vt->input);
892 shl_dlist_link(&vtm->vts, &vt->list);
897 uterm_input_unregister_cb(vt->input, vt_input, vt);
899 ev_eloop_unregister_signal_cb(vtm->eloop, SIGUSR2, vt_sigusr2, vt);
901 ev_eloop_unregister_signal_cb(vtm->eloop, SIGUSR1, vt_sigusr1, vt);
908 void uterm_vt_deallocate(struct uterm_vt *vt)
913 if (vt->mode == UTERM_VT_REAL)
915 else if (vt->mode == UTERM_VT_FAKE)
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);
927 void uterm_vt_ref(struct uterm_vt *vt)
936 void uterm_vt_unref(struct uterm_vt *vt)
938 if (!vt || !vt->ref || --vt->ref)
941 uterm_vt_deallocate(vt);
946 int uterm_vt_activate(struct uterm_vt *vt)
951 if (vt->mode == UTERM_VT_REAL)
952 return real_activate(vt);
954 return fake_activate(vt);
958 int uterm_vt_deactivate(struct uterm_vt *vt)
963 if (vt->mode == UTERM_VT_REAL)
964 return real_deactivate(vt);
966 return fake_deactivate(vt);
970 void uterm_vt_retry(struct uterm_vt *vt)
975 if (vt->mode == UTERM_VT_REAL)
980 unsigned int uterm_vt_get_type(struct uterm_vt *vt)
983 return UTERM_VT_FAKE;
989 int uterm_vt_master_new(struct uterm_vt_master **out,
990 struct ev_eloop *eloop)
992 struct uterm_vt_master *vtm;
997 vtm = malloc(sizeof(*vtm));
1000 memset(vtm, 0, sizeof(*vtm));
1003 shl_dlist_init(&vtm->vts);
1005 ev_eloop_ref(vtm->eloop);
1011 void uterm_vt_master_ref(struct uterm_vt_master *vtm)
1013 if (!vtm || !vtm->ref)
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. */
1022 void uterm_vt_master_unref(struct uterm_vt_master *vtm)
1024 struct uterm_vt *vt;
1026 if (!vtm || !vtm->ref || --vtm->ref)
1029 while (vtm->vts.next != &vtm->vts) {
1030 vt = shl_dlist_entry(vtm->vts.next,
1033 uterm_vt_deallocate(vt);
1036 ev_eloop_unref(vtm->eloop);
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. */
1044 int uterm_vt_master_activate_all(struct uterm_vt_master *vtm)
1046 struct uterm_vt *vt;
1047 struct shl_dlist *iter;
1049 unsigned int in_progress = 0;
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)
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. */
1073 int uterm_vt_master_deactivate_all(struct uterm_vt_master *vtm)
1075 struct uterm_vt *vt;
1076 struct shl_dlist *iter;
1078 unsigned int in_progress = 0;
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)