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