int lk_add_key(struct lk_ctx *ctx, unsigned int k_table, unsigned int k_index, int keycode) { struct lk_array *map; unsigned int code = keycode + 1; if (keycode == CODE_FOR_UNKNOWN_KSYM) { /* is safer not to be silent in this case, * it can be caused by coding errors as well. */ ERR(ctx, _("lk_add_key called with bad keycode %d"), keycode); return -1; } if (!k_index && keycode == K_NOSUCHMAP) return 0; map = lk_array_get_ptr(ctx->keymap, k_table); if (!map) { if (ctx->keywords & LK_KEYWORD_KEYMAPS) { ERR(ctx, _("adding map %d violates explicit keymaps line"), k_table); return -1; } if (lk_add_map(ctx, k_table) < 0) return -1; } if ((ctx->keywords & LK_KEYWORD_ALTISMETA) && keycode == K_HOLE && lk_key_exists(ctx, k_table, k_index)) return 0; map = lk_array_get_ptr(ctx->keymap, k_table); if (lk_array_set(map, k_index, &code) < 0) { ERR(ctx, _("unable to set key %d for table %d"), k_index, k_table); return -1; } if (ctx->keywords & LK_KEYWORD_ALTISMETA) { unsigned int alttable = k_table | M_ALT; int type = KTYP(keycode); int val = KVAL(keycode); if (alttable != k_table && lk_map_exists(ctx, alttable) && !lk_key_exists(ctx, alttable, k_index) && (type == KT_LATIN || type == KT_LETTER) && val < 128) { if (lk_add_key(ctx, alttable, k_index, K(KT_META, val)) < 0) return -1; } } return 0; }
static int do_constant_key(struct lk_ctx *ctx, int i, unsigned short key) { int typ, val; unsigned int j; typ = KTYP(key); val = KVAL(key); if ((typ == KT_LATIN || typ == KT_LETTER) && ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'))) { unsigned short defs[16]; defs[0] = K(KT_LETTER, val); defs[1] = K(KT_LETTER, val ^ 32); defs[2] = defs[0]; defs[3] = defs[1]; for (j = 4; j < 8; j++) defs[j] = K(KT_LATIN, val & ~96); for (j = 8; j < 16; j++) defs[j] = K(KT_META, KVAL(defs[j - 8])); for (j = 0; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (j > 0 && lk_key_exists(ctx, j, i)) continue; if (lk_add_key(ctx, j, i, defs[j % 16]) < 0) return -1; } } else { /* do this also for keys like Escape, as promised in the man page */ for (j = 1; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (lk_key_exists(ctx, j, i)) continue; if (lk_add_key(ctx, j, i, key) < 0) return -1; } } return 0; }
static int defkeys(struct lk_ctx *ctx, int fd, int kbd_mode) { struct kbentry ke; int ct = 0; int i, j, fail; if (ctx->flags & LK_FLAG_UNICODE_MODE) { /* temporarily switch to K_UNICODE while defining keys */ if (ioctl(fd, KDSKBMODE, K_UNICODE)) { ERR(ctx, _("KDSKBMODE: %s: could not switch to Unicode mode"), strerror(errno)); goto fail; } } for (i = 0; i < MAX_NR_KEYMAPS; i++) { int exist = lk_map_exists(ctx, i); if (exist) { for (j = 0; j < NR_KEYS; j++) { if (!lk_key_exists(ctx, i, j)) continue; int value = lk_get_key(ctx, i, j); if (value < 0 || value > USHRT_MAX) { WARN(ctx, _("can not bind key %d to value %d because it is too large"), j, value); continue; } ke.kb_index = (unsigned char) j; ke.kb_table = (unsigned char) i; ke.kb_value = (unsigned short) value; fail = ioctl(fd, KDSKBENT, (unsigned long)&ke); if (fail) { if (errno == EPERM) { ERR(ctx, _("Keymap %d: Permission denied"), i); j = NR_KEYS; continue; } ERR(ctx, "%s", strerror(errno)); } else ct++; INFO(ctx, _("keycode %d, table %d = %d%s"), j, i, ke.kb_value, fail ? _(" FAILED") : ""); if (fail) WARN(ctx, _("failed to bind key %d to value %d"), j, ke.kb_value); } } else if ((ctx->keywords & LK_KEYWORD_KEYMAPS) && !exist) { /* deallocate keymap */ ke.kb_index = 0; ke.kb_table = (unsigned char) i; ke.kb_value = K_NOSUCHMAP; DBG(ctx, _("deallocate keymap %d"), i); if (ioctl(fd, KDSKBENT, (unsigned long)&ke)) { if (errno != EINVAL) { ERR(ctx, _("KDSKBENT: %s: could not deallocate keymap %d"), strerror(errno), i); goto fail; } /* probably an old kernel */ /* clear keymap by hand */ for (j = 0; j < NR_KEYS; j++) { ke.kb_index = (unsigned char) j; ke.kb_table = (unsigned char) i; ke.kb_value = K_HOLE; if (ioctl(fd, KDSKBENT, (unsigned long)&ke)) { if (errno == EINVAL && i >= 16) break; /* old kernel */ ERR(ctx, _("KDSKBENT: %s: cannot deallocate or clear keymap"), strerror(errno)); goto fail; } } } } } if ((ctx->flags & LK_FLAG_UNICODE_MODE) && ioctl(fd, KDSKBMODE, kbd_mode)) { ERR(ctx, _("KDSKBMODE: %s: could not return to original keyboard mode"), strerror(errno)); goto fail; } return ct; fail: return -1; }