From 8ca43646a6c87d00d5b2cb74cebf65a8d0ea5e8e Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Sat, 14 Apr 2007 22:20:10 +0000 Subject: DB4 & Postponed processing - New DB4 database type - Postponed processing in external module + User may allow external module to finish required processing before termination. This could be useful for translation services while using console applications (if network connection is slow, the external will never finish translation before program termination) - SKIP_PARRENT options are renamed to SKIP_PARENT --- examples/example2.c | 3 ++ examples/input-russian.txt | 1 + examples/rcc-gtk-config.c | 2 + external/Makefile.am | 5 +- external/rccexternal.c | 44 +++++++++------- external/rcclibtranslate.c | 4 +- src/Makefile.am | 2 + src/internal.h | 11 ++-- src/librcc.c | 128 +++++---------------------------------------- src/librcc.h | 41 +++++++++++---- src/lngconfig.c | 16 +++--- src/plugin.c | 1 + src/rccconfig.c | 7 +-- src/rccconfig.h | 1 + src/rccdb4.c | 33 +++++++++--- src/rccexternal.c | 19 ++++++- src/rccexternal.h | 8 +++ src/rcchome.c | 52 ++++++++++++++++++ src/rcchome.h | 8 +++ src/rcclock.c | 108 ++++++++++++++++++++++++++++++++++++++ src/rcclock.h | 12 +++++ src/rccspell.c | 26 ++++----- src/rccspell.h | 2 +- src/rcctranslate.c | 4 ++ src/rccxml.c | 15 +++--- src/recode.c | 26 ++++----- 26 files changed, 373 insertions(+), 206 deletions(-) create mode 100644 src/rcchome.c create mode 100644 src/rcchome.h create mode 100644 src/rcclock.c create mode 100644 src/rcclock.h diff --git a/examples/example2.c b/examples/example2.c index 2083fcc..631fccf 100644 --- a/examples/example2.c +++ b/examples/example2.c @@ -25,6 +25,9 @@ int main(int argc, char *argv[]) { rccInitDefaultContext(NULL, 0, 0, classes, 0); rccInitDb4(NULL, "example", 0); rccSetOption(NULL, RCC_OPTION_TRANSLATE, RCC_OPTION_TRANSLATE_SKIP_PARRENT); + rccSetOption(NULL, RCC_OPTION_AUTODETECT_LANGUAGE, 1); +// rccSetOption(NULL, RCC_OPTION_TIMEOUT, 5000000); +// rccSetOption(NULL, RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, 0); current_language_id = rccGetCurrentLanguage(NULL); english_language_id = rccGetLanguageByName(NULL, "en"); diff --git a/examples/input-russian.txt b/examples/input-russian.txt index aa60118..6e1ec74 100644 --- a/examples/input-russian.txt +++ b/examples/input-russian.txt @@ -4,4 +4,5 @@ привет Good Morning Guten Abend +Auf widersehen Çäîðîâåíüê³ Áóëè diff --git a/examples/rcc-gtk-config.c b/examples/rcc-gtk-config.c index da73608..179829c 100644 --- a/examples/rcc-gtk-config.c +++ b/examples/rcc-gtk-config.c @@ -11,11 +11,13 @@ static rcc_class classes[] = { { "pl", RCC_CLASS_STANDARD, "id3", NULL, "PlayList Title Encoding", 0}, { "plfs", RCC_CLASS_STANDARD, "pl", NULL, "PlayList File Encoding", 0 }, { "fs", RCC_CLASS_FS, "LC_CTYPE", NULL, "FileSystem Encoding", 0 }, + { "arc", RCC_CLASS_STANDARD, NULL, NULL, "Archives Encoding", 0 }, { "oem", RCC_CLASS_STANDARD, NULL, NULL, "Zip OEM Encoding", 0 }, { "iso", RCC_CLASS_STANDARD, NULL, NULL, "Zip ISO Encoding", 0 }, { "ftp", RCC_CLASS_STANDARD, NULL, NULL, "FTP Encoding", 0 }, { "http", RCC_CLASS_STANDARD, NULL, NULL, "HTTP Encoding", 0 }, { "ssh", RCC_CLASS_STANDARD, NULL, NULL, "SSH Encoding", 0 }, + { "in", RCC_CLASS_STANDARD, NULL, NULL, "Input Encoding", 0 }, { "out", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "Output Encoding", 0 }, { NULL } }; diff --git a/external/Makefile.am b/external/Makefile.am index 68d2988..51cbad9 100644 --- a/external/Makefile.am +++ b/external/Makefile.am @@ -6,7 +6,10 @@ bindir = $(pkgdatadir)/ rccexternal_SOURCES= rccexternal.c \ rcclibtranslate.c rcclibtranslate.h \ - ../src/rccdb4.c ../src/rccdb4.h + ../src/rccdb4.c ../src/rccdb4.h \ + ../src/rcchome.c ../src/rcchome.h \ + ../src/rcclock.c ../src/rcclock.h + rccexternal_LDADD= @GLIB2_LIBS@ @LIBTRANSLATE_LIBS@ @BDB_LIBS@ AM_CPPFLAGS = @GLIB2_CFLAGS@ @LIBTRANSLATE_CFLAGS@ @BDB_INCLUDES@ -I../src diff --git a/external/rccexternal.c b/external/rccexternal.c index b09623d..56c9882 100644 --- a/external/rccexternal.c +++ b/external/rccexternal.c @@ -35,12 +35,15 @@ #include +#include "../src/rcchome.h" #include "../src/rccexternal.h" #include "rcclibtranslate.h" #define RCC_EXIT_CHECK_TIMEOUT 10 /* seconds */ +char rcc_external_offline = 0; + int main() { #ifdef HAVE_SIGNAL_H struct sigaction act; @@ -51,7 +54,6 @@ int main() { int s, sd; char addr[376]; - const char *rcc_home_dir; struct sockaddr_un mysock, clisock; socklen_t socksize; @@ -61,29 +63,16 @@ int main() { unsigned char loopflag = 1; rcc_external_info info; + rcc_external_option option; + unsigned long option_value_long; + ssize_t readed; unsigned char cmd; -#ifdef HAVE_PWD_H - struct passwd *pw; -#endif /* HAVE_PWD_H */ - - parentpid = getppid(); mypid = getpid(); - - rcc_home_dir = getenv ("HOME"); -#ifdef HAVE_PWD_H - if (!rcc_home_dir) { - setpwent (); - pw = getpwuid(getuid ()); - endpwent (); - if ((pw)&&(pw->pw_dir)) rcc_home_dir = pw->pw_dir; - } -#endif /* HAVE_PWD_H */ - if (strlen(rcc_home_dir)>256) return -1; - if (!rcc_home_dir) rcc_home_dir = "/"; - + + rccHomeSet(); rccLibTranslateInit(rcc_home_dir); sprintf(addr,"%s/.rcc/comm/",rcc_home_dir); @@ -140,6 +129,20 @@ int main() { case RCC_EXTERNAL_MODULE_CONTROL: loopflag = 0; break; + case RCC_EXTERNAL_MODULE_OPTIONS: + readed = recv(sd,&option,sizeof(rcc_external_option),0); + if (readed < sizeof(rcc_external_option)) break; + switch(option) { + case RCC_EXTERNAL_OPTION_OFFLINE: + readed = recv (sd, &option_value_long, sizeof(unsigned long), 0); + if (readed < sizeof(unsigned long)) break; + puts("got an offline option"); + rcc_external_offline = option_value_long?1:0; + break; + default: + break; + } + break; case RCC_EXTERNAL_MODULE_LIBRTRANSLATE: info = (rcc_external_info)malloc(sizeof(rcc_external_info_s)); if (info) info->s = sd; @@ -154,6 +157,7 @@ int main() { unlink(addr); rccLibTranslateFree(); - + rccHomeFree(); + return 0; } diff --git a/external/rcclibtranslate.c b/external/rcclibtranslate.c index 24f44a2..c64020c 100644 --- a/external/rcclibtranslate.c +++ b/external/rcclibtranslate.c @@ -35,6 +35,7 @@ static GCond *cond = NULL; static GQueue *queue = NULL; static GThread *thread = NULL; +extern char rcc_external_offline; static char *rccCreateKey(const char *from, const char *to, const char *data, size_t *keysize) { char *res; @@ -78,7 +79,7 @@ static void *rccLibPostponed(void *info) { to[2] = 0; g_mutex_lock(mutex); - while (!exitflag) { + while ((!exitflag)||(rcc_external_offline)) { data = (char*)g_queue_pop_head(queue); if (data) { g_mutex_unlock(mutex); @@ -103,6 +104,7 @@ static void *rccLibPostponed(void *info) { free(data); g_mutex_lock(mutex); } else { + if (exitflag) break; g_cond_wait(cond, mutex); } } diff --git a/src/Makefile.am b/src/Makefile.am index 6d1ca98..79976c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,7 @@ lib_LTLIBRARIES = librcc.la librcc_la_SOURCES = librcc.c \ + rcchome.c rcchome.h \ + rcclock.c rcclock.h \ rcclocale.c rcclocale.h \ lng.c lng.h \ opt.c opt.h \ diff --git a/src/internal.h b/src/internal.h index c5170be..98ef6d7 100644 --- a/src/internal.h +++ b/src/internal.h @@ -5,11 +5,7 @@ # define LIBRCC_DATA_DIR "/usr/lib/rcc" #endif /* LIBRCC_DATA_DIR */ -#ifndef LIBRCC_LOCK_WAIT -# define LIBRCC_LOCK_WAIT 3000 /* ms */ -#endif /* LIBRCC_LOCK_WAIT */ - -#define RCC_MAX_LANGUAGE_PARRENTS 4 +#define RCC_MAX_LANGUAGE_PARENTS 4 #define RCC_MAX_RELATIONS RCC_MAX_LANGUAGES #ifdef HAVE_STRNLEN @@ -38,11 +34,11 @@ #define RCC_MAX_DISABLED_CHARSETS 64 -typedef rcc_language_id rcc_language_parrent_list[RCC_MAX_LANGUAGE_PARRENTS]; +typedef rcc_language_id rcc_language_parent_list[RCC_MAX_LANGUAGE_PARENTS]; struct rcc_language_internal_t { rcc_language language; - rcc_language_id parrents[RCC_MAX_LANGUAGE_PARRENTS + 1]; + rcc_language_id parents[RCC_MAX_LANGUAGE_PARENTS + 1]; unsigned char latin; }; typedef struct rcc_language_internal_t rcc_language_internal; @@ -102,6 +98,5 @@ int rccConfigure(rcc_context ctx); char *rccCreateResult(rcc_context ctx, size_t len); extern rcc_context rcc_default_ctx; -extern char *rcc_home_dir; #endif /* _RCC_INTERNAL_H */ diff --git a/src/librcc.c b/src/librcc.c index 6d3ce24..a39fef2 100644 --- a/src/librcc.c +++ b/src/librcc.c @@ -35,9 +35,10 @@ #include "rccxml.h" #include "rccexternal.h" #include "rcctranslate.h" +#include "rcclock.h" +#include "rcchome.h" static int initialized = 0; -char *rcc_home_dir = NULL; rcc_context rcc_default_ctx = NULL; static rcc_compiled_configuration_s compiled_configuration; @@ -64,27 +65,12 @@ rcc_compiled_configuration rccGetCompiledConfiguration() { int rccInit() { int err; - char *tmp; unsigned long i, rpos; - -#ifdef HAVE_PWD_H - struct passwd *pw; -#endif /* HAVE_PWD_H */ if (initialized) return 0; - tmp = getenv ("HOME"); - if (tmp) rcc_home_dir = strdup (tmp); -#ifdef HAVE_PWD_H - else { - setpwent (); - pw = getpwuid(getuid ()); - endpwent (); - if ((pw)&&(pw->pw_dir)) rcc_home_dir = strdup (pw->pw_dir); - } -#endif /* HAVE_PWD_H */ - if (!rcc_home_dir) rcc_home_dir = strdup("/"); - + rccHomeSet(); + memcpy(rcc_default_languages, rcc_default_languages_embeded, (RCC_MAX_LANGUAGES + 1)*sizeof(rcc_language)); memcpy(rcc_default_aliases, rcc_default_aliases_embeded, (RCC_MAX_ALIASES + 1)*sizeof(rcc_language_alias)); memcpy(rcc_default_relations, rcc_default_relations_embeded, (RCC_MAX_RELATIONS + 1)*sizeof(rcc_language_relation)); @@ -101,10 +87,10 @@ int rccInit() { if (!strcasecmp(rcc_default_languages[i].sn, rcc_english_language_sn)) continue; rcc_default_relations[rpos].lang = rcc_default_languages[i].sn; - rcc_default_relations[rpos++].parrent = rcc_english_language_sn; + rcc_default_relations[rpos++].parent = rcc_english_language_sn; } rcc_default_relations[rpos].lang = NULL; - rcc_default_relations[rpos].parrent = NULL; + rcc_default_relations[rpos].parent = NULL; err = rccPluginInit(); if (!err) err = rccTranslateInit(); @@ -134,97 +120,11 @@ void rccFree() { rccExternalFree(); - if (rcc_home_dir) { - free(rcc_home_dir); - rcc_home_dir = NULL; - } + rccHomeFree(); initialized = 0; } -static int lockfd = -1; - -int rccLock() { -# ifdef HAVE_SYS_FILE_H - int err, i; - int size; - char *stmp; - struct timespec wait = { 0, 10000000 }; - - if (lockfd>=0) return -1; - - size = strlen(rcc_home_dir) + 32; - stmp = (char*)malloc(size*sizeof(char)); - if (!stmp) return -1; - - sprintf(stmp,"%s/.rcc/", rcc_home_dir); - mkdir(stmp, 00755); - - sprintf(stmp,"%s/.rcc/locks/", rcc_home_dir); - mkdir(stmp, 00700); - - sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); - - lockfd = open(stmp, O_RDWR|O_CREAT, 0644); - if (lockfd >= 0) { - for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { - err = flock(lockfd, LOCK_EX|LOCK_NB); - if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); - else break; - } - - if (err) { - close(lockfd); - - // Removing invalid lock - if (i == (LIBRCC_LOCK_WAIT/10)) { - remove(stmp); - - lockfd = open(stmp, O_RDWR|O_CREAT, 0644); - if (lockfd >= 0) { - for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { - err = flock(lockfd, LOCK_EX|LOCK_NB); - if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); - else break; - } - - if (err) close(lockfd); - else return 0; - } - } - - lockfd = -1; - return -1; - } - - return 0; - } - - return -1; -# else /* HAVE_SYS_FILE_H */ - return 0; -# endif /* HAVE_SYS_FILE_H */ -} - -void rccUnLock() { -#ifdef HAVE_SYS_FILE_H - int size; - char *stmp; - - if (lockfd<0) return; - - size = strlen(rcc_home_dir) + 32; - stmp = (char*)malloc(size*sizeof(char)); - if (!stmp) return; - - sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); - - flock(lockfd, LOCK_UN); - close(lockfd); - lockfd = -1; -#endif /* HAVE_SYS_FILE_H */ -} - rcc_context rccCreateContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) { unsigned int i; @@ -470,7 +370,7 @@ rcc_language_id rccRegisterLanguage(rcc_context ctx, rcc_language *language) { if (ctx->n_languages == ctx->max_languages) return (rcc_language_id)-1; memcpy(ctx->ilang + ctx->n_languages, language, sizeof(rcc_language)); - ctx->ilang[ctx->n_languages].parrents[0] = (rcc_language_id)-1; + ctx->ilang[ctx->n_languages].parents[0] = (rcc_language_id)-1; ctx->ilang[ctx->n_languages].latin = 0; for (i=0;language->charsets[i];i++) @@ -539,7 +439,7 @@ rcc_relation_id rccRegisterLanguageRelation(rcc_context ctx, rcc_language_relati unsigned int i; rcc_language_id language_id; const char *lang; - const char *parrent; + const char *parent; rcc_language_id *list; if (!ctx) { @@ -549,22 +449,22 @@ rcc_relation_id rccRegisterLanguageRelation(rcc_context ctx, rcc_language_relati if (!relation) return (rcc_relation_id)-1; lang = relation->lang; - parrent = relation->parrent; - if ((!lang)||(!parrent)||(!strcasecmp(lang,parrent))) return (rcc_relation_id)-1; + parent = relation->parent; + if ((!lang)||(!parent)||(!strcasecmp(lang,parent))) return (rcc_relation_id)-1; language_id = rccGetLanguageByName(ctx, lang); if (language_id == (rcc_language_id)-1) return (rcc_relation_id)-1; - list = ((rcc_language_internal*)ctx->languages[language_id])->parrents; + list = ((rcc_language_internal*)ctx->languages[language_id])->parents; - language_id = rccGetLanguageByName(ctx, parrent); + language_id = rccGetLanguageByName(ctx, parent); if (language_id == (rcc_language_id)-1) return (rcc_relation_id)0; for (i=0;list[i]!=(rcc_language_id)-1;i++) if (list[i] == language_id) return (rcc_relation_id)0; - if (ispeller) language_id = rccConfigGetLanguage(config); else language_id = (rcc_language_id)-1; - if (language_id != (rcc_language_id)-1) parrents = ((rcc_language_internal*)config->language)->parrents; - else parrents = NULL; + if (language_id != (rcc_language_id)-1) parents = ((rcc_language_internal*)config->language)->parents; + else parents = NULL; - if (parrents) { - for (i = 0; parrents[i]!=(rcc_language_id)-1; i++) { - pconfig = rccGetConfig(config->ctx, parrents[i]); + if (parents) { + for (i = 0; parents[i]!=(rcc_language_id)-1; i++) { + pconfig = rccGetConfig(config->ctx, parents[i]); if (pconfig) { speller = rccConfigGetSpeller(pconfig); rccSpellerAddParrent(config->speller, speller); @@ -467,6 +467,7 @@ rcc_speller rccConfigGetSpeller(rcc_language_config config) { rcc_translate rccConfigGetTranslator(rcc_language_config config, rcc_language_id to) { rcc_option_value timeout; + rcc_option_value offline; if (!config) return NULL; @@ -482,6 +483,9 @@ rcc_translate rccConfigGetTranslator(rcc_language_config config, rcc_language_id config->translang = to; timeout = rccGetOption(config->ctx, RCC_OPTION_TIMEOUT); if (timeout) rccTranslateSetTimeout(config->trans, timeout); + + offline = rccGetOption(config->ctx, RCC_OPTION_OFFLINE); + if (offline) rccTranslateAllowOfflineMode(config->trans); } } rccMutexUnLock(config->mutex); diff --git a/src/plugin.c b/src/plugin.c index b3289b7..c1f0074 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -3,6 +3,7 @@ #include #include "internal.h" +#include "rcchome.h" #include "plugin.h" #ifdef RCC_PLUGINS diff --git a/src/rccconfig.c b/src/rccconfig.c index ae47a63..6723825 100644 --- a/src/rccconfig.c +++ b/src/rccconfig.c @@ -134,7 +134,7 @@ rcc_language rcc_default_languages_embeded[RCC_MAX_LANGUAGES + 1] = { rcc_option_value_name rcc_sn_boolean[] = { "OFF", "ON", NULL }; rcc_option_value_name rcc_sn_learning[] = { "OFF", "ON", "RELEARN", "LEARN", NULL }; rcc_option_value_name rcc_sn_clo[] = { "ALL", "CONFIGURED_AND_AUTO", "CONFIGURED_ONLY", NULL }; -rcc_option_value_name rcc_sn_translate[] = { "OFF", "TRANSLITERATE", "TO_ENGLISH", "SKIP_RELATED", "SKIP_PARRENT", "FULL", NULL }; +rcc_option_value_name rcc_sn_translate[] = { "OFF", "TRANSLITERATE", "TO_ENGLISH", "SKIP_RELATED", "SKIP_PARENT", "FULL", NULL }; rcc_option_description rcc_option_descriptions[RCC_MAX_OPTIONS+1]; rcc_option_description rcc_option_descriptions_embeded[RCC_MAX_OPTIONS+1] = { @@ -162,6 +162,7 @@ rcc_option_description rcc_option_descriptions_embeded[RCC_MAX_OPTIONS+1] = { #else {RCC_OPTION_TIMEOUT, RCC_DEFAULT_RECODING_TIMEOUT, { RCC_OPTION_RANGE_TYPE_RANGE, 0, 5000000, 50000}, RCC_OPTION_TYPE_INVISIBLE, "TIMEOUT", NULL }, #endif /* HAVE_LIBTRANSLATE */ + {RCC_OPTION_OFFLINE, 0, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0 }, RCC_OPTION_TYPE_INVISIBLE, "OFFLINE_PROCESSING", rcc_sn_boolean}, {RCC_MAX_OPTIONS} }; @@ -215,11 +216,11 @@ unsigned int rccDefaultDropLanguageRelations(const char *lang) { if (strcasecmp(lang, rcc_default_relations[i].lang)) { if (jset_flags(dbe, DB_LOG_AUTOREMOVE, 1); + dbe->set_lg_max(dbe, 131072); + + err = rccLock(); + if (!err) { + err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_TXN|DB_USE_ENVIRON|DB_INIT_LOCK|DB_INIT_MPOOL|DB_RECOVER, 00644); + rccUnLock(); + } +# else err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); if (err == DB_VERSION_MISMATCH) { - if (!rccLock()) { err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_USE_ENVIRON|DB_PRIVATE|DB_RECOVER, 0); + dbe->close(dbe, 0); + dbe->remove(dbe, dbpath, 0); rccUnLock(); - } else err = -1; - - dbe->close(dbe, 0); + } else { + err = -1; + dbe->close(dbe, 0); + } + if (err) return NULL; if (strlen(dbpath)<128) { @@ -43,8 +59,10 @@ db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) { err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); } - +# endif + if (err) { +// fprintf(stderr, "BerkelyDB initialization failed: %i (%s)\n", err, db_strerror(err)); dbe->close(dbe, 0); return NULL; } @@ -55,6 +73,7 @@ db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) { return NULL; } + err = db->open(db, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0); if (err) { db->close(db, 0); @@ -71,7 +90,7 @@ db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) { #endif /* HAVE_DB_H */ return NULL; } - + #ifdef HAVE_DB_H ctx->db = db; ctx->dbe = dbe; diff --git a/src/rccexternal.c b/src/rccexternal.c index be9f97d..58b8a23 100644 --- a/src/rccexternal.c +++ b/src/rccexternal.c @@ -38,6 +38,7 @@ # include #endif /* HAVE_SYS_WAIT_H */ +#include "rcchome.h" #include "rccexternal.h" #include "internal.h" @@ -92,7 +93,7 @@ void rccExternalFree() { res = waitpid(pid, NULL, WNOHANG); if (res) break; - else timeout.tv_nsec*10; + else timeout.tv_nsec*=10; } pid = (pid_t)-1; @@ -225,3 +226,19 @@ void rccExternalClose(int s) { close(s); } } + +int rccExternalAllowOfflineMode() { + int sock; + int err; + rcc_external_option opt = RCC_EXTERNAL_OPTION_OFFLINE; + unsigned long opt_value = 1; + + sock = rccExternalConnect(RCC_EXTERNAL_MODULE_OPTIONS); + if (sock) { + err = rccExternalWrite(sock, (char*)&opt, sizeof(rcc_external_option), 0); + if (!err) err = rccExternalWrite(sock, (char*)&opt_value, sizeof(unsigned long), 0); + rccExternalClose(sock); + return err; + } + return -1; +} diff --git a/src/rccexternal.h b/src/rccexternal.h index 236e2df..1038329 100644 --- a/src/rccexternal.h +++ b/src/rccexternal.h @@ -3,6 +3,7 @@ typedef enum rcc_external_module_t { RCC_EXTERNAL_MODULE_CONTROL = 0, + RCC_EXTERNAL_MODULE_OPTIONS, RCC_EXTERNAL_MODULE_LIBRTRANSLATE, RCC_EXTERNAL_MODULE_MAX } rcc_external_module; @@ -13,6 +14,11 @@ struct rcc_external_info_t { typedef struct rcc_external_info_t rcc_external_info_s; typedef struct rcc_external_info_t *rcc_external_info; +typedef enum rcc_external_option_t { + RCC_EXTERNAL_OPTION_OFFLINE = 0, + RCC_EXTERNAL_OPTION_MAX +} rcc_external_option; + struct rcc_external_command_t { unsigned long size; unsigned char cmd; @@ -25,6 +31,8 @@ typedef struct rcc_external_command_t *rcc_external_command; int rccExternalInit(); void rccExternalFree(); +int rccExternalAllowOfflineMode(); + size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout); size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout); int rccExternalConnect(unsigned char module); diff --git a/src/rcchome.c b/src/rcchome.c new file mode 100644 index 0000000..a88a667 --- /dev/null +++ b/src/rcchome.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "../config.h" + + +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_SYS_TYPES_H +# include +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_STAT_H +# include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_PWD_H +# include +#endif /* HAVE_PWD_H */ + +#include "rcchome.h" + +char *rcc_home_dir = NULL; + +void rccHomeSet() { + char *tmp; + +#ifdef HAVE_PWD_H + struct passwd *pw; +#endif /* HAVE_PWD_H */ + + tmp = getenv ("HOME"); + if (tmp) rcc_home_dir = strdup (tmp); +#ifdef HAVE_PWD_H + else { + setpwent (); + pw = getpwuid(getuid ()); + endpwent (); + if ((pw)&&(pw->pw_dir)) rcc_home_dir = strdup (pw->pw_dir); + } +#endif /* HAVE_PWD_H */ + if (!rcc_home_dir) rcc_home_dir = strdup("/"); +} + +void rccHomeFree() { + if (rcc_home_dir) { + free(rcc_home_dir); + rcc_home_dir = NULL; + } +} diff --git a/src/rcchome.h b/src/rcchome.h new file mode 100644 index 0000000..0712eab --- /dev/null +++ b/src/rcchome.h @@ -0,0 +1,8 @@ +#ifndef _RCC_HOME_H +#define _RCC_HOME_H + +extern char *rcc_home_dir; +void rccHomeSet(); +void rccHomeFree(); + +#endif /* _RCC_HOME_H */ diff --git a/src/rcclock.c b/src/rcclock.c new file mode 100644 index 0000000..b8f0e8f --- /dev/null +++ b/src/rcclock.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include + +#include "../config.h" + +#ifdef HAVE_SYS_FILE_H +# include +#endif /* HAVE_SYS_FILE_H */ + +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_SYS_TYPES_H +# include +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_STAT_H +# include +#endif /* HAVE_SYS_STAT_H */ + +#include "rcchome.h" +#include "rcclock.h" + +static int lockfd = -1; + +int rccLock() { +# ifdef HAVE_SYS_FILE_H + int err, i; + int size; + char *stmp; + struct timespec wait = { 0, 10000000 }; + + if (lockfd>=0) return -1; + + size = strlen(rcc_home_dir) + 32; + stmp = (char*)malloc(size*sizeof(char)); + if (!stmp) return -1; + + sprintf(stmp,"%s/.rcc/", rcc_home_dir); + mkdir(stmp, 00755); + + sprintf(stmp,"%s/.rcc/locks/", rcc_home_dir); + mkdir(stmp, 00700); + + sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + + lockfd = open(stmp, O_RDWR|O_CREAT, 0644); + if (lockfd >= 0) { + for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { + err = flock(lockfd, LOCK_EX|LOCK_NB); + if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); + else break; + } + + if (err) { + close(lockfd); + + // Removing invalid lock + if (i == (LIBRCC_LOCK_WAIT/10)) { + remove(stmp); + + lockfd = open(stmp, O_RDWR|O_CREAT, 0644); + if (lockfd >= 0) { + for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { + err = flock(lockfd, LOCK_EX|LOCK_NB); + if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); + else break; + } + + if (err) close(lockfd); + else return 0; + } + } + + lockfd = -1; + return -1; + } + + return 0; + } + + return -1; +# else /* HAVE_SYS_FILE_H */ + return 0; +# endif /* HAVE_SYS_FILE_H */ +} + +void rccUnLock() { +#ifdef HAVE_SYS_FILE_H + int size; + char *stmp; + + if (lockfd<0) return; + + size = strlen(rcc_home_dir) + 32; + stmp = (char*)malloc(size*sizeof(char)); + if (!stmp) return; + + sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + + flock(lockfd, LOCK_UN); + close(lockfd); + lockfd = -1; +#endif /* HAVE_SYS_FILE_H */ +} diff --git a/src/rcclock.h b/src/rcclock.h new file mode 100644 index 0000000..e043150 --- /dev/null +++ b/src/rcclock.h @@ -0,0 +1,12 @@ +#ifndef _RCC_LOCK_H +#define _RCC_LOCK_H + +#ifndef LIBRCC_LOCK_WAIT +# define LIBRCC_LOCK_WAIT 3000 /* ms */ +#endif /* LIBRCC_LOCK_WAIT */ + +int rccLock(); +void rccUnLock(); + +#endif /* _RCC_LOCK_H */ + diff --git a/src/rccspell.c b/src/rccspell.c index da5e4d1..19b5abc 100644 --- a/src/rccspell.c +++ b/src/rccspell.c @@ -29,7 +29,7 @@ rcc_speller rccSpellerCreate(const char *lang) { } rccspeller->speller = speller; - rccspeller->parrents[0] = NULL; + rccspeller->parents[0] = NULL; return rccspeller; #else return NULL; @@ -49,14 +49,14 @@ int rccSpellerGetError(rcc_speller rccspeller) { return 0; } -int rccSpellerAddParrent(rcc_speller speller, rcc_speller parrent) { +int rccSpellerAddParent(rcc_speller speller, rcc_speller parent) { unsigned int i; - if ((!speller)||(!parrent)) return -1; + if ((!speller)||(!parent)) return -1; - for (i=0;speller->parrents[i];i++); - if (i >= RCC_MAX_LANGUAGE_PARRENTS) return -1; - speller->parrents[i++] = parrent; - speller->parrents[i] = NULL; + for (i=0;speller->parents[i];i++); + if (i >= RCC_MAX_LANGUAGE_PARENTS) return -1; + speller->parents[i++] = parent; + speller->parents[i] = NULL; return 0; } @@ -70,10 +70,10 @@ rcc_speller_result rccSpellerSized(rcc_speller speller, const char *word, size_t if (rccSpellerGetError(speller)) return (rcc_speller_result)RCC_SPELLER_INCORRECT; if (recursion) { - for (i=0; speller->parrents[i]; i++) { - result = rccSpellerSized(speller->parrents[i], word, len, 0); - if ((result == RCC_SPELLER_CORRECT)||(result == RCC_SPELLER_PARRENT)) return RCC_SPELLER_PARRENT; - if ((result == RCC_SPELLER_ALMOST_CORRECT)||(result == RCC_SPELLER_ALMOST_PARRENT)) saved_result = RCC_SPELLER_ALMOST_PARRENT; + for (i=0; speller->parents[i]; i++) { + result = rccSpellerSized(speller->parents[i], word, len, 0); + if ((result == RCC_SPELLER_CORRECT)||(result == RCC_SPELLER_PARENT)) return RCC_SPELLER_PARENT; + if ((result == RCC_SPELLER_ALMOST_CORRECT)||(result == RCC_SPELLER_ALMOST_PARENT)) saved_result = RCC_SPELLER_ALMOST_PARENT; } } @@ -95,12 +95,12 @@ int rccSpellerResultIsOwn(rcc_speller_result res) { } int rccSpellerResultIsPrecise(rcc_speller_result res) { - if ((res == RCC_SPELLER_PARRENT)||(res == RCC_SPELLER_CORRECT)) return 1; + if ((res == RCC_SPELLER_PARENT)||(res == RCC_SPELLER_CORRECT)) return 1; return 0; } int rccSpellerResultIsCorrect(rcc_speller_result res) { if ((res == RCC_SPELLER_ALMOST_CORRECT)||(res == RCC_SPELLER_CORRECT)) return 1; - if ((res == RCC_SPELLER_ALMOST_PARRENT)||(res == RCC_SPELLER_PARRENT)) return 1; + if ((res == RCC_SPELLER_ALMOST_PARENT)||(res == RCC_SPELLER_PARENT)) return 1; return 0; } diff --git a/src/rccspell.h b/src/rccspell.h index 49d5c99..4943e93 100644 --- a/src/rccspell.h +++ b/src/rccspell.h @@ -15,7 +15,7 @@ struct rcc_speller_t { #else void *speller; #endif /* HAVE_ASPELL */ - rcc_speller parrents[RCC_MAX_LANGUAGE_PARRENTS+1]; + rcc_speller parents[RCC_MAX_LANGUAGE_PARENTS+1]; }; typedef struct rcc_speller_t rcc_speller_s; diff --git a/src/rcctranslate.c b/src/rcctranslate.c index 37f0f01..98c0f1b 100644 --- a/src/rcctranslate.c +++ b/src/rcctranslate.c @@ -83,6 +83,10 @@ int rccTranslateSetTimeout(rcc_translate translate, unsigned long us) { return 0; } +int rccTranslateAllowOfflineMode(rcc_translate translate) { + return rccExternalAllowOfflineMode(); +} + #define RCC_UNLOCK_W 1 #define RCC_UNLOCK_R 2 #define RCC_UNLOCK_RW 3 diff --git a/src/rccxml.c b/src/rccxml.c index db13750..e5283af 100644 --- a/src/rccxml.c +++ b/src/rccxml.c @@ -31,6 +31,7 @@ #include "internal.h" #include "rccconfig.h" #include "plugin.h" +#include "rcchome.h" #define MAX_HOME_CHARS 96 #define XPATH_LANGUAGE "//Language[@name]" @@ -58,7 +59,7 @@ int rccXmlInit(int LoadConfiguration) { xmlAttrPtr attr; const char *lang, *engine_name; unsigned int pos, lpos, epos, cpos; - const char *alias, *parrent; + const char *alias, *parent; unsigned int j, apos, rpos; rcc_engine *engine; @@ -115,9 +116,9 @@ int rccXmlInit(int LoadConfiguration) { if (pos == (rcc_language_id)-1) { for (rpos=0;rcc_default_relations[rpos].lang;rpos++); if (rpos < RCC_MAX_RELATIONS) { - rcc_default_relations[rpos].parrent = rcc_english_language_sn; + rcc_default_relations[rpos].parent = rcc_english_language_sn; rcc_default_relations[rpos++].lang = lang; - rcc_default_relations[rpos].parrent = NULL; + rcc_default_relations[rpos].parent = NULL; rcc_default_relations[rpos].lang = NULL; } @@ -172,11 +173,11 @@ int rccXmlInit(int LoadConfiguration) { for (enode=node->children;enode;enode=enode->next) { if (enode->type != XML_ELEMENT_NODE) continue; if ((!xmlStrcmp(enode->name, "Parrent"))&&(rposlanguage)->parrents; - for (k = 0;parrents[k] != (rcc_language_id)-1;k++) - if (parrents[k] == bestfixlang) break; + parents = ((rcc_language_internal*)config->language)->parents; + for (k = 0;parents[k] != (rcc_language_id)-1;k++) + if (parents[k] == bestfixlang) break; - if (parrents[k] != bestfixlang) continue; + if (parents[k] != bestfixlang) continue; } speller = rccConfigGetSpeller(config); @@ -281,17 +281,17 @@ rcc_language_id rccDetectLanguage(rcc_context ctx, rcc_class_id class_id, const } -static int rccIsParrentLanguage(rcc_language_config config, rcc_language_id parrent) { +static int rccIsParrentLanguage(rcc_language_config config, rcc_language_id parent) { unsigned int i; rcc_language_id language; rcc_language_id *list; language = rccConfigGetLanguage(config); - if (parrent == language) return 1; + if (parent == language) return 1; - list = ((rcc_language_internal*)config->language)->parrents; + list = ((rcc_language_internal*)config->language)->parents; for (i=0;list[i] != (rcc_language_id)-1;i++) - if (list[i] == parrent) return 1; + if (list[i] == parent) return 1; return 0; } @@ -349,7 +349,7 @@ static char *rccRecodeTranslate(rcc_language_config *config, rcc_class_id class_ } else current_language_id = rccGetCurrentLanguage(ctx); } - + if (current_language_id == (rcc_language_id)-1) return NULL; if (language_id == current_language_id) return NULL; @@ -357,7 +357,7 @@ static char *rccRecodeTranslate(rcc_language_config *config, rcc_class_id class_ if (!curconfig) return NULL; if (rccConfigConfigure(curconfig)) return NULL; - + if (translate == RCC_OPTION_TRANSLATE_TRANSLITERATE) { if (!strcasecmp((*config)->language->sn, rcc_russian_language_sn)) { translated = rccSizedRecodeCharsets(ctx, "UTF-8", "KOI8-R", utfstring, 0, NULL); @@ -405,7 +405,7 @@ static char *rccRecodeTranslate(rcc_language_config *config, rcc_class_id class_ if (rccAreRelatedLanguages(curconfig, *config)) return NULL; } - if (translate == RCC_OPTION_TRANSLATE_SKIP_PARRENT) { + if (translate == RCC_OPTION_TRANSLATE_SKIP_PARENT) { if (rccIsParrentLanguage(curconfig, language_id)) return NULL; } @@ -770,7 +770,7 @@ char *rccSizedToCharset(rcc_context ctx, const char *charset, rcc_const_string b res = rccStringCheck(buf); if (!res) return NULL; - + icnv = rccIConvOpen(charset, "UTF-8"); if (icnv) { rccMutexLock(ctx->mutex); -- cgit v1.2.3