This commit was generated by cvs2svn to track changes on a CVS vendor
[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 *));
13f3017d 50void screensavertype __P((char *));
24380a1e
JH
51void linemode __P((char *));
52void keyrate __P((char *));
53void keymap __P((char *));
bc9a1454 54void mapscr __P((char *));
24380a1e
JH
55void loadfont __P((char *, char *));
56void switchto __P((char *));
57void setfkey __P((char *, char *));
58void displayit __P((void));
59void usage __P((void));
60char *mkfullname __P((const char *, const char *, const char *));
61char *nextarg __P((int, char **, int *, int));
62__END_DECLS
63
64
65
66void
67main(argc, argv)
68int argc;
69char **argv;
70{
71extern char *optarg;
72extern int optind;
73int opt;
74
75
76 prgname = argv[0];
77 if (!is_syscons(0))
78 exit(1);
aa690f4f 79 while((opt = getopt(argc, argv, "s:S:m:r:k:f:t:F:V:vd")) != -1)
24380a1e
JH
80 switch(opt) {
81 case 's':
82 screensaver(optarg);
83 break;
aa690f4f 84 case 'V':
13f3017d
CR
85 screensavertype(optarg);
86 break;
24380a1e
JH
87 case 'm':
88 linemode(optarg);
89 break;
90 case 'r':
91 keyrate(optarg);
92 break;
93 case 'k':
94 keymap(optarg);
95 break;
aa690f4f 96 case 'S':
bc9a1454
JH
97 mapscr(optarg);
98 break;
24380a1e
JH
99 case 'f':
100 loadfont(optarg, nextarg(argc, argv, &optind, 'f'));
101 break;
102 case 't':
103 switchto(optarg);
104 break;
105 case 'F':
106 setfkey(optarg, nextarg(argc, argv, &optind, 'F'));
107 break;
108 case 'v':
109 verbose ++;
110 break;
111 case 'd':
112 displayit();
113 break;
114 default:
115 usage();
116 exit(1);
117 }
118 if ((optind != argc) || (argc == 1)) {
119 usage();
120 exit(1);
121 }
122 exit(0);
123}
124
125
126int
127is_syscons(fd)
128int fd;
129{
130vtmode_t mode;
131
132 /* Try to find out if we are running on a syscons VT */
af717426 133 if (ioctl(fd, VT_GETMODE, &mode) == 0)
24380a1e
JH
134 return(1);
135 if (errno == ENOTTY) {
136 printf("You must be running this from a syscons vty for it to work.\n\n");
137 printf("If you are currently using pccons (default) and wish to have virtual\n");
138 printf("consoles, then rebuild your kernel after replacing the line:\n\n");
139 printf("\tdevice pc0 at isa? port \042IO_KBD\042 tty irq 1 vector pcrint\n");
140 printf("\nwith:\n\n");
141 printf("\tdevice sc0 at isa? port \042IO_KBD\042 tty irq 1 vector scintr\n");
142 printf("\n(Then install the new kernel and reboot your system)\n");
143 }
144 else
145 perror("getting console state");
146 return(0);
147}
148
149
150
151void
152usage(void)
153{
154const char usagestr[] = {"\
155Usage: syscons -v (be verbose)\n\
156 -s {TIME|off} (set screensaver timeout to TIME seconds)\n\
aa690f4f 157 -V {NAME|list} (set screensaver type or list available types\n\
24380a1e
JH
158 -m {80x25|80x50} (set screen to 25 or 50 lines)\n\
159 -r DELAY.REPEAT (set keyboard delay & repeat rate)\n\
0037764b
JH
160 -r fast (set keyboard delay & repeat to fast)\n\
161 -r slow (set keyboard delay & repeat to slow)\n\
162 -r normal (set keyboard delay & repeat to normal)\n\
24380a1e
JH
163 -k MAPFILE (load keyboard map file)\n\
164 -f SIZE FILE (load font file of size 8, 14 or 16)\n\
165 -t SCRNUM (switch to specified VT)\n\
166 -F NUM STRING (set function key NUM to send STRING)\n\
aa690f4f 167 -S SCRNMAP (load screen map file)\n\
24380a1e
JH
168"};
169 fprintf(stderr, usagestr);
170}
171
172
173char *
174nextarg(ac, av, indp, oc)
175int ac;
176char **av;
177int *indp;
178int oc;
179{
180 if (*indp < ac)
181 return(av[(*indp)++]);
182 fprintf(stderr, "%s: option requires two arguments -- %c\n", av[0], oc);
183 usage();
184 exit(1);
185 return("");
186}
187
188
189
190char *
191mkfullname(s1, s2, s3)
192const char *s1, *s2, *s3;
193{
194static char *buf = NULL;
195static int bufl = 0;
196int f;
197
198
199 f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
200 if (f > bufl)
201 if (buf)
202 buf = (char *)realloc(buf, f);
203 else
204 buf = (char *)malloc(f);
205 if (!buf) {
206 bufl = 0;
207 return(NULL);
208 }
209
210 bufl = f;
211 strcpy(buf, s1);
212 strcat(buf, s2);
213 strcat(buf, s3);
214 return(buf);
215}
216
217
218void
219screensaver(opt)
220char *opt;
221{
222int nsec;
223char *s1;
224
225
226 if (!strcmp(opt, "off"))
227 nsec = 0;
228 else {
229 nsec = strtol(opt, &s1, 0);
230 if ((nsec < 0) || (*opt == '\0') || (*s1 != '\0')) {
231 fprintf(stderr, "argument to -s must be a positive integer.\n");
232 return;
233 }
234 }
235
236 if (ioctl(0, CONS_BLANKTIME, &nsec) == -1)
237 perror("setting screensaver period");
238}
239
240
13f3017d
CR
241void
242screensavertype(opt)
243char *opt;
244{
245ssaver_t shaver;
246int i, e;
247
248
249 if (!strcmp(opt, "list")) {
250 i = 0;
251 printf("available screen saver types:\n");
252 do {
253 shaver.num = i;
254 e = ioctl(0, CONS_GSAVER, &shaver);
255 i ++;
256 if (e == 0)
257 printf("\t%d\t%s\n", shaver.num, shaver.name);
258 } while (e == 0);
259 if (e == -1 && errno != EIO)
260 perror("getting screensaver info");
261 } else {
262 i = 0;
263 do {
264 shaver.num = i;
265 e = ioctl(0, CONS_GSAVER, &shaver);
266 i ++;
267 if (e == 0 && !strcmp(opt, shaver.name)) {
268 if (ioctl(0, CONS_SSAVER, &shaver) == -1)
269 perror("setting screensaver type");
270 return;
271 }
272 } while (e == 0);
273 if (e == -1 && errno != EIO)
274 perror("getting screensaver info");
aa6046c2
CR
275 else
276 fprintf(stderr, "%s: No such screensaver\n", opt);
13f3017d
CR
277 }
278}
279
280
24380a1e
JH
281void
282linemode(opt)
283char *opt;
284{
285unsigned long req;
286
287 if (!strcmp(opt, "80x25"))
288 req = CONS_80x25TEXT;
289 else if (!strcmp(opt, "80x50"))
290 req = CONS_80x50TEXT;
291 else {
292 fprintf(stderr, "Unknown mode to -m: %s\n", opt);
293 return;
294 }
295
296 if (ioctl(0, req, NULL) == -1)
297 perror("Setting line mode");
298}
299
300
301void
302keyrate(opt)
303char *opt;
304{
305const int delays[] = {250, 500, 750, 1000};
306const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63,
307 68, 76, 84, 92, 100, 110, 118, 126,
308 136, 152, 168, 184, 200, 220, 236, 252,
309 272, 304, 336, 368, 400, 440, 472, 504};
310const int ndelays = (sizeof(delays) / sizeof(int));
311const int nrepeats = (sizeof(repeats) / sizeof(int));
312struct {
313 int rep:5;
314 int del:2;
315 int pad:1;
316 } rate;
317
318 if (!strcmp(opt, "slow"))
319 rate.del = 3, rate.rep = 31;
320 else if (!strcmp(opt, "normal"))
321 rate.del = 1, rate.rep = 15;
322 else if (!strcmp(opt, "fast"))
323 rate.del = rate.rep = 0;
324 else {
325 int n;
326 int delay, repeat;
327 char *v1;
328
329
330 delay = strtol(opt, &v1, 0);
331 if ((delay < 0) || (*v1 != '.'))
332 goto badopt;
333 opt = ++v1;
334 repeat = strtol(opt, &v1, 0);
335 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
336badopt:
337 fprintf(stderr, "argument to -r must be DELAY.REPEAT\n");
338 return;
339 }
340 for (n = 0; n < ndelays - 1; n++)
341 if (delay <= delays[n])
342 break;
343 rate.del = n;
344 for (n = 0; n < nrepeats - 1; n++)
345 if (repeat <= repeats[n])
346 break;
347 rate.rep = n;
348 }
349
350 if (verbose)
351 fprintf(stderr, "setting keyboard rate to %d.%d\n", delays[rate.del], repeats[rate.rep]);
352 if (ioctl(0, KDSETRAD, rate) == -1)
353 perror("setting keyboard rate");
354}
355
356
357void
358keymap(opt)
359char *opt;
360{
361char *mapfn;
362int mapfd;
363keymap_t map;
364int f;
365const char *prefix[] = {"", "", KEYMAP_PATH, NULL};
366const char *postfix[] = {"", ".map", ".map"};
367
368
369 mapfd = -1;
370 for (f = 0; prefix[f]; f++) {
371 mapfn = mkfullname(prefix[f], opt, postfix[f]);
372 mapfd = open(mapfn, O_RDONLY, 0);
373 if (verbose)
374 fprintf(stderr, "trying to open keymap file %s ... %s\n", mapfn, (mapfd==-1?"failed":"OK"));
375 if (mapfd >= 0)
376 break;
377 }
378 if (mapfd == -1) {
379 perror("Keymap file not found");
380 return;
381 }
382 if ((read(mapfd, &map, sizeof(map)) != sizeof(map)) ||
383 (read(mapfd, &map, 1) != 0)) {
384 fprintf(stderr, "\"%s\" is not in keymap format.\n", opt);
385 (void) close(mapfd);
386 return;
387 }
388 (void) close(mapfd);
389 if (ioctl(0, PIO_KEYMAP, &map) == -1)
390 perror("setting keyboard map");
391}
392
bc9a1454
JH
393void
394mapscr(opt)
395char *opt;
396{
397char *mapfn;
398int mapfd;
399scrmap_t map;
400int f;
401const char *prefix[] = {"", "", SCRNMAP_PATH, NULL};
402const char *postfix[] = {"", ".scr", ".scr"};
403
404
405 mapfd = -1;
406 for (f = 0; prefix[f]; f++) {
407 mapfn = mkfullname(prefix[f], opt, postfix[f]);
408 mapfd = open(mapfn, O_RDONLY, 0);
409 if (verbose)
410 fprintf(stderr, "trying to open scrnmap file %s ... %s\n", mapfn, (mapfd==-1?"failed":"OK"));
411 if (mapfd >= 0)
412 break;
413 }
414 if (mapfd == -1) {
415 perror("Scrnmap file not found");
416 return;
417 }
418 if ((read(mapfd, &map, sizeof(map)) != sizeof(map)) ||
419 (read(mapfd, &map, 1) != 0)) {
420 fprintf(stderr, "\"%s\" is not in scrnmap format.\n", opt);
421 (void) close(mapfd);
422 return;
423 }
424 (void) close(mapfd);
425 if (ioctl(0, PIO_SCRNMAP, &map) == -1)
426 perror("setting screen map");
427}
24380a1e
JH
428
429void
430loadfont(sizec, fname)
431char *sizec;
432char *fname;
433{
434char *fontfn;
435int fontfd;
436void *font;
437char *v1;
438int ind, f;
439const struct {
440 int fsize;
441 int msize;
442 unsigned long req;
443 } fontinfo[] = {
444 { 8, sizeof(fnt8_t), PIO_FONT8x8},
445 { 14, sizeof(fnt14_t), PIO_FONT8x14},
446 { 16, sizeof(fnt16_t), PIO_FONT8x16},
447 { 0 }};
448const char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL};
449const char *postfix[] = {"", ".fnt", "", ".fnt"};
450
451
452
453 f = strtol(sizec, &v1, 0);
454 for (ind = 0; fontinfo[ind].fsize; ind++)
455 if (fontinfo[ind].fsize == f)
456 break;
457 if ((fontinfo[ind].fsize == 0) || (*v1 != '\0')) {
458 fprintf(stderr, "%s is an unsupported font size.\n", sizec);
459 return;
460 }
461 font = (void *)malloc(fontinfo[ind].msize);
462 if (!font) {
463 fprintf(stderr, "loading font: Out of memory.\n");
464 return;
465 }
466
467 fontfd = -1; fontfn = "";
468 for (f = 0; prefix[f]; f++) {
469 fontfn = mkfullname(prefix[f], fname, postfix[f]);
470 fontfd = open(fontfn, O_RDONLY, 0);
471 if (verbose)
472 fprintf(stderr, "trying to open font file %s ... %s\n", fontfn, (fontfd==-1?"failed":"OK"));
473 if (fontfd >= 0)
474 break;
475 }
476 if (fontfd == -1) {
477 perror("Font file not found");
478 return;
479 }
480 if ((read(fontfd, font, fontinfo[ind].msize) != fontinfo[ind].msize) ||
481 (read(fontfd, font, 1) != 0)) {
482 fprintf(stderr, "\"%s\" is not a font with size %s.\n", fontfn, sizec);
483 (void) close(fontfd);
484 return;
485 }
486
487 if (ioctl(0, fontinfo[ind].req, font) == -1)
488 perror("Setting font");
489}
490
491
492void
493switchto(opt)
494char *opt;
495{
496int scrno;
497char *v1;
498
499
500 scrno = strtol(opt, &v1, 0);
501 if ((scrno < 1) || (scrno > 12) || (*v1 != '\0')) {
502 fprintf(stderr, "argument to -t must be between 1 and 12.\n");
503 return;
504 }
505 if (ioctl(0, VT_ACTIVATE, scrno) == -1)
506 perror("switching to new VT");
507}
508
509
510void
511setfkey(knumc, str)
512char *knumc;
513char *str;
514{
515fkeyarg_t fkey;
516char *v1;
bc9a1454 517long keynum;
24380a1e 518
bc9a1454
JH
519 keynum = strtol(knumc, &v1, 0);
520 if (keynum < 0 || keynum > 59 || *v1 != '\0') {
521 fprintf(stderr, "function key number must be between 0 and 59.\n");
24380a1e
JH
522 return;
523 }
bc9a1454 524 fkey.keynum = keynum;
24380a1e
JH
525 if ((fkey.flen = strlen(str)) > MAXFK) {
526 fprintf(stderr, "function key string too long (%d > %d)\n", fkey.flen, MAXFK);
527 return;
528 }
529 strcpy(fkey.keydef, str);
530 if (verbose)
531 fprintf(stderr, "setting F%d to \"%s\"\n", fkey.keynum, str);
532 fkey.keynum--;
533 if (ioctl(0, SETFKEY, &fkey) == -1)
534 perror("setting function key");
535}
536
537
538
539void
540displayit(void)
541{
542 if (verbose)
543 printf("absolutely ");
544 printf("nothing to display.\n");
545}