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 
     10 static int activate_thread_switch_vc;
     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 
     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