1 /*- 2 * Copyright (c) 1994-1996 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef lint 30 static const char rcsid[] = 31 "$FreeBSD$"; 32 #endif /* not lint */ 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <limits.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include <sys/fbio.h> 42 #include <sys/consio.h> 43 #include <sys/errno.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include "path.h" 47 #include "decode.h" 48 49 #define _VESA_800x600_DFL_COLS 80 50 #define _VESA_800x600_DFL_ROWS 25 51 #define _VESA_800x600_DFL_FNSZ 16 52 53 #define DUMP_RAW 0 54 #define DUMP_TXT 1 55 56 #define DUMP_FMT_REV 1 57 58 char legal_colors[16][16] = { 59 "black", "blue", "green", "cyan", 60 "red", "magenta", "brown", "white", 61 "grey", "lightblue", "lightgreen", "lightcyan", 62 "lightred", "lightmagenta", "yellow", "lightwhite" 63 }; 64 int hex = 0; 65 int number; 66 int vesa_cols = _VESA_800x600_DFL_COLS; 67 int vesa_rows = _VESA_800x600_DFL_ROWS; 68 char letter; 69 struct vid_info info; 70 71 72 static void 73 usage() 74 { 75 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 76 "usage: vidcontrol [-CdLPpx] [-b color] [-c appearance] [-f [size] file]", 77 " [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 78 " [-M char] [-m on | off] [-r foreground background]", 79 " [-S on | off] [-s number] [-t N | off] [mode]", 80 " [foreground [background]] [show]"); 81 exit(1); 82 } 83 84 char * 85 nextarg(int ac, char **av, int *indp, int oc, int strict) 86 { 87 if (*indp < ac) 88 return(av[(*indp)++]); 89 if (strict != 0) 90 errx(1, "option requires two arguments -- %c", oc); 91 return(NULL); 92 } 93 94 FILE * 95 openguess(char *a[], char *b[], char *c[], char *d[], char **name) 96 { 97 FILE *f; 98 int i, j, k, l; 99 100 for (i = 0; a[i] != NULL; i++) { 101 for (j = 0; b[j] != NULL; j++) { 102 for (k = 0; c[k] != NULL; k++) { 103 for (l = 0; d[l] != NULL; l++) { 104 asprintf(name, "%s%s%s%s", a[i], b[j], 105 c[k], d[l]); 106 f = fopen(*name, "r"); 107 if (f != NULL) 108 return (f); 109 free(*name); 110 } 111 } 112 } 113 } 114 return (NULL); 115 } 116 117 void 118 load_scrnmap(char *filename) 119 { 120 FILE *fd; 121 int size; 122 char *name; 123 scrmap_t scrnmap; 124 char *a[] = {"", SCRNMAP_PATH, NULL}; 125 char *b[] = {filename, NULL}; 126 char *c[] = {"", ".scm", NULL}; 127 char *d[] = {"", NULL}; 128 129 fd = openguess(a, b, c, d, &name); 130 if (fd == NULL) { 131 warn("screenmap file not found"); 132 return; 133 } 134 size = sizeof(scrnmap); 135 if (decode(fd, (char *)&scrnmap, size) != size) { 136 rewind(fd); 137 if (fread(&scrnmap, 1, size, fd) != size) { 138 warnx("bad screenmap file"); 139 fclose(fd); 140 return; 141 } 142 } 143 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 144 warn("can't load screenmap"); 145 fclose(fd); 146 } 147 148 void 149 load_default_scrnmap() 150 { 151 scrmap_t scrnmap; 152 int i; 153 154 for (i=0; i<256; i++) 155 *((char*)&scrnmap + i) = i; 156 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 157 warn("can't load default screenmap"); 158 } 159 160 void 161 print_scrnmap() 162 { 163 unsigned char map[256]; 164 int i; 165 166 if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 167 warn("getting screenmap"); 168 return; 169 } 170 for (i=0; i<sizeof(map); i++) { 171 if (i > 0 && i % 16 == 0) 172 fprintf(stdout, "\n"); 173 if (hex) 174 fprintf(stdout, " %02x", map[i]); 175 else 176 fprintf(stdout, " %03d", map[i]); 177 } 178 fprintf(stdout, "\n"); 179 180 } 181 182 int 183 fsize(FILE *file) 184 { 185 struct stat sb; 186 187 if (fstat(fileno(file), &sb) == 0) 188 return sb.st_size; 189 else 190 return -1; 191 } 192 193 #define DATASIZE(x) ((x).w * (x).h * 256 / 8) 194 195 void 196 load_font(char *type, char *filename) 197 { 198 FILE *fd; 199 int h, i, size, w; 200 unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 201 char *name, *fontmap, size_sufx[6]; 202 char *a[] = {"", FONT_PATH, NULL}; 203 char *b[] = {filename, NULL}; 204 char *c[] = {"", size_sufx, NULL}; 205 char *d[] = {"", ".fnt", NULL}; 206 vid_info_t info; 207 208 struct sizeinfo { 209 int w; 210 int h; 211 unsigned long io; 212 } sizes[] = {{8, 16, PIO_FONT8x16}, 213 {8, 14, PIO_FONT8x14}, 214 {8, 8, PIO_FONT8x8}, 215 {0, 0, 0}}; 216 217 info.size = sizeof(info); 218 if (ioctl(0, CONS_GETINFO, &info) == -1) { 219 warn("failed to obtain current video mode parameters"); 220 return; 221 } 222 snprintf(size_sufx, sizeof(size_sufx), "-8x%d", info.font_size); 223 fd = openguess(a, b, c, d, &name); 224 if (fd == NULL) { 225 warn("%s: can't load font file", filename); 226 return; 227 } 228 if (type != NULL) { 229 size = 0; 230 if (sscanf(type, "%dx%d", &w, &h) == 2) 231 for (i = 0; sizes[i].w != 0; i++) 232 if (sizes[i].w == w && sizes[i].h == h) { 233 size = DATASIZE(sizes[i]); 234 io = sizes[i].io; 235 } 236 237 if (size == 0) { 238 warnx("%s: bad font size specification", type); 239 fclose(fd); 240 return; 241 } 242 } else { 243 /* Apply heuristics */ 244 int j; 245 int dsize[2]; 246 247 size = DATASIZE(sizes[0]); 248 fontmap = (char*) malloc(size); 249 dsize[0] = decode(fd, fontmap, size); 250 dsize[1] = fsize(fd); 251 free(fontmap); 252 253 size = 0; 254 for (j = 0; j < 2; j++) 255 for (i = 0; sizes[i].w != 0; i++) 256 if (DATASIZE(sizes[i]) == dsize[j]) { 257 size = dsize[j]; 258 io = sizes[i].io; 259 j = 2; /* XXX */ 260 break; 261 } 262 263 if (size == 0) { 264 warnx("%s: can't guess font size", filename); 265 fclose(fd); 266 return; 267 } 268 rewind(fd); 269 } 270 271 fontmap = (char*) malloc(size); 272 if (decode(fd, fontmap, size) != size) { 273 rewind(fd); 274 if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) { 275 warnx("%s: bad font file", filename); 276 fclose(fd); 277 free(fontmap); 278 return; 279 } 280 } 281 if (ioctl(0, io, fontmap) < 0) 282 warn("can't load font"); 283 fclose(fd); 284 free(fontmap); 285 } 286 287 void 288 set_screensaver_timeout(char *arg) 289 { 290 int nsec; 291 292 if (!strcmp(arg, "off")) 293 nsec = 0; 294 else { 295 nsec = atoi(arg); 296 if ((*arg == '\0') || (nsec < 1)) { 297 warnx("argument must be a positive number"); 298 return; 299 } 300 } 301 if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 302 warn("setting screensaver period"); 303 } 304 305 void 306 set_cursor_type(char *appearence) 307 { 308 int type; 309 310 if (!strcmp(appearence, "normal")) 311 type = 0; 312 else if (!strcmp(appearence, "blink")) 313 type = 1; 314 else if (!strcmp(appearence, "destructive")) 315 type = 3; 316 else { 317 warnx("argument to -c must be normal, blink or destructive"); 318 return; 319 } 320 ioctl(0, CONS_CURSORTYPE, &type); 321 } 322 323 void 324 video_mode(int argc, char **argv, int *index) 325 { 326 static struct { 327 char *name; 328 unsigned long mode; 329 } modes[] = { 330 { "80x25", SW_TEXT_80x25 }, 331 { "80x30", SW_TEXT_80x30 }, 332 { "80x43", SW_TEXT_80x43 }, 333 { "80x50", SW_TEXT_80x50 }, 334 { "80x60", SW_TEXT_80x60 }, 335 { "132x25", SW_TEXT_132x25 }, 336 { "132x30", SW_TEXT_132x30 }, 337 { "132x43", SW_TEXT_132x43 }, 338 { "132x50", SW_TEXT_132x50 }, 339 { "132x60", SW_TEXT_132x60 }, 340 { "VGA_40x25", SW_VGA_C40x25 }, 341 { "VGA_80x25", SW_VGA_C80x25 }, 342 { "VGA_80x30", SW_VGA_C80x30 }, 343 { "VGA_80x50", SW_VGA_C80x50 }, 344 { "VGA_80x60", SW_VGA_C80x60 }, 345 #ifdef SW_VGA_C90x25 346 { "VGA_90x25", SW_VGA_C90x25 }, 347 { "VGA_90x30", SW_VGA_C90x30 }, 348 { "VGA_90x43", SW_VGA_C90x43 }, 349 { "VGA_90x50", SW_VGA_C90x50 }, 350 { "VGA_90x60", SW_VGA_C90x60 }, 351 #endif 352 { "VGA_320x200", SW_VGA_CG320 }, 353 { "EGA_80x25", SW_ENH_C80x25 }, 354 { "EGA_80x43", SW_ENH_C80x43 }, 355 { "VESA_132x25", SW_VESA_C132x25 }, 356 { "VESA_132x43", SW_VESA_C132x43 }, 357 { "VESA_132x50", SW_VESA_C132x50 }, 358 { "VESA_132x60", SW_VESA_C132x60 }, 359 { "VESA_800x600", SW_VESA_800x600 }, 360 { NULL }, 361 }; 362 unsigned long mode = 0; 363 int cur_mode; 364 int ioerr; 365 int size[3]; 366 int i; 367 368 if (ioctl(0, CONS_GET, &cur_mode) < 0) 369 err(1, "cannot get the current video mode"); 370 if (*index < argc) { 371 for (i = 0; modes[i].name != NULL; ++i) { 372 if (!strcmp(argv[*index], modes[i].name)) { 373 mode = modes[i].mode; 374 break; 375 } 376 } 377 if (modes[i].name == NULL) 378 return; 379 if (ioctl(0, mode, NULL) < 0) 380 warn("cannot set videomode"); 381 if (mode == SW_VESA_800x600) { 382 /* columns */ 383 if ((vesa_cols * 8 > 800) || (vesa_cols <= 0)) { 384 warnx("incorrect number of columns: %d", 385 vesa_cols); 386 size[0] = _VESA_800x600_DFL_COLS; 387 } else { 388 size[0] = vesa_cols; 389 } 390 /* rows */ 391 if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) || 392 (vesa_rows <=0)) { 393 warnx("incorrect number of rows: %d", 394 vesa_rows); 395 size[1] = _VESA_800x600_DFL_ROWS; 396 } else { 397 size[1] = vesa_rows; 398 } 399 /* font size */ 400 size[2] = _VESA_800x600_DFL_FNSZ; 401 if (ioctl(0, KDRASTER, size)) { 402 ioerr = errno; 403 if (cur_mode >= M_VESA_BASE) 404 ioctl(0, 405 _IO('V', cur_mode - M_VESA_BASE), 406 NULL); 407 else 408 ioctl(0, _IO('S', cur_mode), NULL); 409 warnc(ioerr, "cannot activate raster display"); 410 } 411 } 412 (*index)++; 413 } 414 return; 415 } 416 417 int 418 get_color_number(char *color) 419 { 420 int i; 421 422 for (i=0; i<16; i++) 423 if (!strcmp(color, legal_colors[i])) 424 return i; 425 return -1; 426 } 427 428 void 429 set_normal_colors(int argc, char **argv, int *index) 430 { 431 int color; 432 433 if (*index < argc && (color = get_color_number(argv[*index])) != -1) { 434 (*index)++; 435 fprintf(stderr, "[=%dF", color); 436 if (*index < argc 437 && (color = get_color_number(argv[*index])) != -1 438 && color < 8) { 439 (*index)++; 440 fprintf(stderr, "[=%dG", color); 441 } 442 } 443 } 444 445 void 446 set_reverse_colors(int argc, char **argv, int *index) 447 { 448 int color; 449 450 if ((color = get_color_number(argv[*(index)-1])) != -1) { 451 fprintf(stderr, "[=%dH", color); 452 if (*index < argc 453 && (color = get_color_number(argv[*index])) != -1 454 && color < 8) { 455 (*index)++; 456 fprintf(stderr, "[=%dI", color); 457 } 458 } 459 } 460 461 void 462 set_console(char *arg) 463 { 464 int n; 465 466 if( !arg || strspn(arg,"0123456789") != strlen(arg)) { 467 warnx("bad console number"); 468 return; 469 } 470 471 n = atoi(arg); 472 if (n < 1 || n > 16) { 473 warnx("console number out of range"); 474 } else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) 475 warn("ioctl(VT_ACTIVATE)"); 476 } 477 478 void 479 set_border_color(char *arg) 480 { 481 int color; 482 483 if ((color = get_color_number(arg)) != -1) { 484 fprintf(stderr, "[=%dA", color); 485 } 486 else 487 usage(); 488 } 489 490 void 491 set_mouse_char(char *arg) 492 { 493 struct mouse_info mouse; 494 long l; 495 496 l = strtol(arg, NULL, 0); 497 if ((l < 0) || (l > UCHAR_MAX - 3)) { 498 warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 499 return; 500 } 501 mouse.operation = MOUSE_MOUSECHAR; 502 mouse.u.mouse_char = (int)l; 503 ioctl(0, CONS_MOUSECTL, &mouse); 504 } 505 506 void 507 set_mouse(char *arg) 508 { 509 struct mouse_info mouse; 510 511 if (!strcmp(arg, "on")) 512 mouse.operation = MOUSE_SHOW; 513 else if (!strcmp(arg, "off")) 514 mouse.operation = MOUSE_HIDE; 515 else { 516 warnx("argument to -m must be either on or off"); 517 return; 518 } 519 ioctl(0, CONS_MOUSECTL, &mouse); 520 } 521 522 void 523 set_lockswitch(char *arg) 524 { 525 int data; 526 527 if (!strcmp(arg, "off")) 528 data = 0x01; 529 else if (!strcmp(arg, "on")) 530 data = 0x02; 531 else { 532 warnx("argument to -S must be either on or off"); 533 return; 534 } 535 if (ioctl(0, VT_LOCKSWITCH, &data) == -1) 536 warn("ioctl(VT_LOCKSWITCH)"); 537 } 538 539 static char 540 *adapter_name(int type) 541 { 542 static struct { 543 int type; 544 char *name; 545 } names[] = { 546 { KD_MONO, "MDA" }, 547 { KD_HERCULES, "Hercules" }, 548 { KD_CGA, "CGA" }, 549 { KD_EGA, "EGA" }, 550 { KD_VGA, "VGA" }, 551 { KD_PC98, "PC-98xx" }, 552 { KD_TGA, "TGA" }, 553 { -1, "Unknown" }, 554 }; 555 int i; 556 557 for (i = 0; names[i].type != -1; ++i) 558 if (names[i].type == type) 559 break; 560 return names[i].name; 561 } 562 563 void 564 show_adapter_info(void) 565 { 566 struct video_adapter_info ad; 567 568 ad.va_index = 0; 569 if (ioctl(0, CONS_ADPINFO, &ad)) { 570 warn("failed to obtain adapter information"); 571 return; 572 } 573 574 printf("fb%d:\n", ad.va_index); 575 printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 576 (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 577 (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 578 adapter_name(ad.va_type), ad.va_type, ad.va_flags); 579 printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 580 ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 581 printf(" frame buffer window:0x%x, buffer size:0x%x\n", 582 ad.va_window, ad.va_buffer_size); 583 printf(" window size:0x%x, origin:0x%x\n", 584 ad.va_window_size, ad.va_window_orig); 585 printf(" display start address (%d, %d), scan line width:%d\n", 586 ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 587 printf(" reserved:0x%x\n", ad.va_unused0); 588 } 589 590 void 591 show_mode_info(void) 592 { 593 struct video_info info; 594 char buf[80]; 595 int mode; 596 int c; 597 598 printf(" mode# flags type size " 599 "font window linear buffer\n"); 600 printf("---------------------------------------" 601 "---------------------------------------\n"); 602 for (mode = 0; mode < M_VESA_MODE_MAX; ++mode) { 603 info.vi_mode = mode; 604 if (ioctl(0, CONS_MODEINFO, &info)) 605 continue; 606 if (info.vi_mode != mode) 607 continue; 608 609 printf("%3d (0x%03x)", mode, mode); 610 printf(" 0x%08x", info.vi_flags); 611 if (info.vi_flags & V_INFO_GRAPHICS) { 612 c = 'G'; 613 snprintf(buf, sizeof(buf), "%dx%dx%d %d", 614 info.vi_width, info.vi_height, 615 info.vi_depth, info.vi_planes); 616 } else { 617 c = 'T'; 618 snprintf(buf, sizeof(buf), "%dx%d", 619 info.vi_width, info.vi_height); 620 } 621 printf(" %c %-15s", c, buf); 622 snprintf(buf, sizeof(buf), "%dx%d", 623 info.vi_cwidth, info.vi_cheight); 624 printf(" %-5s", buf); 625 printf(" 0x%05x %2dk %2dk", 626 info.vi_window, (int)info.vi_window_size/1024, 627 (int)info.vi_window_gran/1024); 628 printf(" 0x%08x %dk\n", 629 info.vi_buffer, (int)info.vi_buffer_size/1024); 630 } 631 } 632 633 void 634 show_info(char *arg) 635 { 636 if (!strcmp(arg, "adapter")) 637 show_adapter_info(); 638 else if (!strcmp(arg, "mode")) 639 show_mode_info(); 640 else { 641 warnx("argument to -i must be either adapter or mode"); 642 return; 643 } 644 } 645 646 void 647 test_frame() 648 { 649 int i; 650 651 fprintf(stdout, "[=0G\n\n"); 652 for (i=0; i<8; i++) { 653 fprintf(stdout, "[=15F[=0G %2d [=%dF%-16s" 654 "[=15F[=0G %2d [=%dF%-16s " 655 "[=15F %2d [=%dGBACKGROUND[=0G\n", 656 i, i, legal_colors[i], i+8, i+8, 657 legal_colors[i+8], i, i); 658 } 659 fprintf(stdout, "[=%dF[=%dG[=%dH[=%dI\n", 660 info.mv_norm.fore, info.mv_norm.back, 661 info.mv_rev.fore, info.mv_rev.back); 662 } 663 664 /* 665 * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 666 * ioctl, and writes the results to stdout either in the special 667 * binary format (see manual page for details), or in the plain 668 * text format. 669 */ 670 void 671 dump_screen(int mode) 672 { 673 scrshot_t shot; 674 vid_info_t info; 675 676 info.size = sizeof(info); 677 if (ioctl(0, CONS_GETINFO, &info) == -1) { 678 warn("failed to obtain current video mode parameters"); 679 return; 680 } 681 682 shot.buf = alloca(info.mv_csz * info.mv_rsz * sizeof(u_int16_t)); 683 if (shot.buf == NULL) { 684 warn("failed to allocate memory for dump"); 685 return; 686 } 687 688 shot.xsize = info.mv_csz; 689 shot.ysize = info.mv_rsz; 690 if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 691 warn("failed to get dump of the screen"); 692 return; 693 } 694 695 if (mode == DUMP_RAW) { 696 printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 697 shot.xsize, shot.ysize); 698 fflush(stdout); 699 700 (void)write(STDOUT_FILENO, shot.buf, 701 shot.xsize * shot.ysize * sizeof(u_int16_t)); 702 } else { 703 char *line; 704 int x, y; 705 u_int16_t ch; 706 707 line = alloca(shot.xsize + 1); 708 if (line == NULL) { 709 warn("failed to allocate memory for line buffer"); 710 return; 711 } 712 713 for (y = 0; y < shot.ysize; y++) { 714 for (x = 0; x < shot.xsize; x++) { 715 ch = shot.buf[x + (y * shot.xsize)]; 716 ch &= 0xff; 717 if (isprint(ch) == 0) 718 ch = ' '; 719 line[x] = (char)ch; 720 } 721 722 /* Trim trailing spaces */ 723 do { 724 line[x--] = '\0'; 725 } while (line[x] == ' ' && x != 0); 726 727 puts(line); 728 } 729 fflush(stdout); 730 } 731 732 return; 733 } 734 735 void 736 set_history(char *opt) 737 { 738 int size; 739 740 size = atoi(opt); 741 if ((*opt == '\0') || size < 0) { 742 warnx("argument must be a positive number"); 743 return; 744 } 745 if (ioctl(0, CONS_HISTORY, &size) == -1) 746 warn("setting history buffer size"); 747 } 748 749 void 750 clear_history() 751 { 752 753 if (ioctl(0, CONS_CLRHIST) == -1) 754 warn("clear history buffer"); 755 } 756 757 int 758 main(int argc, char **argv) 759 { 760 char *font, *type; 761 int opt; 762 763 764 info.size = sizeof(info); 765 if (argc == 1) 766 usage(); 767 /* Not reached */ 768 if (ioctl(0, CONS_GETINFO, &info) < 0) 769 err(1, "must be on a virtual console"); 770 while((opt = getopt(argc, argv, "b:Cc:df:g:h:i:l:LM:m:pPr:S:s:t:x")) != -1) 771 switch(opt) { 772 case 'b': 773 set_border_color(optarg); 774 break; 775 case 'C': 776 clear_history(); 777 break; 778 case 'c': 779 set_cursor_type(optarg); 780 break; 781 case 'd': 782 print_scrnmap(); 783 break; 784 case 'f': 785 type = optarg; 786 font = nextarg(argc, argv, &optind, 'f', 0); 787 if (font == NULL) { 788 type = NULL; 789 font = optarg; 790 } 791 load_font(type, font); 792 break; 793 case 'g': 794 if (sscanf(optarg, "%dx%d", &vesa_cols, 795 &vesa_rows) != 2) { 796 warnx("incorrect geometry: %s", optarg); 797 usage(); 798 } 799 break; 800 case 'h': 801 set_history(optarg); 802 break; 803 case 'i': 804 show_info(optarg); 805 break; 806 case 'l': 807 load_scrnmap(optarg); 808 break; 809 case 'L': 810 load_default_scrnmap(); 811 break; 812 case 'M': 813 set_mouse_char(optarg); 814 break; 815 case 'm': 816 set_mouse(optarg); 817 break; 818 case 'p': 819 dump_screen(DUMP_RAW); 820 break; 821 case 'P': 822 dump_screen(DUMP_TXT); 823 break; 824 case 'r': 825 set_reverse_colors(argc, argv, &optind); 826 break; 827 case 'S': 828 set_lockswitch(optarg); 829 break; 830 case 's': 831 set_console(optarg); 832 break; 833 case 't': 834 set_screensaver_timeout(optarg); 835 break; 836 case 'x': 837 hex = 1; 838 break; 839 default: 840 usage(); 841 } 842 video_mode(argc, argv, &optind); 843 set_normal_colors(argc, argv, &optind); 844 if (optind < argc && !strcmp(argv[optind], "show")) { 845 test_frame(); 846 optind++; 847 } 848 if ((optind != argc) || (argc == 1)) 849 usage(); 850 return 0; 851 } 852 853