dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / kbd / kbd.c
blobb099ac5b2e581acd3c4cf7bfaedf2849c81f9f12
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Usage: kbd [-r] [-t] [-l] [-c on|off] [-a enable|disable|alternate]
28 * [-d keyboard device] [-D autorepeat dealy] [-R autorepeat
29 * rate]
30 * kbd [-i] [-d keyboard device]
31 * kbd -s [language]
32 * kbd -b [keyboard|console] frequency
33 * -r reset the keyboard as if power-up
34 * -t return the type of the keyboard being used
35 * -l return the layout of the keyboard being used,
36 * and the Autorepeat settings
37 * -i read in the default configuration file
38 * -c on|off turn on|off clicking
39 * -a enable|disable|alternate sets abort sequence
40 * -D autorepeat delay sets autorepeat dealy, unit in ms
41 * -R autorepeat rate sets autorepeat rate, unit in ms
42 * -d keyboard device chooses the kbd device, default /dev/kbd.
43 * -s keyboard layout sets keyboard layout
44 * -b [keyboard| console] frequency
45 * sets keyboard or console beeper frequency
48 #include <sys/types.h>
49 #include <sys/ioctl.h>
50 #include <sys/kbio.h>
51 #include <sys/kbd.h>
52 #include <stdio.h>
53 #include <fcntl.h>
54 #include <deflt.h>
55 #include <unistd.h>
56 #include <string.h>
57 #include <stdlib.h>
58 #include <stropts.h>
59 #include <libintl.h>
60 #include <locale.h>
61 #include <errno.h>
62 #include <inttypes.h>
63 #include <libscf.h>
65 #define KBD_DEVICE "/dev/kbd" /* default keyboard device */
67 #define KBD_LAYOUT_FILE "/usr/share/lib/keytables/type_6/kbd_layouts"
68 #define MAX_LAYOUT_NUM 128
69 #define MAX_LINE_SIZE 256
70 #define DEFAULT_KBD_LAYOUT 33
72 #define KBD_FMRI "svc:/system/keymap:default"
73 #define KBD_PG "keymap"
74 #define KBD_PROP_LAYOUT "layout"
75 #define KBD_PROP_KEYCLICK "keyclick"
76 #define KBD_PROP_KEYBOARD_ABORT "keyboard_abort"
77 #define KBD_PROP_RPTDELAY "repeat_delay"
78 #define KBD_PROP_RPTRATE "repeat_rate"
79 #define KBD_PROP_FREQ "kbd_beeper_freq"
80 #define KBD_PROP_CONSFREQ "console_beeper_freq"
81 #define KBD_MAX_NAME_LEN 1024
83 char *layout_names[MAX_LAYOUT_NUM];
84 int layout_numbers[MAX_LAYOUT_NUM];
85 static int layout_count;
86 static int default_layout_number = 0;
88 static void reset(int);
89 static int get_type(int);
90 static void get_layout(int);
91 static void kbd_defaults(int);
92 static void usage(void);
94 static int click(char *, int);
95 static int abort_enable(char *, int);
96 static int set_repeat_delay(char *, int);
97 static int set_rptdelay(int, int);
98 static int set_repeat_rate(char *, int);
99 static int set_rptrate(int, int);
101 static int get_layout_number(char *);
102 static int set_layout(int, int);
103 static int get_layouts(void);
104 static int set_kbd_layout(int, char *);
105 static int set_beep_freq(int, char *, int);
108 main(int argc, char **argv)
110 int c, error;
111 int rflag, tflag, lflag, cflag, dflag, aflag, iflag, errflag,
112 Dflag, Rflag, rtlacDRflag, sflag, bflag;
113 char *copt, *aopt, *delay, *rate, *layout_name, *b_type, *freq_str;
114 char *kbdname = KBD_DEVICE, *endptr = NULL;
115 int kbd, freq_val;
116 extern char *optarg;
117 extern int optind;
119 rflag = tflag = cflag = dflag = aflag = iflag = errflag = lflag =
120 Dflag = Rflag = sflag = bflag = 0;
121 copt = aopt = (char *)0;
123 (void) setlocale(LC_ALL, "");
124 #if !defined(TEXT_DOMAIN)
125 #define TEXT_DOMAIN "SYS_TEST"
126 #endif
127 (void) textdomain(TEXT_DOMAIN);
129 while ((c = getopt(argc, argv, "rtlisc:a:d:D:R:b:")) != EOF) {
130 switch (c) {
131 case 'r':
132 rflag++;
133 break;
134 case 't':
135 tflag++;
136 break;
137 case 'l':
138 lflag++;
139 break;
140 case 'i':
141 iflag++;
142 break;
143 case 's':
144 sflag++;
145 break;
146 case 'c':
147 copt = optarg;
148 cflag++;
149 break;
150 case 'a':
151 aopt = optarg;
152 aflag++;
153 break;
154 case 'd':
155 kbdname = optarg;
156 dflag++;
157 break;
158 case 'D':
159 delay = optarg;
160 Dflag++;
161 break;
162 case 'R':
163 rate = optarg;
164 Rflag++;
165 break;
166 case 'b':
167 bflag++;
168 break;
169 case '?':
170 errflag++;
171 break;
176 * Check for valid arguments:
178 * If argument parsing failed or if there are left-over
179 * command line arguments(except -s and -b option),
180 * then we're done now.
182 if (errflag != 0 || (sflag == 0 && bflag == 0 && argc != optind)) {
183 usage();
184 exit(1);
188 * kbd requires that the user specify either "-i" or "-s" or "-b" or
189 * at least one of -[rtlacDR]. The "-d" option is, well, optional.
190 * We don't care if it's there or not.
192 rtlacDRflag = rflag + tflag + lflag + aflag + cflag + Dflag + Rflag;
193 if (!((iflag != 0 && sflag == 0 && bflag == 0 && rtlacDRflag == 0) ||
194 (iflag == 0 && sflag != 0 && bflag == 0 && dflag == 0 &&
195 rtlacDRflag == 0) ||
196 (iflag == 0 && sflag == 0 && bflag == 0 && rtlacDRflag != 0) ||
197 (iflag == 0 && sflag == 0 && bflag != 0 && rtlacDRflag == 0))) {
198 usage();
199 exit(1);
202 if (Dflag && atoi(delay) <= 0) {
203 (void) fprintf(stderr, "Invalid arguments: -D %s\n", delay);
204 usage();
205 exit(1);
208 if (Rflag && atoi(rate) <= 0) {
209 (void) fprintf(stderr, "Invalid arguments: -R %s\n", rate);
210 usage();
211 exit(1);
215 * Open the keyboard device
217 if ((kbd = open(kbdname, O_RDWR)) < 0) {
218 perror("opening the keyboard");
219 (void) fprintf(stderr, "kbd: Cannot open %s\n", kbdname);
220 exit(1);
223 if (iflag) {
224 kbd_defaults(kbd);
225 exit(0); /* A mutually exclusive option */
226 /*NOTREACHED*/
229 if (tflag)
230 (void) get_type(kbd);
232 if (lflag)
233 get_layout(kbd);
235 if (cflag && (error = click(copt, kbd)) != 0)
236 exit(error);
238 if (rflag)
239 reset(kbd);
241 if (aflag && (error = abort_enable(aopt, kbd)) != 0)
242 exit(error);
244 if (Dflag && (error = set_repeat_delay(delay, kbd)) != 0)
245 exit(error);
247 if (Rflag && (error = set_repeat_rate(rate, kbd)) != 0)
248 exit(error);
250 if (sflag) {
251 if (argc == optind) {
252 layout_name = NULL;
253 } else if (argc == (optind + 1)) {
254 layout_name = argv[optind];
255 } else {
256 usage();
257 exit(1);
260 if ((error = set_kbd_layout(kbd, layout_name)) != 0)
261 exit(error);
264 if (bflag) {
265 if (argc == optind) {
266 b_type = "keyboard";
267 } else if (argc == (optind + 1)) {
268 b_type = argv[argc - 2];
269 } else {
270 usage();
271 exit(1);
274 if (strcmp(b_type, "keyboard") && strcmp(b_type, "console")) {
275 usage();
276 exit(1);
279 freq_str = argv[argc - 1];
280 errno = 0;
281 freq_val = (int)strtol(freq_str, &endptr, 10);
282 if (errno != 0 || endptr[0] != '\0') {
283 usage();
284 exit(1);
287 if (freq_val < 0 || freq_val > INT16_MAX) {
288 (void) fprintf(stderr, "Invalid arguments: -b %s\n",
289 freq_str);
290 (void) fprintf(stderr, "Frequency range: [0 - %d]\n",
291 INT16_MAX);
292 exit(1);
295 if ((error = set_beep_freq(kbd, b_type, freq_val)) != 0)
296 exit(1);
299 return (0);
303 * this routine gets the type of the keyboard being used
305 static int
306 set_kbd_layout(int kbd, char *layout_name)
308 int layout_num;
309 int error = 1;
311 /* layout setting is possible only for USB type keyboards */
312 if (get_type(kbd) != KB_USB) {
313 (void) fprintf(stderr, "The -s option does not apply for this"
314 " keyboard type.\n"
315 "Only USB/PS2 type keyboards support this option.\n");
316 return (error);
319 /* get the language info from the layouts file */
320 if (get_layouts() != 0)
321 return (error);
323 if (layout_name != NULL) {
324 if ((layout_num = get_layout_number(layout_name)) == -1) {
325 (void) fprintf(stderr, "%s: unknown layout name\n"
326 "Please refer to 'kbd -s' to get the "
327 "supported layouts.\n", layout_name);
328 return (error);
330 } else {
331 int i, j, print_cnt, input_num;
332 boolean_t input_right = B_TRUE;
333 boolean_t default_input = B_FALSE;
334 char input[8]; /* 8 chars is enough for numbers */
336 print_cnt = (layout_count % 2) ?
337 layout_count/2+1 : layout_count/2;
339 for (i = 1; i <= print_cnt; i++) {
340 (void) printf("%2d. %-30s", i,
341 layout_names[i-1]);
342 j = i + print_cnt;
343 if (j <= layout_count) {
344 (void) printf("%-2d. %-30s\n", j,
345 layout_names[j-1]);
348 (void) printf(gettext("\nTo select the keyboard layout,"
349 " enter a number [default %d]:"),
350 default_layout_number+1);
352 for (;;) {
353 if (input_right == B_FALSE)
354 (void) printf(gettext("Invalid input. "
355 "Please input a number "
356 "(1,2,...):"));
357 (void) memset(input, 0, 8);
358 (void) fflush(stdin);
359 (void) fgets(input, 8, stdin);
360 if (strlen(input) > 4) {
361 input_right = B_FALSE;
362 continue;
364 if (input[0] == '\n') {
365 default_input = B_TRUE;
366 break;
368 input_right = B_TRUE;
369 /* check if the inputs are numbers 0~9 */
370 for (i = 0; i < (strlen(input) - 1); i++) {
371 if ((input[i] < '0') ||
372 (input[i] > '9')) {
373 input_right = B_FALSE;
374 break;
377 if (input_right == B_FALSE)
378 continue;
379 input_num = atoi(input);
380 if ((input_num > 0) &&
381 (input_num <= layout_count))
382 break;
383 else
384 input_right = B_FALSE;
386 if (default_input == B_TRUE)
387 layout_num = DEFAULT_KBD_LAYOUT;
388 else
389 layout_num = layout_numbers[--input_num];
392 if ((error = set_layout(kbd, layout_num)) != 0)
393 return (error);
395 return (0);
399 * This routine sets keyboard or console beeper frequency
401 static int
402 set_beep_freq(int fd, char *type, int freq)
404 struct freq_request fr_struct;
406 if (strcmp(type, "keyboard") == 0)
407 fr_struct.type = KBD_BEEP;
408 else if (strcmp(type, "console") == 0)
409 fr_struct.type = CONSOLE_BEEP;
410 else
411 return (EINVAL);
413 fr_struct.freq = (int16_t)freq;
415 return (ioctl(fd, KIOCSETFREQ, &fr_struct));
419 * this routine resets the state of the keyboard as if power-up
421 static void
422 reset(int kbd)
424 int cmd;
426 cmd = KBD_CMD_RESET;
428 if (ioctl(kbd, KIOCCMD, &cmd)) {
429 perror("kbd: ioctl error");
430 exit(1);
436 * this routine gets the type of the keyboard being used
438 static int
439 get_type(int kbd)
441 int kbd_type;
443 if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
444 perror("ioctl (kbd type)");
445 exit(1);
448 switch (kbd_type) {
450 case KB_SUN3:
451 (void) printf("Type 3 Sun keyboard\n");
452 break;
454 case KB_SUN4:
455 (void) printf("Type 4 Sun keyboard\n");
456 break;
458 case KB_ASCII:
459 (void) printf("ASCII\n");
460 break;
462 case KB_PC:
463 (void) printf("PC\n");
464 break;
466 case KB_USB:
467 (void) printf("USB keyboard\n");
468 break;
470 default:
471 (void) printf("Unknown keyboard type\n");
472 break;
474 return (kbd_type);
478 * this routine gets the layout of the keyboard being used
479 * also, included the autorepeat delay and rate being used
481 static void
482 get_layout(int kbd)
484 int kbd_type;
485 int kbd_layout;
486 /* these two variables are used for getting delay&rate */
487 int delay, rate;
488 delay = rate = 0;
490 if (ioctl(kbd, KIOCTYPE, &kbd_type)) {
491 perror("ioctl (kbd type)");
492 exit(1);
495 if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) {
496 perror("ioctl (kbd layout)");
497 exit(1);
500 (void) printf("type=%d\nlayout=%d (0x%.2x)\n",
501 kbd_type, kbd_layout, kbd_layout);
503 /* below code is used to get the autorepeat delay and rate */
504 if (ioctl(kbd, KIOCGRPTDELAY, &delay)) {
505 perror("ioctl (kbd get repeat delay)");
506 exit(1);
509 if (ioctl(kbd, KIOCGRPTRATE, &rate)) {
510 perror("ioctl (kbd get repeat rate)");
511 exit(1);
514 (void) printf("delay(ms)=%d\n", delay);
515 (void) printf("rate(ms)=%d\n", rate);
519 * this routine enables or disables clicking of the keyboard
521 static int
522 click(char *copt, int kbd)
524 int cmd;
526 if (strcmp(copt, "on") == 0)
527 cmd = KBD_CMD_CLICK;
528 else if (strcmp(copt, "off") == 0)
529 cmd = KBD_CMD_NOCLICK;
530 else {
531 (void) fprintf(stderr, "wrong option -- %s\n", copt);
532 usage();
533 return (1);
536 if (ioctl(kbd, KIOCCMD, &cmd)) {
537 perror("kbd ioctl (keyclick)");
538 return (1);
540 return (0);
544 * this routine enables/disables/sets BRK or abort sequence feature
546 static int
547 abort_enable(char *aopt, int kbd)
549 int enable;
551 if (strcmp(aopt, "alternate") == 0)
552 enable = KIOCABORTALTERNATE;
553 else if (strcmp(aopt, "enable") == 0)
554 enable = KIOCABORTENABLE;
555 else if (strcmp(aopt, "disable") == 0)
556 enable = KIOCABORTDISABLE;
557 else {
558 (void) fprintf(stderr, "wrong option -- %s\n", aopt);
559 usage();
560 return (1);
563 if (ioctl(kbd, KIOCSKABORTEN, &enable)) {
564 perror("kbd ioctl (abort enable)");
565 return (1);
567 return (0);
570 static int
571 set_rptdelay(int delay, int kbd)
574 * The error message depends on the different inputs.
575 * a. the input is a invalid integer(unit in ms)
576 * b. the input is a integer less than the minimal delay setting.
577 * The condition (a) has been covered by main function and kbd_defaults
578 * function.
580 if (ioctl(kbd, KIOCSRPTDELAY, &delay) == -1) {
581 if (delay < KIOCRPTDELAY_MIN)
582 (void) fprintf(stderr, "kbd: specified delay %d is "
583 "less than minimum %d\n", delay, KIOCRPTDELAY_MIN);
584 else
585 perror("kbd: set repeat delay");
586 return (1);
589 return (0);
593 * this routine set autorepeat delay
595 static int
596 set_repeat_delay(char *delay_str, int kbd)
598 int delay = atoi(delay_str);
600 return (set_rptdelay(delay, kbd));
603 static int
604 set_rptrate(int rate, int kbd)
607 * The input validation check has been covered by main function
608 * and kbd_defaults function.Here just give an error message if
609 * the ioctl fails.
611 if (ioctl(kbd, KIOCSRPTRATE, &rate) == -1) {
612 perror("kbd: set repeat rate");
613 return (1);
615 return (0);
619 * this routine set autorepeat rate
621 static int
622 set_repeat_rate(char *rate_str, int kbd)
624 int rate = atoi(rate_str);
626 return (set_rptrate(rate, kbd));
629 #define BAD_DEFAULT_STR "kbd: bad default value for %s: %s\n"
630 #define BAD_DEFAULT_INT "kbd: bad default value for %s: %d\n"
631 #define BAD_DEFAULT_LLINT "kbd: bad default value for %s: %lld\n"
633 static void
634 kbd_defaults(int kbd)
636 scf_handle_t *h = NULL;
637 scf_snapshot_t *snap = NULL;
638 scf_instance_t *inst = NULL;
639 scf_propertygroup_t *pg = NULL;
640 scf_property_t *prop = NULL;
641 scf_value_t *val = NULL;
643 int layout_num;
644 char *val_layout = NULL, *val_abort = NULL;
645 uint8_t val_click;
646 int64_t val_delay, val_rate;
647 int64_t val_kbd_beeper, val_console_beeper;
649 if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
650 scf_handle_bind(h) != 0 ||
651 (inst = scf_instance_create(h)) == NULL ||
652 (snap = scf_snapshot_create(h)) == NULL ||
653 (pg = scf_pg_create(h)) == NULL ||
654 (prop = scf_property_create(h)) == NULL ||
655 (val = scf_value_create(h)) == NULL) {
656 goto out;
659 if (scf_handle_decode_fmri(h, KBD_FMRI, NULL, NULL, inst,
660 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
661 goto out;
664 if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
665 scf_snapshot_destroy(snap);
666 snap = NULL;
669 if (scf_instance_get_pg_composed(inst, snap, KBD_PG, pg) != 0) {
670 goto out;
673 if ((val_abort = malloc(KBD_MAX_NAME_LEN)) == NULL) {
674 (void) fprintf(stderr,
675 "Can not alloc memory for keyboard properties\n");
676 goto out;
679 if ((val_layout = malloc(KBD_MAX_NAME_LEN)) == NULL) {
680 (void) fprintf(stderr,
681 "Can not alloc memory for keyboard properties\n");
682 goto out;
685 if (scf_pg_get_property(pg, KBD_PROP_KEYCLICK, prop) != 0 ||
686 scf_property_get_value(prop, val) != 0 ||
687 scf_value_get_boolean(val, &val_click) == -1) {
688 (void) fprintf(stderr, "Can not get KEYCLICK\n");
691 if (val_click == 1)
692 (void) click("on", kbd);
693 else if (val_click == 0)
694 (void) click("off", kbd);
695 else
696 (void) fprintf(stderr,
697 BAD_DEFAULT_INT, KBD_PROP_KEYCLICK, val_click);
699 if (scf_pg_get_property(pg, KBD_PROP_KEYBOARD_ABORT, prop) != 0 ||
700 scf_property_get_value(prop, val) != 0 ||
701 scf_value_get_astring(val, val_abort, KBD_MAX_NAME_LEN) == -1) {
702 (void) fprintf(stderr, "Can not get KEYBOARD_ABORT\n");
705 if (*val_abort != '\0') {
707 * ABORT must equal "enable", "disable" or "alternate"
709 if ((strcmp(val_abort, "enable") == 0) ||
710 (strcmp(val_abort, "alternate") == 0) ||
711 (strcmp(val_abort, "disable") == 0))
712 (void) abort_enable(val_abort, kbd);
713 else
714 (void) fprintf(stderr, BAD_DEFAULT_STR,
715 KBD_PROP_KEYBOARD_ABORT, val_abort);
718 if (scf_pg_get_property(pg, KBD_PROP_RPTDELAY, prop) != 0 ||
719 scf_property_get_value(prop, val) != 0 ||
720 scf_value_get_integer(val, &val_delay) == -1) {
721 (void) fprintf(stderr, "Can not get RPTDELAY\n");
724 if (val_delay > 0)
725 (void) set_rptdelay(val_delay, kbd);
726 else
727 (void) fprintf(stderr,
728 BAD_DEFAULT_LLINT, KBD_PROP_RPTDELAY, val_delay);
730 if (scf_pg_get_property(pg, KBD_PROP_RPTRATE, prop) != 0 ||
731 scf_property_get_value(prop, val) != 0 ||
732 scf_value_get_integer(val, &val_rate) == -1) {
733 (void) fprintf(stderr, "Can not get RPTRATE\n");
736 if (val_rate > 0)
737 (void) set_rptrate(val_rate, kbd);
738 else
739 (void) fprintf(stderr,
740 BAD_DEFAULT_LLINT, KBD_PROP_RPTRATE, val_rate);
742 if (scf_pg_get_property(pg, KBD_PROP_LAYOUT, prop) != 0 ||
743 scf_property_get_value(prop, val) != 0 ||
744 scf_value_get_astring(val, val_layout, KBD_MAX_NAME_LEN) == -1) {
745 (void) fprintf(stderr, "Can not get LAYOUT\n");
748 if (*val_layout != '\0') {
750 * LAYOUT must be one of the layouts supported in kbd_layouts
752 if (get_layouts() != 0)
753 goto out;
755 if ((layout_num = get_layout_number(val_layout)) == -1) {
756 (void) fprintf(stderr,
757 BAD_DEFAULT_STR, KBD_PROP_LAYOUT, val_layout);
758 goto out;
761 (void) set_layout(kbd, layout_num);
764 if (scf_pg_get_property(pg, KBD_PROP_FREQ, prop) != 0 ||
765 scf_property_get_value(prop, val) != 0 ||
766 scf_value_get_integer(val, &val_kbd_beeper) == -1) {
767 (void) fprintf(stderr, "Can not get FREQ\n");
770 if (val_kbd_beeper >= 0 && val_kbd_beeper <= INT16_MAX)
771 (void) set_beep_freq(kbd, "keyboard", val_kbd_beeper);
772 else
773 (void) fprintf(stderr,
774 BAD_DEFAULT_LLINT, KBD_PROP_FREQ, val_kbd_beeper);
776 if (scf_pg_get_property(pg, KBD_PROP_CONSFREQ, prop) != 0 ||
777 scf_property_get_value(prop, val) != 0 ||
778 scf_value_get_integer(val, &val_console_beeper) == -1) {
779 (void) fprintf(stderr, "Can not get CONSFREQ\n");
782 if (val_console_beeper >= 0 && val_console_beeper <= INT16_MAX)
783 (void) set_beep_freq(kbd, "console", val_console_beeper);
784 else
785 (void) fprintf(stderr,
786 BAD_DEFAULT_LLINT, KBD_PROP_CONSFREQ, val_console_beeper);
788 out:
789 free(val_layout);
790 free(val_abort);
791 if (snap != NULL)
792 scf_snapshot_destroy(snap);
793 scf_value_destroy(val);
794 scf_property_destroy(prop);
795 scf_pg_destroy(pg);
796 scf_instance_destroy(inst);
797 scf_handle_destroy(h);
800 static int
801 get_layout_number(char *layout)
803 int i;
804 int layout_number = -1;
806 for (i = 0; i < layout_count; i ++) {
807 if (strcmp(layout, layout_names[i]) == 0) {
808 layout_number = layout_numbers[i];
809 break;
813 return (layout_number);
816 static int
817 get_layouts()
819 FILE *stream;
820 char buffer[MAX_LINE_SIZE];
821 char *result = NULL;
822 int i = 0;
823 char *tmpbuf;
825 if ((stream = fopen(KBD_LAYOUT_FILE, "r")) == 0) {
826 perror(KBD_LAYOUT_FILE);
827 return (1);
830 while ((fgets(buffer, MAX_LINE_SIZE, stream) != NULL) &&
831 (i < MAX_LAYOUT_NUM)) {
832 if (buffer[0] == '#')
833 continue;
834 if ((result = strtok(buffer, "=")) == NULL)
835 continue;
836 if ((tmpbuf = strdup(result)) != NULL) {
837 layout_names[i] = tmpbuf;
838 } else {
839 perror("out of memory getting layout names");
840 return (1);
842 if ((result = strtok(NULL, "\n")) == NULL)
843 continue;
844 layout_numbers[i] = atoi(result);
845 if (strcmp(tmpbuf, "US-English") == 0)
846 default_layout_number = i;
847 i++;
849 layout_count = i;
851 return (0);
855 * this routine sets the layout of the keyboard being used
857 static int
858 set_layout(int kbd, int layout_num)
861 if (ioctl(kbd, KIOCSLAYOUT, layout_num)) {
862 perror("ioctl (set kbd layout)");
863 return (1);
866 return (0);
869 static char *usage1 = "kbd [-r] [-t] [-l] [-a enable|disable|alternate]";
870 static char *usage2 = " [-c on|off][-D delay][-R rate][-d keyboard device]";
871 static char *usage3 = "kbd -i [-d keyboard device]";
872 static char *usage4 = "kbd -s [language]";
873 static char *usage5 = "kbd -b [keyboard|console] frequency";
875 static void
876 usage(void)
878 (void) fprintf(stderr, "Usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", usage1,
879 usage2, usage3, usage4, usage5);