setconsole.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/kd.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/vt.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int activate_thread_switch_vc;
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *activate_thread(void *arg)
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int res;
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd = (int)arg;
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(activate_thread_switch_vc >= 0) {
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            res = ioctl(fd, VT_ACTIVATE, (void*)activate_thread_switch_vc);
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while(res < 0 && errno == EINTR);
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (res < 0) {
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ioctl( vcfd, VT_ACTIVATE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), activate_thread_switch_vc);
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(activate_thread_switch_vc >= 0)
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sleep(1);
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint setconsole_main(int argc, char *argv[])
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int c;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int res;
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int mode = -1;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int new_vc = 0;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int close_vc = 0;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int switch_vc = -1;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int printvc = 0;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *ttydev = "/dev/tty0";
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c = getopt(argc, argv, "d:gtncv:poh");
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (c == EOF)
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch (c) {
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'd':
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ttydev = optarg;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'g':
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(mode == KD_TEXT) {
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mode = KD_GRAPHICS;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 't':
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(mode == KD_GRAPHICS) {
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fprintf(stderr, "%s: cannot specify both -g and -t\n", argv[0]);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mode = KD_TEXT;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'n':
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            new_vc = 1;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'c':
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            close_vc = 1;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'v':
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            switch_vc = atoi(optarg);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'p':
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printvc |= 1;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'o':
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printvc |= 2;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 'h':
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "%s [-d <dev>] [-v <vc>] [-gtncpoh]\n"
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -d <dev>   Use <dev> instead of /dev/tty0\n"
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -v <vc>    Switch to virtual console <vc>\n"
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -g         Switch to graphics mode\n"
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -t         Switch to text mode\n"
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -n         Create and switch to new virtual console\n"
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -c         Close unused virtual consoles\n"
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -p         Print new virtual console\n"
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -o         Print old virtual console\n"
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "  -h         Print help\n", argv[0]);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '?':
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "%s: invalid option -%c\n",
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                argv[0], optopt);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            exit(1);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (1);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(mode == -1 && new_vc == 0 && close_vc == 0 && switch_vc == -1 && printvc == 0) {
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"%s [-d <dev>] [-v <vc>] [-gtncpoh]\n", argv[0]);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(ttydev, O_RDWR | O_SYNC);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "cannot open %s\n", ttydev);
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((printvc && !new_vc) || (printvc & 2)) {
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct vt_stat vs;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res = ioctl(fd, VT_GETSTATE, &vs);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (res < 0) {
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ioctl(vcfd, VT_GETSTATE, &vs) failed, %d\n", res);
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("%d\n", vs.v_active);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (new_vc) {
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int vtnum;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res = ioctl(fd, VT_OPENQRY, &vtnum);
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (res < 0 || vtnum == -1) {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ioctl(vcfd, VT_OPENQRY, &vtnum) failed, res %d, vtnum %d\n", res, vtnum);
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch_vc = vtnum;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (switch_vc != -1) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pthread_t thread;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pthread_attr_t attr;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        activate_thread_switch_vc = switch_vc;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pthread_attr_init(&attr);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pthread_create(&thread, &attr, activate_thread, (void*)fd);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            res = ioctl(fd, VT_WAITACTIVE, (void*)switch_vc);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while(res < 0 && errno == EINTR);
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        activate_thread_switch_vc = -1;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (res < 0) {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ioctl( vcfd, VT_WAITACTIVE, vtnum) failed, %d %d %s for %d\n", res, errno, strerror(errno), switch_vc);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(printvc & 1)
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            printf("%d\n", switch_vc);
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fd);
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = open(ttydev, O_RDWR | O_SYNC);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fd < 0) {
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "cannot open %s\n", ttydev);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (close_vc) {
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        res = ioctl(fd, VT_DISALLOCATE, 0);
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (res < 0) {
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ioctl(vcfd, VT_DISALLOCATE, 0) failed, %d\n", res);
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mode != -1) {
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ioctl(fd, KDSETMODE, (void*)mode) < 0) {
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "KDSETMODE %d failed\n", mode);
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
165