// vim: nowrap /* OBS.: All methods marqued with '*' in its DESCRIPTION have part of its code pasted from kbdconfig */ #pragma implementation #include #include #include #include #include #include #include #include #include #include #include #include "data.h" #include "paths.h" extern CONFIG_FILE f_keyboard; extern HELP_FILE help_nill; static DATALIST *loaded_data = NULL; static int loaded_count = 0; DATALIST *data_load() { if (loaded_data == NULL) loaded_data = new DATALIST(0); loaded_count++; return loaded_data; } void data_unload() { loaded_count--; if (loaded_count==0){ delete loaded_data; loaded_data = NULL; } } PUBLIC DATA::DATA(const char *_name, const char *_desc){ name = new SSTRING(_name); if (_desc != NULL) desc = new SSTRING(_desc); else desc = name; } PUBLIC DATA::DATA(const char *_name){ name = new SSTRING(_name); desc = name; } PUBLIC DATA::~DATA(){ delete (name); if (name != desc) delete (desc); name = NULL; desc = NULL; } /* DESCRIPTION: The constructor only sets the keyboardtype and define the default keymap. */ PUBLIC DATALIST::DATALIST(int verbose_) { verbose = verbose_; defkeytable = "us-acentos"; keyboardtype = -1; // defining keyboardtype #ifdef __sparc__ keyboardtype = checkSunKeyboard(); #else keyboardtype = KBDTYPE_PC; #endif } PUBLIC DATALIST::~DATALIST() { } /* DESCRIPTION: * Initialization. Read the configuration. Copy the current configuration. Check the keyboardtype for sparc. RETURN: 0 if no inicialization 1 if Ok */ PUBLIC int DATALIST::init() { int ret = 0; if (readcfg()==-1) return ret; #ifdef __sparc__ if (keyboardtype == -1) keyboardtype = KBDTYPE_SUN; if (keyboardtype == KBDTYPE_PC) keymapdir = KEYMAPDIRPC; else keymapdir = KEYMAPDIRSUN; if (keyboardtype == KBDTYPE_SUN && keytable.is_empty()) keytable.setfrom("sunkeymap"); else if (keytable.is_empty()) keytable.setfrom("us"); #endif if (keytable.is_empty()) keytable.setfrom("us"); if (keyboardtype == KBDTYPE_SERIAL) { if (verbose){ xconf_notice (MSG_U(N_SERIALCONSOLE,"Serial console\n"), MSG_U(N_SERIALCONSOLEDESC,"No keymap will be loaded on serial console")); } if ((unlink (ETC_SYSCONFIG_KEYBOARD) < 0 && errno != ENOENT) && verbose) { char buf[100]; sprintf (buf,MSG_U(E_COULDNTREMOVE,"coldn't remove %s: %s"),ETC_SYSCONFIG_KEYBOARD,strerror(errno)); xconf_error (buf); } if (!access(ETC_SYSCONFIG_CONSOLE,W_OK)) { if ((unlink (ETC_SYSCONFIG_CONSOLE_DEFAULTKMAP) < 0 && errno != ENOENT) && verbose) { char buf[100]; sprintf (buf,MSG_R(E_COULDNTREMOVE),ETC_SYSCONFIG_CONSOLE_DEFAULTKMAP,strerror(errno)); xconf_error (buf); } } return ret; } ret = 1; return ret; } PRIVATE DATA *DATALIST::getitem(int no) { return (DATA*)ARRAY::getitem(no); } /* DESCRIPTION: * Read the cfg file pointed by external CONFIG_FILE object in kbdconf.cc. The configuration is stored in 'keytable' and 'keyboardtype' class variables. RETURN: -1 if any error 0 if success */ PUBLIC int DATALIST::readcfg(){ int ret = -1; const char *s; char *se; VIEWITEMS items; if (items.read (f_keyboard)!=0){ if (verbose) xconf_error (MSG_U(E_FILECANTBEREAD,"The file '%s' can't be read"), f_keyboard.getpath()); return ret; } char tmp[256]; s = items.locateval ("KEYTABLE", tmp); if (s){ s = basename(s); se = (char *)s + strlen(s) - 2; if (!strncmp(se-3, ".map", 4)) { //verifica se existe a extensao '.map' se -= 3; //e caso exista retira a extensao e coploca o '\0' *se = '\0'; } keytable.setfrom(s); ret = 0; } s = items.locateval ("KEYBOARDTYPE", tmp); if (s){ #ifdef __sparc__ if (!strcasecmp (s, "sun")){ if (keyboardtype==-1) keyboardtype = KBDTYPE_SUN; } else #endif if (!strcasecmp (s, "pc")) { if (keyboardtype == -1) keyboardtype = KBDTYPE_PC; } else { #ifdef __sparc__ if (verbose){ xconf_error (MSG_U(E_KBDHASTOBESUNORPC, "KEYBOARDTYPE has to be either \"sun\" or \"pc\"\n" "The module will switch KEYBOARDTYPE to \"pc\" by default")); } #else if (verbose){ xconf_error (MSG_U(E_KBDHASTOBEPC, "KEYBOARDTYPE has to be \"pc\"\n" "The module will change KEYBOARDTYPE to \"pc\" by default")); } #endif keyboardtype = 0; } } return ret; } /* DESCRIPTION: * Only for sparc. Check if we have a sun keyboard. Not tested. RETURN: KBDTYPE_SUN 0 KBDTYPE_PC 1 KBDTYPE_SERIAL 2 */ #ifdef __sparc__ PRIVATE int DATALIST::checkSunKeyboard (){ int fd, fdstd = 0; char twelve = 12; char buf[50]; /* Test for serial console */ for (fd = 0; fd <= 2; fd++) { sprintf (buf, "%s%d", PROC_SELF_FD, fd); if (readlink (buf, buf, 4096) == 12 && !strncmp (buf, DEV_CONSOLE, 12)) { fdstd = 1; break; } } if (!fdstd) { fd = open(DEV_CONSOLE, O_RDONLY); if (fd < 0) return -1; } if (ioctl (fd, TIOCLINUX, &twelve) < 0) { if (!fdstd) close(fd); return KBDTYPE_SERIAL; } if (!fdstd) close(fd); fd = open(DEV_KBD, O_RDONLY); if (fd < 0) return KBDTYPE_PC; close(fd); return KBDTYPE_SUN; } #endif /* DESCRIPTION: * Gets the keymaps in KEYMAPDIR and store its maps in SSTRINGS. RETURN: Nothing */ PUBLIC void DATALIST::getKeyboardConfig (DEVICELIST &dev){ char start[255]; DIR *mapdir=NULL; struct dirent *ent; char * fullDirStack[50]; char ** dirStack = fullDirStack; char * fullName; char * currDir; struct stat sb; *dirStack++ = NULL; *dirStack = strdup(KEYMAPDIR); while (*dirStack) { //disStack aponta para um diretorio currDir = *dirStack--; mapdir = opendir(currDir); if (!mapdir) { free(currDir); return; } errno = 0; ent = readdir(mapdir); if (errno) { free(currDir); return; } while (ent) { char *t; strcpy(start, ent->d_name); //para cada arquivo verifica se possui a extensao .kmap ou .map if ((t=strstr(start, ".kmap")) || (t=strstr(start, ".map"))) { *t = '\0'; //para entao colocar um ponteiro ali, com o objetivo de ignorar esta extensao const char *s = NULL; DEVICE *d = dev.getitem_by_name(start); if (d) s = d->descr; add (new DATA(start, s)); } else if (ent->d_name[0] != '.') { //não possui '.kmap' ou '.map' e não comeca por '.' fullName = (char *)malloc(strlen(ent->d_name) + strlen(currDir) + 2); sprintf(fullName, "%s/%s", currDir, ent->d_name); stat(fullName, &sb); //entao ele deve verificar se o bendito é um diretorio if (S_ISDIR(sb.st_mode)) { //se for um diretorio *(++dirStack) = fullName; } else { free(fullName); } } ent = readdir(mapdir); //ler a proxima entrada if (errno) { remove_all(); } } free(currDir); } closedir(mapdir); } /* DESCRIPTION: Point tha layout descriptions in SSTRINGS dest RETURN: Nothing */ PUBLIC void DATALIST::getlistmodels(SSTRINGS &dest) { for (int i=0; idesc); } } /* DESCRIPTION: * Check if the values of 'keytable' was changed. If YES, save the changes. RETURN: 0 if fail 1 if success */ PUBLIC int DATALIST::save () { int ret = 0; VIEWITEMS items; //(vip); if (items.read (f_keyboard)==0){ items.update ("KEYTABLE", keytable); #ifdef __sparc__ items.update ("KEYBOARDTYPE", keyboardtype == KBDTYPE_PC ? "pc" : "sun"); #else VIEWITEM *it = items.locate ("KEYBOARDTYPE"); if (it) items.remove_del(it); #endif if (items.write(f_keyboard, NULL)==0){ ret = 1; } } return ret; } /* DESCRIPTION: RETURN: */ PUBLIC int DATALIST::save (const char *name) { keytable.setfrom(name); return save(); } /* DESCRIPTION: Search in datalist the description for name RETURN: a pointer for description NULL if the description can't be found */ PUBLIC const char *DATALIST::getdescbyname (const char *name) { for (int i=0; iname->cmp(name)==0) return d->desc->get(); } return NULL; } /* DESCRIPTION: Search in datalist the name for description RETURN: a pointer for name NULL if the name can't be found */ PUBLIC const char *DATALIST::getnamebydesc (const char *desc) { for (int i=0; idesc->cmp(desc)==0) return d->name->get(); } return NULL; } /* DESCRIPTION: Restore the keytable for its default value. RETURN: Nothing */ PUBLIC void DATALIST::restoretodefault() { keytable.setfrom(defkeytable); } /* DESCRIPTION: Reset the keyboard by executing the 'loadkeys' command. RETURN: 0 if not or any error 1 if ok */ PUBLIC int DATALIST::updatekeyboard(){ int ret; char arg[50]; sprintf (arg,"\"%s\" 2> /dev/null", keytable.get()); if ( !(ret=execute ("loadkeys",arg)) ){ xconf_error (MSG_U(E_CANTEXECUTELOADKEYS,"can't execute 'loadkeys %s'"),arg); } return ret; } /* DESCRIPTION: Execute the 'command args'. RETURN: 0 if not or any error 1 if success */ PUBLIC int DATALIST::execute (const char *command, const char *args){ int ret = 0; POPEN pop (command,args); if (pop.isok()){ ret = 1; while (pop.wait(1)>=0){ char buf[100]; if (pop.readerr (buf,sizeof(buf)-1)==0){ //xconf_error("Error while executing '%s %s':\n%s", command, args,buf); ret = 0; } } } pop.close(); return ret; } PUBLIC const char *DATALIST::touch() { return "I can touch the kbdconf"; } PUBLIC const char *DATALIST::getlayout() { return keytable.get(); } static const char *kbdconf_api_touch() { return loaded_data->touch(); } static int kbdconf_api_init() { return loaded_data->init(); } static int kbdconf_api_save(const char *k) { return loaded_data->save(k); } static int kbdconf_api_updatekeyboard() { return loaded_data->updatekeyboard(); } static const char *kbdconf_api_getlayout() { return loaded_data->getlayout(); } void *kbdconf_api_get() { KBDCONF_API *api = new KBDCONF_API; api->touch = kbdconf_api_touch; api->init = kbdconf_api_init; api->save = kbdconf_api_save; api->updatekeyboard = kbdconf_api_updatekeyboard; api->getlayout = kbdconf_api_getlayout; data_load(); return api; } void kbdconf_api_release(void *api) { delete (KBDCONF_API*)api; data_unload(); }