|
Packit Service |
50ad14 |
#include "config.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include <errno.h>
|
|
Packit Service |
50ad14 |
#include <stdlib.h>
|
|
Packit Service |
50ad14 |
#include <string.h>
|
|
Packit Service |
50ad14 |
#include <sys/ioctl.h>
|
|
Packit Service |
50ad14 |
#include <linux/kd.h>
|
|
Packit Service |
50ad14 |
#include <linux/keyboard.h>
|
|
Packit Service |
50ad14 |
#include <unistd.h>
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include "keymap.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include "nls.h"
|
|
Packit Service |
50ad14 |
#include "kbd.h"
|
|
Packit Service |
50ad14 |
#include "contextP.h"
|
|
Packit Service |
50ad14 |
#include "ksyms.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static int
|
|
Packit Service |
50ad14 |
defkeys(struct lk_ctx *ctx, int fd, int kbd_mode)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
struct kbentry ke;
|
|
Packit Service |
50ad14 |
int ct = 0;
|
|
Packit Service |
50ad14 |
int i, j, fail;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ctx->flags & LK_FLAG_UNICODE_MODE) {
|
|
Packit Service |
50ad14 |
/* temporarily switch to K_UNICODE while defining keys */
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBMODE, K_UNICODE)) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("KDSKBMODE: %s: could not switch to Unicode mode"),
|
|
Packit Service |
50ad14 |
strerror(errno));
|
|
Packit Service |
50ad14 |
goto fail;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (i = 0; i < MAX_NR_KEYMAPS; i++) {
|
|
Packit Service |
50ad14 |
unsigned int exist = lk_map_exists(ctx, i);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (exist) {
|
|
Packit Service |
50ad14 |
for (j = 0; j < NR_KEYS; j++) {
|
|
Packit Service |
50ad14 |
if (!lk_key_exists(ctx, i, j))
|
|
Packit Service |
50ad14 |
continue;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
ke.kb_index = j;
|
|
Packit Service |
50ad14 |
ke.kb_table = i;
|
|
Packit Service |
50ad14 |
ke.kb_value = lk_get_key(ctx, i, j);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
fail = ioctl(fd, KDSKBENT, (unsigned long)&ke;;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (fail) {
|
|
Packit Service |
50ad14 |
if (errno == EPERM) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("Keymap %d: Permission denied"), i);
|
|
Packit Service |
50ad14 |
j = NR_KEYS;
|
|
Packit Service |
50ad14 |
continue;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
ERR(ctx, "%s", strerror(errno));
|
|
Packit Service |
50ad14 |
} else
|
|
Packit Service |
50ad14 |
ct++;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
INFO(ctx, _("keycode %d, table %d = %d%s"),
|
|
Packit Service |
50ad14 |
j, i, lk_get_key(ctx, i, j), fail ? _(" FAILED") : "");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (fail)
|
|
Packit Service |
50ad14 |
WARN(ctx, _("failed to bind key %d to value %d"),
|
|
Packit Service |
50ad14 |
j, lk_get_key(ctx, i, j));
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
} else if ((ctx->keywords & LK_KEYWORD_KEYMAPS) && !exist) {
|
|
Packit Service |
50ad14 |
/* deallocate keymap */
|
|
Packit Service |
50ad14 |
ke.kb_index = 0;
|
|
Packit Service |
50ad14 |
ke.kb_table = i;
|
|
Packit Service |
50ad14 |
ke.kb_value = K_NOSUCHMAP;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
DBG(ctx, _("deallocate keymap %d"), i);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBENT, (unsigned long)&ke)) {
|
|
Packit Service |
50ad14 |
if (errno != EINVAL) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("KDSKBENT: %s: could not deallocate keymap %d"),
|
|
Packit Service |
50ad14 |
strerror(errno), i);
|
|
Packit Service |
50ad14 |
goto fail;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
/* probably an old kernel */
|
|
Packit Service |
50ad14 |
/* clear keymap by hand */
|
|
Packit Service |
50ad14 |
for (j = 0; j < NR_KEYS; j++) {
|
|
Packit Service |
50ad14 |
ke.kb_index = j;
|
|
Packit Service |
50ad14 |
ke.kb_table = i;
|
|
Packit Service |
50ad14 |
ke.kb_value = K_HOLE;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBENT, (unsigned long)&ke)) {
|
|
Packit Service |
50ad14 |
if (errno == EINVAL && i >= 16)
|
|
Packit Service |
50ad14 |
break; /* old kernel */
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
ERR(ctx, _("KDSKBENT: %s: cannot deallocate or clear keymap"),
|
|
Packit Service |
50ad14 |
strerror(errno));
|
|
Packit Service |
50ad14 |
goto fail;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if ((ctx->flags & LK_FLAG_UNICODE_MODE) && ioctl(fd, KDSKBMODE, kbd_mode)) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("KDSKBMODE: %s: could not return to original keyboard mode"),
|
|
Packit Service |
50ad14 |
strerror(errno));
|
|
Packit Service |
50ad14 |
goto fail;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return ct;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
fail:
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static char *
|
|
Packit Service |
50ad14 |
ostr(struct lk_ctx *ctx, char *s)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int lth = strlen(s);
|
|
Packit Service |
50ad14 |
char *ns0 = malloc(4 * lth + 1);
|
|
Packit Service |
50ad14 |
char *ns = ns0;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ns == NULL) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("out of memory"));
|
|
Packit Service |
50ad14 |
return NULL;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
while (*s) {
|
|
Packit Service |
50ad14 |
switch (*s) {
|
|
Packit Service |
50ad14 |
case '\n':
|
|
Packit Service |
50ad14 |
*ns++ = '\\';
|
|
Packit Service |
50ad14 |
*ns++ = 'n';
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case '\033':
|
|
Packit Service |
50ad14 |
*ns++ = '\\';
|
|
Packit Service |
50ad14 |
*ns++ = '0';
|
|
Packit Service |
50ad14 |
*ns++ = '3';
|
|
Packit Service |
50ad14 |
*ns++ = '3';
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
default:
|
|
Packit Service |
50ad14 |
*ns++ = *s;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
s++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
*ns = 0;
|
|
Packit Service |
50ad14 |
return ns0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static int
|
|
Packit Service |
50ad14 |
deffuncs(struct lk_ctx *ctx, int fd)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int i, ct = 0;
|
|
Packit Service |
50ad14 |
char *ptr, *s;
|
|
Packit Service |
50ad14 |
struct kbsentry kbs;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (i = 0; i < MAX_NR_FUNC; i++) {
|
|
Packit Service |
50ad14 |
kbs.kb_func = i;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
ptr = lk_array_get_ptr(ctx->func_table, i);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ptr) {
|
|
Packit Service |
50ad14 |
strcpy((char *)kbs.kb_string, ptr);
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBSENT, (unsigned long)&kbs)) {
|
|
Packit Service |
50ad14 |
s = ostr(ctx, (char *)kbs.kb_string);
|
|
Packit Service |
50ad14 |
if (s == NULL)
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
ERR(ctx, _("failed to bind string '%s' to function %s"),
|
|
Packit Service |
50ad14 |
s, get_sym(ctx, KT_FN, kbs.kb_func));
|
|
Packit Service |
50ad14 |
free(s);
|
|
Packit Service |
50ad14 |
} else {
|
|
Packit Service |
50ad14 |
ct++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
} else if (ctx->flags & LK_FLAG_CLEAR_STRINGS) {
|
|
Packit Service |
50ad14 |
kbs.kb_string[0] = 0;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBSENT, (unsigned long)&kbs)) {
|
|
Packit Service |
50ad14 |
ERR(ctx, _("failed to clear string %s"),
|
|
Packit Service |
50ad14 |
get_sym(ctx, KT_FN, kbs.kb_func));
|
|
Packit Service |
50ad14 |
} else {
|
|
Packit Service |
50ad14 |
ct++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
return ct;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static int
|
|
Packit Service |
50ad14 |
defdiacs(struct lk_ctx *ctx, int fd)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
unsigned int i, j, count;
|
|
Packit Service |
50ad14 |
struct lk_kbdiacr *ptr;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
count = ctx->accent_table->count;
|
|
Packit Service |
50ad14 |
if (count > MAX_DIACR) {
|
|
Packit Service |
50ad14 |
count = MAX_DIACR;
|
|
Packit Service |
50ad14 |
ERR(ctx, _("too many compose definitions"));
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
#ifdef KDSKBDIACRUC
|
|
Packit Service |
50ad14 |
if (ctx->flags & LK_FLAG_PREFER_UNICODE) {
|
|
Packit Service |
50ad14 |
struct kbdiacrsuc kdu;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kdu.kb_cnt = count;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (i = 0, j = 0; i < ctx->accent_table->total && j < count; i++) {
|
|
Packit Service |
50ad14 |
ptr = lk_array_get_ptr(ctx->accent_table, i);
|
|
Packit Service |
50ad14 |
if (!ptr)
|
|
Packit Service |
50ad14 |
continue;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kdu.kbdiacruc[j].diacr = ptr->diacr;
|
|
Packit Service |
50ad14 |
kdu.kbdiacruc[j].base = ptr->base;
|
|
Packit Service |
50ad14 |
kdu.kbdiacruc[j].result = ptr->result;
|
|
Packit Service |
50ad14 |
j++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBDIACRUC, (unsigned long)&kdu)) {
|
|
Packit Service |
50ad14 |
ERR(ctx, "KDSKBDIACRUC: %s", strerror(errno));
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
} else
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
struct kbdiacrs kd;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kd.kb_cnt = count;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (i = 0, j = 0; i < ctx->accent_table->total && j < count; i++) {
|
|
Packit Service |
50ad14 |
ptr = lk_array_get_ptr(ctx->accent_table, i);
|
|
Packit Service |
50ad14 |
if (!ptr)
|
|
Packit Service |
50ad14 |
continue;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kd.kbdiacr[j].diacr = ptr->diacr;
|
|
Packit Service |
50ad14 |
kd.kbdiacr[j].base = ptr->base;
|
|
Packit Service |
50ad14 |
kd.kbdiacr[j].result = ptr->result;
|
|
Packit Service |
50ad14 |
j++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, KDSKBDIACR, (unsigned long)&kd)) {
|
|
Packit Service |
50ad14 |
ERR(ctx, "KDSKBDIACR: %s", strerror(errno));
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return count;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int lk_load_keymap(struct lk_ctx *ctx, int fd, int kbd_mode)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int keyct, funcct, diacct;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (lk_add_constants(ctx) < 0)
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if ((keyct = defkeys(ctx, fd, kbd_mode)) < 0 || (funcct = deffuncs(ctx, fd)) < 0)
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
INFO(ctx, P_("\nChanged %d key", "\nChanged %d keys", keyct), keyct);
|
|
Packit Service |
50ad14 |
INFO(ctx, P_("Changed %d string", "Changed %d strings", funcct), funcct);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ctx->accent_table->count > 0 || ctx->flags & LK_FLAG_CLEAR_COMPOSE) {
|
|
Packit Service |
50ad14 |
diacct = defdiacs(ctx, fd);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (diacct < 0)
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
INFO(ctx, P_("Loaded %d compose definition",
|
|
Packit Service |
50ad14 |
"Loaded %d compose definitions", diacct),
|
|
Packit Service |
50ad14 |
diacct);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
} else {
|
|
Packit Service |
50ad14 |
INFO(ctx, _("(No change in compose definitions)"));
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|