Home | History | Annotate | Download | only in toolbox
      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;
     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 
     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