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