diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/uvt.h | 3 | ||||
-rw-r--r-- | src/uvt_client.c | 3 | ||||
-rw-r--r-- | src/uvtd_vt.c | 41 |
3 files changed, 42 insertions, 5 deletions
@@ -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); diff --git a/src/uvt_client.c b/src/uvt_client.c index d31a35b..574001e 100644 --- a/src/uvt_client.c +++ b/src/uvt_client.c @@ -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 diff --git a/src/uvtd_vt.c b/src/uvtd_vt.c index 18e4503..cc121a0 100644 --- a/src/uvtd_vt.c +++ b/src/uvtd_vt.c @@ -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) |