12089Ssos/*- 216565Ssos * Copyright (c) 1994-1996 S�ren Schmidt 32089Ssos * All rights reserved. 42089Ssos * 5146736Sdelphij * Portions of this software are based in part on the work of 6146736Sdelphij * Sascha Wildner <saw@online.de> contributed to The DragonFly Project 7146736Sdelphij * 82089Ssos * Redistribution and use in source and binary forms, with or without 92089Ssos * modification, are permitted provided that the following conditions 102089Ssos * are met: 112089Ssos * 1. Redistributions of source code must retain the above copyright 125994Ssos * notice, this list of conditions and the following disclaimer, 135994Ssos * in this position and unchanged. 142089Ssos * 2. Redistributions in binary form must reproduce the above copyright 152089Ssos * notice, this list of conditions and the following disclaimer in the 162089Ssos * documentation and/or other materials provided with the distribution. 172089Ssos * 3. The name of the author may not be used to endorse or promote products 1897748Sschweikh * derived from this software without specific prior written permission 192089Ssos * 202089Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 212089Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 222089Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 232089Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 242089Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 252089Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 262089Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 272089Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 282089Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 292089Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30146736Sdelphij * 31146736Sdelphij * $DragonFly: src/usr.sbin/vidcontrol/vidcontrol.c,v 1.10 2005/03/02 06:08:29 joerg Exp $ 322089Ssos */ 332089Ssos 3430764Scharnier#ifndef lint 3530764Scharnierstatic const char rcsid[] = 3650479Speter "$FreeBSD$"; 3730764Scharnier#endif /* not lint */ 3830764Scharnier 392089Ssos#include <ctype.h> 4030764Scharnier#include <err.h> 4155849Syokota#include <limits.h> 422089Ssos#include <stdio.h> 4323457Sbrian#include <stdlib.h> 4430764Scharnier#include <string.h> 4523702Speter#include <unistd.h> 4666834Sphk#include <sys/fbio.h> 4766834Sphk#include <sys/consio.h> 482089Ssos#include <sys/errno.h> 4975344Ssobomax#include <sys/types.h> 5075344Ssobomax#include <sys/stat.h> 512089Ssos#include "path.h" 5223457Sbrian#include "decode.h" 532089Ssos 5471642Ssobomax 55146736Sdelphij#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 56146736Sdelphij 57102111Ssobomax/* Screen dump modes */ 58102111Ssobomax#define DUMP_FMT_RAW 1 59102111Ssobomax#define DUMP_FMT_TXT 2 60102111Ssobomax/* Screen dump options */ 61102111Ssobomax#define DUMP_FBF 0 62102111Ssobomax#define DUMP_ALL 1 63102111Ssobomax/* Screen dump file format revision */ 6476845Ssobomax#define DUMP_FMT_REV 1 6576845Ssobomax 662089Ssoschar legal_colors[16][16] = { 672089Ssos "black", "blue", "green", "cyan", 682089Ssos "red", "magenta", "brown", "white", 692089Ssos "grey", "lightblue", "lightgreen", "lightcyan", 702089Ssos "lightred", "lightmagenta", "yellow", "lightwhite" 716628Ssos}; 722089Ssos 73146736Sdelphijstruct { 74146736Sdelphij int active_vty; 75146736Sdelphij vid_info_t console_info; 76146736Sdelphij unsigned char screen_map[256]; 77146736Sdelphij int video_mode_number; 78146736Sdelphij struct video_info video_mode_info; 79146736Sdelphij} cur_info; 802089Ssos 81146736Sdelphijint hex = 0; 82146736Sdelphijint number; 83146736Sdelphijint vesa_cols; 84146736Sdelphijint vesa_rows; 85146736Sdelphijint font_height; 86146736Sdelphijint colors_changed; 87146736Sdelphijint video_mode_changed; 88146736Sdelphijint normal_fore_color, normal_back_color; 89146736Sdelphijint revers_fore_color, revers_back_color; 90146736Sdelphijchar letter; 91146736Sdelphijstruct vid_info info; 92146736Sdelphijstruct video_info new_mode_info; 93146736Sdelphij 94146736Sdelphij 95146736Sdelphij/* 96146736Sdelphij * Initialize revert data. 97146736Sdelphij * 98146736Sdelphij * NOTE: the following parameters are not yet saved/restored: 99146736Sdelphij * 100146736Sdelphij * screen saver timeout 101146736Sdelphij * cursor type 102146736Sdelphij * mouse character and mouse show/hide state 103146736Sdelphij * vty switching on/off state 104146736Sdelphij * history buffer size 105146736Sdelphij * history contents 106146736Sdelphij * font maps 107146736Sdelphij */ 108146736Sdelphij 10930764Scharnierstatic void 110146736Sdelphijinit(void) 111146736Sdelphij{ 112146736Sdelphij if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) == -1) 113146736Sdelphij errc(1, errno, "getting active vty"); 114146736Sdelphij 115146736Sdelphij cur_info.console_info.size = sizeof(cur_info.console_info); 116146736Sdelphij 117146736Sdelphij if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1) 118146736Sdelphij errc(1, errno, "getting console information"); 119146736Sdelphij 120146736Sdelphij if (ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1) 121146736Sdelphij errc(1, errno, "getting screen map"); 122146736Sdelphij 123146736Sdelphij if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1) 124146736Sdelphij errc(1, errno, "getting video mode number"); 125146736Sdelphij 126146736Sdelphij cur_info.video_mode_info.vi_mode = cur_info.video_mode_number; 127146736Sdelphij 128146736Sdelphij if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1) 129146736Sdelphij errc(1, errno, "getting video mode parameters"); 130146736Sdelphij 131146736Sdelphij normal_fore_color = cur_info.console_info.mv_norm.fore; 132146736Sdelphij normal_back_color = cur_info.console_info.mv_norm.back; 133146736Sdelphij revers_fore_color = cur_info.console_info.mv_rev.fore; 134146736Sdelphij revers_back_color = cur_info.console_info.mv_rev.back; 135146736Sdelphij} 136146736Sdelphij 137146736Sdelphij 138146736Sdelphij/* 139146736Sdelphij * If something goes wrong along the way we call revert() to go back to the 140146736Sdelphij * console state we came from (which is assumed to be working). 141146736Sdelphij * 142146736Sdelphij * NOTE: please also read the comments of init(). 143146736Sdelphij */ 144146736Sdelphij 145146736Sdelphijstatic void 146146736Sdelphijrevert(void) 147146736Sdelphij{ 148146736Sdelphij int size[3]; 149146736Sdelphij 150162671Sru ioctl(0, VT_ACTIVATE, cur_info.active_vty); 151146736Sdelphij 152146736Sdelphij fprintf(stderr, "\033[=%dA", cur_info.console_info.mv_ovscan); 153146736Sdelphij fprintf(stderr, "\033[=%dF", cur_info.console_info.mv_norm.fore); 154146736Sdelphij fprintf(stderr, "\033[=%dG", cur_info.console_info.mv_norm.back); 155146736Sdelphij fprintf(stderr, "\033[=%dH", cur_info.console_info.mv_rev.fore); 156146736Sdelphij fprintf(stderr, "\033[=%dI", cur_info.console_info.mv_rev.back); 157146736Sdelphij 158146736Sdelphij ioctl(0, PIO_SCRNMAP, &cur_info.screen_map); 159146736Sdelphij 160146736Sdelphij if (cur_info.video_mode_number >= M_VESA_BASE) 161146736Sdelphij ioctl(0, _IO('V', cur_info.video_mode_number - M_VESA_BASE), 162146736Sdelphij NULL); 163146736Sdelphij else 164146736Sdelphij ioctl(0, _IO('S', cur_info.video_mode_number), NULL); 165146736Sdelphij 166146736Sdelphij if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) { 167146736Sdelphij size[0] = cur_info.video_mode_info.vi_width / 8; 168146736Sdelphij size[1] = cur_info.video_mode_info.vi_height / 169146736Sdelphij cur_info.console_info.font_size; 170146736Sdelphij size[2] = cur_info.console_info.font_size; 171146736Sdelphij 172146736Sdelphij ioctl(0, KDRASTER, size); 173146736Sdelphij } 174146736Sdelphij} 175146736Sdelphij 176146736Sdelphij 177146736Sdelphij/* 178146736Sdelphij * Print a short usage string describing all options, then exit. 179146736Sdelphij */ 180146736Sdelphij 181146736Sdelphijstatic void 182140159Sdelphijusage(void) 1836628Ssos{ 18499706Sdd fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 185102111Ssobomax"usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]", 18677329Sdes" [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 18799706Sdd" [-M char] [-m on | off] [-r foreground background]", 188199174Sed" [-S on | off] [-s number] [-T xterm | cons25] [-t N | off]", 189199174Sed" [mode] [foreground [background]] [show]"); 19030764Scharnier exit(1); 1916628Ssos} 1926628Ssos 193146736Sdelphij 194146736Sdelphij/* 195146736Sdelphij * Retrieve the next argument from the command line (for options that require 196146736Sdelphij * more than one argument). 197146736Sdelphij */ 198146736Sdelphij 199140159Sdelphijstatic char * 20075344Ssobomaxnextarg(int ac, char **av, int *indp, int oc, int strict) 2012089Ssos{ 2022089Ssos if (*indp < ac) 2032089Ssos return(av[(*indp)++]); 204146736Sdelphij 205146736Sdelphij if (strict != 0) { 206146736Sdelphij revert(); 20775344Ssobomax errx(1, "option requires two arguments -- %c", oc); 208146736Sdelphij } 209146736Sdelphij 21075344Ssobomax return(NULL); 2112089Ssos} 2122089Ssos 213146736Sdelphij 214146736Sdelphij/* 215146736Sdelphij * Guess which file to open. Try to open each combination of a specified set 216146736Sdelphij * of file name components. 217146736Sdelphij */ 218146736Sdelphij 219140159Sdelphijstatic FILE * 220140159Sdelphijopenguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name) 2212089Ssos{ 22292460Ssobomax FILE *f; 22392460Ssobomax int i, j, k, l; 2242089Ssos 22592460Ssobomax for (i = 0; a[i] != NULL; i++) { 22692460Ssobomax for (j = 0; b[j] != NULL; j++) { 22792460Ssobomax for (k = 0; c[k] != NULL; k++) { 22892460Ssobomax for (l = 0; d[l] != NULL; l++) { 229146736Sdelphij asprintf(name, "%s%s%s%s", 230146736Sdelphij a[i], b[j], c[k], d[l]); 231146736Sdelphij 23292460Ssobomax f = fopen(*name, "r"); 233146736Sdelphij 23492460Ssobomax if (f != NULL) 23592460Ssobomax return (f); 236146736Sdelphij 23792460Ssobomax free(*name); 23892460Ssobomax } 23992460Ssobomax } 24092460Ssobomax } 24152262Sbillf } 24292460Ssobomax return (NULL); 2432089Ssos} 2442089Ssos 245146736Sdelphij 246146736Sdelphij/* 247146736Sdelphij * Load a screenmap from a file and set it. 248146736Sdelphij */ 249146736Sdelphij 250140159Sdelphijstatic void 251140159Sdelphijload_scrnmap(const char *filename) 2522089Ssos{ 25392460Ssobomax FILE *fd; 25492460Ssobomax int size; 2552089Ssos char *name; 2562089Ssos scrmap_t scrnmap; 257140159Sdelphij const char *a[] = {"", SCRNMAP_PATH, NULL}; 258140159Sdelphij const char *b[] = {filename, NULL}; 259140159Sdelphij const char *c[] = {"", ".scm", NULL}; 260140159Sdelphij const char *d[] = {"", NULL}; 2612089Ssos 26292460Ssobomax fd = openguess(a, b, c, d, &name); 263146736Sdelphij 2642089Ssos if (fd == NULL) { 265146736Sdelphij revert(); 266146736Sdelphij errx(1, "screenmap file not found"); 2672089Ssos } 268146736Sdelphij 2692089Ssos size = sizeof(scrnmap); 270146736Sdelphij 27175344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 2722089Ssos rewind(fd); 273146736Sdelphij 274146736Sdelphij if (fread(&scrnmap, 1, size, fd) != (size_t)size) { 27530764Scharnier warnx("bad screenmap file"); 27623457Sbrian fclose(fd); 277146736Sdelphij revert(); 278146736Sdelphij errx(1, "bad screenmap file"); 2792089Ssos } 2802089Ssos } 281146736Sdelphij 282146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 283146736Sdelphij revert(); 284146736Sdelphij errc(1, errno, "loading screenmap"); 285146736Sdelphij } 286146736Sdelphij 28723457Sbrian fclose(fd); 2882089Ssos} 2892089Ssos 290146736Sdelphij 291146736Sdelphij/* 292146736Sdelphij * Set the default screenmap. 293146736Sdelphij */ 294146736Sdelphij 295140159Sdelphijstatic void 296140159Sdelphijload_default_scrnmap(void) 2972089Ssos{ 2986628Ssos scrmap_t scrnmap; 2992089Ssos int i; 3002089Ssos 3012089Ssos for (i=0; i<256; i++) 3022089Ssos *((char*)&scrnmap + i) = i; 303146736Sdelphij 304146736Sdelphij if (ioctl(0, PIO_SCRNMAP, &scrnmap) == -1) { 305146736Sdelphij revert(); 306146736Sdelphij errc(1, errno, "loading default screenmap"); 307146736Sdelphij } 3082089Ssos} 3092089Ssos 310146736Sdelphij 311146736Sdelphij/* 312146736Sdelphij * Print the current screenmap to stdout. 313146736Sdelphij */ 314146736Sdelphij 315140159Sdelphijstatic void 316140159Sdelphijprint_scrnmap(void) 3172089Ssos{ 3182089Ssos unsigned char map[256]; 319140159Sdelphij size_t i; 3202089Ssos 321146736Sdelphij if (ioctl(0, GIO_SCRNMAP, &map) == -1) { 322146736Sdelphij revert(); 323146736Sdelphij errc(1, errno, "getting screenmap"); 3242089Ssos } 3252089Ssos for (i=0; i<sizeof(map); i++) { 326140159Sdelphij if (i != 0 && i % 16 == 0) 3272089Ssos fprintf(stdout, "\n"); 328146736Sdelphij 329146736Sdelphij if (hex != 0) 3308857Srgrimes fprintf(stdout, " %02x", map[i]); 3312089Ssos else 3322089Ssos fprintf(stdout, " %03d", map[i]); 3332089Ssos } 3342089Ssos fprintf(stdout, "\n"); 3352089Ssos 3362089Ssos} 3372089Ssos 338146736Sdelphij 339146736Sdelphij/* 340146736Sdelphij * Determine a file's size. 341146736Sdelphij */ 342146736Sdelphij 343140159Sdelphijstatic int 34475344Ssobomaxfsize(FILE *file) 34575344Ssobomax{ 34675344Ssobomax struct stat sb; 34775344Ssobomax 34875344Ssobomax if (fstat(fileno(file), &sb) == 0) 34975344Ssobomax return sb.st_size; 35075344Ssobomax else 35175344Ssobomax return -1; 35275344Ssobomax} 35375344Ssobomax 35475344Ssobomax 355146736Sdelphij/* 356146736Sdelphij * Load a font from file and set it. 357146736Sdelphij */ 358146736Sdelphij 359140159Sdelphijstatic void 360140159Sdelphijload_font(const char *type, const char *filename) 3612089Ssos{ 36292460Ssobomax FILE *fd; 36375344Ssobomax int h, i, size, w; 36475344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 36592460Ssobomax char *name, *fontmap, size_sufx[6]; 366140159Sdelphij const char *a[] = {"", FONT_PATH, NULL}; 367140159Sdelphij const char *b[] = {filename, NULL}; 368140159Sdelphij const char *c[] = {"", size_sufx, NULL}; 369140159Sdelphij const char *d[] = {"", ".fnt", NULL}; 370140159Sdelphij vid_info_t _info; 3712089Ssos 37275344Ssobomax struct sizeinfo { 37375344Ssobomax int w; 37475344Ssobomax int h; 37575344Ssobomax unsigned long io; 37675344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 37775344Ssobomax {8, 14, PIO_FONT8x14}, 37875344Ssobomax {8, 8, PIO_FONT8x8}, 37975344Ssobomax {0, 0, 0}}; 38075344Ssobomax 381140159Sdelphij _info.size = sizeof(_info); 382140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 383146736Sdelphij revert(); 38492460Ssobomax warn("failed to obtain current video mode parameters"); 38592460Ssobomax return; 3862089Ssos } 387146736Sdelphij 388140159Sdelphij snprintf(size_sufx, sizeof(size_sufx), "-8x%d", _info.font_size); 38992460Ssobomax fd = openguess(a, b, c, d, &name); 390146736Sdelphij 3912089Ssos if (fd == NULL) { 392146736Sdelphij revert(); 393146736Sdelphij errx(1, "%s: can't load font file", filename); 3942089Ssos } 395146736Sdelphij 39675344Ssobomax if (type != NULL) { 39775344Ssobomax size = 0; 398146736Sdelphij if (sscanf(type, "%dx%d", &w, &h) == 2) { 399146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 40075344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 40175344Ssobomax size = DATASIZE(sizes[i]); 40275344Ssobomax io = sizes[i].io; 403146736Sdelphij font_height = sizes[i].h; 40475344Ssobomax } 405146736Sdelphij } 406146736Sdelphij } 40775344Ssobomax if (size == 0) { 40875344Ssobomax fclose(fd); 409146736Sdelphij revert(); 410146736Sdelphij errx(1, "%s: bad font size specification", type); 41175344Ssobomax } 41275344Ssobomax } else { 41375344Ssobomax /* Apply heuristics */ 414146736Sdelphij 41575344Ssobomax int j; 41675344Ssobomax int dsize[2]; 41775344Ssobomax 41875344Ssobomax size = DATASIZE(sizes[0]); 41975344Ssobomax fontmap = (char*) malloc(size); 42075344Ssobomax dsize[0] = decode(fd, fontmap, size); 42175344Ssobomax dsize[1] = fsize(fd); 42275344Ssobomax free(fontmap); 42375344Ssobomax 42475344Ssobomax size = 0; 425146736Sdelphij for (j = 0; j < 2; j++) { 426146736Sdelphij for (i = 0; sizes[i].w != 0; i++) { 42775344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 42875344Ssobomax size = dsize[j]; 42975344Ssobomax io = sizes[i].io; 430146736Sdelphij font_height = sizes[i].h; 43175344Ssobomax j = 2; /* XXX */ 43275344Ssobomax break; 43375344Ssobomax } 434146736Sdelphij } 435146736Sdelphij } 43675344Ssobomax 43775344Ssobomax if (size == 0) { 43875344Ssobomax fclose(fd); 439146736Sdelphij revert(); 440146736Sdelphij errx(1, "%s: can't guess font size", filename); 44175344Ssobomax } 442146736Sdelphij 44375344Ssobomax rewind(fd); 4442089Ssos } 44575344Ssobomax 4462089Ssos fontmap = (char*) malloc(size); 447146736Sdelphij 44875344Ssobomax if (decode(fd, fontmap, size) != size) { 4492089Ssos rewind(fd); 450146736Sdelphij if (fsize(fd) != size || 451146736Sdelphij fread(fontmap, 1, size, fd) != (size_t)size) { 45275344Ssobomax warnx("%s: bad font file", filename); 45323457Sbrian fclose(fd); 4542089Ssos free(fontmap); 455146736Sdelphij revert(); 456146736Sdelphij errx(1, "%s: bad font file", filename); 4572089Ssos } 4582089Ssos } 459146736Sdelphij 460146736Sdelphij if (ioctl(0, io, fontmap) == -1) { 461146736Sdelphij revert(); 462146736Sdelphij errc(1, errno, "loading font"); 463146736Sdelphij } 464146736Sdelphij 46523457Sbrian fclose(fd); 4662089Ssos free(fontmap); 4672089Ssos} 4682089Ssos 469146736Sdelphij 470146736Sdelphij/* 471146736Sdelphij * Set the timeout for the screensaver. 472146736Sdelphij */ 473146736Sdelphij 474140159Sdelphijstatic void 4752089Ssosset_screensaver_timeout(char *arg) 4762089Ssos{ 4772089Ssos int nsec; 4782089Ssos 479146736Sdelphij if (!strcmp(arg, "off")) { 4802089Ssos nsec = 0; 481146736Sdelphij } else { 4822089Ssos nsec = atoi(arg); 483146736Sdelphij 4842089Ssos if ((*arg == '\0') || (nsec < 1)) { 485146736Sdelphij revert(); 486146736Sdelphij errx(1, "argument must be a positive number"); 4872089Ssos } 4882089Ssos } 489146736Sdelphij 490146736Sdelphij if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) { 491146736Sdelphij revert(); 492146736Sdelphij errc(1, errno, "setting screensaver period"); 493146736Sdelphij } 4942089Ssos} 4952089Ssos 496146736Sdelphij 497146736Sdelphij/* 498146736Sdelphij * Set the cursor's shape/type. 499146736Sdelphij */ 500146736Sdelphij 501140159Sdelphijstatic void 5025536Ssosset_cursor_type(char *appearence) 5032089Ssos{ 5045536Ssos int type; 5052089Ssos 5066230Ssos if (!strcmp(appearence, "normal")) 5076230Ssos type = 0; 5086230Ssos else if (!strcmp(appearence, "blink")) 5095536Ssos type = 1; 5106230Ssos else if (!strcmp(appearence, "destructive")) 5116230Ssos type = 3; 5125536Ssos else { 513146736Sdelphij revert(); 514146736Sdelphij errx(1, "argument to -c must be normal, blink or destructive"); 5152089Ssos } 516146736Sdelphij 517146736Sdelphij if (ioctl(0, CONS_CURSORTYPE, &type) == -1) { 518146736Sdelphij revert(); 519146736Sdelphij errc(1, errno, "setting cursor type"); 520146736Sdelphij } 5212089Ssos} 5222089Ssos 523146736Sdelphij 524146736Sdelphij/* 525146736Sdelphij * Set the video mode. 526146736Sdelphij */ 527146736Sdelphij 528140159Sdelphijstatic int 529146736Sdelphijvideo_mode(int argc, char **argv, int *mode_index) 5302089Ssos{ 53139592Syokota static struct { 532140159Sdelphij const char *name; 53339592Syokota unsigned long mode; 534146736Sdelphij unsigned long mode_num; 53539592Syokota } modes[] = { 536146736Sdelphij { "80x25", SW_TEXT_80x25, M_TEXT_80x25 }, 537146736Sdelphij { "80x30", SW_TEXT_80x30, M_TEXT_80x30 }, 538146736Sdelphij { "80x43", SW_TEXT_80x43, M_TEXT_80x43 }, 539146736Sdelphij { "80x50", SW_TEXT_80x50, M_TEXT_80x50 }, 540146736Sdelphij { "80x60", SW_TEXT_80x60, M_TEXT_80x60 }, 541146736Sdelphij { "132x25", SW_TEXT_132x25, M_TEXT_132x25 }, 542146736Sdelphij { "132x30", SW_TEXT_132x30, M_TEXT_132x30 }, 543146736Sdelphij { "132x43", SW_TEXT_132x43, M_TEXT_132x43 }, 544146736Sdelphij { "132x50", SW_TEXT_132x50, M_TEXT_132x50 }, 545146736Sdelphij { "132x60", SW_TEXT_132x60, M_TEXT_132x60 }, 546146736Sdelphij { "VGA_40x25", SW_VGA_C40x25, M_VGA_C40x25 }, 547146736Sdelphij { "VGA_80x25", SW_VGA_C80x25, M_VGA_C80x25 }, 548146736Sdelphij { "VGA_80x30", SW_VGA_C80x30, M_VGA_C80x30 }, 549146736Sdelphij { "VGA_80x50", SW_VGA_C80x50, M_VGA_C80x50 }, 550146736Sdelphij { "VGA_80x60", SW_VGA_C80x60, M_VGA_C80x60 }, 55148105Syokota#ifdef SW_VGA_C90x25 552146736Sdelphij { "VGA_90x25", SW_VGA_C90x25, M_VGA_C90x25 }, 553146736Sdelphij { "VGA_90x30", SW_VGA_C90x30, M_VGA_C90x30 }, 554146736Sdelphij { "VGA_90x43", SW_VGA_C90x43, M_VGA_C90x43 }, 555146736Sdelphij { "VGA_90x50", SW_VGA_C90x50, M_VGA_C90x50 }, 556146736Sdelphij { "VGA_90x60", SW_VGA_C90x60, M_VGA_C90x60 }, 55748105Syokota#endif 558146736Sdelphij { "VGA_320x200", SW_VGA_CG320, M_CG320 }, 559146736Sdelphij { "EGA_80x25", SW_ENH_C80x25, M_ENH_C80x25 }, 560146736Sdelphij { "EGA_80x43", SW_ENH_C80x43, M_ENH_C80x43 }, 561146736Sdelphij { "VESA_132x25", SW_VESA_C132x25,M_VESA_C132x25 }, 562146736Sdelphij { "VESA_132x43", SW_VESA_C132x43,M_VESA_C132x43 }, 563146736Sdelphij { "VESA_132x50", SW_VESA_C132x50,M_VESA_C132x50 }, 564146736Sdelphij { "VESA_132x60", SW_VESA_C132x60,M_VESA_C132x60 }, 565146736Sdelphij { "VESA_800x600", SW_VESA_800x600,M_VESA_800x600 }, 566146736Sdelphij { NULL, 0, 0 }, 56739592Syokota }; 568146736Sdelphij 569146736Sdelphij int new_mode_num = 0; 57042605Smjacob unsigned long mode = 0; 57148105Syokota int cur_mode; 57248105Syokota int ioerr; 57339287Ssos int size[3]; 57439592Syokota int i; 5752089Ssos 57648105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 57748105Syokota err(1, "cannot get the current video mode"); 578146736Sdelphij 579146736Sdelphij /* 580146736Sdelphij * Parse the video mode argument... 581146736Sdelphij */ 582146736Sdelphij 583146736Sdelphij if (*mode_index < argc) { 584146736Sdelphij if (!strncmp(argv[*mode_index], "MODE_", 5)) { 585146736Sdelphij if (!isdigit(argv[*mode_index][5])) 586146736Sdelphij errx(1, "invalid video mode number"); 587146736Sdelphij 588146736Sdelphij new_mode_num = atoi(&argv[*mode_index][5]); 589146736Sdelphij } else { 590146736Sdelphij for (i = 0; modes[i].name != NULL; ++i) { 591146736Sdelphij if (!strcmp(argv[*mode_index], modes[i].name)) { 592146736Sdelphij mode = modes[i].mode; 593146736Sdelphij new_mode_num = modes[i].mode_num; 594146736Sdelphij break; 595146736Sdelphij } 59639592Syokota } 597146736Sdelphij 598146736Sdelphij if (modes[i].name == NULL) 599146736Sdelphij return EXIT_FAILURE; 600146736Sdelphij if (ioctl(0, mode, NULL) < 0) { 601146736Sdelphij warn("cannot set videomode"); 602146736Sdelphij return EXIT_FAILURE; 603146736Sdelphij } 60439592Syokota } 605146736Sdelphij 606146736Sdelphij /* 607146736Sdelphij * Collect enough information about the new video mode... 608146736Sdelphij */ 609146736Sdelphij 610146736Sdelphij new_mode_info.vi_mode = new_mode_num; 611146736Sdelphij 612146736Sdelphij if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) { 613146736Sdelphij revert(); 614146736Sdelphij errc(1, errno, "obtaining new video mode parameters"); 615120201Seivind } 616146736Sdelphij 617146736Sdelphij if (mode == 0) { 618146736Sdelphij if (new_mode_num >= M_VESA_BASE) 619146736Sdelphij mode = _IO('V', new_mode_num - M_VESA_BASE); 620146736Sdelphij else 621146736Sdelphij mode = _IO('S', new_mode_num); 622146736Sdelphij } 623146736Sdelphij 624146736Sdelphij /* 625146736Sdelphij * Try setting the new mode. 626146736Sdelphij */ 627146736Sdelphij 628146736Sdelphij if (ioctl(0, mode, NULL) == -1) { 629146736Sdelphij revert(); 630146736Sdelphij errc(1, errno, "setting video mode"); 631146736Sdelphij } 632146736Sdelphij 633146736Sdelphij /* 634146736Sdelphij * For raster modes it's not enough to just set the mode. 635146736Sdelphij * We also need to explicitly set the raster mode. 636146736Sdelphij */ 637146736Sdelphij 638146736Sdelphij if (new_mode_info.vi_flags & V_INFO_GRAPHICS) { 639146736Sdelphij /* font size */ 640146736Sdelphij 641146736Sdelphij if (font_height == 0) 642146736Sdelphij font_height = cur_info.console_info.font_size; 643146736Sdelphij 644146736Sdelphij size[2] = font_height; 645146736Sdelphij 646146736Sdelphij /* adjust columns */ 647146736Sdelphij 648146736Sdelphij if ((vesa_cols * 8 > new_mode_info.vi_width) || 649146736Sdelphij (vesa_cols <= 0)) { 650146736Sdelphij size[0] = new_mode_info.vi_width / 8; 65171642Ssobomax } else { 65271642Ssobomax size[0] = vesa_cols; 65371642Ssobomax } 654146736Sdelphij 655146736Sdelphij /* adjust rows */ 656146736Sdelphij 657146736Sdelphij if ((vesa_rows * font_height > new_mode_info.vi_height) || 658146736Sdelphij (vesa_rows <= 0)) { 659146736Sdelphij size[1] = new_mode_info.vi_height / 660146736Sdelphij font_height; 66171642Ssobomax } else { 66271642Ssobomax size[1] = vesa_rows; 66371642Ssobomax } 664146736Sdelphij 665146736Sdelphij /* set raster mode */ 666146736Sdelphij 66748105Syokota if (ioctl(0, KDRASTER, size)) { 66848105Syokota ioerr = errno; 66948105Syokota if (cur_mode >= M_VESA_BASE) 67080148Syokota ioctl(0, 67180148Syokota _IO('V', cur_mode - M_VESA_BASE), 67280148Syokota NULL); 67348105Syokota else 67448105Syokota ioctl(0, _IO('S', cur_mode), NULL); 675146736Sdelphij revert(); 67648105Syokota warnc(ioerr, "cannot activate raster display"); 677120201Seivind return EXIT_FAILURE; 67848105Syokota } 67939287Ssos } 680146736Sdelphij 681146736Sdelphij video_mode_changed = 1; 682146736Sdelphij 683146736Sdelphij (*mode_index)++; 6842089Ssos } 685120201Seivind return EXIT_SUCCESS; 6862089Ssos} 6878857Srgrimes 688146736Sdelphij 689146736Sdelphij/* 690146736Sdelphij * Return the number for a specified color name. 691146736Sdelphij */ 692146736Sdelphij 693140159Sdelphijstatic int 6942089Ssosget_color_number(char *color) 6952089Ssos{ 6962089Ssos int i; 6972089Ssos 698146736Sdelphij for (i=0; i<16; i++) { 6992089Ssos if (!strcmp(color, legal_colors[i])) 7002089Ssos return i; 701146736Sdelphij } 7022089Ssos return -1; 7032089Ssos} 7042089Ssos 705146736Sdelphij 706146736Sdelphij/* 707146736Sdelphij * Get normal text and background colors. 708146736Sdelphij */ 709146736Sdelphij 710140159Sdelphijstatic void 711146736Sdelphijget_normal_colors(int argc, char **argv, int *_index) 7122089Ssos{ 7132089Ssos int color; 7142089Ssos 715140159Sdelphij if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) { 716140159Sdelphij (*_index)++; 717146241Snyan fprintf(stderr, "\033[=%dF", color); 718150246Srodrigc normal_fore_color=color; 719150246Srodrigc colors_changed = 1; 720140159Sdelphij if (*_index < argc 721140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 7222089Ssos && color < 8) { 723140159Sdelphij (*_index)++; 724146241Snyan fprintf(stderr, "\033[=%dG", color); 725150246Srodrigc normal_back_color=color; 7262089Ssos } 7272089Ssos } 7282089Ssos} 7292089Ssos 730146736Sdelphij 731146736Sdelphij/* 732146736Sdelphij * Get reverse text and background colors. 733146736Sdelphij */ 734146736Sdelphij 735140159Sdelphijstatic void 736146736Sdelphijget_reverse_colors(int argc, char **argv, int *_index) 7372089Ssos{ 7382089Ssos int color; 7392089Ssos 740140159Sdelphij if ((color = get_color_number(argv[*(_index)-1])) != -1) { 741146241Snyan fprintf(stderr, "\033[=%dH", color); 742150246Srodrigc revers_fore_color=color; 743150246Srodrigc colors_changed = 1; 744140159Sdelphij if (*_index < argc 745140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 7462089Ssos && color < 8) { 747140159Sdelphij (*_index)++; 748146241Snyan fprintf(stderr, "\033[=%dI", color); 749150246Srodrigc revers_back_color=color; 7502089Ssos } 7512089Ssos } 7522089Ssos} 7532089Ssos 754146736Sdelphij 755146736Sdelphij/* 756146736Sdelphij * Set normal and reverse foreground and background colors. 757146736Sdelphij */ 758146736Sdelphij 759140159Sdelphijstatic void 760146736Sdelphijset_colors(void) 761146736Sdelphij{ 762146736Sdelphij fprintf(stderr, "\033[=%dF", normal_fore_color); 763146736Sdelphij fprintf(stderr, "\033[=%dG", normal_back_color); 764146736Sdelphij fprintf(stderr, "\033[=%dH", revers_fore_color); 765146736Sdelphij fprintf(stderr, "\033[=%dI", revers_back_color); 766146736Sdelphij} 767146736Sdelphij 768146736Sdelphij 769146736Sdelphij/* 770146736Sdelphij * Switch to virtual terminal #arg. 771146736Sdelphij */ 772146736Sdelphij 773146736Sdelphijstatic void 77423457Sbrianset_console(char *arg) 77523457Sbrian{ 77623457Sbrian int n; 77723457Sbrian 778146736Sdelphij if(!arg || strspn(arg,"0123456789") != strlen(arg)) { 779146736Sdelphij revert(); 780146736Sdelphij errx(1, "bad console number"); 78123457Sbrian } 78223457Sbrian 78323457Sbrian n = atoi(arg); 784146736Sdelphij 78551393Syokota if (n < 1 || n > 16) { 786146736Sdelphij revert(); 787146736Sdelphij errx(1, "console number out of range"); 788162671Sru } else if (ioctl(0, VT_ACTIVATE, n) == -1) { 789146736Sdelphij revert(); 790146736Sdelphij errc(1, errno, "switching vty"); 791146736Sdelphij } 79223457Sbrian} 79323457Sbrian 794146736Sdelphij 795146736Sdelphij/* 796146736Sdelphij * Sets the border color. 797146736Sdelphij */ 798146736Sdelphij 799140159Sdelphijstatic void 8002089Ssosset_border_color(char *arg) 8012089Ssos{ 8022089Ssos int color; 8032089Ssos 8042089Ssos if ((color = get_color_number(arg)) != -1) { 805146241Snyan fprintf(stderr, "\033[=%dA", color); 8062089Ssos } 8072089Ssos else 8088857Srgrimes usage(); 8092089Ssos} 8102089Ssos 811140159Sdelphijstatic void 81255849Syokotaset_mouse_char(char *arg) 81355849Syokota{ 81455849Syokota struct mouse_info mouse; 81555849Syokota long l; 81655849Syokota 81755849Syokota l = strtol(arg, NULL, 0); 818146736Sdelphij 81975788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 820146736Sdelphij revert(); 82175788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 82255849Syokota return; 82355849Syokota } 824146736Sdelphij 82555849Syokota mouse.operation = MOUSE_MOUSECHAR; 82655849Syokota mouse.u.mouse_char = (int)l; 827146736Sdelphij 828146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 829146736Sdelphij revert(); 830146736Sdelphij errc(1, errno, "setting mouse character"); 831146736Sdelphij } 83255849Syokota} 83355849Syokota 834146736Sdelphij 835146736Sdelphij/* 836146736Sdelphij * Show/hide the mouse. 837146736Sdelphij */ 838146736Sdelphij 839140159Sdelphijstatic void 84016565Ssosset_mouse(char *arg) 84116565Ssos{ 84216565Ssos struct mouse_info mouse; 84316565Ssos 844146736Sdelphij if (!strcmp(arg, "on")) { 84516565Ssos mouse.operation = MOUSE_SHOW; 846146736Sdelphij } else if (!strcmp(arg, "off")) { 84716565Ssos mouse.operation = MOUSE_HIDE; 848146736Sdelphij } else { 849146736Sdelphij revert(); 850146736Sdelphij errx(1, "argument to -m must be either on or off"); 85116565Ssos } 852146736Sdelphij 853146736Sdelphij if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) { 854146736Sdelphij revert(); 855146736Sdelphij errc(1, errno, "%sing the mouse", 856146736Sdelphij mouse.operation == MOUSE_SHOW ? "show" : "hid"); 857146736Sdelphij } 85816565Ssos} 85916565Ssos 860146736Sdelphij 861140159Sdelphijstatic void 86299705Sddset_lockswitch(char *arg) 86399705Sdd{ 86499705Sdd int data; 86599705Sdd 866146736Sdelphij if (!strcmp(arg, "off")) { 86799705Sdd data = 0x01; 868146736Sdelphij } else if (!strcmp(arg, "on")) { 86999705Sdd data = 0x02; 870146736Sdelphij } else { 871146736Sdelphij revert(); 872146736Sdelphij errx(1, "argument to -S must be either on or off"); 87399705Sdd } 874146736Sdelphij 875146736Sdelphij if (ioctl(0, VT_LOCKSWITCH, &data) == -1) { 876146736Sdelphij revert(); 877146736Sdelphij errc(1, errno, "turning %s vty switching", 878146736Sdelphij data == 0x01 ? "off" : "on"); 879146736Sdelphij } 88099705Sdd} 88199705Sdd 882146736Sdelphij 883146736Sdelphij/* 884146736Sdelphij * Return the adapter name for a specified type. 885146736Sdelphij */ 886146736Sdelphij 887140159Sdelphijstatic const char 88839287Ssos*adapter_name(int type) 88939287Ssos{ 89039287Ssos static struct { 89139287Ssos int type; 892140159Sdelphij const char *name; 89339287Ssos } names[] = { 89439287Ssos { KD_MONO, "MDA" }, 89539287Ssos { KD_HERCULES, "Hercules" }, 89639287Ssos { KD_CGA, "CGA" }, 89739287Ssos { KD_EGA, "EGA" }, 89839287Ssos { KD_VGA, "VGA" }, 89939287Ssos { KD_PC98, "PC-98xx" }, 90048105Syokota { KD_TGA, "TGA" }, 90139287Ssos { -1, "Unknown" }, 90239287Ssos }; 903146736Sdelphij 90439287Ssos int i; 90539287Ssos 90639287Ssos for (i = 0; names[i].type != -1; ++i) 90739287Ssos if (names[i].type == type) 90839287Ssos break; 90939287Ssos return names[i].name; 91039287Ssos} 91139287Ssos 912146736Sdelphij 913146736Sdelphij/* 914146736Sdelphij * Show graphics adapter information. 915146736Sdelphij */ 916146736Sdelphij 917140159Sdelphijstatic void 91839287Ssosshow_adapter_info(void) 91939287Ssos{ 92042505Syokota struct video_adapter_info ad; 92139287Ssos 92239287Ssos ad.va_index = 0; 923146736Sdelphij 924146736Sdelphij if (ioctl(0, CONS_ADPINFO, &ad) == -1) { 925146736Sdelphij revert(); 926146736Sdelphij errc(1, errno, "obtaining adapter information"); 92739287Ssos } 92839287Ssos 92942505Syokota printf("fb%d:\n", ad.va_index); 93042505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 93142505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 93239287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 93342505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 93439287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 93539287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 936140159Sdelphij printf(" frame buffer window:0x%zx, buffer size:0x%zx\n", 93748105Syokota ad.va_window, ad.va_buffer_size); 938140159Sdelphij printf(" window size:0x%zx, origin:0x%x\n", 93948105Syokota ad.va_window_size, ad.va_window_orig); 94048105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 94148105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 942140159Sdelphij printf(" reserved:0x%zx\n", ad.va_unused0); 94339287Ssos} 94439287Ssos 945146736Sdelphij 946146736Sdelphij/* 947146736Sdelphij * Show video mode information. 948146736Sdelphij */ 949146736Sdelphij 950140159Sdelphijstatic void 95139287Ssosshow_mode_info(void) 95239287Ssos{ 953205855Sjkim char buf[80]; 954140159Sdelphij struct video_info _info; 955205855Sjkim int c; 956205855Sjkim int mm; 95739287Ssos int mode; 95839287Ssos 95939287Ssos printf(" mode# flags type size " 96039287Ssos "font window linear buffer\n"); 96139287Ssos printf("---------------------------------------" 96239287Ssos "---------------------------------------\n"); 963146736Sdelphij 964250729Seadler for (mode = 0; mode <= M_VESA_MODE_MAX; ++mode) { 965140159Sdelphij _info.vi_mode = mode; 966140159Sdelphij if (ioctl(0, CONS_MODEINFO, &_info)) 96739287Ssos continue; 968140159Sdelphij if (_info.vi_mode != mode) 96948105Syokota continue; 97039287Ssos 97139287Ssos printf("%3d (0x%03x)", mode, mode); 972140159Sdelphij printf(" 0x%08x", _info.vi_flags); 973140159Sdelphij if (_info.vi_flags & V_INFO_GRAPHICS) { 97439287Ssos c = 'G'; 975146736Sdelphij 976205855Sjkim if (_info.vi_mem_model == V_INFO_MM_PLANAR) 977205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %d", 978205855Sjkim _info.vi_width, _info.vi_height, 979205855Sjkim _info.vi_depth, _info.vi_planes); 980205855Sjkim else { 981205855Sjkim switch (_info.vi_mem_model) { 982205855Sjkim case V_INFO_MM_PACKED: 983205855Sjkim mm = 'P'; 984205855Sjkim break; 985205855Sjkim case V_INFO_MM_DIRECT: 986205855Sjkim mm = 'D'; 987205855Sjkim break; 988205855Sjkim case V_INFO_MM_CGA: 989205855Sjkim mm = 'C'; 990205855Sjkim break; 991205855Sjkim case V_INFO_MM_HGC: 992205855Sjkim mm = 'H'; 993205855Sjkim break; 994205855Sjkim case V_INFO_MM_VGAX: 995205855Sjkim mm = 'V'; 996205855Sjkim break; 997205855Sjkim default: 998205855Sjkim mm = ' '; 999205855Sjkim break; 1000205855Sjkim } 1001205855Sjkim snprintf(buf, sizeof(buf), "%dx%dx%d %c", 1002205855Sjkim _info.vi_width, _info.vi_height, 1003205855Sjkim _info.vi_depth, mm); 1004205855Sjkim } 100539287Ssos } else { 100639287Ssos c = 'T'; 1007146736Sdelphij 100839287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1009140159Sdelphij _info.vi_width, _info.vi_height); 101039287Ssos } 1011146736Sdelphij 101239287Ssos printf(" %c %-15s", c, buf); 101339287Ssos snprintf(buf, sizeof(buf), "%dx%d", 1014140159Sdelphij _info.vi_cwidth, _info.vi_cheight); 101539287Ssos printf(" %-5s", buf); 1016140159Sdelphij printf(" 0x%05zx %2dk %2dk", 1017140159Sdelphij _info.vi_window, (int)_info.vi_window_size/1024, 1018140159Sdelphij (int)_info.vi_window_gran/1024); 1019140159Sdelphij printf(" 0x%08zx %dk\n", 1020140159Sdelphij _info.vi_buffer, (int)_info.vi_buffer_size/1024); 102139287Ssos } 102239287Ssos} 102339287Ssos 1024146736Sdelphij 1025140159Sdelphijstatic void 102639287Ssosshow_info(char *arg) 102739287Ssos{ 1028146736Sdelphij if (!strcmp(arg, "adapter")) { 102939287Ssos show_adapter_info(); 1030146736Sdelphij } else if (!strcmp(arg, "mode")) { 103139287Ssos show_mode_info(); 1032146736Sdelphij } else { 1033146736Sdelphij revert(); 1034146736Sdelphij errx(1, "argument to -i must be either adapter or mode"); 103539287Ssos } 103639287Ssos} 103739287Ssos 1038146736Sdelphij 1039140159Sdelphijstatic void 1040140159Sdelphijtest_frame(void) 10412089Ssos{ 1042146237Snyan int i, cur_mode, fore; 10432089Ssos 1044146237Snyan fore = 15; 1045146237Snyan 1046146237Snyan if (ioctl(0, CONS_GET, &cur_mode) < 0) 1047146237Snyan err(1, "must be on a virtual console"); 1048146237Snyan switch (cur_mode) { 1049146237Snyan case M_PC98_80x25: 1050146237Snyan case M_PC98_80x30: 1051146237Snyan fore = 7; 1052146237Snyan break; 1053146237Snyan } 1054146237Snyan 1055146241Snyan fprintf(stdout, "\033[=0G\n\n"); 10562089Ssos for (i=0; i<8; i++) { 1057146241Snyan fprintf(stdout, "\033[=%dF\033[=0G %2d \033[=%dF%-16s" 1058146241Snyan "\033[=%dF\033[=0G %2d \033[=%dF%-16s " 1059146241Snyan "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n", 1060146237Snyan fore, i, i, legal_colors[i], 1061146237Snyan fore, i+8, i+8, legal_colors[i+8], 1062146237Snyan fore, i, i); 10632089Ssos } 1064146241Snyan fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n", 10658857Srgrimes info.mv_norm.fore, info.mv_norm.back, 10662089Ssos info.mv_rev.fore, info.mv_rev.back); 10672089Ssos} 10682089Ssos 1069146736Sdelphij 107076845Ssobomax/* 107176845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 107276845Ssobomax * ioctl, and writes the results to stdout either in the special 107376845Ssobomax * binary format (see manual page for details), or in the plain 107476845Ssobomax * text format. 107576845Ssobomax */ 1076146736Sdelphij 1077140159Sdelphijstatic void 1078102111Ssobomaxdump_screen(int mode, int opt) 107976845Ssobomax{ 108076845Ssobomax scrshot_t shot; 1081140159Sdelphij vid_info_t _info; 108276845Ssobomax 1083140159Sdelphij _info.size = sizeof(_info); 1084146736Sdelphij 1085140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 1086146736Sdelphij revert(); 1087146736Sdelphij errc(1, errno, "obtaining current video mode parameters"); 108876845Ssobomax return; 108976845Ssobomax } 109076845Ssobomax 1091102111Ssobomax shot.x = shot.y = 0; 1092140159Sdelphij shot.xsize = _info.mv_csz; 1093140159Sdelphij shot.ysize = _info.mv_rsz; 1094102111Ssobomax if (opt == DUMP_ALL) 1095140159Sdelphij shot.ysize += _info.mv_hsz; 1096102111Ssobomax 1097102111Ssobomax shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t)); 109876845Ssobomax if (shot.buf == NULL) { 1099146736Sdelphij revert(); 1100146736Sdelphij errx(1, "failed to allocate memory for dump"); 110176845Ssobomax } 110276845Ssobomax 110376845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 1104146736Sdelphij revert(); 1105146736Sdelphij errc(1, errno, "dumping screen"); 110676845Ssobomax } 110776845Ssobomax 1108102111Ssobomax if (mode == DUMP_FMT_RAW) { 110976845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 111076845Ssobomax shot.xsize, shot.ysize); 1111146736Sdelphij 111276845Ssobomax fflush(stdout); 111376845Ssobomax 1114146736Sdelphij write(STDOUT_FILENO, shot.buf, 1115146736Sdelphij shot.xsize * shot.ysize * sizeof(u_int16_t)); 111676845Ssobomax } else { 111776845Ssobomax char *line; 111876845Ssobomax int x, y; 111976845Ssobomax u_int16_t ch; 112076845Ssobomax 112176845Ssobomax line = alloca(shot.xsize + 1); 1122146736Sdelphij 112376845Ssobomax if (line == NULL) { 1124146736Sdelphij revert(); 1125146736Sdelphij errx(1, "failed to allocate memory for line buffer"); 112676845Ssobomax } 112776845Ssobomax 112876845Ssobomax for (y = 0; y < shot.ysize; y++) { 112976845Ssobomax for (x = 0; x < shot.xsize; x++) { 113076845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 113176845Ssobomax ch &= 0xff; 1132146736Sdelphij 113376845Ssobomax if (isprint(ch) == 0) 113476845Ssobomax ch = ' '; 1135146736Sdelphij 113676845Ssobomax line[x] = (char)ch; 113776845Ssobomax } 113876845Ssobomax 113976845Ssobomax /* Trim trailing spaces */ 1140146736Sdelphij 114176845Ssobomax do { 114276845Ssobomax line[x--] = '\0'; 114376845Ssobomax } while (line[x] == ' ' && x != 0); 114476845Ssobomax 114576845Ssobomax puts(line); 114676845Ssobomax } 1147146736Sdelphij 114876845Ssobomax fflush(stdout); 114976845Ssobomax } 115076845Ssobomax} 115176845Ssobomax 1152146736Sdelphij 1153146736Sdelphij/* 1154146736Sdelphij * Set the console history buffer size. 1155146736Sdelphij */ 1156146736Sdelphij 1157140159Sdelphijstatic void 115877329Sdesset_history(char *opt) 115977329Sdes{ 116077329Sdes int size; 116177329Sdes 116277329Sdes size = atoi(opt); 1163146736Sdelphij 116477329Sdes if ((*opt == '\0') || size < 0) { 1165146736Sdelphij revert(); 1166146736Sdelphij errx(1, "argument must be a positive number"); 116777329Sdes } 1168146736Sdelphij 1169146736Sdelphij if (ioctl(0, CONS_HISTORY, &size) == -1) { 1170146736Sdelphij revert(); 1171146736Sdelphij errc(1, errno, "setting history buffer size"); 1172146736Sdelphij } 117377329Sdes} 117477329Sdes 1175146736Sdelphij 1176146736Sdelphij/* 1177146736Sdelphij * Clear the console history buffer. 1178146736Sdelphij */ 1179146736Sdelphij 1180140159Sdelphijstatic void 1181140159Sdelphijclear_history(void) 118277329Sdes{ 1183146736Sdelphij if (ioctl(0, CONS_CLRHIST) == -1) { 1184146736Sdelphij revert(); 1185146736Sdelphij errc(1, errno, "clearing history buffer"); 1186146736Sdelphij } 118777329Sdes} 118877329Sdes 1189199174Sedstatic void 1190199174Sedset_terminal_mode(char *arg) 1191199174Sed{ 1192146736Sdelphij 1193199174Sed if (strcmp(arg, "xterm") == 0) 1194199174Sed fprintf(stderr, "\033[=T"); 1195199174Sed else if (strcmp(arg, "cons25") == 0) 1196199174Sed fprintf(stderr, "\033[=1T"); 1197199174Sed} 1198199174Sed 1199199174Sed 120023457Sbrianint 12012089Ssosmain(int argc, char **argv) 12022089Ssos{ 1203238158Sache char *font, *type, *termmode; 1204102111Ssobomax int dumpmod, dumpopt, opt; 1205120201Seivind int reterr; 12062089Ssos 1207146736Sdelphij init(); 1208146736Sdelphij 12092089Ssos info.size = sizeof(info); 1210146736Sdelphij 1211146736Sdelphij if (ioctl(0, CONS_GETINFO, &info) == -1) 121230764Scharnier err(1, "must be on a virtual console"); 1213102111Ssobomax dumpmod = 0; 1214102111Ssobomax dumpopt = DUMP_FBF; 1215238158Sache termmode = NULL; 1216199174Sed while ((opt = getopt(argc, argv, 1217199174Sed "b:Cc:df:g:h:Hi:l:LM:m:pPr:S:s:T:t:x")) != -1) 12182089Ssos switch(opt) { 121977329Sdes case 'b': 122077329Sdes set_border_color(optarg); 122177329Sdes break; 122277329Sdes case 'C': 122377329Sdes clear_history(); 122477329Sdes break; 122577329Sdes case 'c': 122677329Sdes set_cursor_type(optarg); 122777329Sdes break; 122877329Sdes case 'd': 122977329Sdes print_scrnmap(); 123077329Sdes break; 123177329Sdes case 'f': 123277329Sdes type = optarg; 123377329Sdes font = nextarg(argc, argv, &optind, 'f', 0); 1234146736Sdelphij 123577329Sdes if (font == NULL) { 123677329Sdes type = NULL; 123777329Sdes font = optarg; 123877329Sdes } 1239146736Sdelphij 124077329Sdes load_font(type, font); 124177329Sdes break; 124277329Sdes case 'g': 1243146736Sdelphij if (sscanf(optarg, "%dx%d", 1244146736Sdelphij &vesa_cols, &vesa_rows) != 2) { 1245146736Sdelphij revert(); 124677329Sdes warnx("incorrect geometry: %s", optarg); 12472089Ssos usage(); 124877329Sdes } 1249146736Sdelphij break; 125077329Sdes case 'h': 125177329Sdes set_history(optarg); 125277329Sdes break; 1253102111Ssobomax case 'H': 1254102111Ssobomax dumpopt = DUMP_ALL; 1255102111Ssobomax break; 125677329Sdes case 'i': 125777329Sdes show_info(optarg); 125877329Sdes break; 125977329Sdes case 'l': 126077329Sdes load_scrnmap(optarg); 126177329Sdes break; 126277329Sdes case 'L': 126377329Sdes load_default_scrnmap(); 126477329Sdes break; 126577329Sdes case 'M': 126677329Sdes set_mouse_char(optarg); 126777329Sdes break; 126877329Sdes case 'm': 126977329Sdes set_mouse(optarg); 127077329Sdes break; 127177329Sdes case 'p': 1272102111Ssobomax dumpmod = DUMP_FMT_RAW; 127377329Sdes break; 127477329Sdes case 'P': 1275102111Ssobomax dumpmod = DUMP_FMT_TXT; 127677329Sdes break; 127777329Sdes case 'r': 1278146736Sdelphij get_reverse_colors(argc, argv, &optind); 127977329Sdes break; 128099705Sdd case 'S': 128199705Sdd set_lockswitch(optarg); 128299705Sdd break; 128377329Sdes case 's': 128477329Sdes set_console(optarg); 128577329Sdes break; 1286199174Sed case 'T': 1287238158Sache if (strcmp(optarg, "xterm") != 0 && 1288238158Sache strcmp(optarg, "cons25") != 0) 1289238158Sache usage(); 1290238158Sache termmode = optarg; 1291199174Sed break; 129277329Sdes case 't': 129377329Sdes set_screensaver_timeout(optarg); 129477329Sdes break; 129577329Sdes case 'x': 129677329Sdes hex = 1; 129777329Sdes break; 129877329Sdes default: 129977329Sdes usage(); 13002089Ssos } 1301146736Sdelphij 1302102111Ssobomax if (dumpmod != 0) 1303102111Ssobomax dump_screen(dumpmod, dumpopt); 1304120201Seivind reterr = video_mode(argc, argv, &optind); 1305146736Sdelphij get_normal_colors(argc, argv, &optind); 1306146736Sdelphij 13072089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 13082089Ssos test_frame(); 13092089Ssos optind++; 13102089Ssos } 1311146736Sdelphij 1312146736Sdelphij video_mode(argc, argv, &optind); 1313238158Sache if (termmode != NULL) 1314238158Sache set_terminal_mode(termmode); 1315146736Sdelphij 1316146736Sdelphij get_normal_colors(argc, argv, &optind); 1317146736Sdelphij 1318146736Sdelphij if (colors_changed || video_mode_changed) { 1319146736Sdelphij if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) { 1320146736Sdelphij if ((normal_back_color < 8) && (revers_back_color < 8)) { 1321146736Sdelphij set_colors(); 1322146736Sdelphij } else { 1323146736Sdelphij revert(); 1324146736Sdelphij errx(1, "bg color for text modes must be < 8"); 1325146736Sdelphij } 1326146736Sdelphij } else { 1327146736Sdelphij set_colors(); 1328146736Sdelphij } 1329146736Sdelphij } 1330146736Sdelphij 133130764Scharnier if ((optind != argc) || (argc == 1)) 13322089Ssos usage(); 1333120201Seivind return reterr; 13342089Ssos} 13352089Ssos 1336