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