summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-10-23 15:15:50 +0200
committerDavid Herrmann <dh.herrmann@gmail.com>2013-10-23 15:15:50 +0200
commitbcfb1d2ab5a2b5177c8d1ca2947fa80ce5d99803 (patch)
tree89cae67e4aef3d3318434625e748ac5b8830277f /src
parent695c855da33c3ef40bdd6e5bce7a6a78875a7af8 (diff)
uvtd: remove
Remove uvtd. The idea is outdated and not really needed. With recent systemd-logind changes, all we need is a shim between legacy-programs (like XServer) and logind. We can easily do that via libuvt without requiring a huge daemon like uvtd. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/uvtd_ctx.c474
-rw-r--r--src/uvtd_ctx.h48
-rw-r--r--src/uvtd_main.c276
-rw-r--r--src/uvtd_seat.c630
-rw-r--r--src/uvtd_seat.h96
-rw-r--r--src/uvtd_vt.c419
-rw-r--r--src/uvtd_vt.h54
7 files changed, 0 insertions, 1997 deletions
diff --git a/src/uvtd_ctx.c b/src/uvtd_ctx.c
deleted file mode 100644
index 20a9220..0000000
--- a/src/uvtd_ctx.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Contexts
- * A context manages a single UVT seat. It creates the seat object, allocates
- * the VTs and provides all the bookkeeping for the sessions. It's the main
- * entry point after the seat selectors in uvtd-main.
- *
- * For each seat we create two different kinds of character-devices:
- * /dev/ttyFC<seat>:
- * This is the control-node. It's the preferred way to open new VTs. It
- * provides a fully-backwards compatible VT API so legacy apps should be
- * able to make use of it. Each open-file is associated to a different VT so
- * you cannot share these easily, anymore. You need to pass the FD instead.
- * This avoids problems with multiple users on the same VT that we had in
- * the past.
- * /dev/ttyFD<seat>/tty<num>:
- * These are legacy VTs. They are put into a subdirectory and provide full
- * backwards compatibility to real VTs. They are preallocated and there is
- * only a limited number of them. You can control how many of these are
- * allocated via the configuration options.
- * These VTs can be shared between processes easily as all open-files on a
- * single node share the same VT.
- * All character devices share the MAJOR number that is also used by real VTs.
- * However, the minor numbers use a relatively high offset (default: 2^14) so
- * they don't clash with real VTs.
- * If you need backwards-compatible symlinks, you can use the minor number of a
- * VT node in /dev/ttyFD<seat>/tty<num> and create a symlink:
- * /dev/tty<minor> -> /dev/ttyFD<seat>/tty<num>
- * As the minors are globally unique, they won't clash with other tty nodes in
- * /dev. However, you loose the ability to see which seat a node is associated
- * to. So you normally look into /dev/ttyFD<seat>/, choose a node, look at the
- * minor and then open /dev/tty<minor> respectively.
- * This provides full backwards compatibility for applications that require
- * /dev/tty<num> paths (like old xservers).
- *
- * The VT logic is found in uvtd-vt subsystem. This file only provides the
- * character-device control nodes and links them to the right VTs.
- */
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "eloop.h"
-#include "shl_dlist.h"
-#include "shl_log.h"
-#include "uvt.h"
-#include "uvtd_ctx.h"
-#include "uvtd_seat.h"
-#include "uvtd_vt.h"
-
-#define LOG_SUBSYSTEM "ctx"
-
-struct ctx_legacy {
- struct shl_dlist list;
- struct uvtd_ctx *ctx;
- unsigned int minor;
- unsigned int id;
- struct uvt_cdev *cdev;
- struct uvtd_vt *vt;
-};
-
-struct uvtd_ctx {
- struct ev_eloop *eloop;
- struct uvt_ctx *uctx;
- struct uvtd_seat *seat;
- char *seatname;
-
- unsigned int main_cdev_minor;
- struct uvt_cdev *main_cdev;
-
- struct shl_dlist legacy_list;
- unsigned int legacy_num;
-};
-
-static int ctx_legacy_init_vt(struct ctx_legacy *legacy);
-
-static void ctx_legacy_vt_event(void *vt, struct uvt_vt_event *ev, void *data)
-{
- struct ctx_legacy *legacy = data;
-
- switch (ev->type) {
- case UVT_VT_TTY:
- if (ev->tty.type != UVT_TTY_HUP)
- break;
-
- /* fallthrough */
- case UVT_VT_HUP:
- log_debug("HUP on legacy VT %p", legacy);
-
- uvtd_vt_unregister_cb(legacy->vt, ctx_legacy_vt_event, legacy);
- uvtd_vt_unref(legacy->vt);
- legacy->vt = NULL;
- break;
- }
-}
-
-static void ctx_legacy_cdev_event(struct uvt_cdev *cdev,
- struct uvt_cdev_event *ev, void *data)
-{
- struct ctx_legacy *legacy = data;
- int ret;
-
- switch (ev->type) {
- case UVT_CDEV_HUP:
- log_warning("HUP on legacy cdev %p", cdev);
- uvt_cdev_unregister_cb(legacy->cdev, ctx_legacy_cdev_event,
- legacy);
- uvt_cdev_unref(legacy->cdev);
- legacy->cdev = NULL;
- break;
- case UVT_CDEV_OPEN:
- /* A legacy VT might get closed by the seat/session-scheduler at
- * any time. We want to avoid respawning it right away to avoid
- * error-throttling, so instead we respawn it when the next
- * client opens the underlying cdev. */
- if (!legacy->vt) {
- log_debug("reinitializing VT on legacy cdev %p",
- legacy);
- ret = ctx_legacy_init_vt(legacy);
- if (ret) {
- log_warning("cannot reinitialize VT on legacy cdev %p",
- legacy);
- uvt_client_kill(ev->client);
- break;
- }
- }
-
- ret = uvt_client_set_vt(ev->client, &uvtd_vt_ops, legacy->vt);
- if (ret) {
- log_warning("cannot assign VT to new client: %d",
- ret);
- uvt_client_kill(ev->client);
- }
- break;
- }
-}
-
-static int ctx_legacy_init_vt(struct ctx_legacy *legacy)
-{
- int ret;
-
- ret = uvtd_vt_new(&legacy->vt, legacy->ctx->uctx, legacy->id,
- legacy->ctx->seat, true);
- if (ret)
- return ret;
-
- ret = uvtd_vt_register_cb(legacy->vt, ctx_legacy_vt_event, legacy);
- if (ret) {
- uvtd_vt_unref(legacy->vt);
- legacy->vt = NULL;
- return ret;
- }
-
- return 0;
-}
-
-static int ctx_legacy_init_cdev(struct ctx_legacy *legacy)
-{
- char *name;
- int ret;
-
- ret = asprintf(&name, "ttyFD%s!tty%u", legacy->ctx->seatname,
- legacy->minor);
- if (ret <= 0)
- return -ENOMEM;
-
- ret = uvt_cdev_new(&legacy->cdev, legacy->ctx->uctx, name,
- uvt_ctx_get_major(legacy->ctx->uctx),
- legacy->minor);
- free(name);
-
- if (ret)
- return ret;
-
- ret = uvt_cdev_register_cb(legacy->cdev, ctx_legacy_cdev_event,
- legacy);
- if (ret) {
- uvt_cdev_unref(legacy->cdev);
- legacy->cdev = NULL;
- return ret;
- }
-
- return 0;
-}
-
-static int ctx_legacy_init(struct uvtd_ctx *ctx, unsigned int id)
-{
- struct ctx_legacy *legacy;
- int ret;
-
- legacy = malloc(sizeof(*legacy));
- if (!legacy)
- return -ENOMEM;
-
- log_debug("new legacy cdev %p on ctx %p", legacy, ctx);
-
- memset(legacy, 0, sizeof(*legacy));
- legacy->id = id;
- legacy->ctx = ctx;
-
- ret = uvt_ctx_new_minor(ctx->uctx, &legacy->minor);
- if (ret)
- goto err_free;
-
- ret = ctx_legacy_init_cdev(legacy);
- if (ret)
- goto err_minor;
-
- ret = ctx_legacy_init_vt(legacy);
- if (ret)
- goto err_cdev;
-
- shl_dlist_link(&ctx->legacy_list, &legacy->list);
- return 0;
-
-err_cdev:
- uvt_cdev_unregister_cb(legacy->cdev, ctx_legacy_cdev_event, legacy);
- uvt_cdev_unref(legacy->cdev);
-err_minor:
- uvt_ctx_free_minor(ctx->uctx, legacy->minor);
-err_free:
- free(legacy);
- return ret;
-}
-
-static void ctx_legacy_destroy(struct ctx_legacy *legacy)
-{
- log_debug("free legacy cdev %p", legacy);
-
- shl_dlist_unlink(&legacy->list);
- uvtd_vt_unregister_cb(legacy->vt, ctx_legacy_vt_event, legacy);
- uvtd_vt_unref(legacy->vt);
- uvt_cdev_unregister_cb(legacy->cdev, ctx_legacy_cdev_event, legacy);
- uvt_cdev_unref(legacy->cdev);
- uvt_ctx_free_minor(legacy->ctx->uctx, legacy->minor);
- free(legacy);
-}
-
-static void ctx_legacy_reconf(struct uvtd_ctx *ctx, unsigned int num)
-{
- struct ctx_legacy *l;
- struct shl_dlist *iter;
- unsigned int i;
- int ret;
-
- /* If a legacy cdev received a HUP or some other error and got closed,
- * we try to reinitialize it whenever the context is reconfigured. This
- * avoids implementing any error-throttling while at the same time users
- * can trigger a reinitialization with a reconfiguration.
- * This doesn't touch running cdevs, but only HUP'ed cdevs. */
- shl_dlist_for_each(iter, &ctx->legacy_list) {
- l = shl_dlist_entry(iter, struct ctx_legacy, list);
- if (l->cdev)
- continue;
-
- log_debug("reinitialize legacy cdev %p", l);
-
- ret = ctx_legacy_init_cdev(l);
- if (ret)
- log_warning("cannot reinitialize legacy cdev %p: %d",
- l, ret);
- }
-
- if (num == ctx->legacy_num)
- return;
-
- log_debug("changing #num of legacy cdevs on ctx %p from %u to %u",
- ctx, ctx->legacy_num, num);
-
- if (num > ctx->legacy_num) {
- for (i = ctx->legacy_num; i < num; ++i) {
- ret = ctx_legacy_init(ctx, i);
- if (ret)
- break;
- }
-
- ctx->legacy_num = i;
- } else {
- for (i = num; i < ctx->legacy_num; ++i) {
- l = shl_dlist_last(&ctx->legacy_list,
- struct ctx_legacy, list);
- ctx_legacy_destroy(l);
- }
-
- ctx->legacy_num = num;
- }
-}
-
-static void ctx_main_cdev_event(struct uvt_cdev *cdev,
- struct uvt_cdev_event *ev,
- void *data)
-{
- struct uvtd_ctx *ctx = data;
- struct uvtd_vt *vt;
- int ret;
-
- switch (ev->type) {
- case UVT_CDEV_HUP:
- log_warning("HUP on main cdev on ctx %p", ctx);
- uvt_cdev_unregister_cb(ctx->main_cdev, ctx_main_cdev_event,
- ctx);
- uvt_cdev_unref(ctx->main_cdev);
- ctx->main_cdev = NULL;
- break;
- case UVT_CDEV_OPEN:
- ret = uvtd_vt_new(&vt, ctx->uctx, 0, ctx->seat, false);
- if (ret)
- break;
-
- uvt_client_set_vt(ev->client, &uvtd_vt_ops, vt);
- uvtd_vt_unref(vt);
- break;
- }
-}
-
-static int ctx_init_cdev(struct uvtd_ctx *ctx)
-{
- int ret;
- char *name;
-
- ret = asprintf(&name, "ttyFC%s", ctx->seatname);
- if (ret <= 0)
- return -ENOMEM;
-
- ret = uvt_cdev_new(&ctx->main_cdev, ctx->uctx, name,
- uvt_ctx_get_major(ctx->uctx), ctx->main_cdev_minor);
- free(name);
-
- if (ret)
- return ret;
-
- ret = uvt_cdev_register_cb(ctx->main_cdev, ctx_main_cdev_event, ctx);
- if (ret) {
- uvt_cdev_unref(ctx->main_cdev);
- ctx->main_cdev = NULL;
- return ret;
- }
-
- return 0;
-}
-
-static bool has_real_vts(const char *seatname)
-{
- return !strcmp(seatname, "seat0") &&
- !access("/dev/tty0", F_OK);
-}
-
-int uvtd_ctx_new(struct uvtd_ctx **out, const char *seatname,
- struct ev_eloop *eloop, struct uvt_ctx *uctx)
-{
- struct uvtd_ctx *ctx;
- int ret;
-
- if (!out || !seatname || !eloop || !uctx)
- return -EINVAL;
-
- if (has_real_vts(seatname))
- return -EEXIST;
-
- ctx = malloc(sizeof(*ctx));
- if (!ctx)
- return -ENOMEM;
-
- log_debug("new ctx %p on seat %s", ctx, seatname);
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->eloop = eloop;
- ctx->uctx = uctx;
- shl_dlist_init(&ctx->legacy_list);
-
- ctx->seatname = strdup(seatname);
- if (!ctx->seatname) {
- ret = -ENOMEM;
- goto err_free;
- }
-
- ret = uvtd_seat_new(&ctx->seat, seatname, ctx->eloop, NULL, NULL);
- if (ret)
- goto err_name;
-
- ret = uvt_ctx_new_minor(ctx->uctx, &ctx->main_cdev_minor);
- if (ret)
- goto err_seat;
-
- ret = ctx_init_cdev(ctx);
- if (ret)
- goto err_minor;
-
- ev_eloop_ref(ctx->eloop);
- uvt_ctx_ref(ctx->uctx);
- *out = ctx;
-
- ctx_legacy_reconf(ctx, 8);
-
- return 0;
-
-err_minor:
- uvt_ctx_free_minor(ctx->uctx, ctx->main_cdev_minor);
-err_seat:
- uvtd_seat_free(ctx->seat);
-err_name:
- free(ctx->seatname);
-err_free:
- free(ctx);
- return ret;
-}
-
-void uvtd_ctx_free(struct uvtd_ctx *ctx)
-{
- if (!ctx)
- return;
-
- log_debug("free ctx %p", ctx);
-
- ctx_legacy_reconf(ctx, 0);
- uvt_cdev_unregister_cb(ctx->main_cdev, ctx_main_cdev_event, ctx);
- uvt_cdev_unref(ctx->main_cdev);
- uvt_ctx_free_minor(ctx->uctx, ctx->main_cdev_minor);
- uvtd_seat_free(ctx->seat);
- free(ctx->seatname);
- uvt_ctx_unref(ctx->uctx);
- ev_eloop_unref(ctx->eloop);
- free(ctx);
-}
-
-void uvtd_ctx_reconf(struct uvtd_ctx *ctx, unsigned int legacy_num)
-{
- int ret;
-
- if (!ctx)
- return;
-
- ctx_legacy_reconf(ctx, legacy_num);
-
- /* Lets recreate the control node if it got busted during runtime. We do
- * not recreate it right away after receiving a HUP signal to avoid
- * trapping into the same error that caused the HUP.
- * Instead we recreate the node on reconfiguration so users can control
- * when to recreate them. */
- if (!ctx->main_cdev) {
- log_debug("recreating main cdev on ctx %p", ctx);
- ret = ctx_init_cdev(ctx);
- if (ret)
- log_warning("cannot recreate main cdev on ctx %p",
- ctx);
- }
-}
diff --git a/src/uvtd_ctx.h b/src/uvtd_ctx.h
deleted file mode 100644
index 78e3f0b..0000000
--- a/src/uvtd_ctx.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Contexts
- * A context manages a single UVT seat. It creates the seat object, allocates
- * the VTs and provides all the bookkeeping for the sessions. It's the main
- * entry point after the seat selectors in uvtd-main.
- */
-
-#ifndef UVTD_CTX_H
-#define UVTD_CTX_H
-
-#include <stdlib.h>
-#include "eloop.h"
-#include "uvt.h"
-
-struct uvtd_ctx;
-
-int uvtd_ctx_new(struct uvtd_ctx **out, const char *seatname,
- struct ev_eloop *eloop, struct uvt_ctx *uctx);
-void uvtd_ctx_free(struct uvtd_ctx *ctx);
-
-void uvtd_ctx_reconf(struct uvtd_ctx *ctx, unsigned int legacy_num);
-
-#endif /* UVTD_CTX_H */
diff --git a/src/uvtd_main.c b/src/uvtd_main.c
deleted file mode 100644
index d4b70ff..0000000
--- a/src/uvtd_main.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@googlemail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/signalfd.h>
-#include "eloop.h"
-#include "shl_dlist.h"
-#include "shl_log.h"
-#include "uterm_input.h"
-#include "uterm_monitor.h"
-#include "uvt.h"
-#include "uvtd_ctx.h"
-
-struct app_seat {
- struct shl_dlist list;
- struct uvtd_app *app;
- struct uterm_monitor_seat *useat;
- struct uvtd_ctx *ctx;
-};
-
-struct uvtd_app {
- struct ev_eloop *eloop;
- struct uterm_monitor *mon;
- struct uvt_ctx *ctx;
- struct ev_fd *ctx_fd;
- struct shl_dlist seats;
-};
-
-static int app_seat_new(struct uvtd_app *app, const char *sname,
- struct uterm_monitor_seat *useat)
-{
- struct app_seat *seat;
- int ret;
-
- seat = malloc(sizeof(*seat));
- if (!seat)
- return -ENOMEM;
-
- log_debug("new seat %p on %s", seat, sname);
-
- memset(seat, 0, sizeof(*seat));
- seat->app = app;
- seat->useat = useat;
-
- ret = uvtd_ctx_new(&seat->ctx, sname, app->eloop, app->ctx);
- if (ret == -EEXIST) {
- log_debug("ignoring seat %s as it has real VTs", sname);
- goto err_free;
- } else if (ret) {
- goto err_free;
- }
-
- uterm_monitor_set_seat_data(seat->useat, seat);
- shl_dlist_link(&app->seats, &seat->list);
- return 0;
-
-err_free:
- free(seat);
- return ret;
-}
-
-static void app_seat_free(struct app_seat *seat)
-{
- log_debug("free seat %p", seat);
-
- shl_dlist_unlink(&seat->list);
- uterm_monitor_set_seat_data(seat->useat, NULL);
- uvtd_ctx_free(seat->ctx);
- free(seat);
-}
-
-static void app_monitor_event(struct uterm_monitor *mon,
- struct uterm_monitor_event *ev,
- void *data)
-{
- struct uvtd_app *app = data;
- struct app_seat *seat;
- int ret;
-
- switch (ev->type) {
- case UTERM_MONITOR_NEW_SEAT:
- ret = app_seat_new(app, ev->seat_name, ev->seat);
- if (ret)
- return;
- break;
- case UTERM_MONITOR_FREE_SEAT:
- if (ev->seat_data)
- app_seat_free(ev->seat_data);
- break;
- case UTERM_MONITOR_NEW_DEV:
- seat = ev->seat_data;
- if (!seat)
- return;
-
- switch (ev->dev_type) {
- case UTERM_MONITOR_INPUT:
- log_debug("new input device %s on seat %p",
- ev->dev_node, seat);
- break;
- }
- break;
- case UTERM_MONITOR_FREE_DEV:
- seat = ev->seat_data;
- if (!seat)
- return;
-
- switch (ev->dev_type) {
- case UTERM_MONITOR_INPUT:
- log_debug("free input device %s on seat %p",
- ev->dev_node, seat);
- break;
- }
- break;
- }
-}
-
-static void app_sig_generic(struct ev_eloop *eloop,
- struct signalfd_siginfo *info,
- void *data)
-{
- struct uvtd_app *app = data;
-
- log_info("terminating due to caught signal %d", info->ssi_signo);
- ev_eloop_exit(app->eloop);
-}
-
-static void app_sig_ignore(struct ev_eloop *eloop,
- struct signalfd_siginfo *info,
- void *data)
-{
-}
-
-static void app_ctx_event(struct ev_fd *fd, int mask, void *data)
-{
- struct uvtd_app *app = data;
-
- uvt_ctx_dispatch(app->ctx);
-
- if (!(mask & EV_READABLE) && mask & (EV_HUP | EV_ERR)) {
- log_error("HUP on UVT ctx fd");
- ev_eloop_rm_fd(fd);
- app->ctx_fd = NULL;
- }
-}
-
-static void destroy_app(struct uvtd_app *app)
-{
- ev_eloop_rm_fd(app->ctx_fd);
- uvt_ctx_unref(app->ctx);
- uterm_monitor_unref(app->mon);
- ev_eloop_unregister_signal_cb(app->eloop, SIGPIPE, app_sig_ignore,
- app);
- ev_eloop_unregister_signal_cb(app->eloop, SIGINT, app_sig_generic,
- app);
- ev_eloop_unregister_signal_cb(app->eloop, SIGTERM, app_sig_generic,
- app);
- ev_eloop_unref(app->eloop);
-}
-
-static int setup_app(struct uvtd_app *app)
-{
- int ret, fd;
-
- shl_dlist_init(&app->seats);
-
- ret = ev_eloop_new(&app->eloop, log_llog, NULL);
- if (ret) {
- log_error("cannot create eloop object: %d", ret);
- goto err_app;
- }
-
- ret = ev_eloop_register_signal_cb(app->eloop, SIGTERM,
- app_sig_generic, app);
- if (ret) {
- log_error("cannot register SIGTERM signal handler: %d", ret);
- goto err_app;
- }
-
- ret = ev_eloop_register_signal_cb(app->eloop, SIGINT,
- app_sig_generic, app);
- if (ret) {
- log_error("cannot register SIGINT signal handler: %d", ret);
- goto err_app;
- }
-
- ret = ev_eloop_register_signal_cb(app->eloop, SIGPIPE,
- app_sig_ignore, app);
- if (ret) {
- log_error("cannot register SIGPIPE signal handler: %d", ret);
- goto err_app;
- }
-
- ret = uterm_monitor_new(&app->mon, app->eloop, app_monitor_event, app);
- if (ret) {
- log_error("cannot create device monitor: %d", ret);
- goto err_app;
- }
-
- ret = uvt_ctx_new(&app->ctx, log_llog, NULL);
- if (ret) {
- log_error("cannot create UVT context: %d", ret);
- goto err_app;
- }
-
- fd = uvt_ctx_get_fd(app->ctx);
- if (fd >= 0) {
- ret = ev_eloop_new_fd(app->eloop, &app->ctx_fd, fd,
- EV_READABLE, app_ctx_event, app);
- if (ret) {
- log_error("cannot create UVT ctx efd: %d", ret);
- goto err_app;
- }
- }
-
- log_debug("scanning for devices...");
- uterm_monitor_scan(app->mon);
-
- return 0;
-
-err_app:
- destroy_app(app);
- return ret;
-}
-
-int main(int argc, char **argv)
-{
- int ret;
- struct uvtd_app app;
-
- log_set_config(&LOG_CONFIG_INFO(1, 1));
- log_print_init("uvtd");
-
- memset(&app, 0, sizeof(app));
-
- ret = setup_app(&app);
- if (ret)
- goto err_out;
-
- ev_eloop_run(app.eloop, -1);
-
- ret = 0;
- destroy_app(&app);
-err_out:
- if (ret)
- log_err("cannot initialize uvtd, errno %d: %s",
- ret, strerror(-ret));
- log_info("exiting");
- return -ret;
-}
diff --git a/src/uvtd_seat.c b/src/uvtd_seat.c
deleted file mode 100644
index 0a1d71c..0000000
--- a/src/uvtd_seat.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Seats
- * Each set of input+output devices form a single seat. Each seat is independent
- * of each other and there can be exactly one user per seat interacting with the
- * system.
- * Per seat, we have multiple sessions. But only one session can be active at a
- * time per seat. We allow external sessions, so session activation/deactivation
- * may be asynchronous.
- *
- * A seat object manages all the sessions for a single seat. As long as a seat
- * is asleep, no session is active. If you wake it up, the seat manager
- * automatically schedules a session. You can then request other sessions to be
- * scheduled and the seat manager will try to deactivate the current session and
- * reactivate the new session.
- *
- * Note that session deactivation may be asynchronous (unless forced). So some
- * calls might return -EINPROGRESS if the session-deactivation is pending. This
- * shouldn't bother the user as the session will notify back soon that the
- * deactivation was successfull. However, if it doesn't the user can chose to
- * perform any other action and we will retry the operation. As a last resort,
- * you can always kill the session by unregistering it or forcing a
- * deactivation.
- * "async_schedule" tracks the task that requested the deactivation of a
- * session. So when the session notifies us that it got deactivated, we know
- * what the user wanted and can perform the requested task now.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include "eloop.h"
-#include "shl_dlist.h"
-#include "shl_log.h"
-#include "uvtd_seat.h"
-
-#define LOG_SUBSYSTEM "seat"
-
-struct uvtd_session {
- struct shl_dlist list;
- unsigned long ref;
- struct uvtd_seat *seat;
- unsigned int id;
-
- bool enabled;
- bool deactivating;
-
- uvtd_session_cb_t cb;
- void *data;
-};
-
-/* task that requested the pending session-deactivation */
-enum uvtd_async_schedule {
- SCHEDULE_NONE, /* default, causes a reschedule */
- SCHEDULE_SWITCH, /* causes a reschedule */
- SCHEDULE_SLEEP, /* puts the seat asleep */
- SCHEDULE_UNREGISTER, /* unregisters the session */
-};
-
-struct uvtd_seat {
- struct ev_eloop *eloop;
- char *name;
-
- size_t session_count;
- struct shl_dlist sessions;
-
- bool awake;
- struct uvtd_session *current_sess;
- struct uvtd_session *scheduled_sess;
- struct uvtd_session *dummy_sess;
-
- unsigned int async_schedule;
-
- uvtd_seat_cb_t cb;
- void *data;
-};
-
-static int session_call(struct uvtd_session *sess, unsigned int event)
-{
- if (!sess->cb)
- return 0;
-
- return sess->cb(sess, event, sess->data);
-}
-
-static int session_call_activate(struct uvtd_session *sess)
-{
- log_debug("activate session %p", sess);
- return session_call(sess, UVTD_SESSION_ACTIVATE);
-}
-
-static int session_call_deactivate(struct uvtd_session *sess)
-{
- log_debug("deactivate session %p", sess);
- return session_call(sess, UVTD_SESSION_DEACTIVATE);
-}
-
-/* drop the current session as if it was successfully deactivated */
-static void seat_yield(struct uvtd_seat *seat)
-{
- if (!seat->current_sess)
- return;
-
- seat->current_sess->deactivating = false;
- seat->current_sess = NULL;
- seat->async_schedule = SCHEDULE_NONE;
-}
-
-static int seat_go_asleep(struct uvtd_seat *seat, bool force)
-{
- int ret = 0;
-
- if (!seat->awake)
- return 0;
-
- if (seat->current_sess) {
- ret = -EBUSY;
- if (!force)
- return ret;
-
- seat_yield(seat);
- }
-
- seat->awake = false;
-
- if (seat->cb)
- seat->cb(seat, UVTD_SEAT_SLEEP, seat->data);
-
- return ret;
-}
-
-static void seat_go_awake(struct uvtd_seat *seat)
-{
- if (seat->awake)
- return;
-
- seat->awake = true;
-}
-
-static int seat_run(struct uvtd_seat *seat)
-{
- int ret;
- struct uvtd_session *session;
-
- if (!seat->awake)
- return -EBUSY;
- if (seat->current_sess)
- return 0;
-
- if (!seat->scheduled_sess) {
- log_debug("no session scheduled to run (num: %zu)",
- seat->session_count);
- return -ENOENT;
- }
- session = seat->scheduled_sess;
-
- /* TODO: unregister session and try next on failure */
- ret = session_call_activate(session);
- if (ret) {
- log_warning("cannot activate session %p: %d", session, ret);
- return ret;
- }
-
- seat->current_sess = session;
-
- return 0;
-}
-
-static int seat_pause(struct uvtd_seat *seat, bool force, unsigned int async)
-{
- int ret;
-
- if (!seat->current_sess)
- return 0;
-
- /* TODO: pass \force to the session */
- seat->current_sess->deactivating = true;
- ret = session_call_deactivate(seat->current_sess);
- if (ret) {
- if (!force && ret == -EINPROGRESS) {
- seat->async_schedule = async;
- log_debug("pending deactivation for session %p",
- seat->current_sess);
- } else {
- log_warning("cannot deactivate session %p (%d): %d",
- seat->current_sess, force, ret);
- }
-
- if (!force)
- return ret;
- }
-
- seat_yield(seat);
- return ret;
-}
-
-static void seat_reschedule(struct uvtd_seat *seat)
-{
- struct shl_dlist *iter, *start;
- struct uvtd_session *sess;
-
- if (seat->scheduled_sess && seat->scheduled_sess->enabled)
- return;
-
- if (seat->current_sess && seat->current_sess->enabled) {
- seat->scheduled_sess = seat->current_sess;
- return;
- }
-
- if (seat->current_sess)
- start = &seat->current_sess->list;
- else
- start = &seat->sessions;
-
- shl_dlist_for_each_but_one(iter, start, &seat->sessions) {
- sess = shl_dlist_entry(iter, struct uvtd_session, list);
-
- if (sess != seat->dummy_sess && sess->enabled) {
- seat->scheduled_sess = sess;
- return;
- }
- }
-
- if (seat->dummy_sess && seat->dummy_sess->enabled)
- seat->scheduled_sess = seat->dummy_sess;
- else
- seat->scheduled_sess = NULL;
-}
-
-static bool seat_has_schedule(struct uvtd_seat *seat)
-{
- return seat->scheduled_sess &&
- seat->scheduled_sess != seat->current_sess;
-}
-
-static int seat_switch(struct uvtd_seat *seat)
-{
- int ret;
-
- ret = seat_pause(seat, false, SCHEDULE_SWITCH);
- if (ret)
- return ret;
-
- return seat_run(seat);
-}
-
-static void seat_schedule(struct uvtd_seat *seat, struct uvtd_session *sess)
-{
- seat->scheduled_sess = sess;
- seat_reschedule(seat);
- if (seat_has_schedule(seat))
- seat_switch(seat);
-}
-
-static void seat_next(struct uvtd_seat *seat, bool reverse)
-{
- struct shl_dlist *cur, *iter;
- struct uvtd_session *s, *next;
-
- if (seat->current_sess)
- cur = &seat->current_sess->list;
- else if (seat->session_count)
- cur = &seat->sessions;
- else
- return;
-
- next = NULL;
- if (!seat->current_sess && seat->dummy_sess &&
- seat->dummy_sess->enabled)
- next = seat->dummy_sess;
-
- if (reverse) {
- shl_dlist_for_each_reverse_but_one(iter, cur,
- &seat->sessions) {
- s = shl_dlist_entry(iter, struct uvtd_session, list);
-
- if (s->enabled && seat->dummy_sess != s) {
- next = s;
- break;
- }
- }
- } else {
- shl_dlist_for_each_but_one(iter, cur, &seat->sessions) {
- s = shl_dlist_entry(iter, struct uvtd_session, list);
-
- if (s->enabled && seat->dummy_sess != s) {
- next = s;
- break;
- }
- }
- }
-
- if (!next)
- return;
-
- seat_schedule(seat, next);
-}
-
-int uvtd_seat_new(struct uvtd_seat **out, const char *seatname,
- struct ev_eloop *eloop, uvtd_seat_cb_t cb, void *data)
-{
- struct uvtd_seat *seat;
- int ret;
-
- if (!out || !eloop || !seatname)
- return -EINVAL;
-
- seat = malloc(sizeof(*seat));
- if (!seat)
- return -ENOMEM;
- memset(seat, 0, sizeof(*seat));
- seat->eloop = eloop;
- seat->cb = cb;
- seat->data = data;
- shl_dlist_init(&seat->sessions);
-
- seat->name = strdup(seatname);
- if (!seat->name) {
- ret = -ENOMEM;
- goto err_free;
- }
-
- ev_eloop_ref(seat->eloop);
- *out = seat;
- return 0;
-
-err_free:
- free(seat);
- return ret;
-}
-
-void uvtd_seat_free(struct uvtd_seat *seat)
-{
- struct uvtd_session *s;
- int ret;
-
- if (!seat)
- return;
-
- ret = seat_pause(seat, true, SCHEDULE_NONE);
- if (ret)
- log_warning("destroying seat %s while session %p is active",
- seat->name, seat->current_sess);
-
- ret = seat_go_asleep(seat, true);
- if (ret)
- log_warning("destroying seat %s while still awake: %d",
- seat->name, ret);
-
- while (!shl_dlist_empty(&seat->sessions)) {
- s = shl_dlist_entry(seat->sessions.next, struct uvtd_session,
- list);
- uvtd_session_unregister(s);
- }
-
- free(seat->name);
- ev_eloop_unref(seat->eloop);
- free(seat);
-}
-
-const char *uvtd_seat_get_name(struct uvtd_seat *seat)
-{
- return seat ? seat->name : NULL;
-}
-
-struct ev_eloop *uvtd_seat_get_eloop(struct uvtd_seat *seat)
-{
- return seat ? seat->eloop : NULL;
-}
-
-int uvtd_seat_sleep(struct uvtd_seat *seat, bool force)
-{
- int ret, err = 0;
-
- if (!seat)
- return -EINVAL;
-
- ret = seat_pause(seat, force, SCHEDULE_SLEEP);
- if (ret) {
- if (force)
- err = ret;
- else
- return ret;
- }
-
- ret = seat_go_asleep(seat, force);
- if (ret) {
- if (force)
- err = ret;
- else
- return ret;
- }
-
- return err;
-}
-
-void uvtd_seat_wake_up(struct uvtd_seat *seat)
-{
- if (!seat)
- return;
-
- seat_go_awake(seat);
- seat_run(seat);
-}
-
-void uvtd_seat_schedule(struct uvtd_seat *seat, unsigned int id)
-{
- struct shl_dlist *iter;
- struct uvtd_session *session;
- unsigned int i;
-
- if (!seat || !id)
- return;
-
- session = NULL;
- i = id;
- shl_dlist_for_each(iter, &seat->sessions) {
- session = shl_dlist_entry(iter, struct uvtd_session, list);
- if (!--i)
- break;
- if (session->id >= id)
- break;
- }
-
- if (session)
- seat_schedule(seat, session);
-}
-
-int uvtd_seat_register_session(struct uvtd_seat *seat,
- struct uvtd_session **out,
- unsigned int id, uvtd_session_cb_t cb,
- void *data)
-{
- struct uvtd_session *sess, *s;
- struct shl_dlist *iter;
-
- if (!seat || !out)
- return -EINVAL;
-
- sess = malloc(sizeof(*sess));
- if (!sess)
- return -ENOMEM;
-
- log_debug("register session %p with id %u on seat %p",
- sess, id, seat);
-
- memset(sess, 0, sizeof(*sess));
- sess->ref = 1;
- sess->seat = seat;
- sess->cb = cb;
- sess->data = data;
- sess->id = id;
-
- ++seat->session_count;
- *out = sess;
-
- if (sess->id) {
- shl_dlist_for_each(iter, &seat->sessions) {
- s = shl_dlist_entry(iter, struct uvtd_session, list);
- if (!s->id || s->id > sess->id) {
- shl_dlist_link_tail(iter, &sess->list);
- return 0;
- }
-
- if (s->id == sess->id)
- log_warning("session %p shadowed by %p",
- sess, s);
- }
- }
-
- shl_dlist_link_tail(&seat->sessions, &sess->list);
- return 0;
-}
-
-void uvtd_session_ref(struct uvtd_session *sess)
-{
- if (!sess || !sess->ref)
- return;
-
- ++sess->ref;
-}
-
-void uvtd_session_unref(struct uvtd_session *sess)
-{
- if (!sess || !sess->ref || --sess->ref)
- return;
-
- uvtd_session_unregister(sess);
- free(sess);
-}
-
-void uvtd_session_unregister(struct uvtd_session *sess)
-{
- struct uvtd_seat *seat;
- int ret;
- bool forced = false;
-
- if (!sess || !sess->seat)
- return;
-
- log_debug("unregister session %p", sess);
-
- seat = sess->seat;
- sess->enabled = false;
- if (seat->dummy_sess == sess)
- seat->dummy_sess = NULL;
- seat_reschedule(seat);
-
- if (seat->current_sess == sess) {
- ret = seat_pause(seat, true, SCHEDULE_NONE);
- if (ret) {
- forced = true;
- log_warning("unregistering active session %p; skipping automatic session-switch",
- sess);
- }
- }
-
- shl_dlist_unlink(&sess->list);
- --seat->session_count;
- sess->seat = NULL;
-
- session_call(sess, UVTD_SESSION_UNREGISTER);
- uvtd_session_unref(sess);
-
- /* If this session was active and we couldn't deactivate it, then it
- * might still have resources allocated that couldn't get freed. In this
- * case we should not automatically switch to the next session as it is
- * very likely that it will not be able to start.
- * Instead, we stay inactive and wait for user/external input to switch
- * to another session. This delay will then hopefully be long enough so
- * all resources got freed. */
- if (!forced)
- seat_run(seat);
-}
-
-bool uvtd_session_is_registered(struct uvtd_session *sess)
-{
- return sess && sess->seat;
-}
-
-bool uvtd_session_is_active(struct uvtd_session *sess)
-{
- return sess && sess->seat && sess->seat->current_sess == sess;
-}
-
-void uvtd_session_schedule(struct uvtd_session *sess)
-{
- if (!sess || !sess->seat)
- return;
-
- seat_schedule(sess->seat, sess);
-}
-
-void uvtd_session_enable(struct uvtd_session *sess)
-{
- if (!sess || sess->enabled)
- return;
-
- log_debug("enable session %p", sess);
- sess->enabled = true;
-
- if (sess->seat &&
- (!sess->seat->current_sess ||
- sess->seat->current_sess == sess->seat->dummy_sess))
- seat_schedule(sess->seat, sess);
-}
-
-void uvtd_session_disable(struct uvtd_session *sess)
-{
- if (!sess || !sess->enabled)
- return;
-
- log_debug("disable session %p", sess);
- sess->enabled = false;
-}
-
-bool uvtd_session_is_enabled(struct uvtd_session *sess)
-{
- return sess && sess->enabled;
-}
-
-void uvtd_session_notify_deactivated(struct uvtd_session *sess)
-{
- struct uvtd_seat *seat;
- unsigned int sched;
-
- if (!sess || !sess->seat)
- return;
-
- seat = sess->seat;
- if (seat->current_sess != sess)
- return;
-
- sched = seat->async_schedule;
- log_debug("session %p notified core about deactivation (schedule: %u)",
- sess, sched);
- seat_yield(seat);
- seat_reschedule(seat);
-
- if (sched == SCHEDULE_SLEEP)
- seat_go_asleep(seat, false);
- else if (sched == SCHEDULE_UNREGISTER)
- uvtd_session_unregister(sess);
- else
- seat_run(seat);
-}
diff --git a/src/uvtd_seat.h b/src/uvtd_seat.h
deleted file mode 100644
index 534d773..0000000
--- a/src/uvtd_seat.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Seats
- * Each set of input+output devices form a single seat. Each seat is independent
- * of each other and there can be exactly one user per seat interacting with the
- * system.
- * Per seat, we have multiple sessions. But only one session can be active at a
- * time per seat. We allow external sessions, so session activation/deactivation
- * may be asynchronous.
- */
-
-#ifndef UVTD_SEAT_H
-#define UVTD_SEAT_H
-
-#include <stdlib.h>
-#include "eloop.h"
-
-/* sessions */
-
-struct uvtd_session;
-
-enum uvtd_session_event_type {
- UVTD_SESSION_ACTIVATE,
- UVTD_SESSION_DEACTIVATE,
- UVTD_SESSION_UNREGISTER,
-};
-
-typedef int (*uvtd_session_cb_t) (struct uvtd_session *session,
- unsigned int event,
- void *data);
-
-void uvtd_session_ref(struct uvtd_session *sess);
-void uvtd_session_unref(struct uvtd_session *sess);
-void uvtd_session_unregister(struct uvtd_session *sess);
-bool uvtd_session_is_registered(struct uvtd_session *sess);
-
-bool uvtd_session_is_active(struct uvtd_session *sess);
-void uvtd_session_schedule(struct uvtd_session *sess);
-
-void uvtd_session_enable(struct uvtd_session *sess);
-void uvtd_session_disable(struct uvtd_session *sess);
-bool uvtd_session_is_enabled(struct uvtd_session *sess);
-
-void uvtd_session_notify_deactivated(struct uvtd_session *sess);
-
-/* seats */
-
-struct uvtd_seat;
-
-enum uvtd_seat_event {
- UVTD_SEAT_SLEEP,
-};
-
-typedef void (*uvtd_seat_cb_t) (struct uvtd_seat *seat, unsigned int event,
- void *data);
-
-int uvtd_seat_new(struct uvtd_seat **out, const char *seatname,
- struct ev_eloop *eloop, uvtd_seat_cb_t cb, void *data);
-void uvtd_seat_free(struct uvtd_seat *seat);
-
-const char *uvtd_seat_get_name(struct uvtd_seat *seat);
-struct ev_eloop *uvtd_seat_get_eloop(struct uvtd_seat *seat);
-int uvtd_seat_sleep(struct uvtd_seat *seat, bool force);
-void uvtd_seat_wake_up(struct uvtd_seat *seat);
-void uvtd_seat_schedule(struct uvtd_seat *seat, unsigned int id);
-
-int uvtd_seat_register_session(struct uvtd_seat *seat,
- struct uvtd_session **out,
- unsigned int id, uvtd_session_cb_t cb,
- void *data);
-
-#endif /* UVTD_SEAT_H */
diff --git a/src/uvtd_vt.c b/src/uvtd_vt.c
deleted file mode 100644
index 50eac8e..0000000
--- a/src/uvtd_vt.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Virtual Terminals
- * Every virtual terminal forms a session inside of uvtd. Sessions are scheduled
- * by the seat/session-scheduler and notified whenever they get active/inactive.
- */
-
-#include <errno.h>
-#include <inttypes.h>
-#include <linux/kd.h>
-#include <linux/vt.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termio.h>
-#include <termios.h>
-#include <unistd.h>
-#include "shl_hook.h"
-#include "shl_log.h"
-#include "uvt.h"
-#include "uvtd_seat.h"
-#include "uvtd_vt.h"
-
-#define LOG_SUBSYSTEM "vt"
-
-struct uvtd_vt {
- unsigned long ref;
- struct uvt_ctx *uctx;
- struct shl_hook *hook;
- struct uvtd_session *session;
- struct uvtd_seat *seat;
- bool is_legacy;
-
- unsigned int mode;
- unsigned int kbmode;
- struct vt_mode vtmode;
- pid_t vtpid;
-};
-
-static void vt_hup(struct uvtd_vt *vt)
-{
- struct uvt_vt_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.type = UVT_VT_HUP;
-
- shl_hook_call(vt->hook, vt, &ev);
-}
-
-static int vt_session_event(struct uvtd_session *session, unsigned int event,
- void *data)
-{
- struct uvtd_vt *vt = data;
-
- switch (event) {
- case UVTD_SESSION_UNREGISTER:
- vt->session = NULL;
- vt->seat = NULL;
- vt_hup(vt);
- break;
- case UVTD_SESSION_ACTIVATE:
- log_debug("activate %p", vt);
- break;
- case UVTD_SESSION_DEACTIVATE:
- log_debug("deactivate %p", vt);
- break;
- }
-
- return 0;
-}
-
-int uvtd_vt_new(struct uvtd_vt **out, struct uvt_ctx *uctx, unsigned int id,
- struct uvtd_seat *seat, bool is_legacy)
-{
- struct uvtd_vt *vt;
- int ret;
-
- if (!out || !uctx)
- return -EINVAL;
-
- vt = malloc(sizeof(*vt));
- if (!vt)
- return -ENOMEM;
-
- memset(vt, 0, sizeof(*vt));
- vt->ref = 1;
- vt->uctx = uctx;
- vt->seat = seat;
- vt->is_legacy = is_legacy;
- vt->mode = KD_TEXT;
- vt->kbmode = K_UNICODE;
- vt->vtmode.mode = VT_AUTO;
-
- ret = shl_hook_new(&vt->hook);
- if (ret)
- goto err_free;
-
- ret = uvtd_seat_register_session(seat, &vt->session, id,
- vt_session_event, vt);
- if (ret)
- goto err_hook;
-
- uvt_ctx_ref(vt->uctx);
- *out = vt;
- return 0;
-
-err_hook:
- shl_hook_free(vt->hook);
-err_free:
- free(vt);
- return ret;
-}
-
-void uvtd_vt_ref(struct uvtd_vt *vt)
-{
- if (!vt || !vt->ref)
- return;
-
- ++vt->ref;
-}
-
-void uvtd_vt_unref(struct uvtd_vt *vt)
-{
- if (!vt || !vt->ref || --vt->ref)
- return;
-
- uvtd_session_unregister(vt->session);
- shl_hook_free(vt->hook);
- uvt_ctx_unref(vt->uctx);
- free(vt);
-}
-
-int uvtd_vt_register_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data)
-{
- if (!vt)
- return -EINVAL;
-
- return shl_hook_add_cast(vt->hook, cb, data, false);
-}
-
-void uvtd_vt_unregister_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data)
-{
- if (!vt)
- return;
-
- shl_hook_rm_cast(vt->hook, cb, data);
-}
-
-int uvtd_vt_read(struct uvtd_vt *vt, uint8_t *mem, size_t len)
-{
- if (!vt || !vt->seat)
- return -ENODEV;
-
- return -EAGAIN;
-}
-
-int uvtd_vt_write(struct uvtd_vt *vt, const uint8_t *mem, size_t len)
-{
- if (!vt || !vt->seat)
- return -ENODEV;
-
- return len;
-}
-
-unsigned int uvtd_vt_poll(struct uvtd_vt *vt)
-{
- if (!vt || !vt->seat)
- return UVT_TTY_HUP | UVT_TTY_READ | UVT_TTY_WRITE;
-
- return UVT_TTY_WRITE;
-}
-
-static int vt_ioctl_TCFLSH(void *data, unsigned long arg)
-{
- switch (arg) {
- case TCIFLUSH:
- case TCOFLUSH:
- case TCIOFLUSH:
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vt_ioctl_VT_ACTIVATE(void *data, unsigned long arg)
-{
- struct uvtd_vt *vt = data;
-
- if (!vt->seat)
- return -ENODEV;
-
- return -EINVAL;
-}
-
-static int vt_ioctl_VT_WAITACTIVE(void *data, unsigned long arg)
-{
- struct uvtd_vt *vt = data;
-
- if (!vt->seat)
- return -ENODEV;
-
- return -EINVAL;
-}
-
-static int vt_ioctl_VT_GETSTATE(void *data, struct vt_stat *arg)
-{
- struct uvtd_vt *vt = data;
-
- if (!vt->seat)
- return -ENODEV;
-
- return -EINVAL;
-}
-
-static int vt_ioctl_VT_OPENQRY(void *data, unsigned int *arg)
-{
- struct uvtd_vt *vt = data;
-
- if (!vt->seat)
- return -ENODEV;
-
- return -EINVAL;
-}
-
-static int vt_ioctl_VT_GETMODE(void *data, struct vt_mode *arg)
-{
- struct uvtd_vt *vt = data;
-
- memcpy(arg, &vt->vtmode, sizeof(*arg));
- return 0;
-}
-
-static int vt_ioctl_VT_SETMODE(void *data, const struct vt_mode *arg,
- pid_t pid)
-{
- struct uvtd_vt *vt = data;
-
- /* TODO: implement waitv logic (hang on write if not active) */
- if (arg->waitv)
- return -EOPNOTSUPP;
-
- if (arg->frsig)
- return -EINVAL;
- if (arg->relsig > SIGRTMAX || arg->relsig < 0)
- return -EINVAL;
- if (arg->acqsig > SIGRTMAX || arg->acqsig < 0)
- return -EINVAL;
-
- switch (arg->mode) {
- case VT_AUTO:
- if (arg->acqsig || arg->relsig)
- return -EINVAL;
- vt->vtpid = 0;
- break;
- case VT_PROCESS:
- vt->vtpid = pid;
- break;
- default:
- return -EINVAL;
- }
-
- memcpy(&vt->vtmode, arg, sizeof(*arg));
- return 0;
-}
-
-static int vt_ioctl_VT_RELDISP(void *data, unsigned long arg)
-{
- struct uvtd_vt *vt = data;
-
- if (!vt->seat)
- return -ENODEV;
-
- return -EINVAL;
-}
-
-static int vt_ioctl_KDGETMODE(void *data, unsigned int *arg)
-{
- struct uvtd_vt *vt = data;
-
- *arg = vt->mode;
- return 0;
-}
-
-static int vt_ioctl_KDSETMODE(void *data, unsigned int arg)
-{
- struct uvtd_vt *vt = data;
-
- switch (arg) {
- case KD_TEXT0:
- case KD_TEXT1:
- arg = KD_TEXT;
- /* fallthrough */
- case KD_TEXT:
- case KD_GRAPHICS:
- vt->mode = arg;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vt_ioctl_KDGKBMODE(void *data, unsigned int *arg)
-{
- struct uvtd_vt *vt = data;
-
- *arg = vt->kbmode;
- return 0;
-}
-
-static int vt_ioctl_KDSKBMODE(void *data, unsigned int arg)
-{
- struct uvtd_vt *vt = data;
-
- switch (arg) {
- case K_RAW:
- /* TODO: what does K_RAW do? */
- case K_UNICODE:
- case K_OFF:
- vt->kbmode = arg;
- break;
- case K_XLATE:
- case K_MEDIUMRAW:
- /* TODO: do we need these? */
- return -EOPNOTSUPP;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* compatibility to UVT-VT ops */
-
-static void vt_ref(void *vt)
-{
- uvtd_vt_ref(vt);
-}
-
-static void vt_unref(void *vt)
-{
- uvtd_vt_unref(vt);
-}
-
-static int vt_register_cb(void *vt, uvt_vt_cb cb, void *data)
-{
- return uvtd_vt_register_cb(vt, cb, data);
-}
-
-static void vt_unregister_cb(void *vt, uvt_vt_cb cb, void *data)
-{
- uvtd_vt_register_cb(vt, cb, data);
-}
-
-static int vt_read(void *vt, uint8_t *mem, size_t len)
-{
- return uvtd_vt_read(vt, mem, len);
-}
-
-static int vt_write(void *vt, const uint8_t *mem, size_t len)
-{
- return uvtd_vt_write(vt, mem, len);
-}
-
-static unsigned int vt_poll(void *vt)
-{
- return uvtd_vt_poll(vt);
-}
-
-struct uvt_vt_ops uvtd_vt_ops = {
- .ref = vt_ref,
- .unref = vt_unref,
- .register_cb = vt_register_cb,
- .unregister_cb = vt_unregister_cb,
- .read = vt_read,
- .write = vt_write,
- .poll = vt_poll,
-
- .ioctl_TCFLSH = vt_ioctl_TCFLSH,
-
- .ioctl_VT_ACTIVATE = vt_ioctl_VT_ACTIVATE,
- .ioctl_VT_WAITACTIVE = vt_ioctl_VT_WAITACTIVE,
- .ioctl_VT_GETSTATE = vt_ioctl_VT_GETSTATE,
- .ioctl_VT_OPENQRY = vt_ioctl_VT_OPENQRY,
- .ioctl_VT_GETMODE = vt_ioctl_VT_GETMODE,
- .ioctl_VT_SETMODE = vt_ioctl_VT_SETMODE,
- .ioctl_VT_RELDISP = vt_ioctl_VT_RELDISP,
- .ioctl_KDGETMODE = vt_ioctl_KDGETMODE,
- .ioctl_KDSETMODE = vt_ioctl_KDSETMODE,
- .ioctl_KDGKBMODE = vt_ioctl_KDGKBMODE,
- .ioctl_KDSKBMODE = vt_ioctl_KDSKBMODE,
-};
diff --git a/src/uvtd_vt.h b/src/uvtd_vt.h
deleted file mode 100644
index fe83671..0000000
--- a/src/uvtd_vt.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * uvtd - User-space VT daemon
- *
- * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Virtual Terminals
- * Every virtual terminal forms a session inside of uvtd. Sessions are scheduled
- * by the seat/session-scheduler and notified whenever they get active/inactive.
- */
-
-#ifndef UVTD_VT_H
-#define UVTD_VT_H
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include "uvt.h"
-
-struct uvtd_vt;
-extern struct uvt_vt_ops uvtd_vt_ops;
-
-int uvtd_vt_new(struct uvtd_vt **out, struct uvt_ctx *uctx, unsigned int id,
- struct uvtd_seat *seat, bool is_legacy);
-void uvtd_vt_ref(struct uvtd_vt *vt);
-void uvtd_vt_unref(struct uvtd_vt *vt);
-
-int uvtd_vt_register_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data);
-void uvtd_vt_unregister_cb(struct uvtd_vt *vt, uvt_vt_cb cb, void *data);
-
-int uvtd_vt_read(struct uvtd_vt *vt, uint8_t *mem, size_t len);
-int uvtd_vt_write(struct uvtd_vt *vt, const uint8_t *mem, size_t len);
-unsigned int uvtd_vt_poll(struct uvtd_vt *vt);
-
-#endif /* UVTD_VT_H */