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