xref: /illumos-gate/usr/src/cmd/loadkeys/dumpkeys.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 #ifndef lint
23 #ident	"%Z%%M%	%I%	%E% SMI"
24 #endif
25 
26 /*
27  * Copyright (c) 1988 by Sun Microsystems, Inc.
28  */
29 
30 #include <sys/types.h>
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <sys/kbd.h>
35 #include <sys/kbio.h>
36 #include <errno.h>
37 
38 typedef enum {
39 	SM_INVALID,	/* this shift mask is invalid for this keyboard */
40 	SM_NORMAL,	/* "normal", valid shift mask */
41 	SM_NUMLOCK,	/* "Num Lock" shift mask */
42 	SM_UP		/* "Up" shift mask */
43 } smtype_t;
44 
45 typedef struct {
46 	char	*sm_name;
47 	int	sm_mask;
48 	smtype_t sm_type;
49 } smentry_t;
50 
51 
52 smentry_t shiftmasks[] = {
53 	{ "base",	0,		SM_NORMAL },
54 	{ "shift",	SHIFTMASK,	SM_NORMAL },
55 	{ "caps",	CAPSMASK,	SM_NORMAL },
56 	{ "ctrl",	CTRLMASK,	SM_NORMAL },
57 	{ "altg",	ALTGRAPHMASK,	SM_NORMAL },
58 	{ "numl",	NUMLOCKMASK,	SM_NUMLOCK },
59 	{ "up",		UPMASK,		SM_UP },
60 };
61 
62 #define	NSHIFTS	(sizeof (shiftmasks) / sizeof (shiftmasks[0]))
63 
64 static void	printentry(struct kiockeymap *kio);
65 static void	printchar(int character, int delim);
66 
67 /*ARGSUSED*/
68 int
69 main(argc, argv)
70 	int argc;
71 	char **argv;
72 {
73 	register int kbdfd;
74 	register int keystation;
75 	register int shift;
76 	int ktype;
77 	struct kiockeymap keyentry[NSHIFTS];
78 	register int allsame;
79 
80 	if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
81 		perror("dumpkeys: /dev/kbd");
82 		return (1);
83 	}
84 	if (ioctl(kbdfd, KIOCTYPE, &ktype) < 0) {
85 		perror("dumpkeys: ioctl(KIOCTYPE)");
86 		return (1);
87 	}
88 	/* if no keyboard detected, or ascii terminal, exit silently */
89 	if (ktype == KB_ASCII || ktype < 0)
90 		exit(0);
91 
92 	/*
93 	 * See which shift masks are valid for this keyboard.
94 	 * We do that by trying to get the entry for keystation 0 and that
95 	 * shift mask; if the "ioctl" fails, we assume it's because the shift
96 	 * mask is invalid.
97 	 */
98 	for (shift = 0; shift < NSHIFTS; shift++) {
99 		keyentry[shift].kio_tablemask =
100 		    shiftmasks[shift].sm_mask;
101 		keyentry[shift].kio_station = 0;
102 		if (ioctl(kbdfd, KIOCGKEY, &keyentry[shift]) < 0)
103 			shiftmasks[shift].sm_type = SM_INVALID;
104 	}
105 
106 	/*
107 	 * Loop until we get an EINVAL, so we don't have to know
108 	 * how big the table might be.
109 	 */
110 	for (keystation = 0; ; keystation++) {
111 		for (shift = 0; shift < NSHIFTS; shift++) {
112 			if (shiftmasks[shift].sm_type != SM_INVALID) {
113 				keyentry[shift].kio_tablemask =
114 				    shiftmasks[shift].sm_mask;
115 				keyentry[shift].kio_station = keystation;
116 				if (ioctl(kbdfd, KIOCGKEY,
117 				    &keyentry[shift]) < 0) {
118 					if (errno == EINVAL)
119 						return (0);
120 					perror("dumpkeys: KIOCGKEY");
121 					return (1);
122 				}
123 			}
124 		}
125 
126 		(void) printf("key %d\t", keystation);
127 
128 		/*
129 		 * See if all the "normal" entries (all but the Num Lock and Up
130 		 * entries) are the same.
131 		 */
132 		allsame = 1;
133 		for (shift = 1; shift < NSHIFTS; shift++) {
134 			if (shiftmasks[shift].sm_type == SM_NORMAL) {
135 				if (keyentry[0].kio_entry
136 				    != keyentry[shift].kio_entry) {
137 					allsame = 0;
138 					break;
139 				}
140 			}
141 		}
142 
143 		if (allsame) {
144 			/*
145 			 * All of the "normal" entries are the same; just print
146 			 * "all".
147 			 */
148 			(void) printf(" all ");
149 			printentry(&keyentry[0]);
150 		} else {
151 			/*
152 			 * The normal entries aren't all the same; print them
153 			 * individually.
154 			 */
155 			for (shift = 0; shift < NSHIFTS; shift++) {
156 				if (shiftmasks[shift].sm_type == SM_NORMAL) {
157 					(void) printf(" %s ",
158 					    shiftmasks[shift].sm_name);
159 					printentry(&keyentry[shift]);
160 				}
161 			}
162 		}
163 		if (allsame && keyentry[0].kio_entry == HOLE) {
164 			/*
165 			 * This key is a "hole"; if either the Num Lock or Up
166 			 * entry isn't a "hole", print it.
167 			 */
168 			for (shift = 0; shift < NSHIFTS; shift++) {
169 				switch (shiftmasks[shift].sm_type) {
170 
171 				case SM_NUMLOCK:
172 				case SM_UP:
173 					if (keyentry[shift].kio_entry
174 					    != HOLE) {
175 						(void) printf(" %s ",
176 						    shiftmasks[shift].sm_name);
177 						printentry(&keyentry[shift]);
178 					}
179 					break;
180 				}
181 			}
182 		} else {
183 			/*
184 			 * This entry isn't a "hole"; if the Num Lock entry
185 			 * isn't NONL (i.e, if Num Lock actually does
186 			 * something) print it, and if the Up entry isn't NOP
187 			 * (i.e., if up transitions on this key actually do
188 			 * something) print it.
189 			 */
190 			for (shift = 0; shift < NSHIFTS; shift++) {
191 				switch (shiftmasks[shift].sm_type) {
192 
193 				case SM_NUMLOCK:
194 					if (keyentry[shift].kio_entry
195 					    != NONL) {
196 						(void) printf(" %s ",
197 						    shiftmasks[shift].sm_name);
198 						printentry(&keyentry[shift]);
199 					}
200 					break;
201 
202 				case SM_UP:
203 					if (keyentry[shift].kio_entry
204 					    != NOP) {
205 						(void) printf(" %s ",
206 						    shiftmasks[shift].sm_name);
207 						printentry(&keyentry[shift]);
208 					}
209 					break;
210 				}
211 			}
212 		}
213 		(void) printf("\n");
214 	}
215 }
216 
217 static char *shiftkeys[] = {
218 	"capslock",
219 	"shiftlock",
220 	"leftshift",
221 	"rightshift",
222 	"leftctrl",
223 	"rightctrl",
224 	"meta",			/* not used */
225 	"top",			/* not used */
226 	"cmd",			/* reserved */
227 	"altgraph",
228 	"alt",
229 	"numlock",
230 };
231 
232 #define	NSHIFTKEYS	(sizeof (shiftkeys) / sizeof (shiftkeys[0]))
233 
234 static char *buckybits[] = {
235 	"metabit",
236 	"systembit",
237 };
238 
239 #define	NBUCKYBITS	(sizeof (buckybits) / sizeof (buckybits[0]))
240 
241 static char *funnies[] = {
242 	"nop",
243 	"oops",
244 	"hole",
245 	"reset",
246 	"error",
247 	"idle",
248 	"compose",
249 	"nonl",
250 };
251 
252 #define	NFUNNIES	(sizeof (funnies) / sizeof (funnies[0]))
253 
254 static char *fa_class[] = {
255 	"fa_umlaut",
256 	"fa_cflex",
257 	"fa_tilde",
258 	"fa_cedilla",
259 	"fa_acute",
260 	"fa_grave",
261 };
262 
263 #define	NFA_CLASS	(sizeof (fa_class) / sizeof (fa_class[0]))
264 
265 typedef struct {
266 	char	*string;
267 	char	*name;
268 } builtin_string_t;
269 
270 builtin_string_t builtin_strings[] = {
271 	{ "\033[H",	"homearrow" },
272 	{ "\033[A",	"uparrow" },
273 	{ "\033[B",	"downarrow" },
274 	{ "\033[D",	"leftarrow" },
275 	{ "\033[C",	"rightarrow" },
276 };
277 
278 #define	NBUILTIN_STRINGS	(sizeof (builtin_strings) / \
279 					sizeof (builtin_strings[0]))
280 
281 static char	*fkeysets[] = {
282 	"lf",
283 	"rf",
284 	"tf",
285 	"bf",
286 };
287 
288 #define	NFKEYSETS	(sizeof (fkeysets) / sizeof (fkeysets[0]))
289 
290 static char	*padkeys[] = {
291 	"padequal",
292 	"padslash",
293 	"padstar",
294 	"padminus",
295 	"padsep",
296 	"pad7",
297 	"pad8",
298 	"pad9",
299 	"padplus",
300 	"pad4",
301 	"pad5",
302 	"pad6",
303 	"pad1",
304 	"pad2",
305 	"pad3",
306 	"pad0",
307 	"paddot",
308 	"padenter",
309 };
310 
311 #define	NPADKEYS	(sizeof (padkeys) / sizeof (padkeys[0]))
312 
313 static void
314 printentry(kio)
315 	register struct kiockeymap *kio;
316 {
317 	register int entry = (kio->kio_entry & 0x1F);
318 	register int fkeyset;
319 	register int i;
320 	register int c;
321 
322 	switch (kio->kio_entry >> 8) {
323 
324 	case 0x0:
325 		if (kio->kio_entry == '"')
326 			(void) printf("'\"'");	/* special case */
327 		else if (kio->kio_entry == ' ')
328 			(void) printf("' '");	/* special case */
329 		else
330 			printchar((int)kio->kio_entry, '\'');
331 		break;
332 
333 	case SHIFTKEYS >> 8:
334 		if (entry < NSHIFTKEYS)
335 			(void) printf("shiftkeys+%s", shiftkeys[entry]);
336 		else
337 			(void) printf("%#4x", kio->kio_entry);
338 		break;
339 
340 	case BUCKYBITS >> 8:
341 		if (entry < NBUCKYBITS)
342 			(void) printf("buckybits+%s", buckybits[entry]);
343 		else
344 			(void) printf("%#4x", kio->kio_entry);
345 		break;
346 
347 	case FUNNY >> 8:
348 		if (entry < NFUNNIES)
349 			(void) printf("%s", funnies[entry]);
350 		else
351 			(void) printf("%#4x", kio->kio_entry);
352 		break;
353 
354 	case FA_CLASS >> 8:
355 		if (entry < NFA_CLASS)
356 			(void) printf("%s", fa_class[entry]);
357 		else
358 			(void) printf("%#4x", kio->kio_entry);
359 		break;
360 
361 	case STRING >> 8:
362 		if (entry < NBUILTIN_STRINGS && strncmp(kio->kio_string,
363 			builtin_strings[entry].string, KTAB_STRLEN) == 0)
364 			(void) printf("string+%s", builtin_strings[entry].name);
365 		else {
366 			(void) printf("\"");
367 			for (i = 0;
368 			    i < KTAB_STRLEN && (c = kio->kio_string[i]) != '\0';
369 			    i++)
370 				printchar(c, '"');
371 			(void) printf("\"");
372 		}
373 		break;
374 
375 	case FUNCKEYS >> 8:
376 		fkeyset = (int)(kio->kio_entry & 0xF0) >> 4;
377 		if (fkeyset < NFKEYSETS)
378 			(void) printf("%s(%d)", fkeysets[fkeyset],
379 					(entry&0x0F) + 1);
380 		else
381 			(void) printf("%#4x", kio->kio_entry);
382 		break;
383 
384 	case PADKEYS >> 8:
385 		if (entry < NPADKEYS)
386 			(void) printf("%s", padkeys[entry]);
387 		else
388 			(void) printf("%#4x", kio->kio_entry);
389 		break;
390 
391 	default:
392 		(void) printf("%#4x", kio->kio_entry);
393 		break;
394 	}
395 }
396 
397 static void
398 printchar(character, delim)
399 	int character;
400 	int delim;
401 {
402 	switch (character) {
403 
404 	case '\n':
405 		(void) printf("'\\n'");
406 		break;
407 
408 	case '\t':
409 		(void) printf("'\\t'");
410 		break;
411 
412 	case '\b':
413 		(void) printf("'\\b'");
414 		break;
415 
416 	case '\r':
417 		(void) printf("'\\r'");
418 		break;
419 
420 	case '\v':
421 		(void) printf("'\\v'");
422 		break;
423 
424 	case '\\':
425 		(void) printf("'\\\\'");
426 		break;
427 
428 	default:
429 		if (isprint(character)) {
430 			if (character == delim)
431 				(void) printf("'\\'");
432 			(void) printf("%c", character);
433 		} else {
434 			if (character < 040)
435 				(void) printf("^%c", character + 0100);
436 			else
437 				(void) printf("'\\%.3o'", character);
438 		}
439 		break;
440 	}
441 }
442