summaryrefslogtreecommitdiffstats
path: root/toolbox/setconsole.c
diff options
context:
space:
mode:
Diffstat (limited to 'toolbox/setconsole.c')
-rw-r--r--toolbox/setconsole.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/toolbox/setconsole.c b/toolbox/setconsole.c
new file mode 100644
index 0000000..b0ce13f
--- /dev/null
+++ b/toolbox/setconsole.c
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <errno.h>
+#include <pthread.h>
+
+static int activate_thread_switch_vc;
+static void *activate_thread(void *arg)
+{
+ int res;
+ int fd = (int)arg;
+ while(activate_thread_switch_vc >= 0) {
+ do {
+ res = ioctl(fd, VT_ACTIVATE, (void*)activate_thread_switch_vc);
+ } while(res < 0 && errno == EINTR);
+ if (res < 0) {
+ fprintf(stderr, "ioctl( vcfd, VT_ACTIVATE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), activate_thread_switch_vc);
+ }
+ if(activate_thread_switch_vc >= 0)
+ sleep(1);
+ }
+ return NULL;
+}
+
+
+int setconsole_main(int argc, char *argv[])
+{
+ int c;
+ int fd;
+ int res;
+
+ int mode = -1;
+ int new_vc = 0;
+ int close_vc = 0;
+ int switch_vc = -1;
+ int printvc = 0;
+ char *ttydev = "/dev/tty0";
+
+ do {
+ c = getopt(argc, argv, "d:gtncv:poh");
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'd':
+ ttydev = optarg;
+ break;
+ case 'g':
+ if(mode == KD_TEXT) {
+ fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
+ exit(1);
+ }
+ mode = KD_GRAPHICS;
+ break;
+ case 't':
+ if(mode == KD_GRAPHICS) {
+ fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
+ exit(1);
+ }
+ mode = KD_TEXT;
+ break;
+ case 'n':
+ new_vc = 1;
+ break;
+ case 'c':
+ close_vc = 1;
+ break;
+ case 'v':
+ switch_vc = atoi(optarg);
+ break;
+ case 'p':
+ printvc |= 1;
+ break;
+ case 'o':
+ printvc |= 2;
+ break;
+ case 'h':
+ fprintf(stderr, "%s [-d <dev>] [-v <vc>] [-gtncpoh]\n"
+ " -d <dev> Use <dev> instead of /dev/tty0\n"
+ " -v <vc> Switch to virtual console <vc>\n"
+ " -g Switch to graphics mode\n"
+ " -t Switch to text mode\n"
+ " -n Create and switch to new virtual console\n"
+ " -c Close unused virtual consoles\n"
+ " -p Print new virtual console\n"
+ " -o Print old virtual console\n"
+ " -h Print help\n", argv[0]);
+ return -1;
+ case '?':
+ fprintf(stderr, "%s: invalid option -%c\n",
+ argv[0], optopt);
+ exit(1);
+ }
+ } while (1);
+ if(mode == -1 && new_vc == 0 && close_vc == 0 && switch_vc == -1 && printvc == 0) {
+ fprintf(stderr,"%s [-d <dev>] [-v <vc>] [-gtncpoh]\n", argv[0]);
+ return -1;
+ }
+
+ fd = open(ttydev, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open %s\n", ttydev);
+ return -1;
+ }
+
+ if ((printvc && !new_vc) || (printvc & 2)) {
+ struct vt_stat vs;
+
+ res = ioctl(fd, VT_GETSTATE, &vs);
+ if (res < 0) {
+ fprintf(stderr, "ioctl(vcfd, VT_GETSTATE, &vs) failed, %d\n", res);
+ }
+ printf("%d\n", vs.v_active);
+ }
+
+ if (new_vc) {
+ int vtnum;
+ res = ioctl(fd, VT_OPENQRY, &vtnum);
+ if (res < 0 || vtnum == -1) {
+ fprintf(stderr, "ioctl(vcfd, VT_OPENQRY, &vtnum) failed, res %d, vtnum %d\n", res, vtnum);
+ }
+ switch_vc = vtnum;
+ }
+ if (switch_vc != -1) {
+ pthread_t thread;
+ pthread_attr_t attr;
+ activate_thread_switch_vc = switch_vc;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&thread, &attr, activate_thread, (void*)fd);
+
+ do {
+ res = ioctl(fd, VT_WAITACTIVE, (void*)switch_vc);
+ } while(res < 0 && errno == EINTR);
+ activate_thread_switch_vc = -1;
+ if (res < 0) {
+ fprintf(stderr, "ioctl( vcfd, VT_WAITACTIVE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), switch_vc);
+ }
+ if(printvc & 1)
+ printf("%d\n", switch_vc);
+
+ close(fd);
+ fd = open(ttydev, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open %s\n", ttydev);
+ return -1;
+ }
+ }
+ if (close_vc) {
+ res = ioctl(fd, VT_DISALLOCATE, 0);
+ if (res < 0) {
+ fprintf(stderr, "ioctl(vcfd, VT_DISALLOCATE, 0) failed, %d\n", res);
+ }
+ }
+ if (mode != -1) {
+ if (ioctl(fd, KDSETMODE, (void*)mode) < 0) {
+ fprintf(stderr, "KDSETMODE %d failed\n", mode);
+ return -1;
+ }
+ }
+ return 0;
+}