4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23
24 #ifndef lint
25 #pragma ident "%Z%%M% %I% %E% SMI"
26 #endif
27
28 /*
29 * Copyright (c) 1999 by Sun Microsystems, Inc.
30 * All rights reserved.
31 */
32
33 #include <sys/param.h>
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <search.h>
37 #include <string.h>
38 #include <malloc.h>
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <sys/kbd.h>
44 #include <sys/kbio.h>
45
46 #define ALL -1 /* special symbol for all tables */
47
48 /*
49 * SunOS 4.x and Solaris 2.[1234] put Type 4 key tables into
50 * the keytables directory with no type qualification.
51 * If we're a SPARC, we might be using an NFS server that
52 * doesn't have the new type-qualified directories.
53 * (loadkeys wasn't used on non-SPARCs in 2.[1234].)
54 */
55 #ifdef sparc
56 #define COMPATIBILITY_DIR
57 #endif
58
59 static char keytable_dir[] = "/usr/share/lib/keytables/type_%d/";
60 #ifdef COMPATIBILITY_DIR
61 static char keytable_dir2[] = "/usr/share/lib/keytables/";
62 #endif
63 static char layout_prefix[] = "layout_";
64
65 struct keyentry {
66 struct keyentry *ke_next;
67 struct kiockeymap ke_entry;
68 };
69
70 typedef struct keyentry keyentry;
71
72 static keyentry *firstentry;
73 static keyentry *lastentry;
74
75 struct dupentry {
76 struct dupentry *de_next;
77 int de_station;
78 int de_otherstation;
79 };
80
81 typedef struct dupentry dupentry;
82
115
116 static smentry_t shiftmasks[] = {
117 { 0, SM_NORMAL },
118 { SHIFTMASK, SM_NORMAL },
119 { CAPSMASK, SM_NORMAL },
120 { CTRLMASK, SM_NORMAL },
121 { ALTGRAPHMASK, SM_NORMAL },
122 { NUMLOCKMASK, SM_NUMLOCK },
123 { UPMASK, SM_UP },
124 };
125
126
127 #define NSHIFTS (sizeof (shiftmasks) / sizeof (shiftmasks[0]))
128
129 static void enter_mapentry(int station, keyentry *entrylistp);
130 static keyentry *makeentry(int tablemask, int entry);
131 static int loadkey(int kbdfd, keyentry *kep);
132 static int dupkey(int kbdfd, dupentry *dep, int shiftmask);
133 static int swapkey(int kbdfd, dupentry *dep, int shiftmask);
134 static int yylex();
135 static int readesc(FILE *stream, int delim, int single_char);
136 static int wordcmp(const void *w1, const void *w2);
137 static int yyerror(char *msg);
138 static void usage(void);
139 static void set_layout(char *arg);
140 static FILE *open_mapping_file(char *pathbuf, char *name,
141 boolean_t explicit_name, int type);
142
143 int
144 main(argc, argv)
145 int argc;
146 char **argv;
147 {
148 register int kbdfd;
149 int type;
150 int layout;
151 /* maxint is 8 hex digits. */
152 char layout_filename[sizeof(layout_prefix)+8];
153 char pathbuf[MAXPATHLEN];
154 register int shift;
155 struct kiockeymap mapentry;
156 register keyentry *kep;
157 register dupentry *dep;
158 boolean_t explicit_name;
159
160 while(++argv, --argc) {
161 if(argv[0][0] != '-') break;
162 switch(argv[0][1]) {
163 case 'e':
164 /* -e obsolete, silently ignore */
165 break;
166 case 's':
167 if (argc != 2) {
168 usage();
169 /* NOTREACHED */
170 }
171 set_layout(argv[1]);
172 exit(0);
173 default:
174 usage();
175 /* NOTREACHED */
176 }
177 }
316 }
317
318 if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
319 perror("/dev/kbd");
320 exit(1);
321 }
322
323 ret = ioctl(kbdfd, KIOCSLAYOUT, layout);
324 if (ret == -1) {
325 perror("KIOCSLAYOUT");
326 }
327
328 close(kbdfd);
329 }
330
331 /*
332 * Attempt to find the specified mapping file. Return a FILE * if found,
333 * else print a message on stderr and return NULL.
334 */
335 FILE *
336 open_mapping_file(
337 char *pathbuf,
338 char *name,
339 boolean_t explicit_name,
340 int type
341 ) {
342 /* If the user specified the name, try it "raw". */
343 if (explicit_name) {
344 strcpy(pathbuf, name);
345 infile = fopen(pathbuf, "r");
346 if (infile) return (infile);
347 if (errno != ENOENT) goto fopen_fail;
348 }
349
350 /* Everything after this point applies only to relative names. */
351 if (*name == '/') goto fopen_fail;
352
353 /* Try the type-qualified directory name. */
354 sprintf(pathbuf, keytable_dir, type);
355 if ((int)(strlen(pathbuf) + strlen(name) + 1) >= MAXPATHLEN) {
356 (void) fprintf(stderr, "loadkeys: Name %s is too long\n",
357 name);
358 return (NULL);
359 }
360 (void) strcat(pathbuf, name);
361 infile = fopen(pathbuf, "r");
362 if (infile) return (infile);
363 if (errno != ENOENT) goto fopen_fail;
364
365 #ifdef COMPATIBILITY_DIR
366 /* If not, and either the name was specified explicitly */
367 /* or this is a type 4... */
368 if (explicit_name || type == KB_SUN4) {
369 /* Try the compatibility name. */
370 /* No need to check len here, it's shorter. */
371 (void) strcpy(pathbuf, keytable_dir2);
372 (void) strcat(pathbuf, infilename);
373 infile = fopen(pathbuf, "r");
374 if (infile) return (infile);
375 if (errno != ENOENT) goto fopen_fail;
376 }
377 #endif
378
379 fopen_fail:
380 (void) fprintf(stderr, "loadkeys: ");
381 perror(name);
382 return (NULL);
383 }
384
385 /*
386 * We have a list of entries for a given keystation, and the keystation number
387 * for that keystation; put that keystation number into all the entries in that
388 * list, and chain that list to the end of the main list of entries.
389 */
390 static void
391 enter_mapentry(station, entrylistp)
392 int station;
393 keyentry *entrylistp;
394 {
395 register keyentry *kep;
396
397 if (lastentry == NULL)
398 firstentry = entrylistp;
408 kep = kep->ke_next;
409 }
410 }
411
412 /*
413 * Allocate and fill in a new entry.
414 */
415 static keyentry *
416 makeentry(tablemask, entry)
417 int tablemask;
418 int entry;
419 {
420 register keyentry *kep;
421 register int index;
422
423 if ((kep = (keyentry *) malloc((unsigned)sizeof (keyentry))) == NULL)
424 yyerror("out of memory for entries");
425 kep->ke_next = NULL;
426 kep->ke_entry.kio_tablemask = tablemask;
427 kep->ke_entry.kio_station = 0;
428 kep->ke_entry.kio_entry = (u_short)entry;
429 index = entry - STRING;
430 if (index >= 0 && index <= 15)
431 (void) strncpy(kep->ke_entry.kio_string, strings[index],
432 KTAB_STRLEN);
433 return (kep);
434 }
435
436 /*
437 * Make a set of entries for a keystation that indicate that that keystation's
438 * settings should be copied from another keystation's settings.
439 */
440 static void
441 duplicate_mapentry(station, otherstation)
442 int station;
443 int otherstation;
444 {
445 register dupentry *dep;
446
447 if ((dep = (dupentry *) malloc((unsigned)sizeof (dupentry))) == NULL)
448 yyerror("out of memory for entries");
607 $$ = $1;
608 }
609 ;
610
611 entry:
612 TABLENAME code
613 {
614 $$ = makeentry($1, $2);
615 }
616 ;
617
618 code:
619 CHARSTRING
620 {
621 $$ = $1;
622 }
623 | CHAR
624 {
625 $$ = $1;
626 }
627 | '('
628 {
629 $$ = '(';
630 }
631 | ')'
632 {
633 $$ = ')';
634 }
635 | '+'
636 {
637 $$ = '+';
638 }
639 | expr
640 {
641 $$ = $1;
642 }
643 ;
644
645 expr:
646 term
690
691 /*
692 * Table must be in alphabetical order.
693 */
694 word_t wordtab[] = {
695 { "all", TABLENAME, ALL },
696 { "alt", CONSTANT, ALT },
697 { "altg", TABLENAME, ALTGRAPHMASK },
698 { "altgraph", CONSTANT, ALTGRAPH },
699 { "as", AS, 0 },
700 { "base", TABLENAME, 0 },
701 { "bf", FKEY, BOTTOMFUNC },
702 { "buckybits", CONSTANT, BUCKYBITS },
703 { "caps", TABLENAME, CAPSMASK },
704 { "capslock", CONSTANT, CAPSLOCK },
705 { "compose", CONSTANT, COMPOSE },
706 { "ctrl", TABLENAME, CTRLMASK },
707 { "downarrow", CONSTANT, DOWNARROW },
708 { "error", CONSTANT, ERROR },
709 { "fa_acute", CONSTANT, FA_ACUTE },
710 { "fa_cedilla", CONSTANT, FA_CEDILLA },
711 { "fa_cflex", CONSTANT, FA_CFLEX },
712 { "fa_grave", CONSTANT, FA_GRAVE },
713 { "fa_tilde", CONSTANT, FA_TILDE },
714 { "fa_umlaut", CONSTANT, FA_UMLAUT },
715 { "hole", CONSTANT, HOLE },
716 { "homearrow", CONSTANT, HOMEARROW },
717 { "idle", CONSTANT, IDLE },
718 { "key", KEY, 0 },
719 { "leftarrow", CONSTANT, LEFTARROW },
720 { "leftctrl", CONSTANT, LEFTCTRL },
721 { "leftshift", CONSTANT, LEFTSHIFT },
722 { "lf", FKEY, LEFTFUNC },
723 { "metabit", CONSTANT, METABIT },
724 { "nonl", CONSTANT, NONL },
725 { "nop", CONSTANT, NOP },
726 { "numl", TABLENAME, NUMLOCKMASK },
727 { "numlock", CONSTANT, NUMLOCK },
728 { "oops", CONSTANT, OOPS },
729 { "pad0", CONSTANT, PAD0 },
730 { "pad1", CONSTANT, PAD1 },
731 { "pad2", CONSTANT, PAD2 },
732 { "pad3", CONSTANT, PAD3 },
893 } else if (strlen(tokbuf) == 2 && tokbuf[0] == '^') {
894 tokentype = CHAR;
895 yylval.number = (unsigned char)(tokbuf[1] & 037);
896 } else {
897 word_t word;
898 register word_t *wptr;
899 char *ptr;
900
901 for (cp = &tokbuf[0]; (c = *cp) != '\0'; cp++) {
902 if (isupper(c))
903 *cp = tolower(c);
904 }
905 word.w_string = tokbuf;
906 wptr = (word_t *)bsearch((char *)&word,
907 (char *)wordtab, NWORDS, sizeof (word_t),
908 wordcmp);
909 if (wptr != NULL) {
910 yylval.number = wptr->w_lval;
911 tokentype = wptr->w_type;
912 } else {
913 yylval.number = strtol(tokbuf, &ptr, 10);
914 if (ptr == tokbuf)
915 yyerror("syntax error");
916 else
917 tokentype = INT;
918 }
919 break;
920 }
921 }
922
923 return (tokentype);
924 }
925
926 static int
927 readesc(stream, delim, single_char)
928 FILE *stream;
929 int delim;
930 int single_char;
931 {
932 register int c;
933 register int val;
|
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23
24 /*
25 * Copyright (c) 1999 by Sun Microsystems, Inc.
26 * All rights reserved.
27 */
28
29 #include <sys/param.h>
30 #include <ctype.h>
31 #include <stdio.h>
32 #include <search.h>
33 #include <string.h>
34 #include <malloc.h>
35 #include <fcntl.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <sys/kbd.h>
40 #include <sys/kbio.h>
41
42 #define ALL -1 /* special symbol for all tables */
43
44 static char keytable_dir[] = "/usr/share/lib/keytables/type_%d/";
45 static char layout_prefix[] = "layout_";
46
47 struct keyentry {
48 struct keyentry *ke_next;
49 struct kiockeymap ke_entry;
50 };
51
52 typedef struct keyentry keyentry;
53
54 static keyentry *firstentry;
55 static keyentry *lastentry;
56
57 struct dupentry {
58 struct dupentry *de_next;
59 int de_station;
60 int de_otherstation;
61 };
62
63 typedef struct dupentry dupentry;
64
97
98 static smentry_t shiftmasks[] = {
99 { 0, SM_NORMAL },
100 { SHIFTMASK, SM_NORMAL },
101 { CAPSMASK, SM_NORMAL },
102 { CTRLMASK, SM_NORMAL },
103 { ALTGRAPHMASK, SM_NORMAL },
104 { NUMLOCKMASK, SM_NUMLOCK },
105 { UPMASK, SM_UP },
106 };
107
108
109 #define NSHIFTS (sizeof (shiftmasks) / sizeof (shiftmasks[0]))
110
111 static void enter_mapentry(int station, keyentry *entrylistp);
112 static keyentry *makeentry(int tablemask, int entry);
113 static int loadkey(int kbdfd, keyentry *kep);
114 static int dupkey(int kbdfd, dupentry *dep, int shiftmask);
115 static int swapkey(int kbdfd, dupentry *dep, int shiftmask);
116 static int yylex();
117 extern int yyparse(void);
118 static int readesc(FILE *stream, int delim, int single_char);
119 static int wordcmp(const void *w1, const void *w2);
120 static int yyerror(char *msg);
121 static void usage(void);
122 static void set_layout(char *arg);
123 static FILE *open_mapping_file(char *pathbuf, char *name,
124 boolean_t explicit_name, int type);
125
126 int
127 main(int argc, char **argv)
128 {
129 int kbdfd;
130 int type;
131 int layout;
132 /* maxint is 8 hex digits. */
133 char layout_filename[sizeof(layout_prefix)+8];
134 char pathbuf[MAXPATHLEN];
135 int shift;
136 struct kiockeymap mapentry;
137 keyentry *kep;
138 dupentry *dep;
139 boolean_t explicit_name;
140
141 while(++argv, --argc) {
142 if(argv[0][0] != '-') break;
143 switch(argv[0][1]) {
144 case 'e':
145 /* -e obsolete, silently ignore */
146 break;
147 case 's':
148 if (argc != 2) {
149 usage();
150 /* NOTREACHED */
151 }
152 set_layout(argv[1]);
153 exit(0);
154 default:
155 usage();
156 /* NOTREACHED */
157 }
158 }
297 }
298
299 if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
300 perror("/dev/kbd");
301 exit(1);
302 }
303
304 ret = ioctl(kbdfd, KIOCSLAYOUT, layout);
305 if (ret == -1) {
306 perror("KIOCSLAYOUT");
307 }
308
309 close(kbdfd);
310 }
311
312 /*
313 * Attempt to find the specified mapping file. Return a FILE * if found,
314 * else print a message on stderr and return NULL.
315 */
316 FILE *
317 open_mapping_file(char *pathbuf, char *name, boolean_t explicit_name, int type)
318 {
319 /* If the user specified the name, try it "raw". */
320 if (explicit_name) {
321 strcpy(pathbuf, name);
322 infile = fopen(pathbuf, "r");
323 if (infile) return (infile);
324 if (errno != ENOENT) goto fopen_fail;
325 }
326
327 /* Everything after this point applies only to relative names. */
328 if (*name == '/') goto fopen_fail;
329
330 /* Try the type-qualified directory name. */
331 sprintf(pathbuf, keytable_dir, type);
332 if ((int)(strlen(pathbuf) + strlen(name) + 1) >= MAXPATHLEN) {
333 (void) fprintf(stderr, "loadkeys: Name %s is too long\n",
334 name);
335 return (NULL);
336 }
337 (void) strcat(pathbuf, name);
338 if ((infile = fopen(pathbuf, "r")) != NULL)
339 return (infile);
340
341 fopen_fail:
342 (void) fprintf(stderr, "loadkeys: ");
343 perror(name);
344 return (NULL);
345 }
346
347 /*
348 * We have a list of entries for a given keystation, and the keystation number
349 * for that keystation; put that keystation number into all the entries in that
350 * list, and chain that list to the end of the main list of entries.
351 */
352 static void
353 enter_mapentry(station, entrylistp)
354 int station;
355 keyentry *entrylistp;
356 {
357 register keyentry *kep;
358
359 if (lastentry == NULL)
360 firstentry = entrylistp;
370 kep = kep->ke_next;
371 }
372 }
373
374 /*
375 * Allocate and fill in a new entry.
376 */
377 static keyentry *
378 makeentry(tablemask, entry)
379 int tablemask;
380 int entry;
381 {
382 register keyentry *kep;
383 register int index;
384
385 if ((kep = (keyentry *) malloc((unsigned)sizeof (keyentry))) == NULL)
386 yyerror("out of memory for entries");
387 kep->ke_next = NULL;
388 kep->ke_entry.kio_tablemask = tablemask;
389 kep->ke_entry.kio_station = 0;
390 kep->ke_entry.kio_entry = entry;
391 index = entry - STRING;
392 if (index >= 0 && index <= 15)
393 (void) strncpy(kep->ke_entry.kio_string, strings[index],
394 KTAB_STRLEN);
395 return (kep);
396 }
397
398 /*
399 * Make a set of entries for a keystation that indicate that that keystation's
400 * settings should be copied from another keystation's settings.
401 */
402 static void
403 duplicate_mapentry(station, otherstation)
404 int station;
405 int otherstation;
406 {
407 register dupentry *dep;
408
409 if ((dep = (dupentry *) malloc((unsigned)sizeof (dupentry))) == NULL)
410 yyerror("out of memory for entries");
569 $$ = $1;
570 }
571 ;
572
573 entry:
574 TABLENAME code
575 {
576 $$ = makeentry($1, $2);
577 }
578 ;
579
580 code:
581 CHARSTRING
582 {
583 $$ = $1;
584 }
585 | CHAR
586 {
587 $$ = $1;
588 }
589 | INT
590 {
591 $$ = $1;
592 }
593 | '('
594 {
595 $$ = '(';
596 }
597 | ')'
598 {
599 $$ = ')';
600 }
601 | '+'
602 {
603 $$ = '+';
604 }
605 | expr
606 {
607 $$ = $1;
608 }
609 ;
610
611 expr:
612 term
656
657 /*
658 * Table must be in alphabetical order.
659 */
660 word_t wordtab[] = {
661 { "all", TABLENAME, ALL },
662 { "alt", CONSTANT, ALT },
663 { "altg", TABLENAME, ALTGRAPHMASK },
664 { "altgraph", CONSTANT, ALTGRAPH },
665 { "as", AS, 0 },
666 { "base", TABLENAME, 0 },
667 { "bf", FKEY, BOTTOMFUNC },
668 { "buckybits", CONSTANT, BUCKYBITS },
669 { "caps", TABLENAME, CAPSMASK },
670 { "capslock", CONSTANT, CAPSLOCK },
671 { "compose", CONSTANT, COMPOSE },
672 { "ctrl", TABLENAME, CTRLMASK },
673 { "downarrow", CONSTANT, DOWNARROW },
674 { "error", CONSTANT, ERROR },
675 { "fa_acute", CONSTANT, FA_ACUTE },
676 { "fa_apostrophe", CONSTANT, FA_APOSTROPHE },
677 { "fa_breve", CONSTANT, FA_BREVE },
678 { "fa_caron", CONSTANT, FA_CARON },
679 { "fa_cedilla", CONSTANT, FA_CEDILLA },
680 { "fa_cflex", CONSTANT, FA_CFLEX },
681 { "fa_dacute", CONSTANT, FA_DACUTE },
682 { "fa_dot", CONSTANT, FA_DOT },
683 { "fa_grave", CONSTANT, FA_GRAVE },
684 { "fa_macron", CONSTANT, FA_MACRON },
685 { "fa_ogonek", CONSTANT, FA_OGONEK },
686 { "fa_ring", CONSTANT, FA_RING },
687 { "fa_slash", CONSTANT, FA_SLASH },
688 { "fa_tilde", CONSTANT, FA_TILDE },
689 { "fa_umlaut", CONSTANT, FA_UMLAUT },
690 { "hole", CONSTANT, HOLE },
691 { "homearrow", CONSTANT, HOMEARROW },
692 { "idle", CONSTANT, IDLE },
693 { "key", KEY, 0 },
694 { "leftarrow", CONSTANT, LEFTARROW },
695 { "leftctrl", CONSTANT, LEFTCTRL },
696 { "leftshift", CONSTANT, LEFTSHIFT },
697 { "lf", FKEY, LEFTFUNC },
698 { "metabit", CONSTANT, METABIT },
699 { "nonl", CONSTANT, NONL },
700 { "nop", CONSTANT, NOP },
701 { "numl", TABLENAME, NUMLOCKMASK },
702 { "numlock", CONSTANT, NUMLOCK },
703 { "oops", CONSTANT, OOPS },
704 { "pad0", CONSTANT, PAD0 },
705 { "pad1", CONSTANT, PAD1 },
706 { "pad2", CONSTANT, PAD2 },
707 { "pad3", CONSTANT, PAD3 },
868 } else if (strlen(tokbuf) == 2 && tokbuf[0] == '^') {
869 tokentype = CHAR;
870 yylval.number = (unsigned char)(tokbuf[1] & 037);
871 } else {
872 word_t word;
873 register word_t *wptr;
874 char *ptr;
875
876 for (cp = &tokbuf[0]; (c = *cp) != '\0'; cp++) {
877 if (isupper(c))
878 *cp = tolower(c);
879 }
880 word.w_string = tokbuf;
881 wptr = (word_t *)bsearch((char *)&word,
882 (char *)wordtab, NWORDS, sizeof (word_t),
883 wordcmp);
884 if (wptr != NULL) {
885 yylval.number = wptr->w_lval;
886 tokentype = wptr->w_type;
887 } else {
888 yylval.number = strtol(tokbuf, &ptr, 0);
889 if (ptr == tokbuf)
890 yyerror("syntax error");
891 else
892 tokentype = INT;
893 }
894 break;
895 }
896 }
897
898 return (tokentype);
899 }
900
901 static int
902 readesc(stream, delim, single_char)
903 FILE *stream;
904 int delim;
905 int single_char;
906 {
907 register int c;
908 register int val;
|