xref: /freebsd/usr.sbin/kbdmap/kbdmap.c (revision 0f4e8037)
1ece80b1dSMark Murray /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4ece80b1dSMark Murray  * Copyright (c) 2002 Jonathan Belson <jon@witchspace.com>
5ece80b1dSMark Murray  * All rights reserved.
6ece80b1dSMark Murray  *
7ece80b1dSMark Murray  * Redistribution and use in source and binary forms, with or without
8ece80b1dSMark Murray  * modification, are permitted provided that the following conditions
9ece80b1dSMark Murray  * are met:
10ece80b1dSMark Murray  * 1. Redistributions of source code must retain the above copyright
11ece80b1dSMark Murray  *    notice, this list of conditions and the following disclaimer.
12ece80b1dSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
13ece80b1dSMark Murray  *    notice, this list of conditions and the following disclaimer in the
14ece80b1dSMark Murray  *    documentation and/or other materials provided with the distribution.
15ece80b1dSMark Murray  *
16ece80b1dSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17ece80b1dSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18ece80b1dSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ece80b1dSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20ece80b1dSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ece80b1dSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22ece80b1dSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ece80b1dSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24ece80b1dSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25ece80b1dSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26ece80b1dSMark Murray  * SUCH DAMAGE.
27ece80b1dSMark Murray  */
28ece80b1dSMark Murray 
29ece80b1dSMark Murray #include <sys/types.h>
30ece80b1dSMark Murray #include <sys/queue.h>
316fe6b12fSStefan Eßer #include <sys/sysctl.h>
32ece80b1dSMark Murray 
33ece80b1dSMark Murray #include <assert.h>
3424b05d7aSBaptiste Daroussin #include <bsddialog.h>
35ece80b1dSMark Murray #include <ctype.h>
36ece80b1dSMark Murray #include <dirent.h>
37688dfe45SGarrett Wollman #include <limits.h>
38ece80b1dSMark Murray #include <stdio.h>
39ece80b1dSMark Murray #include <stdlib.h>
40ece80b1dSMark Murray #include <string.h>
41ece80b1dSMark Murray #include <stringlist.h>
42ece80b1dSMark Murray #include <unistd.h>
43ece80b1dSMark Murray 
44ece80b1dSMark Murray #include "kbdmap.h"
45ece80b1dSMark Murray 
46ece80b1dSMark Murray 
47ece80b1dSMark Murray static const char *lang_default = DEFAULT_LANG;
48ece80b1dSMark Murray static const char *font;
49ece80b1dSMark Murray static const char *lang;
50ece80b1dSMark Murray static const char *program;
516fe6b12fSStefan Eßer static const char *keymapdir = DEFAULT_VT_KEYMAP_DIR;
526fe6b12fSStefan Eßer static const char *fontdir = DEFAULT_VT_FONT_DIR;
536fe6b12fSStefan Eßer static const char *font_default = DEFAULT_VT_FONT;
54ece80b1dSMark Murray static const char *sysconfig = DEFAULT_SYSCONFIG;
55ece80b1dSMark Murray static const char *font_current;
56ece80b1dSMark Murray static const char *dir;
57ece80b1dSMark Murray static const char *menu = "";
5829f64e28SEd Maste static const char *title = "Keyboard Menu";
59ece80b1dSMark Murray 
60ece80b1dSMark Murray static int x11;
611b4e3694SEd Maste static int using_vt;
62ece80b1dSMark Murray static int show;
63ece80b1dSMark Murray static int verbose;
64ece80b1dSMark Murray static int print;
65ece80b1dSMark Murray 
66ece80b1dSMark Murray 
67ece80b1dSMark Murray struct keymap {
68ece80b1dSMark Murray 	char	*desc;
69ece80b1dSMark Murray 	char	*keym;
70ece80b1dSMark Murray 	int	mark;
71ece80b1dSMark Murray 	SLIST_ENTRY(keymap) entries;
72ece80b1dSMark Murray };
73ece80b1dSMark Murray static SLIST_HEAD(slisthead, keymap) head = SLIST_HEAD_INITIALIZER(head);
74ece80b1dSMark Murray 
75ece80b1dSMark Murray 
76ece80b1dSMark Murray /*
77ece80b1dSMark Murray  * Get keymap entry for 'key', or NULL of not found
78ece80b1dSMark Murray  */
79ece80b1dSMark Murray static struct keymap *
get_keymap(const char * key)80ece80b1dSMark Murray get_keymap(const char *key)
81ece80b1dSMark Murray {
82ece80b1dSMark Murray 	struct keymap *km;
83ece80b1dSMark Murray 
84ece80b1dSMark Murray 	SLIST_FOREACH(km, &head, entries)
85ece80b1dSMark Murray 		if (!strcmp(km->keym, key))
86ece80b1dSMark Murray 			return km;
87ece80b1dSMark Murray 
88ece80b1dSMark Murray 	return NULL;
89ece80b1dSMark Murray }
90ece80b1dSMark Murray 
91ece80b1dSMark Murray /*
92ece80b1dSMark Murray  * Count the number of keymaps we found
93ece80b1dSMark Murray  */
94ece80b1dSMark Murray static int
get_num_keymaps(void)95ece80b1dSMark Murray get_num_keymaps(void)
96ece80b1dSMark Murray {
97ece80b1dSMark Murray 	struct keymap *km;
98ece80b1dSMark Murray 	int count = 0;
99ece80b1dSMark Murray 
100ece80b1dSMark Murray 	SLIST_FOREACH(km, &head, entries)
101ece80b1dSMark Murray 		count++;
102ece80b1dSMark Murray 
103ece80b1dSMark Murray 	return count;
104ece80b1dSMark Murray }
105ece80b1dSMark Murray 
106ece80b1dSMark Murray /*
107ece80b1dSMark Murray  * Remove any keymap with given keym
108ece80b1dSMark Murray  */
109ece80b1dSMark Murray static void
remove_keymap(const char * keym)110ece80b1dSMark Murray remove_keymap(const char *keym)
111ece80b1dSMark Murray {
112ece80b1dSMark Murray 	struct keymap *km;
113ece80b1dSMark Murray 
114ece80b1dSMark Murray 	SLIST_FOREACH(km, &head, entries) {
115ece80b1dSMark Murray 		if (!strcmp(keym, km->keym)) {
116ece80b1dSMark Murray 			SLIST_REMOVE(&head, km, keymap, entries);
117ece80b1dSMark Murray 			free(km);
118ece80b1dSMark Murray 			break;
119ece80b1dSMark Murray 		}
120ece80b1dSMark Murray 	}
121ece80b1dSMark Murray }
122ece80b1dSMark Murray 
123ece80b1dSMark Murray /*
124ece80b1dSMark Murray  * Add to hash with 'key'
125ece80b1dSMark Murray  */
126ece80b1dSMark Murray static void
add_keymap(const char * desc,int mark,const char * keym)127ece80b1dSMark Murray add_keymap(const char *desc, int mark, const char *keym)
128ece80b1dSMark Murray {
129ece80b1dSMark Murray 	struct keymap *km, *km_new;
130ece80b1dSMark Murray 
131ece80b1dSMark Murray 	/* Is there already an entry with this key? */
132ece80b1dSMark Murray 	SLIST_FOREACH(km, &head, entries) {
133ece80b1dSMark Murray 		if (!strcmp(km->keym, keym)) {
134ece80b1dSMark Murray 			/* Reuse this entry */
135ece80b1dSMark Murray 			free(km->desc);
136ece80b1dSMark Murray 			km->desc = strdup(desc);
137ece80b1dSMark Murray 			km->mark = mark;
138ece80b1dSMark Murray 			return;
139ece80b1dSMark Murray 		}
140ece80b1dSMark Murray 	}
141ece80b1dSMark Murray 
142ece80b1dSMark Murray 	km_new = (struct keymap *) malloc (sizeof(struct keymap));
143ece80b1dSMark Murray 	km_new->desc = strdup(desc);
144ece80b1dSMark Murray 	km_new->keym = strdup(keym);
145ece80b1dSMark Murray 	km_new->mark = mark;
146ece80b1dSMark Murray 
147ece80b1dSMark Murray 	/* Add to keymap list */
148ece80b1dSMark Murray 	SLIST_INSERT_HEAD(&head, km_new, entries);
149ece80b1dSMark Murray }
150ece80b1dSMark Murray 
151ece80b1dSMark Murray /*
1526fe6b12fSStefan Eßer  * Return 0 if syscons is in use (to select legacy defaults).
1536fe6b12fSStefan Eßer  */
1546fe6b12fSStefan Eßer static int
check_vt(void)1551b4e3694SEd Maste check_vt(void)
1566fe6b12fSStefan Eßer {
1576fe6b12fSStefan Eßer 	size_t len;
1586fe6b12fSStefan Eßer 	char term[3];
1596fe6b12fSStefan Eßer 
1606fe6b12fSStefan Eßer 	len = 3;
1616fe6b12fSStefan Eßer 	if (sysctlbyname("kern.vty", &term, &len, NULL, 0) != 0 ||
1626fe6b12fSStefan Eßer 	    strcmp(term, "vt") != 0)
1636fe6b12fSStefan Eßer 		return 0;
1641b4e3694SEd Maste 	return 1;
1656fe6b12fSStefan Eßer }
1666fe6b12fSStefan Eßer 
1676fe6b12fSStefan Eßer /*
168ece80b1dSMark Murray  * Figure out the default language to use.
169ece80b1dSMark Murray  */
170ece80b1dSMark Murray static const char *
get_locale(void)171ece80b1dSMark Murray get_locale(void)
172ece80b1dSMark Murray {
173ece80b1dSMark Murray 	const char *locale;
174ece80b1dSMark Murray 
175ece80b1dSMark Murray 	if ((locale = getenv("LC_ALL")) == NULL &&
176ece80b1dSMark Murray 	    (locale = getenv("LC_CTYPE")) == NULL &&
177ece80b1dSMark Murray 	    (locale = getenv("LANG")) == NULL)
178ece80b1dSMark Murray 		locale = lang_default;
179ece80b1dSMark Murray 
180ece80b1dSMark Murray 	/* Check for alias */
181ece80b1dSMark Murray 	if (!strcmp(locale, "C"))
182ece80b1dSMark Murray 		locale = DEFAULT_LANG;
183ece80b1dSMark Murray 
184ece80b1dSMark Murray 	return locale;
185ece80b1dSMark Murray }
186ece80b1dSMark Murray 
187ece80b1dSMark Murray /*
188ece80b1dSMark Murray  * Extract filename part
189ece80b1dSMark Murray  */
190ece80b1dSMark Murray static const char *
extract_name(const char * name)191ece80b1dSMark Murray extract_name(const char *name)
192ece80b1dSMark Murray {
193ece80b1dSMark Murray 	char *p;
194ece80b1dSMark Murray 
195ece80b1dSMark Murray 	p = strrchr(name, '/');
196ece80b1dSMark Murray 	if (p != NULL && p[1] != '\0')
197ece80b1dSMark Murray 		return p + 1;
198ece80b1dSMark Murray 
199ece80b1dSMark Murray 	return name;
200ece80b1dSMark Murray }
201ece80b1dSMark Murray 
202ece80b1dSMark Murray /*
203ece80b1dSMark Murray  * Return file extension or NULL
204ece80b1dSMark Murray  */
205ece80b1dSMark Murray static char *
get_extension(const char * name)206ece80b1dSMark Murray get_extension(const char *name)
207ece80b1dSMark Murray {
208ece80b1dSMark Murray 	char *p;
209ece80b1dSMark Murray 
210ece80b1dSMark Murray 	p = strrchr(name, '.');
211ece80b1dSMark Murray 
212ece80b1dSMark Murray 	if (p != NULL && p[1] != '\0')
213ece80b1dSMark Murray 		return p;
214ece80b1dSMark Murray 
215ece80b1dSMark Murray 	return NULL;
216ece80b1dSMark Murray }
217ece80b1dSMark Murray 
218ece80b1dSMark Murray /*
219ece80b1dSMark Murray  * Read font from /etc/rc.conf else return default.
220ece80b1dSMark Murray  * Freeing the memory is the caller's responsibility.
221ece80b1dSMark Murray  */
222ece80b1dSMark Murray static char *
get_font(void)223ece80b1dSMark Murray get_font(void)
224ece80b1dSMark Murray {
225e17fede8SDimitry Andric 	char line[256], buf[21];
226ece80b1dSMark Murray 	char *fnt = NULL;
227ece80b1dSMark Murray 
228ece80b1dSMark Murray 	FILE *fp = fopen(sysconfig, "r");
229ece80b1dSMark Murray 	if (fp) {
230ece80b1dSMark Murray 		while (fgets(line, sizeof(line), fp)) {
231ece80b1dSMark Murray 			int a, b, matches;
232ece80b1dSMark Murray 
233ece80b1dSMark Murray 			if (line[0] == '#')
234ece80b1dSMark Murray 				continue;
235ece80b1dSMark Murray 
236ece80b1dSMark Murray 			matches = sscanf(line,
237ece80b1dSMark Murray 			    " font%dx%d = \"%20[-.0-9a-zA-Z_]",
238ece80b1dSMark Murray 			    &a, &b, buf);
239ece80b1dSMark Murray 			if (matches==3) {
240ece80b1dSMark Murray 				if (strcmp(buf, "NO")) {
241ece80b1dSMark Murray 					if (fnt)
242ece80b1dSMark Murray 						free(fnt);
2435f81babdSStefan Eßer 					fnt = strdup(buf);
244ece80b1dSMark Murray 				}
245ece80b1dSMark Murray 			}
246ece80b1dSMark Murray 		}
247b2ce2d69SJaakko Heinonen 		fclose(fp);
248ece80b1dSMark Murray 	} else
249ece80b1dSMark Murray 		fprintf(stderr, "Could not open %s for reading\n", sysconfig);
250ece80b1dSMark Murray 
251ece80b1dSMark Murray 	return fnt;
252ece80b1dSMark Murray }
253ece80b1dSMark Murray 
254ece80b1dSMark Murray /*
255ece80b1dSMark Murray  * Set a font using 'vidcontrol'
256ece80b1dSMark Murray  */
257ece80b1dSMark Murray static void
vidcontrol(const char * fnt)258ece80b1dSMark Murray vidcontrol(const char *fnt)
259ece80b1dSMark Murray {
2601b4e3694SEd Maste 	char *tmp, *p, *q, *cmd;
261ece80b1dSMark Murray 	char ch;
262ece80b1dSMark Murray 	int i;
263ece80b1dSMark Murray 
264ece80b1dSMark Murray 	/* syscons test failed */
265ece80b1dSMark Murray 	if (x11)
266ece80b1dSMark Murray 		return;
267ece80b1dSMark Murray 
2681b4e3694SEd Maste 	if (using_vt) {
2691b4e3694SEd Maste 		asprintf(&cmd, "vidcontrol -f %s", fnt);
2701b4e3694SEd Maste 		system(cmd);
2711b4e3694SEd Maste 		free(cmd);
2721b4e3694SEd Maste 		return;
2731b4e3694SEd Maste 	}
2741b4e3694SEd Maste 
275ece80b1dSMark Murray 	tmp = strdup(fnt);
276ece80b1dSMark Murray 
277ece80b1dSMark Murray 	/* Extract font size */
278ece80b1dSMark Murray 	p = strrchr(tmp, '-');
279ece80b1dSMark Murray 	if (p && p[1] != '\0') {
280ece80b1dSMark Murray 		p++;
281ece80b1dSMark Murray 		/* Remove any '.fnt' extension */
282ece80b1dSMark Murray 		if ((q = strstr(p, ".fnt")))
283ece80b1dSMark Murray 			*q = '\0';
284ece80b1dSMark Murray 
285ece80b1dSMark Murray 		/*
286ece80b1dSMark Murray 		 * Check font size is valid, with no trailing characters
287ece80b1dSMark Murray 		 *  ('&ch' should not be matched)
288ece80b1dSMark Murray 		 */
289ece80b1dSMark Murray 		if (sscanf(p, "%dx%d%c", &i, &i, &ch) != 2)
290ece80b1dSMark Murray 			fprintf(stderr, "Which font size? %s\n", fnt);
291ece80b1dSMark Murray 		else {
292ece80b1dSMark Murray 			asprintf(&cmd, "vidcontrol -f %s %s", p, fnt);
293ece80b1dSMark Murray 			if (verbose)
294ece80b1dSMark Murray 				fprintf(stderr, "%s\n", cmd);
295ece80b1dSMark Murray 			system(cmd);
296ece80b1dSMark Murray 			free(cmd);
297ece80b1dSMark Murray 		}
298ece80b1dSMark Murray 	} else
299ece80b1dSMark Murray 		fprintf(stderr, "Which font size? %s\n", fnt);
300ece80b1dSMark Murray 
301ece80b1dSMark Murray 	free(tmp);
302ece80b1dSMark Murray }
303ece80b1dSMark Murray 
304ece80b1dSMark Murray /*
305ece80b1dSMark Murray  * Execute 'kbdcontrol' with the appropriate arguments
306ece80b1dSMark Murray  */
307ece80b1dSMark Murray static void
do_kbdcontrol(struct keymap * km)308ece80b1dSMark Murray do_kbdcontrol(struct keymap *km)
309ece80b1dSMark Murray {
310ece80b1dSMark Murray 	char *kbd_cmd;
311ece80b1dSMark Murray 	asprintf(&kbd_cmd, "kbdcontrol -l %s/%s", dir, km->keym);
312ece80b1dSMark Murray 
313ece80b1dSMark Murray 	if (!x11)
314ece80b1dSMark Murray 		system(kbd_cmd);
315ece80b1dSMark Murray 
3165d920ef7SNathan Whitehorn 	fprintf(stderr, "keymap=\"%s\"\n", km->keym);
317ece80b1dSMark Murray 	free(kbd_cmd);
318ece80b1dSMark Murray }
319ece80b1dSMark Murray 
320ece80b1dSMark Murray /*
321ece80b1dSMark Murray  * Call 'vidcontrol' with the appropriate arguments
322ece80b1dSMark Murray  */
323ece80b1dSMark Murray static void
do_vidfont(struct keymap * km)324ece80b1dSMark Murray do_vidfont(struct keymap *km)
325ece80b1dSMark Murray {
326ece80b1dSMark Murray 	char *vid_cmd, *tmp, *p, *q;
327ece80b1dSMark Murray 
328ece80b1dSMark Murray 	asprintf(&vid_cmd, "%s/%s", dir, km->keym);
329ece80b1dSMark Murray 	vidcontrol(vid_cmd);
330ece80b1dSMark Murray 	free(vid_cmd);
331ece80b1dSMark Murray 
332ece80b1dSMark Murray 	tmp = strdup(km->keym);
333ece80b1dSMark Murray 	p = strrchr(tmp, '-');
334ece80b1dSMark Murray 	if (p && p[1]!='\0') {
335ece80b1dSMark Murray 		p++;
336ece80b1dSMark Murray 		q = get_extension(p);
337ece80b1dSMark Murray 		if (q) {
338ece80b1dSMark Murray 			*q = '\0';
339ece80b1dSMark Murray 			printf("font%s=%s\n", p, km->keym);
340ece80b1dSMark Murray 		}
341ece80b1dSMark Murray 	}
342ece80b1dSMark Murray 	free(tmp);
343ece80b1dSMark Murray }
344ece80b1dSMark Murray 
345ece80b1dSMark Murray /*
346ece80b1dSMark Murray  * Display dialog from 'keymaps[]'
347ece80b1dSMark Murray  */
348ece80b1dSMark Murray static void
show_dialog(struct keymap ** km_sorted,int num_keymaps)349ece80b1dSMark Murray show_dialog(struct keymap **km_sorted, int num_keymaps)
350ece80b1dSMark Murray {
35124b05d7aSBaptiste Daroussin 	struct bsddialog_conf conf;
35224b05d7aSBaptiste Daroussin 	struct bsddialog_menuitem *listitems;
35324b05d7aSBaptiste Daroussin 	int i, result;
354ece80b1dSMark Murray 
355263660c0SAlfonso Siciliano 	if (bsddialog_init() == BSDDIALOG_ERROR) {
356263660c0SAlfonso Siciliano 		fprintf(stderr, "Error bsddialog: %s\n", bsddialog_geterror());
357ece80b1dSMark Murray 		exit(1);
358ece80b1dSMark Murray 	}
35924b05d7aSBaptiste Daroussin 	conf.title = __DECONST(char *, title);
36024b05d7aSBaptiste Daroussin 
36124b05d7aSBaptiste Daroussin 	listitems = calloc(num_keymaps + 1, sizeof(struct bsddialog_menuitem));
36224b05d7aSBaptiste Daroussin 	if (listitems == NULL) {
36324b05d7aSBaptiste Daroussin 		fprintf(stderr, "Failed to allocate memory in show_dialog");
364263660c0SAlfonso Siciliano 		bsddialog_end();
36524b05d7aSBaptiste Daroussin 		exit(1);
36624b05d7aSBaptiste Daroussin 	}
367ece80b1dSMark Murray 
368ece80b1dSMark Murray 	/* start right font, assume that current font is equal
369ece80b1dSMark Murray 	 * to default font in /etc/rc.conf
370ece80b1dSMark Murray 	 *
371ece80b1dSMark Murray 	 * $font is the font which require the language $lang; e.g.
372ece80b1dSMark Murray 	 * russian *need* a koi8 font
373ece80b1dSMark Murray 	 * $font_current is the current font from /etc/rc.conf
374ece80b1dSMark Murray 	 */
375ece80b1dSMark Murray 	if (font && strcmp(font, font_current))
376ece80b1dSMark Murray 		vidcontrol(font);
377ece80b1dSMark Murray 
37824b05d7aSBaptiste Daroussin 	/* Build up the menu */
379ece80b1dSMark Murray 	for (i=0; i<num_keymaps; i++) {
380263660c0SAlfonso Siciliano 		listitems[i].prefix = "";
38124b05d7aSBaptiste Daroussin 		listitems[i].depth = 0;
382263660c0SAlfonso Siciliano 		listitems[i].bottomdesc = "";
38324b05d7aSBaptiste Daroussin 		listitems[i].on = false;
38424b05d7aSBaptiste Daroussin 		listitems[i].name = km_sorted[i]->desc;
385263660c0SAlfonso Siciliano 		listitems[i].desc = "";
386ece80b1dSMark Murray 	}
387263660c0SAlfonso Siciliano 	bsddialog_initconf(&conf);
388263660c0SAlfonso Siciliano 	conf.title = title;
389263660c0SAlfonso Siciliano 	conf.clear = true;
390263660c0SAlfonso Siciliano 	conf.key.enable_esc = true;
391263660c0SAlfonso Siciliano 	result = bsddialog_menu(&conf, menu, 0, 0, 0, num_keymaps, listitems,
392263660c0SAlfonso Siciliano 	    NULL);
393263660c0SAlfonso Siciliano 	if (result == BSDDIALOG_ERROR)
394263660c0SAlfonso Siciliano 		fprintf(stderr, "Error bsddialog: %s\n", bsddialog_geterror());
39524b05d7aSBaptiste Daroussin 	bsddialog_end();
396263660c0SAlfonso Siciliano 
39724b05d7aSBaptiste Daroussin 	switch (result) {
3981de4665dSAlfonso Siciliano 	case BSDDIALOG_OK:
399ece80b1dSMark Murray 		for (i = 0; i < num_keymaps; i++) {
40024b05d7aSBaptiste Daroussin 			if (listitems[i].on) {
4010f4e8037SBaptiste Daroussin 				if (!strcmp(program, "kbdmap"))
402ece80b1dSMark Murray 					do_kbdcontrol(km_sorted[i]);
403ece80b1dSMark Murray 				else
404ece80b1dSMark Murray 					do_vidfont(km_sorted[i]);
405ece80b1dSMark Murray 				break;
406ece80b1dSMark Murray 			}
407ece80b1dSMark Murray 		}
40824b05d7aSBaptiste Daroussin 		break;
40924b05d7aSBaptiste Daroussin 	default:
410ece80b1dSMark Murray 		if (font != NULL && strcmp(font, font_current))
411ece80b1dSMark Murray 			/* Cancelled, restore old font */
412ece80b1dSMark Murray 			vidcontrol(font_current);
41324b05d7aSBaptiste Daroussin 		break;
414ece80b1dSMark Murray 	}
415ece80b1dSMark Murray }
416ece80b1dSMark Murray 
417ece80b1dSMark Murray /*
418ece80b1dSMark Murray  * Search for 'token' in comma delimited array 'buffer'.
419ece80b1dSMark Murray  * Return true for found, false for not found.
420ece80b1dSMark Murray  */
421ece80b1dSMark Murray static int
find_token(const char * buffer,const char * token)422ece80b1dSMark Murray find_token(const char *buffer, const char *token)
423ece80b1dSMark Murray {
424ece80b1dSMark Murray 	char *buffer_tmp, *buffer_copy, *inputstring;
425ece80b1dSMark Murray 	char **ap;
426ece80b1dSMark Murray 	int found;
427ece80b1dSMark Murray 
428ece80b1dSMark Murray 	buffer_copy = strdup(buffer);
429ece80b1dSMark Murray 	buffer_tmp = buffer_copy;
430ece80b1dSMark Murray 	inputstring = buffer_copy;
431ece80b1dSMark Murray 	ap = &buffer_tmp;
432ece80b1dSMark Murray 
433ece80b1dSMark Murray 	found = 0;
434ece80b1dSMark Murray 
435ece80b1dSMark Murray 	while ((*ap = strsep(&inputstring, ",")) != NULL) {
436ece80b1dSMark Murray 		if (strcmp(buffer_tmp, token) == 0) {
437ece80b1dSMark Murray 			found = 1;
438ece80b1dSMark Murray 			break;
439ece80b1dSMark Murray 		}
440ece80b1dSMark Murray 	}
441ece80b1dSMark Murray 
442ece80b1dSMark Murray 	free(buffer_copy);
443ece80b1dSMark Murray 
444ece80b1dSMark Murray 	return found;
445ece80b1dSMark Murray }
446ece80b1dSMark Murray 
447ece80b1dSMark Murray /*
448ece80b1dSMark Murray  * Compare function for qsort
449ece80b1dSMark Murray  */
450ece80b1dSMark Murray static int
compare_keymap(const void * a,const void * b)451ece80b1dSMark Murray compare_keymap(const void *a, const void *b)
452ece80b1dSMark Murray {
453ece80b1dSMark Murray 
454ece80b1dSMark Murray 	/* We've been passed pointers to pointers, so: */
455ece80b1dSMark Murray 	const struct keymap *km1 = *((const struct keymap * const *) a);
456ece80b1dSMark Murray 	const struct keymap *km2 = *((const struct keymap * const *) b);
457ece80b1dSMark Murray 
458ece80b1dSMark Murray 	return strcmp(km1->desc, km2->desc);
459ece80b1dSMark Murray }
460ece80b1dSMark Murray 
461ece80b1dSMark Murray /*
462ece80b1dSMark Murray  * Compare function for qsort
463ece80b1dSMark Murray  */
464ece80b1dSMark Murray static int
compare_lang(const void * a,const void * b)465ece80b1dSMark Murray compare_lang(const void *a, const void *b)
466ece80b1dSMark Murray {
467ece80b1dSMark Murray 	const char *l1 = *((const char * const *) a);
468ece80b1dSMark Murray 	const char *l2 = *((const char * const *) b);
469ece80b1dSMark Murray 
470ece80b1dSMark Murray 	return strcmp(l1, l2);
471ece80b1dSMark Murray }
472ece80b1dSMark Murray 
473ece80b1dSMark Murray /*
474ece80b1dSMark Murray  * Change '8x8' to '8x08' so qsort will put it before eg. '8x14'
475ece80b1dSMark Murray  */
476ece80b1dSMark Murray static void
kludge_desc(struct keymap ** km_sorted,int num_keymaps)477ece80b1dSMark Murray kludge_desc(struct keymap **km_sorted, int num_keymaps)
478ece80b1dSMark Murray {
479ece80b1dSMark Murray 	int i;
480ece80b1dSMark Murray 
481ece80b1dSMark Murray 	for (i=0; i<num_keymaps; i++) {
482ece80b1dSMark Murray 		char *p;
483ece80b1dSMark Murray 		char *km = km_sorted[i]->desc;
484ece80b1dSMark Murray 		if ((p = strstr(km, "8x8")) != NULL) {
485ece80b1dSMark Murray 			int len;
486ece80b1dSMark Murray 			int j;
487ece80b1dSMark Murray 			int offset;
488ece80b1dSMark Murray 
489ece80b1dSMark Murray 			offset = p - km;
490ece80b1dSMark Murray 
491ece80b1dSMark Murray 			/* Make enough space for the extra '0' */
492ece80b1dSMark Murray 			len = strlen(km);
493ece80b1dSMark Murray 			km = realloc(km, len + 2);
494ece80b1dSMark Murray 
495ece80b1dSMark Murray 			for (j=len; j!=offset+1; j--)
496ece80b1dSMark Murray 				km[j + 1] = km[j];
497ece80b1dSMark Murray 
498ece80b1dSMark Murray 			km[offset+2] = '0';
499ece80b1dSMark Murray 
500ece80b1dSMark Murray 			km_sorted[i]->desc = km;
501ece80b1dSMark Murray 		}
502ece80b1dSMark Murray 	}
503ece80b1dSMark Murray }
504ece80b1dSMark Murray 
505ece80b1dSMark Murray /*
506ece80b1dSMark Murray  * Reverse 'kludge_desc()' - change '8x08' back to '8x8'
507ece80b1dSMark Murray  */
508ece80b1dSMark Murray static void
unkludge_desc(struct keymap ** km_sorted,int num_keymaps)509ece80b1dSMark Murray unkludge_desc(struct keymap **km_sorted, int num_keymaps)
510ece80b1dSMark Murray {
511ece80b1dSMark Murray 	int i;
512ece80b1dSMark Murray 
513ece80b1dSMark Murray 	for (i=0; i<num_keymaps; i++) {
514ece80b1dSMark Murray 		char *p;
515ece80b1dSMark Murray 		char *km = km_sorted[i]->desc;
516ece80b1dSMark Murray 		if ((p = strstr(km, "8x08")) != NULL) {
517ece80b1dSMark Murray 			p += 2;
518ece80b1dSMark Murray 			while (*p++)
519ece80b1dSMark Murray 				p[-1] = p[0];
520ece80b1dSMark Murray 
521ece80b1dSMark Murray 			km = realloc(km, p - km - 1);
522ece80b1dSMark Murray 			km_sorted[i]->desc = km;
523ece80b1dSMark Murray 		}
524ece80b1dSMark Murray 	}
525ece80b1dSMark Murray }
526ece80b1dSMark Murray 
527ece80b1dSMark Murray /*
528ece80b1dSMark Murray  * Return 0 if file exists and is readable, else -1
529ece80b1dSMark Murray  */
530ece80b1dSMark Murray static int
check_file(const char * keym)531ece80b1dSMark Murray check_file(const char *keym)
532ece80b1dSMark Murray {
533ece80b1dSMark Murray 	int status = 0;
534ece80b1dSMark Murray 
535ece80b1dSMark Murray 	if (access(keym, R_OK) == -1) {
536ece80b1dSMark Murray 		char *fn;
537ece80b1dSMark Murray 		asprintf(&fn, "%s/%s", dir, keym);
538ece80b1dSMark Murray 		if (access(fn, R_OK) == -1) {
539ece80b1dSMark Murray 			if (verbose)
540ece80b1dSMark Murray 				fprintf(stderr, "%s not found!\n", fn);
541ece80b1dSMark Murray 			status = -1;
542ece80b1dSMark Murray 		}
543ece80b1dSMark Murray 		free(fn);
544ece80b1dSMark Murray 	} else {
545ece80b1dSMark Murray 		if (verbose)
546ece80b1dSMark Murray 			fprintf(stderr, "No read permission for %s!\n", keym);
547ece80b1dSMark Murray 		status = -1;
548ece80b1dSMark Murray 	}
549ece80b1dSMark Murray 
550ece80b1dSMark Murray 	return status;
551ece80b1dSMark Murray }
552ece80b1dSMark Murray 
553ece80b1dSMark Murray /*
5543df5ecacSUlrich Spörlein  * Read options from the relevant configuration file, then
555ece80b1dSMark Murray  *  present to user.
556ece80b1dSMark Murray  */
557ece80b1dSMark Murray static void
menu_read(void)558ece80b1dSMark Murray menu_read(void)
559ece80b1dSMark Murray {
560ece80b1dSMark Murray 	const char *lg;
561ece80b1dSMark Murray 	char *p;
562ece80b1dSMark Murray 	int mark, num_keymaps, items, i;
563ece80b1dSMark Murray 	char buffer[256], filename[PATH_MAX];
564e17fede8SDimitry Andric 	char keym[65], lng[65], desc[257];
565ece80b1dSMark Murray 	char dialect[64], lang_abk[64];
566ece80b1dSMark Murray 	struct keymap *km;
567ece80b1dSMark Murray 	struct keymap **km_sorted;
568ece80b1dSMark Murray 	struct dirent *dp;
569ece80b1dSMark Murray 	StringList *lang_list;
570ece80b1dSMark Murray 	FILE *fp;
571ece80b1dSMark Murray 	DIR *dirp;
572ece80b1dSMark Murray 
573ece80b1dSMark Murray 	lang_list = sl_init();
574ece80b1dSMark Murray 
575ece80b1dSMark Murray 	sprintf(filename, "%s/INDEX.%s", dir, extract_name(dir));
576ece80b1dSMark Murray 
577ece80b1dSMark Murray 	/* en_US.ISO8859-1 -> en_..\.ISO8859-1 */
578ece80b1dSMark Murray 	strlcpy(dialect, lang, sizeof(dialect));
57976c61349SRuslan Ermilov 	if (strlen(dialect) >= 6 && dialect[2] == '_') {
580ece80b1dSMark Murray 		dialect[3] = '.';
581ece80b1dSMark Murray 		dialect[4] = '.';
582ece80b1dSMark Murray 	}
583ece80b1dSMark Murray 
584ece80b1dSMark Murray 
585ece80b1dSMark Murray 	/* en_US.ISO8859-1 -> en */
586ece80b1dSMark Murray 	strlcpy(lang_abk, lang, sizeof(lang_abk));
58776c61349SRuslan Ermilov 	if (strlen(lang_abk) >= 3 && lang_abk[2] == '_')
58876c61349SRuslan Ermilov 		lang_abk[2] = '\0';
589ece80b1dSMark Murray 
590ece80b1dSMark Murray 	fprintf(stderr, "lang_default = %s\n", lang_default);
591ece80b1dSMark Murray 	fprintf(stderr, "dialect = %s\n", dialect);
592ece80b1dSMark Murray 	fprintf(stderr, "lang_abk = %s\n", lang_abk);
593ece80b1dSMark Murray 
594ece80b1dSMark Murray 	fp = fopen(filename, "r");
595ece80b1dSMark Murray 	if (fp) {
596ece80b1dSMark Murray 		int matches;
597ece80b1dSMark Murray 		while (fgets(buffer, sizeof(buffer), fp)) {
598ece80b1dSMark Murray 			p = buffer;
599ece80b1dSMark Murray 			if (p[0] == '#')
600ece80b1dSMark Murray 				continue;
601ece80b1dSMark Murray 
602ece80b1dSMark Murray 			while (isspace(*p))
603ece80b1dSMark Murray 				p++;
604ece80b1dSMark Murray 
605ece80b1dSMark Murray 			if (*p == '\0')
606ece80b1dSMark Murray 				continue;
607ece80b1dSMark Murray 
608ece80b1dSMark Murray 			/* Parse input, removing newline */
60992ee8e8fSEd Maste 			matches = sscanf(p, "%64[^:]:%64[^:]:%256[^:\n]",
610ece80b1dSMark Murray 			    keym, lng, desc);
611ece80b1dSMark Murray 			if (matches == 3) {
61229f64e28SEd Maste 				if (strcmp(keym, "FONT") != 0 &&
61329f64e28SEd Maste 				    strcmp(keym, "MENU") != 0 &&
61429f64e28SEd Maste 				    strcmp(keym, "TITLE") != 0) {
615ece80b1dSMark Murray 					/* Check file exists & is readable */
616ece80b1dSMark Murray 					if (check_file(keym) == -1)
617ece80b1dSMark Murray 						continue;
618ece80b1dSMark Murray 				}
619ece80b1dSMark Murray 			}
620ece80b1dSMark Murray 
621ece80b1dSMark Murray 			if (show) {
622ece80b1dSMark Murray 				/*
623ece80b1dSMark Murray 				 * Take note of supported languages, which
624ece80b1dSMark Murray 				 * might be in a comma-delimited list
625ece80b1dSMark Murray 				 */
626ece80b1dSMark Murray 				char *tmp = strdup(lng);
627ece80b1dSMark Murray 				char *delim = tmp;
628ece80b1dSMark Murray 
629ece80b1dSMark Murray 				for (delim = tmp; ; ) {
630ece80b1dSMark Murray 					char ch = *delim++;
631ece80b1dSMark Murray 					if (ch == ',' || ch == '\0') {
632ece80b1dSMark Murray 						delim[-1] = '\0';
633ece80b1dSMark Murray 						if (!sl_find(lang_list, tmp))
634ece80b1dSMark Murray 							sl_add(lang_list, tmp);
635ece80b1dSMark Murray 						if (ch == '\0')
636ece80b1dSMark Murray 							break;
637ece80b1dSMark Murray 						tmp = delim;
638ece80b1dSMark Murray 					}
639ece80b1dSMark Murray 				}
640ece80b1dSMark Murray 			}
641ece80b1dSMark Murray 			/* Set empty language to default language */
642ece80b1dSMark Murray 			if (lng[0] == '\0')
643ece80b1dSMark Murray 				lg = lang_default;
644ece80b1dSMark Murray 			else
645ece80b1dSMark Murray 				lg = lng;
646ece80b1dSMark Murray 
647ece80b1dSMark Murray 
648ece80b1dSMark Murray 			/* 4) Your choice if it exists
649ece80b1dSMark Murray 			 * 3) Long match eg. en_GB.ISO8859-1 is equal to
650ece80b1dSMark Murray 			 *      en_..\.ISO8859-1
651ece80b1dSMark Murray 			 * 2) short match 'de'
652ece80b1dSMark Murray 			 * 1) default langlist 'en'
653ece80b1dSMark Murray 			 * 0) any language
654ece80b1dSMark Murray 			 *
655ece80b1dSMark Murray 			 * Language may be a comma separated list
656ece80b1dSMark Murray 			 * A higher match overwrites a lower
657ece80b1dSMark Murray 			 * A later entry overwrites a previous if it exists
658ece80b1dSMark Murray 			 *     twice in the database
659ece80b1dSMark Murray 			 */
660ece80b1dSMark Murray 
661ece80b1dSMark Murray 			/* Check for favoured language */
662ece80b1dSMark Murray 			km = get_keymap(keym);
663ece80b1dSMark Murray 			mark = (km) ? km->mark : 0;
664ece80b1dSMark Murray 
665ece80b1dSMark Murray 			if (find_token(lg, lang))
666ece80b1dSMark Murray 				add_keymap(desc, 4, keym);
667ece80b1dSMark Murray 			else if (mark <= 3 && find_token(lg, dialect))
668ece80b1dSMark Murray 				add_keymap(desc, 3, keym);
669ece80b1dSMark Murray 			else if (mark <= 2 && find_token(lg, lang_abk))
670ece80b1dSMark Murray 				add_keymap(desc, 2, keym);
671ece80b1dSMark Murray 			else if (mark <= 1 && find_token(lg, lang_default))
672ece80b1dSMark Murray 				add_keymap(desc, 1, keym);
673ece80b1dSMark Murray 			else if (mark <= 0)
674ece80b1dSMark Murray 				add_keymap(desc, 0, keym);
675ece80b1dSMark Murray 		}
676ece80b1dSMark Murray 		fclose(fp);
677ece80b1dSMark Murray 
678ece80b1dSMark Murray 	} else
679632ddb87SEd Maste 		fprintf(stderr, "Could not open %s for reading\n", filename);
680ece80b1dSMark Murray 
681ece80b1dSMark Murray 	if (show) {
682ece80b1dSMark Murray 		qsort(lang_list->sl_str, lang_list->sl_cur, sizeof(char*),
683ece80b1dSMark Murray 		    compare_lang);
684ece80b1dSMark Murray 		printf("Currently supported languages: ");
685ece80b1dSMark Murray 		for (i=0; i< (int) lang_list->sl_cur; i++)
686ece80b1dSMark Murray 			printf("%s ", lang_list->sl_str[i]);
687ece80b1dSMark Murray 		puts("");
688ece80b1dSMark Murray 		exit(0);
689ece80b1dSMark Murray 	}
690ece80b1dSMark Murray 
69129f64e28SEd Maste 	km = get_keymap("TITLE");
69229f64e28SEd Maste 	if (km)
69329f64e28SEd Maste 		/* Take note of dialog title */
69429f64e28SEd Maste 		title = strdup(km->desc);
695ece80b1dSMark Murray 	km = get_keymap("MENU");
696ece80b1dSMark Murray 	if (km)
697ece80b1dSMark Murray 		/* Take note of menu title */
698ece80b1dSMark Murray 		menu = strdup(km->desc);
699ece80b1dSMark Murray 	km = get_keymap("FONT");
700ece80b1dSMark Murray 	if (km)
701ece80b1dSMark Murray 		/* Take note of language font */
702ece80b1dSMark Murray 		font = strdup(km->desc);
703ece80b1dSMark Murray 
704ece80b1dSMark Murray 	/* Remove unwanted items from list */
705ece80b1dSMark Murray 	remove_keymap("FONT");
70629f64e28SEd Maste 	remove_keymap("MENU");
70729f64e28SEd Maste 	remove_keymap("TITLE");
708ece80b1dSMark Murray 
709ece80b1dSMark Murray 	/* Look for keymaps not in database */
710ece80b1dSMark Murray 	dirp = opendir(dir);
711ece80b1dSMark Murray 	if (dirp) {
712ece80b1dSMark Murray 		while ((dp = readdir(dirp)) != NULL) {
713ece80b1dSMark Murray 			const char *ext = get_extension(dp->d_name);
714ece80b1dSMark Murray 			if (ext) {
715ece80b1dSMark Murray 				if ((!strcmp(ext, ".fnt") ||
716ece80b1dSMark Murray 				    !strcmp(ext, ".kbd")) &&
717ece80b1dSMark Murray 				    !get_keymap(dp->d_name)) {
718ece80b1dSMark Murray 					char *q;
719ece80b1dSMark Murray 
720ece80b1dSMark Murray 					/* Remove any .fnt or .kbd extension */
721ece80b1dSMark Murray 					q = strdup(dp->d_name);
722ece80b1dSMark Murray 					*(get_extension(q)) = '\0';
723ece80b1dSMark Murray 					add_keymap(q, 0, dp->d_name);
724ece80b1dSMark Murray 					free(q);
725ece80b1dSMark Murray 
726ece80b1dSMark Murray 					if (verbose)
727ece80b1dSMark Murray 						fprintf(stderr,
728ece80b1dSMark Murray 						    "'%s' not in database\n",
729ece80b1dSMark Murray 						    dp->d_name);
730ece80b1dSMark Murray 				}
731ece80b1dSMark Murray 			}
732ece80b1dSMark Murray 		}
733ece80b1dSMark Murray 		closedir(dirp);
734ece80b1dSMark Murray 	} else
735ece80b1dSMark Murray 		fprintf(stderr, "Could not open directory '%s'\n", dir);
736ece80b1dSMark Murray 
737ece80b1dSMark Murray 	/* Sort items in keymap */
738ece80b1dSMark Murray 	num_keymaps = get_num_keymaps();
739ece80b1dSMark Murray 
740ece80b1dSMark Murray 	km_sorted = (struct keymap **)
741ece80b1dSMark Murray 	    malloc(num_keymaps*sizeof(struct keymap *));
742ece80b1dSMark Murray 
743ece80b1dSMark Murray 	/* Make array of pointers to items in hash */
744ece80b1dSMark Murray 	items = 0;
745ece80b1dSMark Murray 	SLIST_FOREACH(km, &head, entries)
746ece80b1dSMark Murray 		km_sorted[items++] = km;
747ece80b1dSMark Murray 
748ece80b1dSMark Murray 	/* Change '8x8' to '8x08' so sort works as we might expect... */
749ece80b1dSMark Murray 	kludge_desc(km_sorted, num_keymaps);
750ece80b1dSMark Murray 
751ece80b1dSMark Murray 	qsort(km_sorted, num_keymaps, sizeof(struct keymap *), compare_keymap);
752ece80b1dSMark Murray 
753ece80b1dSMark Murray 	/* ...change back again */
754ece80b1dSMark Murray 	unkludge_desc(km_sorted, num_keymaps);
755ece80b1dSMark Murray 
756ece80b1dSMark Murray 	if (print) {
757ece80b1dSMark Murray 		for (i=0; i<num_keymaps; i++)
758ece80b1dSMark Murray 			printf("%s\n", km_sorted[i]->desc);
759ece80b1dSMark Murray 		exit(0);
760ece80b1dSMark Murray 	}
761ece80b1dSMark Murray 
762ece80b1dSMark Murray 	show_dialog(km_sorted, num_keymaps);
763ece80b1dSMark Murray 
764ece80b1dSMark Murray 	free(km_sorted);
765ece80b1dSMark Murray }
766ece80b1dSMark Murray 
767ece80b1dSMark Murray /*
768ece80b1dSMark Murray  * Display usage information and exit
769ece80b1dSMark Murray  */
770ece80b1dSMark Murray static void
usage(void)771ece80b1dSMark Murray usage(void)
772ece80b1dSMark Murray {
773ece80b1dSMark Murray 
774ece80b1dSMark Murray 	fprintf(stderr, "usage: %s\t[-K] [-V] [-d|-default] [-h|-help] "
775ece80b1dSMark Murray 	    "[-l|-lang language]\n\t\t[-p|-print] [-r|-restore] [-s|-show] "
776ece80b1dSMark Murray 	    "[-v|-verbose]\n", program);
777ece80b1dSMark Murray 	exit(1);
778ece80b1dSMark Murray }
779ece80b1dSMark Murray 
780ece80b1dSMark Murray static void
parse_args(int argc,char ** argv)781ece80b1dSMark Murray parse_args(int argc, char **argv)
782ece80b1dSMark Murray {
783ece80b1dSMark Murray 	int i;
784ece80b1dSMark Murray 
785ece80b1dSMark Murray 	for (i=1; i<argc; i++) {
786ece80b1dSMark Murray 		if (argv[i][0] != '-')
787ece80b1dSMark Murray 			usage();
788ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "-h"))
789ece80b1dSMark Murray 			usage();
790ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-verbose") || !strcmp(argv[i], "-v"))
791ece80b1dSMark Murray 			verbose = 1;
792ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-lang") || !strcmp(argv[i], "-l"))
793ece80b1dSMark Murray 			if (i + 1 == argc)
794ece80b1dSMark Murray 				usage();
795ece80b1dSMark Murray 			else
796ece80b1dSMark Murray 				lang = argv[++i];
797ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-default") || !strcmp(argv[i], "-d"))
798ece80b1dSMark Murray 			lang = lang_default;
799ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-show") || !strcmp(argv[i], "-s"))
800ece80b1dSMark Murray 			show = 1;
801ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-print") || !strcmp(argv[i], "-p"))
802ece80b1dSMark Murray 			print = 1;
803ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-restore") ||
804ece80b1dSMark Murray 		    !strcmp(argv[i], "-r")) {
805ece80b1dSMark Murray 			vidcontrol(font_current);
806ece80b1dSMark Murray 			exit(0);
807ece80b1dSMark Murray 		} else if (!strcmp(argv[i], "-K"))
808ece80b1dSMark Murray 			dir = keymapdir;
809ece80b1dSMark Murray 		else if (!strcmp(argv[i], "-V"))
810ece80b1dSMark Murray 			dir = fontdir;
811ece80b1dSMark Murray 		else
812ece80b1dSMark Murray 			usage();
813ece80b1dSMark Murray 	}
814ece80b1dSMark Murray }
815ece80b1dSMark Murray 
816ece80b1dSMark Murray /*
817ece80b1dSMark Murray  * A front-end for the 'vidfont' and 'kbdmap' programs.
818ece80b1dSMark Murray  */
819ece80b1dSMark Murray int
main(int argc,char ** argv)820ece80b1dSMark Murray main(int argc, char **argv)
821ece80b1dSMark Murray {
822ece80b1dSMark Murray 
823ece80b1dSMark Murray 	x11 = system("kbdcontrol -d >/dev/null");
824ece80b1dSMark Murray 
825ece80b1dSMark Murray 	if (x11) {
826ece80b1dSMark Murray 		fprintf(stderr, "You are not on a virtual console - "
827ece80b1dSMark Murray 				"expect certain strange side-effects\n");
828ece80b1dSMark Murray 		sleep(2);
829ece80b1dSMark Murray 	}
830ece80b1dSMark Murray 
8311b4e3694SEd Maste 	using_vt = check_vt();
8321b4e3694SEd Maste 	if (using_vt == 0) {
8336fe6b12fSStefan Eßer 		keymapdir = DEFAULT_SC_KEYMAP_DIR;
8346fe6b12fSStefan Eßer 		fontdir = DEFAULT_SC_FONT_DIR;
8356fe6b12fSStefan Eßer 		font_default = DEFAULT_SC_FONT;
8366fe6b12fSStefan Eßer 	}
8376fe6b12fSStefan Eßer 
838ece80b1dSMark Murray 	SLIST_INIT(&head);
839ece80b1dSMark Murray 
840ece80b1dSMark Murray 	lang = get_locale();
841ece80b1dSMark Murray 
842ece80b1dSMark Murray 	program = extract_name(argv[0]);
843ece80b1dSMark Murray 
844ece80b1dSMark Murray 	font_current = get_font();
845ece80b1dSMark Murray 	if (font_current == NULL)
846ece80b1dSMark Murray 		font_current = font_default;
847ece80b1dSMark Murray 
848ece80b1dSMark Murray 	if (strcmp(program, "kbdmap"))
849ece80b1dSMark Murray 		dir = fontdir;
850ece80b1dSMark Murray 	else
851ece80b1dSMark Murray 		dir = keymapdir;
852ece80b1dSMark Murray 
85361927b82SFlorent Thoumie 	/* Parse command line arguments */
85461927b82SFlorent Thoumie 	parse_args(argc, argv);
85561927b82SFlorent Thoumie 
856ece80b1dSMark Murray 	/* Read and display options */
857ece80b1dSMark Murray 	menu_read();
858ece80b1dSMark Murray 
859ece80b1dSMark Murray 	return 0;
860ece80b1dSMark Murray }
861