xref: /dflybsd-src/usr.sbin/kbdmap/kbdmap.c (revision ebfa7d96f28674f33a2481aa40c96306d29fc408)
121ece67dSChris Pressey /*-
221ece67dSChris Pressey  * Copyright (c) 2002 Jonathan Belson <jon@witchspace.com>
321ece67dSChris Pressey  * All rights reserved.
421ece67dSChris Pressey  *
521ece67dSChris Pressey  * Redistribution and use in source and binary forms, with or without
621ece67dSChris Pressey  * modification, are permitted provided that the following conditions
721ece67dSChris Pressey  * are met:
821ece67dSChris Pressey  * 1. Redistributions of source code must retain the above copyright
921ece67dSChris Pressey  *    notice, this list of conditions and the following disclaimer.
1021ece67dSChris Pressey  * 2. Redistributions in binary form must reproduce the above copyright
1121ece67dSChris Pressey  *    notice, this list of conditions and the following disclaimer in the
1221ece67dSChris Pressey  *    documentation and/or other materials provided with the distribution.
1321ece67dSChris Pressey  *
1421ece67dSChris Pressey  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1521ece67dSChris Pressey  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1621ece67dSChris Pressey  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1721ece67dSChris Pressey  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1821ece67dSChris Pressey  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1921ece67dSChris Pressey  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2021ece67dSChris Pressey  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2121ece67dSChris Pressey  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2221ece67dSChris Pressey  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2321ece67dSChris Pressey  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2421ece67dSChris Pressey  * SUCH DAMAGE.
2521ece67dSChris Pressey  *
26*ebfa7d96SPeter Avalos  * $FreeBSD: head/usr.sbin/kbdmap/kbdmap.c 237257 2012-06-19 06:10:31Z eadler $
2721ece67dSChris Pressey  */
2821ece67dSChris Pressey 
2921ece67dSChris Pressey #include <sys/types.h>
3021ece67dSChris Pressey #include <sys/queue.h>
3121ece67dSChris Pressey 
3221ece67dSChris Pressey #include <assert.h>
3321ece67dSChris Pressey #include <ctype.h>
3421ece67dSChris Pressey #include <dirent.h>
3521ece67dSChris Pressey #include <limits.h>
3621ece67dSChris Pressey #include <stdio.h>
3721ece67dSChris Pressey #include <stdlib.h>
3821ece67dSChris Pressey #include <string.h>
3921ece67dSChris Pressey #include <stringlist.h>
4021ece67dSChris Pressey #include <unistd.h>
4121ece67dSChris Pressey 
4221ece67dSChris Pressey #include "kbdmap.h"
4321ece67dSChris Pressey 
4421ece67dSChris Pressey 
4521ece67dSChris Pressey static const char *lang_default = DEFAULT_LANG;
4621ece67dSChris Pressey static const char *font;
4721ece67dSChris Pressey static const char *lang;
4821ece67dSChris Pressey static const char *program;
4921ece67dSChris Pressey static const char *keymapdir = DEFAULT_KEYMAP_DIR;
5021ece67dSChris Pressey static const char *fontdir = DEFAULT_FONT_DIR;
5121ece67dSChris Pressey static const char *sysconfig = DEFAULT_SYSCONFIG;
5221ece67dSChris Pressey static const char *font_default = DEFAULT_FONT;
5321ece67dSChris Pressey static const char *font_current;
5421ece67dSChris Pressey static const char *dir;
5521ece67dSChris Pressey static const char *menu = "";
5621ece67dSChris Pressey 
5721ece67dSChris Pressey static int x11;
5821ece67dSChris Pressey static int show;
5921ece67dSChris Pressey static int verbose;
6021ece67dSChris Pressey static int print;
6121ece67dSChris Pressey 
6221ece67dSChris Pressey 
6321ece67dSChris Pressey struct keymap {
6421ece67dSChris Pressey 	char	*desc;
6521ece67dSChris Pressey 	char	*keym;
6621ece67dSChris Pressey 	int	mark;
6721ece67dSChris Pressey 	SLIST_ENTRY(keymap) entries;
6821ece67dSChris Pressey };
6921ece67dSChris Pressey static SLIST_HEAD(slisthead, keymap) head = SLIST_HEAD_INITIALIZER(head);
7021ece67dSChris Pressey 
7121ece67dSChris Pressey 
7221ece67dSChris Pressey /*
7321ece67dSChris Pressey  * Get keymap entry for 'key', or NULL of not found
7421ece67dSChris Pressey  */
7521ece67dSChris Pressey static struct keymap *
get_keymap(const char * key)7621ece67dSChris Pressey get_keymap(const char *key)
7721ece67dSChris Pressey {
7821ece67dSChris Pressey 	struct keymap *km;
7921ece67dSChris Pressey 
8021ece67dSChris Pressey 	SLIST_FOREACH(km, &head, entries)
8121ece67dSChris Pressey 		if (!strcmp(km->keym, key))
8221ece67dSChris Pressey 			return km;
8321ece67dSChris Pressey 
8421ece67dSChris Pressey 	return NULL;
8521ece67dSChris Pressey }
8621ece67dSChris Pressey 
8721ece67dSChris Pressey /*
8821ece67dSChris Pressey  * Count the number of keymaps we found
8921ece67dSChris Pressey  */
9021ece67dSChris Pressey static int
get_num_keymaps(void)9121ece67dSChris Pressey get_num_keymaps(void)
9221ece67dSChris Pressey {
9321ece67dSChris Pressey 	struct keymap *km;
9421ece67dSChris Pressey 	int count = 0;
9521ece67dSChris Pressey 
9621ece67dSChris Pressey 	SLIST_FOREACH(km, &head, entries)
9721ece67dSChris Pressey 		count++;
9821ece67dSChris Pressey 
9921ece67dSChris Pressey 	return count;
10021ece67dSChris Pressey }
10121ece67dSChris Pressey 
10221ece67dSChris Pressey /*
10321ece67dSChris Pressey  * Remove any keymap with given keym
10421ece67dSChris Pressey  */
10521ece67dSChris Pressey static void
remove_keymap(const char * keym)10621ece67dSChris Pressey remove_keymap(const char *keym)
10721ece67dSChris Pressey {
10821ece67dSChris Pressey 	struct keymap *km;
10921ece67dSChris Pressey 
11021ece67dSChris Pressey 	SLIST_FOREACH(km, &head, entries) {
11121ece67dSChris Pressey 		if (!strcmp(keym, km->keym)) {
11221ece67dSChris Pressey 			SLIST_REMOVE(&head, km, keymap, entries);
11321ece67dSChris Pressey 			free(km);
11421ece67dSChris Pressey 			break;
11521ece67dSChris Pressey 		}
11621ece67dSChris Pressey 	}
11721ece67dSChris Pressey }
11821ece67dSChris Pressey 
11921ece67dSChris Pressey /*
12021ece67dSChris Pressey  * Add to hash with 'key'
12121ece67dSChris Pressey  */
12221ece67dSChris Pressey static void
add_keymap(const char * desc,int mark,const char * keym)12321ece67dSChris Pressey add_keymap(const char *desc, int mark, const char *keym)
12421ece67dSChris Pressey {
12521ece67dSChris Pressey 	struct keymap *km, *km_new;
12621ece67dSChris Pressey 
12721ece67dSChris Pressey 	/* Is there already an entry with this key? */
12821ece67dSChris Pressey 	SLIST_FOREACH(km, &head, entries) {
12921ece67dSChris Pressey 		if (!strcmp(km->keym, keym)) {
13021ece67dSChris Pressey 			/* Reuse this entry */
13121ece67dSChris Pressey 			free(km->desc);
13221ece67dSChris Pressey 			km->desc = strdup(desc);
13321ece67dSChris Pressey 			km->mark = mark;
13421ece67dSChris Pressey 			return;
13521ece67dSChris Pressey 		}
13621ece67dSChris Pressey 	}
13721ece67dSChris Pressey 
13821ece67dSChris Pressey 	km_new = (struct keymap *) malloc (sizeof(struct keymap));
13921ece67dSChris Pressey 	km_new->desc = strdup(desc);
14021ece67dSChris Pressey 	km_new->keym = strdup(keym);
14121ece67dSChris Pressey 	km_new->mark = mark;
14221ece67dSChris Pressey 
14321ece67dSChris Pressey 	/* Add to keymap list */
14421ece67dSChris Pressey 	SLIST_INSERT_HEAD(&head, km_new, entries);
14521ece67dSChris Pressey }
14621ece67dSChris Pressey 
14721ece67dSChris Pressey /*
14821ece67dSChris Pressey  * Figure out the default language to use.
14921ece67dSChris Pressey  */
15021ece67dSChris Pressey static const char *
get_locale(void)15121ece67dSChris Pressey get_locale(void)
15221ece67dSChris Pressey {
15321ece67dSChris Pressey 	const char *locale;
15421ece67dSChris Pressey 
15521ece67dSChris Pressey 	if ((locale = getenv("LC_ALL")) == NULL &&
15621ece67dSChris Pressey 	    (locale = getenv("LC_CTYPE")) == NULL &&
15721ece67dSChris Pressey 	    (locale = getenv("LANG")) == NULL)
15821ece67dSChris Pressey 		locale = lang_default;
15921ece67dSChris Pressey 
16021ece67dSChris Pressey 	/* Check for alias */
16121ece67dSChris Pressey 	if (!strcmp(locale, "C"))
16221ece67dSChris Pressey 		locale = DEFAULT_LANG;
16321ece67dSChris Pressey 
16421ece67dSChris Pressey 	return locale;
16521ece67dSChris Pressey }
16621ece67dSChris Pressey 
16721ece67dSChris Pressey /*
16821ece67dSChris Pressey  * Extract filename part
16921ece67dSChris Pressey  */
17021ece67dSChris Pressey static const char *
extract_name(const char * name)17121ece67dSChris Pressey extract_name(const char *name)
17221ece67dSChris Pressey {
17321ece67dSChris Pressey 	char *p;
17421ece67dSChris Pressey 
17521ece67dSChris Pressey 	p = strrchr(name, '/');
17621ece67dSChris Pressey 	if (p != NULL && p[1] != '\0')
17721ece67dSChris Pressey 		return p + 1;
17821ece67dSChris Pressey 
17921ece67dSChris Pressey 	return name;
18021ece67dSChris Pressey }
18121ece67dSChris Pressey 
18221ece67dSChris Pressey /*
18321ece67dSChris Pressey  * Return file extension or NULL
18421ece67dSChris Pressey  */
18521ece67dSChris Pressey static char *
get_extension(const char * name)18621ece67dSChris Pressey get_extension(const char *name)
18721ece67dSChris Pressey {
18821ece67dSChris Pressey 	char *p;
18921ece67dSChris Pressey 
19021ece67dSChris Pressey 	p = strrchr(name, '.');
19121ece67dSChris Pressey 
19221ece67dSChris Pressey 	if (p != NULL && p[1] != '\0')
19321ece67dSChris Pressey 		return p;
19421ece67dSChris Pressey 
19521ece67dSChris Pressey 	return NULL;
19621ece67dSChris Pressey }
19721ece67dSChris Pressey 
19821ece67dSChris Pressey /*
19921ece67dSChris Pressey  * Read font from /etc/rc.conf else return default.
20021ece67dSChris Pressey  * Freeing the memory is the caller's responsibility.
20121ece67dSChris Pressey  */
20221ece67dSChris Pressey static char *
get_font(void)20321ece67dSChris Pressey get_font(void)
20421ece67dSChris Pressey {
20521ece67dSChris Pressey 	char line[256], buf[20];
20621ece67dSChris Pressey 	char *fnt = NULL;
20721ece67dSChris Pressey 
20821ece67dSChris Pressey 	FILE *fp = fopen(sysconfig, "r");
20921ece67dSChris Pressey 	if (fp) {
21021ece67dSChris Pressey 		while (fgets(line, sizeof(line), fp)) {
21121ece67dSChris Pressey 			int a, b, matches;
21221ece67dSChris Pressey 
21321ece67dSChris Pressey 			if (line[0] == '#')
21421ece67dSChris Pressey 				continue;
21521ece67dSChris Pressey 
21621ece67dSChris Pressey 			matches = sscanf(line,
21721ece67dSChris Pressey 			    " font%dx%d = \"%20[-.0-9a-zA-Z_]",
21821ece67dSChris Pressey 			    &a, &b, buf);
21921ece67dSChris Pressey 			if (matches==3) {
22021ece67dSChris Pressey 				if (strcmp(buf, "NO")) {
22121ece67dSChris Pressey 					if (fnt)
22221ece67dSChris Pressey 						free(fnt);
22321ece67dSChris Pressey 					fnt = (char *) malloc(strlen(buf) + 1);
22421ece67dSChris Pressey 					strcpy(fnt, buf);
22521ece67dSChris Pressey 				}
22621ece67dSChris Pressey 			}
22721ece67dSChris Pressey 		}
228*ebfa7d96SPeter Avalos 		fclose(fp);
22921ece67dSChris Pressey 	} else
23021ece67dSChris Pressey 		fprintf(stderr, "Could not open %s for reading\n", sysconfig);
23121ece67dSChris Pressey 
23221ece67dSChris Pressey 	return fnt;
23321ece67dSChris Pressey }
23421ece67dSChris Pressey 
23521ece67dSChris Pressey /*
23621ece67dSChris Pressey  * Set a font using 'vidcontrol'
23721ece67dSChris Pressey  */
23821ece67dSChris Pressey static void
vidcontrol(const char * fnt)23921ece67dSChris Pressey vidcontrol(const char *fnt)
24021ece67dSChris Pressey {
24121ece67dSChris Pressey 	char *tmp, *p, *q;
24221ece67dSChris Pressey 	char ch;
24321ece67dSChris Pressey 	int i;
24421ece67dSChris Pressey 
24521ece67dSChris Pressey 	/* syscons test failed */
24621ece67dSChris Pressey 	if (x11)
24721ece67dSChris Pressey 		return;
24821ece67dSChris Pressey 
24921ece67dSChris Pressey 	tmp = strdup(fnt);
25021ece67dSChris Pressey 
25121ece67dSChris Pressey 	/* Extract font size */
25221ece67dSChris Pressey 	p = strrchr(tmp, '-');
25321ece67dSChris Pressey 	if (p && p[1] != '\0') {
25421ece67dSChris Pressey 		p++;
25521ece67dSChris Pressey 		/* Remove any '.fnt' extension */
25621ece67dSChris Pressey 		if ((q = strstr(p, ".fnt")))
25721ece67dSChris Pressey 			*q = '\0';
25821ece67dSChris Pressey 
25921ece67dSChris Pressey 		/*
26021ece67dSChris Pressey 		 * Check font size is valid, with no trailing characters
26121ece67dSChris Pressey 		 *  ('&ch' should not be matched)
26221ece67dSChris Pressey 		 */
26321ece67dSChris Pressey 		if (sscanf(p, "%dx%d%c", &i, &i, &ch) != 2)
26421ece67dSChris Pressey 			fprintf(stderr, "Which font size? %s\n", fnt);
26521ece67dSChris Pressey 		else {
26621ece67dSChris Pressey 			char *cmd;
26721ece67dSChris Pressey 			asprintf(&cmd, "vidcontrol -f %s %s", p, fnt);
26821ece67dSChris Pressey 			if (verbose)
26921ece67dSChris Pressey 				fprintf(stderr, "%s\n", cmd);
27021ece67dSChris Pressey 			system(cmd);
27121ece67dSChris Pressey 			free(cmd);
27221ece67dSChris Pressey 		}
27321ece67dSChris Pressey 	} else
27421ece67dSChris Pressey 		fprintf(stderr, "Which font size? %s\n", fnt);
27521ece67dSChris Pressey 
27621ece67dSChris Pressey 	free(tmp);
27721ece67dSChris Pressey }
27821ece67dSChris Pressey 
27921ece67dSChris Pressey /*
28021ece67dSChris Pressey  * Execute 'kbdcontrol' with the appropriate arguments
28121ece67dSChris Pressey  */
28221ece67dSChris Pressey static void
do_kbdcontrol(struct keymap * km)28321ece67dSChris Pressey do_kbdcontrol(struct keymap *km)
28421ece67dSChris Pressey {
28521ece67dSChris Pressey 	char *kbd_cmd;
28621ece67dSChris Pressey 	asprintf(&kbd_cmd, "kbdcontrol -l %s/%s", dir, km->keym);
28721ece67dSChris Pressey 
28821ece67dSChris Pressey 	if (!x11)
28921ece67dSChris Pressey 		system(kbd_cmd);
29021ece67dSChris Pressey 
291*ebfa7d96SPeter Avalos 	fprintf(stderr, "keymap=\"%s\"\n", km->keym);
29221ece67dSChris Pressey 	free(kbd_cmd);
29321ece67dSChris Pressey }
29421ece67dSChris Pressey 
29521ece67dSChris Pressey /*
29621ece67dSChris Pressey  * Call 'vidcontrol' with the appropriate arguments
29721ece67dSChris Pressey  */
29821ece67dSChris Pressey static void
do_vidfont(struct keymap * km)29921ece67dSChris Pressey do_vidfont(struct keymap *km)
30021ece67dSChris Pressey {
30121ece67dSChris Pressey 	char *vid_cmd, *tmp, *p, *q;
30221ece67dSChris Pressey 
30321ece67dSChris Pressey 	asprintf(&vid_cmd, "%s/%s", dir, km->keym);
30421ece67dSChris Pressey 	vidcontrol(vid_cmd);
30521ece67dSChris Pressey 	free(vid_cmd);
30621ece67dSChris Pressey 
30721ece67dSChris Pressey 	tmp = strdup(km->keym);
30821ece67dSChris Pressey 	p = strrchr(tmp, '-');
30921ece67dSChris Pressey 	if (p && p[1]!='\0') {
31021ece67dSChris Pressey 		p++;
31121ece67dSChris Pressey 		q = get_extension(p);
31221ece67dSChris Pressey 		if (q) {
31321ece67dSChris Pressey 			*q = '\0';
31421ece67dSChris Pressey 			printf("font%s=%s\n", p, km->keym);
31521ece67dSChris Pressey 		}
31621ece67dSChris Pressey 	}
31721ece67dSChris Pressey 	free(tmp);
31821ece67dSChris Pressey }
31921ece67dSChris Pressey 
32021ece67dSChris Pressey /*
32121ece67dSChris Pressey  * Display dialog from 'keymaps[]'
32221ece67dSChris Pressey  */
32321ece67dSChris Pressey static void
show_dialog(struct keymap ** km_sorted,int num_keymaps)32421ece67dSChris Pressey show_dialog(struct keymap **km_sorted, int num_keymaps)
32521ece67dSChris Pressey {
32621ece67dSChris Pressey 	FILE *fp;
32721ece67dSChris Pressey 	char *cmd, *dialog;
32821ece67dSChris Pressey 	char tmp_name[] = "/tmp/_kbd_lang.XXXX";
32921ece67dSChris Pressey 	int fd, i, size;
33021ece67dSChris Pressey 
33121ece67dSChris Pressey 	fd = mkstemp(tmp_name);
33221ece67dSChris Pressey 	if (fd == -1) {
33321ece67dSChris Pressey 		fprintf(stderr, "Could not open temporary file \"%s\"\n",
33421ece67dSChris Pressey 		    tmp_name);
33521ece67dSChris Pressey 		exit(1);
33621ece67dSChris Pressey 	}
33721ece67dSChris Pressey 	asprintf(&dialog, "/usr/bin/dialog --clear --title \"Keyboard Menu\" "
338*ebfa7d96SPeter Avalos 			  "--menu \"%s\" 0 0 0", menu);
33921ece67dSChris Pressey 
34021ece67dSChris Pressey 	/* start right font, assume that current font is equal
34121ece67dSChris Pressey 	 * to default font in /etc/rc.conf
34221ece67dSChris Pressey 	 *
34321ece67dSChris Pressey 	 * $font is the font which require the language $lang; e.g.
34421ece67dSChris Pressey 	 * russian *need* a koi8 font
34521ece67dSChris Pressey 	 * $font_current is the current font from /etc/rc.conf
34621ece67dSChris Pressey 	 */
34721ece67dSChris Pressey 	if (font && strcmp(font, font_current))
34821ece67dSChris Pressey 		vidcontrol(font);
34921ece67dSChris Pressey 
35021ece67dSChris Pressey 	/* Build up the command */
35121ece67dSChris Pressey 	size = 0;
35221ece67dSChris Pressey 	for (i=0; i<num_keymaps; i++) {
35321ece67dSChris Pressey 		/*
35421ece67dSChris Pressey 		 * Each 'font' is passed as ' "font" ""', so allow the
35521ece67dSChris Pressey 		 * extra space
35621ece67dSChris Pressey 		 */
35721ece67dSChris Pressey 		size += strlen(km_sorted[i]->desc) + 6;
35821ece67dSChris Pressey 	}
35921ece67dSChris Pressey 
36021ece67dSChris Pressey 	/* Allow the space for '2> tmpfilename' redirection */
36121ece67dSChris Pressey 	size += strlen(tmp_name) + 3;
36221ece67dSChris Pressey 
36321ece67dSChris Pressey 	cmd = (char *) malloc(strlen(dialog) + size + 1);
36421ece67dSChris Pressey 	strcpy(cmd, dialog);
36521ece67dSChris Pressey 
36621ece67dSChris Pressey 	for (i=0; i<num_keymaps; i++) {
36721ece67dSChris Pressey 		strcat(cmd, " \"");
36821ece67dSChris Pressey 		strcat(cmd, km_sorted[i]->desc);
36921ece67dSChris Pressey 		strcat(cmd, "\"");
37021ece67dSChris Pressey 		strcat(cmd, " \"\"");
37121ece67dSChris Pressey 	}
37221ece67dSChris Pressey 
37321ece67dSChris Pressey 	strcat(cmd, " 2>");
37421ece67dSChris Pressey 	strcat(cmd, tmp_name);
37521ece67dSChris Pressey 
37621ece67dSChris Pressey 	/* Show the dialog.. */
37721ece67dSChris Pressey 	system(cmd);
37821ece67dSChris Pressey 
37921ece67dSChris Pressey 	fp = fopen(tmp_name, "r");
38021ece67dSChris Pressey 	if (fp) {
38121ece67dSChris Pressey 		char choice[64];
382*ebfa7d96SPeter Avalos 		if (fgets(choice, sizeof(choice), fp) != NULL) {
38321ece67dSChris Pressey 			/* Find key for desc */
38421ece67dSChris Pressey 			for (i=0; i<num_keymaps; i++) {
38521ece67dSChris Pressey 				if (!strcmp(choice, km_sorted[i]->desc)) {
38621ece67dSChris Pressey 					if (!strcmp(program, "kbdmap"))
38721ece67dSChris Pressey 						do_kbdcontrol(km_sorted[i]);
38821ece67dSChris Pressey 					else
38921ece67dSChris Pressey 						do_vidfont(km_sorted[i]);
39021ece67dSChris Pressey 					break;
39121ece67dSChris Pressey 				}
39221ece67dSChris Pressey 			}
39321ece67dSChris Pressey 		} else {
39421ece67dSChris Pressey 			if (font != NULL && strcmp(font, font_current))
39521ece67dSChris Pressey 				/* Cancelled, restore old font */
39621ece67dSChris Pressey 				vidcontrol(font_current);
39721ece67dSChris Pressey 		}
39821ece67dSChris Pressey 		fclose(fp);
39921ece67dSChris Pressey 	} else
40021ece67dSChris Pressey 		fprintf(stderr, "Failed to open temporary file");
40121ece67dSChris Pressey 
40221ece67dSChris Pressey 	/* Tidy up */
40321ece67dSChris Pressey 	remove(tmp_name);
40421ece67dSChris Pressey 	free(cmd);
40521ece67dSChris Pressey 	free(dialog);
40621ece67dSChris Pressey 	close(fd);
40721ece67dSChris Pressey }
40821ece67dSChris Pressey 
40921ece67dSChris Pressey /*
41021ece67dSChris Pressey  * Search for 'token' in comma delimited array 'buffer'.
41121ece67dSChris Pressey  * Return true for found, false for not found.
41221ece67dSChris Pressey  */
41321ece67dSChris Pressey static int
find_token(const char * buffer,const char * token)41421ece67dSChris Pressey find_token(const char *buffer, const char *token)
41521ece67dSChris Pressey {
41621ece67dSChris Pressey 	char *buffer_tmp, *buffer_copy, *inputstring;
41721ece67dSChris Pressey 	char **ap;
41821ece67dSChris Pressey 	int found;
41921ece67dSChris Pressey 
42021ece67dSChris Pressey 	buffer_copy = strdup(buffer);
42121ece67dSChris Pressey 	buffer_tmp = buffer_copy;
42221ece67dSChris Pressey 	inputstring = buffer_copy;
42321ece67dSChris Pressey 	ap = &buffer_tmp;
42421ece67dSChris Pressey 
42521ece67dSChris Pressey 	found = 0;
42621ece67dSChris Pressey 
42721ece67dSChris Pressey 	while ((*ap = strsep(&inputstring, ",")) != NULL) {
42821ece67dSChris Pressey 		if (strcmp(buffer_tmp, token) == 0) {
42921ece67dSChris Pressey 			found = 1;
43021ece67dSChris Pressey 			break;
43121ece67dSChris Pressey 		}
43221ece67dSChris Pressey 	}
43321ece67dSChris Pressey 
43421ece67dSChris Pressey 	free(buffer_copy);
43521ece67dSChris Pressey 
43621ece67dSChris Pressey 	return found;
43721ece67dSChris Pressey }
43821ece67dSChris Pressey 
43921ece67dSChris Pressey /*
44021ece67dSChris Pressey  * Compare function for qsort
44121ece67dSChris Pressey  */
44221ece67dSChris Pressey static int
compare_keymap(const void * a,const void * b)44321ece67dSChris Pressey compare_keymap(const void *a, const void *b)
44421ece67dSChris Pressey {
44521ece67dSChris Pressey 
44621ece67dSChris Pressey 	/* We've been passed pointers to pointers, so: */
44721ece67dSChris Pressey 	const struct keymap *km1 = *((const struct keymap * const *) a);
44821ece67dSChris Pressey 	const struct keymap *km2 = *((const struct keymap * const *) b);
44921ece67dSChris Pressey 
45021ece67dSChris Pressey 	return strcmp(km1->desc, km2->desc);
45121ece67dSChris Pressey }
45221ece67dSChris Pressey 
45321ece67dSChris Pressey /*
45421ece67dSChris Pressey  * Compare function for qsort
45521ece67dSChris Pressey  */
45621ece67dSChris Pressey static int
compare_lang(const void * a,const void * b)45721ece67dSChris Pressey compare_lang(const void *a, const void *b)
45821ece67dSChris Pressey {
45921ece67dSChris Pressey 	const char *l1 = *((const char * const *) a);
46021ece67dSChris Pressey 	const char *l2 = *((const char * const *) b);
46121ece67dSChris Pressey 
46221ece67dSChris Pressey 	return strcmp(l1, l2);
46321ece67dSChris Pressey }
46421ece67dSChris Pressey 
46521ece67dSChris Pressey /*
46621ece67dSChris Pressey  * Change '8x8' to '8x08' so qsort will put it before eg. '8x14'
46721ece67dSChris Pressey  */
46821ece67dSChris Pressey static void
kludge_desc(struct keymap ** km_sorted,int num_keymaps)46921ece67dSChris Pressey kludge_desc(struct keymap **km_sorted, int num_keymaps)
47021ece67dSChris Pressey {
47121ece67dSChris Pressey 	int i;
47221ece67dSChris Pressey 
47321ece67dSChris Pressey 	for (i=0; i<num_keymaps; i++) {
47421ece67dSChris Pressey 		char *p;
47521ece67dSChris Pressey 		char *km = km_sorted[i]->desc;
47621ece67dSChris Pressey 		if ((p = strstr(km, "8x8")) != NULL) {
47721ece67dSChris Pressey 			int len;
47821ece67dSChris Pressey 			int j;
47921ece67dSChris Pressey 			int offset;
48021ece67dSChris Pressey 
48121ece67dSChris Pressey 			offset = p - km;
48221ece67dSChris Pressey 
48321ece67dSChris Pressey 			/* Make enough space for the extra '0' */
48421ece67dSChris Pressey 			len = strlen(km);
48521ece67dSChris Pressey 			km = realloc(km, len + 2);
48621ece67dSChris Pressey 
48721ece67dSChris Pressey 			for (j=len; j!=offset+1; j--)
48821ece67dSChris Pressey 				km[j + 1] = km[j];
48921ece67dSChris Pressey 
49021ece67dSChris Pressey 			km[offset+2] = '0';
49121ece67dSChris Pressey 
49221ece67dSChris Pressey 			km_sorted[i]->desc = km;
49321ece67dSChris Pressey 		}
49421ece67dSChris Pressey 	}
49521ece67dSChris Pressey }
49621ece67dSChris Pressey 
49721ece67dSChris Pressey /*
49821ece67dSChris Pressey  * Reverse 'kludge_desc()' - change '8x08' back to '8x8'
49921ece67dSChris Pressey  */
50021ece67dSChris Pressey static void
unkludge_desc(struct keymap ** km_sorted,int num_keymaps)50121ece67dSChris Pressey unkludge_desc(struct keymap **km_sorted, int num_keymaps)
50221ece67dSChris Pressey {
50321ece67dSChris Pressey 	int i;
50421ece67dSChris Pressey 
50521ece67dSChris Pressey 	for (i=0; i<num_keymaps; i++) {
50621ece67dSChris Pressey 		char *p;
50721ece67dSChris Pressey 		char *km = km_sorted[i]->desc;
50821ece67dSChris Pressey 		if ((p = strstr(km, "8x08")) != NULL) {
50921ece67dSChris Pressey 			p += 2;
51021ece67dSChris Pressey 			while (*p++)
51121ece67dSChris Pressey 				p[-1] = p[0];
51221ece67dSChris Pressey 
51321ece67dSChris Pressey 			km = realloc(km, p - km - 1);
51421ece67dSChris Pressey 			km_sorted[i]->desc = km;
51521ece67dSChris Pressey 		}
51621ece67dSChris Pressey 	}
51721ece67dSChris Pressey }
51821ece67dSChris Pressey 
51921ece67dSChris Pressey /*
52021ece67dSChris Pressey  * Return 0 if file exists and is readable, else -1
52121ece67dSChris Pressey  */
52221ece67dSChris Pressey static int
check_file(const char * keym)52321ece67dSChris Pressey check_file(const char *keym)
52421ece67dSChris Pressey {
52521ece67dSChris Pressey 	int status = 0;
52621ece67dSChris Pressey 
52721ece67dSChris Pressey 	if (access(keym, R_OK) == -1) {
52821ece67dSChris Pressey 		char *fn;
52921ece67dSChris Pressey 		asprintf(&fn, "%s/%s", dir, keym);
53021ece67dSChris Pressey 		if (access(fn, R_OK) == -1) {
53121ece67dSChris Pressey 			if (verbose)
53221ece67dSChris Pressey 				fprintf(stderr, "%s not found!\n", fn);
53321ece67dSChris Pressey 			status = -1;
53421ece67dSChris Pressey 		}
53521ece67dSChris Pressey 		free(fn);
53621ece67dSChris Pressey 	} else {
53721ece67dSChris Pressey 		if (verbose)
53821ece67dSChris Pressey 			fprintf(stderr, "No read permission for %s!\n", keym);
53921ece67dSChris Pressey 		status = -1;
54021ece67dSChris Pressey 	}
54121ece67dSChris Pressey 
54221ece67dSChris Pressey 	return status;
54321ece67dSChris Pressey }
54421ece67dSChris Pressey 
54521ece67dSChris Pressey /*
546*ebfa7d96SPeter Avalos  * Read options from the relevant configuration file, then
54721ece67dSChris Pressey  *  present to user.
54821ece67dSChris Pressey  */
54921ece67dSChris Pressey static void
menu_read(void)55021ece67dSChris Pressey menu_read(void)
55121ece67dSChris Pressey {
55221ece67dSChris Pressey 	const char *lg;
55321ece67dSChris Pressey 	char *p;
55421ece67dSChris Pressey 	int mark, num_keymaps, items, i;
55521ece67dSChris Pressey 	char buffer[256], filename[PATH_MAX];
55621ece67dSChris Pressey 	char keym[64], lng[64], desc[64];
55721ece67dSChris Pressey 	char dialect[64], lang_abk[64];
55821ece67dSChris Pressey 	struct keymap *km;
55921ece67dSChris Pressey 	struct keymap **km_sorted;
56021ece67dSChris Pressey 	struct dirent *dp;
56121ece67dSChris Pressey 	StringList *lang_list;
56221ece67dSChris Pressey 	FILE *fp;
56321ece67dSChris Pressey 	DIR *dirp;
56421ece67dSChris Pressey 
56521ece67dSChris Pressey 	lang_list = sl_init();
56621ece67dSChris Pressey 
56721ece67dSChris Pressey 	sprintf(filename, "%s/INDEX.%s", dir, extract_name(dir));
56821ece67dSChris Pressey 
56921ece67dSChris Pressey 	/* en_US.ISO8859-1 -> en_..\.ISO8859-1 */
57021ece67dSChris Pressey 	strlcpy(dialect, lang, sizeof(dialect));
571*ebfa7d96SPeter Avalos 	if (strlen(dialect) >= 6 && dialect[2] == '_') {
57221ece67dSChris Pressey 		dialect[3] = '.';
57321ece67dSChris Pressey 		dialect[4] = '.';
57421ece67dSChris Pressey 	}
57521ece67dSChris Pressey 
57621ece67dSChris Pressey 
57721ece67dSChris Pressey 	/* en_US.ISO8859-1 -> en */
57821ece67dSChris Pressey 	strlcpy(lang_abk, lang, sizeof(lang_abk));
579*ebfa7d96SPeter Avalos 	if (strlen(lang_abk) >= 3 && lang_abk[2] == '_')
580*ebfa7d96SPeter Avalos 		lang_abk[2] = '\0';
58121ece67dSChris Pressey 
58221ece67dSChris Pressey 	fprintf(stderr, "lang_default = %s\n", lang_default);
58321ece67dSChris Pressey 	fprintf(stderr, "dialect = %s\n", dialect);
58421ece67dSChris Pressey 	fprintf(stderr, "lang_abk = %s\n", lang_abk);
58521ece67dSChris Pressey 
58621ece67dSChris Pressey 	fp = fopen(filename, "r");
58721ece67dSChris Pressey 	if (fp) {
58821ece67dSChris Pressey 		int matches;
58921ece67dSChris Pressey 		while (fgets(buffer, sizeof(buffer), fp)) {
59021ece67dSChris Pressey 			p = buffer;
59121ece67dSChris Pressey 			if (p[0] == '#')
59221ece67dSChris Pressey 				continue;
59321ece67dSChris Pressey 
59421ece67dSChris Pressey 			while (isspace(*p))
59521ece67dSChris Pressey 				p++;
59621ece67dSChris Pressey 
59721ece67dSChris Pressey 			if (*p == '\0')
59821ece67dSChris Pressey 				continue;
59921ece67dSChris Pressey 
60021ece67dSChris Pressey 			/* Parse input, removing newline */
60121ece67dSChris Pressey 			matches = sscanf(p, "%64[^:]:%64[^:]:%64[^:\n]",
60221ece67dSChris Pressey 			    keym, lng, desc);
60321ece67dSChris Pressey 			if (matches == 3) {
60421ece67dSChris Pressey 				if (strcmp(keym, "FONT")
60521ece67dSChris Pressey 				    && strcmp(keym, "MENU")) {
60621ece67dSChris Pressey 					/* Check file exists & is readable */
60721ece67dSChris Pressey 					if (check_file(keym) == -1)
60821ece67dSChris Pressey 						continue;
60921ece67dSChris Pressey 				}
61021ece67dSChris Pressey 			}
61121ece67dSChris Pressey 
61221ece67dSChris Pressey 			if (show) {
61321ece67dSChris Pressey 				/*
61421ece67dSChris Pressey 				 * Take note of supported languages, which
61521ece67dSChris Pressey 				 * might be in a comma-delimited list
61621ece67dSChris Pressey 				 */
61721ece67dSChris Pressey 				char *tmp = strdup(lng);
61821ece67dSChris Pressey 				char *delim = tmp;
61921ece67dSChris Pressey 
62021ece67dSChris Pressey 				for (delim = tmp; ; ) {
62121ece67dSChris Pressey 					char ch = *delim++;
62221ece67dSChris Pressey 					if (ch == ',' || ch == '\0') {
62321ece67dSChris Pressey 						delim[-1] = '\0';
62421ece67dSChris Pressey 						if (!sl_find(lang_list, tmp))
62521ece67dSChris Pressey 							sl_add(lang_list, tmp);
62621ece67dSChris Pressey 						if (ch == '\0')
62721ece67dSChris Pressey 							break;
62821ece67dSChris Pressey 						tmp = delim;
62921ece67dSChris Pressey 					}
63021ece67dSChris Pressey 				}
63121ece67dSChris Pressey 			}
63221ece67dSChris Pressey 			/* Set empty language to default language */
63321ece67dSChris Pressey 			if (lng[0] == '\0')
63421ece67dSChris Pressey 				lg = lang_default;
63521ece67dSChris Pressey 			else
63621ece67dSChris Pressey 				lg = lng;
63721ece67dSChris Pressey 
63821ece67dSChris Pressey 
63921ece67dSChris Pressey 			/* 4) Your choice if it exists
64021ece67dSChris Pressey 			 * 3) Long match eg. en_GB.ISO8859-1 is equal to
64121ece67dSChris Pressey 			 *      en_..\.ISO8859-1
64221ece67dSChris Pressey 			 * 2) short match 'de'
64321ece67dSChris Pressey 			 * 1) default langlist 'en'
64421ece67dSChris Pressey 			 * 0) any language
64521ece67dSChris Pressey 			 *
64621ece67dSChris Pressey 			 * Language may be a comma separated list
64721ece67dSChris Pressey 			 * A higher match overwrites a lower
64821ece67dSChris Pressey 			 * A later entry overwrites a previous if it exists
64921ece67dSChris Pressey 			 *     twice in the database
65021ece67dSChris Pressey 			 */
65121ece67dSChris Pressey 
65221ece67dSChris Pressey 			/* Check for favoured language */
65321ece67dSChris Pressey 			km = get_keymap(keym);
65421ece67dSChris Pressey 			mark = (km) ? km->mark : 0;
65521ece67dSChris Pressey 
65621ece67dSChris Pressey 			if (find_token(lg, lang))
65721ece67dSChris Pressey 				add_keymap(desc, 4, keym);
65821ece67dSChris Pressey 			else if (mark <= 3 && find_token(lg, dialect))
65921ece67dSChris Pressey 				add_keymap(desc, 3, keym);
66021ece67dSChris Pressey 			else if (mark <= 2 && find_token(lg, lang_abk))
66121ece67dSChris Pressey 				add_keymap(desc, 2, keym);
66221ece67dSChris Pressey 			else if (mark <= 1 && find_token(lg, lang_default))
66321ece67dSChris Pressey 				add_keymap(desc, 1, keym);
66421ece67dSChris Pressey 			else if (mark <= 0)
66521ece67dSChris Pressey 				add_keymap(desc, 0, keym);
66621ece67dSChris Pressey 		}
66721ece67dSChris Pressey 		fclose(fp);
66821ece67dSChris Pressey 
66921ece67dSChris Pressey 	} else
67021ece67dSChris Pressey 		printf("Could not open file\n");
67121ece67dSChris Pressey 
67221ece67dSChris Pressey 	if (show) {
67321ece67dSChris Pressey 		qsort(lang_list->sl_str, lang_list->sl_cur, sizeof(char*),
67421ece67dSChris Pressey 		    compare_lang);
67521ece67dSChris Pressey 		printf("Currently supported languages: ");
67621ece67dSChris Pressey 		for (i=0; i< (int) lang_list->sl_cur; i++)
67721ece67dSChris Pressey 			printf("%s ", lang_list->sl_str[i]);
67821ece67dSChris Pressey 		puts("");
67921ece67dSChris Pressey 		exit(0);
68021ece67dSChris Pressey 	}
68121ece67dSChris Pressey 
68221ece67dSChris Pressey 	km = get_keymap("MENU");
68321ece67dSChris Pressey 	if (km)
68421ece67dSChris Pressey 		/* Take note of menu title */
68521ece67dSChris Pressey 		menu = strdup(km->desc);
68621ece67dSChris Pressey 	km = get_keymap("FONT");
68721ece67dSChris Pressey 	if (km)
68821ece67dSChris Pressey 		/* Take note of language font */
68921ece67dSChris Pressey 		font = strdup(km->desc);
69021ece67dSChris Pressey 
69121ece67dSChris Pressey 	/* Remove unwanted items from list */
69221ece67dSChris Pressey 	remove_keymap("MENU");
69321ece67dSChris Pressey 	remove_keymap("FONT");
69421ece67dSChris Pressey 
69521ece67dSChris Pressey 	/* Look for keymaps not in database */
69621ece67dSChris Pressey 	dirp = opendir(dir);
69721ece67dSChris Pressey 	if (dirp) {
69821ece67dSChris Pressey 		while ((dp = readdir(dirp)) != NULL) {
69921ece67dSChris Pressey 			const char *ext = get_extension(dp->d_name);
70021ece67dSChris Pressey 			if (ext) {
70121ece67dSChris Pressey 				if ((!strcmp(ext, ".fnt") ||
70221ece67dSChris Pressey 				    !strcmp(ext, ".kbd")) &&
70321ece67dSChris Pressey 				    !get_keymap(dp->d_name)) {
70421ece67dSChris Pressey 					char *q;
70521ece67dSChris Pressey 
70621ece67dSChris Pressey 					/* Remove any .fnt or .kbd extension */
70721ece67dSChris Pressey 					q = strdup(dp->d_name);
70821ece67dSChris Pressey 					*(get_extension(q)) = '\0';
70921ece67dSChris Pressey 					add_keymap(q, 0, dp->d_name);
71021ece67dSChris Pressey 					free(q);
71121ece67dSChris Pressey 
71221ece67dSChris Pressey 					if (verbose)
71321ece67dSChris Pressey 						fprintf(stderr,
71421ece67dSChris Pressey 						    "'%s' not in database\n",
71521ece67dSChris Pressey 						    dp->d_name);
71621ece67dSChris Pressey 				}
71721ece67dSChris Pressey 			}
71821ece67dSChris Pressey 		}
71921ece67dSChris Pressey 		closedir(dirp);
72021ece67dSChris Pressey 	} else
72121ece67dSChris Pressey 		fprintf(stderr, "Could not open directory '%s'\n", dir);
72221ece67dSChris Pressey 
72321ece67dSChris Pressey 	/* Sort items in keymap */
72421ece67dSChris Pressey 	num_keymaps = get_num_keymaps();
72521ece67dSChris Pressey 
72621ece67dSChris Pressey 	km_sorted = (struct keymap **)
72721ece67dSChris Pressey 	    malloc(num_keymaps*sizeof(struct keymap *));
72821ece67dSChris Pressey 
72921ece67dSChris Pressey 	/* Make array of pointers to items in hash */
73021ece67dSChris Pressey 	items = 0;
73121ece67dSChris Pressey 	SLIST_FOREACH(km, &head, entries)
73221ece67dSChris Pressey 		km_sorted[items++] = km;
73321ece67dSChris Pressey 
73421ece67dSChris Pressey 	/* Change '8x8' to '8x08' so sort works as we might expect... */
73521ece67dSChris Pressey 	kludge_desc(km_sorted, num_keymaps);
73621ece67dSChris Pressey 
73721ece67dSChris Pressey 	qsort(km_sorted, num_keymaps, sizeof(struct keymap *), compare_keymap);
73821ece67dSChris Pressey 
73921ece67dSChris Pressey 	/* ...change back again */
74021ece67dSChris Pressey 	unkludge_desc(km_sorted, num_keymaps);
74121ece67dSChris Pressey 
74221ece67dSChris Pressey 	if (print) {
74321ece67dSChris Pressey 		for (i=0; i<num_keymaps; i++)
74421ece67dSChris Pressey 			printf("%s\n", km_sorted[i]->desc);
74521ece67dSChris Pressey 		exit(0);
74621ece67dSChris Pressey 	}
74721ece67dSChris Pressey 
74821ece67dSChris Pressey 	show_dialog(km_sorted, num_keymaps);
74921ece67dSChris Pressey 
75021ece67dSChris Pressey 	free(km_sorted);
75121ece67dSChris Pressey }
75221ece67dSChris Pressey 
75321ece67dSChris Pressey /*
75421ece67dSChris Pressey  * Display usage information and exit
75521ece67dSChris Pressey  */
75621ece67dSChris Pressey static void
usage(void)75721ece67dSChris Pressey usage(void)
75821ece67dSChris Pressey {
75921ece67dSChris Pressey 
76021ece67dSChris Pressey 	fprintf(stderr, "usage: %s\t[-K] [-V] [-d|-default] [-h|-help] "
76121ece67dSChris Pressey 	    "[-l|-lang language]\n\t\t[-p|-print] [-r|-restore] [-s|-show] "
76221ece67dSChris Pressey 	    "[-v|-verbose]\n", program);
76321ece67dSChris Pressey 	exit(1);
76421ece67dSChris Pressey }
76521ece67dSChris Pressey 
76621ece67dSChris Pressey static void
parse_args(int argc,char ** argv)76721ece67dSChris Pressey parse_args(int argc, char **argv)
76821ece67dSChris Pressey {
76921ece67dSChris Pressey 	int i;
77021ece67dSChris Pressey 
77121ece67dSChris Pressey 	for (i=1; i<argc; i++) {
77221ece67dSChris Pressey 		if (argv[i][0] != '-')
77321ece67dSChris Pressey 			usage();
77421ece67dSChris Pressey 		else if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "-h"))
77521ece67dSChris Pressey 			usage();
77621ece67dSChris Pressey 		else if (!strcmp(argv[i], "-verbose") || !strcmp(argv[i], "-v"))
77721ece67dSChris Pressey 			verbose = 1;
77821ece67dSChris Pressey 		else if (!strcmp(argv[i], "-lang") || !strcmp(argv[i], "-l"))
77921ece67dSChris Pressey 			if (i + 1 == argc)
78021ece67dSChris Pressey 				usage();
78121ece67dSChris Pressey 			else
78221ece67dSChris Pressey 				lang = argv[++i];
78321ece67dSChris Pressey 		else if (!strcmp(argv[i], "-default") || !strcmp(argv[i], "-d"))
78421ece67dSChris Pressey 			lang = lang_default;
78521ece67dSChris Pressey 		else if (!strcmp(argv[i], "-show") || !strcmp(argv[i], "-s"))
78621ece67dSChris Pressey 			show = 1;
78721ece67dSChris Pressey 		else if (!strcmp(argv[i], "-print") || !strcmp(argv[i], "-p"))
78821ece67dSChris Pressey 			print = 1;
78921ece67dSChris Pressey 		else if (!strcmp(argv[i], "-restore") ||
79021ece67dSChris Pressey 		    !strcmp(argv[i], "-r")) {
79121ece67dSChris Pressey 			vidcontrol(font_current);
79221ece67dSChris Pressey 			exit(0);
79321ece67dSChris Pressey 		} else if (!strcmp(argv[i], "-K"))
79421ece67dSChris Pressey 			dir = keymapdir;
79521ece67dSChris Pressey 		else if (!strcmp(argv[i], "-V"))
79621ece67dSChris Pressey 			dir = fontdir;
79721ece67dSChris Pressey 		else
79821ece67dSChris Pressey 			usage();
79921ece67dSChris Pressey 	}
80021ece67dSChris Pressey }
80121ece67dSChris Pressey 
80221ece67dSChris Pressey /*
80321ece67dSChris Pressey  * A front-end for the 'vidfont' and 'kbdmap' programs.
80421ece67dSChris Pressey  */
80521ece67dSChris Pressey int
main(int argc,char ** argv)80621ece67dSChris Pressey main(int argc, char **argv)
80721ece67dSChris Pressey {
80821ece67dSChris Pressey 
80921ece67dSChris Pressey 	x11 = system("kbdcontrol -d >/dev/null");
81021ece67dSChris Pressey 
81121ece67dSChris Pressey 	if (x11) {
81221ece67dSChris Pressey 		fprintf(stderr, "You are not on a virtual console - "
81321ece67dSChris Pressey 				"expect certain strange side-effects\n");
81421ece67dSChris Pressey 		sleep(2);
81521ece67dSChris Pressey 	}
81621ece67dSChris Pressey 
81721ece67dSChris Pressey 	SLIST_INIT(&head);
81821ece67dSChris Pressey 
81921ece67dSChris Pressey 	lang = get_locale();
82021ece67dSChris Pressey 
82121ece67dSChris Pressey 	program = extract_name(argv[0]);
82221ece67dSChris Pressey 
82321ece67dSChris Pressey 	font_current = get_font();
82421ece67dSChris Pressey 	if (font_current == NULL)
82521ece67dSChris Pressey 		font_current = font_default;
82621ece67dSChris Pressey 
82721ece67dSChris Pressey 	if (strcmp(program, "kbdmap"))
82821ece67dSChris Pressey 		dir = fontdir;
82921ece67dSChris Pressey 	else
83021ece67dSChris Pressey 		dir = keymapdir;
83121ece67dSChris Pressey 
832914238a4SSascha Wildner 	/* Parse command line arguments */
833914238a4SSascha Wildner 	parse_args(argc, argv);
834914238a4SSascha Wildner 
83521ece67dSChris Pressey 	/* Read and display options */
83621ece67dSChris Pressey 	menu_read();
83721ece67dSChris Pressey 
83821ece67dSChris Pressey 	return 0;
83921ece67dSChris Pressey }
840