diff options
Diffstat (limited to 'external')
-rw-r--r-- | external/Makefile.am | 12 | ||||
-rw-r--r-- | external/rccexternal.c | 117 | ||||
-rw-r--r-- | external/rcclibtranslate.c | 286 | ||||
-rw-r--r-- | external/rcclibtranslate.h | 9 |
4 files changed, 424 insertions, 0 deletions
diff --git a/external/Makefile.am b/external/Makefile.am new file mode 100644 index 0000000..68d2988 --- /dev/null +++ b/external/Makefile.am @@ -0,0 +1,12 @@ +if HAVE_GLIB2 +bin_PROGRAMS= rccexternal +endif + +bindir = $(pkgdatadir)/ + +rccexternal_SOURCES= rccexternal.c \ + rcclibtranslate.c rcclibtranslate.h \ + ../src/rccdb4.c ../src/rccdb4.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 new file mode 100644 index 0000000..47f628a --- /dev/null +++ b/external/rccexternal.c @@ -0,0 +1,117 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif /* HAVE_PWD_H */ + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_SOCKET_H +# include <sys/socket.h> +#endif /* HAVE_SYS_SOCKET_H */ +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */ +#ifdef HAVE_SYS_UN_H +# include <sys/un.h> +#endif /* HAVE_SYS_UN_H */ + +#include <glib/gthread.h> + +#include "../src/rccexternal.h" +#include "rcclibtranslate.h" + + +int main() { + int s, sd; + char addr[376]; + const char *rcc_home_dir; + struct sockaddr_un mysock, clisock; + socklen_t socksize; + pid_t mypid; + + unsigned char loopflag = 1; + + rcc_external_info info; + ssize_t readed; + unsigned char cmd; + +#ifdef HAVE_PWD_H + struct passwd *pw; +#endif /* HAVE_PWD_H */ + + 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 = "/"; + + rccLibTranslateInit(rcc_home_dir); + + sprintf(addr,"%s/.rcc/comm/",rcc_home_dir); + mkdir(addr, 00600); + sprintf(addr,"%s/.rcc/comm/%lu.sock", rcc_home_dir, (unsigned long)mypid); + + s = socket(PF_UNIX, SOCK_STREAM, 0); + if (!s) return -1; + + memset(&mysock, 0, sizeof(mysock)); + mysock.sun_family=AF_UNIX; + strncpy(mysock.sun_path,addr,sizeof(mysock.sun_path)); + mysock.sun_path[sizeof(mysock.sun_path)-1]=0; + + unlink(addr); + if (bind(s,(struct sockaddr*)&mysock,sizeof(mysock))==-1) return -1; + if (listen(s,1)<0) { + unlink(addr); + return -1; + } + + while (loopflag) { + sd = accept(s,(struct sockaddr*)&clisock,&socksize); + if (sd < 0) continue; + + readed = recv(sd,&cmd,1,0); + if (readed<=0) { + close(sd); + continue; + } + + switch (cmd) { + case RCC_EXTERNAL_MODULE_CONTROL: + loopflag = 0; + break; + case RCC_EXTERNAL_MODULE_LIBRTRANSLATE: + info = (rcc_external_info)malloc(sizeof(rcc_external_info_s)); + if (info) info->s = sd; + else break; + if (g_thread_create(rccLibTranslate, info, FALSE, NULL)) continue; + break; + } + close(sd); + } + + close(s); + unlink(addr); + + rccLibTranslateFree(); + + return 0; +} diff --git a/external/rcclibtranslate.c b/external/rcclibtranslate.c new file mode 100644 index 0000000..56ce8a2 --- /dev/null +++ b/external/rcclibtranslate.c @@ -0,0 +1,286 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +#include "../config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_LIBTRANSLATE +#include <translate.h> +#endif /* HAVE_LIBTRANSLATE */ + +#include "../src/rccexternal.h" +#include "../src/rcctranslate.h" +#include "../src/rccdb4.h" +#include "rcclibtranslate.h" + + +#ifdef HAVE_LIBTRANSLATE +static TranslateSession *session = NULL; +static db4_context db4ctx = NULL; + +static int exitflag = 0; +static GMutex *mutex = NULL; +static GCond *cond = NULL; +static GQueue *queue = NULL; +static GThread *thread = NULL; + + +static char *rccCreateKey(const char *from, const char *to, const char *data, size_t *keysize) { + char *res; + + *keysize = strlen(data) + 4; + res = (char*)malloc((*keysize+1)*sizeof(char)); + if (res) sprintf(res,"%s%s%s",from,to,data); + return res; +} + +static void *rccLibPostponed(void *info) { + char *result; + char *data; + char from[3]; + char to[3]; + + from[2] = 0; + to[2] = 0; + + g_mutex_lock(mutex); + while (!exitflag) { + data = (char*)g_queue_pop_head(queue); + if (data) { + g_mutex_unlock(mutex); + + memcpy(from, data, 2); + memcpy(to, data + 2, 2); + result = translate_session_translate_text(session, data + 4, from, to, NULL, NULL, NULL); + + if (result) { + rccDb4SetKey(db4ctx, data, strlen(data), result); + free(result); + } + + free(data); + g_mutex_lock(mutex); + } else { + g_cond_wait(cond, mutex); + } + } + g_mutex_unlock(mutex); + return NULL; +} + +#endif /* HAVE_LIBTRANSLATE */ + + +int rccLibTranslateInit(const char *rcc_home_dir) { +#ifdef HAVE_LIBTRANSLATE + size_t size; + char *dbname; + GSList *list = NULL; + + const char *http_proxy; + + if (!translate_init(NULL)) return -1; + + http_proxy = getenv("HTTP_PROXY"); + if (!http_proxy) http_proxy = getenv("http_proxy"); + translate_set_proxy(http_proxy); + + list = translate_get_services(); + + session = translate_session_new(list); + + g_slist_foreach(list, (GFunc) g_object_unref, NULL); + g_slist_free(list); + + + size = strlen(rcc_home_dir) + 32; + dbname = (char*)malloc(size*sizeof(char)); + if (dbname) { + sprintf(dbname,"%s/.rcc/",rcc_home_dir); + mkdir(dbname, 00644); + + sprintf(dbname,"%s/.rcc/libtranslate.db/",rcc_home_dir); + mkdir(dbname, 00644); + + db4ctx = rccDb4CreateContext(dbname, 0); + free(dbname); + } + if (db4ctx) { + mutex = g_mutex_new(); + cond = g_cond_new(); + if ((mutex)&&(cond)) + queue = g_queue_new(); + if (queue) + thread = g_thread_create(rccLibPostponed, NULL, TRUE, NULL); + } +#endif /* HAVE_LIBTRANSLATE */ + + return 0; +} + +void rccLibTranslateFree() { +#ifdef HAVE_LIBTRANSLATE + char *ptr; + if (session) { + if (thread) { + exitflag = 1; + g_cond_signal(cond); + g_thread_join(thread); + thread = NULL; + exitflag = 0; + } + if (queue) { + do { + ptr = g_queue_pop_head(queue); + if (ptr) free(ptr); + } while (ptr); + g_queue_free(queue); + queue = NULL; + } + if (mutex) { + g_mutex_free(mutex); + mutex = NULL; + } + if (cond) { + g_cond_free(cond); + cond = NULL; + } + if (db4ctx) rccDb4FreeContext(db4ctx); + g_object_unref(session); + session = NULL; + } +#endif /* HAVE_LIBTRANSLATE */ +} + + +static char *rccLibTranslateDo(const char *from, const char *to, const char *text, unsigned long timeout) { +#ifdef HAVE_LIBTRANSLATE + char *result; + char *key = NULL; + size_t keysize; + + if ((!session)||(!from)||(!to)||(!text)) return NULL; + if ((strlen(from)!=2)||(strlen(to)!=2)) return NULL; + + if (db4ctx) { + key = rccCreateKey(from,to,text,&keysize); + if (key) { + result = rccDb4GetKey(db4ctx, key, keysize); + if (result) { + free(key); + return result; + } + } + } +# ifdef HAVE_LIBTRANSLATE_TIMED_TRANSLATE + result = translate_session_timed_translate_text(session, text, from, to, timeout, NULL, NULL, NULL); +# else + result = translate_session_translate_text(session, text, from, to, NULL, NULL, NULL); +# endif /* HAVE_LIBTRANSLATE_TIMED_TRANSLATE */ + + if ((db4ctx)&&(key)) { + if (result) { + rccDb4SetKey(db4ctx, key, keysize, result); + free(key); + } + else { + g_mutex_lock(mutex); + g_queue_push_tail(queue, key); + g_mutex_unlock(mutex); + g_cond_signal(cond); + } + } + + return result; +#else + return NULL; +#endif /* HAVE_LIBTRANSLATE */ +} + + +void *rccLibTranslate(void *info) { + int s; +#ifdef HAVE_LIBTRANSLATE + unsigned char connected = 1; + rcc_translate_prefix_s prefix; + ssize_t readed, writed, res; + char *buffer; + size_t size; + char *translated = NULL; +#endif /* HAVE_LIBTRANSLATE */ + + if (!info) return NULL; + + s = ((rcc_external_info)info)->s; + free(info); + +#ifdef HAVE_LIBTRANSLATE + while (connected) { + readed = read(s, &prefix, sizeof(rcc_translate_prefix_s)-1); + if ((readed<=0)||(readed != (sizeof(rcc_translate_prefix_s)-1))) break; + + switch (prefix.cmd.cmd) { + case RCC_EXTERNAL_COMMAND_CLOSE: + connected = 0; + break; + case RCC_EXTERNAL_COMMAND_TRANSLATE: + size = 1 + prefix.cmd.size + sizeof(rcc_external_command_s) - sizeof(rcc_translate_prefix_s); + buffer = (char*)malloc(size); + if (buffer) { + for (readed = 0; (readed < size)&&(connected); readed += res) { + res = read(s, buffer + readed, size - readed); + if (res<=0) connected = 0; + } + + prefix.cmd.cmd = 0; + prefix.cmd.size = 0; + + if ((prefix.from[2])||(prefix.to[2])||(buffer[readed-1])) goto respond; + + translated = rccLibTranslateDo(prefix.from, prefix.to, buffer, prefix.timeout); + if (translated) { + prefix.cmd.cmd = RCC_EXTERNAL_COMMAND_TRANSLATE; + prefix.cmd.size = strlen(translated) + 1; + } + +respond: + res = write(s, &prefix.cmd, sizeof(rcc_external_command_s)); + if (res == sizeof(rcc_external_command_s)) { + for (writed = 0; (writed < prefix.cmd.size)&&(connected); writed += res) { + res = write(s, translated + writed, prefix.cmd.size - writed); + if (res<=0) connected = 0; + } + } else connected = 0; + + if (prefix.cmd.size) free(translated); + free(buffer); + } else connected = 0; + break; + default: + buffer = (char*)malloc(prefix.cmd.size); + if (buffer) { + for (readed = 0; (readed < prefix.cmd.size)&&(connected); readed += res) { + res = read(s, buffer + readed, prefix.cmd.size - readed); + if (res<=0) connected = 0; + } + free(buffer); + } else connected = 0; + } + } +#endif /* HAVE_LIBTRANSLATE */ + + close(s); + return NULL; +} + diff --git a/external/rcclibtranslate.h b/external/rcclibtranslate.h new file mode 100644 index 0000000..f54f5e6 --- /dev/null +++ b/external/rcclibtranslate.h @@ -0,0 +1,9 @@ +#ifndef _RCC_LIBTRANSLATE_H +#define _RCC_LIBTRANSLATE_H + +int rccLibTranslateInit(const char *rcc_home_dir); +void rccLibTranslateFree(); + +void *rccLibTranslate(void *info); + +#endif /* _RCC_LIBTRANSLATE_H */ |