Change <sys/queue.h> to <queue.h> (thanks Nate! I'm falling asleep
[unix-history] / usr.bin / syscons / syscons.c
CommitLineData
24380a1e
JH
1/*
2 * Copyright (c) 1993 Christoph M. Robitschko
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 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Christoph M. Robitschko
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software withough specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/file.h>
33#include <sys/ioctl.h>
e7eb8a29 34#include <machine/console.h>
24380a1e
JH
35#include <stdlib.h>
36#include <unistd.h>
37#include <stdio.h>
38#include <string.h>
39#include <sys/errno.h>
40
c9ef87c4
JH
41#include "syscons.h"
42
24380a1e
JH
43int verbose = 0;
44char *prgname;
45
46
47__BEGIN_DECLS
48int is_syscons __P((int));
49void screensaver __P((char *));
50void linemode __P((char *));
51void keyrate __P((char *));
52void keymap __P((char *));
bc9a1454 53void mapscr __P((char *));
24380a1e
JH
54void loadfont __P((char *, char *));
55void switchto __P((char *));
56void setfkey __P((char *, char *));
57void displayit __P((void));
58void usage __P((void));
59char *mkfullname __P((const char *, const char *, const char *));
60char *nextarg __P((int, char **, int *, int));
61__END_DECLS
62
63
64
65void
66main(argc, argv)
67int argc;
68char **argv;
69{
70extern char *optarg;
71extern int optind;
72int opt;
73
74
75 prgname = argv[0];
76 if (!is_syscons(0))
77 exit(1);
bc9a1454 78 while((opt = getopt(argc, argv, "s:m:r:k:f:t:F:S:vd")) != -1)
24380a1e
JH
79 switch(opt) {
80 case 's':
81 screensaver(optarg);
82 break;
83 case 'm':
84 linemode(optarg);
85 break;
86 case 'r':
87 keyrate(optarg);
88 break;
89 case 'k':
90 keymap(optarg);
91 break;
bc9a1454
JH
92 case 'S':
93 mapscr(optarg);
94 break;
24380a1e
JH
95 case 'f':
96 loadfont(optarg, nextarg(argc, argv, &optind, 'f'));
97 break;
98 case 't':
99 switchto(optarg);
100 break;
101 case 'F':
102 setfkey(optarg, nextarg(argc, argv, &optind, 'F'));
103 break;
104 case 'v':
105 verbose ++;
106 break;
107 case 'd':
108 displayit();
109 break;
110 default:
111 usage();
112 exit(1);
113 }
114 if ((optind != argc) || (argc == 1)) {
115 usage();
116 exit(1);
117 }
118 exit(0);
119}
120
121
122int
123is_syscons(fd)
124int fd;
125{
126vtmode_t mode;
127
128 /* Try to find out if we are running on a syscons VT */
af717426 129 if (ioctl(fd, VT_GETMODE, &mode) == 0)
24380a1e
JH
130 return(1);
131 if (errno == ENOTTY) {
132 printf("You must be running this from a syscons vty for it to work.\n\n");
133 printf("If you are currently using pccons (default) and wish to have virtual\n");
134 printf("consoles, then rebuild your kernel after replacing the line:\n\n");
135 printf("\tdevice pc0 at isa? port \042IO_KBD\042 tty irq 1 vector pcrint\n");
136 printf("\nwith:\n\n");
137 printf("\tdevice sc0 at isa? port \042IO_KBD\042 tty irq 1 vector scintr\n");
138 printf("\n(Then install the new kernel and reboot your system)\n");
139 }
140 else
141 perror("getting console state");
142 return(0);
143}
144
145
146
147void
148usage(void)
149{
150const char usagestr[] = {"\
151Usage: syscons -v (be verbose)\n\
152 -s {TIME|off} (set screensaver timeout to TIME seconds)\n\
153 -m {80x25|80x50} (set screen to 25 or 50 lines)\n\
154 -r DELAY.REPEAT (set keyboard delay & repeat rate)\n\
0037764b
JH
155 -r fast (set keyboard delay & repeat to fast)\n\
156 -r slow (set keyboard delay & repeat to slow)\n\
157 -r normal (set keyboard delay & repeat to normal)\n\
24380a1e
JH
158 -k MAPFILE (load keyboard map file)\n\
159 -f SIZE FILE (load font file of size 8, 14 or 16)\n\
160 -t SCRNUM (switch to specified VT)\n\
161 -F NUM STRING (set function key NUM to send STRING)\n\
bc9a1454 162 -S SCRNMAP (load screen map file)\n\
24380a1e
JH
163"};
164 fprintf(stderr, usagestr);
165}
166
167
168char *
169nextarg(ac, av, indp, oc)
170int ac;
171char **av;
172int *indp;
173int oc;
174{
175 if (*indp < ac)
176 return(av[(*indp)++]);
177 fprintf(stderr, "%s: option requires two arguments -- %c\n", av[0], oc);
178 usage();
179 exit(1);
180 return("");
181}
182
183
184
185char *
186mkfullname(s1, s2, s3)
187const char *s1, *s2, *s3;
188{
189static char *buf = NULL;
190static int bufl = 0;
191int f;
192
193
194 f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
195 if (f > bufl)
196 if (buf)
197 buf = (char *)realloc(buf, f);
198 else
199 buf = (char *)malloc(f);
200 if (!buf) {
201 bufl = 0;
202 return(NULL);
203 }
204
205 bufl = f;
206 strcpy(buf, s1);
207 strcat(buf, s2);
208 strcat(buf, s3);
209 return(buf);
210}
211
212
213void
214screensaver(opt)
215char *opt;
216{
217int nsec;
218char *s1;
219
220
221 if (!strcmp(opt, "off"))
222 nsec = 0;
223 else {
224 nsec = strtol(opt, &s1, 0);
225 if ((nsec < 0) || (*opt == '\0') || (*s1 != '\0')) {
226 fprintf(stderr, "argument to -s must be a positive integer.\n");
227 return;
228 }
229 }
230
231 if (ioctl(0, CONS_BLANKTIME, &nsec) == -1)
232 perror("setting screensaver period");
233}
234
235
236void
237linemode(opt)
238char *opt;
239{
240unsigned long req;
241
242 if (!strcmp(opt, "80x25"))
243 req = CONS_80x25TEXT;
244 else if (!strcmp(opt, "80x50"))
245 req = CONS_80x50TEXT;
246 else {
247 fprintf(stderr, "Unknown mode to -m: %s\n", opt);
248 return;
249 }
250
251 if (ioctl(0, req, NULL) == -1)
252 perror("Setting line mode");
253}
254
255
256void
257keyrate(opt)
258char *opt;
259{
260const int delays[] = {250, 500, 750, 1000};
261const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63,
262 68, 76, 84, 92, 100, 110, 118, 126,
263 136, 152, 168, 184, 200, 220, 236, 252,
264 272, 304, 336, 368, 400, 440, 472, 504};
265const int ndelays = (sizeof(delays) / sizeof(int));
266const int nrepeats = (sizeof(repeats) / sizeof(int));
267struct {
268 int rep:5;
269 int del:2;
270 int pad:1;
271 } rate;
272
273 if (!strcmp(opt, "slow"))
274 rate.del = 3, rate.rep = 31;
275 else if (!strcmp(opt, "normal"))
276 rate.del = 1, rate.rep = 15;
277 else if (!strcmp(opt, "fast"))
278 rate.del = rate.rep = 0;
279 else {
280 int n;
281 int delay, repeat;
282 char *v1;
283
284
285 delay = strtol(opt, &v1, 0);
286 if ((delay < 0) || (*v1 != '.'))
287 goto badopt;
288 opt = ++v1;
289 repeat = strtol(opt, &v1, 0);
290 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
291badopt:
292 fprintf(stderr, "argument to -r must be DELAY.REPEAT\n");
293 return;
294 }
295 for (n = 0; n < ndelays - 1; n++)
296 if (delay <= delays[n])
297 break;
298 rate.del = n;
299 for (n = 0; n < nrepeats - 1; n++)
300 if (repeat <= repeats[n])
301 break;
302 rate.rep = n;
303 }
304
305 if (verbose)
306 fprintf(stderr, "setting keyboard rate to %d.%d\n", delays[rate.del], repeats[rate.rep]);
307 if (ioctl(0, KDSETRAD, rate) == -1)
308 perror("setting keyboard rate");
309}
310
311
312void
313keymap(opt)
314char *opt;
315{
316char *mapfn;
317int mapfd;
318keymap_t map;
319int f;
320const char *prefix[] = {"", "", KEYMAP_PATH, NULL};
321const char *postfix[] = {"", ".map", ".map"};
322
323
324 mapfd = -1;
325 for (f = 0; prefix[f]; f++) {
326 mapfn = mkfullname(prefix[f], opt, postfix[f]);
327 mapfd = open(mapfn, O_RDONLY, 0);
328 if (verbose)
329 fprintf(stderr, "trying to open keymap file %s ... %s\n", mapfn, (mapfd==-1?"failed":"OK"));
330 if (mapfd >= 0)
331 break;
332 }
333 if (mapfd == -1) {
334 perror("Keymap file not found");
335 return;
336 }
337 if ((read(mapfd, &map, sizeof(map)) != sizeof(map)) ||
338 (read(mapfd, &map, 1) != 0)) {
339 fprintf(stderr, "\"%s\" is not in keymap format.\n", opt);
340 (void) close(mapfd);
341 return;
342 }
343 (void) close(mapfd);
344 if (ioctl(0, PIO_KEYMAP, &map) == -1)
345 perror("setting keyboard map");
346}
347
bc9a1454
JH
348void
349mapscr(opt)
350char *opt;
351{
352char *mapfn;
353int mapfd;
354scrmap_t map;
355int f;
356const char *prefix[] = {"", "", SCRNMAP_PATH, NULL};
357const char *postfix[] = {"", ".scr", ".scr"};
358
359
360 mapfd = -1;
361 for (f = 0; prefix[f]; f++) {
362 mapfn = mkfullname(prefix[f], opt, postfix[f]);
363 mapfd = open(mapfn, O_RDONLY, 0);
364 if (verbose)
365 fprintf(stderr, "trying to open scrnmap file %s ... %s\n", mapfn, (mapfd==-1?"failed":"OK"));
366 if (mapfd >= 0)
367 break;
368 }
369 if (mapfd == -1) {
370 perror("Scrnmap file not found");
371 return;
372 }
373 if ((read(mapfd, &map, sizeof(map)) != sizeof(map)) ||
374 (read(mapfd, &map, 1) != 0)) {
375 fprintf(stderr, "\"%s\" is not in scrnmap format.\n", opt);
376 (void) close(mapfd);
377 return;
378 }
379 (void) close(mapfd);
380 if (ioctl(0, PIO_SCRNMAP, &map) == -1)
381 perror("setting screen map");
382}
24380a1e
JH
383
384void
385loadfont(sizec, fname)
386char *sizec;
387char *fname;
388{
389char *fontfn;
390int fontfd;
391void *font;
392char *v1;
393int ind, f;
394const struct {
395 int fsize;
396 int msize;
397 unsigned long req;
398 } fontinfo[] = {
399 { 8, sizeof(fnt8_t), PIO_FONT8x8},
400 { 14, sizeof(fnt14_t), PIO_FONT8x14},
401 { 16, sizeof(fnt16_t), PIO_FONT8x16},
402 { 0 }};
403const char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL};
404const char *postfix[] = {"", ".fnt", "", ".fnt"};
405
406
407
408 f = strtol(sizec, &v1, 0);
409 for (ind = 0; fontinfo[ind].fsize; ind++)
410 if (fontinfo[ind].fsize == f)
411 break;
412 if ((fontinfo[ind].fsize == 0) || (*v1 != '\0')) {
413 fprintf(stderr, "%s is an unsupported font size.\n", sizec);
414 return;
415 }
416 font = (void *)malloc(fontinfo[ind].msize);
417 if (!font) {
418 fprintf(stderr, "loading font: Out of memory.\n");
419 return;
420 }
421
422 fontfd = -1; fontfn = "";
423 for (f = 0; prefix[f]; f++) {
424 fontfn = mkfullname(prefix[f], fname, postfix[f]);
425 fontfd = open(fontfn, O_RDONLY, 0);
426 if (verbose)
427 fprintf(stderr, "trying to open font file %s ... %s\n", fontfn, (fontfd==-1?"failed":"OK"));
428 if (fontfd >= 0)
429 break;
430 }
431 if (fontfd == -1) {
432 perror("Font file not found");
433 return;
434 }
435 if ((read(fontfd, font, fontinfo[ind].msize) != fontinfo[ind].msize) ||
436 (read(fontfd, font, 1) != 0)) {
437 fprintf(stderr, "\"%s\" is not a font with size %s.\n", fontfn, sizec);
438 (void) close(fontfd);
439 return;
440 }
441
442 if (ioctl(0, fontinfo[ind].req, font) == -1)
443 perror("Setting font");
444}
445
446
447void
448switchto(opt)
449char *opt;
450{
451int scrno;
452char *v1;
453
454
455 scrno = strtol(opt, &v1, 0);
456 if ((scrno < 1) || (scrno > 12) || (*v1 != '\0')) {
457 fprintf(stderr, "argument to -t must be between 1 and 12.\n");
458 return;
459 }
460 if (ioctl(0, VT_ACTIVATE, scrno) == -1)
461 perror("switching to new VT");
462}
463
464
465void
466setfkey(knumc, str)
467char *knumc;
468char *str;
469{
470fkeyarg_t fkey;
471char *v1;
bc9a1454 472long keynum;
24380a1e 473
bc9a1454
JH
474 keynum = strtol(knumc, &v1, 0);
475 if (keynum < 0 || keynum > 59 || *v1 != '\0') {
476 fprintf(stderr, "function key number must be between 0 and 59.\n");
24380a1e
JH
477 return;
478 }
bc9a1454 479 fkey.keynum = keynum;
24380a1e
JH
480 if ((fkey.flen = strlen(str)) > MAXFK) {
481 fprintf(stderr, "function key string too long (%d > %d)\n", fkey.flen, MAXFK);
482 return;
483 }
484 strcpy(fkey.keydef, str);
485 if (verbose)
486 fprintf(stderr, "setting F%d to \"%s\"\n", fkey.keynum, str);
487 fkey.keynum--;
488 if (ioctl(0, SETFKEY, &fkey) == -1)
489 perror("setting function key");
490}
491
492
493
494void
495displayit(void)
496{
497 if (verbose)
498 printf("absolutely ");
499 printf("nothing to display.\n");
500}