// vim: nowrap #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define XkbConfigFile "/usr/X11R6/lib/X11/xkb/X0-config.keyboard" #define CONFPATH "%A," "%R," \ "/etc/X11/%R," "%P/etc/X11/%R," \ "%E," "%F," \ "/etc/X11/%F," "%P/etc/X11/%F," \ "%D/%X," \ "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ "%P/etc/X11/%X," \ "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ "%P/lib/X11/%X" #define LAYOUTNAME 0 #define LAYOUTDESC 1 #define MODELNAME 2 #define MODELDESC 3 #define CURLAYOUT 4 #define CURMODEL 5 #define ALL 6 XF86ConfigPtr XF86Config; XF86ConfInputPtr keyboard; /* * Types */ typedef struct { char **name; char **desc; int nelem; } XF86XkbDescInfo; typedef struct { XkbDescPtr xkb; XkbRF_VarDefsRec defs; XkbConfigRtrnRec config; } XkbInfo; static XF86XkbDescInfo xkb_model; static XF86XkbDescInfo xkb_layout; static char *XkbRulesFile = "/usr/X11R6/lib/X11/xkb/rules/xfree86"; static char *model, *layout; XkbInfo *xkb_info; Display *display; int ErrorF(const char *fmt, ...) { int retval; va_list ap; va_start(ap, fmt); retval = vfprintf(stderr, fmt, ap); va_end(ap); return (retval); } int VErrorF(const char *fmt, va_list ap) { int retval; retval = vfprintf(stderr, fmt, ap); return (retval); } int InitializeKeyboard(void) { static int first = 1; XkbRF_RulesPtr list; XF86OptionPtr option; int i; FILE *file; if (!first) return (0); first = 0; xkb_info = (XkbInfo *)calloc(1, sizeof(XkbInfo)); if (display) { int major, minor, op, event, error; int timeout = 5; if (XkbQueryExtension(display, &op, &event, &error, &major, &minor) == 0) { fprintf(stderr, "Unable to initialize XKEYBOARD extension"); exit(1); } while (timeout > 0) { xkb_info->xkb = XkbGetKeyboard(display, XkbGBN_AllComponentsMask, XkbUseCoreKbd); if (xkb_info->xkb == NULL || xkb_info->xkb->geom == NULL) { timeout -= 1; sleep(1); } else break; } if (timeout <= 0) { fprintf(stderr, "Couldn't get keyboard\n"); exit(1); } xkb_info->xkb = XkbGetKeyboard(display, XkbGBN_AllComponentsMask, XkbUseCoreKbd); if (xkb_info->xkb->names->geometry == 0) xkb_info->xkb->names->geometry = xkb_info->xkb->geom->name; } bzero((char*)&(xkb_info->defs), sizeof(XkbRF_VarDefsRec)); if ((list = XkbRF_Create(0, 0)) == NULL || !XkbRF_LoadDescriptionsByName(XkbRulesFile, NULL, list)) { fprintf(stderr, "Can't create rules structure\n"); return (1); } for (i = 0; i < list->models.num_desc; i++) { if (i % 16 == 0) { xkb_model.name = (char**)realloc(xkb_model.name, (i + 16) * sizeof(char*)); xkb_model.desc = (char**)realloc(xkb_model.desc, (i + 16) * sizeof(char*)); } xkb_model.name[i] = strdup(list->models.desc[i].name); xkb_model.desc[i] = strdup(list->models.desc[i].desc); } xkb_model.nelem = i; for (i = 0; i < list->layouts.num_desc; i++) { if (i % 16 == 0) { xkb_layout.name = (char**)realloc(xkb_layout.name, (i + 16) * sizeof(char*)); xkb_layout.desc = (char**)realloc(xkb_layout.desc, (i + 16) * sizeof(char*)); } xkb_layout.name[i] = strdup(list->layouts.desc[i].name); xkb_layout.desc[i] = strdup(list->layouts.desc[i].desc); } xkb_layout.nelem = i; XkbRF_Free(list, True); /* Load configuration */ file = fopen(XkbConfigFile, "r"); if (file != NULL) { if (XkbCFParse(file, XkbCFDflts, xkb_info->xkb, &xkb_info->config) == 0) { fprintf(stderr, "Error parsing config file: "); XkbCFReportError(stderr, XkbConfigFile, xkb_info->config.error, xkb_info->config.line); } fclose(file); } while (keyboard != NULL) { if (strcasecmp(keyboard->inp_driver, "keyboard") == 0) break; keyboard = (XF86ConfInputPtr)(keyboard->list.next); } if (keyboard == NULL) return; if (xkb_info->config.model != NULL) xkb_info->defs.model = xkb_info->config.model; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbModel")) != NULL) xkb_info->defs.model = option->opt_val; else xkb_info->defs.model = xkb_model.name[0]; model = xkb_info->defs.model; if (xkb_info->config.layout != NULL) xkb_info->defs.layout = xkb_info->config.layout; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbLayout")) != NULL) xkb_info->defs.layout = option->opt_val; else xkb_info->defs.layout = xkb_layout.name[0]; layout = xkb_info->defs.layout; return (0); } Bool WriteXKBConfiguration(char *model, char *layout) { FILE *fp; int i, count; if ((fp = fopen(XkbConfigFile, "w")) == NULL) return (False); if (model != NULL) fprintf(fp, "Model = \"%s\"\n", model); if (layout != NULL) fprintf(fp, "Layout = \"%s\"\n", layout); fclose(fp); return (True); } void UpdateKeyboard(Bool load) { static XkbRF_RulesPtr rules; XkbComponentNamesRec comps; XkbDescPtr xkb; if (rules == NULL) { FILE *fp; if ((fp = fopen(XkbRulesFile, "r")) == NULL) { fprintf(stderr, "Can't open rules file\n"); exit(1); } if ((rules = XkbRF_Create(0, 0)) == NULL) { fclose(fp); fprintf(stderr, "Can't create rules structure\n"); exit(1); } if (!XkbRF_LoadRules(fp, rules)) { fclose(fp); XkbRF_Free(rules, True); fprintf(stderr, "Can't load rules\n"); exit(1); } fclose(fp); } bzero((char*)&comps, sizeof(XkbComponentNamesRec)); XkbRF_GetComponents(rules, &(xkb_info->defs), &comps); xkb = XkbGetKeyboardByName(display, XkbUseCoreKbd, &comps, //HERE XkbGBN_AllComponentsMask, 0, load); if (xkb == NULL || xkb->geom == NULL) { fprintf(stderr, "Couldn't get keyboard\n"); exit(1); } if (xkb->names->geometry == 0) xkb->names->geometry = xkb->geom->name; XkbFreeKeyboard(xkb_info->xkb, 0, False); xkb_info->xkb = xkb; free(comps.keymap); free(comps.keycodes); free(comps.compat); free(comps.types); free(comps.symbols); free(comps.geometry); } void cleanstruct() { int i; free (xkb_info); for (i=0; iconf_input_lst; // inicializa teclado InitializeKeyboard(); switch (opt){ case ALL: printf ("--- LAYOUT ---\n"); for (i = 0; i < xkb_layout.nelem; i++) { printf ("%s", xkb_layout.name[i]); printf ("%32s\n", xkb_layout.desc[i]); } printf ("--- MODEL ---\n"); for (i = 0; i < xkb_model.nelem; i++) { printf ("%s", xkb_model.name[i]); printf ("%32s\n", xkb_model.desc[i]); } break; case LAYOUTNAME: for (i = 0; i < xkb_layout.nelem; i++) { printf ("%s\n", xkb_layout.name[i]); } break; case LAYOUTDESC: for (i = 0; i < xkb_layout.nelem; i++) { printf ("%s\n", xkb_layout.desc[i]); } break; case MODELNAME: for (i = 0; i < xkb_model.nelem; i++) { printf ("%s\n", xkb_model.name[i]); } break; case MODELDESC: for (i = 0; i < xkb_model.nelem; i++) { printf ("%s\n", xkb_model.desc[i]); } break; case CURLAYOUT: printf ("%s\n", layout); break; case CURMODEL: printf ("%s\n", model); } xf86freeConfig(XF86Config); //se display esta aberto, limpa display //if (display) // XCloseDisplay(display); cleanstruct(); } void setconfig(char *mdl, char *lt) { int i; XF86OptionPtr option; const char *filename; // abre o display //display = XOpenDisplay(NULL); // abre o arquivo de configuracao do XF86Config if ((filename = xf86openConfigFile(CONFPATH, NULL, NULL)) == NULL) { fprintf(stderr, "Cannot to open config file.\n"); exit(1); } // le os dados para XF86Config if ((XF86Config = xf86readConfigFile()) == NULL) { fprintf(stderr, "Problem when parsing config file\n"); exit(1); } // armazena em um ponteiro do tipo XF86ConfInputPtr o conteudo de input list keyboard = XF86Config->conf_input_lst; // inicializa teclado InitializeKeyboard(); model = mdl; layout = lt; // passa para xbd_info os modelos a serem alterados xkb_info->defs.model = model; xkb_info->defs.layout = layout; // Atualização dinâmica do teclado no X //UpdateKeyboard(True); // Salva em xkb/X0-config.keyboard WriteXKBConfiguration(model, layout); // Salva no XF86Config // verifica se consegue encontrar o XkbModel if ((option = xf86findOption(keyboard->inp_option_lst, "XkbModel")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbModel", model); else { free(option->opt_val); option->opt_val = strdup(model); } // verifica se consegue encontrar o XkbLayout if ((option = xf86findOption(keyboard->inp_option_lst, "XkbLayout")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbLayout", layout); else { free(option->opt_val); option->opt_val = strdup(layout); } // salva os dados xf86writeConfigFile(filename, XF86Config); xf86freeConfig(XF86Config); //se display esta aberto, limpa display //if (display) // XCloseDisplay(display); exit(0); } void setlayoutconfig(char *lt) { int i; XF86OptionPtr option; const char *filename; // abre o display //display = XOpenDisplay(NULL); // abre o arquivo de configuracao do XF86Config if ((filename = xf86openConfigFile(CONFPATH, NULL, NULL)) == NULL) { fprintf(stderr, "Cannot to open config file.\n"); exit(1); } // le os dados para XF86Config if ((XF86Config = xf86readConfigFile()) == NULL) { fprintf(stderr, "Problem when parsing config file\n"); exit(1); } // armazena em um ponteiro do tipo XF86ConfInputPtr o conteudo de input list keyboard = XF86Config->conf_input_lst; // inicializa teclado InitializeKeyboard(); layout = lt; // passa para xbd_info os modelos a serem alterados xkb_info->defs.model = model; xkb_info->defs.layout = layout; // Atualização dinâmica do teclado no X //UpdateKeyboard(True); // Salva em xkb/X0-config.keyboard WriteXKBConfiguration(model, layout); // Salva no XF86Config // verifica se consegue encontrar o XkbModel if ((option = xf86findOption(keyboard->inp_option_lst, "XkbModel")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbModel", model); else { free(option->opt_val); option->opt_val = strdup(model); } // verifica se consegue encontrar o XkbLayout if ((option = xf86findOption(keyboard->inp_option_lst, "XkbLayout")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbLayout", layout); else { free(option->opt_val); option->opt_val = strdup(layout); } // salva os dados xf86writeConfigFile(filename, XF86Config); xf86freeConfig(XF86Config); //se display esta aberto, limpa display //if (display) // XCloseDisplay(display); exit(0); } void setmodelconfig(char *mdl) { int i; XF86OptionPtr option; const char *filename; // abre o display //display = XOpenDisplay(NULL); // abre o arquivo de configuracao do XF86Config if ((filename = xf86openConfigFile(CONFPATH, NULL, NULL)) == NULL) { fprintf(stderr, "Cannot to open config file.\n"); exit(1); } // le os dados para XF86Config if ((XF86Config = xf86readConfigFile()) == NULL) { fprintf(stderr, "Problem when parsing config file\n"); exit(1); } // armazena em um ponteiro do tipo XF86ConfInputPtr o conteudo de input list keyboard = XF86Config->conf_input_lst; // inicializa teclado InitializeKeyboard(); model = mdl; // passa para xbd_info os modelos a serem alterados xkb_info->defs.model = model; xkb_info->defs.layout = layout; // Atualização dinâmica do teclado no X //UpdateKeyboard(True); // Salva em xkb/X0-config.keyboard WriteXKBConfiguration(model, layout); // Salva no XF86Config // verifica se consegue encontrar o XkbModel if ((option = xf86findOption(keyboard->inp_option_lst, "XkbModel")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbModel", model); else { free(option->opt_val); option->opt_val = strdup(model); } // verifica se consegue encontrar o XkbLayout if ((option = xf86findOption(keyboard->inp_option_lst, "XkbLayout")) == NULL) keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, "XkbLayout", layout); else { free(option->opt_val); option->opt_val = strdup(layout); } // salva os dados xf86writeConfigFile(filename, XF86Config); xf86freeConfig(XF86Config); //se display esta aberto, limpa display //if (display) // XCloseDisplay(display); exit(0); } void update(void) { int i; XF86OptionPtr option; const char *filename; // abre o display display = XOpenDisplay(NULL); // abre o arquivo de configuracao do XF86Config if ((filename = xf86openConfigFile(CONFPATH, NULL, NULL)) == NULL) { fprintf(stderr, "Cannot to open config file.\n"); exit(1); } // le os dados para XF86Config if ((XF86Config = xf86readConfigFile()) == NULL) { fprintf(stderr, "Problem when parsing config file\n"); exit(1); } // armazena em um ponteiro do tipo XF86ConfInputPtr o conteudo de input list keyboard = XF86Config->conf_input_lst; // inicializa teclado InitializeKeyboard(); //model = mdl; //layout = lt; // passa para xbd_info os modelos a serem alterados xkb_info->defs.model = model; xkb_info->defs.layout = layout; // Atualização dinâmica do teclado no X UpdateKeyboard(True); xf86freeConfig(XF86Config); //se display esta aberto, limpa display if (display) XCloseDisplay(display); exit(0); } void isaccessible(void) { const char *filename; // abre o display display = XOpenDisplay(NULL); // abre o arquivo de configuracao do XF86Config if ((filename = xf86openConfigFile(CONFPATH, NULL, NULL)) == NULL) { fprintf(stderr, "Cannot to open config file.\n"); exit(1); } // le os dados para XF86Config if ((XF86Config = xf86readConfigFile()) == NULL) { fprintf(stderr, "Problem when parsing config file\n"); exit(1); } exit(0); } int main(int argc, char *argv[]) { if (argc > 1){ if (strcmp(argv[1], "--listlayoutnames")==0){ list(LAYOUTNAME); exit(0); } else if (strcmp(argv[1], "--listlayoutdesc")==0){ list(LAYOUTDESC); exit(0); } else if (strcmp(argv[1], "--listmodelnames")==0){ list(MODELNAME); exit(0); } else if (strcmp(argv[1], "--listmodeldesc")==0){ list(MODELDESC); exit(0); } else if (strcmp(argv[1], "--getlayout")==0){ list (CURLAYOUT); exit(0); } else if (strcmp(argv[1], "--getmodel")==0){ list (CURMODEL); exit(0); } else if (strcmp(argv[1], "--list")==0){ list (ALL); exit(0); } else if (strcmp(argv[1], "--setconfig")==0 && argc==4){ setconfig (argv[2],argv[3]); } else if (strcmp(argv[1], "--setmodelconfig")==0 && argc==3){ setmodelconfig (argv[2]); } else if (strcmp(argv[1], "--setlayoutconfig")==0 && argc==3){ setlayoutconfig (argv[2]); } else if (strcmp(argv[1], "--updatekeyboard")==0){ update (); } else if (strcmp(argv[1], "--isaccessible")==0){ isaccessible (); } else if (strcmp(argv[1], "--havedisplay")==0){ //abre o display display = XOpenDisplay(NULL); if (display==NULL){ printf ("no\n"); } else { printf ("yes\n"); } exit(0); } else if (strcmp(argv[1], "--version")==0){ display = XOpenDisplay(NULL); if (display){ printf("%d\n",VendorRelease(display)/1000); } else { printf("-1\n"); } exit(0); } } fprintf (stderr, "Invalid option\n"); fprintf (stderr, "--listlayoutnames List all X11 layout names\n"); fprintf (stderr, "--listlayoutdesc List all X11 layout descriptions\n"); fprintf (stderr, "--listmodelnames List all X11 model names\n"); fprintf (stderr, "--listmodeldesc List all X11 model descriptions\n"); fprintf (stderr, "--list List all X11 model names/desc and layout names/desc\n"); fprintf (stderr, "--getlayout Get the current layout\n"); fprintf (stderr, "--getmodel Get the current model\n"); fprintf (stderr, "--setconfig Set the new model and layout\n"); fprintf (stderr, "--setmodelconfig Set the new model\n"); fprintf (stderr, "--setlayoutconfig Set the new layout\n"); fprintf (stderr, "--havedisplay check if display can be accessible. yes/no\n"); fprintf (stderr, "--updatekeyboard update the keyboard if the display can be accessed\n"); fprintf (stderr, "--isaccessible check if the /etc/X11/XF86Config-4 is accessible\n"); fprintf (stderr, "--version check the version of XFree86\n"); }