xref: /freebsd/usr.sbin/kbdcontrol/kbdcontrol.c (revision f65c19a242de322930f6a1cd7d5e6bf3ce19ce42)
108bddad1SSøren Schmidt /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4f76b3199SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
508bddad1SSøren Schmidt  * All rights reserved.
608bddad1SSøren Schmidt  *
708bddad1SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
808bddad1SSøren Schmidt  * modification, are permitted provided that the following conditions
908bddad1SSøren Schmidt  * are met:
1008bddad1SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
11a926a37bSSøren Schmidt  *    notice, this list of conditions and the following disclaimer,
12a926a37bSSøren Schmidt  *    in this position and unchanged.
1308bddad1SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
1408bddad1SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
1508bddad1SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
1608bddad1SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
1721dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
1808bddad1SSøren Schmidt  *
1908bddad1SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2008bddad1SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2108bddad1SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2208bddad1SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2308bddad1SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2408bddad1SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2508bddad1SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2608bddad1SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2708bddad1SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2808bddad1SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2908bddad1SSøren Schmidt  */
3008bddad1SSøren Schmidt 
31b728350eSDavid E. O'Brien #include <sys/cdefs.h>
3208bddad1SSøren Schmidt #include <ctype.h>
332976d54bSPhilippe Charnier #include <err.h>
3408bddad1SSøren Schmidt #include <stdio.h>
352976d54bSPhilippe Charnier #include <stdlib.h>
36be0856f8SSteven Wallace #include <string.h>
372976d54bSPhilippe Charnier #include <unistd.h>
38c67e8bd3SKazutaka YOKOTA #include <fcntl.h>
3900d25f51SPoul-Henning Kamp #include <sys/kbio.h>
4000d25f51SPoul-Henning Kamp #include <sys/consio.h>
41971bac5aSMichael #include <sys/param.h>
428c0d1b47SEd Maste #include <sys/queue.h>
432f11ee62SAleksandr Rybalko #include <sys/sysctl.h>
4408bddad1SSøren Schmidt #include "path.h"
4508bddad1SSøren Schmidt #include "lex.h"
4608bddad1SSøren Schmidt 
47daf4075aSEd Schouten #define	SPECIAL		0x80000000
48daf4075aSEd Schouten 
49968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
504d9a3537SEd Schouten static const char ctrl_names[32][4] = {
5108bddad1SSøren Schmidt 	"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
5208bddad1SSøren Schmidt 	"bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ",
5308bddad1SSøren Schmidt 	"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
54b897510fSKazutaka YOKOTA 	"can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us "
5508bddad1SSøren Schmidt 	};
56968a3db7SJessica Clarke #endif
5708bddad1SSøren Schmidt 
584d9a3537SEd Schouten static const char acc_names[15][5] = {
591f150ac4SKazutaka YOKOTA 	"dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot",
601f150ac4SKazutaka YOKOTA 	"duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo",
611f150ac4SKazutaka YOKOTA 	"dcar",
621f150ac4SKazutaka YOKOTA 	};
631f150ac4SKazutaka YOKOTA 
644d9a3537SEd Schouten static const char acc_names_u[15][5] = {
651f150ac4SKazutaka YOKOTA 	"DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT",
661f150ac4SKazutaka YOKOTA 	"DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO",
671f150ac4SKazutaka YOKOTA 	"DCAR",
681f150ac4SKazutaka YOKOTA 	};
691f150ac4SKazutaka YOKOTA 
70968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
714d9a3537SEd Schouten static const char fkey_table[96][MAXFK] = {
72a926a37bSSøren Schmidt /* 01-04 */	"\033[M", "\033[N", "\033[O", "\033[P",
73a926a37bSSøren Schmidt /* 05-08 */	"\033[Q", "\033[R", "\033[S", "\033[T",
74a926a37bSSøren Schmidt /* 09-12 */	"\033[U", "\033[V", "\033[W", "\033[X",
75a926a37bSSøren Schmidt /* 13-16 */	"\033[Y", "\033[Z", "\033[a", "\033[b",
76a926a37bSSøren Schmidt /* 17-20 */	"\033[c", "\033[d", "\033[e", "\033[f",
77a926a37bSSøren Schmidt /* 21-24 */	"\033[g", "\033[h", "\033[i", "\033[j",
78a926a37bSSøren Schmidt /* 25-28 */	"\033[k", "\033[l", "\033[m", "\033[n",
79a926a37bSSøren Schmidt /* 29-32 */	"\033[o", "\033[p", "\033[q", "\033[r",
80a926a37bSSøren Schmidt /* 33-36 */	"\033[s", "\033[t", "\033[u", "\033[v",
81a926a37bSSøren Schmidt /* 37-40 */	"\033[w", "\033[x", "\033[y", "\033[z",
82a926a37bSSøren Schmidt /* 41-44 */	"\033[@", "\033[[", "\033[\\","\033[]",
83d3628763SRodney W. Grimes /* 45-48 */     "\033[^", "\033[_", "\033[`", "\033[{",
84a926a37bSSøren Schmidt /* 49-52 */	"\033[H", "\033[A", "\033[I", "-"     ,
85a926a37bSSøren Schmidt /* 53-56 */	"\033[D", "\033[E", "\033[C", "+"     ,
86a926a37bSSøren Schmidt /* 57-60 */	"\033[F", "\033[B", "\033[G", "\033[L",
87d3628763SRodney W. Grimes /* 61-64 */     "\177",   "\033[J", "\033[~", "\033[}",
88a926a37bSSøren Schmidt /* 65-68 */	""      , ""      , ""      , ""      ,
89a926a37bSSøren Schmidt /* 69-72 */	""      , ""      , ""      , ""      ,
90a926a37bSSøren Schmidt /* 73-76 */	""      , ""      , ""      , ""      ,
91a926a37bSSøren Schmidt /* 77-80 */	""      , ""      , ""      , ""      ,
92a926a37bSSøren Schmidt /* 81-84 */	""      , ""      , ""      , ""      ,
93a926a37bSSøren Schmidt /* 85-88 */	""      , ""      , ""      , ""      ,
94a926a37bSSøren Schmidt /* 89-92 */	""      , ""      , ""      , ""      ,
95a926a37bSSøren Schmidt /* 93-96 */	""      , ""      , ""      , ""      ,
9608bddad1SSøren Schmidt 	};
97968a3db7SJessica Clarke #endif
9808bddad1SSøren Schmidt 
99968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
100971bac5aSMichael static const int ndelays = nitems(kbdelays);
101971bac5aSMichael static const int nrepeats = nitems(kbrates);
1024d9a3537SEd Schouten static int	hex = 0;
103968a3db7SJessica Clarke #endif
1048c0d1b47SEd Maste static int	paths_configured = 0;
1054d9a3537SEd Schouten static int	token;
1064d9a3537SEd Schouten 
10700e0cb65SSøren Schmidt int		number;
10808bddad1SSøren Schmidt char		letter;
10908bddad1SSøren Schmidt 
1108c0d1b47SEd Maste static void	add_keymap_path(const char *path);
1114d9a3537SEd Schouten static void	dump_accent_definition(char *name, accentmap_t *accentmap);
1124d9a3537SEd Schouten static void	dump_entry(int value);
1134d9a3537SEd Schouten static void	dump_key_definition(char *name, keymap_t *keymap);
1144d9a3537SEd Schouten static int	get_accent_definition_line(accentmap_t *);
1154d9a3537SEd Schouten static int	get_entry(void);
1164d9a3537SEd Schouten static int	get_key_definition_line(keymap_t *);
1174d9a3537SEd Schouten static void	load_keymap(char *opt, int dumponly);
118968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
1194d9a3537SEd Schouten static void	load_default_functionkeys(void);
120968a3db7SJessica Clarke #endif
1214d9a3537SEd Schouten static char *	nextarg(int ac, char **av, int *indp, int oc);
1224d9a3537SEd Schouten static char *	mkfullname(const char *s1, const char *s2, const char *s3);
123968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
1244d9a3537SEd Schouten static void	print_accent_definition_line(FILE *fp, int accent,
1254f5d9133SAlfred Perlstein 		struct acc_t *key);
1264d9a3537SEd Schouten static void	print_entry(FILE *fp, int value);
1274d9a3537SEd Schouten static void	print_key_definition_line(FILE *fp, int scancode,
1284f5d9133SAlfred Perlstein 		struct keyent_t *key);
1294d9a3537SEd Schouten static void	print_keymap(void);
1304d9a3537SEd Schouten static void	release_keyboard(void);
1314d9a3537SEd Schouten static void	mux_keyboard(u_int op, char *kbd);
1324d9a3537SEd Schouten static void	set_bell_values(char *opt);
1334d9a3537SEd Schouten static void	set_functionkey(char *keynumstr, char *string);
1344d9a3537SEd Schouten static void	set_keyboard(char *device);
1354d9a3537SEd Schouten static void	set_keyrates(char *opt);
1364d9a3537SEd Schouten static void	show_kbd_info(void);
137968a3db7SJessica Clarke #endif
1384d9a3537SEd Schouten static void	usage(void) __dead2;
13908bddad1SSøren Schmidt 
1408c0d1b47SEd Maste struct pathent {
1418c0d1b47SEd Maste 	STAILQ_ENTRY(pathent) next;
1428c0d1b47SEd Maste 	char *path;
1438c0d1b47SEd Maste };
1448c0d1b47SEd Maste static STAILQ_HEAD(, pathent) pathlist = STAILQ_HEAD_INITIALIZER(pathlist);
1458c0d1b47SEd Maste 
146968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
1472f11ee62SAleksandr Rybalko /* Detect presence of vt(4). */
1482f11ee62SAleksandr Rybalko static int
is_vt4(void)1492f11ee62SAleksandr Rybalko is_vt4(void)
1502f11ee62SAleksandr Rybalko {
1516c79f788SEd Maste 	char vty_name[4] = "";
1526c79f788SEd Maste 	size_t len = sizeof(vty_name);
1532f11ee62SAleksandr Rybalko 
1546c79f788SEd Maste 	if (sysctlbyname("kern.vty", vty_name, &len, NULL, 0) != 0)
1552f11ee62SAleksandr Rybalko 		return (0);
1566c79f788SEd Maste 	return (strcmp(vty_name, "vt") == 0);
1572f11ee62SAleksandr Rybalko }
158968a3db7SJessica Clarke #endif
1592f11ee62SAleksandr Rybalko 
1604d9a3537SEd Schouten static char *
nextarg(int ac,char ** av,int * indp,int oc)16108bddad1SSøren Schmidt nextarg(int ac, char **av, int *indp, int oc)
16208bddad1SSøren Schmidt {
16308bddad1SSøren Schmidt 	if (*indp < ac)
16408bddad1SSøren Schmidt 		return(av[(*indp)++]);
1652976d54bSPhilippe Charnier 	warnx("option requires two arguments -- %c", oc);
16608bddad1SSøren Schmidt 	usage();
16708bddad1SSøren Schmidt }
16808bddad1SSøren Schmidt 
16908bddad1SSøren Schmidt 
1704d9a3537SEd Schouten static char *
mkfullname(const char * s1,const char * s2,const char * s3)17108bddad1SSøren Schmidt mkfullname(const char *s1, const char *s2, const char *s3)
17208bddad1SSøren Schmidt {
17308bddad1SSøren Schmidt 	static char	*buf = NULL;
17408bddad1SSøren Schmidt 	static int	bufl = 0;
17508bddad1SSøren Schmidt 	int		f;
17608bddad1SSøren Schmidt 
17708bddad1SSøren Schmidt 	f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
17813edc254SMaxim Sobolev 	if (f > bufl) {
17908bddad1SSøren Schmidt 		if (buf)
18008bddad1SSøren Schmidt 			buf = (char *)realloc(buf, f);
18108bddad1SSøren Schmidt 		else
18208bddad1SSøren Schmidt 			buf = (char *)malloc(f);
18313edc254SMaxim Sobolev 	}
18408bddad1SSøren Schmidt 	if (!buf) {
18508bddad1SSøren Schmidt 		bufl = 0;
18608bddad1SSøren Schmidt 		return(NULL);
18708bddad1SSøren Schmidt 	}
18808bddad1SSøren Schmidt 
18908bddad1SSøren Schmidt 	bufl = f;
19008bddad1SSøren Schmidt 	strcpy(buf, s1);
19108bddad1SSøren Schmidt 	strcat(buf, s2);
19208bddad1SSøren Schmidt 	strcat(buf, s3);
19308bddad1SSøren Schmidt 	return(buf);
19408bddad1SSøren Schmidt }
19508bddad1SSøren Schmidt 
19608bddad1SSøren Schmidt 
1974d9a3537SEd Schouten static int
get_entry(void)1984f5d9133SAlfred Perlstein get_entry(void)
19908bddad1SSøren Schmidt {
2001f150ac4SKazutaka YOKOTA 	switch ((token = yylex())) {
20108bddad1SSøren Schmidt 	case TNOP:
202daf4075aSEd Schouten 		return NOP | SPECIAL;
20308bddad1SSøren Schmidt 	case TLSH:
204daf4075aSEd Schouten 		return LSH | SPECIAL;
20508bddad1SSøren Schmidt 	case TRSH:
206daf4075aSEd Schouten 		return RSH | SPECIAL;
20708bddad1SSøren Schmidt 	case TCLK:
208daf4075aSEd Schouten 		return CLK | SPECIAL;
20908bddad1SSøren Schmidt 	case TNLK:
210daf4075aSEd Schouten 		return NLK | SPECIAL;
21108bddad1SSøren Schmidt 	case TSLK:
212daf4075aSEd Schouten 		return SLK | SPECIAL;
21308bddad1SSøren Schmidt 	case TBTAB:
214daf4075aSEd Schouten 		return BTAB | SPECIAL;
21508bddad1SSøren Schmidt 	case TLALT:
216daf4075aSEd Schouten 		return LALT | SPECIAL;
21708bddad1SSøren Schmidt 	case TLCTR:
218daf4075aSEd Schouten 		return LCTR | SPECIAL;
21908bddad1SSøren Schmidt 	case TNEXT:
220daf4075aSEd Schouten 		return NEXT | SPECIAL;
221ac80d4b4SKazutaka YOKOTA 	case TPREV:
222daf4075aSEd Schouten 		return PREV | SPECIAL;
22308bddad1SSøren Schmidt 	case TRCTR:
224daf4075aSEd Schouten 		return RCTR | SPECIAL;
22508bddad1SSøren Schmidt 	case TRALT:
226daf4075aSEd Schouten 		return RALT | SPECIAL;
22708bddad1SSøren Schmidt 	case TALK:
228daf4075aSEd Schouten 		return ALK | SPECIAL;
22908bddad1SSøren Schmidt 	case TASH:
230daf4075aSEd Schouten 		return ASH | SPECIAL;
23108bddad1SSøren Schmidt 	case TMETA:
232daf4075aSEd Schouten 		return META | SPECIAL;
23308bddad1SSøren Schmidt 	case TRBT:
234daf4075aSEd Schouten 		return RBT | SPECIAL;
23508bddad1SSøren Schmidt 	case TDBG:
236daf4075aSEd Schouten 		return DBG | SPECIAL;
237a926a37bSSøren Schmidt 	case TSUSP:
238daf4075aSEd Schouten 		return SUSP | SPECIAL;
23928d2c691SKazutaka YOKOTA 	case TSPSC:
240daf4075aSEd Schouten 		return SPSC | SPECIAL;
24152990a39SKazutaka YOKOTA 	case TPANIC:
242daf4075aSEd Schouten 		return PNC | SPECIAL;
24352990a39SKazutaka YOKOTA 	case TLSHA:
244daf4075aSEd Schouten 		return LSHA | SPECIAL;
24552990a39SKazutaka YOKOTA 	case TRSHA:
246daf4075aSEd Schouten 		return RSHA | SPECIAL;
24752990a39SKazutaka YOKOTA 	case TLCTRA:
248daf4075aSEd Schouten 		return LCTRA | SPECIAL;
24952990a39SKazutaka YOKOTA 	case TRCTRA:
250daf4075aSEd Schouten 		return RCTRA | SPECIAL;
25152990a39SKazutaka YOKOTA 	case TLALTA:
252daf4075aSEd Schouten 		return LALTA | SPECIAL;
25352990a39SKazutaka YOKOTA 	case TRALTA:
254daf4075aSEd Schouten 		return RALTA | SPECIAL;
2551c06ce61SDavid Malone 	case THALT:
256daf4075aSEd Schouten 		return HALT | SPECIAL;
2571c06ce61SDavid Malone 	case TPDWN:
258daf4075aSEd Schouten 		return PDWN | SPECIAL;
2594629b5e0SAndrey A. Chernov 	case TPASTE:
260daf4075aSEd Schouten 		return PASTE | SPECIAL;
2611f150ac4SKazutaka YOKOTA 	case TACC:
2621f150ac4SKazutaka YOKOTA 		if (ACC(number) > L_ACC)
2631f150ac4SKazutaka YOKOTA 			return -1;
264daf4075aSEd Schouten 		return ACC(number) | SPECIAL;
26508bddad1SSøren Schmidt 	case TFUNC:
26608bddad1SSøren Schmidt 		if (F(number) > L_FN)
26708bddad1SSøren Schmidt 			return -1;
268daf4075aSEd Schouten 		return F(number) | SPECIAL;
26908bddad1SSøren Schmidt 	case TSCRN:
27008bddad1SSøren Schmidt 		if (S(number) > L_SCR)
27108bddad1SSøren Schmidt 			return -1;
272daf4075aSEd Schouten 		return S(number) | SPECIAL;
27308bddad1SSøren Schmidt 	case TLET:
27408bddad1SSøren Schmidt 		return (unsigned char)letter;
27508bddad1SSøren Schmidt 	case TNUM:
276b05f9c86SEd Schouten 		if (number < 0x000000 || number > 0x10FFFF)
27708bddad1SSøren Schmidt 			return -1;
27808bddad1SSøren Schmidt 		return number;
27908bddad1SSøren Schmidt 	default:
28008bddad1SSøren Schmidt 		return -1;
28108bddad1SSøren Schmidt 	}
28208bddad1SSøren Schmidt }
28308bddad1SSøren Schmidt 
28413edc254SMaxim Sobolev static int
get_definition_line(FILE * file,keymap_t * keymap,accentmap_t * accentmap)2858c0d1b47SEd Maste get_definition_line(FILE *file, keymap_t *keymap, accentmap_t *accentmap)
28608bddad1SSøren Schmidt {
2871f150ac4SKazutaka YOKOTA 	int c;
28808bddad1SSøren Schmidt 
2898c0d1b47SEd Maste 	yyin = file;
29008bddad1SSøren Schmidt 
2911f150ac4SKazutaka YOKOTA 	if (token < 0)
2921f150ac4SKazutaka YOKOTA 		token = yylex();
2931f150ac4SKazutaka YOKOTA 	switch (token) {
2941f150ac4SKazutaka YOKOTA 	case TNUM:
2951f150ac4SKazutaka YOKOTA 		c = get_key_definition_line(keymap);
2961f150ac4SKazutaka YOKOTA 		if (c < 0)
2971f150ac4SKazutaka YOKOTA 			errx(1, "invalid key definition");
2981f150ac4SKazutaka YOKOTA 		if (c > keymap->n_keys)
2991f150ac4SKazutaka YOKOTA 			keymap->n_keys = c;
3001f150ac4SKazutaka YOKOTA 		break;
3011f150ac4SKazutaka YOKOTA 	case TACC:
3021f150ac4SKazutaka YOKOTA 		c = get_accent_definition_line(accentmap);
3031f150ac4SKazutaka YOKOTA 		if (c < 0)
3041f150ac4SKazutaka YOKOTA 			errx(1, "invalid accent key definition");
3051f150ac4SKazutaka YOKOTA 		if (c > accentmap->n_accs)
3061f150ac4SKazutaka YOKOTA 			accentmap->n_accs = c;
3071f150ac4SKazutaka YOKOTA 		break;
3081f150ac4SKazutaka YOKOTA 	case 0:
3091f150ac4SKazutaka YOKOTA 		/* EOF */
31008bddad1SSøren Schmidt 		return -1;
3111f150ac4SKazutaka YOKOTA 	default:
3121f150ac4SKazutaka YOKOTA 		errx(1, "illegal definition line");
3131f150ac4SKazutaka YOKOTA 	}
3141f150ac4SKazutaka YOKOTA 	return c;
3151f150ac4SKazutaka YOKOTA }
3161f150ac4SKazutaka YOKOTA 
3174d9a3537SEd Schouten static int
get_key_definition_line(keymap_t * map)3181f150ac4SKazutaka YOKOTA get_key_definition_line(keymap_t *map)
3191f150ac4SKazutaka YOKOTA {
3201f150ac4SKazutaka YOKOTA 	int i, def, scancode;
3211f150ac4SKazutaka YOKOTA 
3221f150ac4SKazutaka YOKOTA 	/* check scancode number */
32308bddad1SSøren Schmidt 	if (number < 0 || number >= NUM_KEYS)
32408bddad1SSøren Schmidt 		return -1;
32508bddad1SSøren Schmidt 	scancode = number;
32608bddad1SSøren Schmidt 
32708bddad1SSøren Schmidt 	/* get key definitions */
32808bddad1SSøren Schmidt 	map->key[scancode].spcl = 0;
32908bddad1SSøren Schmidt 	for (i=0; i<NUM_STATES; i++) {
33008bddad1SSøren Schmidt 		if ((def = get_entry()) == -1)
33108bddad1SSøren Schmidt 			return -1;
332daf4075aSEd Schouten 		if (def & SPECIAL)
33308bddad1SSøren Schmidt 			map->key[scancode].spcl |= (0x80 >> i);
334daf4075aSEd Schouten 		map->key[scancode].map[i] = def & ~SPECIAL;
33508bddad1SSøren Schmidt 	}
33608bddad1SSøren Schmidt 	/* get lock state key def */
3371f150ac4SKazutaka YOKOTA 	if ((token = yylex()) != TFLAG)
33808bddad1SSøren Schmidt 		return -1;
33908bddad1SSøren Schmidt 	map->key[scancode].flgs = number;
3401f150ac4SKazutaka YOKOTA 	token = yylex();
3411f150ac4SKazutaka YOKOTA 	return (scancode + 1);
34208bddad1SSøren Schmidt }
34308bddad1SSøren Schmidt 
3444d9a3537SEd Schouten static int
get_accent_definition_line(accentmap_t * map)3451f150ac4SKazutaka YOKOTA get_accent_definition_line(accentmap_t *map)
3461f150ac4SKazutaka YOKOTA {
3471f150ac4SKazutaka YOKOTA 	int accent;
3481f150ac4SKazutaka YOKOTA 	int c1, c2;
3491f150ac4SKazutaka YOKOTA 	int i;
3501f150ac4SKazutaka YOKOTA 
3511f150ac4SKazutaka YOKOTA 	if (ACC(number) < F_ACC || ACC(number) > L_ACC)
3521f150ac4SKazutaka YOKOTA 		/* number out of range */
3531f150ac4SKazutaka YOKOTA 		return -1;
3541f150ac4SKazutaka YOKOTA 	accent = number;
3551f150ac4SKazutaka YOKOTA 	if (map->acc[accent].accchar != 0) {
3561f150ac4SKazutaka YOKOTA 		/* this entry has already been defined before! */
3571f150ac4SKazutaka YOKOTA 		errx(1, "duplicated accent key definition");
3581f150ac4SKazutaka YOKOTA 	}
3591f150ac4SKazutaka YOKOTA 
3601f150ac4SKazutaka YOKOTA 	switch ((token = yylex())) {
3611f150ac4SKazutaka YOKOTA 	case TLET:
3621f150ac4SKazutaka YOKOTA 		map->acc[accent].accchar = letter;
3631f150ac4SKazutaka YOKOTA 		break;
3641f150ac4SKazutaka YOKOTA 	case TNUM:
3651f150ac4SKazutaka YOKOTA 		map->acc[accent].accchar = number;
3661f150ac4SKazutaka YOKOTA 		break;
3671f150ac4SKazutaka YOKOTA 	default:
3681f150ac4SKazutaka YOKOTA 		return -1;
3691f150ac4SKazutaka YOKOTA 	}
3701f150ac4SKazutaka YOKOTA 
3711f150ac4SKazutaka YOKOTA 	for (i = 0; (token = yylex()) == '(';) {
3721f150ac4SKazutaka YOKOTA 		switch ((token = yylex())) {
3731f150ac4SKazutaka YOKOTA 		case TLET:
3741f150ac4SKazutaka YOKOTA 			c1 = letter;
3751f150ac4SKazutaka YOKOTA 			break;
3761f150ac4SKazutaka YOKOTA 		case TNUM:
3771f150ac4SKazutaka YOKOTA 			c1 = number;
3781f150ac4SKazutaka YOKOTA 			break;
3791f150ac4SKazutaka YOKOTA 		default:
3801f150ac4SKazutaka YOKOTA 			return -1;
3811f150ac4SKazutaka YOKOTA 		}
3821f150ac4SKazutaka YOKOTA 		switch ((token = yylex())) {
3831f150ac4SKazutaka YOKOTA 		case TLET:
3841f150ac4SKazutaka YOKOTA 			c2 = letter;
3851f150ac4SKazutaka YOKOTA 			break;
3861f150ac4SKazutaka YOKOTA 		case TNUM:
3871f150ac4SKazutaka YOKOTA 			c2 = number;
3881f150ac4SKazutaka YOKOTA 			break;
3891f150ac4SKazutaka YOKOTA 		default:
3901f150ac4SKazutaka YOKOTA 			return -1;
3911f150ac4SKazutaka YOKOTA 		}
3921f150ac4SKazutaka YOKOTA 		if ((token = yylex()) != ')')
3931f150ac4SKazutaka YOKOTA 			return -1;
3941f150ac4SKazutaka YOKOTA 		if (i >= NUM_ACCENTCHARS) {
3951f150ac4SKazutaka YOKOTA 			warnx("too many accented characters, ignored");
3961f150ac4SKazutaka YOKOTA 			continue;
3971f150ac4SKazutaka YOKOTA 		}
3981f150ac4SKazutaka YOKOTA 		map->acc[accent].map[i][0] = c1;
3991f150ac4SKazutaka YOKOTA 		map->acc[accent].map[i][1] = c2;
4001f150ac4SKazutaka YOKOTA 		++i;
4011f150ac4SKazutaka YOKOTA 	}
4021f150ac4SKazutaka YOKOTA 	return (accent + 1);
4031f150ac4SKazutaka YOKOTA }
40408bddad1SSøren Schmidt 
405968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
4064d9a3537SEd Schouten static void
print_entry(FILE * fp,int value)40708bddad1SSøren Schmidt print_entry(FILE *fp, int value)
40808bddad1SSøren Schmidt {
409daf4075aSEd Schouten 	int val = value & ~SPECIAL;
41008bddad1SSøren Schmidt 
41108bddad1SSøren Schmidt 	switch (value) {
412daf4075aSEd Schouten 	case NOP | SPECIAL:
41308bddad1SSøren Schmidt 		fprintf(fp, " nop   ");
41408bddad1SSøren Schmidt 		break;
415daf4075aSEd Schouten 	case LSH | SPECIAL:
41608bddad1SSøren Schmidt 		fprintf(fp, " lshift");
41708bddad1SSøren Schmidt 		break;
418daf4075aSEd Schouten 	case RSH | SPECIAL:
41908bddad1SSøren Schmidt 		fprintf(fp, " rshift");
42008bddad1SSøren Schmidt 		break;
421daf4075aSEd Schouten 	case CLK | SPECIAL:
42208bddad1SSøren Schmidt 		fprintf(fp, " clock ");
42308bddad1SSøren Schmidt 		break;
424daf4075aSEd Schouten 	case NLK | SPECIAL:
42508bddad1SSøren Schmidt 		fprintf(fp, " nlock ");
42608bddad1SSøren Schmidt 		break;
427daf4075aSEd Schouten 	case SLK | SPECIAL:
42808bddad1SSøren Schmidt 		fprintf(fp, " slock ");
42908bddad1SSøren Schmidt 		break;
430daf4075aSEd Schouten 	case BTAB | SPECIAL:
43108bddad1SSøren Schmidt 		fprintf(fp, " btab  ");
43208bddad1SSøren Schmidt 		break;
433daf4075aSEd Schouten 	case LALT | SPECIAL:
43408bddad1SSøren Schmidt 		fprintf(fp, " lalt  ");
43508bddad1SSøren Schmidt 		break;
436daf4075aSEd Schouten 	case LCTR | SPECIAL:
43708bddad1SSøren Schmidt 		fprintf(fp, " lctrl ");
43808bddad1SSøren Schmidt 		break;
439daf4075aSEd Schouten 	case NEXT | SPECIAL:
44008bddad1SSøren Schmidt 		fprintf(fp, " nscr  ");
44108bddad1SSøren Schmidt 		break;
442daf4075aSEd Schouten 	case PREV | SPECIAL:
443ac80d4b4SKazutaka YOKOTA 		fprintf(fp, " pscr  ");
444ac80d4b4SKazutaka YOKOTA 		break;
445daf4075aSEd Schouten 	case RCTR | SPECIAL:
44608bddad1SSøren Schmidt 		fprintf(fp, " rctrl ");
44708bddad1SSøren Schmidt 		break;
448daf4075aSEd Schouten 	case RALT | SPECIAL:
44908bddad1SSøren Schmidt 		fprintf(fp, " ralt  ");
45008bddad1SSøren Schmidt 		break;
451daf4075aSEd Schouten 	case ALK | SPECIAL:
45208bddad1SSøren Schmidt 		fprintf(fp, " alock ");
45308bddad1SSøren Schmidt 		break;
454daf4075aSEd Schouten 	case ASH | SPECIAL:
45508bddad1SSøren Schmidt 		fprintf(fp, " ashift");
45608bddad1SSøren Schmidt 		break;
457daf4075aSEd Schouten 	case META | SPECIAL:
45808bddad1SSøren Schmidt 		fprintf(fp, " meta  ");
45908bddad1SSøren Schmidt 		break;
460daf4075aSEd Schouten 	case RBT | SPECIAL:
46108bddad1SSøren Schmidt 		fprintf(fp, " boot  ");
46208bddad1SSøren Schmidt 		break;
463daf4075aSEd Schouten 	case DBG | SPECIAL:
46408bddad1SSøren Schmidt 		fprintf(fp, " debug ");
46508bddad1SSøren Schmidt 		break;
466daf4075aSEd Schouten 	case SUSP | SPECIAL:
4671f150ac4SKazutaka YOKOTA 		fprintf(fp, " susp  ");
4681f150ac4SKazutaka YOKOTA 		break;
469daf4075aSEd Schouten 	case SPSC | SPECIAL:
47028d2c691SKazutaka YOKOTA 		fprintf(fp, " saver ");
47128d2c691SKazutaka YOKOTA 		break;
472daf4075aSEd Schouten 	case PNC | SPECIAL:
47352990a39SKazutaka YOKOTA 		fprintf(fp, " panic ");
47452990a39SKazutaka YOKOTA 		break;
475daf4075aSEd Schouten 	case LSHA | SPECIAL:
47652990a39SKazutaka YOKOTA 		fprintf(fp, " lshifta");
47752990a39SKazutaka YOKOTA 		break;
478daf4075aSEd Schouten 	case RSHA | SPECIAL:
47952990a39SKazutaka YOKOTA 		fprintf(fp, " rshifta");
48052990a39SKazutaka YOKOTA 		break;
481daf4075aSEd Schouten 	case LCTRA | SPECIAL:
48252990a39SKazutaka YOKOTA 		fprintf(fp, " lctrla");
48352990a39SKazutaka YOKOTA 		break;
484daf4075aSEd Schouten 	case RCTRA | SPECIAL:
48552990a39SKazutaka YOKOTA 		fprintf(fp, " rctrla");
48652990a39SKazutaka YOKOTA 		break;
487daf4075aSEd Schouten 	case LALTA | SPECIAL:
48852990a39SKazutaka YOKOTA 		fprintf(fp, " lalta ");
48952990a39SKazutaka YOKOTA 		break;
490daf4075aSEd Schouten 	case RALTA | SPECIAL:
49152990a39SKazutaka YOKOTA 		fprintf(fp, " ralta ");
49252990a39SKazutaka YOKOTA 		break;
493daf4075aSEd Schouten 	case HALT | SPECIAL:
4941c06ce61SDavid Malone 		fprintf(fp, " halt  ");
4951c06ce61SDavid Malone 		break;
496daf4075aSEd Schouten 	case PDWN | SPECIAL:
4971c06ce61SDavid Malone 		fprintf(fp, " pdwn  ");
4981c06ce61SDavid Malone 		break;
499daf4075aSEd Schouten 	case PASTE | SPECIAL:
5004629b5e0SAndrey A. Chernov 		fprintf(fp, " paste ");
5014629b5e0SAndrey A. Chernov 		break;
50208bddad1SSøren Schmidt 	default:
503daf4075aSEd Schouten 		if (value & SPECIAL) {
50408bddad1SSøren Schmidt 		 	if (val >= F_FN && val <= L_FN)
50508bddad1SSøren Schmidt 				fprintf(fp, " fkey%02d", val - F_FN + 1);
50608bddad1SSøren Schmidt 		 	else if (val >= F_SCR && val <= L_SCR)
50708bddad1SSøren Schmidt 				fprintf(fp, " scr%02d ", val - F_SCR + 1);
5081f150ac4SKazutaka YOKOTA 		 	else if (val >= F_ACC && val <= L_ACC)
5091f150ac4SKazutaka YOKOTA 				fprintf(fp, " %-6s", acc_names[val - F_ACC]);
51008bddad1SSøren Schmidt 			else if (hex)
51108bddad1SSøren Schmidt 				fprintf(fp, " 0x%02x  ", val);
51208bddad1SSøren Schmidt 			else
51308bddad1SSøren Schmidt 				fprintf(fp, " %3d   ", val);
51408bddad1SSøren Schmidt 		}
51508bddad1SSøren Schmidt 		else {
51608bddad1SSøren Schmidt 			if (val < ' ')
51708bddad1SSøren Schmidt 				fprintf(fp, " %s   ", ctrl_names[val]);
51808bddad1SSøren Schmidt 			else if (val == 127)
51908bddad1SSøren Schmidt 				fprintf(fp, " del   ");
520d3628763SRodney W. Grimes 			else if (isascii(val) && isprint(val))
52108bddad1SSøren Schmidt 				fprintf(fp, " '%c'   ", val);
52208bddad1SSøren Schmidt 			else if (hex)
52308bddad1SSøren Schmidt 				fprintf(fp, " 0x%02x  ", val);
52408bddad1SSøren Schmidt 			else
52508bddad1SSøren Schmidt 				fprintf(fp, " %3d   ", val);
52608bddad1SSøren Schmidt 		}
52708bddad1SSøren Schmidt 	}
52808bddad1SSøren Schmidt }
52908bddad1SSøren Schmidt 
5304d9a3537SEd Schouten static void
print_key_definition_line(FILE * fp,int scancode,struct keyent_t * key)531c67e8bd3SKazutaka YOKOTA print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
53208bddad1SSøren Schmidt {
5332976d54bSPhilippe Charnier 	int i;
53408bddad1SSøren Schmidt 
53508bddad1SSøren Schmidt 	/* print scancode number */
53608bddad1SSøren Schmidt 	if (hex)
53708bddad1SSøren Schmidt 		fprintf(fp, " 0x%02x  ", scancode);
53808bddad1SSøren Schmidt 	else
53908bddad1SSøren Schmidt 		fprintf(fp, "  %03d  ", scancode);
54008bddad1SSøren Schmidt 
54108bddad1SSøren Schmidt 	/* print key definitions */
54208bddad1SSøren Schmidt 	for (i=0; i<NUM_STATES; i++) {
54308bddad1SSøren Schmidt 		if (key->spcl & (0x80 >> i))
544daf4075aSEd Schouten 			print_entry(fp, key->map[i] | SPECIAL);
54508bddad1SSøren Schmidt 		else
54608bddad1SSøren Schmidt 			print_entry(fp, key->map[i]);
54708bddad1SSøren Schmidt 	}
54808bddad1SSøren Schmidt 
54908bddad1SSøren Schmidt 	/* print lock state key def */
55008bddad1SSøren Schmidt 	switch (key->flgs) {
55108bddad1SSøren Schmidt 	case 0:
55208bddad1SSøren Schmidt 		fprintf(fp, "  O\n");
55308bddad1SSøren Schmidt 		break;
55408bddad1SSøren Schmidt 	case 1:
55508bddad1SSøren Schmidt 		fprintf(fp, "  C\n");
55608bddad1SSøren Schmidt 		break;
55708bddad1SSøren Schmidt 	case 2:
55808bddad1SSøren Schmidt 		fprintf(fp, "  N\n");
55908bddad1SSøren Schmidt 		break;
56000e0cb65SSøren Schmidt 	case 3:
56100e0cb65SSøren Schmidt 		fprintf(fp, "  B\n");
56200e0cb65SSøren Schmidt 		break;
56308bddad1SSøren Schmidt 	}
56408bddad1SSøren Schmidt }
56508bddad1SSøren Schmidt 
5664d9a3537SEd Schouten static void
print_accent_definition_line(FILE * fp,int accent,struct acc_t * key)5671f150ac4SKazutaka YOKOTA print_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
5681f150ac4SKazutaka YOKOTA {
5691f150ac4SKazutaka YOKOTA 	int c;
5701f150ac4SKazutaka YOKOTA 	int i;
5711f150ac4SKazutaka YOKOTA 
5721f150ac4SKazutaka YOKOTA 	if (key->accchar == 0)
5731f150ac4SKazutaka YOKOTA 		return;
5741f150ac4SKazutaka YOKOTA 
5751f150ac4SKazutaka YOKOTA 	/* print accent number */
5761f150ac4SKazutaka YOKOTA 	fprintf(fp, "  %-6s", acc_names[accent]);
5771f150ac4SKazutaka YOKOTA 	if (isascii(key->accchar) && isprint(key->accchar))
5781f150ac4SKazutaka YOKOTA 		fprintf(fp, "'%c'  ", key->accchar);
5791f150ac4SKazutaka YOKOTA 	else if (hex)
5801f150ac4SKazutaka YOKOTA 		fprintf(fp, "0x%02x ", key->accchar);
5811f150ac4SKazutaka YOKOTA 	else
5821f150ac4SKazutaka YOKOTA 		fprintf(fp, "%03d  ", key->accchar);
5831f150ac4SKazutaka YOKOTA 
5841f150ac4SKazutaka YOKOTA 	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
5851f150ac4SKazutaka YOKOTA 		c = key->map[i][0];
5861f150ac4SKazutaka YOKOTA 		if (c == 0)
5871f150ac4SKazutaka YOKOTA 			break;
5881f150ac4SKazutaka YOKOTA 		if ((i > 0) && ((i % 4) == 0))
5891f150ac4SKazutaka YOKOTA 			fprintf(fp, "\n             ");
5901f150ac4SKazutaka YOKOTA 		if (isascii(c) && isprint(c))
5911f150ac4SKazutaka YOKOTA 			fprintf(fp, "( '%c' ", c);
5921f150ac4SKazutaka YOKOTA 		else if (hex)
5931f150ac4SKazutaka YOKOTA 			fprintf(fp, "(0x%02x ", c);
5941f150ac4SKazutaka YOKOTA 		else
5951f150ac4SKazutaka YOKOTA 			fprintf(fp, "( %03d ", c);
5961f150ac4SKazutaka YOKOTA 		c = key->map[i][1];
5971f150ac4SKazutaka YOKOTA 		if (isascii(c) && isprint(c))
5981f150ac4SKazutaka YOKOTA 			fprintf(fp, "'%c' ) ", c);
5991f150ac4SKazutaka YOKOTA 		else if (hex)
6001f150ac4SKazutaka YOKOTA 			fprintf(fp, "0x%02x) ", c);
6011f150ac4SKazutaka YOKOTA 		else
6021f150ac4SKazutaka YOKOTA 			fprintf(fp, "%03d ) ", c);
6031f150ac4SKazutaka YOKOTA 	}
6041f150ac4SKazutaka YOKOTA 	fprintf(fp, "\n");
6051f150ac4SKazutaka YOKOTA }
606968a3db7SJessica Clarke #endif
6071f150ac4SKazutaka YOKOTA 
6084d9a3537SEd Schouten static void
dump_entry(int value)6091f150ac4SKazutaka YOKOTA dump_entry(int value)
6101f150ac4SKazutaka YOKOTA {
611daf4075aSEd Schouten 	if (value & SPECIAL) {
612daf4075aSEd Schouten 		value &= ~SPECIAL;
6131f150ac4SKazutaka YOKOTA 		switch (value) {
6141f150ac4SKazutaka YOKOTA 		case NOP:
6151f150ac4SKazutaka YOKOTA 			printf("  NOP, ");
6161f150ac4SKazutaka YOKOTA 			break;
6171f150ac4SKazutaka YOKOTA 		case LSH:
6181f150ac4SKazutaka YOKOTA 			printf("  LSH, ");
6191f150ac4SKazutaka YOKOTA 			break;
6201f150ac4SKazutaka YOKOTA 		case RSH:
6211f150ac4SKazutaka YOKOTA 			printf("  RSH, ");
6221f150ac4SKazutaka YOKOTA 			break;
6231f150ac4SKazutaka YOKOTA 		case CLK:
6241f150ac4SKazutaka YOKOTA 			printf("  CLK, ");
6251f150ac4SKazutaka YOKOTA 			break;
6261f150ac4SKazutaka YOKOTA 		case NLK:
6271f150ac4SKazutaka YOKOTA 			printf("  NLK, ");
6281f150ac4SKazutaka YOKOTA 			break;
6291f150ac4SKazutaka YOKOTA 		case SLK:
6301f150ac4SKazutaka YOKOTA 			printf("  SLK, ");
6311f150ac4SKazutaka YOKOTA 			break;
6321f150ac4SKazutaka YOKOTA 		case BTAB:
6331f150ac4SKazutaka YOKOTA 			printf(" BTAB, ");
6341f150ac4SKazutaka YOKOTA 			break;
6351f150ac4SKazutaka YOKOTA 		case LALT:
6361f150ac4SKazutaka YOKOTA 			printf(" LALT, ");
6371f150ac4SKazutaka YOKOTA 			break;
6381f150ac4SKazutaka YOKOTA 		case LCTR:
6391f150ac4SKazutaka YOKOTA 			printf(" LCTR, ");
6401f150ac4SKazutaka YOKOTA 			break;
6411f150ac4SKazutaka YOKOTA 		case NEXT:
6421f150ac4SKazutaka YOKOTA 			printf(" NEXT, ");
6431f150ac4SKazutaka YOKOTA 			break;
644ac80d4b4SKazutaka YOKOTA 		case PREV:
645ac80d4b4SKazutaka YOKOTA 			printf(" PREV, ");
646ac80d4b4SKazutaka YOKOTA 			break;
6471f150ac4SKazutaka YOKOTA 		case RCTR:
6481f150ac4SKazutaka YOKOTA 			printf(" RCTR, ");
6491f150ac4SKazutaka YOKOTA 			break;
6501f150ac4SKazutaka YOKOTA 		case RALT:
6511f150ac4SKazutaka YOKOTA 			printf(" RALT, ");
6521f150ac4SKazutaka YOKOTA 			break;
6531f150ac4SKazutaka YOKOTA 		case ALK:
6541f150ac4SKazutaka YOKOTA 			printf("  ALK, ");
6551f150ac4SKazutaka YOKOTA 			break;
6561f150ac4SKazutaka YOKOTA 		case ASH:
6571f150ac4SKazutaka YOKOTA 			printf("  ASH, ");
6581f150ac4SKazutaka YOKOTA 			break;
6591f150ac4SKazutaka YOKOTA 		case META:
6601f150ac4SKazutaka YOKOTA 			printf(" META, ");
6611f150ac4SKazutaka YOKOTA 			break;
6621f150ac4SKazutaka YOKOTA 		case RBT:
6631f150ac4SKazutaka YOKOTA 			printf("  RBT, ");
6641f150ac4SKazutaka YOKOTA 			break;
6651f150ac4SKazutaka YOKOTA 		case DBG:
6661f150ac4SKazutaka YOKOTA 			printf("  DBG, ");
6671f150ac4SKazutaka YOKOTA 			break;
6681f150ac4SKazutaka YOKOTA 		case SUSP:
6691f150ac4SKazutaka YOKOTA 			printf(" SUSP, ");
6701f150ac4SKazutaka YOKOTA 			break;
67128d2c691SKazutaka YOKOTA 		case SPSC:
67228d2c691SKazutaka YOKOTA 			printf(" SPSC, ");
67328d2c691SKazutaka YOKOTA 			break;
67452990a39SKazutaka YOKOTA 		case PNC:
67552990a39SKazutaka YOKOTA 			printf("  PNC, ");
67652990a39SKazutaka YOKOTA 			break;
67752990a39SKazutaka YOKOTA 		case LSHA:
67852990a39SKazutaka YOKOTA 			printf(" LSHA, ");
67952990a39SKazutaka YOKOTA 			break;
68052990a39SKazutaka YOKOTA 		case RSHA:
68152990a39SKazutaka YOKOTA 			printf(" RSHA, ");
68252990a39SKazutaka YOKOTA 			break;
68352990a39SKazutaka YOKOTA 		case LCTRA:
68452990a39SKazutaka YOKOTA 			printf("LCTRA, ");
68552990a39SKazutaka YOKOTA 			break;
68652990a39SKazutaka YOKOTA 		case RCTRA:
68752990a39SKazutaka YOKOTA 			printf("RCTRA, ");
68852990a39SKazutaka YOKOTA 			break;
68952990a39SKazutaka YOKOTA 		case LALTA:
69052990a39SKazutaka YOKOTA 			printf("LALTA, ");
69152990a39SKazutaka YOKOTA 			break;
69252990a39SKazutaka YOKOTA 		case RALTA:
69352990a39SKazutaka YOKOTA 			printf("RALTA, ");
69452990a39SKazutaka YOKOTA 			break;
6951c06ce61SDavid Malone 		case HALT:
6961c06ce61SDavid Malone 			printf(" HALT, ");
6971c06ce61SDavid Malone 			break;
6981c06ce61SDavid Malone 		case PDWN:
6991c06ce61SDavid Malone 			printf(" PDWN, ");
7001c06ce61SDavid Malone 			break;
7014629b5e0SAndrey A. Chernov 		case PASTE:
7024629b5e0SAndrey A. Chernov 			printf("PASTE, ");
7034629b5e0SAndrey A. Chernov 			break;
7041f150ac4SKazutaka YOKOTA 		default:
7051f150ac4SKazutaka YOKOTA 	 		if (value >= F_FN && value <= L_FN)
7061f150ac4SKazutaka YOKOTA 				printf(" F(%2d),", value - F_FN + 1);
7071f150ac4SKazutaka YOKOTA 	 		else if (value >= F_SCR && value <= L_SCR)
7082c807029SKazutaka YOKOTA 				printf(" S(%2d),", value - F_SCR + 1);
7091f150ac4SKazutaka YOKOTA 	 		else if (value >= F_ACC && value <= L_ACC)
7101f150ac4SKazutaka YOKOTA 				printf(" %-4s, ", acc_names_u[value - F_ACC]);
7111f150ac4SKazutaka YOKOTA 			else
7121f150ac4SKazutaka YOKOTA 				printf(" 0x%02X, ", value);
7131f150ac4SKazutaka YOKOTA 			break;
7141f150ac4SKazutaka YOKOTA 		}
7151f150ac4SKazutaka YOKOTA 	} else if (value == '\'') {
7161f150ac4SKazutaka YOKOTA 		printf(" '\\'', ");
7171f150ac4SKazutaka YOKOTA 	} else if (value == '\\') {
7181f150ac4SKazutaka YOKOTA 		printf(" '\\\\', ");
7191f150ac4SKazutaka YOKOTA 	} else if (isascii(value) && isprint(value)) {
7201f150ac4SKazutaka YOKOTA 		printf("  '%c', ", value);
7211f150ac4SKazutaka YOKOTA 	} else {
7221f150ac4SKazutaka YOKOTA 		printf(" 0x%02X, ", value);
7231f150ac4SKazutaka YOKOTA 	}
7241f150ac4SKazutaka YOKOTA }
7251f150ac4SKazutaka YOKOTA 
7264d9a3537SEd Schouten static void
dump_key_definition(char * name,keymap_t * keymap)7271f150ac4SKazutaka YOKOTA dump_key_definition(char *name, keymap_t *keymap)
7281f150ac4SKazutaka YOKOTA {
7291f150ac4SKazutaka YOKOTA 	int	i, j;
7301f150ac4SKazutaka YOKOTA 
7312c807029SKazutaka YOKOTA 	printf("static keymap_t keymap_%s = { 0x%02x, {\n",
7321f150ac4SKazutaka YOKOTA 	       name, (unsigned)keymap->n_keys);
7331f150ac4SKazutaka YOKOTA 	printf(
7341f150ac4SKazutaka YOKOTA "/*                                                         alt\n"
7351f150ac4SKazutaka YOKOTA " * scan                       cntrl          alt    alt   cntrl\n"
7361f150ac4SKazutaka YOKOTA " * code  base   shift  cntrl  shift   alt   shift  cntrl  shift    spcl flgs\n"
7371f150ac4SKazutaka YOKOTA " * ---------------------------------------------------------------------------\n"
7381f150ac4SKazutaka YOKOTA " */\n");
7391f150ac4SKazutaka YOKOTA 	for (i = 0; i < keymap->n_keys; i++) {
7402c807029SKazutaka YOKOTA 		printf("/*%02x*/{{", i);
7411f150ac4SKazutaka YOKOTA 		for (j = 0; j < NUM_STATES; j++) {
7421f150ac4SKazutaka YOKOTA 			if (keymap->key[i].spcl & (0x80 >> j))
743daf4075aSEd Schouten 				dump_entry(keymap->key[i].map[j] | SPECIAL);
7441f150ac4SKazutaka YOKOTA 			else
7451f150ac4SKazutaka YOKOTA 				dump_entry(keymap->key[i].map[j]);
7461f150ac4SKazutaka YOKOTA 		}
7472c807029SKazutaka YOKOTA 		printf("}, 0x%02X,0x%02X },\n",
7481f150ac4SKazutaka YOKOTA 		       (unsigned)keymap->key[i].spcl,
7491f150ac4SKazutaka YOKOTA 		       (unsigned)keymap->key[i].flgs);
7501f150ac4SKazutaka YOKOTA 	}
7512c807029SKazutaka YOKOTA 	printf("} };\n\n");
7521f150ac4SKazutaka YOKOTA }
7531f150ac4SKazutaka YOKOTA 
7544d9a3537SEd Schouten static void
dump_accent_definition(char * name,accentmap_t * accentmap)7551f150ac4SKazutaka YOKOTA dump_accent_definition(char *name, accentmap_t *accentmap)
7561f150ac4SKazutaka YOKOTA {
7571f150ac4SKazutaka YOKOTA 	int i, j;
7581f150ac4SKazutaka YOKOTA 	int c;
7591f150ac4SKazutaka YOKOTA 
7602c807029SKazutaka YOKOTA 	printf("static accentmap_t accentmap_%s = { %d",
7611f150ac4SKazutaka YOKOTA 		name, accentmap->n_accs);
7622c807029SKazutaka YOKOTA 	if (accentmap->n_accs <= 0) {
7632c807029SKazutaka YOKOTA 		printf(" };\n\n");
7642c807029SKazutaka YOKOTA 		return;
7652c807029SKazutaka YOKOTA 	}
7662c807029SKazutaka YOKOTA 	printf(", {\n");
7671f150ac4SKazutaka YOKOTA 	for (i = 0; i < NUM_DEADKEYS; i++) {
7681f150ac4SKazutaka YOKOTA 		printf("    /* %s=%d */\n    {", acc_names[i], i);
7691f150ac4SKazutaka YOKOTA 		c = accentmap->acc[i].accchar;
7701f150ac4SKazutaka YOKOTA 		if (c == '\'')
7711f150ac4SKazutaka YOKOTA 			printf(" '\\'', {");
7721f150ac4SKazutaka YOKOTA 		else if (c == '\\')
7731f150ac4SKazutaka YOKOTA 			printf(" '\\\\', {");
7741f150ac4SKazutaka YOKOTA 		else if (isascii(c) && isprint(c))
7751f150ac4SKazutaka YOKOTA 			printf("  '%c', {", c);
7761f150ac4SKazutaka YOKOTA 		else if (c == 0) {
7771f150ac4SKazutaka YOKOTA 			printf(" 0x00 }, \n");
7781f150ac4SKazutaka YOKOTA 			continue;
7791f150ac4SKazutaka YOKOTA 		} else
7801f150ac4SKazutaka YOKOTA 			printf(" 0x%02x, {", c);
7811f150ac4SKazutaka YOKOTA 		for (j = 0; j < NUM_ACCENTCHARS; j++) {
7821f150ac4SKazutaka YOKOTA 			c = accentmap->acc[i].map[j][0];
7831f150ac4SKazutaka YOKOTA 			if (c == 0)
7841f150ac4SKazutaka YOKOTA 				break;
7851f150ac4SKazutaka YOKOTA 			if ((j > 0) && ((j % 4) == 0))
7861f150ac4SKazutaka YOKOTA 				printf("\n\t     ");
7871f150ac4SKazutaka YOKOTA 			if (isascii(c) && isprint(c))
7881f150ac4SKazutaka YOKOTA 				printf(" {  '%c',", c);
7891f150ac4SKazutaka YOKOTA 			else
7901f150ac4SKazutaka YOKOTA 				printf(" { 0x%02x,", c);
7911f150ac4SKazutaka YOKOTA 			printf("0x%02x },", accentmap->acc[i].map[j][1]);
7921f150ac4SKazutaka YOKOTA 		}
7931f150ac4SKazutaka YOKOTA 		printf(" }, },\n");
7941f150ac4SKazutaka YOKOTA 	}
7952c807029SKazutaka YOKOTA 	printf("} };\n\n");
7961f150ac4SKazutaka YOKOTA }
79708bddad1SSøren Schmidt 
7984d9a3537SEd Schouten static void
add_keymap_path(const char * path)7998c0d1b47SEd Maste add_keymap_path(const char *path)
8008c0d1b47SEd Maste {
8018c0d1b47SEd Maste 	struct pathent* pe;
8028c0d1b47SEd Maste 	size_t len;
8038c0d1b47SEd Maste 
8048c0d1b47SEd Maste 	len = strlen(path);
8058c0d1b47SEd Maste 	if ((pe = malloc(sizeof(*pe))) == NULL ||
8068c0d1b47SEd Maste 	    (pe->path = malloc(len + 2)) == NULL)
8078c0d1b47SEd Maste 		err(1, "malloc");
8088c0d1b47SEd Maste 	memcpy(pe->path, path, len);
8098c0d1b47SEd Maste 	if (len > 0 && path[len - 1] != '/')
8108c0d1b47SEd Maste 		pe->path[len++] = '/';
8118c0d1b47SEd Maste 	pe->path[len] = '\0';
8128c0d1b47SEd Maste 	STAILQ_INSERT_TAIL(&pathlist, pe, next);
8138c0d1b47SEd Maste }
8148c0d1b47SEd Maste 
815b4eab621SStefan Eßer #ifdef OPIO_DEADKEYMAP
8168c0d1b47SEd Maste static void
to_old_accentmap(accentmap_t * from,oaccentmap_t * to)817b92f8e5cSStefan Eßer to_old_accentmap(accentmap_t *from, oaccentmap_t *to)
818b92f8e5cSStefan Eßer {
819b92f8e5cSStefan Eßer 	int i, j;
820b92f8e5cSStefan Eßer 
821b92f8e5cSStefan Eßer 	to->n_accs = from->n_accs;
822b92f8e5cSStefan Eßer 	for (i = 0; i < NUM_DEADKEYS; i++) {
823b92f8e5cSStefan Eßer 		for (j = 0; j < NUM_ACCENTCHARS; j++) {
824b92f8e5cSStefan Eßer 			to->acc[i].map[j][0] = from->acc[i].map[j][0];
825b92f8e5cSStefan Eßer 			to->acc[i].map[j][1] = from->acc[i].map[j][1];
826b92f8e5cSStefan Eßer 			to->acc[i].accchar = from->acc[i].accchar;
827b92f8e5cSStefan Eßer 		}
828b92f8e5cSStefan Eßer 	}
829b92f8e5cSStefan Eßer }
830b4eab621SStefan Eßer #endif /* OPIO_DEADKEYMAP */
831b92f8e5cSStefan Eßer 
832b92f8e5cSStefan Eßer static void
load_keymap(char * opt,int dumponly)833501d86efSJoerg Wunsch load_keymap(char *opt, int dumponly)
83408bddad1SSøren Schmidt {
8351f150ac4SKazutaka YOKOTA 	keymap_t keymap;
8361f150ac4SKazutaka YOKOTA 	accentmap_t accentmap;
837b4eab621SStefan Eßer #ifdef OPIO_DEADKEYMAP
838b92f8e5cSStefan Eßer 	oaccentmap_t oaccentmap;
839b4eab621SStefan Eßer #endif /* OPIO_DEADKEYMAP */
8408c0d1b47SEd Maste 	struct pathent *pe;
8418c0d1b47SEd Maste 	FILE	*file;
8428c0d1b47SEd Maste 	int	j;
843501d86efSJoerg Wunsch 	char	*name, *cp;
8442f11ee62SAleksandr Rybalko 	char	blank[] = "", keymap_path[] = KEYMAP_PATH;
8452f11ee62SAleksandr Rybalko 	char	vt_keymap_path[] = VT_KEYMAP_PATH, dotkbd[] = ".kbd";
8464f5d9133SAlfred Perlstein 	char	*postfix[] = {blank, dotkbd, NULL};
84708bddad1SSøren Schmidt 
8488c0d1b47SEd Maste 	if (!paths_configured) {
8498e21e585SMaxim Sobolev 		cp = getenv("KEYMAP_PATH");
8508e21e585SMaxim Sobolev 		if (cp != NULL)
8518c0d1b47SEd Maste 			add_keymap_path(cp);
8528c0d1b47SEd Maste 		add_keymap_path("");
853968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
8548c0d1b47SEd Maste 		if (is_vt4())
8558c0d1b47SEd Maste 			add_keymap_path(vt_keymap_path);
8568c0d1b47SEd Maste 		else
8578c0d1b47SEd Maste 			add_keymap_path(keymap_path);
858968a3db7SJessica Clarke #endif
8598c0d1b47SEd Maste 		paths_configured = 1;
8608c0d1b47SEd Maste 	}
861b010fac2SMaxim Sobolev 
8628c0d1b47SEd Maste 	file = NULL;
8638c0d1b47SEd Maste 	STAILQ_FOREACH(pe, &pathlist, next) {
8648c0d1b47SEd Maste 		for (j=0; postfix[j] && file == NULL; j++) {
8658c0d1b47SEd Maste 			name = mkfullname(pe->path, opt, postfix[j]);
8668c0d1b47SEd Maste 			file = fopen(name, "r");
8678c0d1b47SEd Maste 			if (file != NULL)
8688c0d1b47SEd Maste 				break;
869f83a28e0SWarner Losh 		}
87008bddad1SSøren Schmidt 	}
8718c0d1b47SEd Maste 	if (file == NULL) {
872bdcfaae4SDavid E. O'Brien 		warn("keymap file \"%s\" not found", opt);
87308bddad1SSøren Schmidt 		return;
87408bddad1SSøren Schmidt 	}
8751f150ac4SKazutaka YOKOTA 	memset(&keymap, 0, sizeof(keymap));
8761f150ac4SKazutaka YOKOTA 	memset(&accentmap, 0, sizeof(accentmap));
8771f150ac4SKazutaka YOKOTA 	token = -1;
87808bddad1SSøren Schmidt 	while (1) {
8798c0d1b47SEd Maste 		if (get_definition_line(file, &keymap, &accentmap) < 0)
88008bddad1SSøren Schmidt 			break;
88108bddad1SSøren Schmidt     	}
882501d86efSJoerg Wunsch 	if (dumponly) {
883501d86efSJoerg Wunsch 		/* fix up the filename to make it a valid C identifier */
884501d86efSJoerg Wunsch 		for (cp = opt; *cp; cp++)
885501d86efSJoerg Wunsch 			if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_';
8861f150ac4SKazutaka YOKOTA 		printf("/*\n"
8871f150ac4SKazutaka YOKOTA 		       " * Automatically generated from %s.\n"
8881f150ac4SKazutaka YOKOTA 	               " * DO NOT EDIT!\n"
8891f150ac4SKazutaka YOKOTA 		       " */\n", name);
8901f150ac4SKazutaka YOKOTA 		dump_key_definition(opt, &keymap);
8911f150ac4SKazutaka YOKOTA 		dump_accent_definition(opt, &accentmap);
892501d86efSJoerg Wunsch 		return;
893501d86efSJoerg Wunsch 	}
894968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
8951f150ac4SKazutaka YOKOTA 	if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
8962976d54bSPhilippe Charnier 		warn("setting keymap");
8978c0d1b47SEd Maste 		fclose(file);
89808bddad1SSøren Schmidt 		return;
89908bddad1SSøren Schmidt 	}
9001f150ac4SKazutaka YOKOTA 	if ((accentmap.n_accs > 0)
9011f150ac4SKazutaka YOKOTA 	    && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
902b4eab621SStefan Eßer #ifdef OPIO_DEADKEYMAP
903b92f8e5cSStefan Eßer 		to_old_accentmap(&accentmap, &oaccentmap);
904b4eab621SStefan Eßer 		if (ioctl(0, OPIO_DEADKEYMAP, &oaccentmap) < 0)
905b4eab621SStefan Eßer #endif /* OGIO_DEADKEYMAP */
906b4eab621SStefan Eßer 		{
9071f150ac4SKazutaka YOKOTA 			warn("setting accentmap");
9088c0d1b47SEd Maste 			fclose(file);
9091f150ac4SKazutaka YOKOTA 			return;
9101f150ac4SKazutaka YOKOTA 		}
91108bddad1SSøren Schmidt 	}
912968a3db7SJessica Clarke #endif
913b92f8e5cSStefan Eßer }
914b92f8e5cSStefan Eßer 
915b4eab621SStefan Eßer #ifdef OPIO_DEADKEYMAP
916b92f8e5cSStefan Eßer static void
to_new_accentmap(oaccentmap_t * from,accentmap_t * to)917b92f8e5cSStefan Eßer to_new_accentmap(oaccentmap_t *from, accentmap_t *to)
918b92f8e5cSStefan Eßer {
919b92f8e5cSStefan Eßer 	int i, j;
920b92f8e5cSStefan Eßer 
921b92f8e5cSStefan Eßer 	to->n_accs = from->n_accs;
922b92f8e5cSStefan Eßer 	for (i = 0; i < NUM_DEADKEYS; i++) {
923b92f8e5cSStefan Eßer 		for (j = 0; j < NUM_ACCENTCHARS; j++) {
924b92f8e5cSStefan Eßer 			to->acc[i].map[j][0] = from->acc[i].map[j][0];
925b92f8e5cSStefan Eßer 			to->acc[i].map[j][1] = from->acc[i].map[j][1];
926b92f8e5cSStefan Eßer 			to->acc[i].accchar = from->acc[i].accchar;
927b92f8e5cSStefan Eßer 		}
928b92f8e5cSStefan Eßer 	}
929b92f8e5cSStefan Eßer }
930b4eab621SStefan Eßer #endif /* OPIO_DEADKEYMAP */
93108bddad1SSøren Schmidt 
932968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
9334d9a3537SEd Schouten static void
print_keymap(void)9344f5d9133SAlfred Perlstein print_keymap(void)
93508bddad1SSøren Schmidt {
9361f150ac4SKazutaka YOKOTA 	keymap_t keymap;
9371f150ac4SKazutaka YOKOTA 	accentmap_t accentmap;
938b4eab621SStefan Eßer #ifdef OGIO_DEADKEYMAP
939b92f8e5cSStefan Eßer 	oaccentmap_t oaccentmap;
940b4eab621SStefan Eßer #endif /* OPIO_DEADKEYMAP */
94108bddad1SSøren Schmidt 	int i;
94208bddad1SSøren Schmidt 
9431f150ac4SKazutaka YOKOTA 	if (ioctl(0, GIO_KEYMAP, &keymap) < 0)
9442976d54bSPhilippe Charnier 		err(1, "getting keymap");
945b92f8e5cSStefan Eßer 	if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) {
946b4eab621SStefan Eßer #ifdef OGIO_DEADKEYMAP
947b92f8e5cSStefan Eßer 		if (ioctl(0, OGIO_DEADKEYMAP, &oaccentmap) == 0)
948b92f8e5cSStefan Eßer 			to_new_accentmap(&oaccentmap, &accentmap);
949b92f8e5cSStefan Eßer 		else
950b4eab621SStefan Eßer #endif /* OGIO_DEADKEYMAP */
9511f150ac4SKazutaka YOKOTA 			memset(&accentmap, 0, sizeof(accentmap));
952b92f8e5cSStefan Eßer 	}
95308bddad1SSøren Schmidt     	printf(
95408bddad1SSøren Schmidt "#                                                         alt\n"
95508bddad1SSøren Schmidt "# scan                       cntrl          alt    alt   cntrl lock\n"
95608bddad1SSøren Schmidt "# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n"
95708bddad1SSøren Schmidt "# ------------------------------------------------------------------\n"
95808bddad1SSøren Schmidt     	);
9591f150ac4SKazutaka YOKOTA 	for (i=0; i<keymap.n_keys; i++)
9601f150ac4SKazutaka YOKOTA 		print_key_definition_line(stdout, i, &keymap.key[i]);
9611f150ac4SKazutaka YOKOTA 
9621f150ac4SKazutaka YOKOTA 	printf("\n");
9631f150ac4SKazutaka YOKOTA 	for (i = 0; i < NUM_DEADKEYS; i++)
9641f150ac4SKazutaka YOKOTA 		print_accent_definition_line(stdout, i, &accentmap.acc[i]);
9651f150ac4SKazutaka YOKOTA 
96608bddad1SSøren Schmidt }
96708bddad1SSøren Schmidt 
9684d9a3537SEd Schouten static void
load_default_functionkeys(void)9694f5d9133SAlfred Perlstein load_default_functionkeys(void)
97008bddad1SSøren Schmidt {
97108bddad1SSøren Schmidt 	fkeyarg_t fkey;
97208bddad1SSøren Schmidt 	int i;
97308bddad1SSøren Schmidt 
97408bddad1SSøren Schmidt 	for (i=0; i<NUM_FKEYS; i++) {
97508bddad1SSøren Schmidt 		fkey.keynum = i;
97608bddad1SSøren Schmidt 		strcpy(fkey.keydef, fkey_table[i]);
97708bddad1SSøren Schmidt 		fkey.flen = strlen(fkey_table[i]);
97808bddad1SSøren Schmidt 		if (ioctl(0, SETFKEY, &fkey) < 0)
9792976d54bSPhilippe Charnier 			warn("setting function key");
98008bddad1SSøren Schmidt 	}
98108bddad1SSøren Schmidt }
98208bddad1SSøren Schmidt 
9834d9a3537SEd Schouten static void
set_functionkey(char * keynumstr,char * string)98408bddad1SSøren Schmidt set_functionkey(char *keynumstr, char *string)
98508bddad1SSøren Schmidt {
98608bddad1SSøren Schmidt 	fkeyarg_t fkey;
98708bddad1SSøren Schmidt 
98808bddad1SSøren Schmidt 	if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) {
98908bddad1SSøren Schmidt 		load_default_functionkeys();
99008bddad1SSøren Schmidt 		return;
99108bddad1SSøren Schmidt 	}
99208bddad1SSøren Schmidt 	fkey.keynum = atoi(keynumstr);
99308bddad1SSøren Schmidt 	if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) {
9942976d54bSPhilippe Charnier 		warnx("function key number must be between 1 and %d",
99508bddad1SSøren Schmidt 			NUM_FKEYS);
99608bddad1SSøren Schmidt 		return;
99708bddad1SSøren Schmidt 	}
99808bddad1SSøren Schmidt 	if ((fkey.flen = strlen(string)) > MAXFK) {
9992976d54bSPhilippe Charnier 		warnx("function key string too long (%d > %d)",
100008bddad1SSøren Schmidt 			fkey.flen, MAXFK);
100108bddad1SSøren Schmidt 		return;
100208bddad1SSøren Schmidt 	}
100337a0f391SJohn-Mark Gurney 	strncpy(fkey.keydef, string, MAXFK);
100408bddad1SSøren Schmidt 	fkey.keynum -= 1;
100508bddad1SSøren Schmidt 	if (ioctl(0, SETFKEY, &fkey) < 0)
10062976d54bSPhilippe Charnier 		warn("setting function key");
100708bddad1SSøren Schmidt }
100808bddad1SSøren Schmidt 
10094d9a3537SEd Schouten static void
set_bell_values(char * opt)101008bddad1SSøren Schmidt set_bell_values(char *opt)
101108bddad1SSøren Schmidt {
101263787756SSøren Schmidt 	int bell, duration, pitch;
101308bddad1SSøren Schmidt 
10142aa0aafbSKazutaka YOKOTA 	bell = 0;
101596329ce7SStefan Eßer 	duration = 0;
101696329ce7SStefan Eßer 	pitch = 0;
10172aa0aafbSKazutaka YOKOTA 	if (!strncmp(opt, "quiet.", 6)) {
10185a66b663SRuslan Ermilov 		bell = CONS_QUIET_BELL;
10192aa0aafbSKazutaka YOKOTA 		opt += 6;
10202aa0aafbSKazutaka YOKOTA 	}
102163787756SSøren Schmidt 	if (!strcmp(opt, "visual"))
10225a66b663SRuslan Ermilov 		bell |= CONS_VISUAL_BELL;
102363787756SSøren Schmidt 	else if (!strcmp(opt, "normal"))
10242aa0aafbSKazutaka YOKOTA 		duration = 5, pitch = 800;
102539c33d76SKazutaka YOKOTA 	else if (!strcmp(opt, "off"))
102639c33d76SKazutaka YOKOTA 		duration = 0, pitch = 0;
102708bddad1SSøren Schmidt 	else {
102808bddad1SSøren Schmidt 		char		*v1;
102908bddad1SSøren Schmidt 
103063787756SSøren Schmidt 		bell = 0;
103108bddad1SSøren Schmidt 		duration = strtol(opt, &v1, 0);
103208bddad1SSøren Schmidt 		if ((duration < 0) || (*v1 != '.'))
103308bddad1SSøren Schmidt 			goto badopt;
103408bddad1SSøren Schmidt 		opt = ++v1;
103508bddad1SSøren Schmidt 		pitch = strtol(opt, &v1, 0);
103608bddad1SSøren Schmidt 		if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) {
103708bddad1SSøren Schmidt badopt:
103813edc254SMaxim Sobolev 			warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off");
103908bddad1SSøren Schmidt 			return;
104008bddad1SSøren Schmidt 		}
1041*f65c19a2SEd Maste 		if (!is_vt4()) {
10422aa0aafbSKazutaka YOKOTA 			if (pitch != 0)
10432aa0aafbSKazutaka YOKOTA 				pitch = 1193182 / pitch;	/* in Hz */
1044*f65c19a2SEd Maste 		}
10452aa0aafbSKazutaka YOKOTA 		duration /= 10;	/* in 10 m sec */
104608bddad1SSøren Schmidt 	}
104708bddad1SSøren Schmidt 
104863787756SSøren Schmidt 	ioctl(0, CONS_BELLTYPE, &bell);
104996329ce7SStefan Eßer 	if (duration > 0 && pitch > 0)
105096329ce7SStefan Eßer 		fprintf(stderr, "\e[=%d;%dB", pitch, duration);
105108bddad1SSøren Schmidt }
105208bddad1SSøren Schmidt 
10534d9a3537SEd Schouten static void
set_keyrates(char * opt)105408bddad1SSøren Schmidt set_keyrates(char *opt)
105508bddad1SSøren Schmidt {
1056e9deda23SKazutaka YOKOTA 	int arg[2];
1057d30ada6dSKazutaka YOKOTA 	int repeat;
1058d30ada6dSKazutaka YOKOTA 	int delay;
1059f64191e9SKazutaka YOKOTA 	int r, d;
106008bddad1SSøren Schmidt 
1061f64191e9SKazutaka YOKOTA 	if (!strcmp(opt, "slow")) {
1062971bac5aSMichael 		delay = 1000;
1063971bac5aSMichael 		repeat = 504;
1064971bac5aSMichael 		d = 3;
1065971bac5aSMichael 		r = 31;
1066f64191e9SKazutaka YOKOTA 	} else if (!strcmp(opt, "normal")) {
1067971bac5aSMichael 		delay = 500;
1068971bac5aSMichael 		repeat = 126;
1069971bac5aSMichael 		d = 1;
1070971bac5aSMichael 		r = 15;
1071f64191e9SKazutaka YOKOTA 	} else if (!strcmp(opt, "fast")) {
1072971bac5aSMichael 		delay = 0;
1073971bac5aSMichael 		repeat = 0;
1074971bac5aSMichael 		d = 0;
1075971bac5aSMichael 		r = 0;
1076f64191e9SKazutaka YOKOTA 	} else {
107708bddad1SSøren Schmidt 		int		n;
107808bddad1SSøren Schmidt 		char		*v1;
107908bddad1SSøren Schmidt 
108008bddad1SSøren Schmidt 		delay = strtol(opt, &v1, 0);
108108bddad1SSøren Schmidt 		if ((delay < 0) || (*v1 != '.'))
108208bddad1SSøren Schmidt 			goto badopt;
108308bddad1SSøren Schmidt 		opt = ++v1;
108408bddad1SSøren Schmidt 		repeat = strtol(opt, &v1, 0);
108508bddad1SSøren Schmidt 		if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
108608bddad1SSøren Schmidt badopt:
108713edc254SMaxim Sobolev 			warnx("argument to -r must be delay.repeat or slow|normal|fast");
108808bddad1SSøren Schmidt 			return;
108908bddad1SSøren Schmidt 		}
1090f64191e9SKazutaka YOKOTA 		for (n = 0; n < ndelays - 1; n++)
1091971bac5aSMichael 			if (delay <= kbdelays[n])
1092f64191e9SKazutaka YOKOTA 				break;
1093f64191e9SKazutaka YOKOTA 		d = n;
1094f64191e9SKazutaka YOKOTA 		for (n = 0; n < nrepeats - 1; n++)
1095971bac5aSMichael 			if (repeat <= kbrates[n])
1096f64191e9SKazutaka YOKOTA 				break;
1097f64191e9SKazutaka YOKOTA 		r = n;
109808bddad1SSøren Schmidt 	}
109908bddad1SSøren Schmidt 
1100e9deda23SKazutaka YOKOTA 	arg[0] = delay;
1101e9deda23SKazutaka YOKOTA 	arg[1] = repeat;
1102f64191e9SKazutaka YOKOTA 	if (ioctl(0, KDSETREPEAT, arg)) {
1103971bac5aSMichael 		warn("fallback, setting keyboard rate via legacy interface (KDSETRAD), will be removed soon");
1104f64191e9SKazutaka YOKOTA 		if (ioctl(0, KDSETRAD, (d << 5) | r))
11052976d54bSPhilippe Charnier 			warn("setting keyboard rate");
110608bddad1SSøren Schmidt 	}
1107f64191e9SKazutaka YOKOTA }
110808bddad1SSøren Schmidt 
11094f5d9133SAlfred Perlstein static const char *
get_kbd_type_name(int type)11104f5d9133SAlfred Perlstein get_kbd_type_name(int type)
1111c67e8bd3SKazutaka YOKOTA {
1112c67e8bd3SKazutaka YOKOTA 	static struct {
1113c67e8bd3SKazutaka YOKOTA 		int type;
11144f5d9133SAlfred Perlstein 		const char *name;
1115c67e8bd3SKazutaka YOKOTA 	} name_table[] = {
1116c67e8bd3SKazutaka YOKOTA 		{ KB_84,	"AT 84" },
1117c67e8bd3SKazutaka YOKOTA 		{ KB_101,	"AT 101/102" },
1118c67e8bd3SKazutaka YOKOTA 		{ KB_OTHER,	"generic" },
1119c67e8bd3SKazutaka YOKOTA 	};
11204f5d9133SAlfred Perlstein 	unsigned int i;
1121c67e8bd3SKazutaka YOKOTA 
1122338d9c35SElyes Haouas 	for (i = 0; i < nitems(name_table); ++i) {
1123c67e8bd3SKazutaka YOKOTA 		if (type == name_table[i].type)
1124c67e8bd3SKazutaka YOKOTA 			return name_table[i].name;
1125c67e8bd3SKazutaka YOKOTA 	}
1126c67e8bd3SKazutaka YOKOTA 	return "unknown";
1127c67e8bd3SKazutaka YOKOTA }
1128c67e8bd3SKazutaka YOKOTA 
11294d9a3537SEd Schouten static void
show_kbd_info(void)1130c67e8bd3SKazutaka YOKOTA show_kbd_info(void)
1131c67e8bd3SKazutaka YOKOTA {
1132c67e8bd3SKazutaka YOKOTA 	keyboard_info_t info;
1133c67e8bd3SKazutaka YOKOTA 
1134c67e8bd3SKazutaka YOKOTA 	if (ioctl(0, KDGKBINFO, &info) == -1) {
1135c67e8bd3SKazutaka YOKOTA 		warn("unable to obtain keyboard information");
1136c67e8bd3SKazutaka YOKOTA 		return;
1137c67e8bd3SKazutaka YOKOTA 	}
1138c67e8bd3SKazutaka YOKOTA 	printf("kbd%d:\n", info.kb_index);
1139c67e8bd3SKazutaka YOKOTA 	printf("    %.*s%d, type:%s (%d)\n",
114013edc254SMaxim Sobolev 		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
1141c67e8bd3SKazutaka YOKOTA 		get_kbd_type_name(info.kb_type), info.kb_type);
1142c67e8bd3SKazutaka YOKOTA }
1143c67e8bd3SKazutaka YOKOTA 
11444d9a3537SEd Schouten static void
set_keyboard(char * device)1145c67e8bd3SKazutaka YOKOTA set_keyboard(char *device)
1146c67e8bd3SKazutaka YOKOTA {
1147c67e8bd3SKazutaka YOKOTA 	keyboard_info_t info;
1148c67e8bd3SKazutaka YOKOTA 	int fd;
1149c67e8bd3SKazutaka YOKOTA 
1150c67e8bd3SKazutaka YOKOTA 	fd = open(device, O_RDONLY);
1151c67e8bd3SKazutaka YOKOTA 	if (fd < 0) {
1152c67e8bd3SKazutaka YOKOTA 		warn("cannot open %s", device);
1153c67e8bd3SKazutaka YOKOTA 		return;
1154c67e8bd3SKazutaka YOKOTA 	}
1155c67e8bd3SKazutaka YOKOTA 	if (ioctl(fd, KDGKBINFO, &info) == -1) {
1156c67e8bd3SKazutaka YOKOTA 		warn("unable to obtain keyboard information");
1157c67e8bd3SKazutaka YOKOTA 		close(fd);
1158c67e8bd3SKazutaka YOKOTA 		return;
1159c67e8bd3SKazutaka YOKOTA 	}
1160c67e8bd3SKazutaka YOKOTA 	/*
1161c67e8bd3SKazutaka YOKOTA 	 * The keyboard device driver won't release the keyboard by
1162c67e8bd3SKazutaka YOKOTA 	 * the following ioctl, but it automatically will, when the device
1163c67e8bd3SKazutaka YOKOTA 	 * is closed.  So, we don't check error here.
1164c67e8bd3SKazutaka YOKOTA 	 */
1165c67e8bd3SKazutaka YOKOTA 	ioctl(fd, CONS_RELKBD, 0);
1166c67e8bd3SKazutaka YOKOTA 	close(fd);
1167c67e8bd3SKazutaka YOKOTA #if 1
1168c67e8bd3SKazutaka YOKOTA 	printf("kbd%d\n", info.kb_index);
1169c67e8bd3SKazutaka YOKOTA 	printf("    %.*s%d, type:%s (%d)\n",
117013edc254SMaxim Sobolev 		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
1171c67e8bd3SKazutaka YOKOTA 		get_kbd_type_name(info.kb_type), info.kb_type);
1172c67e8bd3SKazutaka YOKOTA #endif
1173c67e8bd3SKazutaka YOKOTA 
1174c67e8bd3SKazutaka YOKOTA 	if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
1175c67e8bd3SKazutaka YOKOTA 		warn("unable to set keyboard");
1176c67e8bd3SKazutaka YOKOTA }
1177c67e8bd3SKazutaka YOKOTA 
11784d9a3537SEd Schouten static void
release_keyboard(void)1179c67e8bd3SKazutaka YOKOTA release_keyboard(void)
1180c67e8bd3SKazutaka YOKOTA {
1181c67e8bd3SKazutaka YOKOTA 	keyboard_info_t info;
1182c67e8bd3SKazutaka YOKOTA 
1183c67e8bd3SKazutaka YOKOTA 	/*
1184c67e8bd3SKazutaka YOKOTA 	 * If stdin is not associated with a keyboard, the following ioctl
1185c67e8bd3SKazutaka YOKOTA 	 * will fail.
1186c67e8bd3SKazutaka YOKOTA 	 */
1187c67e8bd3SKazutaka YOKOTA 	if (ioctl(0, KDGKBINFO, &info) == -1) {
1188c67e8bd3SKazutaka YOKOTA 		warn("unable to obtain keyboard information");
1189c67e8bd3SKazutaka YOKOTA 		return;
1190c67e8bd3SKazutaka YOKOTA 	}
1191c67e8bd3SKazutaka YOKOTA #if 1
1192c67e8bd3SKazutaka YOKOTA 	printf("kbd%d\n", info.kb_index);
1193c67e8bd3SKazutaka YOKOTA 	printf("    %.*s%d, type:%s (%d)\n",
119413edc254SMaxim Sobolev 		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
1195c67e8bd3SKazutaka YOKOTA 		get_kbd_type_name(info.kb_type), info.kb_type);
1196c67e8bd3SKazutaka YOKOTA #endif
1197c67e8bd3SKazutaka YOKOTA 	if (ioctl(0, CONS_RELKBD, 0) == -1)
1198c67e8bd3SKazutaka YOKOTA 		warn("unable to release the keyboard");
1199c67e8bd3SKazutaka YOKOTA }
1200c67e8bd3SKazutaka YOKOTA 
12014d9a3537SEd Schouten static void
mux_keyboard(u_int op,char * kbd)1202eb65c05eSMaksim Yevmenkin mux_keyboard(u_int op, char *kbd)
12034673ea01SMaksim Yevmenkin {
12044673ea01SMaksim Yevmenkin 	keyboard_info_t	info;
12054673ea01SMaksim Yevmenkin 	char		*unit, *ep;
12064673ea01SMaksim Yevmenkin 
12074673ea01SMaksim Yevmenkin 	/*
12084673ea01SMaksim Yevmenkin 	 * If stdin is not associated with a keyboard, the following ioctl
12094673ea01SMaksim Yevmenkin 	 * will fail.
12104673ea01SMaksim Yevmenkin 	 */
12114673ea01SMaksim Yevmenkin 	if (ioctl(0, KDGKBINFO, &info) == -1) {
12124673ea01SMaksim Yevmenkin 		warn("unable to obtain keyboard information");
12134673ea01SMaksim Yevmenkin 		return;
12144673ea01SMaksim Yevmenkin 	}
12154673ea01SMaksim Yevmenkin #if 1
12164673ea01SMaksim Yevmenkin 	printf("kbd%d\n", info.kb_index);
12174673ea01SMaksim Yevmenkin 	printf("    %.*s%d, type:%s (%d)\n",
12184673ea01SMaksim Yevmenkin 		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
12194673ea01SMaksim Yevmenkin 		get_kbd_type_name(info.kb_type), info.kb_type);
12204673ea01SMaksim Yevmenkin #endif
12214673ea01SMaksim Yevmenkin 	/*
12224673ea01SMaksim Yevmenkin 	 * split kbd into name and unit. find the right most part of the
12234673ea01SMaksim Yevmenkin 	 * kbd string that consist of only digits.
12244673ea01SMaksim Yevmenkin 	 */
12254673ea01SMaksim Yevmenkin 
12264673ea01SMaksim Yevmenkin 	memset(&info, 0, sizeof(info));
12274673ea01SMaksim Yevmenkin 
12284673ea01SMaksim Yevmenkin 	info.kb_unit = -1;
12294673ea01SMaksim Yevmenkin 	ep = kbd - 1;
12304673ea01SMaksim Yevmenkin 
12314673ea01SMaksim Yevmenkin 	do {
12324673ea01SMaksim Yevmenkin 		unit = strpbrk(ep + 1, "0123456789");
12334673ea01SMaksim Yevmenkin 		if (unit != NULL) {
12344673ea01SMaksim Yevmenkin 			info.kb_unit = strtol(unit, &ep, 10);
12354673ea01SMaksim Yevmenkin 			if (*ep != '\0')
12364673ea01SMaksim Yevmenkin 				info.kb_unit = -1;
12374673ea01SMaksim Yevmenkin 		}
12384673ea01SMaksim Yevmenkin 	} while (unit != NULL && info.kb_unit == -1);
12394673ea01SMaksim Yevmenkin 
12404673ea01SMaksim Yevmenkin 	if (info.kb_unit == -1) {
12414673ea01SMaksim Yevmenkin 		warnx("unable to find keyboard driver unit in '%s'", kbd);
12424673ea01SMaksim Yevmenkin 		return;
12434673ea01SMaksim Yevmenkin 	}
12444673ea01SMaksim Yevmenkin 
12454673ea01SMaksim Yevmenkin 	if (unit == kbd) {
12464673ea01SMaksim Yevmenkin 		warnx("unable to find keyboard driver name in '%s'", kbd);
12474673ea01SMaksim Yevmenkin 		return;
12484673ea01SMaksim Yevmenkin 	}
12494673ea01SMaksim Yevmenkin 	if (unit - kbd >= (int) sizeof(info.kb_name)) {
12504673ea01SMaksim Yevmenkin 		warnx("keyboard name '%s' is too long", kbd);
12514673ea01SMaksim Yevmenkin 		return;
12524673ea01SMaksim Yevmenkin 	}
12534673ea01SMaksim Yevmenkin 
12544673ea01SMaksim Yevmenkin 	strncpy(info.kb_name, kbd, unit - kbd);
12554673ea01SMaksim Yevmenkin 
12564673ea01SMaksim Yevmenkin 	/*
12574673ea01SMaksim Yevmenkin 	 * If stdin is not associated with a kbdmux(4) keyboard, the following
12584673ea01SMaksim Yevmenkin 	 * ioctl will fail.
12594673ea01SMaksim Yevmenkin 	 */
12604673ea01SMaksim Yevmenkin 
12614673ea01SMaksim Yevmenkin 	if (ioctl(0, op, &info) == -1)
12624673ea01SMaksim Yevmenkin 		warn("unable to (un)mux the keyboard");
12634673ea01SMaksim Yevmenkin }
1264968a3db7SJessica Clarke #endif
126500e0cb65SSøren Schmidt 
12664d9a3537SEd Schouten static void
usage(void)12679a958de5SEd Schouten usage(void)
126808bddad1SSøren Schmidt {
1269968a3db7SJessica Clarke #ifdef BOOTSTRAP_KBDCONTROL
1270968a3db7SJessica Clarke 	fprintf(stderr, "%s\n",
1271968a3db7SJessica Clarke "usage: kbdcontrol [-L mapfile] [-P path]");
1272968a3db7SJessica Clarke #else
12732976d54bSPhilippe Charnier 	fprintf(stderr, "%s\n%s\n%s\n",
12744673ea01SMaksim Yevmenkin "usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]",
12752976d54bSPhilippe Charnier "                  [-r delay.repeat | speed] [-l mapfile] [-f # string]",
12768c0d1b47SEd Maste "                  [-k device] [-L mapfile] [-P path]");
1277968a3db7SJessica Clarke #endif
12782976d54bSPhilippe Charnier 	exit(1);
127908bddad1SSøren Schmidt }
128008bddad1SSøren Schmidt 
128108bddad1SSøren Schmidt 
1282e46b89dcSPeter Wemm int
main(int argc,char ** argv)128308bddad1SSøren Schmidt main(int argc, char **argv)
128408bddad1SSøren Schmidt {
1285968a3db7SJessica Clarke #ifdef BOOTSTRAP_KBDCONTROL
1286968a3db7SJessica Clarke 	const char	*optstring = "L:P:";
1287968a3db7SJessica Clarke #else
12888c0d1b47SEd Maste 	const char	*optstring = "A:a:b:df:iKk:Fl:L:P:r:x";
1289968a3db7SJessica Clarke #endif
129008bddad1SSøren Schmidt 	int		opt;
129108bddad1SSøren Schmidt 
12928c0d1b47SEd Maste 	/* Collect any -P arguments, regardless of where they appear. */
129373701bbeSWarner Losh 	while ((opt = getopt(argc, argv, optstring)) != -1) {
12948c0d1b47SEd Maste 		if (opt == 'P')
12958c0d1b47SEd Maste 			add_keymap_path(optarg);
129673701bbeSWarner Losh 		if (opt == '?')
129773701bbeSWarner Losh 			usage();
129873701bbeSWarner Losh 	}
12998c0d1b47SEd Maste 
13008c0d1b47SEd Maste 	optind = optreset = 1;
13018c0d1b47SEd Maste 	while ((opt = getopt(argc, argv, optstring)) != -1)
130208bddad1SSøren Schmidt 		switch(opt) {
1303968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
13044673ea01SMaksim Yevmenkin 		case 'A':
13054673ea01SMaksim Yevmenkin 		case 'a':
13064673ea01SMaksim Yevmenkin 			mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg);
13074673ea01SMaksim Yevmenkin 			break;
130808bddad1SSøren Schmidt 		case 'b':
130908bddad1SSøren Schmidt 			set_bell_values(optarg);
131008bddad1SSøren Schmidt 			break;
131108bddad1SSøren Schmidt 		case 'd':
131208bddad1SSøren Schmidt 			print_keymap();
131308bddad1SSøren Schmidt 			break;
131408bddad1SSøren Schmidt 		case 'l':
1315501d86efSJoerg Wunsch 			load_keymap(optarg, 0);
1316501d86efSJoerg Wunsch 			break;
1317968a3db7SJessica Clarke #endif
1318501d86efSJoerg Wunsch 		case 'L':
1319501d86efSJoerg Wunsch 			load_keymap(optarg, 1);
132008bddad1SSøren Schmidt 			break;
13218c0d1b47SEd Maste 		case 'P':
13228c0d1b47SEd Maste 			break;
1323968a3db7SJessica Clarke #ifndef BOOTSTRAP_KBDCONTROL
132408bddad1SSøren Schmidt 		case 'f':
132508bddad1SSøren Schmidt 			set_functionkey(optarg,
132608bddad1SSøren Schmidt 			    nextarg(argc, argv, &optind, 'f'));
132708bddad1SSøren Schmidt 			break;
132808bddad1SSøren Schmidt 		case 'F':
132908bddad1SSøren Schmidt 			load_default_functionkeys();
133008bddad1SSøren Schmidt 			break;
1331c67e8bd3SKazutaka YOKOTA 		case 'i':
1332c67e8bd3SKazutaka YOKOTA 			show_kbd_info();
1333c67e8bd3SKazutaka YOKOTA 			break;
1334c67e8bd3SKazutaka YOKOTA 		case 'K':
1335c67e8bd3SKazutaka YOKOTA 			release_keyboard();
1336c67e8bd3SKazutaka YOKOTA 			break;
1337c67e8bd3SKazutaka YOKOTA 		case 'k':
1338c67e8bd3SKazutaka YOKOTA 			set_keyboard(optarg);
1339c67e8bd3SKazutaka YOKOTA 			break;
134008bddad1SSøren Schmidt 		case 'r':
134108bddad1SSøren Schmidt 			set_keyrates(optarg);
134208bddad1SSøren Schmidt 			break;
134308bddad1SSøren Schmidt 		case 'x':
134408bddad1SSøren Schmidt 			hex = 1;
134508bddad1SSøren Schmidt 			break;
1346968a3db7SJessica Clarke #endif
134708bddad1SSøren Schmidt 		default:
134808bddad1SSøren Schmidt 			usage();
134908bddad1SSøren Schmidt 		}
13502976d54bSPhilippe Charnier 	if ((optind != argc) || (argc == 1))
135108bddad1SSøren Schmidt 		usage();
135208bddad1SSøren Schmidt 	exit(0);
135308bddad1SSøren Schmidt }
1354