Move lk_ctx content to private part of library
[platform/upstream/kbd.git] / src / loadkeys.c
1 /* loadkeys.c
2  *
3  * This file is part of kbd project.
4  * Copyright (C) 1993  Risto Kankkunen.
5  * Copyright (C) 1993  Eugene G. Crosser.
6  * Copyright (C) 1994-2007  Andries E. Brouwer.
7  * Copyright (C) 2007-2012  Alexey Gladkov <gladkov.alexey@gmail.com>
8  *
9  * This file is covered by the GNU General Public License,
10  * which should be included with kbd as the file COPYING.
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <getopt.h>
17 #include <unistd.h>
18 #include <sys/ioctl.h>
19
20 #include "../config.h"
21 #include "nls.h"
22 #include "kbd.h"
23 #include "paths.h"
24 #include "getfd.h"
25
26 #include "keymap.h"
27
28 static const char *progname = NULL;
29 static const char *const dirpath1[] = { "", DATADIR "/" KEYMAPDIR "/**", KERNDIR "/", 0 };
30 static const char *const suffixes[] = { "", ".kmap", ".map", 0 };
31
32 static void __attribute__ ((noreturn))
33 usage(void)
34 {
35         fprintf(stderr, _("loadkeys version %s\n"
36                           "\n"
37                           "Usage: %s [option...] [mapfile...]\n"
38                           "\n"
39                           "Valid options are:\n"
40                           "\n"
41                           "  -a --ascii         force conversion to ASCII\n"
42                           "  -b --bkeymap       output a binary keymap to stdout\n"
43                           "  -c --clearcompose  clear kernel compose table\n"
44                           "  -C --console=file\n"
45                           "                     the console device to be used\n"
46                           "  -d --default       load \"%s\"\n"
47                           "  -h --help          display this help text\n"
48                           "  -m --mktable       output a \"defkeymap.c\" to stdout\n"
49                           "  -q --quiet         suppress all normal output\n"
50                           "  -s --clearstrings  clear kernel string table\n"
51                           "  -u --unicode       force conversion to Unicode\n"
52                           "  -v --verbose       report the changes\n"),
53                 PACKAGE_VERSION, progname, DEFMAP);
54         exit(EXIT_FAILURE);
55 }
56
57 static inline const char *
58 set_progname(const char *name)
59 {
60         char *p;
61         p = strrchr(name, '/');
62         return (p && p + 1 ? p + 1 : name);
63 }
64
65 int
66 main(int argc, char *argv[])
67 {
68         const char *const short_opts = "abcC:dhmsuqvV";
69         const struct option const long_opts[] = {
70                 { "console", required_argument, NULL, 'C'},
71                 { "ascii",              no_argument, NULL, 'a' },
72                 { "bkeymap",            no_argument, NULL, 'b' },
73                 { "clearcompose",       no_argument, NULL, 'c' },
74                 { "default",            no_argument, NULL, 'd' },
75                 { "help",               no_argument, NULL, 'h' },
76                 { "mktable",            no_argument, NULL, 'm' },
77                 { "clearstrings",       no_argument, NULL, 's' },
78                 { "unicode",            no_argument, NULL, 'u' },
79                 { "quiet",              no_argument, NULL, 'q' },
80                 { "verbose",            no_argument, NULL, 'v' },
81                 { "version",            no_argument, NULL, 'V' },
82                 { NULL, 0, NULL, 0 }
83         };
84
85         enum options {
86                 OPT_A = (1 << 1),
87                 OPT_B = (1 << 2),
88                 OPT_D = (1 << 3),
89                 OPT_M = (1 << 4),
90                 OPT_U = (1 << 5)
91         };
92         int options = 0;
93
94         const char *const *dirpath;
95         const char *dirpath2[] = { 0, 0 };
96
97         struct lk_ctx *ctx;
98         lk_flags flags = 0;
99
100         int c, i, rc = -1;
101         int fd;
102         int kbd_mode;
103         int kd_mode;
104         char *console = NULL;
105         char *ev;
106         lkfile_t f;
107
108         setlocale(LC_ALL, "");
109         bindtextdomain(PACKAGE_NAME, LOCALEDIR);
110         textdomain(PACKAGE_NAME);
111
112         progname = set_progname(argv[0]);
113
114         ctx = lk_init();
115         if (!ctx) {
116                 exit(EXIT_FAILURE);
117         }
118
119         while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
120                 switch (c) {
121                 case 'a':
122                         options |= OPT_A;
123                         break;
124                 case 'b':
125                         options |= OPT_B;
126                         break;
127                 case 'c':
128                         flags |= LK_FLAG_CLEAR_COMPOSE;
129                         break;
130                 case 'C':
131                         console = optarg;
132                         break;
133                 case 'd':
134                         options |= OPT_D;
135                         break;
136                 case 'm':
137                         options |= OPT_M;
138                         break;
139                 case 's':
140                         flags |= LK_FLAG_CLEAR_STRINGS;
141                         break;
142                 case 'u':
143                         options |= OPT_U;
144                         flags |= LK_FLAG_UNICODE_MODE;
145                         flags |= LK_FLAG_PREFER_UNICODE;
146                         break;
147                 case 'q':
148                         lk_set_log_priority(ctx, LOG_ERR);
149                         break;
150                 case 'v':
151                         lk_set_log_priority(ctx, LOG_INFO);
152                         break;
153                 case 'V':
154                         fprintf(stdout, _("%s from %s\n"), progname, PACKAGE_STRING);
155                         exit(0);
156                 case 'h':
157                 case '?':
158                         usage();
159                 }
160         }
161
162         if ((options & OPT_U) && (options & OPT_A)) {
163                 fprintf(stderr,
164                         _("%s: Options --unicode and --ascii are mutually exclusive\n"),
165                         progname);
166                 exit(EXIT_FAILURE);
167         }
168
169         /* get console */
170         fd = getfd(console);
171
172         if (!(options & OPT_M) && !(options & OPT_B)) {
173                 /* check whether the keyboard is in Unicode mode */
174                 if (ioctl(fd, KDGKBMODE, &kbd_mode) ||
175                     ioctl(fd, KDGETMODE, &kd_mode)) {
176                         fprintf(stderr, _("%s: error reading keyboard mode: %m\n"),
177                                 progname);
178                         exit(EXIT_FAILURE);
179                 }
180
181                 if (kbd_mode == K_UNICODE) {
182                         if (options & OPT_A) {
183                                 fprintf(stderr,
184                                         _("%s: warning: loading non-Unicode keymap on Unicode console\n"
185                                           "    (perhaps you want to do `kbd_mode -a'?)\n"),
186                                         progname);
187                         } else {
188                                 flags |= LK_FLAG_PREFER_UNICODE;
189                         }
190
191                         /* reset -u option if keyboard is in K_UNICODE anyway */
192                         flags ^= LK_FLAG_UNICODE_MODE;
193
194                 } else if (options & OPT_U && kd_mode != KD_GRAPHICS) {
195                         fprintf(stderr,
196                                 _("%s: warning: loading Unicode keymap on non-Unicode console\n"
197                                   "    (perhaps you want to do `kbd_mode -u'?)\n"),
198                                 progname);
199                 }
200         }
201
202         lk_set_parser_flags(ctx, flags);
203
204         dirpath = dirpath1;
205         if ((ev = getenv("LOADKEYS_KEYMAP_PATH")) != NULL) {
206                 dirpath2[0] = ev;
207                 dirpath = dirpath2;
208         }
209
210         if (options & OPT_D) {
211                 /* first read default map - search starts in . */
212
213                 if (lk_findfile(DEFMAP, dirpath, suffixes, &f)) {
214                         fprintf(stderr, _("Cannot find %s\n"), DEFMAP);
215                         exit(EXIT_FAILURE);
216                 }
217
218                 if ((rc = lk_parse_keymap(ctx, &f)) == -1)
219                         goto fail;
220
221
222         } else if (optind == argc) {
223                 f.fd = stdin;
224                 strcpy(f.pathname, "<stdin>");
225
226                 if ((rc = lk_parse_keymap(ctx, &f)) == -1)
227                         goto fail;
228         }
229
230         for (i = optind; argv[i]; i++) {
231                 if (!strcmp(argv[i], "-")) {
232                         f.fd = stdin;
233                         strcpy(f.pathname, "<stdin>");
234
235                 } else if (lk_findfile(argv[i], dirpath, suffixes, &f)) {
236                         fprintf(stderr, _("cannot open file %s\n"), argv[i]);
237                         goto fail;
238                 }
239
240                 if ((rc = lk_parse_keymap(ctx, &f)) == -1)
241                         goto fail;
242         }
243
244         if (options & OPT_B) {
245                 rc = lk_dump_bkeymap(ctx, stdout);
246         } else if (options & OPT_M) {
247                 rc = lk_dump_ctable(ctx, stdout);
248         } else {
249                 rc = lk_load_keymap(ctx, fd, kbd_mode);
250         }
251
252  fail:  lk_free(ctx);
253         lk_fpclose(&f);
254         close(fd);
255
256         if (rc < 0)
257                 exit(EXIT_FAILURE);
258
259         exit(EXIT_SUCCESS);
260 }