• 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