Thread (6 messages) 6 messages, 3 authors, 2025-11-24

[Patch v2 1/1] man/man2/ioctl_vt.2: Various improvements.

From: Teika Kazura <hidden>
Date: 2025-11-10 07:59:56
Subsystem: the rest · Maintainer: Linus Torvalds

In the current version of ioctl_vt.2, many explanations are insufficient, wrong or inaccurate. The patch improves this situation.

These points are fixed:

* The first argument fd was not explained. The third argument was written only "void *", but there are cases where it is an integer.
* VT_SETMODE: The member "waitv" of struct vt_mode is unused. This is so already in kernel 5.4, the oldest longterm, so I wrote it as "unused".
* The descrptions of VT_SETMODE and VT_RELDISP were far from sufficient.
* In 3 ioctls the relation between fd and argp was not explained.
* There are 5 ioctls that are not documented. I don't know what they are, so I simply mentioned them as "available, but not documented."

Signed-off by: Teika Kazura [off-list ref]
---
 man/man2/ioctl_vt.2 | 187 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 164 insertions(+), 23 deletions(-)
diff --git a/man/man2/ioctl_vt.2 b/man/man2/ioctl_vt.2
index 05b4637..18e1b24 100644
--- a/man/man2/ioctl_vt.2
+++ b/man/man2/ioctl_vt.2
@@ -19,59 +19,77 @@ .SH SYNOPSIS
 .B #include <sys/ioctl.h>
 .P
 .BI "int ioctl(int " fd ", unsigned long " op ", void *" argp );
+.BI "int ioctl(int " fd ", unsigned long " op ", int " argi );
 .fi
 .SH DESCRIPTION
 The following Linux-specific
 .BR ioctl (2)
 operations are supported for console terminals and virtual consoles.
+.P
+For operations for which
+.I fd
+is relevant, it is the file descrpitor of the target vt, which should be the active vt. Superuser can target any vt. Furthermore the calling process needs to own the vt or have the appropriate privilege of CAP_SYS_TTY_CONFIG. When the target vt is running X or Wayland, it will fail except for superuser.
+.P
+.I op
+is one of
+.B VT_*
+listed below. The third argument is some pointer or an unsigned long integer. See each entry for the detail.
 .TP
 .B VT_OPENQRY
 Returns the first available (non-opened) console.
 .I argp
-points to an
+will point to an
 .I int
 which is set to the
 number of the vt (1 <=
 .I *argp
 <= MAX_NR_CONSOLES).
 .TP
-.B VT_GETMODE
-Get mode of active vt.
+.B VT_SETMODE
+Set mode of vt.
 .I argp
-points to a
+points to this structure:
 .IP
 .in +4n
 .EX
 struct vt_mode {
     char  mode;    /* vt mode */
-    char  waitv;   /* if set, hang on writes if not active */
-    short relsig;  /* signal to raise on release op */
+    char  waitv;   /* unused (set to 0) */
+    short relsig;  /* signal to raise on release */
     short acqsig;  /* signal to raise on acquisition */
     short frsig;   /* unused (set to 0) */
 };
 .EE
 .in
 .IP
-which is set to the mode of the active vt.
 .I mode
 is set to one of these values:
 .TS
 l l.
-VT_AUTO	auto vt switching
-VT_PROCESS	process controls switching
-VT_ACKACQ	acknowledge switch
+VT_PROCESS      process controls switching
+VT_AUTO         switching happens unconditionally (default)
 .TE
+.IP
+When mode is VT_PROCESS, signals will be sent to the calling process when this vt is requested to go inactive (release) or active (acquisition). On release VT_RELDISP below has to be called, and decide if it allows or refuses vt switching. The signals and the associated calling process are overwritten by later calls of VT_SETMODE, so do avoid such use.
+.IP
+.BR "Note":
+As stated above, VT_SETMODE should not be called twice for one vt to set it the VT_PROCESS mode. In fact you should not call VT_SETMODE unless you are absolutely sure. This ioctl was originally intended for the X server, and today Wayland (via seatd) needs it too.
+.IP
+If you want to wait for activation events, use VT_WAITACTIVE instead.
+.IP
+.BR "Note 2":
+When a vt release is requested and its controlling process is dead, the release will be done, and the vt will be reset to VT_AUTO.
 .TP
-.B VT_SETMODE
-Set mode of active vt.
+.B VT_GETMODE
+Get mode of active vt.
 .I argp
-points to a
+will point  to a
 .IR "struct vt_mode" .
 .TP
 .B VT_GETSTATE
 Get global vt state info.
 .I argp
-points to a
+will point to
 .IP
 .in +4n
 .EX
@@ -89,23 +107,44 @@ .SH DESCRIPTION
 (Linux 1.0 through Linux 1.1.92.)
 .TP
 .B VT_RELDISP
-Release a display.
+When vt's mode is set to VT_PROCESS in the VT_SETMODE call explained above, the registered process has to call VT_RELDISP when vt release is requested, i.e. when handling the signal
+.IR "relsig" .
+Until then the process that requested vt switchig will be blocked. When
+.I argi
+is 0, the process refuses the release, and vt won't switch from the current one. Otherwise, the switch is allowed to happen.
+.IP
+Historical note: Also on a vt acquisition event, it is possible to call VT_PROCESS. The Xorg server and seatd still calls VT_RELDISP on vt acquisition. In fact it does nothing, so it is completely meaningless today. In that case when
+.I argi
+is VT_ACKACQ, the call succeeds, and otherwise, EINVAL is returned, but it is superficial, and  it does not affect any in reality.
+
 .TP
 .B VT_ACTIVATE
 Switch to vt
-.I argp
+.I argi
 (1 <=
-.I argp
+.I argi
 <= MAX_NR_CONSOLES).
+.IP
+.I fd
+does not have to coincide with
+.IR "argi" .
+The calling process does not need any permission about
+.IR "argi" ,
+but the restriction of
+.I fd
+stated before applies.
 .TP
 .B VT_WAITACTIVE
 Wait until vt
-.I argp
-has been activated.
+.I argi
+has been activated. If already active, returns immediately.
+See the VT_ACTIVATE case about
+.IR "fd" .
 .TP
 .B VT_DISALLOCATE
 Deallocate the memory associated with vt
-.IR argp .
+.IR argi ,
+which should not be busy.
 (Since Linux 1.1.54.)
 .TP
 .B VT_RESIZE
@@ -160,7 +199,7 @@ .SH DESCRIPTION
 .B VT_GETCONSIZECSRPOS
 Get console size and cursor position.
 .I argp
-points to a
+will point to a
 .IP
 .in +4n
 .EX
@@ -174,6 +213,17 @@ .SH DESCRIPTION
 .in
 .IP
 (Since Linux 6.16.)
+.TP
+.B VT_WAITEVENT
+.TQ
+.B VT_LOCKSWITCH
+.TQ
+.B VT_UNLOCKSWITCH
+.TQ
+.B VT_GETHIFONTMASK
+.TQ
+.B VT_SETACTIVATE
+These are implemented but not documented.
 .SH RETURN VALUE
 On success, 0 is returned (except where indicated).
 On failure, \-1 is returned, and
@@ -183,9 +233,100 @@ .SH ERRORS
 .TP
 .B EINVAL
 .I argp
+or
+.I argi
 is invalid.
-.SH STANDARDS
+.TP
+.B ENOTTY
+Not tty device.
+.TP
+.B ENXIO
+No such device.
+.TP
+.B EPERM
+Operation not permitted.
+.SH
+STANDARDS
 Linux.
-.SH SEE ALSO
+.SH EXAMPLES
+.SS Use of VT_SETMODE and VT_RELDISP
+.\" SRC BEGIN (***.c)
+.EX
+/*
+ * Run this code in VT1, and press Alt+F2.
+ * VT1 release is delayed by 1 sec.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/vt.h>
+\&
+static int tty_fd;
+\&
+static void handle_signal(int sig) {
+    if (sig == SIGUSR1) {
+        printf("VT release requested\\n");
+        printf("Wait for a second...\\n");
+        sleep(1);
+        // Tell kernel we’re OK to release
+        // If 0, refuses to release
+        ioctl(tty_fd, VT_RELDISP, 1);
+        printf("Release done.\\n");
+    } else if (sig == SIGUSR2) {
+        printf("VT acquired\\n");
+
+        // Optionally you can do this, but it does not make any difference.
+        ioctl(tty_fd, VT_RELDISP, VT_ACKACQ);
+    }
+}
+\&
+int main(void) {
+    struct vt_mode mode;
+\&
+    tty_fd = open("/dev/tty1", O_RDWR);
+    if (tty_fd < 0) {
+        perror("open /dev/tty1");
+        return 1;
+    }
+\&
+    // Install signal handlers
+    struct sigaction sa;
+    sa.sa_handler = handle_signal;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sigaction(SIGUSR1, &sa, NULL);
+    sigaction(SIGUSR2, &sa, NULL);
+\&
+    // Set VT mode to process mode
+    mode.mode = VT_PROCESS;
+    mode.waitv = 0;
+    mode.relsig = SIGUSR1;
+    mode.acqsig = SIGUSR2;
+    mode.frsig = 0;
+\&
+    if (ioctl(tty_fd, VT_SETMODE, &mode) < 0) {
+        perror("VT_SETMODE");
+        close(tty_fd);
+        return 1;
+    }
+\&
+    printf("VT process mode set. Waiting for release/acquire events...\\n");
+\&
+    // Just idle; signals will handle events
+    while (1) {
+        pause();
+    }
+\&
+    close(tty_fd);
+    return 0;
+}
+.EE
+.\" SRC END
+.SS Python examples
+A python exapmle similar to the above code is found at <https://bugzilla.kernel.org/attachment.cgi?id=308927>. A VT_WAITACTIVE example is found at <https://bugzilla.kernel.org/attachment.cgi?id=308928>. SEE ALSO
 .BR ioctl (2),
 .BR ioctl_console (2)
+.BR ioctl_kd (2)
-- 
2.49.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help