uvtd: vt: implement VT_GETMODE/SETMODE ioctl state-tracking
authorDavid Herrmann <dh.herrmann@gmail.com>
Wed, 6 Mar 2013 18:03:34 +0000 (19:03 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Wed, 6 Mar 2013 18:03:34 +0000 (19:03 +0100)
These ioctls are used to retrieve and set the VT-mode. That is, the
signals and PID information that correspond to the VT controlling process.
It is notified whenever the VT gets active/inactive so it can react to it
or prevent/acknowledge it.

This doesn't implement the signal-sending logic, yet. It only implements
state-tracking.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
src/uvt.h
src/uvt_client.c
src/uvtd_vt.c

index a69dd6f..e767005 100644 (file)
--- a/src/uvt.h
+++ b/src/uvt.h
@@ -108,7 +108,8 @@ struct uvt_vt_ops {
        int (*ioctl_VT_GETSTATE) (void *data, struct vt_stat *arg);
        int (*ioctl_VT_OPENQRY) (void *data, unsigned int *arg);
        int (*ioctl_VT_GETMODE) (void *data, struct vt_mode *arg);
-       int (*ioctl_VT_SETMODE) (void *data, const struct vt_mode *arg);
+       int (*ioctl_VT_SETMODE) (void *data, const struct vt_mode *arg,
+                                pid_t pid);
        int (*ioctl_VT_RELDISP) (void *data, unsigned long arg);
        int (*ioctl_KDGETMODE) (void *data, unsigned int *arg);
        int (*ioctl_KDSETMODE) (void *data, unsigned int arg);
index d31a35b..574001e 100644 (file)
@@ -972,7 +972,8 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
                        fuse_reply_err(req, EOPNOTSUPP);
                } else {
                        ret = client->vt->ioctl_VT_SETMODE(client->vt_data,
-                                               (const struct vt_mode*)in_buf);
+                                               (const struct vt_mode*)in_buf,
+                                               fuse_req_ctx(req)->pid);
                        if (ret)
                                fuse_reply_err(req, abs(ret));
                        else
index 18e4503..cc121a0 100644 (file)
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <linux/kd.h>
 #include <linux/vt.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <termio.h>
@@ -55,6 +56,8 @@ struct uvtd_vt {
 
        unsigned int mode;
        unsigned int kbmode;
+       struct vt_mode vtmode;
+       pid_t vtpid;
 };
 
 static void vt_hup(struct uvtd_vt *vt)
@@ -107,6 +110,7 @@ int uvtd_vt_new(struct uvtd_vt **out, struct uvt_ctx *uctx, unsigned int id,
        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)
@@ -214,12 +218,43 @@ static int vt_ioctl_VT_OPENQRY(void *data, unsigned int *arg)
 
 static int vt_ioctl_VT_GETMODE(void *data, struct vt_mode *arg)
 {
-       return -EINVAL;
+       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)
+static int vt_ioctl_VT_SETMODE(void *data, const struct vt_mode *arg,
+                              pid_t pid)
 {
-       return -EINVAL;
+       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)