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 *)); | |
50 | void linemode __P((char *)); | |
51 | void keyrate __P((char *)); | |
52 | void keymap __P((char *)); | |
bc9a1454 | 53 | void mapscr __P((char *)); |
24380a1e JH |
54 | void loadfont __P((char *, char *)); |
55 | void switchto __P((char *)); | |
56 | void setfkey __P((char *, char *)); | |
57 | void displayit __P((void)); | |
58 | void usage __P((void)); | |
59 | char *mkfullname __P((const char *, const char *, const char *)); | |
60 | char *nextarg __P((int, char **, int *, int)); | |
61 | __END_DECLS | |
62 | ||
63 | ||
64 | ||
65 | void | |
66 | main(argc, argv) | |
67 | int argc; | |
68 | char **argv; | |
69 | { | |
70 | extern char *optarg; | |
71 | extern int optind; | |
72 | int 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 | ||
122 | int | |
123 | is_syscons(fd) | |
124 | int fd; | |
125 | { | |
126 | vtmode_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 | ||
147 | void | |
148 | usage(void) | |
149 | { | |
150 | const char usagestr[] = {"\ | |
151 | Usage: 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 | ||
168 | char * | |
169 | nextarg(ac, av, indp, oc) | |
170 | int ac; | |
171 | char **av; | |
172 | int *indp; | |
173 | int 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 | ||
185 | char * | |
186 | mkfullname(s1, s2, s3) | |
187 | const char *s1, *s2, *s3; | |
188 | { | |
189 | static char *buf = NULL; | |
190 | static int bufl = 0; | |
191 | int 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 | ||
213 | void | |
214 | screensaver(opt) | |
215 | char *opt; | |
216 | { | |
217 | int nsec; | |
218 | char *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 | ||
236 | void | |
237 | linemode(opt) | |
238 | char *opt; | |
239 | { | |
240 | unsigned 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 | ||
256 | void | |
257 | keyrate(opt) | |
258 | char *opt; | |
259 | { | |
260 | const int delays[] = {250, 500, 750, 1000}; | |
261 | const 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}; | |
265 | const int ndelays = (sizeof(delays) / sizeof(int)); | |
266 | const int nrepeats = (sizeof(repeats) / sizeof(int)); | |
267 | struct { | |
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')) { | |
291 | badopt: | |
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 | ||
312 | void | |
313 | keymap(opt) | |
314 | char *opt; | |
315 | { | |
316 | char *mapfn; | |
317 | int mapfd; | |
318 | keymap_t map; | |
319 | int f; | |
320 | const char *prefix[] = {"", "", KEYMAP_PATH, NULL}; | |
321 | const 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 |
348 | void |
349 | mapscr(opt) | |
350 | char *opt; | |
351 | { | |
352 | char *mapfn; | |
353 | int mapfd; | |
354 | scrmap_t map; | |
355 | int f; | |
356 | const char *prefix[] = {"", "", SCRNMAP_PATH, NULL}; | |
357 | const 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 | |
384 | void | |
385 | loadfont(sizec, fname) | |
386 | char *sizec; | |
387 | char *fname; | |
388 | { | |
389 | char *fontfn; | |
390 | int fontfd; | |
391 | void *font; | |
392 | char *v1; | |
393 | int ind, f; | |
394 | const 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 }}; | |
403 | const char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; | |
404 | const 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 | ||
447 | void | |
448 | switchto(opt) | |
449 | char *opt; | |
450 | { | |
451 | int scrno; | |
452 | char *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 | ||
465 | void | |
466 | setfkey(knumc, str) | |
467 | char *knumc; | |
468 | char *str; | |
469 | { | |
470 | fkeyarg_t fkey; | |
471 | char *v1; | |
bc9a1454 | 472 | long 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 | ||
494 | void | |
495 | displayit(void) | |
496 | { | |
497 | if (verbose) | |
498 | printf("absolutely "); | |
499 | printf("nothing to display.\n"); | |
500 | } |