Commit | Line | Data |
---|---|---|
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 |
43 | int verbose = 0; |
44 | char *prgname; | |
45 | ||
46 | ||
47 | __BEGIN_DECLS | |
48 | int is_syscons __P((int)); | |
49 | void screensaver __P((char *)); | |
13f3017d | 50 | void screensavertype __P((char *)); |
24380a1e JH |
51 | void linemode __P((char *)); |
52 | void keyrate __P((char *)); | |
53 | void keymap __P((char *)); | |
bc9a1454 | 54 | void mapscr __P((char *)); |
24380a1e JH |
55 | void loadfont __P((char *, char *)); |
56 | void switchto __P((char *)); | |
57 | void setfkey __P((char *, char *)); | |
58 | void displayit __P((void)); | |
59 | void usage __P((void)); | |
60 | char *mkfullname __P((const char *, const char *, const char *)); | |
61 | char *nextarg __P((int, char **, int *, int)); | |
62 | __END_DECLS | |
63 | ||
64 | ||
65 | ||
66 | void | |
67 | main(argc, argv) | |
68 | int argc; | |
69 | char **argv; | |
70 | { | |
71 | extern char *optarg; | |
72 | extern int optind; | |
73 | int 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 | ||
126 | int | |
127 | is_syscons(fd) | |
128 | int fd; | |
129 | { | |
130 | vtmode_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 | ||
151 | void | |
152 | usage(void) | |
153 | { | |
154 | const char usagestr[] = {"\ | |
155 | Usage: 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 | ||
173 | char * | |
174 | nextarg(ac, av, indp, oc) | |
175 | int ac; | |
176 | char **av; | |
177 | int *indp; | |
178 | int 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 | ||
190 | char * | |
191 | mkfullname(s1, s2, s3) | |
192 | const char *s1, *s2, *s3; | |
193 | { | |
194 | static char *buf = NULL; | |
195 | static int bufl = 0; | |
196 | int 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 | ||
218 | void | |
219 | screensaver(opt) | |
220 | char *opt; | |
221 | { | |
222 | int nsec; | |
223 | char *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 |
241 | void |
242 | screensavertype(opt) | |
243 | char *opt; | |
244 | { | |
245 | ssaver_t shaver; | |
246 | int 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 |
281 | void |
282 | linemode(opt) | |
283 | char *opt; | |
284 | { | |
285 | unsigned 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 | ||
301 | void | |
302 | keyrate(opt) | |
303 | char *opt; | |
304 | { | |
305 | const int delays[] = {250, 500, 750, 1000}; | |
306 | const 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}; | |
310 | const int ndelays = (sizeof(delays) / sizeof(int)); | |
311 | const int nrepeats = (sizeof(repeats) / sizeof(int)); | |
312 | struct { | |
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')) { | |
336 | badopt: | |
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 | ||
357 | void | |
358 | keymap(opt) | |
359 | char *opt; | |
360 | { | |
361 | char *mapfn; | |
362 | int mapfd; | |
363 | keymap_t map; | |
364 | int f; | |
365 | const char *prefix[] = {"", "", KEYMAP_PATH, NULL}; | |
366 | const 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 |
393 | void |
394 | mapscr(opt) | |
395 | char *opt; | |
396 | { | |
397 | char *mapfn; | |
398 | int mapfd; | |
399 | scrmap_t map; | |
400 | int f; | |
401 | const char *prefix[] = {"", "", SCRNMAP_PATH, NULL}; | |
402 | const 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 | |
429 | void | |
430 | loadfont(sizec, fname) | |
431 | char *sizec; | |
432 | char *fname; | |
433 | { | |
434 | char *fontfn; | |
435 | int fontfd; | |
436 | void *font; | |
437 | char *v1; | |
438 | int ind, f; | |
439 | const 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 }}; | |
448 | const char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; | |
449 | const 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 | ||
492 | void | |
493 | switchto(opt) | |
494 | char *opt; | |
495 | { | |
496 | int scrno; | |
497 | char *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 | ||
510 | void | |
511 | setfkey(knumc, str) | |
512 | char *knumc; | |
513 | char *str; | |
514 | { | |
515 | fkeyarg_t fkey; | |
516 | char *v1; | |
bc9a1454 | 517 | long 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 | ||
539 | void | |
540 | displayit(void) | |
541 | { | |
542 | if (verbose) | |
543 | printf("absolutely "); | |
544 | printf("nothing to display.\n"); | |
545 | } |