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