dictd/dictd-1.9.15-ipv6.patch
2018-10-16 05:12:41 +00:00

10217 lines
271 KiB
Diff

--- a/dictd.c
+++ b/dictd.c
@@ -31,14 +31,14 @@
#include "plugin.h"
#endif
-#include <grp.h> /* initgroups */
-#include <pwd.h> /* getpwuid */
-#include <locale.h> /* setlocale */
+#include <grp.h> /* initgroups */
+#include <pwd.h> /* getpwuid */
+#include <locale.h> /* setlocale */
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
-#define MAXPROCTITLE 2048 /* Maximum amount of proc title we'll use. */
+#define MAXPROCTITLE 2048 /* Maximum amount of proc title we'll use. */
#undef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#ifndef UID_NOBODY
@@ -55,278 +55,283 @@
-extern int yy_flex_debug;
+extern int yy_flex_debug;
-static int _dict_daemon;
-static int _dict_reaps;
+static int _dict_daemon;
+static int _dict_reaps;
-static char *_dict_argvstart;
-static int _dict_argvlen;
+static char *_dict_argvstart;
+static int _dict_argvlen;
- int _dict_forks;
+int _dict_forks;
-int default_strategy_set; /* 1 if set by command line option */
+int default_strategy_set; /* 1 if set by command line option */
-int logOptions = 0;
+int logOptions = 0;
-const char *logFile = NULL;
-int logFile_set; /* 1 if set by command line option */
+const char *logFile = NULL;
+int logFile_set; /* 1 if set by command line option */
-const char *pidFile = "/var/run/dictd.pid";
-int pidFile_set; /* 1 if set by command line option */
+const char *pidFile = "/var/run/dictd.pid";
+int pidFile_set; /* 1 if set by command line option */
-const char *daemon_service = DICT_DEFAULT_SERVICE;
-int daemon_service_set; /* 1 if set by command line option */
+const char *daemon_service = DICT_DEFAULT_SERVICE;
+int daemon_service_set; /* 1 if set by command line option */
-int _dict_daemon_limit_childs = DICT_DAEMON_LIMIT_CHILDS;
-int _dict_daemon_limit_childs_set; /* 1 if set by command line option */
+int _dict_daemon_limit_childs = DICT_DAEMON_LIMIT_CHILDS;
+int _dict_daemon_limit_childs_set; /* 1 if set by command line option */
-int _dict_daemon_limit_matches = DICT_DAEMON_LIMIT_MATCHES;
-int _dict_daemon_limit_defs = DICT_DAEMON_LIMIT_DEFS;
-int _dict_daemon_limit_time = DICT_DAEMON_LIMIT_TIME;
-int _dict_daemon_limit_queries = DICT_DAEMON_LIMIT_QUERIES;
+int _dict_daemon_limit_matches = DICT_DAEMON_LIMIT_MATCHES;
+int _dict_daemon_limit_defs = DICT_DAEMON_LIMIT_DEFS;
+int _dict_daemon_limit_time = DICT_DAEMON_LIMIT_TIME;
+int _dict_daemon_limit_queries = DICT_DAEMON_LIMIT_QUERIES;
-int _dict_markTime = 0;
-int _dict_markTime_set; /* 1 if set by command line option */
+int _dict_markTime = 0;
+int _dict_markTime_set; /* 1 if set by command line option */
-const char *locale = NULL;
-int locale_set; /* 1 if set by command line option */
+const char *locale = NULL;
+int locale_set; /* 1 if set by command line option */
-int client_delay = DICT_DEFAULT_DELAY;
-int client_delay_set; /* 1 if set by command line option */
+int client_delay = DICT_DEFAULT_DELAY;
+int client_delay_set; /* 1 if set by command line option */
-int depth = DICT_QUEUE_DEPTH;
-int depth_set; /* 1 if set by command line option */
+int depth = DICT_QUEUE_DEPTH;
+int depth_set; /* 1 if set by command line option */
-int useSyslog = 0;
-int syslog_facility_set; /* 1 if set by command line option */
+int useSyslog = 0;
+int syslog_facility_set; /* 1 if set by command line option */
-const char *preprocessor = NULL;
+const char *preprocessor = NULL;
-const char *bind_to = NULL;
-int bind_to_set; /* 1 if set by command line option */
+const char *bind_to = NULL;
+int bind_to_set; /* 1 if set by command line option */
/* information about dict server, i.e.
text returned by SHOW SERVER command
*/
-const char *site_info = NULL;
-int site_info_no_banner = 0;
-int site_info_no_uptime = 0;
-int site_info_no_dblist = 0;
+const char *site_info = NULL;
+int site_info_no_banner = 0;
+int site_info_no_uptime = 0;
+int site_info_no_dblist = 0;
-int inetd = 0;
+int inetd = 0;
-int need_reload_config = 0;
+int need_reload_config = 0;
-int need_unload_databases = 0;
-int databases_unloaded = 0;
+int need_unload_databases = 0;
+int databases_unloaded = 0;
-static const char *configFile = DICT_CONFIG_PATH DICTD_CONFIG_NAME;
+static const char *configFile = DICT_CONFIG_PATH DICTD_CONFIG_NAME;
-static void dict_close_databases (dictConfig *c);
-static void sanity (const char *confFile);
-static void dict_init_databases (dictConfig *c);
-static void dict_config_print (FILE *stream, dictConfig *c);
-static void postprocess_filenames (dictConfig *dc);
+static void dict_close_databases(dictConfig * c);
+static void sanity(const char *confFile);
+static void dict_init_databases(dictConfig * c);
+static void dict_config_print(FILE * stream, dictConfig * c);
+static void postprocess_filenames(dictConfig * dc);
-void dict_initsetproctitle( int argc, char **argv, char **envp )
+void dict_initsetproctitle(int argc, char **argv, char **envp)
{
- int i;
+ int i;
- _dict_argvstart = argv[0];
-
- for (i = 0; envp[i]; i++) continue;
+ _dict_argvstart = argv[0];
- if (i)
- _dict_argvlen = envp[i-1] + strlen(envp[i-1]) - _dict_argvstart;
- else
- _dict_argvlen = argv[argc-1] + strlen(argv[argc-1]) - _dict_argvstart;
+ for (i = 0; envp[i]; i++)
+ continue;
- argv[1] = NULL;
+ if (i)
+ _dict_argvlen =
+ envp[i - 1] + strlen(envp[i - 1]) - _dict_argvstart;
+ else
+ _dict_argvlen =
+ argv[argc - 1] + strlen(argv[argc - 1]) - _dict_argvstart;
+
+ argv[1] = NULL;
}
-void dict_setproctitle( const char *format, ... )
+void dict_setproctitle(const char *format, ...)
{
- va_list ap;
- int len;
- char buf[MAXPROCTITLE];
+ va_list ap;
+ int len;
+ char buf[MAXPROCTITLE];
- va_start( ap, format );
- vsnprintf( buf, MAXPROCTITLE, format, ap );
- va_end( ap );
+ va_start(ap, format);
+ vsnprintf(buf, MAXPROCTITLE, format, ap);
+ va_end(ap);
- if ((len = strlen(buf)) > MAXPROCTITLE-1)
- err_fatal( __func__, "buffer overflow (%d)\n", len );
+ if ((len = strlen(buf)) > MAXPROCTITLE - 1)
+ err_fatal(__func__, "buffer overflow (%d)\n", len);
- buf[ MIN(_dict_argvlen,MAXPROCTITLE) - 1 ] = '\0';
- strcpy( _dict_argvstart, buf );
- memset( _dict_argvstart+len, 0, _dict_argvlen-len );
+ buf[MIN(_dict_argvlen, MAXPROCTITLE) - 1] = '\0';
+ strcpy(_dict_argvstart, buf);
+ memset(_dict_argvstart + len, 0, _dict_argvlen - len);
}
-const char *dict_format_time( double t )
+const char *dict_format_time(double t)
{
- static int current = 0;
- static char buf[10][128]; /* Rotate 10 buffers */
- static char *this;
- long int s, m, h, d;
+ static int current = 0;
+ static char buf[10][128]; /* Rotate 10 buffers */
+ static char *this;
+ long int s, m, h, d;
- this = buf[current];
- if (++current >= 10) current = 0;
+ this = buf[current];
+ if (++current >= 10)
+ current = 0;
- if (t < 600) {
- snprintf( this, sizeof (buf [0]), "%0.3f", t );
- } else {
- s = (long int)t;
- d = s / (3600*24);
- s -= d * 3600 * 24;
- h = s / 3600;
- s -= h * 3600;
- m = s / 60;
- s -= m * 60;
+ if (t < 600) {
+ snprintf(this, sizeof(buf[0]), "%0.3f", t);
+ } else {
+ s = (long int) t;
+ d = s / (3600 * 24);
+ s -= d * 3600 * 24;
+ h = s / 3600;
+ s -= h * 3600;
+ m = s / 60;
+ s -= m * 60;
- if (d)
- snprintf( this, sizeof (buf [0]), "%ld+%02ld:%02ld:%02ld", d, h, m, s );
- else if (h)
- snprintf( this, sizeof (buf [0]), "%02ld:%02ld:%02ld", h, m, s );
- else
- snprintf( this, sizeof (buf [0]), "%02ld:%02ld", m, s );
- }
+ if (d)
+ snprintf(this, sizeof(buf[0]), "%ld+%02ld:%02ld:%02ld", d, h,
+ m, s);
+ else if (h)
+ snprintf(this, sizeof(buf[0]), "%02ld:%02ld:%02ld", h, m, s);
+ else
+ snprintf(this, sizeof(buf[0]), "%02ld:%02ld", m, s);
+ }
- return this;
+ return this;
}
-static int waitpid__exit_status (int status)
+static int waitpid__exit_status(int status)
{
- if (WIFEXITED(status)){
- return WEXITSTATUS(status);
- }else if (WIFSIGNALED(status)){
- return 128 + WTERMSIG(status);
- }else{
- return -1;
- }
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ return 128 + WTERMSIG(status);
+ } else {
+ return -1;
+ }
}
-static void reaper( int dummy )
+static void reaper(int dummy)
{
#if 0
- union wait status;
+ union wait status;
#else
- int status;
+ int status;
#endif
- pid_t pid;
+ pid_t pid;
- while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
- ++_dict_reaps;
+ while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
+ ++_dict_reaps;
- if (flg_test(LOG_SERVER))
- log_info( ":I: Reaped %d%s, exit status %i\n",
- pid,
- _dict_daemon ? " IN CHILD": "",
- waitpid__exit_status (status));
- }
+ if (flg_test(LOG_SERVER))
+ log_info(":I: Reaped %d%s, exit status %i\n",
+ pid,
+ _dict_daemon ? " IN CHILD" : "",
+ waitpid__exit_status(status));
+ }
}
-static int start_daemon( void )
+static int start_daemon(void)
{
- pid_t pid;
-
- ++_dict_forks;
- switch ((pid = fork())) {
- case 0:
- ++_dict_daemon;
- break;
- case -1:
- log_info( ":E: Unable to fork daemon\n" );
- alarm(10); /* Can't use sleep() here */
- pause();
- break;
- default:
- if (flg_test(LOG_SERVER)) log_info( ":I: Forked %d\n", pid );
- break;
- }
- return pid;
+ pid_t pid;
+
+ ++_dict_forks;
+ switch ((pid = fork())) {
+ case 0:
+ ++_dict_daemon;
+ break;
+ case -1:
+ log_info(":E: Unable to fork daemon\n");
+ alarm(10); /* Can't use sleep() here */
+ pause();
+ break;
+ default:
+ if (flg_test(LOG_SERVER))
+ log_info(":I: Forked %d\n", pid);
+ break;
+ }
+ return pid;
}
-static const char * signal2name (int sig)
+static const char *signal2name(int sig)
{
- static char name [50];
+ static char name[50];
- switch (sig) {
- case SIGHUP:
- return "SIGHUP";
- case SIGINT:
- return "SIGINT";
- case SIGQUIT:
- return "SIGQUIT";
- case SIGILL:
- return "SIGILL";
- case SIGTRAP:
- return "SIGTRAP";
- case SIGTERM:
- return "SIGTERM";
- case SIGPIPE:
- return "SIGPIPE";
- case SIGALRM:
- return "SIGALRM";
- default:
- snprintf (name, sizeof (name), "Signal %d", sig);
- return name;
- }
+ switch (sig) {
+ case SIGHUP:
+ return "SIGHUP";
+ case SIGINT:
+ return "SIGINT";
+ case SIGQUIT:
+ return "SIGQUIT";
+ case SIGILL:
+ return "SIGILL";
+ case SIGTRAP:
+ return "SIGTRAP";
+ case SIGTERM:
+ return "SIGTERM";
+ case SIGPIPE:
+ return "SIGPIPE";
+ case SIGALRM:
+ return "SIGALRM";
+ default:
+ snprintf(name, sizeof(name), "Signal %d", sig);
+ return name;
+ }
}
-static void log_sig_info (int sig)
+static void log_sig_info(int sig)
{
- log_info (
- ":I: %s: c/f = %d/%d; %sr %su %ss\n",
- signal2name (sig),
- _dict_comparisons,
- _dict_forks,
- dict_format_time (tim_get_real ("dictd")),
- dict_format_time (tim_get_user ("dictd")),
- dict_format_time (tim_get_system ("dictd")));
+ log_info(":I: %s: c/f = %d/%d; %sr %su %ss\n",
+ signal2name(sig),
+ _dict_comparisons,
+ _dict_forks,
+ dict_format_time(tim_get_real("dictd")),
+ dict_format_time(tim_get_user("dictd")),
+ dict_format_time(tim_get_system("dictd")));
}
-static void unload_databases (void)
+static void unload_databases(void)
{
- dict_close_databases (DictConfig);
- DictConfig = NULL;
+ dict_close_databases(DictConfig);
+ DictConfig = NULL;
}
-static void reload_config (void)
+static void reload_config(void)
{
- dict_close_databases (DictConfig);
+ dict_close_databases(DictConfig);
- if (!access(configFile,R_OK)){
- prs_file_pp (preprocessor, configFile);
- postprocess_filenames (DictConfig);
- }
+ if (!access(configFile, R_OK)) {
+ prs_file_pp(preprocessor, configFile);
+ postprocess_filenames(DictConfig);
+ }
- sanity (configFile);
+ sanity(configFile);
- if (dbg_test (DBG_VERBOSE))
- dict_config_print( NULL, DictConfig );
+ if (dbg_test(DBG_VERBOSE))
+ dict_config_print(NULL, DictConfig);
- dict_init_databases (DictConfig);
+ dict_init_databases(DictConfig);
}
-static void xsigaddset (sigset_t *set, int signo)
+static void xsigaddset(sigset_t * set, int signo)
{
- if (sigaddset (set, signo)){
- log_error ("", "sigaddset(2) failed: %s\n", strerror (errno));
- }
+ if (sigaddset(set, signo)) {
+ log_error("", "sigaddset(2) failed: %s\n", strerror(errno));
+ }
}
-static void xsigprocmask (int how, const sigset_t *set, sigset_t *oset)
+static void xsigprocmask(int how, const sigset_t * set, sigset_t * oset)
{
- if (sigprocmask (how, set, oset)){
- log_error ("", "sigaddset(2) failed: %s\n", strerror (errno));
- }
+ if (sigprocmask(how, set, oset)) {
+ log_error("", "sigaddset(2) failed: %s\n", strerror(errno));
+ }
}
/*
@@ -353,910 +358,930 @@ static void unblock_signals (void)
}
*/
-static void handler( int sig )
+static void handler(int sig)
{
- const char *name = NULL;
- time_t t;
+ const char *name = NULL;
+ time_t t;
- name = signal2name (sig);
+ name = signal2name(sig);
- if (_dict_daemon) {
- daemon_terminate( sig, name );
- } else {
- tim_stop( "dictd" );
- switch (sig){
- case SIGALRM:
- if (_dict_markTime > 0){
- time(&t);
- log_info( ":t: %24.24s; %d/%d %sr %su %ss\n",
- ctime(&t),
- _dict_forks - _dict_reaps,
- _dict_forks,
- dict_format_time( tim_get_real( "dictd" ) ),
- dict_format_time( tim_get_user( "dictd" ) ),
- dict_format_time( tim_get_system( "dictd" ) ) );
- alarm(_dict_markTime);
- return;
- }
+ if (_dict_daemon) {
+ daemon_terminate(sig, name);
+ } else {
+ tim_stop("dictd");
+ switch (sig) {
+ case SIGALRM:
+ if (_dict_markTime > 0) {
+ time(&t);
+ log_info(":t: %24.24s; %d/%d %sr %su %ss\n",
+ ctime(&t),
+ _dict_forks - _dict_reaps,
+ _dict_forks,
+ dict_format_time(tim_get_real("dictd")),
+ dict_format_time(tim_get_user("dictd")),
+ dict_format_time(tim_get_system("dictd")));
+ alarm(_dict_markTime);
+ return;
+ }
- break;
- }
+ break;
+ }
- log_sig_info (sig);
- }
- if (!dbg_test(DBG_NOFORK) || sig != SIGALRM)
- exit(sig+128);
+ log_sig_info(sig);
+ }
+ if (!dbg_test(DBG_NOFORK) || sig != SIGALRM)
+ exit(sig + 128);
}
-static const char *postprocess_filename (const char *fn, const char *prefix)
+static const char *postprocess_filename(const char *fn, const char *prefix)
{
- char *new_fn;
+ char *new_fn;
- if (!fn)
- return NULL;
+ if (!fn)
+ return NULL;
- if (fn [0] != '/' && fn [0] != '.'){
- new_fn = xmalloc (2 + strlen (prefix) + strlen (fn));
- strcpy (new_fn, prefix);
- strcat (new_fn, fn);
+ if (fn[0] != '/' && fn[0] != '.') {
+ new_fn = xmalloc(2 + strlen(prefix) + strlen(fn));
+ strcpy(new_fn, prefix);
+ strcat(new_fn, fn);
- return new_fn;
- }else{
- return xstrdup (fn);
- }
+ return new_fn;
+ } else {
+ return xstrdup(fn);
+ }
}
-const char *postprocess_plugin_filename (const char *fn)
+const char *postprocess_plugin_filename(const char *fn)
{
- return postprocess_filename (fn, DICT_PLUGIN_PATH);
+ return postprocess_filename(fn, DICT_PLUGIN_PATH);
}
-const char *postprocess_dict_filename (const char *fn)
+const char *postprocess_dict_filename(const char *fn)
{
- return postprocess_filename (fn, DICT_DICTIONARY_PATH);
+ return postprocess_filename(fn, DICT_DICTIONARY_PATH);
}
-static void postprocess_filenames (dictConfig *dc)
+static void postprocess_filenames(dictConfig * dc)
{
- lst_Position p;
- dictDatabase *db;
+ lst_Position p;
+ dictDatabase *db;
- LST_ITERATE(dc -> dbl, p, db) {
- db -> dataFilename = postprocess_dict_filename (db -> dataFilename);
- db -> indexFilename = postprocess_dict_filename (db -> indexFilename);
- db -> indexsuffixFilename = postprocess_dict_filename (db -> indexsuffixFilename);
- db -> indexwordFilename = postprocess_dict_filename (db -> indexwordFilename);
- db -> pluginFilename = postprocess_plugin_filename (db -> pluginFilename);
- }
+ LST_ITERATE(dc->dbl, p, db) {
+ db->dataFilename = postprocess_dict_filename(db->dataFilename);
+ db->indexFilename = postprocess_dict_filename(db->indexFilename);
+ db->indexsuffixFilename =
+ postprocess_dict_filename(db->indexsuffixFilename);
+ db->indexwordFilename =
+ postprocess_dict_filename(db->indexwordFilename);
+ db->pluginFilename =
+ postprocess_plugin_filename(db->pluginFilename);
+ }
- site_info = postprocess_dict_filename (site_info);
+ site_info = postprocess_dict_filename(site_info);
}
-static void handler_sighup (int sig)
+static void handler_sighup(int sig)
{
- log_sig_info (sig);
- need_reload_config = 1;
+ log_sig_info(sig);
+ need_reload_config = 1;
}
-static void handler_sigusr1 (int sig)
+static void handler_sigusr1(int sig)
{
- log_sig_info (sig);
- need_unload_databases = 1;
+ log_sig_info(sig);
+ need_unload_databases = 1;
}
-static void setsig( int sig, void (*f)(int), int sa_flags )
+static void setsig(int sig, void (*f) (int), int sa_flags)
{
- struct sigaction sa;
+ struct sigaction sa;
- sa.sa_handler = f;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = sa_flags;
- sigaction(sig, &sa, NULL);
+ sa.sa_handler = f;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = sa_flags;
+ sigaction(sig, &sa, NULL);
}
struct access_print_struct {
- FILE *s;
- int offset;
+ FILE *s;
+ int offset;
};
-static int access_print( const void *datum, void *arg )
+static int access_print(const void *datum, void *arg)
{
- dictAccess *a = (dictAccess *)datum;
- struct access_print_struct *aps = (struct access_print_struct *)arg;
- FILE *s = aps->s;
- int offset = aps->offset;
- int i;
- const char *desc;
-
- for (i = 0; i < offset; i++) fputc( ' ', s );
- switch (a->type) {
- case DICT_DENY: desc = "deny"; break;
- case DICT_ALLOW: desc = "allow"; break;
- case DICT_AUTHONLY: desc = "authonly"; break;
- case DICT_USER: desc = "user"; break;
- case DICT_GROUP: desc = "group"; break; /* Not implemented. */
- default: desc = "unknown"; break;
- }
- fprintf( s, "%s %s\n", desc, a->spec );
- return 0;
-}
-
-static void acl_print( FILE *s, lst_List l, int offset)
-{
- struct access_print_struct aps;
- int i;
-
- aps.s = s;
- aps.offset = offset + 3;
-
- for (i = 0; i < offset; i++) fputc( ' ', s );
- fprintf( s, "access {\n" );
- lst_iterate_arg( l, access_print, &aps );
- for (i = 0; i < offset; i++) fputc( ' ', s );
- fprintf( s, "}\n" );
-}
-
-static int user_print( const void *key, const void *datum, void *arg )
-{
- const char *username = (const char *)key;
- const char *secret = (const char *)datum;
- FILE *s = (FILE *)arg;
-
- if (dbg_test(DBG_AUTH))
- fprintf( s, "user %s %s\n", username, secret );
- else
- fprintf( s, "user %s *\n", username );
- return 0;
-}
-
-static int config_print( const void *datum, void *arg )
-{
- dictDatabase *db = (dictDatabase *)datum;
- FILE *s = (FILE *)arg;
-
- fprintf( s, "database %s {\n", db->databaseName );
-
- if (db->dataFilename)
- fprintf( s, " data %s\n", db->dataFilename );
- if (db->indexFilename)
- fprintf( s, " index %s\n", db->indexFilename );
- if (db->indexsuffixFilename)
- fprintf( s, " index_suffix %s\n", db->indexsuffixFilename );
- if (db->indexwordFilename)
- fprintf( s, " index_word %s\n", db->indexwordFilename );
- if (db->filter)
- fprintf( s, " filter %s\n", db->filter );
- if (db->prefilter)
- fprintf( s, " prefilter %s\n", db->prefilter );
- if (db->postfilter)
- fprintf( s, " postfilter %s\n", db->postfilter );
- if (db->databaseShort)
- fprintf( s, " name %s\n", db->databaseShort );
- if (db->acl)
- acl_print( s, db->acl, 3 );
-
- fprintf( s, "}\n" );
-
- return 0;
-}
-
-static void dict_config_print( FILE *stream, dictConfig *c )
-{
- FILE *s = stream ? stream : stderr;
-
- if (c->acl) acl_print( s, c->acl, 0 );
- lst_iterate_arg( c->dbl, config_print, s );
- if (c->usl) hsh_iterate_arg( c->usl, user_print, s );
-}
-
-static const char *get_entry_info( dictDatabase *db, const char *entryName )
-{
- dictWord *dw;
- lst_List list = lst_create();
- char *pt, *buf;
- size_t len;
-
- if (
- 0 >= dict_search (
- list, entryName, db, DICT_STRAT_EXACT, 0,
- NULL, NULL, NULL ))
- {
+ dictAccess *a = (dictAccess *) datum;
+ struct access_print_struct *aps = (struct access_print_struct *) arg;
+ FILE *s = aps->s;
+ int offset = aps->offset;
+ int i;
+ const char *desc;
+
+ for (i = 0; i < offset; i++)
+ fputc(' ', s);
+ switch (a->type) {
+ case DICT_DENY:
+ desc = "deny";
+ break;
+ case DICT_ALLOW:
+ desc = "allow";
+ break;
+ case DICT_AUTHONLY:
+ desc = "authonly";
+ break;
+ case DICT_USER:
+ desc = "user";
+ break;
+ case DICT_GROUP:
+ desc = "group";
+ break; /* Not implemented. */
+ default:
+ desc = "unknown";
+ break;
+ }
+ fprintf(s, "%s %s\n", desc, a->spec);
+ return 0;
+}
+
+static void acl_print(FILE * s, lst_List l, int offset)
+{
+ struct access_print_struct aps;
+ int i;
+
+ aps.s = s;
+ aps.offset = offset + 3;
+
+ for (i = 0; i < offset; i++)
+ fputc(' ', s);
+ fprintf(s, "access {\n");
+ lst_iterate_arg(l, access_print, &aps);
+ for (i = 0; i < offset; i++)
+ fputc(' ', s);
+ fprintf(s, "}\n");
+}
+
+static int user_print(const void *key, const void *datum, void *arg)
+{
+ const char *username = (const char *) key;
+ const char *secret = (const char *) datum;
+ FILE *s = (FILE *) arg;
+
+ if (dbg_test(DBG_AUTH))
+ fprintf(s, "user %s %s\n", username, secret);
+ else
+ fprintf(s, "user %s *\n", username);
+ return 0;
+}
+
+static int config_print(const void *datum, void *arg)
+{
+ dictDatabase *db = (dictDatabase *) datum;
+ FILE *s = (FILE *) arg;
+
+ fprintf(s, "database %s {\n", db->databaseName);
+
+ if (db->dataFilename)
+ fprintf(s, " data %s\n", db->dataFilename);
+ if (db->indexFilename)
+ fprintf(s, " index %s\n", db->indexFilename);
+ if (db->indexsuffixFilename)
+ fprintf(s, " index_suffix %s\n", db->indexsuffixFilename);
+ if (db->indexwordFilename)
+ fprintf(s, " index_word %s\n", db->indexwordFilename);
+ if (db->filter)
+ fprintf(s, " filter %s\n", db->filter);
+ if (db->prefilter)
+ fprintf(s, " prefilter %s\n", db->prefilter);
+ if (db->postfilter)
+ fprintf(s, " postfilter %s\n", db->postfilter);
+ if (db->databaseShort)
+ fprintf(s, " name %s\n", db->databaseShort);
+ if (db->acl)
+ acl_print(s, db->acl, 3);
+
+ fprintf(s, "}\n");
+
+ return 0;
+}
+
+static void dict_config_print(FILE * stream, dictConfig * c)
+{
+ FILE *s = stream ? stream : stderr;
+
+ if (c->acl)
+ acl_print(s, c->acl, 0);
+ lst_iterate_arg(c->dbl, config_print, s);
+ if (c->usl)
+ hsh_iterate_arg(c->usl, user_print, s);
+}
+
+static const char *get_entry_info(dictDatabase * db, const char *entryName)
+{
+ dictWord *dw;
+ lst_List list = lst_create();
+ char *pt, *buf;
+ size_t len;
+
+ if (0 >= dict_search(list, entryName, db, DICT_STRAT_EXACT, 0,
+ NULL, NULL, NULL)) {
#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
+ call_dictdb_free(DictConfig->dbl);
#endif
- lst_destroy( list );
- return NULL;
- }
+ lst_destroy(list);
+ return NULL;
+ }
- dw = lst_nth_get( list, 1 );
+ dw = lst_nth_get(list, 1);
- assert (dw -> database);
+ assert(dw->database);
- buf = pt = dict_data_obtain( dw -> database, dw );
+ buf = pt = dict_data_obtain(dw->database, dw);
- if (!strncmp (pt, "00database", 10) || !strncmp (pt, "00-database", 11)){
- while (*pt != '\n')
- ++pt;
+ if (!strncmp(pt, "00database", 10) || !strncmp(pt, "00-database", 11)) {
+ while (*pt != '\n')
+ ++pt;
- ++pt;
- }
+ ++pt;
+ }
- while (*pt == ' ' || *pt == '\t')
- ++pt;
+ while (*pt == ' ' || *pt == '\t')
+ ++pt;
- len = strlen(pt);
- if (pt [len - 1] == '\n')
- pt [len - 1] = '\0';
+ len = strlen(pt);
+ if (pt[len - 1] == '\n')
+ pt[len - 1] = '\0';
#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
+ call_dictdb_free(DictConfig->dbl);
#endif
- dict_destroy_list( list );
+ dict_destroy_list(list);
- pt = xstrdup (pt);
+ pt = xstrdup(pt);
- xfree (buf);
+ xfree(buf);
- return pt;
+ return pt;
}
-static dictDatabase *dbname2database (const char *dbname)
+static dictDatabase *dbname2database(const char *dbname)
{
- dictDatabase *db = NULL;
- lst_Position db_pos = lst_init_position (DictConfig->dbl);
+ dictDatabase *db = NULL;
+ lst_Position db_pos = lst_init_position(DictConfig->dbl);
- while (db_pos){
- db = lst_get_position (db_pos);
+ while (db_pos) {
+ db = lst_get_position(db_pos);
- if (!strcmp (db -> databaseName, dbname)){
- return db;
- }
+ if (!strcmp(db->databaseName, dbname)) {
+ return db;
+ }
- db_pos = lst_next_position (db_pos);
- }
+ db_pos = lst_next_position(db_pos);
+ }
- return NULL;
+ return NULL;
}
-static lst_List string2virtual_db_list (char *s)
+static lst_List string2virtual_db_list(char *s)
{
- int len, i;
- lst_List virtual_db_list;
- char *p;
+ int len, i;
+ lst_List virtual_db_list;
+ char *p;
- dictDatabase *db = NULL;
+ dictDatabase *db = NULL;
- p = s;
- len = strlen (s);
+ p = s;
+ len = strlen(s);
- virtual_db_list = lst_create ();
+ virtual_db_list = lst_create();
- for (i = 0; i <= len; ++i){
- if (s [i] == ',' || s [i] == '\n' || s [i] == '\0'){
- s [i] = '\0';
+ for (i = 0; i <= len; ++i) {
+ if (s[i] == ',' || s[i] == '\n' || s[i] == '\0') {
+ s[i] = '\0';
- if (*p){
- db = dbname2database (p);
+ if (*p) {
+ db = dbname2database(p);
- if (db){
- lst_append (virtual_db_list, db);
- }else{
- log_info( ":E: Unknown database '%s'\n", p );
- PRINTF(DBG_INIT, (":E: Unknown database '%s'\n", p));
- exit (2);
+ if (db) {
+ lst_append(virtual_db_list, db);
+ } else {
+ log_info(":E: Unknown database '%s'\n", p);
+ PRINTF(DBG_INIT, (":E: Unknown database '%s'\n", p));
+ exit(2);
+ }
}
- }
- p = s + i + 1;
- }
- }
-
- return virtual_db_list;
-}
-
-static int init_virtual_db_list (const void *datum)
-{
- lst_List list;
- dictDatabase *db = (dictDatabase *)datum;
- dictWord *dw;
- char *buf;
- int ret;
-
- if (db -> database_list){
- buf = xstrdup (db -> database_list);
- db -> virtual_db_list = string2virtual_db_list (buf);
- xfree (buf);
- }else{
- if (!db -> index)
- return 0;
-
- list = lst_create();
- ret = dict_search (
- list, DICT_FLAG_VIRTUAL, db, DICT_STRAT_EXACT, 0,
- NULL, NULL, NULL);
-
- switch (ret){
- case 1: case 2:
- dw = (dictWord *) lst_pop (list);
- buf = dict_data_obtain (db, dw);
- dict_destroy_datum (dw);
-
- db -> virtual_db_list = string2virtual_db_list (buf);
-
- xfree (buf);
- break;
- case 0:
- break;
- default:
- err_fatal (
- __func__,
- "index file contains more than one %s entry",
- DICT_FLAG_VIRTUAL);
- }
-
- dict_destroy_list (list);
- }
-
- return 0;
-}
-
-static int init_mime_db_list (const void *datum)
-{
- dictDatabase *db = (dictDatabase *)datum;
-
- if (!db -> mime_db)
- return 0;
-
- /* MIME */
- if (db -> mime_mimeDbname){
- db -> mime_mimeDB = dbname2database (db -> mime_mimeDbname);
-
- if (!db -> mime_mimeDB){
- err_fatal (
- __func__,
- "Incorrect database name '%s'\n",
- db -> mime_mimeDbname);
- }
- }else{
- err_fatal (
- __func__,
- "MIME database '%s' has no mime_dbname keyword\n",
- db -> databaseName);
- }
-
- /* NO MIME */
- if (db -> mime_nomimeDbname){
- db -> mime_nomimeDB = dbname2database (db -> mime_nomimeDbname);
-
- if (!db -> mime_nomimeDB){
- err_fatal (
- __func__,
- "Incorrect database name '%s'\n",
- db -> mime_nomimeDbname);
- }
- }else{
- err_fatal (
- __func__,
- "MIME database '%s' has no nomime_dbname keyword\n",
- db -> databaseName);
- }
+ p = s + i + 1;
+ }
+ }
+
+ return virtual_db_list;
+}
+
+static int init_virtual_db_list(const void *datum)
+{
+ lst_List list;
+ dictDatabase *db = (dictDatabase *) datum;
+ dictWord *dw;
+ char *buf;
+ int ret;
+
+ if (db->database_list) {
+ buf = xstrdup(db->database_list);
+ db->virtual_db_list = string2virtual_db_list(buf);
+ xfree(buf);
+ } else {
+ if (!db->index)
+ return 0;
+
+ list = lst_create();
+ ret = dict_search(list, DICT_FLAG_VIRTUAL, db, DICT_STRAT_EXACT, 0,
+ NULL, NULL, NULL);
+
+ switch (ret) {
+ case 1:
+ case 2:
+ dw = (dictWord *) lst_pop(list);
+ buf = dict_data_obtain(db, dw);
+ dict_destroy_datum(dw);
+
+ db->virtual_db_list = string2virtual_db_list(buf);
+
+ xfree(buf);
+ break;
+ case 0:
+ break;
+ default:
+ err_fatal(__func__,
+ "index file contains more than one %s entry",
+ DICT_FLAG_VIRTUAL);
+ }
+
+ dict_destroy_list(list);
+ }
+
+ return 0;
+}
+
+static int init_mime_db_list(const void *datum)
+{
+ dictDatabase *db = (dictDatabase *) datum;
+
+ if (!db->mime_db)
+ return 0;
+
+ /* MIME */
+ if (db->mime_mimeDbname) {
+ db->mime_mimeDB = dbname2database(db->mime_mimeDbname);
+
+ if (!db->mime_mimeDB) {
+ err_fatal(__func__,
+ "Incorrect database name '%s'\n",
+ db->mime_mimeDbname);
+ }
+ } else {
+ err_fatal(__func__,
+ "MIME database '%s' has no mime_dbname keyword\n",
+ db->databaseName);
+ }
+
+ /* NO MIME */
+ if (db->mime_nomimeDbname) {
+ db->mime_nomimeDB = dbname2database(db->mime_nomimeDbname);
+
+ if (!db->mime_nomimeDB) {
+ err_fatal(__func__,
+ "Incorrect database name '%s'\n",
+ db->mime_nomimeDbname);
+ }
+ } else {
+ err_fatal(__func__,
+ "MIME database '%s' has no nomime_dbname keyword\n",
+ db->databaseName);
+ }
- return 0;
+ return 0;
}
-static int init_plugin( const void *datum )
+static int init_plugin(const void *datum)
{
#ifdef USE_PLUGIN
- dictDatabase *db = (dictDatabase *)datum;
- dict_plugin_init (db);
+ dictDatabase *db = (dictDatabase *) datum;
+ dict_plugin_init(db);
#endif
- return 0;
+ return 0;
}
-void dict_disable_strat (dictDatabase *db, const char* strategy)
+void dict_disable_strat(dictDatabase * db, const char *strategy)
{
- int strat = -1;
- int array_size = get_max_strategy_num () + 1;
+ int strat = -1;
+ int array_size = get_max_strategy_num() + 1;
- assert (db);
- assert (strategy);
+ assert(db);
+ assert(strategy);
- if (!db -> strategy_disabled){
- db -> strategy_disabled = xmalloc (array_size * sizeof (int));
- memset (db -> strategy_disabled, 0, array_size * sizeof (int));
- }
+ if (!db->strategy_disabled) {
+ db->strategy_disabled = xmalloc(array_size * sizeof(int));
+ memset(db->strategy_disabled, 0, array_size * sizeof(int));
+ }
- strat = lookup_strategy_ex (strategy);
- assert (strat >= 0);
+ strat = lookup_strategy_ex(strategy);
+ assert(strat >= 0);
- db -> strategy_disabled [strat] = 1;
+ db->strategy_disabled[strat] = 1;
}
-static void init_database_alphabet (dictDatabase *db)
+static void init_database_alphabet(dictDatabase * db)
{
- int ret;
- lst_List l;
- const dictWord *dw;
- char *data;
+ int ret;
+ lst_List l;
+ const dictWord *dw;
+ char *data;
- if (!db -> normal_db)
- return;
+ if (!db->normal_db)
+ return;
- l = lst_create ();
+ l = lst_create();
- ret = dict_search_database_ (l, DICT_FLAG_ALPHABET, db, DICT_STRAT_EXACT);
+ ret =
+ dict_search_database_(l, DICT_FLAG_ALPHABET, db, DICT_STRAT_EXACT);
- if (ret){
- dw = (const dictWord *) lst_top (l);
- data = dict_data_obtain (db, dw);
- db -> alphabet = data;
+ if (ret) {
+ dw = (const dictWord *) lst_top(l);
+ data = dict_data_obtain(db, dw);
+ db->alphabet = data;
- data = strchr (db -> alphabet, '\n');
- if (data)
- *data = 0;
- }
+ data = strchr(db->alphabet, '\n');
+ if (data)
+ *data = 0;
+ }
- dict_destroy_list (l);
+ dict_destroy_list(l);
}
-static void init_database_default_strategy (dictDatabase *db)
+static void init_database_default_strategy(dictDatabase * db)
{
- int ret;
- lst_List l;
- const dictWord *dw;
- char *data;
- int def_strat = -1;
- char *p;
+ int ret;
+ lst_List l;
+ const dictWord *dw;
+ char *data;
+ int def_strat = -1;
+ char *p;
- if (!db -> normal_db)
- return;
+ if (!db->normal_db)
+ return;
- if (db -> default_strategy > 0){
- /* already set by `default_strategy' directive*/
- return;
- }
+ if (db->default_strategy > 0) {
+ /* already set by `default_strategy' directive */
+ return;
+ }
- l = lst_create ();
+ l = lst_create();
- ret = dict_search_database_ (l, DICT_FLAG_DEFAULT_STRAT, db, DICT_STRAT_EXACT);
+ ret =
+ dict_search_database_(l, DICT_FLAG_DEFAULT_STRAT, db,
+ DICT_STRAT_EXACT);
- if (ret){
- dw = (const dictWord *) lst_top (l);
- data = dict_data_obtain (db, dw);
+ if (ret) {
+ dw = (const dictWord *) lst_top(l);
+ data = dict_data_obtain(db, dw);
- for (p=data; *p && isalpha ((unsigned char) *p); ++p){
- }
- *p = '\0';
+ for (p = data; *p && isalpha((unsigned char) *p); ++p) {
+ }
+ *p = '\0';
- def_strat = lookup_strategy (data);
- if (-1 == def_strat){
- PRINTF (DBG_INIT, (":I: `%s' is not supported by dictd\n", data));
- }else{
- db -> default_strategy = def_strat;
- }
+ def_strat = lookup_strategy(data);
+ if (-1 == def_strat) {
+ PRINTF(DBG_INIT,
+ (":I: `%s' is not supported by dictd\n", data));
+ } else {
+ db->default_strategy = def_strat;
+ }
- xfree (data);
- }
+ xfree(data);
+ }
- dict_destroy_list (l);
+ dict_destroy_list(l);
}
-static int init_database_mime_header (const void *datum)
+static int init_database_mime_header(const void *datum)
{
- dictDatabase *db = (dictDatabase *) datum;
- int ret;
- lst_List l;
- const dictWord *dw;
- char *data;
+ dictDatabase *db = (dictDatabase *) datum;
+ int ret;
+ lst_List l;
+ const dictWord *dw;
+ char *data;
- if (!db -> normal_db)
- return 0;
+ if (!db->normal_db)
+ return 0;
- if (db -> mime_header){
- /* already set by `mime_header' directive*/
- return 0;
- }
+ if (db->mime_header) {
+ /* already set by `mime_header' directive */
+ return 0;
+ }
- l = lst_create ();
+ l = lst_create();
- ret = dict_search_database_ (l, DICT_FLAG_MIME_HEADER, db, DICT_STRAT_EXACT);
+ ret =
+ dict_search_database_(l, DICT_FLAG_MIME_HEADER, db,
+ DICT_STRAT_EXACT);
- if (ret){
- dw = (const dictWord *) lst_top (l);
- data = dict_data_obtain (db, dw);
+ if (ret) {
+ dw = (const dictWord *) lst_top(l);
+ data = dict_data_obtain(db, dw);
- db -> mime_header = xstrdup (data);
+ db->mime_header = xstrdup(data);
- xfree (data);
- }
+ xfree(data);
+ }
- dict_destroy_list (l);
+ dict_destroy_list(l);
- return 0;
+ return 0;
}
-static int init_database( const void *datum )
+static int init_database(const void *datum)
{
- dictDatabase *db = (dictDatabase *)datum;
- const char *strat_name = NULL;
+ dictDatabase *db = (dictDatabase *) datum;
+ const char *strat_name = NULL;
- PRINTF (DBG_INIT, (":I: Initializing '%s'\n", db->databaseName));
+ PRINTF(DBG_INIT, (":I: Initializing '%s'\n", db->databaseName));
- if (db->indexFilename){
- PRINTF (DBG_INIT, (":I: Opening indices\n"));
- }
+ if (db->indexFilename) {
+ PRINTF(DBG_INIT, (":I: Opening indices\n"));
+ }
- db->index = dict_index_open( db->indexFilename, 1, NULL );
+ db->index = dict_index_open(db->indexFilename, 1, NULL);
- if (db->indexFilename){
- PRINTF (DBG_INIT, (":I: .index <ok>\n"));
- }
+ if (db->indexFilename) {
+ PRINTF(DBG_INIT, (":I: .index <ok>\n"));
+ }
- if (db->index){
- db->index_suffix = dict_index_open(
- db->indexsuffixFilename,
- 0, db->index);
+ if (db->index) {
+ db->index_suffix = dict_index_open(db->indexsuffixFilename,
+ 0, db->index);
- db->index_word = dict_index_open(
- db->indexwordFilename,
- 0, db->index);
- }
+ db->index_word = dict_index_open(db->indexwordFilename,
+ 0, db->index);
+ }
- if (db->index_suffix){
- PRINTF (DBG_INIT, (":I: .indexsuffix <ok>\n"));
- db->index_suffix->flag_8bit = db->index->flag_8bit;
- db->index_suffix->flag_utf8 = db->index->flag_utf8;
- db->index_suffix->flag_allchars = db->index->flag_allchars;
- }
- if (db->index_word){
- PRINTF (DBG_INIT, (":I: .indexword <ok>\n"));
- db->index_word->flag_utf8 = db->index->flag_utf8;
- db->index_word->flag_8bit = db->index->flag_8bit;
- db->index_word->flag_allchars = db->index->flag_allchars;
- }
+ if (db->index_suffix) {
+ PRINTF(DBG_INIT, (":I: .indexsuffix <ok>\n"));
+ db->index_suffix->flag_8bit = db->index->flag_8bit;
+ db->index_suffix->flag_utf8 = db->index->flag_utf8;
+ db->index_suffix->flag_allchars = db->index->flag_allchars;
+ }
+ if (db->index_word) {
+ PRINTF(DBG_INIT, (":I: .indexword <ok>\n"));
+ db->index_word->flag_utf8 = db->index->flag_utf8;
+ db->index_word->flag_8bit = db->index->flag_8bit;
+ db->index_word->flag_allchars = db->index->flag_allchars;
+ }
- if (db->dataFilename){
- PRINTF (DBG_INIT, (":I: Opening data\n"));
- }
+ if (db->dataFilename) {
+ PRINTF(DBG_INIT, (":I: Opening data\n"));
+ }
- db->data = dict_data_open( db->dataFilename, 0 );
+ db->data = dict_data_open(db->dataFilename, 0);
- init_database_alphabet (db);
- if (db -> alphabet){
- PRINTF (DBG_INIT, (":I: alphabet: %s\n", db -> alphabet));
- }else{
- PRINTF (DBG_INIT, (":I: alphabet: (NULL)\n"));
- }
+ init_database_alphabet(db);
+ if (db->alphabet) {
+ PRINTF(DBG_INIT, (":I: alphabet: %s\n", db->alphabet));
+ } else {
+ PRINTF(DBG_INIT, (":I: alphabet: (NULL)\n"));
+ }
- if (db -> default_strategy){
- strat_name = get_strategy (db -> default_strategy) -> name;
- PRINTF (DBG_INIT, (":I: default_strategy (from conf file): %s\n",
- strat_name));
- }else{
- init_database_default_strategy (db);
- if (db -> default_strategy){
- strat_name = get_strategy (db -> default_strategy) -> name;
- PRINTF (DBG_INIT, (":I: default_strategy (from db): %s\n", strat_name));
- }else{
- db -> default_strategy = default_strategy;
- }
- }
+ if (db->default_strategy) {
+ strat_name = get_strategy(db->default_strategy)->name;
+ PRINTF(DBG_INIT,
+ (":I: default_strategy (from conf file): %s\n",
+ strat_name));
+ } else {
+ init_database_default_strategy(db);
+ if (db->default_strategy) {
+ strat_name = get_strategy(db->default_strategy)->name;
+ PRINTF(DBG_INIT,
+ (":I: default_strategy (from db): %s\n",
+ strat_name));
+ } else {
+ db->default_strategy = default_strategy;
+ }
+ }
- if (db->dataFilename){
- PRINTF(DBG_INIT,
- (":I: '%s' initialized\n", db->databaseName));
- }
+ if (db->dataFilename) {
+ PRINTF(DBG_INIT, (":I: '%s' initialized\n", db->databaseName));
+ }
- return 0;
+ return 0;
}
-static int init_database_short (const void *datum)
+static int init_database_short(const void *datum)
{
- char *NL;
+ char *NL;
- dictDatabase *db = (dictDatabase *) datum;
+ dictDatabase *db = (dictDatabase *) datum;
- if (!db->databaseShort){
- db->databaseShort = get_entry_info( db, DICT_SHORT_ENTRY_NAME );
- }else if (*db->databaseShort == '@'){
- db->databaseShort = get_entry_info( db, db->databaseShort + 1 );
- }else{
- db->databaseShort = xstrdup (db->databaseShort);
- }
+ if (!db->databaseShort) {
+ db->databaseShort = get_entry_info(db, DICT_SHORT_ENTRY_NAME);
+ } else if (*db->databaseShort == '@') {
+ db->databaseShort = get_entry_info(db, db->databaseShort + 1);
+ } else {
+ db->databaseShort = xstrdup(db->databaseShort);
+ }
- if (db->databaseShort){
- NL = strchr (db->databaseShort, '\n');
- if (NL)
- *NL = 0;
- }
+ if (db->databaseShort) {
+ NL = strchr(db->databaseShort, '\n');
+ if (NL)
+ *NL = 0;
+ }
- if (!db->databaseShort)
- db->databaseShort = xstrdup (db->databaseName);
+ if (!db->databaseShort)
+ db->databaseShort = xstrdup(db->databaseName);
- return 0;
+ return 0;
}
-static int close_plugin (const void *datum)
+static int close_plugin(const void *datum)
{
#ifdef USE_PLUGIN
- dictDatabase *db = (dictDatabase *)datum;
- dict_plugin_destroy (db);
+ dictDatabase *db = (dictDatabase *) datum;
+ dict_plugin_destroy(db);
#endif
- return 0;
+ return 0;
}
-static int close_database (const void *datum)
+static int close_database(const void *datum)
{
- dictDatabase *db = (dictDatabase *)datum;
+ dictDatabase *db = (dictDatabase *) datum;
- dict_index_close (db->index);
- dict_index_close (db->index_suffix);
- dict_index_close (db->index_word);
+ dict_index_close(db->index);
+ dict_index_close(db->index_suffix);
+ dict_index_close(db->index_word);
- dict_data_close (db->data);
+ dict_data_close(db->data);
- if (db -> databaseShort)
- xfree ((void *) db -> databaseShort);
+ if (db->databaseShort)
+ xfree((void *) db->databaseShort);
- if (db -> indexFilename)
- xfree ((void *) db -> indexFilename);
- if (db -> dataFilename)
- xfree ((void *) db -> dataFilename);
- if (db -> indexwordFilename)
- xfree ((void *) db -> indexwordFilename);
- if (db -> indexsuffixFilename)
- xfree ((void *) db -> indexsuffixFilename);
- if (db -> pluginFilename)
- xfree ((void *) db -> pluginFilename);
- if (db -> strategy_disabled)
- xfree ((void *) db -> strategy_disabled);
- if (db -> alphabet)
- xfree ((void *) db -> alphabet);
- if (db -> mime_header)
- xfree ((void *) db -> mime_header);
+ if (db->indexFilename)
+ xfree((void *) db->indexFilename);
+ if (db->dataFilename)
+ xfree((void *) db->dataFilename);
+ if (db->indexwordFilename)
+ xfree((void *) db->indexwordFilename);
+ if (db->indexsuffixFilename)
+ xfree((void *) db->indexsuffixFilename);
+ if (db->pluginFilename)
+ xfree((void *) db->pluginFilename);
+ if (db->strategy_disabled)
+ xfree((void *) db->strategy_disabled);
+ if (db->alphabet)
+ xfree((void *) db->alphabet);
+ if (db->mime_header)
+ xfree((void *) db->mime_header);
- return 0;
+ return 0;
}
-static int log_database_info( const void *datum )
+static int log_database_info(const void *datum)
{
- dictDatabase *db = (dictDatabase *)datum;
- const char *pt;
- unsigned long headwords = 0;
+ dictDatabase *db = (dictDatabase *) datum;
+ const char *pt;
+ unsigned long headwords = 0;
- if (db->index){
- for (pt = db->index->start; pt < db->index->end; pt++)
- if (*pt == '\n') ++headwords;
- db->index->headwords = headwords;
+ if (db->index) {
+ for (pt = db->index->start; pt < db->index->end; pt++)
+ if (*pt == '\n')
+ ++headwords;
+ db->index->headwords = headwords;
- log_info( ":I: %-12.12s %12lu %12lu %12lu %12lu\n",
- db->databaseName, headwords,
- db->index->size, db->data->size, db->data->length );
- }
+ log_info(":I: %-12.12s %12lu %12lu %12lu %12lu\n",
+ db->databaseName, headwords,
+ db->index->size, db->data->size, db->data->length);
+ }
- return 0;
+ return 0;
}
-static void dict_ltdl_init ()
+static void dict_ltdl_init()
{
#if defined(USE_PLUGIN) && !HAVE_DLFCN_H
- if (lt_dlinit ())
- err_fatal( __func__, "Can not initialize 'ltdl' library\n" );
+ if (lt_dlinit())
+ err_fatal(__func__, "Can not initialize 'ltdl' library\n");
#endif
}
-static void dict_ltdl_close ()
+static void dict_ltdl_close()
{
#if defined(USE_PLUGIN) && !HAVE_DLFCN_H
- if (lt_dlexit ())
- err_fatal( __func__, "Can not deinitialize 'ltdl' library\n" );
+ if (lt_dlexit())
+ err_fatal(__func__, "Can not deinitialize 'ltdl' library\n");
#endif
}
/*
Makes dictionary_exit db invisible if it is the last visible one
*/
-static void make_dictexit_invisible (dictConfig *c)
+static void make_dictexit_invisible(dictConfig * c)
+{
+ lst_Position p;
+ dictDatabase *db;
+ dictDatabase *db_exit = NULL;
+
+ LST_ITERATE(c->dbl, p, db) {
+ if (!db->invisible) {
+ if (db_exit)
+ db_exit->invisible = 0;
+
+ db_exit = NULL;
+ }
+
+ if (db->exit_db) {
+ db_exit = db;
+ db_exit->invisible = 1;
+ }
+ }
+}
+
+static void dict_init_databases(dictConfig * c)
+{
+ make_dictexit_invisible(c);
+
+ lst_iterate(c->dbl, init_database);
+ lst_iterate(c->dbl, init_plugin);
+ lst_iterate(c->dbl, init_virtual_db_list);
+ lst_iterate(c->dbl, init_mime_db_list);
+ lst_iterate(c->dbl, init_database_short);
+ lst_iterate(c->dbl, init_database_mime_header);
+ lst_iterate(c->dbl, log_database_info);
+}
+
+static void dict_close_databases(dictConfig * c)
+{
+ dictDatabase *db;
+ dictAccess *acl;
+
+ if (!c)
+ return;
+
+ if (c->dbl) {
+ while (lst_length(c->dbl) > 0) {
+ db = (dictDatabase *) lst_pop(c->dbl);
+
+ if (db->virtual_db_list)
+ lst_destroy(db->virtual_db_list);
+
+ close_plugin(db);
+ close_database(db);
+ xfree(db);
+ }
+ lst_destroy(c->dbl);
+ }
+
+ if (c->acl) {
+ while (lst_length(c->acl) > 0) {
+ acl = (dictAccess *) lst_pop(c->acl);
+ xfree(acl);
+ }
+ lst_destroy(c->acl);
+ }
+
+ if (site_info)
+ xfree((void *) site_info);
+
+ xfree(c);
+}
+
+static const char *id_string(void)
+{
+ static char buffer[BUFFERSIZE];
+
+ snprintf(buffer, BUFFERSIZE, "%s", DICT_VERSION);
+
+ return buffer;
+}
+
+const char *dict_get_banner(int shortFlag)
+{
+ static char *shortBuffer = NULL;
+ static char *longBuffer = NULL;
+ struct utsname uts;
+
+ if (shortFlag && shortBuffer)
+ return shortBuffer;
+ if (!shortFlag && longBuffer)
+ return longBuffer;
+
+ uname(&uts);
+
+ shortBuffer = xmalloc(256);
+ snprintf(shortBuffer, 256, "%s %s", err_program_name(), id_string());
+
+ longBuffer = xmalloc(256);
+ snprintf(longBuffer, 256,
+ "%s %s/rf on %s %s", err_program_name(), id_string(),
+ uts.sysname, uts.release);
+
+ if (shortFlag)
+ return shortBuffer;
+
+ return longBuffer;
+}
+
+static void banner(void)
{
- lst_Position p;
- dictDatabase *db;
- dictDatabase *db_exit = NULL;
-
- LST_ITERATE(c -> dbl, p, db) {
- if (!db -> invisible){
- if (db_exit)
- db_exit -> invisible = 0;
-
- db_exit = NULL;
- }
-
- if (db -> exit_db){
- db_exit = db;
- db_exit -> invisible = 1;
- }
- }
-}
-
-static void dict_init_databases( dictConfig *c )
-{
- make_dictexit_invisible (c);
-
- lst_iterate( c->dbl, init_database );
- lst_iterate( c->dbl, init_plugin );
- lst_iterate( c->dbl, init_virtual_db_list );
- lst_iterate( c->dbl, init_mime_db_list );
- lst_iterate( c->dbl, init_database_short );
- lst_iterate( c->dbl, init_database_mime_header);
- lst_iterate( c->dbl, log_database_info );
-}
-
-static void dict_close_databases (dictConfig *c)
-{
- dictDatabase *db;
- dictAccess *acl;
-
- if (!c)
- return;
-
- if (c -> dbl){
- while (lst_length (c -> dbl) > 0){
- db = (dictDatabase *) lst_pop (c -> dbl);
-
- if (db -> virtual_db_list)
- lst_destroy (db -> virtual_db_list);
-
- close_plugin (db);
- close_database (db);
- xfree (db);
- }
- lst_destroy (c -> dbl);
- }
-
- if (c -> acl){
- while (lst_length (c -> acl) > 0){
- acl = (dictAccess *) lst_pop (c->acl);
- xfree (acl);
- }
- lst_destroy (c -> acl);
- }
-
- if (site_info)
- xfree ((void *) site_info);
-
- xfree (c);
-}
-
-static const char *id_string (void)
-{
- static char buffer [BUFFERSIZE];
-
- snprintf( buffer, BUFFERSIZE, "%s", DICT_VERSION );
-
- return buffer;
-}
-
-const char *dict_get_banner( int shortFlag )
-{
- static char *shortBuffer = NULL;
- static char *longBuffer = NULL;
- struct utsname uts;
-
- if (shortFlag && shortBuffer) return shortBuffer;
- if (!shortFlag && longBuffer) return longBuffer;
-
- uname( &uts );
-
- shortBuffer = xmalloc(256);
- snprintf(
- shortBuffer, 256,
- "%s %s", err_program_name(), id_string () );
-
- longBuffer = xmalloc(256);
- snprintf(
- longBuffer, 256,
- "%s %s/rf on %s %s", err_program_name(), id_string (),
- uts.sysname,
- uts.release );
-
- if (shortFlag)
- return shortBuffer;
-
- return longBuffer;
-}
-
-static void banner( void )
-{
- printf( "%s\n", dict_get_banner(0) );
- printf( "Copyright 1997-2002 Rickard E. Faith (faith@dict.org)\n" );
- printf( "Copyright 2002-2007 Aleksey Cheusov (vle@gmx.net)\n" );
- printf( "\n" );
-}
-
-static void license( void )
-{
- static const char *license_msg[] = {
- "This program is free software; you can redistribute it and/or modify it",
- "under the terms of the GNU General Public License as published by the",
- "Free Software Foundation; either version 1, or (at your option) any",
- "later version.",
- "",
- "This program is distributed in the hope that it will be useful, but",
- "WITHOUT ANY WARRANTY; without even the implied warranty of",
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
- "General Public License for more details.",
- "",
- "You should have received a copy of the GNU General Public License along",
- "with this program; if not, write to the Free Software Foundation, Inc.,",
- "675 Mass Ave, Cambridge, MA 02139, USA.",
- 0 };
- const char **p = license_msg;
-
- banner();
- while (*p) printf( " %s\n", *p++ );
-}
-
-static void help( void )
-{
- static const char *help_msg[] = {
- "Usage: dictd [options]",
- "Start the dictd daemon",
- "",
- "-h --help give this help",
- " --license display software license",
- "-v --verbose verbose mode",
- "-V --version display version number",
- "-p --port <port> port number",
- " --delay <seconds> client timeout in seconds",
- " --depth <length> TCP/IP queue depth",
- " --limit <children> maximum simultaneous children",
- "-c --config <file> configuration file",
- "-l --log <option> select logging option",
- "-s --syslog log via syslog(3)",
- "-L --logfile <file> log via specified file",
- "-m --mark <minutes> how often should a timestamp be logged",
- " --facility <fac> set syslog logging facility",
- "-d --debug <option> select debug option",
- "-i --inetd run from inetd",
- " --pid-file <path> PID filename",
- " --pp <prog> set preprocessor for configuration file",
- "-f --force force startup even if daemon running",
- " --locale <locale> specifies the locale used for searching.\n\
+ printf("%s\n", dict_get_banner(0));
+ printf("Copyright 1997-2002 Rickard E. Faith (faith@dict.org)\n");
+ printf("Copyright 2002-2007 Aleksey Cheusov (vle@gmx.net)\n");
+ printf("\n");
+}
+
+static void license(void)
+{
+ static const char *license_msg[] = {
+ "This program is free software; you can redistribute it and/or modify it",
+ "under the terms of the GNU General Public License as published by the",
+ "Free Software Foundation; either version 1, or (at your option) any",
+ "later version.",
+ "",
+ "This program is distributed in the hope that it will be useful, but",
+ "WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
+ "General Public License for more details.",
+ "",
+ "You should have received a copy of the GNU General Public License along",
+ "with this program; if not, write to the Free Software Foundation, Inc.,",
+ "675 Mass Ave, Cambridge, MA 02139, USA.",
+ 0
+ };
+ const char **p = license_msg;
+
+ banner();
+ while (*p)
+ printf(" %s\n", *p++);
+}
+
+static void help(void)
+{
+ static const char *help_msg[] = {
+ "Usage: dictd [options]",
+ "Start the dictd daemon",
+ "",
+ "-h --help give this help",
+ " --license display software license",
+ "-v --verbose verbose mode",
+ "-V --version display version number",
+ "-p --port <port> port number",
+ " --delay <seconds> client timeout in seconds",
+ " --depth <length> TCP/IP queue depth",
+ " --limit <children> maximum simultaneous children",
+ "-c --config <file> configuration file",
+ "-l --log <option> select logging option",
+ "-s --syslog log via syslog(3)",
+ "-L --logfile <file> log via specified file",
+ "-m --mark <minutes> how often should a timestamp be logged",
+ " --facility <fac> set syslog logging facility",
+ "-d --debug <option> select debug option",
+ "-i --inetd run from inetd",
+ " --pid-file <path> PID filename",
+ " --pp <prog> set preprocessor for configuration file",
+ "-f --force force startup even if daemon running",
+ " --locale <locale> specifies the locale used for searching.\n\
if no locale is specified, the \"C\" locale is used.",
-" --default-strategy set the default search strategy for 'match' queries.\n\
+ " --default-strategy set the default search strategy for 'match' queries.\n\
the default is 'lev'.",
-" --without-strategy <strategies> disable strategies.\n\
+ " --without-strategy <strategies> disable strategies.\n\
<strategies> is a comma-separated list.",
-" --add-strategy <strat>:<descr> adds new strategy <strat>\n\
+ " --add-strategy <strat>:<descr> adds new strategy <strat>\n\
with a description <descr>.",
-" --listen-to bind a socket to the specified address",
-"\n------------------ options for debugging ---------------------------",
-" --fast-start don't create additional (internal) index.",
+ " --listen-to bind a socket to the specified address",
+ "\n------------------ options for debugging ---------------------------",
+ " --fast-start don't create additional (internal) index.",
#ifdef HAVE_MMAP
-" --without-mmap do not use mmap() function and load files\n\
+ " --without-mmap do not use mmap() function and load files\n\
into memory instead.",
#endif
-" --stdin2stdout copy stdin to stdout (addition to -i option).",
- 0 };
- const char **p = help_msg;
+ " --stdin2stdout copy stdin to stdout (addition to -i option).",
+ 0
+ };
+ const char **p = help_msg;
- banner();
- while (*p)
- printf( "%s\n", *p++ );
+ banner();
+ while (*p)
+ printf("%s\n", *p++);
}
-void set_minimal( void )
+void set_minimal(void)
{
- flg_set(flg_name(LOG_FOUND));
- flg_set(flg_name(LOG_NOTFOUND));
- flg_set(flg_name(LOG_STATS));
- flg_set(flg_name(LOG_CLIENT));
- flg_set(flg_name(LOG_AUTH));
- flg_set("-min");
+ flg_set(flg_name(LOG_FOUND));
+ flg_set(flg_name(LOG_NOTFOUND));
+ flg_set(flg_name(LOG_STATS));
+ flg_set(flg_name(LOG_CLIENT));
+ flg_set(flg_name(LOG_AUTH));
+ flg_set("-min");
}
-static void release_root_privileges( void )
+static void release_root_privileges(void)
/* At the spring 1999 Linux Expo in Raleigh, Rik Faith told me that he
* did not want dictd to be allowed to run as root for any reason.
* This patch irrevocably releases root privileges. -- Kirk Hilliard
@@ -1266,24 +1291,24 @@ static void release_root_privileges( voi
* -- Bob Hilliard
*/
{
- int unused __attribute__((unused));
- if (geteuid() == 0) {
- struct passwd *pwd;
-
- if ((pwd = getpwnam("dictd"))) {
- unused = setgid(pwd->pw_gid);
- initgroups("dictd",pwd->pw_gid);
- unused = setuid(pwd->pw_uid);
- } else if ((pwd = getpwnam("nobody"))) {
- unused = setgid(pwd->pw_gid);
- initgroups("nobody",pwd->pw_gid);
- unused = setuid(pwd->pw_uid);
- } else {
- unused = setgid(GID_NOGROUP);
- initgroups("nobody", GID_NOGROUP);
- unused = setuid(UID_NOBODY);
- }
- }
+ int unused __attribute__ ((unused));
+ if (geteuid() == 0) {
+ struct passwd *pwd;
+
+ if ((pwd = getpwnam("dictd"))) {
+ unused = setgid(pwd->pw_gid);
+ initgroups("dictd", pwd->pw_gid);
+ unused = setuid(pwd->pw_uid);
+ } else if ((pwd = getpwnam("nobody"))) {
+ unused = setgid(pwd->pw_gid);
+ initgroups("nobody", pwd->pw_gid);
+ unused = setuid(pwd->pw_uid);
+ } else {
+ unused = setgid(GID_NOGROUP);
+ initgroups("nobody", GID_NOGROUP);
+ unused = setuid(UID_NOBODY);
+ }
+ }
}
/* Perform sanity checks that are often problems for people trying to
@@ -1291,538 +1316,580 @@ static void release_root_privileges( voi
* console. */
static void sanity(const char *confFile)
{
- int fail = 0;
- int reading_error = 0;
- struct passwd *pw = NULL;
- struct group *gr = NULL;
-
- if (access(confFile,R_OK)) {
- log_info(":E: %s is not readable (config file)\n", confFile);
- ++fail;
- }
- if (DictConfig && !DictConfig->dbl) {
- log_info(":E: no databases have been defined\n");
- log_info(":E: check %s or use -c\n", confFile);
- ++fail;
- }
- if (DictConfig && DictConfig->dbl) {
- lst_Position p;
- dictDatabase *e;
- LST_ITERATE(DictConfig->dbl, p, e) {
- if (e->indexFilename && access(e->indexFilename, R_OK)) {
- log_info(":E: %s is not readable (index file)\n",
- e->indexFilename);
- ++fail;
- reading_error = 1;
- }
- if (e->indexsuffixFilename && access(e->indexsuffixFilename, R_OK)) {
- log_info(":E: %s is not readable (index_suffix file)\n",
- e->indexsuffixFilename);
- ++fail;
- reading_error = 1;
- }
- if (e->indexwordFilename && access(e->indexwordFilename, R_OK)) {
- log_info(":E: %s is not readable (index_word file)\n",
- e->indexwordFilename);
- ++fail;
- reading_error = 1;
- }
-
- if (e->dataFilename && access(e->dataFilename, R_OK)) {
- log_info(":E: %s is not readable (data file)\n",
- e->dataFilename);
- ++fail;
- reading_error = 1;
- }
- if (e->virtual_db && !e->database_list){
- log_info(
- ":E: database list is not specified for virtual dictionary '%s'\n",
- e->databaseName);
- ++fail;
- }
- if (e->normal_db && !e->dataFilename){
- log_info(
- ":E: data filename is not specified for dictionary '%s'\n",
- e->databaseName);
- ++fail;
- }
- if (e->normal_db && !e->indexFilename){
- log_info(
- ":E: index filename is not specified for dictionary '%s'\n",
- e->databaseName);
- ++fail;
- }
- if (e->plugin_db && !e->pluginFilename){
- log_info(
- ":E: plugin filename is not specified for dictionary '%s'\n",
- e->databaseName);
- ++fail;
- }
+ int fail = 0;
+ int reading_error = 0;
+ struct passwd *pw = NULL;
+ struct group *gr = NULL;
+
+ if (access(confFile, R_OK)) {
+ log_info(":E: %s is not readable (config file)\n", confFile);
+ ++fail;
+ }
+ if (DictConfig && !DictConfig->dbl) {
+ log_info(":E: no databases have been defined\n");
+ log_info(":E: check %s or use -c\n", confFile);
+ ++fail;
+ }
+ if (DictConfig && DictConfig->dbl) {
+ lst_Position p;
+ dictDatabase *e;
+ LST_ITERATE(DictConfig->dbl, p, e) {
+ if (e->indexFilename && access(e->indexFilename, R_OK)) {
+ log_info(":E: %s is not readable (index file)\n",
+ e->indexFilename);
+ ++fail;
+ reading_error = 1;
+ }
+ if (e->indexsuffixFilename
+ && access(e->indexsuffixFilename, R_OK)) {
+ log_info(":E: %s is not readable (index_suffix file)\n",
+ e->indexsuffixFilename);
+ ++fail;
+ reading_error = 1;
+ }
+ if (e->indexwordFilename && access(e->indexwordFilename, R_OK)) {
+ log_info(":E: %s is not readable (index_word file)\n",
+ e->indexwordFilename);
+ ++fail;
+ reading_error = 1;
+ }
+
+ if (e->dataFilename && access(e->dataFilename, R_OK)) {
+ log_info(":E: %s is not readable (data file)\n",
+ e->dataFilename);
+ ++fail;
+ reading_error = 1;
+ }
+ if (e->virtual_db && !e->database_list) {
+ log_info
+ (":E: database list is not specified for virtual dictionary '%s'\n",
+ e->databaseName);
+ ++fail;
+ }
+ if (e->normal_db && !e->dataFilename) {
+ log_info
+ (":E: data filename is not specified for dictionary '%s'\n",
+ e->databaseName);
+ ++fail;
+ }
+ if (e->normal_db && !e->indexFilename) {
+ log_info
+ (":E: index filename is not specified for dictionary '%s'\n",
+ e->databaseName);
+ ++fail;
+ }
+ if (e->plugin_db && !e->pluginFilename) {
+ log_info
+ (":E: plugin filename is not specified for dictionary '%s'\n",
+ e->databaseName);
+ ++fail;
+ }
#ifndef USE_PLUGIN
- if (e -> plugin_db){
- log_info (
- ":E: plugin support was disabled at compile time\n");
- ++fail;
- }
+ if (e->plugin_db) {
+ log_info
+ (":E: plugin support was disabled at compile time\n");
+ ++fail;
+ }
#endif
- }
- }
- if (fail) {
- if (reading_error){
- pw = getpwuid (geteuid ());
- gr = getgrgid (getegid ());
-
- log_info(":E: for security, this program will not run as root.\n");
- log_info(":E: if started as root, this program will change"
- " to \"dictd\" or \"nobody\".\n");
- log_info(":E: currently running as user %d/%s, group %d/%s\n",
- geteuid(), pw && pw->pw_name ? pw->pw_name : "?",
- getegid(), gr && gr->gr_name ? gr->gr_name : "?");
- log_info(":E: config and db files must be readable by that user\n");
- }
- err_fatal(__func__, ":E: terminating due to errors. See log file\n");
- }
-}
-
-static void set_locale_and_flags (const char *loc)
-{
- const char *charset = NULL;
- int ascii_mode;
-
- if (!setlocale(LC_COLLATE, loc) || !setlocale(LC_CTYPE, loc)){
- fprintf (stderr, "invalid locale '%s'\n", locale);
- exit (2);
- }
+ }
+ }
+ if (fail) {
+ if (reading_error) {
+ pw = getpwuid(geteuid());
+ gr = getgrgid(getegid());
+
+ log_info
+ (":E: for security, this program will not run as root.\n");
+ log_info(":E: if started as root, this program will change"
+ " to \"dictd\" or \"nobody\".\n");
+ log_info(":E: currently running as user %d/%s, group %d/%s\n",
+ geteuid(), pw
+ && pw->pw_name ? pw->pw_name : "?", getegid(), gr
+ && gr->gr_name ? gr->gr_name : "?");
+ log_info
+ (":E: config and db files must be readable by that user\n");
+ }
+ err_fatal(__func__,
+ ":E: terminating due to errors. See log file\n");
+ }
+}
+
+static void set_locale_and_flags(const char *loc)
+{
+ const char *charset = NULL;
+ int ascii_mode;
+
+ if (!setlocale(LC_COLLATE, loc) || !setlocale(LC_CTYPE, loc)) {
+ fprintf(stderr, "invalid locale '%s'\n", locale);
+ exit(2);
+ }
- charset = nl_langinfo (CODESET);
+ charset = nl_langinfo(CODESET);
- utf8_mode = !strcmp (charset, "UTF-8") || !strcmp (charset, "utf-8");
+ utf8_mode = !strcmp(charset, "UTF-8") || !strcmp(charset, "utf-8");
#if !HAVE_UTF8
- if (utf8_mode){
- err_fatal (
- __func__,
- "utf-8 support was disabled at compile time\n");
- }
+ if (utf8_mode) {
+ err_fatal(__func__,
+ "utf-8 support was disabled at compile time\n");
+ }
#endif
- ascii_mode =
- !strcmp (charset, "ANSI_X3.4-1968") ||
- !strcmp (charset, "US-ASCII") ||
- (locale [0] == 'C' && locale [1] == 0);
+ ascii_mode =
+ !strcmp(charset, "ANSI_X3.4-1968") ||
+ !strcmp(charset, "US-ASCII") ||
+ (locale[0] == 'C' && locale[1] == 0);
- bit8_mode = !ascii_mode && !utf8_mode;
+ bit8_mode = !ascii_mode && !utf8_mode;
}
-static void set_umask (void)
+static void set_umask(void)
{
#if defined(__OPENNT) || defined(__INTERIX)
- umask(002); /* set safe umask */
+ umask(002); /* set safe umask */
#else
- umask(022); /* set safe umask */
+ umask(022); /* set safe umask */
#endif
}
-static void init (const char *fn)
+static void init(const char *fn)
{
- maa_init (fn);
- dict_ltdl_init ();
- dict_init_strategies ();
+ maa_init(fn);
+ dict_ltdl_init();
+ dict_init_strategies();
}
-static void destroy ()
+static void destroy()
{
- maa_shutdown ();
+ maa_shutdown();
- dict_ltdl_close ();
- dict_destroy_strategies ();
+ dict_ltdl_close();
+ dict_destroy_strategies();
}
FILE *pid_fd = NULL;
-static void pid_file_create ()
+static void pid_file_create()
{
- pid_fd = fopen (pidFile, "w");
+ pid_fd = fopen(pidFile, "w");
- if (!pid_fd){
- log_info(":E: cannot open pid file '%s'\n:E: err msg: %s\n",
- pidFile, strerror (errno));
- err_fatal(__func__,
- ":E: terminating due to errors. See log file\n");
- }
-}
-
-static void pid_file_write ()
-{
- if (-1 == fprintf (pid_fd, "%lu\n", (unsigned long) getpid ()) ||
- fclose (pid_fd))
- {
- log_info(":E: cannot write to pid file '%s'\n:E: err msg: %s\n",
- pidFile, strerror (errno));
- err_fatal(__func__,
- ":E: terminating due to errors. See log file\n");
- }
-}
-
-static void reopen_012 (void)
-{
- int fd = open ("/dev/null", O_RDWR);
- int unused __attribute__((unused));
- if (fd == -1)
- err_fatal_errno (__func__, ":E: can't open /dev/null");
-
- close (0);
- close (1);
- close (2);
-
- unused = dup (fd);
- unused = dup (fd);
- unused = dup (fd);
-}
-
-int main (int argc, char **argv, char **envp)
-{
- int childSocket;
- int masterSocket;
- struct sockaddr_in csin;
- int c;
- time_t startTime;
- socklen_t alen = sizeof (csin);
- int detach = 1;
- int forceStartup = 0;
- int i;
-
- int errno_accept = 0;
- int unused __attribute__((unused));
-
- const char * default_strategy_arg = "???";
-
- char * new_strategy;
- char * new_strategy_descr;
-
- struct option longopts[] = {
- { "verbose", 0, 0, 'v' },
- { "version", 0, 0, 'V' },
- { "debug", 1, 0, 'd' },
- { "port", 1, 0, 'p' },
- { "config", 1, 0, 'c' },
- { "help", 0, 0, 'h' },
- { "license", 0, 0, 500 },
- { "log", 1, 0, 'l' },
- { "logfile", 1, 0, 'L' },
- { "syslog", 0, 0, 's' },
- { "mark", 1, 0, 'm' },
- { "delay", 1, 0, 502 },
- { "depth", 1, 0, 503 },
- { "limit", 1, 0, 504 },
- { "facility", 1, 0, 505 },
- { "force", 1, 0, 'f' },
- { "inetd", 0, 0, 'i' },
- { "locale", 1, 0, 506 },
+ if (!pid_fd) {
+ log_info(":E: cannot open pid file '%s'\n:E: err msg: %s\n",
+ pidFile, strerror(errno));
+ err_fatal(__func__,
+ ":E: terminating due to errors. See log file\n");
+ }
+}
+
+static void pid_file_write()
+{
+ if (-1 == fprintf(pid_fd, "%lu\n", (unsigned long) getpid()) ||
+ fclose(pid_fd)) {
+ log_info(":E: cannot write to pid file '%s'\n:E: err msg: %s\n",
+ pidFile, strerror(errno));
+ err_fatal(__func__,
+ ":E: terminating due to errors. See log file\n");
+ }
+}
+
+static void reopen_012(void)
+{
+ int fd = open("/dev/null", O_RDWR);
+ int unused __attribute__ ((unused));
+ if (fd == -1)
+ err_fatal_errno(__func__, ":E: can't open /dev/null");
+
+ close(0);
+ close(1);
+ close(2);
+
+ unused = dup(fd);
+ unused = dup(fd);
+ unused = dup(fd);
+}
+
+int main(int argc, char **argv, char **envp)
+{
+ int childSocket;
+ int masterSocket;
+ struct sockaddr_storage csin;
+ int c;
+ time_t startTime;
+ socklen_t alen = sizeof(csin);
+ int detach = 1;
+ int forceStartup = 0;
+ int i;
+
+ int errno_accept = 0;
+ int unused __attribute__ ((unused));
+
+ const char *default_strategy_arg = "???";
+
+ char *new_strategy;
+ char *new_strategy_descr;
+
+ struct option longopts[] = {
+ {"verbose", 0, 0, 'v'},
+ {"version", 0, 0, 'V'},
+ {"debug", 1, 0, 'd'},
+ {"port", 1, 0, 'p'},
+ {"config", 1, 0, 'c'},
+ {"help", 0, 0, 'h'},
+ {"license", 0, 0, 500},
+ {"log", 1, 0, 'l'},
+ {"logfile", 1, 0, 'L'},
+ {"syslog", 0, 0, 's'},
+ {"mark", 1, 0, 'm'},
+ {"delay", 1, 0, 502},
+ {"depth", 1, 0, 503},
+ {"limit", 1, 0, 504},
+ {"facility", 1, 0, 505},
+ {"force", 1, 0, 'f'},
+ {"inetd", 0, 0, 'i'},
+ {"locale", 1, 0, 506},
#ifdef HAVE_MMAP
- { "no-mmap", 0, 0, 508 },
- { "without-mmap", 0, 0, 508 },
+ {"no-mmap", 0, 0, 508},
+ {"without-mmap", 0, 0, 508},
#endif
- { "default-strategy", 1, 0, 511 },
- { "without-strategy", 1, 0, 513 },
- { "add-strategy", 1, 0, 516 },
- { "fast-start", 0, 0, 517 },
- { "pp", 1, 0, 518 },
- { "listen-to", 1, 0, 519 },
- { "pid-file", 1, 0, 521 },
- { "stdin2stdout", 0, 0, 522 },
- { 0, 0, 0, 0 }
- };
-
- set_umask ();
- init (argv[0]);
-
- flg_register( LOG_SERVER, "server" );
- flg_register( LOG_CONNECT, "connect" );
- flg_register( LOG_STATS, "stats" );
- flg_register( LOG_COMMAND, "command" );
- flg_register( LOG_FOUND, "found" );
- flg_register( LOG_NOTFOUND, "notfound" );
- flg_register( LOG_CLIENT, "client" );
- flg_register( LOG_HOST, "host" );
- flg_register( LOG_TIMESTAMP, "timestamp" );
- flg_register( LOG_MIN, "min" );
- flg_register( LOG_AUTH, "auth" );
-
- dbg_register( DBG_VERBOSE, "verbose" );
- dbg_register( DBG_UNZIP, "unzip" );
- dbg_register( DBG_SCAN, "scan" );
- dbg_register( DBG_PARSE, "parse" );
- dbg_register( DBG_SEARCH, "search" );
- dbg_register( DBG_INIT, "init" );
- dbg_register( DBG_PORT, "port" );
- dbg_register( DBG_LEV, "lev" );
- dbg_register( DBG_AUTH, "auth" );
- dbg_register( DBG_NODETACH, "nodetach" );
- dbg_register( DBG_NOFORK, "nofork" );
- dbg_register( DBG_ALT, "alt" );
-
- log_stream ("dictd", stderr);
-
- while ((c = getopt_long( argc, argv,
- "vVd:p:c:hL:t:l:sm:fi", longopts, NULL )) != EOF)
- switch (c) {
- /* Remember to copy optarg since we're
- going to destroy argv soon... */
- case 'v': dbg_set( "verbose" ); break;
- case 'V': banner(); exit(1); break;
- case 'd': dbg_set( optarg ); break;
- case 'p':
- daemon_service = str_copy(optarg);
- daemon_service_set = 1;
- break;
- case 'c': configFile = str_copy(optarg); break;
- case 'L':
- logFile = str_copy(optarg);
- logFile_set = 1;
- break;
- case 's': ++useSyslog; break;
- case 'm':
- _dict_markTime = 60*atoi(optarg);
- _dict_markTime_set = 1;
- break;
- case 'f': ++forceStartup; break;
- case 'i':
- inetd = 1;
- optStart_mode = 0;
- break;
- case 'l':
- ++logOptions;
- flg_set( optarg );
- if (flg_test(LOG_MIN)) set_minimal();
- break;
- case 500: license(); exit(1); break;
- case 502:
- client_delay = atoi(optarg);
- client_delay_set = 1;
- _dict_daemon_limit_time = 0;
- break;
- case 503:
- depth = atoi(optarg);
- depth_set = 1;
- break;
- case 504:
- _dict_daemon_limit_childs = atoi(optarg);
- _dict_daemon_limit_childs_set = 1;
- break;
- case 505:
- ++useSyslog;
- log_set_facility (optarg);
- syslog_facility_set = 1;
- break;
- case 506:
- locale = str_copy (optarg);
- locale_set = 1;
- break;
- case 508: mmap_mode = 0; break;
- case 511:
- default_strategy_arg = str_copy (optarg);
- default_strategy = lookup_strategy_ex (default_strategy_arg);
- default_strategy_set = 1;
- break;
- case 513:
- dict_disable_strategies (optarg);
- break;
- case 516:
- new_strategy = optarg;
- new_strategy_descr = strchr (new_strategy, ':');
- if (!new_strategy_descr){
- fprintf (stderr, "missing ':' symbol in --add-strategy option\n");
- exit (1);
- }
-
- *new_strategy_descr++ = 0;
-
- dict_add_strategy (new_strategy, new_strategy_descr);
-
- break;
- case 517: optStart_mode = 0; break;
- case 518: preprocessor = str_copy (optarg); break;
- case 519:
- bind_to = str_copy (optarg);
- bind_to_set = 1;
- break;
- case 521:
- pidFile = str_copy(optarg);
- pidFile_set = 1;
- break;
- case 522:
- stdin2stdout_mode = 1;
- break;
- case 'h':
- default: help(); exit(0); break;
- }
-
- if (inetd)
- detach = 0;
-
- if (-1 == default_strategy){
- fprintf (stderr, "%s is not a valid search strategy\n",
- default_strategy_arg);
-
- fprintf (stderr, "available ones are:\n");
-
- for (i = 0; i < get_strategy_count (); ++i){
- fprintf (
- stderr, " %15s : %s\n",
- get_strategies () [i] -> name, get_strategies () [i] -> description);
- }
- exit (1);
- }
-
- if (dbg_test(DBG_NOFORK)) dbg_set_flag( DBG_NODETACH);
- if (dbg_test(DBG_NODETACH)) detach = 0;
- if (dbg_test(DBG_PARSE)) prs_set_debug(1);
- if (dbg_test(DBG_SCAN)) yy_flex_debug = 1;
- else yy_flex_debug = 0;
- if (flg_test(LOG_TIMESTAMP)) log_option( LOG_OPTION_FULL );
- else log_option( LOG_OPTION_NO_FULL );
-
- if (!access(configFile,R_OK)) {
- prs_file_pp (preprocessor, configFile );
- postprocess_filenames (DictConfig);
- }
-
- if (detach) pid_file_create (); /* before leaving root priviledges */
-
- release_root_privileges();
-
- if (logFile) log_file ("dictd", logFile);
- log_stream ("dictd", NULL);
- if (useSyslog) log_syslog ("dictd");
- if (! inetd && ! detach) log_stream ("dictd", stderr);
- if ((logFile || useSyslog || !detach) && !logOptions)
- set_minimal();
-
- if (detach){
- /* become a daemon */
- unused = daemon (0, 1);
- reopen_012 ();
-
- /* after fork from daemon(3) */
- pid_file_write ();
- }
-
- time(&startTime);
- log_info(":I: %d starting %s %24.24s\n",
- getpid(), dict_get_banner(0), ctime(&startTime));
-
- tim_start( "dictd" );
- alarm(_dict_markTime);
-
- if (locale)
- set_locale_and_flags (locale);
-
- sanity(configFile);
-
- setsig(SIGCHLD, reaper, SA_RESTART);
- setsig(SIGHUP, handler_sighup, 0);
- setsig(SIGUSR1, handler_sigusr1, 0);
- if (!dbg_test(DBG_NOFORK))
- setsig(SIGINT, handler, 0);
- setsig(SIGQUIT, handler, 0);
- setsig(SIGILL, handler, 0);
- setsig(SIGTRAP, handler, 0);
- setsig(SIGTERM, handler, 0);
- setsig(SIGPIPE, handler, 0);
- setsig(SIGALRM, handler, SA_RESTART);
-
- fflush(stdout);
- fflush(stderr);
-
- if (locale)
- log_info(":I: using locale \"%s\"\n", locale);
-
- if (dbg_test(DBG_VERBOSE))
- dict_config_print( NULL, DictConfig );
-
- dict_init_databases( DictConfig );
-
- dict_initsetproctitle(argc, argv, envp);
-
- if (inetd) {
- dict_inetd(0);
- exit(0);
- }
-
- masterSocket = net_open_tcp( bind_to, daemon_service, depth );
-
-
- for (;;) {
- dict_setproctitle( "%s: %d/%d",
- dict_get_banner(1),
- _dict_forks - _dict_reaps,
- _dict_forks );
+ {"default-strategy", 1, 0, 511},
+ {"without-strategy", 1, 0, 513},
+ {"add-strategy", 1, 0, 516},
+ {"fast-start", 0, 0, 517},
+ {"pp", 1, 0, 518},
+ {"listen-to", 1, 0, 519},
+ {"pid-file", 1, 0, 521},
+ {"stdin2stdout", 0, 0, 522},
+ {0, 0, 0, 0}
+ };
+
+ set_umask();
+ init(argv[0]);
+
+ flg_register(LOG_SERVER, "server");
+ flg_register(LOG_CONNECT, "connect");
+ flg_register(LOG_STATS, "stats");
+ flg_register(LOG_COMMAND, "command");
+ flg_register(LOG_FOUND, "found");
+ flg_register(LOG_NOTFOUND, "notfound");
+ flg_register(LOG_CLIENT, "client");
+ flg_register(LOG_HOST, "host");
+ flg_register(LOG_TIMESTAMP, "timestamp");
+ flg_register(LOG_MIN, "min");
+ flg_register(LOG_AUTH, "auth");
+
+ dbg_register(DBG_VERBOSE, "verbose");
+ dbg_register(DBG_UNZIP, "unzip");
+ dbg_register(DBG_SCAN, "scan");
+ dbg_register(DBG_PARSE, "parse");
+ dbg_register(DBG_SEARCH, "search");
+ dbg_register(DBG_INIT, "init");
+ dbg_register(DBG_PORT, "port");
+ dbg_register(DBG_LEV, "lev");
+ dbg_register(DBG_AUTH, "auth");
+ dbg_register(DBG_NODETACH, "nodetach");
+ dbg_register(DBG_NOFORK, "nofork");
+ dbg_register(DBG_ALT, "alt");
+
+ log_stream("dictd", stderr);
+
+ while ((c = getopt_long(argc, argv,
+ "vVd:p:c:hL:t:l:sm:fi", longopts,
+ NULL)) != EOF)
+ switch (c) {
+ /* Remember to copy optarg since we're
+ going to destroy argv soon... */
+ case 'v':
+ dbg_set("verbose");
+ break;
+ case 'V':
+ banner();
+ exit(1);
+ break;
+ case 'd':
+ dbg_set(optarg);
+ break;
+ case 'p':
+ daemon_service = str_copy(optarg);
+ daemon_service_set = 1;
+ break;
+ case 'c':
+ configFile = str_copy(optarg);
+ break;
+ case 'L':
+ logFile = str_copy(optarg);
+ logFile_set = 1;
+ break;
+ case 's':
+ ++useSyslog;
+ break;
+ case 'm':
+ _dict_markTime = 60 * atoi(optarg);
+ _dict_markTime_set = 1;
+ break;
+ case 'f':
+ ++forceStartup;
+ break;
+ case 'i':
+ inetd = 1;
+ optStart_mode = 0;
+ break;
+ case 'l':
+ ++logOptions;
+ flg_set(optarg);
+ if (flg_test(LOG_MIN))
+ set_minimal();
+ break;
+ case 500:
+ license();
+ exit(1);
+ break;
+ case 502:
+ client_delay = atoi(optarg);
+ client_delay_set = 1;
+ _dict_daemon_limit_time = 0;
+ break;
+ case 503:
+ depth = atoi(optarg);
+ depth_set = 1;
+ break;
+ case 504:
+ _dict_daemon_limit_childs = atoi(optarg);
+ _dict_daemon_limit_childs_set = 1;
+ break;
+ case 505:
+ ++useSyslog;
+ log_set_facility(optarg);
+ syslog_facility_set = 1;
+ break;
+ case 506:
+ locale = str_copy(optarg);
+ locale_set = 1;
+ break;
+ case 508:
+ mmap_mode = 0;
+ break;
+ case 511:
+ default_strategy_arg = str_copy(optarg);
+ default_strategy = lookup_strategy_ex(default_strategy_arg);
+ default_strategy_set = 1;
+ break;
+ case 513:
+ dict_disable_strategies(optarg);
+ break;
+ case 516:
+ new_strategy = optarg;
+ new_strategy_descr = strchr(new_strategy, ':');
+ if (!new_strategy_descr) {
+ fprintf(stderr,
+ "missing ':' symbol in --add-strategy option\n");
+ exit(1);
+ }
+
+ *new_strategy_descr++ = 0;
- if (flg_test(LOG_SERVER))
- log_info( ":I: %d accepting on %s\n", getpid(), daemon_service );
+ dict_add_strategy(new_strategy, new_strategy_descr);
+
+ break;
+ case 517:
+ optStart_mode = 0;
+ break;
+ case 518:
+ preprocessor = str_copy(optarg);
+ break;
+ case 519:
+ bind_to = str_copy(optarg);
+ bind_to_set = 1;
+ break;
+ case 521:
+ pidFile = str_copy(optarg);
+ pidFile_set = 1;
+ break;
+ case 522:
+ stdin2stdout_mode = 1;
+ break;
+ case 'h':
+ default:
+ help();
+ exit(0);
+ break;
+ }
+
+ if (inetd)
+ detach = 0;
+
+ if (-1 == default_strategy) {
+ fprintf(stderr, "%s is not a valid search strategy\n",
+ default_strategy_arg);
+
+ fprintf(stderr, "available ones are:\n");
+
+ for (i = 0; i < get_strategy_count(); ++i) {
+ fprintf(stderr, " %15s : %s\n",
+ get_strategies()[i]->name,
+ get_strategies()[i]->description);
+ }
+ exit(1);
+ }
+
+ if (dbg_test(DBG_NOFORK))
+ dbg_set_flag(DBG_NODETACH);
+ if (dbg_test(DBG_NODETACH))
+ detach = 0;
+ if (dbg_test(DBG_PARSE))
+ prs_set_debug(1);
+ if (dbg_test(DBG_SCAN))
+ yy_flex_debug = 1;
+ else
+ yy_flex_debug = 0;
+ if (flg_test(LOG_TIMESTAMP))
+ log_option(LOG_OPTION_FULL);
+ else
+ log_option(LOG_OPTION_NO_FULL);
+
+ if (!access(configFile, R_OK)) {
+ prs_file_pp(preprocessor, configFile);
+ postprocess_filenames(DictConfig);
+ }
+
+ if (detach)
+ pid_file_create(); /* before leaving root priviledges */
+
+ release_root_privileges();
+
+ if (logFile)
+ log_file("dictd", logFile);
+ log_stream("dictd", NULL);
+ if (useSyslog)
+ log_syslog("dictd");
+ if (!inetd && !detach)
+ log_stream("dictd", stderr);
+ if ((logFile || useSyslog || !detach) && !logOptions)
+ set_minimal();
+
+ if (detach) {
+ /* become a daemon */
+ unused = daemon(0, 1);
+ reopen_012();
+
+ /* after fork from daemon(3) */
+ pid_file_write();
+ }
+
+ time(&startTime);
+ log_info(":I: %d starting %s %24.24s\n",
+ getpid(), dict_get_banner(0), ctime(&startTime));
+
+ tim_start("dictd");
+ alarm(_dict_markTime);
+
+ if (locale)
+ set_locale_and_flags(locale);
+
+ sanity(configFile);
+
+ setsig(SIGCHLD, reaper, SA_RESTART);
+ setsig(SIGHUP, handler_sighup, 0);
+ setsig(SIGUSR1, handler_sigusr1, 0);
+ if (!dbg_test(DBG_NOFORK))
+ setsig(SIGINT, handler, 0);
+ setsig(SIGQUIT, handler, 0);
+ setsig(SIGILL, handler, 0);
+ setsig(SIGTRAP, handler, 0);
+ setsig(SIGTERM, handler, 0);
+ setsig(SIGPIPE, handler, 0);
+ setsig(SIGALRM, handler, SA_RESTART);
+
+ fflush(stdout);
+ fflush(stderr);
+
+ if (locale)
+ log_info(":I: using locale \"%s\"\n", locale);
+
+ if (dbg_test(DBG_VERBOSE))
+ dict_config_print(NULL, DictConfig);
+
+ dict_init_databases(DictConfig);
+
+ dict_initsetproctitle(argc, argv, envp);
+
+ if (inetd) {
+ dict_inetd(0);
+ exit(0);
+ }
+
+ masterSocket = net_open_tcp(bind_to, daemon_service, depth);
+
+
+ for (;;) {
+ dict_setproctitle("%s: %d/%d",
+ dict_get_banner(1),
+ _dict_forks - _dict_reaps, _dict_forks);
+
+ if (flg_test(LOG_SERVER))
+ log_info(":I: %d accepting on %s\n", getpid(), daemon_service);
/*unblock_signals ();*/
- childSocket = accept (masterSocket,
- (struct sockaddr *)&csin, &alen);
- errno_accept = errno;
+ childSocket = accept(masterSocket,
+ (struct sockaddr *) &csin, &alen);
+ errno_accept = errno;
/*block_signals ();*/
- if (childSocket < 0){
- switch (errno_accept){
- case EINTR:
- if (need_reload_config){
- reload_config ();
- need_reload_config = 0;
- databases_unloaded = 0;
+ if (childSocket < 0) {
+ switch (errno_accept) {
+ case EINTR:
+ if (need_reload_config) {
+ reload_config();
+ need_reload_config = 0;
+ databases_unloaded = 0;
+ }
+
+ if (need_unload_databases) {
+ unload_databases();
+ need_unload_databases = 0;
+ databases_unloaded = 1;
+ }
+ continue;
+ case ECONNABORTED:
+ case ECONNRESET:
+ case ETIMEDOUT:
+ case EHOSTUNREACH:
+ case ENETUNREACH:
+ continue;
+ default:
+ log_info(":E: can't accept: errno = %d: %s\n",
+ errno_accept, strerror(errno_accept));
+ err_fatal_errno(__func__, ":E: can't accept");
}
+ }
- if (need_unload_databases){
- unload_databases ();
- need_unload_databases = 0;
- databases_unloaded = 1;
- }
- continue;
- case ECONNABORTED:
- case ECONNRESET:
- case ETIMEDOUT:
- case EHOSTUNREACH:
- case ENETUNREACH:
- continue;
- default:
- log_info (":E: can't accept: errno = %d: %s\n",
- errno_accept, strerror (errno_accept));
- err_fatal_errno (__func__, ":E: can't accept");
- }
- }
-
- if (_dict_daemon || dbg_test(DBG_NOFORK)) {
- dict_daemon(childSocket,&csin,0);
- } else {
- if (_dict_forks - _dict_reaps < _dict_daemon_limit_childs) {
- if (!start_daemon()) { /* child */
- int databases_loaded = (DictConfig != NULL);
-
- alarm(0);
- if (_dict_daemon_limit_time){
- setsig (SIGALRM, handler, 0);
- alarm(_dict_daemon_limit_time);
- }
-
- dict_daemon (childSocket, &csin, databases_loaded ? 0 : 2);
-
- exit(0);
- } else { /* parent */
- close(childSocket);
+ if (_dict_daemon || dbg_test(DBG_NOFORK)) {
+ dict_daemon(childSocket, &csin, 0);
+ } else {
+ if (_dict_forks - _dict_reaps < _dict_daemon_limit_childs) {
+ if (!start_daemon()) { /* child */
+ int databases_loaded = (DictConfig != NULL);
+
+ alarm(0);
+ if (_dict_daemon_limit_time) {
+ setsig(SIGALRM, handler, 0);
+ alarm(_dict_daemon_limit_time);
+ }
+
+ dict_daemon(childSocket, &csin,
+ databases_loaded ? 0 : 2);
+
+ exit(0);
+ } else { /* parent */
+ close(childSocket);
+ }
+ } else {
+ dict_daemon(childSocket, &csin, 1);
}
- } else {
- dict_daemon(childSocket, &csin, 1);
- }
- }
- }
+ }
+ }
- dict_close_databases (DictConfig);
+ dict_close_databases(DictConfig);
- destroy ();
- return 0;
+ destroy();
+ return 0;
}
--- a/dict.c
+++ b/dict.c
@@ -23,14 +23,14 @@
#include "md5.h"
#include <stdarg.h>
-extern int yy_flex_debug;
- lst_List dict_Servers;
- FILE *dict_output;
- FILE *dict_error;
- int formatted;
- int flush;
+extern int yy_flex_debug;
+lst_List dict_Servers;
+FILE *dict_output;
+FILE *dict_error;
+int formatted;
+int flush;
-const char *host_connected = NULL;
+const char *host_connected = NULL;
const char *service_connected = NULL;
#define BUFFERSIZE 2048
@@ -56,33 +56,33 @@ const char *service_connected = NULL;
#define CMD_OPTION_MIME 15
struct cmd {
- int command;
- int sent;
- int flag;
- const char *host;
- const char *service;
- const char *database;
- const char *strategy;
- const char *word;
- const char *client;
- const char *user;
- const char *key;
- const char *comment;
+ int command;
+ int sent;
+ int flag;
+ const char *host;
+ const char *service;
+ const char *database;
+ const char *strategy;
+ const char *word;
+ const char *client;
+ const char *user;
+ const char *key;
+ const char *comment;
};
-lst_List cmd_list;
+lst_List cmd_list;
unsigned long client_defines;
unsigned long client_bytes;
unsigned long client_pipesize = PIPESIZE;
-char *client_text = NULL;
+char *client_text = NULL;
int option_mime = 0;
int ex_status = 0;
-static void set_ex_status (int status)
+static void set_ex_status(int status)
{
- if (!ex_status)
- ex_status = status;
+ if (!ex_status)
+ ex_status = status;
}
#define EXST_NO_MATCH 20
@@ -104,1364 +104,1516 @@ static void set_ex_status (int status)
#define EXST_CONNECTION_FAILED 41
struct def {
- lst_List data;
- const char *word;
- const char *db;
- const char *dbname;
+ lst_List data;
+ const char *word;
+ const char *db;
+ const char *dbname;
};
struct reply {
- int s;
- const char *host;
- const char *service;
- const char *user;
- const char *key;
- const char *msgid;
- const char *word;
- lst_List data;
- int retcode;
- int count; /* definitions found */
- int matches; /* matches found */
- int match; /* doing match found */
- int listed; /* Databases or strategies listed */
- struct def *defs;
+ int s;
+ const char *host;
+ const char *service;
+ const char *user;
+ const char *key;
+ const char *msgid;
+ const char *word;
+ lst_List data;
+ int retcode;
+ int count; /* definitions found */
+ int matches; /* matches found */
+ int match; /* doing match found */
+ int listed; /* Databases or strategies listed */
+ struct def *defs;
} cmd_reply;
-static const char *cpy( const char *s )
+static const char *cpy(const char *s)
{
- if (!s || !*s) return NULL;
- return str_copy(s);
+ if (!s || !*s)
+ return NULL;
+ return str_copy(s);
}
-static void client_crlf( char *d, const char *s )
+static void client_crlf(char *d, const char *s)
{
- int flag = 0;
-
- while (*s) {
- if (*s == '\n') {
- *d++ = '\r';
- *d++ = '\n';
- ++s;
- ++flag;
- } else {
- *d++ = *s++;
- flag = 0;
- }
- }
- if (!flag) {
- *d++ = '\r';
- *d++ = '\n';
- }
- *d = '\0';
-}
-
-static void unexpected_status_code (
- int expected_status, int act_status,
- const char *message)
-{
- switch (act_status){
- case CODE_TEMPORARILY_UNAVAILABLE:
- fprintf (stderr,
- "%s\n",
- (message ? message : "Server temporarily unavailable"));
- exit (EXST_TEMPORARILY_UNAVAILABLE);
-
- case CODE_SHUTTING_DOWN:
- fprintf (stderr,
- "%s\n", (message ? message : "Server shutting down"));
- exit (EXST_SHUTTING_DOWN);
-
- case CODE_SYNTAX_ERROR:
- fprintf (stderr,
- "%s\n", (message ? message : "Command not recognized"));
- exit (EXST_SYNTAX_ERROR);
-
- case CODE_ILLEGAL_PARAM:
- fprintf (stderr,
- "%s\n", (message ? message : "Illegal parameters"));
- exit (EXST_ILLEGAL_PARAM);
-
- case CODE_COMMAND_NOT_IMPLEMENTED:
- fprintf (stderr,
- "%s\n", (message ? message : "Command not implemented"));
- exit (EXST_COMMAND_NOT_IMPLEMENTED);
-
- case CODE_PARAM_NOT_IMPLEMENTED:
- fprintf (stderr,
- "%s\n", (message ? message : "Parameter not implemented"));
- exit (EXST_PARAM_NOT_IMPLEMENTED);
-
- case CODE_ACCESS_DENIED:
- fprintf (stderr,
- "%s\n", (message ? message : "Access denied"));
- exit (EXST_ACCESS_DENIED);
-
- case CODE_AUTH_DENIED:
- fprintf (stderr,
- "%s\n", (message ? message : "Authentication denied"));
- exit (EXST_AUTH_DENIED);
-
- case CODE_INVALID_DB:
- fprintf (stderr,
- "%s\n", (message ? message : "Invalid database"));
- exit (EXST_INVALID_DB);
-
- case CODE_INVALID_STRATEGY:
- fprintf (stderr,
- "%s\n", (message ? message : "Invalid strategy"));
- exit (EXST_INVALID_STRATEGY);
-
- case CODE_NO_MATCH:
- fprintf (stderr,
- "%s\n", (message ? message : "No matches found"));
- exit (EXST_NO_MATCH);
-
- case CODE_NO_DATABASES:
- fprintf (stderr,
- "%s\n", (message ? message : "No databases"));
- exit (EXST_NO_DATABASES);
-
- case CODE_NO_STRATEGIES:
- fprintf (stderr,
- "%s\n", (message ? message : "No strategies"));
- exit (EXST_NO_STRATEGIES);
-
- default:
- fprintf (stderr,
- "Unexpected status code %d (%s), wanted %d\n",
- act_status,
- (message ? message : "no message"),
- expected_status);
-
- exit (EXST_UNEXPECTED);
- }
-}
-
-static void client_open_pager( void )
-{
- dict_output = stdout;
- dict_error = stderr;
-}
-
-static void client_close_pager( void )
-{
- fflush (dict_output);
-}
-
-static lst_List client_read_text( int s )
-{
- lst_List l = lst_create();
- char line[BUFFERSIZE];
- int len;
-
- while ((len = net_read(s, line, BUFFERSIZE - 1)) >= 0) {
- line [len] = 0;
-
- client_bytes += len;
- PRINTF(DBG_RAW,("* Text: %s\n",line));
- if (line[0] == '.' && line[1] == '\0') break;
- if (len >= 2 && line[0] == '.' && line[1] == '.')
- lst_append( l, xstrdup(line + 1) );
- else
- lst_append( l, xstrdup(line) );
- }
- if (len < 0) {
- client_close_pager();
- err_fatal_errno( __func__, "Error reading from socket\n" );
- }
- return l;
-}
-
-static void client_print_text( lst_List l, int print_host_port )
-{
- lst_Position p;
- const char *e;
-
- if (!l) return;
-
- if (formatted && print_host_port){
- fprintf (dict_output, "%s\t%s\n", host_connected, service_connected);
- }
-
- LST_ITERATE(l,p,e) fprintf( dict_output, " %s\n", e );
-}
-
-static void client_print_definitions (const struct def *r)
-{
- if (formatted){
- fprintf (dict_output, "%s\t%s\t", host_connected, service_connected);
-
- if (r -> dbname && r -> db)
- {
- fprintf( dict_output, "%s\t%s\n", r -> db, r -> dbname);
- } else if (r -> dbname) {
- fprintf( dict_output, "%s\n", r -> dbname );
- } else if (r -> db) {
- fprintf( dict_output, "%s\n", r -> db );
- } else {
- fprintf( dict_output, "unknown\n" );
- }
- }else{
- fprintf (dict_output, "\nFrom ");
- if (r -> dbname && r -> db)
- {
- fprintf( dict_output, "%s [%s]",
- r -> dbname,
- r -> db);
- } else if (r -> dbname) {
- fprintf( dict_output, "%s", r -> dbname );
- } else if (r -> db) {
- fprintf( dict_output, "%s", r -> db );
- } else {
- fprintf( dict_output, "unknown" );
- }
-
- fprintf( dict_output, ":\n\n" );
- }
-
- client_print_text( r -> data, 0 );
-}
-
-static void client_print_matches( lst_List l, int flag, const char *word )
-{
- lst_Position p;
- const char *e;
- arg_List a;
- const char *prev = NULL;
- const char *last;
- const char *db;
- static int first = 1;
- int pos = 0;
- int len;
- int count;
- int empty_line_found = 0;
-
- const char *arg0 = NULL;
- const char *arg1 = NULL;
-
- count = 0;
- if (l) {
- last = NULL;
- LST_ITERATE(l,p,e) {
- if (last && !strcmp(last,e)) continue;
- ++count;
- last = e;
- }
- } else {
- if (flag)
- fprintf( dict_error, "No matches found for \"%s\"\n", word );
- set_ex_status (EXST_NO_MATCH);
- return;
- }
-
- last = NULL;
- LST_ITERATE(l,p,e) {
- /* skip MIME header */
- if (option_mime && !empty_line_found){
- empty_line_found = (e [0] == 0 ||
- (e [0] == '\r' && e [1] == 0));
- continue;
- }
-
- /* */
- if (last && !strcmp(last,e)) continue;
- last = e;
- a = arg_argify( e, 0 );
- if (arg_count(a) != 2)
- err_internal( __func__,
- "MATCH command didn't return 2 args: \"%s\"\n", e );
-
- arg0 = arg_get (a,0);
- arg1 = arg_get (a,1);
-
- if (formatted){
- fprintf (dict_output, "%s\t%s\t%s\t%s\n",
- host_connected, service_connected, arg0, arg1);
- }else{
- if ((db = str_find(arg0)) != prev) {
- if (!first) fprintf( dict_output, "\n" );
- first = 0;
- fprintf( dict_output, "%s:", db );
- prev = db;
- pos = 6 + strlen(db);
- }
- len = strlen(arg1);
- if (pos + len + 4 > 70) {
- fprintf( dict_output, "\n" );
- pos = 0;
- }
- if (strchr (arg1,' ')) {
- fprintf( dict_output, " \"%s\"", arg1 );
- pos += len + 4;
- } else {
- fprintf( dict_output, " %s", arg1 );
- pos += len + 2;
- }
- }
-
- arg_destroy(a);
- }
- fprintf( dict_output, "\n" );
-}
-
-static void client_print_listed( lst_List l )
-{
- lst_Position p;
- const char *e;
- arg_List a;
- int colWidth = 10; /* minimum size of first column */
- int colMax = 16; /* maximum size of unragged first column */
- char format[32];
- int empty_line_found = 0;
- int len;
-
- if (!l) return;
- LST_ITERATE(l,p,e) {
- /* skip MIME header */
- if (option_mime && !empty_line_found){
- empty_line_found = (e [0] == 0 ||
- (e [0] == '\r' && e [1] == 0));
- continue;
- }
-
- /* */
- a = arg_argify( e, 0 );
- if (arg_count(a) != 2)
- err_internal( __func__,
- "SHOW command didn't return 2 args: \"%s\"\n", e );
-
- len = strlen (arg_get (a,0));
-
- if (len > colWidth && len <= colMax)
- colWidth = len;
-
- arg_destroy(a);
- }
-
- snprintf( format, sizeof (format), " %%-%ds %%s\n", colWidth );
-
- empty_line_found = 0;
-
- LST_ITERATE(l,p,e) {
- /* skip MIME header */
- if (option_mime && !empty_line_found){
- empty_line_found = (e [0] == 0 ||
- (e [0] == '\r' && e [1] == 0));
- continue;
- }
-
- /* */
- a = arg_argify( e, 0 );
-
- if (formatted){
- assert (host_connected);
- assert (service_connected);
-
- fprintf (dict_output, "%s\t%s\t%s\t%s\n",
- host_connected, service_connected, arg_get (a,0), arg_get (a,1));
- }else{
- fprintf (dict_output, format, arg_get (a,0), arg_get (a,1));
- }
-
- arg_destroy(a);
- }
-}
-
-static void client_free_text( lst_List l )
-{
- lst_Position p;
- char *e;
-
- if (!l) return;
- LST_ITERATE(l,p,e) {
- if (e) xfree(e);
- }
- lst_destroy(l);
-}
-
-static int client_read_status( int s,
- const char **message,
- int *count,
- const char **word,
- const char **db,
- const char **dbname,
- const char **msgid )
-{
- static char buf[BUFFERSIZE];
- arg_List cmdline;
- int argc;
- char **argv;
- int status;
- char *start, *end, *p;
- int len;
-
- if ((len = net_read( s, buf, BUFFERSIZE )) < 0) {
- client_close_pager();
- err_fatal_errno( __func__, "Error reading from socket\n" );
- }
- client_bytes += len;
- PRINTF(DBG_RAW,("* Read: %s\n",buf));
-
- if ((status = atoi(buf)) < 100) status = 600;
- PRINTF(DBG_RAW,("* Status = %d\n",status));
-
- if (message && (p = strchr(buf, ' '))) *message = p + 1;
-
- if (count) *count = 0;
- if (word) *word = NULL;
- if (db) *db = NULL;
- if (dbname) *dbname = NULL;
- if (msgid) *msgid = NULL;
-
- switch (status) {
- case CODE_HELLO:
- if ((start = strrchr(buf, '<')) && (end = strrchr(buf,'>'))) {
- end[1] = '\0';
- *msgid = str_copy( start );
- PRINTF(DBG_VERBOSE,("Msgid is \"%s\"\n",*msgid));
- }
- break;
- case CODE_DATABASE_LIST:
- case CODE_STRATEGY_LIST:
- case CODE_DEFINITIONS_FOUND:
- case CODE_MATCHES_FOUND:
- cmdline = arg_argify(buf,0);
- arg_get_vector( cmdline, &argc, &argv );
- if (argc > 1 && count) *count = atoi(argv[1]);
- arg_destroy(cmdline);
- break;
- case CODE_DEFINITION_FOLLOWS:
- cmdline = arg_argify(buf,0);
- arg_get_vector( cmdline, &argc, &argv );
- if (argc > 1 && word) *word = str_find(argv[1]);
- if (argc > 2 && db) *db = str_find(argv[2]);
- if (argc > 3 && dbname) *dbname = str_find(argv[3]);
- arg_destroy(cmdline);
- break;
- default:
- break;
- }
-
- return status;
-}
-
-static struct cmd *make_command( int command, ... )
-{
- va_list ap;
- struct cmd *c = xmalloc( sizeof( struct cmd ) );
-
- memset( c, 0, sizeof( struct cmd ) );
- c->command = command;
-
- va_start( ap, command );
- switch (command) {
- case CMD_PRINT:
- c->comment = va_arg( ap, const char * );
- break;
- case CMD_DEFPRINT:
- c->database = va_arg( ap, const char * );
- c->word = va_arg( ap, const char * );
- c->flag = va_arg( ap, int );
- break;
- case CMD_CONNECT:
- c->host = va_arg( ap, const char * );
- c->service = va_arg( ap, const char * );
- c->user = va_arg( ap, const char * );
- c->key = va_arg( ap, const char * );
- break;
- case CMD_CLIENT:
- c->client = va_arg( ap, const char * );
- break;
- case CMD_AUTH:
- break;
- case CMD_INFO:
- c->database = va_arg( ap, const char * );
- break;
- case CMD_SERVER:
- break;
- case CMD_DBS:
- break;
- case CMD_STRATS:
- break;
- case CMD_HELP:
- break;
- case CMD_MATCH:
- c->database = va_arg( ap, const char * );
- c->strategy = va_arg( ap, const char * );
- c->word = va_arg( ap, const char * );
- break;
- case CMD_DEFINE:
- c->database = va_arg( ap, const char * );
- c->word = va_arg( ap, const char * );
- break;
- case CMD_SPELL:
- c->database = va_arg( ap, const char * );
- c->word = va_arg( ap, const char * );
- break;
- case CMD_WIND:
- c->database = va_arg( ap, const char * );
- c->strategy = va_arg( ap, const char * );
- c->word = va_arg( ap, const char * );
- break;
- case CMD_CLOSE:
- break;
- case CMD_OPTION_MIME:
- break;
- default:
- err_internal( __func__, "Illegal command %d\n", command );
- }
- va_end( ap );
-
- return c;
-}
-
-static void append_command( struct cmd *c )
-{
- if (!cmd_list) cmd_list = lst_create();
- lst_append( cmd_list, c );
-}
-
-
-static void prepend_command( struct cmd *c )
-{
- if (!cmd_list) cmd_list = lst_create();
- lst_push( cmd_list, c );
-}
-
-
-static void request( void )
-{
- char b[BUFFERSIZE];
- char *buffer = alloca( client_pipesize );
- char *p = buffer;
- lst_Position pos;
- struct cmd *c = NULL;
- unsigned char digest[16];
- char hex[33];
- struct MD5Context ctx;
- int i;
- unsigned len;
- int total = 0;
- int count = 0;
-
- *p = '\0';
- c = lst_top(cmd_list);
- if (c->command == CMD_CONNECT) {
- cmd_reply.user = c->user;
- cmd_reply.key = c->key;
- }
-
- LST_ITERATE(cmd_list,pos,c) {
- b[0] = '\0';
- len = 0;
- PRINTF(DBG_PIPE,("* Looking at request %d\n",c->command));
- if (c->sent) {
- PRINTF(DBG_PIPE,("* Skipping\n"));
- return; /* FIXME! Keep sending deeper things? */
- }
- ++count;
- switch( c->command) {
- case CMD_PRINT: break;
- case CMD_DEFPRINT: break;
- case CMD_CONNECT: break;
- case CMD_AUTH:
- if (!cmd_reply.key || !cmd_reply.user) break;
- if (!cmd_reply.msgid) goto end;
- MD5Init(&ctx);
- MD5Update(&ctx, (const unsigned char *) cmd_reply.msgid, strlen(cmd_reply.msgid));
- MD5Update(&ctx, (const unsigned char *) cmd_reply.key, strlen(cmd_reply.key));
- MD5Final(digest, &ctx );
- for (i = 0; i < 16; i++)
- sprintf( hex+2*i, "%02x", digest[i] );
- hex[32] = '\0';
- snprintf( b, BUFFERSIZE, "auth %s %s\n", cmd_reply.user, hex );
- break;
- case CMD_CLIENT:
- if (client_text)
- snprintf( b, BUFFERSIZE, "client \"%s: %s\"\n",
- c->client, client_text );
- else
- snprintf( b, BUFFERSIZE, "client \"%s\"\n", c->client );
- break;
- case CMD_INFO: snprintf( b, BUFFERSIZE, "show info %s\n",
- c->database ); break;
- case CMD_SERVER: snprintf( b, BUFFERSIZE, "show server\n" ); break;
- case CMD_DBS: snprintf( b, BUFFERSIZE, "show db\n" ); break;
- case CMD_STRATS: snprintf( b, BUFFERSIZE, "show strat\n" ); break;
- case CMD_HELP: snprintf( b, BUFFERSIZE, "help\n" ); break;
- case CMD_MATCH:
- cmd_reply.word = c->word;
- snprintf( b, BUFFERSIZE,
- "match %s %s \"%s\"\n",
- c->database, c->strategy, c->word ); break;
- case CMD_DEFINE:
- cmd_reply.word = c->word;
- snprintf( b, BUFFERSIZE, "define %s \"%s\"\n",
- c->database, c->word ); break;
- case CMD_SPELL: goto end;
- case CMD_WIND: goto end;
- case CMD_CLOSE: snprintf( b, BUFFERSIZE, "quit\n" ); break;
- case CMD_OPTION_MIME: snprintf( b, BUFFERSIZE, "option mime\n" ); break;
- default:
- err_internal( __func__, "Unknown command %d\n", c->command );
- }
- len = strlen(b);
- if (total + len + 3 > client_pipesize) {
- if (count == 1 && p == buffer && total == 0) {
- /* The buffer is too small, but we have to
- send something... */
- PRINTF(DBG_PIPE,("* Reallocating buffer to %d bytes\n",len+1));
- p = buffer = alloca( len + 1 );
- } else {
- break;
- }
- }
- strcpy( p, b );
- p += len;
- total += len;
- ++c->sent;
- if (dbg_test(DBG_SERIAL)) break; /* Don't pipeline. */
- }
+ int flag = 0;
-end: /* Ready to send buffer, but are we
+ while (*s) {
+ if (*s == '\n') {
+ *d++ = '\r';
+ *d++ = '\n';
+ ++s;
+ ++flag;
+ } else {
+ *d++ = *s++;
+ flag = 0;
+ }
+ }
+ if (!flag) {
+ *d++ = '\r';
+ *d++ = '\n';
+ }
+ *d = '\0';
+}
+
+static void unexpected_status_code(int expected_status, int act_status,
+ const char *message)
+{
+ switch (act_status) {
+ case CODE_TEMPORARILY_UNAVAILABLE:
+ fprintf(stderr,
+ "%s\n",
+ (message ? message : "Server temporarily unavailable"));
+ exit(EXST_TEMPORARILY_UNAVAILABLE);
+
+ case CODE_SHUTTING_DOWN:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Server shutting down"));
+ exit(EXST_SHUTTING_DOWN);
+
+ case CODE_SYNTAX_ERROR:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Command not recognized"));
+ exit(EXST_SYNTAX_ERROR);
+
+ case CODE_ILLEGAL_PARAM:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Illegal parameters"));
+ exit(EXST_ILLEGAL_PARAM);
+
+ case CODE_COMMAND_NOT_IMPLEMENTED:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Command not implemented"));
+ exit(EXST_COMMAND_NOT_IMPLEMENTED);
+
+ case CODE_PARAM_NOT_IMPLEMENTED:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Parameter not implemented"));
+ exit(EXST_PARAM_NOT_IMPLEMENTED);
+
+ case CODE_ACCESS_DENIED:
+ fprintf(stderr, "%s\n", (message ? message : "Access denied"));
+ exit(EXST_ACCESS_DENIED);
+
+ case CODE_AUTH_DENIED:
+ fprintf(stderr,
+ "%s\n", (message ? message : "Authentication denied"));
+ exit(EXST_AUTH_DENIED);
+
+ case CODE_INVALID_DB:
+ fprintf(stderr, "%s\n", (message ? message : "Invalid database"));
+ exit(EXST_INVALID_DB);
+
+ case CODE_INVALID_STRATEGY:
+ fprintf(stderr, "%s\n", (message ? message : "Invalid strategy"));
+ exit(EXST_INVALID_STRATEGY);
+
+ case CODE_NO_MATCH:
+ fprintf(stderr, "%s\n", (message ? message : "No matches found"));
+ exit(EXST_NO_MATCH);
+
+ case CODE_NO_DATABASES:
+ fprintf(stderr, "%s\n", (message ? message : "No databases"));
+ exit(EXST_NO_DATABASES);
+
+ case CODE_NO_STRATEGIES:
+ fprintf(stderr, "%s\n", (message ? message : "No strategies"));
+ exit(EXST_NO_STRATEGIES);
+
+ default:
+ fprintf(stderr,
+ "Unexpected status code %d (%s), wanted %d\n",
+ act_status,
+ (message ? message : "no message"), expected_status);
+
+ exit(EXST_UNEXPECTED);
+ }
+}
+
+static void client_open_pager(void)
+{
+ dict_output = stdout;
+ dict_error = stderr;
+}
+
+static void client_close_pager(void)
+{
+ fflush(dict_output);
+}
+
+static lst_List client_read_text(int s)
+{
+ lst_List l = lst_create();
+ char line[BUFFERSIZE];
+ int len;
+
+ while ((len = net_read(s, line, BUFFERSIZE - 1)) >= 0) {
+ line[len] = 0;
+
+ client_bytes += len;
+ PRINTF(DBG_RAW, ("* Text: %s\n", line));
+ if (line[0] == '.' && line[1] == '\0')
+ break;
+ if (len >= 2 && line[0] == '.' && line[1] == '.')
+ lst_append(l, xstrdup(line + 1));
+ else
+ lst_append(l, xstrdup(line));
+ }
+ if (len < 0) {
+ client_close_pager();
+ err_fatal_errno(__func__, "Error reading from socket\n");
+ }
+ return l;
+}
+
+static void client_print_text(lst_List l, int print_host_port)
+{
+ lst_Position p;
+ const char *e;
+
+ if (!l)
+ return;
+
+ if (formatted && print_host_port) {
+ fprintf(dict_output, "%s\t%s\n", host_connected,
+ service_connected);
+ }
+
+ LST_ITERATE(l, p, e) fprintf(dict_output, " %s\n", e);
+}
+
+static void client_print_definitions(const struct def *r)
+{
+ if (formatted) {
+ fprintf(dict_output, "%s\t%s\t", host_connected,
+ service_connected);
+
+ if (r->dbname && r->db) {
+ fprintf(dict_output, "%s\t%s\n", r->db, r->dbname);
+ } else if (r->dbname) {
+ fprintf(dict_output, "%s\n", r->dbname);
+ } else if (r->db) {
+ fprintf(dict_output, "%s\n", r->db);
+ } else {
+ fprintf(dict_output, "unknown\n");
+ }
+ } else {
+ fprintf(dict_output, "\nFrom ");
+ if (r->dbname && r->db) {
+ fprintf(dict_output, "%s [%s]", r->dbname, r->db);
+ } else if (r->dbname) {
+ fprintf(dict_output, "%s", r->dbname);
+ } else if (r->db) {
+ fprintf(dict_output, "%s", r->db);
+ } else {
+ fprintf(dict_output, "unknown");
+ }
+
+ fprintf(dict_output, ":\n\n");
+ }
+
+ client_print_text(r->data, 0);
+}
+
+static void client_print_matches(lst_List l, int flag, const char *word)
+{
+ lst_Position p;
+ const char *e;
+ arg_List a;
+ const char *prev = NULL;
+ const char *last;
+ const char *db;
+ static int first = 1;
+ int pos = 0;
+ int len;
+ int count;
+ int empty_line_found = 0;
+
+ const char *arg0 = NULL;
+ const char *arg1 = NULL;
+
+ count = 0;
+ if (l) {
+ last = NULL;
+ LST_ITERATE(l, p, e) {
+ if (last && !strcmp(last, e))
+ continue;
+ ++count;
+ last = e;
+ }
+ } else {
+ if (flag)
+ fprintf(dict_error, "No matches found for \"%s\"\n", word);
+ set_ex_status(EXST_NO_MATCH);
+ return;
+ }
+
+ last = NULL;
+ LST_ITERATE(l, p, e) {
+ /* skip MIME header */
+ if (option_mime && !empty_line_found) {
+ empty_line_found = (e[0] == 0 || (e[0] == '\r' && e[1] == 0));
+ continue;
+ }
+
+ /* */
+ if (last && !strcmp(last, e))
+ continue;
+ last = e;
+ a = arg_argify(e, 0);
+ if (arg_count(a) != 2)
+ err_internal(__func__,
+ "MATCH command didn't return 2 args: \"%s\"\n",
+ e);
+
+ arg0 = arg_get(a, 0);
+ arg1 = arg_get(a, 1);
+
+ if (formatted) {
+ fprintf(dict_output, "%s\t%s\t%s\t%s\n",
+ host_connected, service_connected, arg0, arg1);
+ } else {
+ if ((db = str_find(arg0)) != prev) {
+ if (!first)
+ fprintf(dict_output, "\n");
+ first = 0;
+ fprintf(dict_output, "%s:", db);
+ prev = db;
+ pos = 6 + strlen(db);
+ }
+ len = strlen(arg1);
+ if (pos + len + 4 > 70) {
+ fprintf(dict_output, "\n");
+ pos = 0;
+ }
+ if (strchr(arg1, ' ')) {
+ fprintf(dict_output, " \"%s\"", arg1);
+ pos += len + 4;
+ } else {
+ fprintf(dict_output, " %s", arg1);
+ pos += len + 2;
+ }
+ }
+
+ arg_destroy(a);
+ }
+ fprintf(dict_output, "\n");
+}
+
+static void client_print_listed(lst_List l)
+{
+ lst_Position p;
+ const char *e;
+ arg_List a;
+ int colWidth = 10; /* minimum size of first column */
+ int colMax = 16; /* maximum size of unragged first column */
+ char format[32];
+ int empty_line_found = 0;
+ int len;
+
+ if (!l)
+ return;
+ LST_ITERATE(l, p, e) {
+ /* skip MIME header */
+ if (option_mime && !empty_line_found) {
+ empty_line_found = (e[0] == 0 || (e[0] == '\r' && e[1] == 0));
+ continue;
+ }
+
+ /* */
+ a = arg_argify(e, 0);
+ if (arg_count(a) != 2)
+ err_internal(__func__,
+ "SHOW command didn't return 2 args: \"%s\"\n", e);
+
+ len = strlen(arg_get(a, 0));
+
+ if (len > colWidth && len <= colMax)
+ colWidth = len;
+
+ arg_destroy(a);
+ }
+
+ snprintf(format, sizeof(format), " %%-%ds %%s\n", colWidth);
+
+ empty_line_found = 0;
+
+ LST_ITERATE(l, p, e) {
+ /* skip MIME header */
+ if (option_mime && !empty_line_found) {
+ empty_line_found = (e[0] == 0 || (e[0] == '\r' && e[1] == 0));
+ continue;
+ }
+
+ /* */
+ a = arg_argify(e, 0);
+
+ if (formatted) {
+ assert(host_connected);
+ assert(service_connected);
+
+ fprintf(dict_output, "%s\t%s\t%s\t%s\n",
+ host_connected, service_connected, arg_get(a, 0),
+ arg_get(a, 1));
+ } else {
+ fprintf(dict_output, format, arg_get(a, 0), arg_get(a, 1));
+ }
+
+ arg_destroy(a);
+ }
+}
+
+static void client_free_text(lst_List l)
+{
+ lst_Position p;
+ char *e;
+
+ if (!l)
+ return;
+ LST_ITERATE(l, p, e) {
+ if (e)
+ xfree(e);
+ }
+ lst_destroy(l);
+}
+
+static int client_read_status(int s,
+ const char **message,
+ int *count,
+ const char **word,
+ const char **db,
+ const char **dbname, const char **msgid)
+{
+ static char buf[BUFFERSIZE];
+ arg_List cmdline;
+ int argc;
+ char **argv;
+ int status;
+ char *start, *end, *p;
+ int len;
+
+ if ((len = net_read(s, buf, BUFFERSIZE)) < 0) {
+ client_close_pager();
+ err_fatal_errno(__func__, "Error reading from socket\n");
+ }
+ client_bytes += len;
+ PRINTF(DBG_RAW, ("* Read: %s\n", buf));
+
+ if ((status = atoi(buf)) < 100)
+ status = 600;
+ PRINTF(DBG_RAW, ("* Status = %d\n", status));
+
+ if (message && (p = strchr(buf, ' ')))
+ *message = p + 1;
+
+ if (count)
+ *count = 0;
+ if (word)
+ *word = NULL;
+ if (db)
+ *db = NULL;
+ if (dbname)
+ *dbname = NULL;
+ if (msgid)
+ *msgid = NULL;
+
+ switch (status) {
+ case CODE_HELLO:
+ if ((start = strrchr(buf, '<')) && (end = strrchr(buf, '>'))) {
+ end[1] = '\0';
+ *msgid = str_copy(start);
+ PRINTF(DBG_VERBOSE, ("Msgid is \"%s\"\n", *msgid));
+ }
+ break;
+ case CODE_DATABASE_LIST:
+ case CODE_STRATEGY_LIST:
+ case CODE_DEFINITIONS_FOUND:
+ case CODE_MATCHES_FOUND:
+ cmdline = arg_argify(buf, 0);
+ arg_get_vector(cmdline, &argc, &argv);
+ if (argc > 1 && count)
+ *count = atoi(argv[1]);
+ arg_destroy(cmdline);
+ break;
+ case CODE_DEFINITION_FOLLOWS:
+ cmdline = arg_argify(buf, 0);
+ arg_get_vector(cmdline, &argc, &argv);
+ if (argc > 1 && word)
+ *word = str_find(argv[1]);
+ if (argc > 2 && db)
+ *db = str_find(argv[2]);
+ if (argc > 3 && dbname)
+ *dbname = str_find(argv[3]);
+ arg_destroy(cmdline);
+ break;
+ default:
+ break;
+ }
+
+ return status;
+}
+
+static struct cmd *make_command(int command, ...)
+{
+ va_list ap;
+ struct cmd *c = xmalloc(sizeof(struct cmd));
+
+ memset(c, 0, sizeof(struct cmd));
+ c->command = command;
+
+ va_start(ap, command);
+ switch (command) {
+ case CMD_PRINT:
+ c->comment = va_arg(ap, const char *);
+ break;
+ case CMD_DEFPRINT:
+ c->database = va_arg(ap, const char *);
+ c->word = va_arg(ap, const char *);
+ c->flag = va_arg(ap, int);
+ break;
+ case CMD_CONNECT:
+ c->host = va_arg(ap, const char *);
+ c->service = va_arg(ap, const char *);
+ c->user = va_arg(ap, const char *);
+ c->key = va_arg(ap, const char *);
+ break;
+ case CMD_CLIENT:
+ c->client = va_arg(ap, const char *);
+ break;
+ case CMD_AUTH:
+ break;
+ case CMD_INFO:
+ c->database = va_arg(ap, const char *);
+ break;
+ case CMD_SERVER:
+ break;
+ case CMD_DBS:
+ break;
+ case CMD_STRATS:
+ break;
+ case CMD_HELP:
+ break;
+ case CMD_MATCH:
+ c->database = va_arg(ap, const char *);
+ c->strategy = va_arg(ap, const char *);
+ c->word = va_arg(ap, const char *);
+ break;
+ case CMD_DEFINE:
+ c->database = va_arg(ap, const char *);
+ c->word = va_arg(ap, const char *);
+ break;
+ case CMD_SPELL:
+ c->database = va_arg(ap, const char *);
+ c->word = va_arg(ap, const char *);
+ break;
+ case CMD_WIND:
+ c->database = va_arg(ap, const char *);
+ c->strategy = va_arg(ap, const char *);
+ c->word = va_arg(ap, const char *);
+ break;
+ case CMD_CLOSE:
+ break;
+ case CMD_OPTION_MIME:
+ break;
+ default:
+ err_internal(__func__, "Illegal command %d\n", command);
+ }
+ va_end(ap);
+
+ return c;
+}
+
+static void append_command(struct cmd *c)
+{
+ if (!cmd_list)
+ cmd_list = lst_create();
+ lst_append(cmd_list, c);
+}
+
+
+static void prepend_command(struct cmd *c)
+{
+ if (!cmd_list)
+ cmd_list = lst_create();
+ lst_push(cmd_list, c);
+}
+
+
+static void request(void)
+{
+ char b[BUFFERSIZE];
+ char *buffer = alloca(client_pipesize);
+ char *p = buffer;
+ lst_Position pos;
+ struct cmd *c = NULL;
+ unsigned char digest[16];
+ char hex[33];
+ struct MD5Context ctx;
+ int i;
+ unsigned len;
+ int total = 0;
+ int count = 0;
+
+ *p = '\0';
+ c = lst_top(cmd_list);
+ if (c->command == CMD_CONNECT) {
+ cmd_reply.user = c->user;
+ cmd_reply.key = c->key;
+ }
+
+ LST_ITERATE(cmd_list, pos, c) {
+ b[0] = '\0';
+ len = 0;
+ PRINTF(DBG_PIPE, ("* Looking at request %d\n", c->command));
+ if (c->sent) {
+ PRINTF(DBG_PIPE, ("* Skipping\n"));
+ return; /* FIXME! Keep sending deeper things? */
+ }
+ ++count;
+ switch (c->command) {
+ case CMD_PRINT:
+ break;
+ case CMD_DEFPRINT:
+ break;
+ case CMD_CONNECT:
+ break;
+ case CMD_AUTH:
+ if (!cmd_reply.key || !cmd_reply.user)
+ break;
+ if (!cmd_reply.msgid)
+ goto end;
+ MD5Init(&ctx);
+ MD5Update(&ctx, (const unsigned char *) cmd_reply.msgid,
+ strlen(cmd_reply.msgid));
+ MD5Update(&ctx, (const unsigned char *) cmd_reply.key,
+ strlen(cmd_reply.key));
+ MD5Final(digest, &ctx);
+ for (i = 0; i < 16; i++)
+ sprintf(hex + 2 * i, "%02x", digest[i]);
+ hex[32] = '\0';
+ snprintf(b, BUFFERSIZE, "auth %s %s\n", cmd_reply.user, hex);
+ break;
+ case CMD_CLIENT:
+ if (client_text)
+ snprintf(b, BUFFERSIZE, "client \"%s: %s\"\n",
+ c->client, client_text);
+ else
+ snprintf(b, BUFFERSIZE, "client \"%s\"\n", c->client);
+ break;
+ case CMD_INFO:
+ snprintf(b, BUFFERSIZE, "show info %s\n", c->database);
+ break;
+ case CMD_SERVER:
+ snprintf(b, BUFFERSIZE, "show server\n");
+ break;
+ case CMD_DBS:
+ snprintf(b, BUFFERSIZE, "show db\n");
+ break;
+ case CMD_STRATS:
+ snprintf(b, BUFFERSIZE, "show strat\n");
+ break;
+ case CMD_HELP:
+ snprintf(b, BUFFERSIZE, "help\n");
+ break;
+ case CMD_MATCH:
+ cmd_reply.word = c->word;
+ snprintf(b, BUFFERSIZE,
+ "match %s %s \"%s\"\n",
+ c->database, c->strategy, c->word);
+ break;
+ case CMD_DEFINE:
+ cmd_reply.word = c->word;
+ snprintf(b, BUFFERSIZE, "define %s \"%s\"\n",
+ c->database, c->word);
+ break;
+ case CMD_SPELL:
+ goto end;
+ case CMD_WIND:
+ goto end;
+ case CMD_CLOSE:
+ snprintf(b, BUFFERSIZE, "quit\n");
+ break;
+ case CMD_OPTION_MIME:
+ snprintf(b, BUFFERSIZE, "option mime\n");
+ break;
+ default:
+ err_internal(__func__, "Unknown command %d\n", c->command);
+ }
+ len = strlen(b);
+ if (total + len + 3 > client_pipesize) {
+ if (count == 1 && p == buffer && total == 0) {
+ /* The buffer is too small, but we have to
+ send something... */
+ PRINTF(DBG_PIPE,
+ ("* Reallocating buffer to %d bytes\n", len + 1));
+ p = buffer = alloca(len + 1);
+ } else {
+ break;
+ }
+ }
+ strcpy(p, b);
+ p += len;
+ total += len;
+ ++c->sent;
+ if (dbg_test(DBG_SERIAL))
+ break; /* Don't pipeline. */
+ }
+
+ end: /* Ready to send buffer, but are we
connected? */
- if (!cmd_reply.s) {
- c = lst_top(cmd_list);
- if (c->command != CMD_CONNECT) {
- err_internal( __func__, "Not connected, but no CMD_CONNECT\n" );
- }
- if ((cmd_reply.s = net_connect_tcp( c->host,
- c->service
- ? c->service
- : DICT_DEFAULT_SERVICE )) < 0) {
- const char *message;
-
- switch (cmd_reply.s) {
- case NET_NOHOST: message = "Can't get host entry for"; break;
- case NET_NOSERVICE: message = "Can't get service entry for"; break;
- case NET_NOPROTOCOL: message = "Can't get protocol entry for"; break;
- case NET_NOCONNECT: message = "Can't connect to"; break;
- default: message = "Unknown error for"; break;
- }
- PRINTF(DBG_VERBOSE,("%s %s.%s\n",
- message,
- c->host,
- c->service ? c->service : DICT_DEFAULT_SERVICE));
- if (lst_length(cmd_list) > 1) {
- c = lst_nth_get(cmd_list,2);
- if (c->command == CMD_CONNECT) {
- /* undo pipelining */
- cmd_reply.s = 0;
- if (!dbg_test(DBG_SERIAL)) {
- LST_ITERATE(cmd_list,pos,c) c->sent = 0;
- }
- return;
- }
- }
- client_close_pager();
- fprintf (stderr, "Cannot connect to any servers%s\n",\
- dbg_test(DBG_VERBOSE) ? "" : " (use -v to see why)" );
- exit (EXST_CONNECTION_FAILED);
- }
- cmd_reply.host = c->host;
- cmd_reply.service = c->service ? c->service : DICT_DEFAULT_SERVICE;
- cmd_reply.user = c->user;
- cmd_reply.key = c->key;
- }
- if ((len = strlen(buffer))) {
- char *pt;
-
- PRINTF(DBG_PIPE,("* Sending %d commands (%d bytes)\n",count,len));
- PRINTF(DBG_RAW,("* Send/%d: %s",c->command,buffer));
- pt = alloca(2*len);
- client_crlf(pt,buffer);
- net_write( cmd_reply.s, pt, strlen(pt) );
- } else {
- PRINTF(DBG_PIPE,("* Sending nothing\n"));
- PRINTF(DBG_RAW,("* Send/%d\n",c->command));
- }
-}
-
-static void process( void )
-{
- struct cmd *c;
- int expected;
- const char *message = NULL;
- int i;
- int *listed;
- FILE *old;
-
- while ((c = lst_top( cmd_list ))) {
- request(); /* Send requests */
- lst_pop( cmd_list );
- expected = CODE_OK;
- switch (c->command) {
- case CMD_PRINT:
- if (!formatted){
- if (c->comment) fprintf( dict_output, "%s", c->comment );
- }
-
- if (cmd_reply.match)
- client_print_matches( cmd_reply.data, 1, cmd_reply.word );
- else if (cmd_reply.listed)
- client_print_listed( cmd_reply.data );
- else
- client_print_text( cmd_reply.data, 1 );
-
- if (flush){
- fflush (dict_output);
- }
-
- client_free_text( cmd_reply.data );
- cmd_reply.data = NULL;
- cmd_reply.matches = cmd_reply.match = cmd_reply.listed = 0;
- expected = cmd_reply.retcode;
- break;
- case CMD_DEFPRINT:
- if (cmd_reply.count) {
- if (c->flag) {
- fprintf( dict_output, "%d definition%s found",
- cmd_reply.count,
- cmd_reply.count == 1 ? "" : "s" );
- fprintf( dict_output, "\n" );
- }
- for (i = 0; i < cmd_reply.count; i++) {
- client_print_definitions (&cmd_reply.defs [i]);
-
- if (flush){
- fflush (dict_output);
- }
-
- client_free_text( cmd_reply.defs[i].data );
- cmd_reply.defs[i].data = NULL;
- }
- xfree( cmd_reply.defs );
- cmd_reply.count = 0;
-
- } else if (cmd_reply.matches) {
- fprintf( dict_error,
- "No definitions found for \"%s\", perhaps you mean:",
- c->word );
- fprintf( dict_error, "\n" );
-
- old = dict_output;
- dict_output = dict_error;
- client_print_matches( cmd_reply.data, 0, c->word );
- dict_output = old;
+ if (!cmd_reply.s) {
+ c = lst_top(cmd_list);
+ if (c->command != CMD_CONNECT) {
+ err_internal(__func__, "Not connected, but no CMD_CONNECT\n");
+ }
+ if ((cmd_reply.s = net_connect_tcp(c->host,
+ c->service
+ ? c->service
+ : DICT_DEFAULT_SERVICE)) < 0) {
+ const char *message;
+
+ switch (cmd_reply.s) {
+ case NET_NOHOST:
+ message = "Can't get host entry for";
+ break;
+ case NET_NOSERVICE:
+ message = "Can't get service entry for";
+ break;
+ case NET_NOPROTOCOL:
+ message = "Can't get protocol entry for";
+ break;
+ case NET_NOCONNECT:
+ message = "Can't connect to";
+ break;
+ default:
+ message = "Unknown error for";
+ break;
+ }
+ PRINTF(DBG_VERBOSE, ("%s %s.%s\n",
+ message,
+ c->host,
+ c->service ? c->
+ service : DICT_DEFAULT_SERVICE));
+ if (lst_length(cmd_list) > 1) {
+ c = lst_nth_get(cmd_list, 2);
+ if (c->command == CMD_CONNECT) {
+ /* undo pipelining */
+ cmd_reply.s = 0;
+ if (!dbg_test(DBG_SERIAL)) {
+ LST_ITERATE(cmd_list, pos, c) c->sent = 0;
+ }
+ return;
+ }
+ }
+ client_close_pager();
+ fprintf(stderr, "Cannot connect to any servers%s\n",
+ dbg_test(DBG_VERBOSE) ? "" : " (use -v to see why)");
+ exit(EXST_CONNECTION_FAILED);
+ }
+ cmd_reply.host = c->host;
+ cmd_reply.service = c->service ? c->service : DICT_DEFAULT_SERVICE;
+ cmd_reply.user = c->user;
+ cmd_reply.key = c->key;
+ }
+ if ((len = strlen(buffer))) {
+ char *pt;
+
+ PRINTF(DBG_PIPE,
+ ("* Sending %d commands (%d bytes)\n", count, len));
+ PRINTF(DBG_RAW, ("* Send/%d: %s", c->command, buffer));
+ pt = alloca(2 * len);
+ client_crlf(pt, buffer);
+ net_write(cmd_reply.s, pt, strlen(pt));
+ } else {
+ PRINTF(DBG_PIPE, ("* Sending nothing\n"));
+ PRINTF(DBG_RAW, ("* Send/%d\n", c->command));
+ }
+}
+
+static void process(void)
+{
+ struct cmd *c;
+ int expected;
+ const char *message = NULL;
+ int i;
+ int *listed;
+ FILE *old;
+
+ while ((c = lst_top(cmd_list))) {
+ request(); /* Send requests */
+ lst_pop(cmd_list);
+ expected = CODE_OK;
+ switch (c->command) {
+ case CMD_PRINT:
+ if (!formatted) {
+ if (c->comment)
+ fprintf(dict_output, "%s", c->comment);
+ }
+
+ if (cmd_reply.match)
+ client_print_matches(cmd_reply.data, 1, cmd_reply.word);
+ else if (cmd_reply.listed)
+ client_print_listed(cmd_reply.data);
+ else
+ client_print_text(cmd_reply.data, 1);
- if (flush){
- fflush (dict_output);
+ if (flush) {
+ fflush(dict_output);
}
- client_free_text( cmd_reply.data );
+ client_free_text(cmd_reply.data);
cmd_reply.data = NULL;
- cmd_reply.matches = 0;
+ cmd_reply.matches = cmd_reply.match = cmd_reply.listed = 0;
+ expected = cmd_reply.retcode;
+ break;
+ case CMD_DEFPRINT:
+ if (cmd_reply.count) {
+ if (c->flag) {
+ fprintf(dict_output, "%d definition%s found",
+ cmd_reply.count,
+ cmd_reply.count == 1 ? "" : "s");
+ fprintf(dict_output, "\n");
+ }
+ for (i = 0; i < cmd_reply.count; i++) {
+ client_print_definitions(&cmd_reply.defs[i]);
+
+ if (flush) {
+ fflush(dict_output);
+ }
+
+ client_free_text(cmd_reply.defs[i].data);
+ cmd_reply.defs[i].data = NULL;
+ }
+ xfree(cmd_reply.defs);
+ cmd_reply.count = 0;
+
+ } else if (cmd_reply.matches) {
+ fprintf(dict_error,
+ "No definitions found for \"%s\", perhaps you mean:",
+ c->word);
+ fprintf(dict_error, "\n");
+
+ old = dict_output;
+ dict_output = dict_error;
+ client_print_matches(cmd_reply.data, 0, c->word);
+ dict_output = old;
+
+ if (flush) {
+ fflush(dict_output);
+ }
+
+ client_free_text(cmd_reply.data);
+ cmd_reply.data = NULL;
+ cmd_reply.matches = 0;
+
+ set_ex_status(EXST_APPROX_MATCHES);
+ } else {
+ fprintf(dict_error,
+ "No definitions found for \"%s\"\n", c->word);
+
+ set_ex_status(EXST_NO_MATCH);
+ }
+
+ expected = cmd_reply.retcode;
+ break;
+ case CMD_CONNECT:
+ if (!cmd_reply.s)
+ break; /* Connection failed, continue; */
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL, NULL,
+ &cmd_reply.msgid);
+ if (cmd_reply.retcode == CODE_ACCESS_DENIED) {
+ client_close_pager();
+ err_fatal(NULL,
+ "Access to server %s.%s denied when connecting\n",
+ cmd_reply.host, cmd_reply.service);
+ }
+
+ /* */
+ host_connected = c->host;
+ if (c->service)
+ service_connected = c->service;
+ else
+ service_connected = DICT_DEFAULT_SERVICE;
+
+ /* */
+ expected = CODE_HELLO;
+ while (((struct cmd *) lst_top(cmd_list))->command ==
+ CMD_CONNECT)
+ lst_pop(cmd_list);
+
+ break;
+ case CMD_OPTION_MIME:
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ if (cmd_reply.retcode != expected && dbg_test(DBG_VERBOSE))
+ fprintf(dict_error,
+ "Client command gave unexpected status code %d (%s)\n",
+ cmd_reply.retcode,
+ message ? message : "no message");
- set_ex_status (EXST_APPROX_MATCHES);
- } else {
- fprintf( dict_error,
- "No definitions found for \"%s\"\n", c->word );
-
- set_ex_status (EXST_NO_MATCH);
- }
-
- expected = cmd_reply.retcode;
- break;
- case CMD_CONNECT:
- if (!cmd_reply.s) break; /* Connection failed, continue; */
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL, NULL, NULL, NULL,
- &cmd_reply.msgid );
- if (cmd_reply.retcode == CODE_ACCESS_DENIED) {
- client_close_pager();
- err_fatal( NULL,
- "Access to server %s.%s denied when connecting\n",
- cmd_reply.host,
- cmd_reply.service );
- }
-
- /* */
- host_connected = c -> host;
- if (c -> service)
- service_connected = c -> service;
- else
- service_connected = DICT_DEFAULT_SERVICE;
-
- /* */
- expected = CODE_HELLO;
- while (((struct cmd *)lst_top(cmd_list))->command == CMD_CONNECT)
- lst_pop(cmd_list);
-
- break;
- case CMD_OPTION_MIME:
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL, NULL, NULL, NULL, NULL);
- if (cmd_reply.retcode != expected && dbg_test(DBG_VERBOSE))
- fprintf( dict_error, "Client command gave unexpected status code %d (%s)\n",
- cmd_reply.retcode, message ? message : "no message" );
-
- expected = cmd_reply.retcode;
- break;
- case CMD_CLIENT:
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL, NULL, NULL, NULL, NULL);
- if (cmd_reply.retcode != expected && dbg_test(DBG_VERBOSE))
- fprintf( dict_error, "Client command gave unexpected status code %d (%s)\n",
- cmd_reply.retcode, message ? message : "no message" );
+ expected = cmd_reply.retcode;
+ break;
+ case CMD_CLIENT:
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ if (cmd_reply.retcode != expected && dbg_test(DBG_VERBOSE))
+ fprintf(dict_error,
+ "Client command gave unexpected status code %d (%s)\n",
+ cmd_reply.retcode,
+ message ? message : "no message");
/* set_ex_status (cmd_reply.retcode); */
- expected = cmd_reply.retcode;
- break;
- case CMD_AUTH:
- if (!cmd_reply.key || !cmd_reply.user || !cmd_reply.msgid) {
expected = cmd_reply.retcode;
break;
- }
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL, NULL, NULL, NULL, NULL);
- expected = CODE_AUTH_OK;
- if (cmd_reply.retcode == CODE_AUTH_DENIED) {
- err_warning( NULL,
- "Authentication to %s.%s denied\n",
- cmd_reply.host,
- cmd_reply.service );
- expected = CODE_AUTH_DENIED;
- }
- break;
- case CMD_INFO:
- expected = CODE_DATABASE_INFO;
- listed = NULL;
- goto gettext;
- case CMD_SERVER:
- expected = CODE_SERVER_INFO;
- listed = NULL;
- goto gettext;
- case CMD_HELP:
- expected = CODE_HELP;
- listed = NULL;
- goto gettext;
- case CMD_DBS:
- expected = CODE_DATABASE_LIST;
- listed = &cmd_reply.listed;
- goto gettext;
- case CMD_STRATS:
- expected = CODE_STRATEGY_LIST;
- listed = &cmd_reply.listed;
- goto gettext;
- gettext:
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- listed,
- NULL, NULL, NULL, NULL);
- if (cmd_reply.retcode == expected) {
- cmd_reply.data = client_read_text( cmd_reply.s );
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL,NULL,NULL,NULL,NULL);
- expected = CODE_OK;
- }
- break;
- case CMD_DEFINE:
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- &cmd_reply.count,
- NULL, NULL, NULL, NULL );
- if (!client_defines) tim_start( "define" );
- switch (expected = cmd_reply.retcode) {
- case CODE_DEFINITIONS_FOUND:
- cmd_reply.defs = xmalloc(cmd_reply.count*sizeof(struct def));
- expected = CODE_DEFINITION_FOLLOWS;
- for (i = 0; i < cmd_reply.count; i++) {
- ++client_defines;
- cmd_reply.retcode
- = client_read_status( cmd_reply.s,
- &message,
- NULL,
- &cmd_reply.defs[i].word,
- &cmd_reply.defs[i].db,
- &cmd_reply.defs[i].dbname,
- NULL );
- if (cmd_reply.retcode != expected) goto error;
- cmd_reply.defs[i].data = client_read_text( cmd_reply.s );
- }
- expected = CODE_OK;
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL,NULL,NULL,NULL,NULL );
- break;
- case CODE_NO_MATCH:
- PRINTF(DBG_VERBOSE,
- ("No match found for \"%s\" in %s\n",c->word,c->database));
- break;
- case CODE_INVALID_DB:
- fprintf(stderr, "%s is not a valid database, use -D for a list\n",
- c->database );
- set_ex_status (EXST_INVALID_DB);
- break;
- case CODE_NO_DATABASES:
- fprintf( dict_error, "There are no databases currently available\n" );
-
- set_ex_status (EXST_NO_DATABASES);
-
- break;
- default:
- expected = CODE_OK;
- }
- error:
- break;
- case CMD_MATCH:
- cmd_reply.match = 1;
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- &cmd_reply.matches,
- NULL, NULL, NULL, NULL );
- switch (expected = cmd_reply.retcode) {
- case CODE_MATCHES_FOUND:
- cmd_reply.data = client_read_text( cmd_reply.s );
- expected = CODE_OK;
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL,NULL,NULL,NULL,NULL );
- break;
- case CODE_TEMPORARILY_UNAVAILABLE:
- fprintf (stderr,
- "Server temporarily unavailable\n");
-
- set_ex_status (EXST_TEMPORARILY_UNAVAILABLE);
-
- break;
- case CODE_NO_MATCH:
- PRINTF(DBG_VERBOSE,
- ("No match found in %s for \"%s\" using %s\n",
- c->database,c->word,c->strategy));
-
- set_ex_status (EXST_NO_MATCH);
-
- break;
- case CODE_INVALID_DB:
- fprintf( dict_error,
- "%s is not a valid database, use -D for a list\n",
- c->database );
-
- set_ex_status (EXST_INVALID_DB);
-
- break;
- case CODE_INVALID_STRATEGY:
- fprintf( dict_error,
- "%s is not a valid search strategy, use -S for a list\n",
- c->strategy );
-
- set_ex_status (EXST_INVALID_STRATEGY);
-
- break;
- case CODE_NO_DATABASES:
- fprintf( dict_error,
- "There are no databases currently available\n" );
-
- set_ex_status (EXST_NO_DATABASES);
-
- break;
- case CODE_NO_STRATEGIES:
- fprintf( dict_error,
- "There are no search strategies currently available\n" );
-
- set_ex_status (EXST_NO_STRATEGIES);
-
- break;
- default:
- expected = CODE_OK;
- }
- break;
- case CMD_SPELL:
- if (cmd_reply.retcode == CODE_NO_MATCH) {
- prepend_command( make_command( CMD_MATCH,
- c->database, DEF_STRAT, c->word ) );
- }
- expected = cmd_reply.retcode;
- break;
- case CMD_WIND:
- if (cmd_reply.matches) {
- if (!cmd_reply.data)
- err_internal( __func__,
- "%d matches, but no list\n", cmd_reply.matches );
-
- for (i = cmd_reply.matches; i > 0; --i) {
- /* skip MIME header */
- const char *line = lst_nth_get( cmd_reply.data, i );
- arg_List a;
- const char *orig, *s;
- char *escaped, *d;
-
- if (option_mime){
- if (line [0] == 0 ||
- (line [0] == '\r' && line [1] == '\0'))
- {
- break;
- }
- }
-
- /* */
- a = arg_argify( line, 0 );
- if (arg_count(a) != 2)
- err_internal( __func__,
- "MATCH command didn't return 2 args: \"%s\"\n",
- line );
-
- prepend_command( make_command( CMD_DEFPRINT,
- str_find(arg_get(a,0)),
- str_copy(arg_get(a,1)),
- 0 ) );
-
- /* Escape " and \ in word before sending */
- orig = arg_get(a,1);
- escaped = xmalloc(strlen(orig) * 2 + 1);
- for (s = orig, d = escaped; *s;) {
- switch (*s) {
- case '"':
- case '\\':
- *d++ = '\\';
- default:
- *d++ = *s++;
- }
- }
- *d++ = '\0';
- prepend_command( make_command( CMD_DEFINE,
- str_find(arg_get(a,0)),
- str_copy(escaped),
- 0 ) );
- xfree(escaped);
- arg_destroy(a);
- }
- client_free_text( cmd_reply.data );
- cmd_reply.matches = 0;
- } else {
- fprintf( dict_error, "No matches found for \"%s\"", c->word );
- fprintf( dict_error, "\n" );
-
- set_ex_status (EXST_NO_MATCH);
- }
- expected = cmd_reply.retcode;
- break;
- case CMD_CLOSE:
- cmd_reply.retcode = client_read_status( cmd_reply.s,
- &message,
- NULL, NULL, NULL, NULL, NULL);
- expected = CODE_GOODBYE;
- break;
- default:
- err_internal( __func__, "Illegal command %d\n", c->command );
- }
- if (cmd_reply.s && cmd_reply.retcode != expected) {
- client_close_pager();
- unexpected_status_code (expected, cmd_reply.retcode, message);
- }
- PRINTF(DBG_RAW,("* Processed %d\n",c->command));
- xfree(c);
- }
+ case CMD_AUTH:
+ if (!cmd_reply.key || !cmd_reply.user || !cmd_reply.msgid) {
+ expected = cmd_reply.retcode;
+ break;
+ }
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ expected = CODE_AUTH_OK;
+ if (cmd_reply.retcode == CODE_AUTH_DENIED) {
+ err_warning(NULL,
+ "Authentication to %s.%s denied\n",
+ cmd_reply.host, cmd_reply.service);
+ expected = CODE_AUTH_DENIED;
+ }
+ break;
+ case CMD_INFO:
+ expected = CODE_DATABASE_INFO;
+ listed = NULL;
+ goto gettext;
+ case CMD_SERVER:
+ expected = CODE_SERVER_INFO;
+ listed = NULL;
+ goto gettext;
+ case CMD_HELP:
+ expected = CODE_HELP;
+ listed = NULL;
+ goto gettext;
+ case CMD_DBS:
+ expected = CODE_DATABASE_LIST;
+ listed = &cmd_reply.listed;
+ goto gettext;
+ case CMD_STRATS:
+ expected = CODE_STRATEGY_LIST;
+ listed = &cmd_reply.listed;
+ goto gettext;
+ gettext:
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ listed,
+ NULL, NULL, NULL, NULL);
+ if (cmd_reply.retcode == expected) {
+ cmd_reply.data = client_read_text(cmd_reply.s);
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL,
+ NULL, NULL);
+ expected = CODE_OK;
+ }
+ break;
+ case CMD_DEFINE:
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ &cmd_reply.count,
+ NULL, NULL, NULL, NULL);
+ if (!client_defines)
+ tim_start("define");
+ switch (expected = cmd_reply.retcode) {
+ case CODE_DEFINITIONS_FOUND:
+ cmd_reply.defs =
+ xmalloc(cmd_reply.count * sizeof(struct def));
+ expected = CODE_DEFINITION_FOLLOWS;
+ for (i = 0; i < cmd_reply.count; i++) {
+ ++client_defines;
+ cmd_reply.retcode
+ = client_read_status(cmd_reply.s,
+ &message,
+ NULL,
+ &cmd_reply.defs[i].word,
+ &cmd_reply.defs[i].db,
+ &cmd_reply.defs[i].dbname,
+ NULL);
+ if (cmd_reply.retcode != expected)
+ goto error;
+ cmd_reply.defs[i].data = client_read_text(cmd_reply.s);
+ }
+ expected = CODE_OK;
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL,
+ NULL, NULL);
+ break;
+ case CODE_NO_MATCH:
+ PRINTF(DBG_VERBOSE,
+ ("No match found for \"%s\" in %s\n", c->word,
+ c->database));
+ break;
+ case CODE_INVALID_DB:
+ fprintf(stderr,
+ "%s is not a valid database, use -D for a list\n",
+ c->database);
+ set_ex_status(EXST_INVALID_DB);
+ break;
+ case CODE_NO_DATABASES:
+ fprintf(dict_error,
+ "There are no databases currently available\n");
+
+ set_ex_status(EXST_NO_DATABASES);
+
+ break;
+ default:
+ expected = CODE_OK;
+ }
+ error:
+ break;
+ case CMD_MATCH:
+ cmd_reply.match = 1;
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ &cmd_reply.matches,
+ NULL, NULL, NULL, NULL);
+ switch (expected = cmd_reply.retcode) {
+ case CODE_MATCHES_FOUND:
+ cmd_reply.data = client_read_text(cmd_reply.s);
+ expected = CODE_OK;
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL,
+ NULL, NULL);
+ break;
+ case CODE_TEMPORARILY_UNAVAILABLE:
+ fprintf(stderr, "Server temporarily unavailable\n");
+
+ set_ex_status(EXST_TEMPORARILY_UNAVAILABLE);
+
+ break;
+ case CODE_NO_MATCH:
+ PRINTF(DBG_VERBOSE,
+ ("No match found in %s for \"%s\" using %s\n",
+ c->database, c->word, c->strategy));
+
+ set_ex_status(EXST_NO_MATCH);
+
+ break;
+ case CODE_INVALID_DB:
+ fprintf(dict_error,
+ "%s is not a valid database, use -D for a list\n",
+ c->database);
+
+ set_ex_status(EXST_INVALID_DB);
+
+ break;
+ case CODE_INVALID_STRATEGY:
+ fprintf(dict_error,
+ "%s is not a valid search strategy, use -S for a list\n",
+ c->strategy);
+
+ set_ex_status(EXST_INVALID_STRATEGY);
+
+ break;
+ case CODE_NO_DATABASES:
+ fprintf(dict_error,
+ "There are no databases currently available\n");
+
+ set_ex_status(EXST_NO_DATABASES);
+
+ break;
+ case CODE_NO_STRATEGIES:
+ fprintf(dict_error,
+ "There are no search strategies currently available\n");
+
+ set_ex_status(EXST_NO_STRATEGIES);
+
+ break;
+ default:
+ expected = CODE_OK;
+ }
+ break;
+ case CMD_SPELL:
+ if (cmd_reply.retcode == CODE_NO_MATCH) {
+ prepend_command(make_command(CMD_MATCH,
+ c->database, DEF_STRAT,
+ c->word));
+ }
+ expected = cmd_reply.retcode;
+ break;
+ case CMD_WIND:
+ if (cmd_reply.matches) {
+ if (!cmd_reply.data)
+ err_internal(__func__,
+ "%d matches, but no list\n",
+ cmd_reply.matches);
+
+ for (i = cmd_reply.matches; i > 0; --i) {
+ /* skip MIME header */
+ const char *line = lst_nth_get(cmd_reply.data, i);
+ arg_List a;
+ const char *orig, *s;
+ char *escaped, *d;
+
+ if (option_mime) {
+ if (line[0] == 0 ||
+ (line[0] == '\r' && line[1] == '\0')) {
+ break;
+ }
+ }
+
+ /* */
+ a = arg_argify(line, 0);
+ if (arg_count(a) != 2)
+ err_internal(__func__,
+ "MATCH command didn't return 2 args: \"%s\"\n",
+ line);
+
+ prepend_command(make_command(CMD_DEFPRINT,
+ str_find(arg_get(a, 0)),
+ str_copy(arg_get(a, 1)),
+ 0));
+
+ /* Escape " and \ in word before sending */
+ orig = arg_get(a, 1);
+ escaped = xmalloc(strlen(orig) * 2 + 1);
+ for (s = orig, d = escaped; *s;) {
+ switch (*s) {
+ case '"':
+ case '\\':
+ *d++ = '\\';
+ default:
+ *d++ = *s++;
+ }
+ }
+ *d++ = '\0';
+ prepend_command(make_command(CMD_DEFINE,
+ str_find(arg_get(a, 0)),
+ str_copy(escaped), 0));
+ xfree(escaped);
+ arg_destroy(a);
+ }
+ client_free_text(cmd_reply.data);
+ cmd_reply.matches = 0;
+ } else {
+ fprintf(dict_error, "No matches found for \"%s\"",
+ c->word);
+ fprintf(dict_error, "\n");
+
+ set_ex_status(EXST_NO_MATCH);
+ }
+ expected = cmd_reply.retcode;
+ break;
+ case CMD_CLOSE:
+ cmd_reply.retcode = client_read_status(cmd_reply.s,
+ &message,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ expected = CODE_GOODBYE;
+ break;
+ default:
+ err_internal(__func__, "Illegal command %d\n", c->command);
+ }
+ if (cmd_reply.s && cmd_reply.retcode != expected) {
+ client_close_pager();
+ unexpected_status_code(expected, cmd_reply.retcode, message);
+ }
+ PRINTF(DBG_RAW, ("* Processed %d\n", c->command));
+ xfree(c);
+ }
}
#if 0
-static void handler( int sig )
+static void handler(int sig)
{
- const char *name = NULL;
-
- switch (sig) {
- case SIGHUP: name = "SIGHUP"; break;
- case SIGINT: name = "SIGINT"; break;
- case SIGQUIT: name = "SIGQUIT"; break;
- case SIGILL: name = "SIGILL"; break;
- case SIGTRAP: name = "SIGTRAP"; break;
- case SIGTERM: name = "SIGTERM"; break;
- case SIGPIPE: name = "SIGPIPE"; break;
- }
-
- if (name)
- err_fatal( __func__, "Caught %s, exiting\n", name );
- else
- err_fatal( __func__, "Caught signal %d, exiting\n", sig );
-
- exit(0);
-}
-
-static void setsig( int sig, void (*f)(int) )
-{
- struct sigaction sa;
-
- sa.sa_handler = f;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(sig, &sa, NULL);
+ const char *name = NULL;
+
+ switch (sig) {
+ case SIGHUP:
+ name = "SIGHUP";
+ break;
+ case SIGINT:
+ name = "SIGINT";
+ break;
+ case SIGQUIT:
+ name = "SIGQUIT";
+ break;
+ case SIGILL:
+ name = "SIGILL";
+ break;
+ case SIGTRAP:
+ name = "SIGTRAP";
+ break;
+ case SIGTERM:
+ name = "SIGTERM";
+ break;
+ case SIGPIPE:
+ name = "SIGPIPE";
+ break;
+ }
+
+ if (name)
+ err_fatal(__func__, "Caught %s, exiting\n", name);
+ else
+ err_fatal(__func__, "Caught signal %d, exiting\n", sig);
+
+ exit(0);
+}
+
+static void setsig(int sig, void (*f) (int))
+{
+ struct sigaction sa;
+
+ sa.sa_handler = f;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(sig, &sa, NULL);
}
#endif
-static void client_config_print( FILE *stream, lst_List c )
+static void client_config_print(FILE * stream, lst_List c)
{
- FILE *s = stream ? stream : stderr;
- lst_Position p;
- dictServer *e;
-
- printf( "Configuration file:\n" );
- LST_ITERATE(dict_Servers,p,e) {
- if (e->port || e->user || e->secret) {
- fprintf( s, " server %s {\n", e->host );
- if (e->port) fprintf( s, " port %s\n", e->port );
- if (e->user) fprintf( s, " user %s %s\n",
- e->user,
- e->secret ? "*" : "(none)" );
- fprintf( s, " }\n" );
- } else {
- fprintf( s, " server %s\n", e->host );
- }
- }
-}
-
-static const char *id_string (void)
-{
- static char buffer[BUFFERSIZE];
-
- snprintf( buffer, BUFFERSIZE, "%s", DICT_VERSION );
-
- return buffer;
-}
-
-static const char *client_get_banner( void )
-{
- static char *buffer= NULL;
- struct utsname uts;
-
- if (buffer) return buffer;
- uname( &uts );
- buffer = xmalloc(256);
- snprintf( buffer, 256,
- "%s %s/rf on %s %s", err_program_name (), id_string (),
- uts.sysname, uts.release );
- return buffer;
-}
-
-static void banner( FILE *out_stream )
-{
- fprintf( out_stream , "%s\n", client_get_banner() );
- fprintf( out_stream,
- "Copyright 1997-2002 Rickard E. Faith (faith@dict.org)\n" );
- fprintf( out_stream,
- "Copyright 2002-2007 Aleksey Cheusov (vle@gmx.net)\n" );
- fprintf( out_stream, "\n" );
-}
-
-static void license( void )
-{
- static const char *license_msg[] = {
- "This program is free software; you can redistribute it and/or modify it",
- "under the terms of the GNU General Public License as published by the",
- "Free Software Foundation; either version 1, or (at your option) any",
- "later version.",
- "",
- "This program is distributed in the hope that it will be useful, but",
- "WITHOUT ANY WARRANTY; without even the implied warranty of",
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
- "General Public License for more details.",
- "",
- "You should have received a copy of the GNU General Public License along",
- "with this program; if not, write to the Free Software Foundation, Inc.,",
- "675 Mass Ave, Cambridge, MA 02139, USA.",
- 0 };
- const char **p = license_msg;
-
- banner ( stdout );
- while (*p) fprintf( stdout, " %s\n", *p++ );
-}
-
-static void help( FILE *out_stream )
-{
- static const char *help_msg[] = {
- "Usage: dict [options] [word]",
- "Query a dictd server for the definition of a word",
- "",
- "-h --host <server> specify server",
- "-p --port <service> specify port",
- "-d --database <dbname> select a database to search",
- "-m --match match instead of define",
- "-s --strategy <strategy> strategy for matching or defining",
- "-c --config <file> specify configuration file",
- "-C --nocorrect disable attempted spelling correction",
- "-D --dbs show available databases",
- "-S --strats show available search strategies",
- "-H --serverhelp show server help",
- "-i --info <dbname> show information about a database",
- "-I --serverinfo show information about the server",
- "-a --noauth disable authentication",
- "-u --user <username> username for authentication",
- "-k --key <key> shared secret for authentication",
- "-V --version display version information",
- "-L --license display copyright and license information",
- " --help display this help",
- "-v --verbose be verbose",
- "-r --raw trace raw transaction",
- " --debug <flag> set debugging flag",
- " --pipesize <size> specify buffer size for pipelining (256)",
- " --client <text> additional text for client command",
- "-M --mime send OPTION MIME command if server supports it",
- "-f --formatted use strict tabbed format of output",
- 0 };
- const char **p = help_msg;
-
- banner( out_stream );
- while (*p) fprintf( out_stream, "%s\n", *p++ );
-}
-
-int main( int argc, char **argv )
-{
- int c;
- const char *host = NULL;
- const char *service = NULL;
- const char *user = NULL;
- const char *key = NULL;
- const char *database = DEF_DB;
- const char *strategy = DEF_STRAT;
- const char *configFile = NULL;
- const char *word = NULL;
- int doauth = 1;
- int docorrect = 1;
- int offset = 0;
- int i;
- enum { DEFINE = 0x0001,
- MATCH = 0x0002,
- INFO = 0x0010,
- SERVER = 0x0020,
- DBS = 0x0040,
- STRATS = 0x0080,
- HELP = 0x0100,
- OPTION_MIME = 0x0200,
- } function = DEFINE;
- struct option longopts[] = {
- { "host", 1, 0, 'h' },
- { "port", 1, 0, 'p' },
- { "database", 1, 0, 'd' },
- { "info", 1, 0, 'i' },
- { "serverinfo", 0, 0, 'I' },
- { "match", 0, 0, 'm' },
- { "strategy", 1, 0, 's' },
- { "nocorrect", 0, 0, 'C' },
- { "config", 1, 0, 'c' },
- { "dbs", 0, 0, 'D' },
- { "strats", 0, 0, 'S' },
- { "serverhelp", 0, 0, 'H' },
- { "noauth", 0, 0, 'a' },
- { "user", 1, 0, 'u' },
- { "key", 1, 0, 'k' },
- { "version", 0, 0, 'V' },
- { "license", 0, 0, 'L' },
- { "help", 0, 0, 501 },
- { "verbose", 0, 0, 'v' },
- { "raw", 0, 0, 'r' },
- { "pager", 1, 0, 'P' },
- { "debug", 1, 0, 502 },
- { "pipesize", 1, 0, 504 },
- { "client", 1, 0, 505 },
- { "mime", 1, 0, 'M' },
- { "formatted", 0, 0, 'f' },
- { "flush", 0, 0, 'F' },
- { 0, 0, 0, 0 }
- };
-
- dict_output = stdout;
- dict_error = stderr;
-
- maa_init (argv[0]);
-
- dbg_register( DBG_VERBOSE, "verbose" );
- dbg_register( DBG_RAW, "raw" );
- dbg_register( DBG_SCAN, "scan" );
- dbg_register( DBG_PARSE, "parse" );
- dbg_register( DBG_PIPE, "pipe" );
- dbg_register( DBG_SERIAL, "serial" );
- dbg_register( DBG_TIME, "time" );
- dbg_register( DBG_URL, "url" );
+ FILE *s = stream ? stream : stderr;
+ lst_Position p;
+ dictServer *e;
+
+ printf("Configuration file:\n");
+ LST_ITERATE(dict_Servers, p, e) {
+ if (e->port || e->user || e->secret) {
+ fprintf(s, " server %s {\n", e->host);
+ if (e->port)
+ fprintf(s, " port %s\n", e->port);
+ if (e->user)
+ fprintf(s, " user %s %s\n",
+ e->user, e->secret ? "*" : "(none)");
+ fprintf(s, " }\n");
+ } else {
+ fprintf(s, " server %s\n", e->host);
+ }
+ }
+}
+
+static const char *id_string(void)
+{
+ static char buffer[BUFFERSIZE];
+
+ snprintf(buffer, BUFFERSIZE, "%s", DICT_VERSION);
+
+ return buffer;
+}
+
+static const char *client_get_banner(void)
+{
+ static char *buffer = NULL;
+ struct utsname uts;
+
+ if (buffer)
+ return buffer;
+ uname(&uts);
+ buffer = xmalloc(256);
+ snprintf(buffer, 256,
+ "%s %s/rf on %s %s", err_program_name(), id_string(),
+ uts.sysname, uts.release);
+ return buffer;
+}
+
+static void banner(FILE * out_stream)
+{
+ fprintf(out_stream, "%s\n", client_get_banner());
+ fprintf(out_stream,
+ "Copyright 1997-2002 Rickard E. Faith (faith@dict.org)\n");
+ fprintf(out_stream,
+ "Copyright 2002-2007 Aleksey Cheusov (vle@gmx.net)\n");
+ fprintf(out_stream, "\n");
+}
+
+static void license(void)
+{
+ static const char *license_msg[] = {
+ "This program is free software; you can redistribute it and/or modify it",
+ "under the terms of the GNU General Public License as published by the",
+ "Free Software Foundation; either version 1, or (at your option) any",
+ "later version.",
+ "",
+ "This program is distributed in the hope that it will be useful, but",
+ "WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
+ "General Public License for more details.",
+ "",
+ "You should have received a copy of the GNU General Public License along",
+ "with this program; if not, write to the Free Software Foundation, Inc.,",
+ "675 Mass Ave, Cambridge, MA 02139, USA.",
+ 0
+ };
+ const char **p = license_msg;
+
+ banner(stdout);
+ while (*p)
+ fprintf(stdout, " %s\n", *p++);
+}
+
+static void help(FILE * out_stream)
+{
+ static const char *help_msg[] = {
+ "Usage: dict [options] [word]",
+ "Query a dictd server for the definition of a word",
+ "",
+ "-h --host <server> specify server",
+ "-p --port <service> specify port",
+ "-d --database <dbname> select a database to search",
+ "-m --match match instead of define",
+ "-s --strategy <strategy> strategy for matching or defining",
+ "-c --config <file> specify configuration file",
+ "-C --nocorrect disable attempted spelling correction",
+ "-D --dbs show available databases",
+ "-S --strats show available search strategies",
+ "-H --serverhelp show server help",
+ "-i --info <dbname> show information about a database",
+ "-I --serverinfo show information about the server",
+ "-a --noauth disable authentication",
+ "-u --user <username> username for authentication",
+ "-k --key <key> shared secret for authentication",
+ "-V --version display version information",
+ "-L --license display copyright and license information",
+ " --help display this help",
+ "-v --verbose be verbose",
+ "-r --raw trace raw transaction",
+ " --debug <flag> set debugging flag",
+ " --pipesize <size> specify buffer size for pipelining (256)",
+ " --client <text> additional text for client command",
+ "-M --mime send OPTION MIME command if server supports it",
+ "-f --formatted use strict tabbed format of output",
+ 0
+ };
+ const char **p = help_msg;
+
+ banner(out_stream);
+ while (*p)
+ fprintf(out_stream, "%s\n", *p++);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ const char *host = NULL;
+ const char *service = NULL;
+ const char *user = NULL;
+ const char *key = NULL;
+ const char *database = DEF_DB;
+ const char *strategy = DEF_STRAT;
+ const char *configFile = NULL;
+ const char *word = NULL;
+ int doauth = 1;
+ int docorrect = 1;
+ int offset = 0;
+ int i;
+ enum { DEFINE = 0x0001,
+ MATCH = 0x0002,
+ INFO = 0x0010,
+ SERVER = 0x0020,
+ DBS = 0x0040,
+ STRATS = 0x0080,
+ HELP = 0x0100,
+ OPTION_MIME = 0x0200,
+ } function = DEFINE;
+ struct option longopts[] = {
+ {"host", 1, 0, 'h'},
+ {"port", 1, 0, 'p'},
+ {"database", 1, 0, 'd'},
+ {"info", 1, 0, 'i'},
+ {"serverinfo", 0, 0, 'I'},
+ {"match", 0, 0, 'm'},
+ {"strategy", 1, 0, 's'},
+ {"nocorrect", 0, 0, 'C'},
+ {"config", 1, 0, 'c'},
+ {"dbs", 0, 0, 'D'},
+ {"strats", 0, 0, 'S'},
+ {"serverhelp", 0, 0, 'H'},
+ {"noauth", 0, 0, 'a'},
+ {"user", 1, 0, 'u'},
+ {"key", 1, 0, 'k'},
+ {"version", 0, 0, 'V'},
+ {"license", 0, 0, 'L'},
+ {"help", 0, 0, 501},
+ {"verbose", 0, 0, 'v'},
+ {"raw", 0, 0, 'r'},
+ {"pager", 1, 0, 'P'},
+ {"debug", 1, 0, 502},
+ {"pipesize", 1, 0, 504},
+ {"client", 1, 0, 505},
+ {"mime", 1, 0, 'M'},
+ {"formatted", 0, 0, 'f'},
+ {"flush", 0, 0, 'F'},
+ {0, 0, 0, 0}
+ };
+
+ dict_output = stdout;
+ dict_error = stderr;
+
+ maa_init(argv[0]);
+
+ dbg_register(DBG_VERBOSE, "verbose");
+ dbg_register(DBG_RAW, "raw");
+ dbg_register(DBG_SCAN, "scan");
+ dbg_register(DBG_PARSE, "parse");
+ dbg_register(DBG_PIPE, "pipe");
+ dbg_register(DBG_SERIAL, "serial");
+ dbg_register(DBG_TIME, "time");
+ dbg_register(DBG_URL, "url");
- while ((c = getopt_long( argc, argv,
+ while ((c = getopt_long(argc, argv,
"h:p:d:i:Ims:DSHau:c:Ck:VLvrP:MfF",
- longopts, NULL )) != EOF)
- {
- switch (c) {
- case 'h': host = optarg; break;
- case 'p': service = optarg; break;
- case 'd': database = optarg; break;
- case 'i': database = optarg; function |= INFO; break;
- case 'I': function |= SERVER; break;
- case 'm': function &= ~DEFINE; function |= MATCH; break;
- case 's': strategy = optarg; break;
- case 'D': function |= DBS; break;
- case 'S': function |= STRATS; break;
- case 'H': function |= HELP; break;
- case 'M': option_mime = 1; function |= OPTION_MIME; break;
- case 'c': configFile = optarg; break;
- case 'C': docorrect = 0; break;
- case 'a': doauth = 0; break;
- case 'u': user = optarg; break;
- case 'k': key = optarg; break;
- case 'V': banner( stdout ); exit(1); break;
- case 'L': license(); exit(1); break;
- case 'v': dbg_set( "verbose" ); break;
- case 'r': dbg_set( "raw" ); break;
- case 'P':
- if (strcmp (optarg, "-")){
- fprintf (stderr, "Option --pager is now deprecated");
- exit (1);
- }
- break;
- case 505: client_text = optarg; break;
- case 504: client_pipesize = atoi(optarg); break;
- case 502: dbg_set( optarg ); break;
- case 501: help( stdout ); exit(1); break;
- case 'f': formatted = 1; break;
- case 'F': flush = 1; break;
- default: help( stderr ); exit(1); break;
- }
- }
-
- if (optind == argc && (!(function & ~(DEFINE|MATCH)))) {
- banner( stderr );
- fprintf( stderr, "Use --help for help\n" );
- exit(1);
- }
-
- if (client_pipesize > 1000000) client_pipesize = 1000000;
-
- if (dbg_test(DBG_PARSE)) prs_set_debug(1);
- if (dbg_test(DBG_SCAN)) yy_flex_debug = 1;
- else yy_flex_debug = 0;
-
- if (configFile) {
- prs_file_nocpp( configFile );
- } else {
- char b[256];
- char *env = getenv("HOME");
-
- snprintf( b, 256, "%s/%s", env ? env : "./", DICT_RC_NAME );
- PRINTF(DBG_VERBOSE,("Trying %s...\n",b));
- if (!access(b, R_OK)) {
- prs_file_nocpp(b);
- } else {
- PRINTF(DBG_VERBOSE,("Trying %s...\n",
- DICT_CONFIG_PATH DICT_CONFIG_NAME));
- if (!access( DICT_CONFIG_PATH DICT_CONFIG_NAME, R_OK ))
- prs_file_nocpp( DICT_CONFIG_PATH DICT_CONFIG_NAME );
- }
- }
- if (dbg_test(DBG_VERBOSE)) {
- if (dict_Servers) client_config_print( NULL, dict_Servers );
- else fprintf( stderr, "No configuration\n" );
- }
-
- if (optind < argc && !strncmp(argv[optind],"dict://",7)) {
- char *p;
- int state, fin;
- char *s;
+ longopts, NULL)) != EOF) {
+ switch (c) {
+ case 'h':
+ host = optarg;
+ break;
+ case 'p':
+ service = optarg;
+ break;
+ case 'd':
+ database = optarg;
+ break;
+ case 'i':
+ database = optarg;
+ function |= INFO;
+ break;
+ case 'I':
+ function |= SERVER;
+ break;
+ case 'm':
+ function &= ~DEFINE;
+ function |= MATCH;
+ break;
+ case 's':
+ strategy = optarg;
+ break;
+ case 'D':
+ function |= DBS;
+ break;
+ case 'S':
+ function |= STRATS;
+ break;
+ case 'H':
+ function |= HELP;
+ break;
+ case 'M':
+ option_mime = 1;
+ function |= OPTION_MIME;
+ break;
+ case 'c':
+ configFile = optarg;
+ break;
+ case 'C':
+ docorrect = 0;
+ break;
+ case 'a':
+ doauth = 0;
+ break;
+ case 'u':
+ user = optarg;
+ break;
+ case 'k':
+ key = optarg;
+ break;
+ case 'V':
+ banner(stdout);
+ exit(1);
+ break;
+ case 'L':
+ license();
+ exit(1);
+ break;
+ case 'v':
+ dbg_set("verbose");
+ break;
+ case 'r':
+ dbg_set("raw");
+ break;
+ case 'P':
+ if (strcmp(optarg, "-")) {
+ fprintf(stderr, "Option --pager is now deprecated");
+ exit(1);
+ }
+ break;
+ case 505:
+ client_text = optarg;
+ break;
+ case 504:
+ client_pipesize = atoi(optarg);
+ break;
+ case 502:
+ dbg_set(optarg);
+ break;
+ case 501:
+ help(stdout);
+ exit(1);
+ break;
+ case 'f':
+ formatted = 1;
+ break;
+ case 'F':
+ flush = 1;
+ break;
+ default:
+ help(stderr);
+ exit(1);
+ break;
+ }
+ }
+
+ if (optind == argc && (!(function & ~(DEFINE | MATCH)))) {
+ banner(stderr);
+ fprintf(stderr, "Use --help for help\n");
+ exit(1);
+ }
+
+ if (client_pipesize > 1000000)
+ client_pipesize = 1000000;
+
+ if (dbg_test(DBG_PARSE))
+ prs_set_debug(1);
+ if (dbg_test(DBG_SCAN))
+ yy_flex_debug = 1;
+ else
+ yy_flex_debug = 0;
+
+ if (configFile) {
+ prs_file_nocpp(configFile);
+ } else {
+ char b[256];
+ char *env = getenv("HOME");
+
+ snprintf(b, 256, "%s/%s", env ? env : "./", DICT_RC_NAME);
+ PRINTF(DBG_VERBOSE, ("Trying %s...\n", b));
+ if (!access(b, R_OK)) {
+ prs_file_nocpp(b);
+ } else {
+ PRINTF(DBG_VERBOSE, ("Trying %s...\n",
+ DICT_CONFIG_PATH DICT_CONFIG_NAME));
+ if (!access(DICT_CONFIG_PATH DICT_CONFIG_NAME, R_OK))
+ prs_file_nocpp(DICT_CONFIG_PATH DICT_CONFIG_NAME);
+ }
+ }
+ if (dbg_test(DBG_VERBOSE)) {
+ if (dict_Servers)
+ client_config_print(NULL, dict_Servers);
+ else
+ fprintf(stderr, "No configuration\n");
+ }
+
+ if (optind < argc && !strncmp(argv[optind], "dict://", 7)) {
+ char *p;
+ int state, fin;
+ char *s;
/* dict://<user>:<passphrase>@<host>:<port>/d:<word>:<database>:<n>
000000 111111111111 222222 333333 4 555555 6666666666 777
@@ -1489,213 +1641,303 @@ int main( int argc, char **argv )
*/
- for (s = p = argv[optind] + 7, state = 0, fin = 0; !fin; ++p) {
- switch (*p) {
- case '\0': ++fin;
- case ':':
- switch (state) {
- case 0: *p = '\0'; host = user = cpy(s); ++state; s=p+1; break;
- case 2: *p = '\0'; host = cpy(s); ++state; s=p+1; break;
- case 4:
- if (s == p - 1) {
- if (*s == 'd') function = DEFINE;
- else if (*s == 'm') function = MATCH;
- else {
- PRINTF(DBG_URL,("State = %d, s = %s\n",state,s));
- client_close_pager();
- err_fatal( NULL, "Parse error at %s\n", p );
- }
- ++state; s=p+1; break;
- } else {
- PRINTF(DBG_URL,("State = %d, s = %s\n",state,s));
- client_close_pager();
- err_fatal( NULL, "Parse error at %s\n", p );
- }
- break;
- case 5: *p = '\0'; word = cpy(s); ++state; s=p+1; break;
- case 6: *p = '\0'; database = cpy(s); ++state; s=p+1; break;
- case 7: *p = '\0';
- if (function == DEFINE) offset = atoi(s);
- else strategy = cpy(s);
- ++state; s=p+1; break;
- case 8: *p = '\0';
- if (function == MATCH) offset = atoi(s); ++state; s=p+1; break;
- /* FALLTHROUGH */
- default:
- PRINTF(DBG_URL,("State = %d, s = %s\n",state,s));
- client_close_pager();
- err_fatal( NULL, "Parse error at %s\n", p );
+ for (s = p = argv[optind] + 7, state = 0, fin = 0; !fin; ++p) {
+ switch (*p) {
+ case '\0':
+ ++fin;
+ case '[':
+ state = 32;
+ s = p + 1;
+ break;
+ case ']':
+ *p = '\0';
+ host = cpy(s);
+ state = 33;
+ s = p + 1;
+ break;
+ case ':':
+ switch (state) {
+ case 32:
+ continue;
+ case 33:
+ state = 1;
+ s = p + 1;
+ break;
+ case 0:
+ *p = '\0';
+ host = user = cpy(s);
+ ++state;
+ s = p + 1;
+ break;
+ case 2:
+ *p = '\0';
+ host = cpy(s);
+ ++state;
+ s = p + 1;
+ break;
+ case 4:
+ if (s == p - 1) {
+ if (*s == 'd')
+ function = DEFINE;
+ else if (*s == 'm')
+ function = MATCH;
+ else {
+ PRINTF(DBG_URL,
+ ("State = %d, s = %s\n", state, s));
+ client_close_pager();
+ err_fatal(NULL, "Parse error at %s\n", p);
+ }
+ ++state;
+ s = p + 1;
+ break;
+ } else {
+ PRINTF(DBG_URL,
+ ("State = %d, s = %s\n", state, s));
+ client_close_pager();
+ err_fatal(NULL, "Parse error at %s\n", p);
+ }
+ break;
+ case 5:
+ *p = '\0';
+ word = cpy(s);
+ ++state;
+ s = p + 1;
+ break;
+ case 6:
+ *p = '\0';
+ database = cpy(s);
+ ++state;
+ s = p + 1;
+ break;
+ case 7:
+ *p = '\0';
+ if (function == DEFINE)
+ offset = atoi(s);
+ else
+ strategy = cpy(s);
+ ++state;
+ s = p + 1;
+ break;
+ case 8:
+ *p = '\0';
+ if (function == MATCH)
+ offset = atoi(s);
+ ++state;
+ s = p + 1;
+ break;
+ /* FALLTHROUGH */
+ default:
+ PRINTF(DBG_URL, ("State = %d, s = %s\n", state, s));
+ client_close_pager();
+ err_fatal(NULL, "Parse error at %s\n", p);
+ }
+ break;
+ case '@':
+ switch (state) {
+ case 1:
+ *p = '\0';
+ key = xstrdup(s);
+ ++state;
+ s = p + 1;
+ break;
+ default:
+ PRINTF(DBG_URL, ("State = %d, s = %s\n", state, s));
+ client_close_pager();
+ err_fatal(NULL, "Parse error at %s\n", p);
+ }
+ break;
+ case '/':
+ switch (state) {
+ case 0:
+ *p = '\0';
+ host = xstrdup(s);
+ state = 4;
+ s = p + 1;
+ break;
+ case 1:
+ case 3:
+ *p = '\0';
+ service = xstrdup(s);
+ state = 4;
+ s = p + 1;
+ break;
+ case 2:
+ *p = '\0';
+ host = xstrdup(s);
+ state = 4;
+ s = p + 1;
+ break;
+ case 33:
+ state = 4;
+ s = p + 1;
+ break;
+ default:
+ PRINTF(DBG_URL, ("State = %d, s = %s\n", state, s));
+ client_close_pager();
+ err_fatal(NULL, "Parse error at %s\n", p);
+ }
+ break;
}
- break;
- case '@':
- switch (state) {
- case 1: *p = '\0'; key = xstrdup(s); ++state; s=p+1; break;
- default:
- PRINTF(DBG_URL,("State = %d, s = %s\n",state,s));
- client_close_pager();
- err_fatal( NULL, "Parse error at %s\n", p );
- }
- break;
- case '/':
- switch (state) {
- case 0: *p = '\0'; host = xstrdup(s); state = 4; s=p+1; break;
- case 1: *p = '\0'; service = xstrdup(s); state = 4; s=p+1; break;
- case 2: *p = '\0'; host = xstrdup(s); state = 4; s=p+1; break;
- default:
- PRINTF(DBG_URL,("State = %d, s = %s\n",state,s));
- client_close_pager();
- err_fatal( NULL, "Parse error at %s\n", p );
- }
- break;
- }
- }
-
- if (!key) user = NULL;
- if (!database) database = DEF_DB;
- if (!strategy) strategy = DEF_STRAT;
-
- if (dbg_test(DBG_URL)) {
- printf( "user = %s, passphrase = %s\n",
- user ? user : "(null)", key ? key : "(null)" );
- printf( "host = %s, port = %s\n",
- host ? host : "(null)", service ? service : "(null)" );
- printf( "word = %s, database = %s, strategy = %s\n",
- word ? word : "(null)",
- strategy ? strategy : "(null)",
- database ? database : "(null)" );
- }
- if (host && !host[0]) { /* Empty host causes default to be used. */
- xfree((void *)host);
- host = NULL;
- }
- }
+ }
+ if (!key)
+ user = NULL;
+ if (!database)
+ database = DEF_DB;
+ if (!strategy)
+ strategy = DEF_STRAT;
+
+ if (dbg_test(DBG_URL)) {
+ printf("user = %s, passphrase = %s\n",
+ user ? user : "(null)", key ? key : "(null)");
+ printf("host = %s, port = %s\n",
+ host ? host : "(null)", service ? service : "(null)");
+ printf("word = %s, database = %s, strategy = %s\n",
+ word ? word : "(null)",
+ strategy ? strategy : "(null)",
+ database ? database : "(null)");
+ }
+ if (host && !host[0]) { /* Empty host causes default to be used. */
+ xfree((void *) host);
+ host = NULL;
+ }
+ }
#if 0
- setsig(SIGHUP, handler);
- setsig(SIGINT, handler);
- setsig(SIGQUIT, handler);
- setsig(SIGILL, handler);
- setsig(SIGTRAP, handler);
- setsig(SIGTERM, handler);
- setsig(SIGPIPE, handler);
+ setsig(SIGHUP, handler);
+ setsig(SIGINT, handler);
+ setsig(SIGQUIT, handler);
+ setsig(SIGILL, handler);
+ setsig(SIGTRAP, handler);
+ setsig(SIGTERM, handler);
+ setsig(SIGPIPE, handler);
#endif
- fflush(stdout);
- fflush(stderr);
+ fflush(stdout);
+ fflush(stderr);
- tim_start("total");
+ tim_start("total");
- if (host) {
- append_command( make_command( CMD_CONNECT, host, service, user, key ) );
- } else {
- lst_Position p;
- dictServer *s;
-
- if (dict_Servers) {
- LST_ITERATE(dict_Servers,p,s) {
- append_command( make_command( CMD_CONNECT,
- s->host,
- s->port,
- s->user,
- s->secret ) );
- }
+ if (host) {
+ append_command(make_command
+ (CMD_CONNECT, host, service, user, key));
+ } else {
+ lst_Position p;
+ dictServer *s;
+
+ if (dict_Servers) {
+ LST_ITERATE(dict_Servers, p, s) {
+ append_command(make_command(CMD_CONNECT,
+ s->host,
+ s->port, s->user, s->secret));
+ }
#ifdef USE_DICT_ORG
- }
- append_command(make_command(CMD_CONNECT,"dict.org", NULL,user,key));
- append_command(make_command(CMD_CONNECT,"alt0.dict.org",NULL,user,key));
+ }
+ append_command(make_command
+ (CMD_CONNECT, "dict.org", NULL, user, key));
+ append_command(make_command
+ (CMD_CONNECT, "alt0.dict.org", NULL, user, key));
#else
- }else{
- fprintf (stderr, "'dict.conf' doesn't specify any dict server\n");
- exit (1);
- }
+ } else {
+ fprintf(stderr,
+ "'dict.conf' doesn't specify any dict server\n");
+ exit(1);
+ }
#endif
- }
- append_command( make_command( CMD_CLIENT, client_get_banner() ) );
- if (doauth) append_command( make_command( CMD_AUTH ) );
- if (function & OPTION_MIME) {
- append_command( make_command( CMD_OPTION_MIME ) );
- append_command( make_command( CMD_PRINT, NULL ) );
- }
- if (function & INFO) {
- append_command( make_command( CMD_INFO, database ) );
- append_command( make_command( CMD_PRINT, NULL ) );
- }
- if (function & SERVER) {
- append_command( make_command( CMD_SERVER ) );
- append_command( make_command( CMD_PRINT, NULL ) );
- }
- if (function & DBS) {
- append_command( make_command( CMD_DBS ) );
- append_command( make_command( CMD_PRINT, "Databases available:\n" ) );
- }
- if (function & STRATS) {
- append_command( make_command( CMD_STRATS ) );
- append_command( make_command( CMD_PRINT, "Strategies available:\n" ) );
- }
- if (function & HELP) {
- append_command( make_command( CMD_HELP ) );
- append_command( make_command( CMD_PRINT, "Server help:\n" ) );
- }
-
- if (function & MATCH) {
- if (word) {
- append_command( make_command( CMD_MATCH, database, strategy, word ) );
- append_command( make_command( CMD_PRINT, NULL ) );
- } else {
- for (i = optind; i < argc; i++) {
- append_command( make_command( CMD_MATCH,
- database, strategy, argv[i] ) );
- append_command( make_command( CMD_PRINT, NULL ) );
- }
- }
- } else if (function & DEFINE) {
- if (word) {
- append_command( make_command( CMD_DEFINE, database, word ) );
- append_command( make_command( CMD_DEFPRINT, database, word, 1 ) );
- } else {
- for (i = optind; i < argc; i++) {
- if (!strcmp(strategy, DEF_STRAT)) {
- append_command( make_command( CMD_DEFINE, database, argv[i] ) );
- if (docorrect)
- append_command( make_command( CMD_SPELL, database, argv[i]));
- append_command( make_command(CMD_DEFPRINT,database,argv[i],1) );
- } else {
- append_command( make_command( CMD_MATCH,
- database, strategy, argv[i] ) );
- append_command( make_command( CMD_WIND,
- database, strategy, argv[i] ) );
- }
- }
- }
- }
- append_command( make_command( CMD_CLOSE ) );
-
- if (!dbg_test(DBG_VERBOSE|DBG_TIME)) client_open_pager();
- process();
- client_close_pager();
-
- if (dbg_test(DBG_TIME)) {
- fprintf( dict_output, "\n" );
- tim_stop("total");
- if (client_defines) {
- tim_stop("define");
- fprintf( stderr,
- "* %ld definitions in %.2fr %.2fu %.2fs"
- " => %.1f d/sec\n",
- client_defines,
- tim_get_real( "define" ),
- tim_get_user( "define" ),
- tim_get_system( "define" ),
- client_defines / tim_get_real( "define" ) );
- }
- fprintf( stderr,
- "* %ld bytes total in %.2fr %.2fu %.2fs => %.0f bps\n",
- client_bytes,
- tim_get_real( "total" ),
- tim_get_user( "total" ),
- tim_get_system( "total" ),
- client_bytes / tim_get_real( "total" ) );
- }
+ }
+ append_command(make_command(CMD_CLIENT, client_get_banner()));
+ if (doauth)
+ append_command(make_command(CMD_AUTH));
+ if (function & OPTION_MIME) {
+ append_command(make_command(CMD_OPTION_MIME));
+ append_command(make_command(CMD_PRINT, NULL));
+ }
+ if (function & INFO) {
+ append_command(make_command(CMD_INFO, database));
+ append_command(make_command(CMD_PRINT, NULL));
+ }
+ if (function & SERVER) {
+ append_command(make_command(CMD_SERVER));
+ append_command(make_command(CMD_PRINT, NULL));
+ }
+ if (function & DBS) {
+ append_command(make_command(CMD_DBS));
+ append_command(make_command(CMD_PRINT, "Databases available:\n"));
+ }
+ if (function & STRATS) {
+ append_command(make_command(CMD_STRATS));
+ append_command(make_command(CMD_PRINT, "Strategies available:\n"));
+ }
+ if (function & HELP) {
+ append_command(make_command(CMD_HELP));
+ append_command(make_command(CMD_PRINT, "Server help:\n"));
+ }
+
+ if (function & MATCH) {
+ if (word) {
+ append_command(make_command
+ (CMD_MATCH, database, strategy, word));
+ append_command(make_command(CMD_PRINT, NULL));
+ } else {
+ for (i = optind; i < argc; i++) {
+ append_command(make_command(CMD_MATCH,
+ database, strategy, argv[i]));
+ append_command(make_command(CMD_PRINT, NULL));
+ }
+ }
+ } else if (function & DEFINE) {
+ if (word) {
+ append_command(make_command(CMD_DEFINE, database, word));
+ append_command(make_command(CMD_DEFPRINT, database, word, 1));
+ } else {
+ for (i = optind; i < argc; i++) {
+ if (!strcmp(strategy, DEF_STRAT)) {
+ append_command(make_command
+ (CMD_DEFINE, database, argv[i]));
+ if (docorrect)
+ append_command(make_command
+ (CMD_SPELL, database, argv[i]));
+ append_command(make_command
+ (CMD_DEFPRINT, database, argv[i], 1));
+ } else {
+ append_command(make_command(CMD_MATCH,
+ database, strategy,
+ argv[i]));
+ append_command(make_command
+ (CMD_WIND, database, strategy,
+ argv[i]));
+ }
+ }
+ }
+ }
+ append_command(make_command(CMD_CLOSE));
+
+ if (!dbg_test(DBG_VERBOSE | DBG_TIME))
+ client_open_pager();
+ process();
+ client_close_pager();
+
+ if (dbg_test(DBG_TIME)) {
+ fprintf(dict_output, "\n");
+ tim_stop("total");
+ if (client_defines) {
+ tim_stop("define");
+ fprintf(stderr,
+ "* %ld definitions in %.2fr %.2fu %.2fs"
+ " => %.1f d/sec\n",
+ client_defines,
+ tim_get_real("define"),
+ tim_get_user("define"),
+ tim_get_system("define"),
+ client_defines / tim_get_real("define"));
+ }
+ fprintf(stderr,
+ "* %ld bytes total in %.2fr %.2fu %.2fs => %.0f bps\n",
+ client_bytes,
+ tim_get_real("total"),
+ tim_get_user("total"),
+ tim_get_system("total"),
+ client_bytes / tim_get_real("total"));
+ }
- return ex_status;
+ return ex_status;
}
--- a/dictd.h
+++ b/dictd.h
@@ -42,9 +42,9 @@
*/
extern const char *site_info;
-extern int site_info_no_banner;
-extern int site_info_no_uptime;
-extern int site_info_no_dblist;
+extern int site_info_no_banner;
+extern int site_info_no_uptime;
+extern int site_info_no_dblist;
extern const char *daemon_service;
extern int client_delay;
@@ -79,59 +79,60 @@ extern int bind_to_set;
-extern void dict_disable_strat (dictDatabase *db, const char* strat);
+extern void dict_disable_strat(dictDatabase * db, const char *strat);
-extern void dict_dump_list( lst_List list );
-extern void dict_destroy_list( lst_List list );
+extern void dict_dump_list(lst_List list);
+extern void dict_destroy_list(lst_List list);
-extern int dict_destroy_datum( const void *datum );
+extern int dict_destroy_datum(const void *datum);
#ifdef USE_PLUGIN
-extern int dict_plugin_open (dictDatabase *db);
-extern void dict_plugin_close (dictDatabase *db);
+extern int dict_plugin_open(dictDatabase * db);
+extern void dict_plugin_close(dictDatabase * db);
#endif
/* dictd.c */
-extern void set_minimal (void);
+extern void set_minimal(void);
-extern void dict_initsetproctitle( int argc, char **argv, char **envp );
-extern void dict_setproctitle( const char *format, ... );
-extern const char *dict_format_time( double t );
-extern const char *dict_get_hostname( void );
-extern const char *dict_get_banner( int shortFlag );
-
-extern dictConfig *DictConfig; /* GLOBAL VARIABLE */
-extern int _dict_comparisons; /* GLOBAL VARIABLE */
-extern int _dict_forks; /* GLOBAL VARIABLE */
+extern void dict_initsetproctitle(int argc, char **argv, char **envp);
+extern void dict_setproctitle(const char *format, ...);
+extern const char *dict_format_time(double t);
+extern const char *dict_get_hostname(void);
+extern const char *dict_get_banner(int shortFlag);
+
+extern dictConfig *DictConfig; /* GLOBAL VARIABLE */
+extern int _dict_comparisons; /* GLOBAL VARIABLE */
+extern int _dict_forks; /* GLOBAL VARIABLE */
extern const char *locale;
extern const char *locale;
-extern int inetd; /* 1 if --inetd is applied, 0 otherwise */
+extern int inetd; /* 1 if --inetd is applied, 0 otherwise */
/*
If the filename doesn't start with / or .,
it is prepended with DICT_DIR
*/
-extern const char *postprocess_dict_filename (const char *fn);
+extern const char *postprocess_dict_filename(const char *fn);
/*
If the filename doesn't start with / or .,
it is prepended with PLUGIN_DIR
*/
-extern const char *postprocess_plugin_filename (const char *fn);
+extern const char *postprocess_plugin_filename(const char *fn);
/* daemon.c */
-extern int dict_daemon( int s, struct sockaddr_in *csin, int error );
-extern int dict_inetd( int error );
-extern void daemon_terminate( int sig, const char *name );
+extern int dict_daemon(int s, struct sockaddr_storage *csin, char ***argv0,
+ int delay, int error);
+extern int dict_inetd(int error);
+extern void daemon_terminate(int sig, const char *name);
/* */
extern int utf8_mode;
extern int stdin2stdout_mode;
/* dmalloc must be last */
#ifdef DMALLOC_FUNC_CHECK
-# include "dmalloc.h"
+#include "dmalloc.h"
#endif
#endif
--- a/daemon.c
+++ b/daemon.c
@@ -2,17 +2,17 @@
* Created: Fri Feb 28 18:17:56 1997 by faith@dict.org
* Copyright 1997, 1998, 1999, 2000, 2002 Rickard E. Faith (faith@dict.org)
* Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
- *
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 1, or (at your option) any
* later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -30,1579 +30,1652 @@
#include <ctype.h>
#include <setjmp.h>
-int stdin2stdout_mode = 0; /* copy stdin to stdout ( dict_dictd function ) */
+int stdin2stdout_mode = 0; /* copy stdin to stdout ( dict_dictd function ) */
-static int _dict_defines, _dict_matches;
-static int daemonS_in = 0;
-static int daemonS_out = 1;
-static const char *daemonHostname = NULL;
-static const char *daemonIP = NULL;
-static int daemonPort = -1;
-static char daemonStamp[256] = "";
-static jmp_buf env;
-
-static int daemonMime;
-
-static void daemon_define( const char *cmdline, int argc, const char **argv );
-static void daemon_match( const char *cmdline, int argc, const char **argv );
-static void daemon_show_db( const char *cmdline, int argc, const char **argv );
-static void daemon_show_strat( const char *cmdline, int argc, const char **argv );
-void daemon_show_info( const char *cmdline, int argc, const char **argv );
-static void daemon_show_server( const char *cmdline, int argc, const char **argv );
-static void daemon_show( const char *cmdline, int argc, const char **argv );
-static void daemon_option_mime( const char *cmdline, int argc, const char **argv );
-static void daemon_option( const char *cmdline, int argc, const char **argv );
-static void daemon_client( const char *cmdline, int argc, const char **argv );
-static void daemon_auth( const char *cmdline, int argc, const char **argv );
-static void daemon_status( const char *cmdline, int argc, const char **argv );
-static void daemon_help( const char *cmdline, int argc, const char **argv );
-static void daemon_quit( const char *cmdline, int argc, const char **argv );
+static int _dict_defines, _dict_matches;
+static int daemonS_in = 0;
+static int daemonS_out = 1;
+static const char *daemonHostname = NULL;
+static const char *daemonIP = NULL;
+static int daemonPort = -1;
+static char daemonStamp[256] = "";
+static jmp_buf env;
+
+static int daemonMime;
+
+static void daemon_define(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_match(const char *cmdline, int argc, const char **argv);
+static void daemon_show_db(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_show_strat(const char *cmdline, int argc,
+ const char **argv);
+void daemon_show_info(const char *cmdline, int argc, const char **argv);
+static void daemon_show_server(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_show(const char *cmdline, int argc, const char **argv);
+static void daemon_option_mime(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_option(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_client(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_auth(const char *cmdline, int argc, const char **argv);
+static void daemon_status(const char *cmdline, int argc,
+ const char **argv);
+static void daemon_help(const char *cmdline, int argc, const char **argv);
+static void daemon_quit(const char *cmdline, int argc, const char **argv);
#define MAXARGCS 3
static struct {
- int argc;
- const char *name[MAXARGCS];
- void (*f)( const char *cmdline, int argc, const char **argv );
+ int argc;
+ const char *name[MAXARGCS];
+ void (*f) (const char *cmdline, int argc, const char **argv);
} commandInfo[] = {
- { 1, {"define"}, daemon_define },
- { 1, {"d"}, daemon_define },
- { 1, {"match"}, daemon_match },
- { 1, {"m"}, daemon_match },
- { 2, {"show", "db"}, daemon_show_db },
- { 2, {"show", "databases"}, daemon_show_db },
- { 2, {"show", "strat"}, daemon_show_strat },
- { 2, {"show", "strategies"}, daemon_show_strat },
- { 2, {"show", "info"}, daemon_show_info },
- { 2, {"show", "server"}, daemon_show_server },
- { 1, {"show"}, daemon_show },
- { 2, {"option", "mime"}, daemon_option_mime },
- { 1, {"option"}, daemon_option },
- { 1, {"client"}, daemon_client },
- { 1, {"auth"}, daemon_auth },
- { 1, {"status"}, daemon_status },
- { 1, {"s"}, daemon_status },
- { 1, {"help"}, daemon_help },
- { 1, {"h"}, daemon_help },
- { 1, {"quit"}, daemon_quit },
- { 1, {"q"}, daemon_quit },
-};
+ {
+ 1, {
+ "define"}, daemon_define}, {
+ 1, {
+ "d"}, daemon_define}, {
+ 1, {
+ "match"}, daemon_match}, {
+ 1, {
+ "m"}, daemon_match}, {
+ 2, {
+ "show", "db"}, daemon_show_db}, {
+ 2, {
+ "show", "databases"}, daemon_show_db}, {
+ 2, {
+ "show", "strat"}, daemon_show_strat}, {
+ 2, {
+ "show", "strategies"}, daemon_show_strat}, {
+ 2, {
+ "show", "info"}, daemon_show_info}, {
+ 2, {
+ "show", "server"}, daemon_show_server}, {
+ 1, {
+ "show"}, daemon_show}, {
+ 2, {
+ "option", "mime"}, daemon_option_mime}, {
+ 1, {
+ "option"}, daemon_option}, {
+ 1, {
+ "client"}, daemon_client}, {
+ 1, {
+ "auth"}, daemon_auth}, {
+ 1, {
+ "status"}, daemon_status}, {
+ 1, {
+ "s"}, daemon_status}, {
+ 1, {
+ "help"}, daemon_help}, {
+ 1, {
+ "h"}, daemon_help}, {
+ 1, {
+ "quit"}, daemon_quit}, {
+ 1, {
+"q"}, daemon_quit},};
+
#define COMMANDS (sizeof(commandInfo)/sizeof(commandInfo[0]))
-static void *(lookup_command)( int argc, const char **argv )
-{
- size_t i;
- int j;
- int err;
-
- for (i = 0; i < COMMANDS; i++) {
- if (argc >= commandInfo[i].argc) {
- for (err = 0, j = 0; j < commandInfo[i].argc; j++) {
- if (strcasecmp(argv[j], commandInfo[i].name[j])) {
- err = 1;
- break;
+static void *(lookup_command) (int argc, const char **argv) {
+ size_t i;
+ int j;
+ int err;
+
+ for (i = 0; i < COMMANDS; i++) {
+ if (argc >= commandInfo[i].argc) {
+ for (err = 0, j = 0; j < commandInfo[i].argc; j++) {
+ if (strcasecmp(argv[j], commandInfo[i].name[j])) {
+ err = 1;
+ break;
+ }
}
- }
- if (!err) return commandInfo[i].f;
- }
- }
- return NULL;
+ if (!err)
+ return commandInfo[i].f;
+ }
+ }
+ return NULL;
}
static unsigned long daemon_compute_mask(int bits)
{
- unsigned long mask = 0xffffffff;
-
- if (bits < 1) return 0;
- if (bits < 32) mask -= (1 << (32-bits)) - 1;
- return mask;
-}
-
-static void daemon_log( int type, const char *format, ... )
-{
- va_list ap;
- char buf[8*1024];
- char *buf2;
- size_t len;
- char *s, *d;
- int c;
- char marker = '?';
-
- switch (type) {
- case DICT_LOG_TERM:
- if (!flg_test(LOG_STATS)) return; marker = 'I'; break;
- case DICT_LOG_TRACE:
- if (!flg_test(LOG_SERVER)) return; marker = 'I'; break;
- case DICT_LOG_CLIENT:
- if (!flg_test(LOG_CLIENT)) return; marker = 'C'; break;
- case DICT_LOG_CONNECT:
- if (!flg_test(LOG_CONNECT)) return; marker = 'K'; break;
- case DICT_LOG_DEFINE:
- if (!flg_test(LOG_FOUND)) return; marker = 'D'; break;
- case DICT_LOG_MATCH:
- if (!flg_test(LOG_FOUND)) return; marker = 'M'; break;
- case DICT_LOG_NOMATCH:
- if (!flg_test(LOG_NOTFOUND)) return; marker = 'N'; break;
- case DICT_LOG_COMMAND:
- if (!flg_test(LOG_COMMAND)) return; marker = 'T'; break;
- case DICT_LOG_AUTH:
- if (!flg_test(LOG_AUTH)) return; marker = 'A'; break;
- }
-
- if (dbg_test(DBG_PORT))
- snprintf(
- buf, sizeof (buf)/2,
- ":%c: %s:%d ", marker, daemonHostname, daemonPort );
- else if (flg_test(LOG_HOST))
- snprintf(
- buf, sizeof (buf)/2,
- ":%c: %s ", marker, daemonHostname );
- else
- snprintf(
- buf, sizeof (buf)/2,
- ":%c: ", marker );
-
- len = strlen( buf );
-
- va_start( ap, format );
- vsnprintf( buf+len, sizeof (buf)/2-len, format, ap );
- va_end( ap );
- len = strlen( buf );
-
- if (len >= sizeof (buf)/2) {
- log_info( ":E: buffer overflow (%d)\n", len );
- buf[2048] = '\0';
- len = strlen(buf);
- }
-
- buf2 = alloca( 3*(len+3) );
-
- for (s = buf, d = buf2; *s; s++) {
- c = (unsigned char)*s;
- if (c == '\t') *d++ = ' ';
- else if (c == '\n') *d++ = c;
- else {
- if (c < 32) { *d++ = '^'; *d++ = c + 64; }
- else if (c == 127) { *d++ = '^'; *d++ = '?'; }
- else *d++ = c;
- }
- }
- *d = '\0';
- log_info( "%s", buf2 );
+ unsigned long mask = 0xffffffff;
- if (d != buf2) d[-1] = '\0'; /* kill newline */
- dict_setproctitle( "dictd %s", buf2 );
+ if (bits < 1)
+ return 0;
+ if (bits < 32)
+ mask -= (1 << (32 - bits)) - 1;
+ return mask;
+}
+
+static void daemon_log(int type, const char *format, ...)
+{
+ va_list ap;
+ char buf[8 * 1024];
+ char *buf2;
+ size_t len;
+ char *s, *d;
+ int c;
+ char marker = '?';
+
+ switch (type) {
+ case DICT_LOG_TERM:
+ if (!flg_test(LOG_STATS))
+ return;
+ marker = 'I';
+ break;
+ case DICT_LOG_TRACE:
+ if (!flg_test(LOG_SERVER))
+ return;
+ marker = 'I';
+ break;
+ case DICT_LOG_CLIENT:
+ if (!flg_test(LOG_CLIENT))
+ return;
+ marker = 'C';
+ break;
+ case DICT_LOG_CONNECT:
+ if (!flg_test(LOG_CONNECT))
+ return;
+ marker = 'K';
+ break;
+ case DICT_LOG_DEFINE:
+ if (!flg_test(LOG_FOUND))
+ return;
+ marker = 'D';
+ break;
+ case DICT_LOG_MATCH:
+ if (!flg_test(LOG_FOUND))
+ return;
+ marker = 'M';
+ break;
+ case DICT_LOG_NOMATCH:
+ if (!flg_test(LOG_NOTFOUND))
+ return;
+ marker = 'N';
+ break;
+ case DICT_LOG_COMMAND:
+ if (!flg_test(LOG_COMMAND))
+ return;
+ marker = 'T';
+ break;
+ case DICT_LOG_AUTH:
+ if (!flg_test(LOG_AUTH))
+ return;
+ marker = 'A';
+ break;
+ }
+
+ if (dbg_test(DBG_PORT))
+ snprintf(buf, sizeof(buf) / 2,
+ ":%c: %s:%d ", marker, daemonHostname, daemonPort);
+ else if (flg_test(LOG_HOST))
+ snprintf(buf, sizeof(buf) / 2, ":%c: %s ", marker, daemonHostname);
+ else
+ snprintf(buf, sizeof(buf) / 2, ":%c: ", marker);
+
+ len = strlen(buf);
+
+ va_start(ap, format);
+ vsnprintf(buf + len, sizeof(buf) / 2 - len, format, ap);
+ va_end(ap);
+ len = strlen(buf);
+
+ if (len >= sizeof(buf) / 2) {
+ log_info(":E: buffer overflow (%d)\n", len);
+ buf[2048] = '\0';
+ len = strlen(buf);
+ }
+
+ buf2 = alloca(3 * (len + 3));
+
+ for (s = buf, d = buf2; *s; s++) {
+ c = (unsigned char) *s;
+ if (c == '\t')
+ *d++ = ' ';
+ else if (c == '\n')
+ *d++ = c;
+ else {
+ if (c < 32) {
+ *d++ = '^';
+ *d++ = c + 64;
+ } else if (c == 127) {
+ *d++ = '^';
+ *d++ = '?';
+ } else
+ *d++ = c;
+ }
+ }
+ *d = '\0';
+ log_info("%s", buf2);
+
+ if (d != buf2)
+ d[-1] = '\0'; /* kill newline */
+ dict_setproctitle("dictd %s", buf2);
}
static int daemon_check_mask(const char *spec, const char *ip)
{
- char *tmp = alloca(strlen(spec) + 1);
- char *pt;
- char tstring[64], mstring[64];
- struct in_addr target, mask;
- int bits;
- unsigned long bitmask;
-
- strcpy(tmp, spec);
- if (!(pt = strchr(tmp, '/'))) {
- log_info( ":E: No / in %s, denying access to %s\n", spec, ip);
- return DICT_DENY;
- }
- *pt++ = '\0';
- if (!*pt) {
- log_info( ":E: No bit count after / in %s, denying access to %s\n",
- spec, ip);
- return DICT_DENY;
- }
-
- inet_aton(ip, &target);
- inet_aton(tmp, &mask);
- bits = strtol(pt, NULL, 10);
- strcpy(tstring, inet_ntoa(target));
- strcpy(mstring, inet_ntoa(mask));
- if (bits < 0 || bits > 32) {
- log_info( ":E: Bit count (%d) out of range, denying access to %s\n",
- bits, ip);
- return DICT_DENY;
- }
-
- bitmask = daemon_compute_mask(bits);
- if ((ntohl(target.s_addr) & bitmask) == (ntohl(mask.s_addr) & bitmask)) {
- PRINTF(DBG_AUTH, ("%s matches %s/%d\n", tstring, mstring, bits));
- return DICT_MATCH;
- }
- PRINTF(DBG_AUTH, ("%s does NOT match %s/%d\n", tstring, mstring, bits));
- return DICT_NOMATCH;
+ char *tmp = alloca(strlen(spec) + 1);
+ char *pt;
+ char tstring[64], mstring[64];
+ struct in_addr target, mask;
+ int bits;
+ unsigned long bitmask;
+
+ strcpy(tmp, spec);
+ if (!(pt = strchr(tmp, '/'))) {
+ log_info(":E: No / in %s, denying access to %s\n", spec, ip);
+ return DICT_DENY;
+ }
+ *pt++ = '\0';
+ if (!*pt) {
+ log_info(":E: No bit count after / in %s, denying access to %s\n",
+ spec, ip);
+ return DICT_DENY;
+ }
+
+ inet_aton(ip, &target);
+ inet_aton(tmp, &mask);
+ bits = strtol(pt, NULL, 10);
+ strcpy(tstring, inet_ntoa(target));
+ strcpy(mstring, inet_ntoa(mask));
+ if (bits < 0 || bits > 32) {
+ log_info(":E: Bit count (%d) out of range, denying access to %s\n",
+ bits, ip);
+ return DICT_DENY;
+ }
+
+ bitmask = daemon_compute_mask(bits);
+ if ((ntohl(target.s_addr) & bitmask) == (ntohl(mask.s_addr) & bitmask)) {
+ PRINTF(DBG_AUTH, ("%s matches %s/%d\n", tstring, mstring, bits));
+ return DICT_MATCH;
+ }
+ PRINTF(DBG_AUTH,
+ ("%s does NOT match %s/%d\n", tstring, mstring, bits));
+ return DICT_NOMATCH;
}
static int daemon_check_range(const char *spec, const char *ip)
{
- char *tmp = alloca(strlen(spec) + 1);
- char *pt;
- char tstring[64], minstring[64], maxstring[64];
- struct in_addr target, min, max;
-
- strcpy(tmp, spec);
- if (!(pt = strchr(tmp, ':'))) {
- log_info( ":E: No : in range %s, denying access to %s\n", spec, ip);
- return DICT_DENY;
- }
- *pt++ = '\0';
- if (strchr(pt, ':')) {
- log_info( ":E: More than one : in range %s, denying access to %s\n",
- spec, ip);
- return DICT_DENY;
- }
- if (!*pt) {
- log_info( ":E: Misformed range %s, denying access to %s\n", spec, ip);
- return DICT_DENY;
- }
-
- inet_aton(ip, &target);
- inet_aton(tmp, &min);
- inet_aton(pt, &max);
- strcpy(tstring, inet_ntoa(target));
- strcpy(minstring, inet_ntoa(min));
- strcpy(maxstring, inet_ntoa(max));
- if (ntohl(target.s_addr) >= ntohl(min.s_addr)
- && ntohl(target.s_addr) <= ntohl(max.s_addr)) {
- PRINTF(DBG_AUTH,("%s in range from %s to %s\n",
- tstring, minstring, maxstring));
- return DICT_MATCH;
- }
- PRINTF(DBG_AUTH,("%s NOT in range from %s to %s\n",
- tstring, minstring, maxstring));
- return DICT_NOMATCH;
+ char *tmp = alloca(strlen(spec) + 1);
+ char *pt;
+ char tstring[64], minstring[64], maxstring[64];
+ struct in_addr target, min, max;
+
+ strcpy(tmp, spec);
+ if (!(pt = strchr(tmp, ':'))) {
+ log_info(":E: No : in range %s, denying access to %s\n", spec, ip);
+ return DICT_DENY;
+ }
+ *pt++ = '\0';
+ if (strchr(pt, ':')) {
+ log_info(":E: More than one : in range %s, denying access to %s\n",
+ spec, ip);
+ return DICT_DENY;
+ }
+ if (!*pt) {
+ log_info(":E: Misformed range %s, denying access to %s\n", spec,
+ ip);
+ return DICT_DENY;
+ }
+
+ inet_aton(ip, &target);
+ inet_aton(tmp, &min);
+ inet_aton(pt, &max);
+ strcpy(tstring, inet_ntoa(target));
+ strcpy(minstring, inet_ntoa(min));
+ strcpy(maxstring, inet_ntoa(max));
+ if (ntohl(target.s_addr) >= ntohl(min.s_addr)
+ && ntohl(target.s_addr) <= ntohl(max.s_addr)) {
+ PRINTF(DBG_AUTH, ("%s in range from %s to %s\n",
+ tstring, minstring, maxstring));
+ return DICT_MATCH;
+ }
+ PRINTF(DBG_AUTH, ("%s NOT in range from %s to %s\n",
+ tstring, minstring, maxstring));
+ return DICT_NOMATCH;
}
static int daemon_check_wildcard(const char *spec, const char *ip)
{
- char regbuf[256];
- char erbuf[100];
- int err;
- const char *s;
- char *d;
- regex_t re;
-
- for (d = regbuf, s = spec; s && *s; ++s) {
- switch (*s) {
- case '*': *d++ = '.'; *d++ = '*'; break;
- case '.': *d++ = '\\'; *d++ = '.'; break;
- case '?': *d++ = '.'; break;
- default: *d++ = *s; break;
- }
- }
- *d = '\0';
- if ((err = regcomp(&re, regbuf, REG_ICASE|REG_NOSUB))) {
- regerror(err, &re, erbuf, sizeof(erbuf));
- log_info( ":E: regcomp(%s): %s\n", regbuf, erbuf );
- return DICT_DENY; /* Err on the side of safety */
- }
- if (!regexec(&re, daemonHostname, 0, NULL, 0)
- || !regexec(&re, daemonIP, 0, NULL, 0)) {
- PRINTF(DBG_AUTH,
- ("Match %s with %s/%s\n", spec, daemonHostname, daemonIP));
- regfree(&re);
- return DICT_MATCH;
- }
- regfree(&re);
- PRINTF(DBG_AUTH,
- ("No match (%s with %s/%s)\n", spec, daemonHostname, daemonIP));
- return DICT_NOMATCH;
-}
-
-static int daemon_check_list( const char *user, lst_List acl )
-{
- lst_Position p;
- dictAccess *a;
- int retcode;
-
- if (!acl)
- return DICT_ALLOW;
-
- for (p = lst_init_position(acl); p; p = lst_next_position(p)) {
- a = lst_get_position(p);
- switch (a->type) {
- case DICT_DENY:
- case DICT_ALLOW:
- case DICT_AUTHONLY:
- if (strchr(a->spec, '/'))
- retcode = daemon_check_mask(a->spec, daemonIP);
- else if (strchr(a->spec, ':'))
- retcode = daemon_check_range(a->spec, daemonIP);
- else
- retcode = daemon_check_wildcard(a->spec, daemonIP);
- switch (retcode) {
- case DICT_DENY:
- return DICT_DENY;
- case DICT_MATCH:
- if (a->type == DICT_DENY) {
- daemon_log( DICT_LOG_AUTH, "spec %s denies %s/%s\n",
- a->spec, daemonHostname, daemonIP);
- }
- return a->type;
- }
- break;
- case DICT_USER:
- if (user && !strcmp(user,a->spec)) return DICT_ALLOW;
- case DICT_GROUP: /* Groups are not yet implemented. */
- break;
- }
- }
- return DICT_DENY;
-}
-
-static int daemon_check_auth( const char *user )
-{
- lst_Position p;
- lst_List dbl = DictConfig->dbl;
- dictDatabase *db;
-
- switch (daemon_check_list( user, DictConfig->acl )) {
- default:
- case DICT_DENY:
- return 1;
- case DICT_AUTHONLY:
- if (!user) return 0;
- case DICT_ALLOW:
- for (p = lst_init_position(dbl); p; p = lst_next_position(p)) {
- db = lst_get_position(p);
- switch (daemon_check_list(user, db->acl)) {
- case DICT_ALLOW: db->available = 1; continue;
- default: db->available = 0; continue;
- }
- }
- break;
- }
- return 0;
-}
-
-void daemon_terminate( int sig, const char *name )
-{
- alarm(0);
- tim_stop( "t" );
- close(daemonS_in);
- close(daemonS_out);
- if (name) {
- daemon_log( DICT_LOG_TERM,
- "%s: d/m/c = %d/%d/%d; %sr %su %ss\n",
- name,
- _dict_defines,
- _dict_matches,
- _dict_comparisons,
- dict_format_time( tim_get_real( "t" ) ),
- dict_format_time( tim_get_user( "t" ) ),
- dict_format_time( tim_get_system( "t" ) ) );
- } else {
- daemon_log( DICT_LOG_TERM,
- "signal %d: d/m/c = %d/%d/%d; %sr %su %ss\n",
- sig,
- _dict_defines,
- _dict_matches,
- _dict_comparisons,
- dict_format_time( tim_get_real( "t" ) ),
- dict_format_time( tim_get_user( "t" ) ),
- dict_format_time( tim_get_system( "t" ) ) );
- }
-
- log_close();
- longjmp(env,1);
- if (sig) exit(sig+128);
-
- exit(0);
-}
-
-
-static void daemon_write( const char *buf, int len )
-{
- int left = len;
- int count;
-
- while (left) {
- if ((count = write(daemonS_out, buf, left)) != left) {
- if (count <= 0) {
- if (errno == EPIPE) {
- daemon_terminate( 0, "pipe" );
+ char regbuf[256];
+ char erbuf[100];
+ int err;
+ const char *s;
+ char *d;
+ regex_t re;
+
+ for (d = regbuf, s = spec; s && *s; ++s) {
+ switch (*s) {
+ case '*':
+ *d++ = '.';
+ *d++ = '*';
+ break;
+ case '.':
+ *d++ = '\\';
+ *d++ = '.';
+ break;
+ case '?':
+ *d++ = '.';
+ break;
+ default:
+ *d++ = *s;
+ break;
+ }
+ }
+ *d = '\0';
+ if ((err = regcomp(&re, regbuf, REG_ICASE | REG_NOSUB))) {
+ regerror(err, &re, erbuf, sizeof(erbuf));
+ log_info(":E: regcomp(%s): %s\n", regbuf, erbuf);
+ return DICT_DENY; /* Err on the side of safety */
+ }
+ if (!regexec(&re, daemonHostname, 0, NULL, 0)
+ || !regexec(&re, daemonIP, 0, NULL, 0)) {
+ PRINTF(DBG_AUTH,
+ ("Match %s with %s/%s\n", spec, daemonHostname, daemonIP));
+ regfree(&re);
+ return DICT_MATCH;
+ }
+ regfree(&re);
+ PRINTF(DBG_AUTH,
+ ("No match (%s with %s/%s)\n", spec, daemonHostname, daemonIP));
+ return DICT_NOMATCH;
+}
+
+static int daemon_check_list(const char *user, lst_List acl)
+{
+ lst_Position p;
+ dictAccess *a;
+ int retcode;
+
+ if (!acl)
+ return DICT_ALLOW;
+
+ for (p = lst_init_position(acl); p; p = lst_next_position(p)) {
+ a = lst_get_position(p);
+ switch (a->type) {
+ case DICT_DENY:
+ case DICT_ALLOW:
+ case DICT_AUTHONLY:
+ if (strchr(a->spec, '/'))
+ retcode = daemon_check_mask(a->spec, daemonIP);
+ else if (strchr(a->spec, ':'))
+ retcode = daemon_check_range(a->spec, daemonIP);
+ else
+ retcode = daemon_check_wildcard(a->spec, daemonIP);
+ switch (retcode) {
+ case DICT_DENY:
+ return DICT_DENY;
+ case DICT_MATCH:
+ if (a->type == DICT_DENY) {
+ daemon_log(DICT_LOG_AUTH, "spec %s denies %s/%s\n",
+ a->spec, daemonHostname, daemonIP);
+ }
+ return a->type;
+ }
+ break;
+ case DICT_USER:
+ if (user && !strcmp(user, a->spec))
+ return DICT_ALLOW;
+ case DICT_GROUP: /* Groups are not yet implemented. */
+ break;
+ }
+ }
+ return DICT_DENY;
+}
+
+static int daemon_check_auth(const char *user)
+{
+ lst_Position p;
+ lst_List dbl = DictConfig->dbl;
+ dictDatabase *db;
+
+ switch (daemon_check_list(user, DictConfig->acl)) {
+ default:
+ case DICT_DENY:
+ return 1;
+ case DICT_AUTHONLY:
+ if (!user)
+ return 0;
+ case DICT_ALLOW:
+ for (p = lst_init_position(dbl); p; p = lst_next_position(p)) {
+ db = lst_get_position(p);
+ switch (daemon_check_list(user, db->acl)) {
+ case DICT_ALLOW:
+ db->available = 1;
+ continue;
+ default:
+ db->available = 0;
+ continue;
}
+ }
+ break;
+ }
+ return 0;
+}
+
+void daemon_terminate(int sig, const char *name)
+{
+ alarm(0);
+ tim_stop("t");
+ close(daemonS_in);
+ close(daemonS_out);
+ if (name) {
+ daemon_log(DICT_LOG_TERM,
+ "%s: d/m/c = %d/%d/%d; %sr %su %ss\n",
+ name,
+ _dict_defines,
+ _dict_matches,
+ _dict_comparisons,
+ dict_format_time(tim_get_real("t")),
+ dict_format_time(tim_get_user("t")),
+ dict_format_time(tim_get_system("t")));
+ } else {
+ daemon_log(DICT_LOG_TERM,
+ "signal %d: d/m/c = %d/%d/%d; %sr %su %ss\n",
+ sig,
+ _dict_defines,
+ _dict_matches,
+ _dict_comparisons,
+ dict_format_time(tim_get_real("t")),
+ dict_format_time(tim_get_user("t")),
+ dict_format_time(tim_get_system("t")));
+ }
+
+ log_close();
+ longjmp(env, 1);
+ if (sig)
+ exit(sig + 128);
+
+ exit(0);
+}
+
+
+static void daemon_write(const char *buf, int len)
+{
+ int left = len;
+ int count;
+
+ while (left) {
+ if ((count = write(daemonS_out, buf, left)) != left) {
+ if (count <= 0) {
+ if (errno == EPIPE) {
+ daemon_terminate(0, "pipe");
+ }
#if HAVE_STRERROR
- log_info( ":E: writing %d of %d bytes:"
- " retval = %d, errno = %d (%s)\n",
- left, len, count, errno, strerror(errno) );
+ log_info(":E: writing %d of %d bytes:"
+ " retval = %d, errno = %d (%s)\n",
+ left, len, count, errno, strerror(errno));
#else
- log_info( ":E: writing %d of %d bytes:"
- " retval = %d, errno = %d\n",
- left, len, count, errno );
+ log_info(":E: writing %d of %d bytes:"
+ " retval = %d, errno = %d\n",
+ left, len, count, errno);
#endif
- daemon_terminate( 0, __func__ );
- }
- }
- left -= count;
- }
-}
-
-static void daemon_crlf( char *d, const char *s, int dot )
-{
- int first = 1;
-
- while (*s) {
- if (*s == '\n') {
- *d++ = '\r';
- *d++ = '\n';
- first = 1;
- ++s;
- } else {
- if (dot && first && *s == '.' && s[1] == '\n')
- *d++ = '.'; /* double first dot on line */
- first = 0;
- *d++ = *s++;
- }
- }
- if (dot) { /* add final . */
- if (!first){
- *d++ = '\r';
- *d++ = '\n';
- }
- *d++ = '.';
- *d++ = '\r';
- *d++ = '\n';
- }
- *d = '\0';
-}
-
-static void daemon_printf( const char *format, ... )
-{
- va_list ap;
- char buf[BUFFERSIZE];
- char *pt;
- int len;
-
- va_start( ap, format );
- vsnprintf( buf, sizeof (buf), format, ap );
- va_end( ap );
- if ((len = strlen( buf )) >= BUFFERSIZE) {
- log_info( ":E: buffer overflow: %d\n", len );
- daemon_terminate( 0, __func__ );
- }
-
- pt = alloca(2*len + 10); /* +10 for the case when buf == "\n"*/
- daemon_crlf(pt, buf, 0);
- daemon_write(pt, strlen(pt));
-}
-
-static void daemon_mime( void )
-{
- if (daemonMime) daemon_write( "\r\n", 2 );
-}
-
-static void daemon_mime_definition (const dictDatabase *db)
-{
- if (daemonMime){
- if (db -> mime_header){
- daemon_printf ("%s", db -> mime_header);
- }
-
- daemon_write ("\r\n", 2);
- }
-}
-
-static void daemon_text( const char *text, int dot )
-{
- char *pt = alloca( 2*strlen(text) + 10 );
-
- daemon_crlf(pt, text, dot);
- daemon_write(pt, strlen(pt));
-}
-
-static int daemon_read( char *buf, int count )
-{
- return net_read( daemonS_in, buf, count );
-}
-
-static void daemon_ok( int code, const char *string, const char *timer )
-{
- static int lastDefines = 0;
- static int lastMatches = 0;
- static int lastComparisons = 0;
-
- if (code == CODE_STATUS) {
- lastDefines = 0;
- lastMatches = 0;
- lastComparisons = 0;
- }
-
- if (!timer) {
- daemon_printf("%d %s\n", code, string);
- } else {
- tim_stop( timer );
- daemon_printf("%d %s [d/m/c = %d/%d/%d; %sr %su %ss]\n",
- code,
- string,
- _dict_defines - lastDefines,
- _dict_matches - lastMatches,
- _dict_comparisons - lastComparisons,
- dict_format_time( tim_get_real( timer ) ),
- dict_format_time( tim_get_user( timer ) ),
- dict_format_time( tim_get_system( timer ) ) );
- }
-
- lastDefines = _dict_defines;
- lastMatches = _dict_matches;
- lastComparisons = _dict_comparisons;
-}
-
-static int daemon_count_defs( lst_List list )
-{
- lst_Position p;
- dictWord *dw;
- unsigned long previousStart = 0;
- unsigned long previousEnd = 0;
- const char *previousDef = NULL;
- int count = 0;
-
- LST_ITERATE(list,p,dw) {
- if (
- previousStart == dw->start &&
- previousEnd == dw->end &&
- previousDef == dw->def)
- {
- continue;
- }
-
- previousStart = dw->start;
- previousEnd = dw->end;
- previousDef = dw->def;
-
- ++count;
- }
- return count;
-}
-
-static void daemon_dump_defs( lst_List list )
-{
- lst_Position p;
- char *buf;
- dictWord *dw;
- const dictDatabase *db = NULL;
- const dictDatabase *db_visible = NULL;
- unsigned long previousStart = 0;
- unsigned long previousEnd = 0;
- const char * previousDef = NULL;
- int count;
-
- LST_ITERATE(list,p,dw) {
- db = dw->database;
-
- if (
- previousStart == dw->start &&
- previousEnd == dw->end &&
- previousDef == dw->def)
- {
- continue;
- }
-
- previousStart = dw->start;
- previousEnd = dw->end;
- previousDef = dw->def;
-
- buf = dict_data_obtain ( db, dw );
-
- if (dw -> database_visible){
- db_visible = dw -> database_visible;
- }else{
- db_visible = db;
- }
-
- daemon_printf (
- "%d \"%s\" %s \"%s\"\n",
- CODE_DEFINITION_FOLLOWS,
- dw->word,
- db_visible -> invisible ? "*" : db_visible -> databaseName,
- db_visible -> invisible ? "" : db_visible -> databaseShort);
-
- daemon_mime_definition (db);
-
- if (db->filter){
- count = strlen(buf);
- daemon_log( DICT_LOG_AUTH, "filtering with: %s\ncount: %d\n",
- db->filter, count );
-
- dict_data_filter(buf, &count, strlen (buf), db->filter);
- buf[count] = '\0';
- }
-
- daemon_text(buf, 1);
- xfree( buf );
- }
-}
-
-static int daemon_count_matches( lst_List list )
-{
- lst_Position p;
- dictWord *dw;
- const char *prevword = NULL;
- const dictDatabase *prevdb = NULL;
- int count = 0;
-
- LST_ITERATE(list,p,dw) {
- if (prevdb == dw->database && prevword && !strcmp(prevword,dw->word))
- continue;
-
- prevword = dw->word;
- prevdb = dw->database;
-
- ++count;
- }
- return count;
-}
-
-static void daemon_dump_matches( lst_List list )
-{
- lst_Position p;
- dictWord *dw;
- const char *prevword = NULL;
- const dictDatabase *prevdb = NULL;
- const dictDatabase *db = NULL;
-
- daemon_mime();
- LST_ITERATE(list,p,dw) {
- db = dw -> database;
-
- if (prevdb == dw->database && prevword && !strcmp(prevword,dw->word))
- continue;
-
- prevword = dw->word;
- prevdb = dw->database;
-
- if (dw -> database_visible){
- db = dw -> database_visible;
- }
-
- daemon_printf (
- "%s \"%s\"\n",
- db -> invisible ? "*" : db -> databaseName,
- dw -> word );
- }
- daemon_printf( ".\n" );
-}
-
-static void daemon_banner( void )
-{
- time_t t;
-
- time(&t);
-
- snprintf( daemonStamp, sizeof (daemonStamp), "<%d.%d.%lu@%s>",
- _dict_forks,
- (int) getpid(),
- (long unsigned)t,
- net_hostname() );
- daemon_printf( "%d %s %s <auth.mime> %s\n",
- CODE_HELLO,
- net_hostname(),
- dict_get_banner(0),
- daemonStamp );
-}
-
-static void daemon_define( const char *cmdline, int argc, const char **argv )
-{
- lst_List list = lst_create();
- int matches = 0;
- const char *word;
- const char *databaseName;
- int extension = (argv[0][0] == 'd' && argv[0][1] == '\0');
- int db_found = 0;
-
- if (extension) {
- switch (argc) {
- case 2: databaseName = "*"; word = argv[1]; break;
- case 3: databaseName = argv[1]; word = argv[2]; break;
- default:
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
- } else if (argc == 3) {
- databaseName = argv[1];
- word = argv[2];
- } else {
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
-
- matches = abs(dict_search_databases (
- list, NULL,
- databaseName, word, DICT_STRAT_EXACT,
- &db_found));
-
- if (db_found && matches > 0) {
- int actual_matches = daemon_count_defs( list );
-
- _dict_defines += actual_matches;
- daemon_log( DICT_LOG_DEFINE,
- "%s \"%s\" %d\n", databaseName, word, actual_matches);
- daemon_printf( "%d %d definitions retrieved\n",
- CODE_DEFINITIONS_FOUND,
- actual_matches );
- daemon_dump_defs( list );
- daemon_ok( CODE_OK, "ok", "c" );
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- return;
- }
+ daemon_terminate(0, __func__);
+ }
+ }
+ left -= count;
+ }
+}
- if (!db_found) {
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- daemon_printf( "%d invalid database, use SHOW DB for list\n",
- CODE_INVALID_DB );
- return;
- }
+static void daemon_crlf(char *d, const char *s, int dot)
+{
+ int first = 1;
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- daemon_log( DICT_LOG_NOMATCH,
- "%s exact \"%s\"\n", databaseName, word );
- daemon_ok( CODE_NO_MATCH, "no match", "c" );
-}
-
-static void daemon_match( const char *cmdline, int argc, const char **argv )
-{
- lst_List list = lst_create();
- int matches = 0;
- const char *word;
- const char *databaseName;
- const char *strategy;
- int strategyNumber;
- int extension = (argv[0][0] == 'm' && argv[0][1] == '\0');
- int db_found = 0;
-
- if (extension) {
- switch (argc) {
- case 2:databaseName = "*"; strategy = "."; word = argv[1]; break;
- case 3:databaseName = "*"; strategy = argv[1]; word = argv[2]; break;
- case 4:databaseName = argv[1]; strategy = argv[2]; word = argv[3]; break;
- default:
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
- } else if (argc == 4) {
- databaseName = argv[1];
- strategy = argv[2];
- word = argv[3];
- } else {
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
-
- if ((strategyNumber = lookup_strategy(strategy)) < 0) {
- daemon_printf( "%d invalid strategy, use SHOW STRAT for a list\n",
- CODE_INVALID_STRATEGY );
- return;
- }
-
- matches = abs(dict_search_databases (
- list, NULL,
- databaseName, word, strategyNumber | DICT_MATCH_MASK,
- &db_found));
-
- if (db_found && matches > 0) {
- int actual_matches = daemon_count_matches( list );
-
- _dict_matches += actual_matches;
- daemon_log( DICT_LOG_MATCH,
- "%s %s \"%s\" %d\n",
- databaseName, strategy, word, actual_matches);
- daemon_printf( "%d %d matches found\n",
- CODE_MATCHES_FOUND, actual_matches );
- daemon_dump_matches( list );
- daemon_ok( CODE_OK, "ok", "c" );
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- return;
- }
+ while (*s) {
+ if (*s == '\n') {
+ *d++ = '\r';
+ *d++ = '\n';
+ first = 1;
+ ++s;
+ } else {
+ if (dot && first && *s == '.' && s[1] == '\n')
+ *d++ = '.'; /* double first dot on line */
+ first = 0;
+ *d++ = *s++;
+ }
+ }
+ if (dot) { /* add final . */
+ if (!first) {
+ *d++ = '\r';
+ *d++ = '\n';
+ }
+ *d++ = '.';
+ *d++ = '\r';
+ *d++ = '\n';
+ }
+ *d = '\0';
+}
- if (!db_found) {
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- daemon_printf( "%d invalid database, use SHOW DB for list\n",
- CODE_INVALID_DB );
- return;
- }
+static void daemon_printf(const char *format, ...)
+{
+ va_list ap;
+ char buf[BUFFERSIZE];
+ char *pt;
+ int len;
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- dict_destroy_list( list );
- daemon_log( DICT_LOG_NOMATCH,
- "%s %s \"%s\"\n", databaseName, strategy, word );
- daemon_ok( CODE_NO_MATCH, "no match", "c" );
+ va_start(ap, format);
+ vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ if ((len = strlen(buf)) >= BUFFERSIZE) {
+ log_info(":E: buffer overflow: %d\n", len);
+ daemon_terminate(0, __func__);
+ }
+
+ pt = alloca(2 * len + 10); /* +10 for the case when buf == "\n" */
+ daemon_crlf(pt, buf, 0);
+ daemon_write(pt, strlen(pt));
+}
+
+static void daemon_mime(void)
+{
+ if (daemonMime)
+ daemon_write("\r\n", 2);
}
-static lst_Position first_database_pos (void)
+static void daemon_mime_definition(const dictDatabase * db)
{
- return lst_init_position (DictConfig->dbl);
+ if (daemonMime) {
+ if (db->mime_header) {
+ daemon_printf("%s", db->mime_header);
+ }
+
+ daemon_write("\r\n", 2);
+ }
}
-static dictDatabase *next_database (
- lst_Position *databasePosition,
- const char *name)
+static void daemon_text(const char *text, int dot)
{
- dictDatabase *db = NULL;
+ char *pt = alloca(2 * strlen(text) + 10);
- assert (databasePosition);
+ daemon_crlf(pt, text, dot);
+ daemon_write(pt, strlen(pt));
+}
- if (!name)
- return NULL;
+static int daemon_read(char *buf, int count)
+{
+ return net_read(daemonS_in, buf, count);
+}
- if (*name == '*' || *name == '!') {
- if (*databasePosition) {
- do {
- db = lst_get_position( *databasePosition );
+static void daemon_ok(int code, const char *string, const char *timer)
+{
+ static int lastDefines = 0;
+ static int lastMatches = 0;
+ static int lastComparisons = 0;
- *databasePosition = lst_next_position( *databasePosition );
- } while ( db && (!db->available || db->invisible));
- }
- return db;
- } else {
- while (*databasePosition) {
- db = lst_get_position( *databasePosition );
- *databasePosition = lst_next_position( *databasePosition );
+ if (code == CODE_STATUS) {
+ lastDefines = 0;
+ lastMatches = 0;
+ lastComparisons = 0;
+ }
- if (db){
- if (
- !db -> invisible && db->available &&
- !strcmp(db -> databaseName,name))
- {
- return db;
- }
- }else{
- return NULL;
- }
- }
+ if (!timer) {
+ daemon_printf("%d %s\n", code, string);
+ } else {
+ tim_stop(timer);
+ daemon_printf("%d %s [d/m/c = %d/%d/%d; %sr %su %ss]\n",
+ code,
+ string,
+ _dict_defines - lastDefines,
+ _dict_matches - lastMatches,
+ _dict_comparisons - lastComparisons,
+ dict_format_time(tim_get_real(timer)),
+ dict_format_time(tim_get_user(timer)),
+ dict_format_time(tim_get_system(timer)));
+ }
- return NULL;
- }
+ lastDefines = _dict_defines;
+ lastMatches = _dict_matches;
+ lastComparisons = _dict_comparisons;
}
-static int count_databases( void )
+static int daemon_count_defs(lst_List list)
{
- int count = 0;
- const dictDatabase *db;
+ lst_Position p;
+ dictWord *dw;
+ unsigned long previousStart = 0;
+ unsigned long previousEnd = 0;
+ const char *previousDef = NULL;
+ int count = 0;
+
+ LST_ITERATE(list, p, dw) {
+ if (previousStart == dw->start &&
+ previousEnd == dw->end && previousDef == dw->def) {
+ continue;
+ }
- lst_Position databasePosition = first_database_pos ();
+ previousStart = dw->start;
+ previousEnd = dw->end;
+ previousDef = dw->def;
+
+ ++count;
+ }
+ return count;
+}
+
+static void daemon_dump_defs(lst_List list)
+{
+ lst_Position p;
+ char *buf;
+ dictWord *dw;
+ const dictDatabase *db = NULL;
+ const dictDatabase *db_visible = NULL;
+ unsigned long previousStart = 0;
+ unsigned long previousEnd = 0;
+ const char *previousDef = NULL;
+ int count;
- while (NULL != (db = next_database (&databasePosition, "*"))){
- assert (!db -> invisible);
+ LST_ITERATE(list, p, dw) {
+ db = dw->database;
- if (!db -> exit_db)
- ++count;
- }
+ if (previousStart == dw->start &&
+ previousEnd == dw->end && previousDef == dw->def) {
+ continue;
+ }
+
+ previousStart = dw->start;
+ previousEnd = dw->end;
+ previousDef = dw->def;
+
+ buf = dict_data_obtain(db, dw);
+
+ if (dw->database_visible) {
+ db_visible = dw->database_visible;
+ } else {
+ db_visible = db;
+ }
+
+ daemon_printf("%d \"%s\" %s \"%s\"\n",
+ CODE_DEFINITION_FOLLOWS,
+ dw->word,
+ db_visible->invisible ? "*" : db_visible->
+ databaseName,
+ db_visible->invisible ? "" : db_visible->
+ databaseShort);
+
+ daemon_mime_definition(db);
+
+ if (db->filter) {
+ count = strlen(buf);
+ daemon_log(DICT_LOG_AUTH, "filtering with: %s\ncount: %d\n",
+ db->filter, count);
+
+ dict_data_filter(buf, &count, strlen(buf), db->filter);
+ buf[count] = '\0';
+ }
+
+ daemon_text(buf, 1);
+ xfree(buf);
+ }
+}
+
+static int daemon_count_matches(lst_List list)
+{
+ lst_Position p;
+ dictWord *dw;
+ const char *prevword = NULL;
+ const dictDatabase *prevdb = NULL;
+ int count = 0;
+
+ LST_ITERATE(list, p, dw) {
+ if (prevdb == dw->database && prevword
+ && !strcmp(prevword, dw->word))
+ continue;
- return count;
+ prevword = dw->word;
+ prevdb = dw->database;
+
+ ++count;
+ }
+ return count;
}
-static void destroy_word_list (lst_List l)
+static void daemon_dump_matches(lst_List list)
{
- char *word;
+ lst_Position p;
+ dictWord *dw;
+ const char *prevword = NULL;
+ const dictDatabase *prevdb = NULL;
+ const dictDatabase *db = NULL;
- while (lst_length (l)){
- word = lst_pop (l);
- if (word)
- xfree (word);
- }
- lst_destroy (l);
-}
+ daemon_mime();
+ LST_ITERATE(list, p, dw) {
+ db = dw->database;
-/*
- Search for all words in word_list in the database db
- */
-static int dict_search_words (
- lst_List *l,
- lst_List word_list,
- const dictDatabase *db,
- int strategy,
- int *error, int *result,
- const dictPluginData **extra_result, int *extra_result_size)
-{
- lst_Position word_list_pos;
- int mc = 0;
- int matches_count = 0;
- const char *word;
-
- word_list_pos = lst_init_position (word_list);
- while (word_list_pos){
- word = lst_get_position (word_list_pos);
-
- if (word){
- matches_count = dict_search (
- l, word, db, strategy,
- daemonMime,
- result, extra_result, extra_result_size);
-
- if (*result == DICT_PLUGIN_RESULT_PREPROCESS){
- assert (matches_count > 0);
-
- xfree (lst_get_position (word_list_pos));
- lst_set_position (word_list_pos, NULL);
- }
-
- if (matches_count < 0){
- *error = 1;
- matches_count = abs (matches_count);
- mc += matches_count;
- break;
- }
+ if (prevdb == dw->database && prevword
+ && !strcmp(prevword, dw->word))
+ continue;
- mc += matches_count;
- }
+ prevword = dw->word;
+ prevdb = dw->database;
- word_list_pos = lst_next_position (word_list_pos);
- }
+ if (dw->database_visible) {
+ db = dw->database_visible;
+ }
- return mc;
+ daemon_printf("%s \"%s\"\n",
+ db->invisible ? "*" : db->databaseName, dw->word);
+ }
+ daemon_printf(".\n");
}
-int dict_search_databases (
- lst_List *l,
- lst_Position databasePosition, /* NULL for global database list */
- const char *databaseName, const char *word, int strategy,
- int *db_found)
+static void daemon_banner(void)
{
- int matches = -1;
- int matches_count = 0;
- int error = 0;
-
+ time_t t;
- const dictDatabase *db;
- dictWord *dw;
- char *p;
+ time(&t);
- lst_List preprocessed_words;
- int i;
-
- int result;
- const dictPluginData *extra_result;
- int extra_result_size;
+ snprintf(daemonStamp, sizeof(daemonStamp), "<%d.%d.%lu@%s>",
+ _dict_forks,
+ (int) getpid(), (long unsigned) t, net_hostname());
+ daemon_printf("%d %s %s <auth.mime> %s\n",
+ CODE_HELLO,
+ net_hostname(), dict_get_banner(0), daemonStamp);
+}
- *db_found = 0;
+static void daemon_define(const char *cmdline, int argc, const char **argv)
+{
+ lst_List list = lst_create();
+ int matches = 0;
+ const char *word;
+ const char *databaseName;
+ int extension = (argv[0][0] == 'd' && argv[0][1] == '\0');
+ int db_found = 0;
+
+ if (extension) {
+ switch (argc) {
+ case 2:
+ databaseName = "*";
+ word = argv[1];
+ break;
+ case 3:
+ databaseName = argv[1];
+ word = argv[2];
+ break;
+ default:
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+ } else if (argc == 3) {
+ databaseName = argv[1];
+ word = argv[2];
+ } else {
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+
+ matches = abs(dict_search_databases(list, NULL,
+ databaseName, word,
+ DICT_STRAT_EXACT, &db_found));
+
+ if (db_found && matches > 0) {
+ int actual_matches = daemon_count_defs(list);
+
+ _dict_defines += actual_matches;
+ daemon_log(DICT_LOG_DEFINE,
+ "%s \"%s\" %d\n", databaseName, word, actual_matches);
+ daemon_printf("%d %d definitions retrieved\n",
+ CODE_DEFINITIONS_FOUND, actual_matches);
+ daemon_dump_defs(list);
+ daemon_ok(CODE_OK, "ok", "c");
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ return;
+ }
- if (!databasePosition)
- databasePosition = first_database_pos ();
+ if (!db_found) {
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ daemon_printf("%d invalid database, use SHOW DB for list\n",
+ CODE_INVALID_DB);
+ return;
+ }
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ daemon_log(DICT_LOG_NOMATCH, "%s exact \"%s\"\n", databaseName, word);
+ daemon_ok(CODE_NO_MATCH, "no match", "c");
+}
+
+static void daemon_match(const char *cmdline, int argc, const char **argv)
+{
+ lst_List list = lst_create();
+ int matches = 0;
+ const char *word;
+ const char *databaseName;
+ const char *strategy;
+ int strategyNumber;
+ int extension = (argv[0][0] == 'm' && argv[0][1] == '\0');
+ int db_found = 0;
+
+ if (extension) {
+ switch (argc) {
+ case 2:
+ databaseName = "*";
+ strategy = ".";
+ word = argv[1];
+ break;
+ case 3:
+ databaseName = "*";
+ strategy = argv[1];
+ word = argv[2];
+ break;
+ case 4:
+ databaseName = argv[1];
+ strategy = argv[2];
+ word = argv[3];
+ break;
+ default:
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+ } else if (argc == 4) {
+ databaseName = argv[1];
+ strategy = argv[2];
+ word = argv[3];
+ } else {
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+
+ if ((strategyNumber = lookup_strategy(strategy)) < 0) {
+ daemon_printf("%d invalid strategy, use SHOW STRAT for a list\n",
+ CODE_INVALID_STRATEGY);
+ return;
+ }
+
+ matches = abs(dict_search_databases(list, NULL,
+ databaseName, word,
+ strategyNumber | DICT_MATCH_MASK,
+ &db_found));
+
+ if (db_found && matches > 0) {
+ int actual_matches = daemon_count_matches(list);
+
+ _dict_matches += actual_matches;
+ daemon_log(DICT_LOG_MATCH,
+ "%s %s \"%s\" %d\n",
+ databaseName, strategy, word, actual_matches);
+ daemon_printf("%d %d matches found\n",
+ CODE_MATCHES_FOUND, actual_matches);
+ daemon_dump_matches(list);
+ daemon_ok(CODE_OK, "ok", "c");
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ return;
+ }
- preprocessed_words = lst_create ();
- lst_append (preprocessed_words, xstrdup(word));
+ if (!db_found) {
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ daemon_printf("%d invalid database, use SHOW DB for list\n",
+ CODE_INVALID_DB);
+ return;
+ }
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
+ dict_destroy_list(list);
+ daemon_log(DICT_LOG_NOMATCH,
+ "%s %s \"%s\"\n", databaseName, strategy, word);
+ daemon_ok(CODE_NO_MATCH, "no match", "c");
+}
- while (!error && (db = next_database (&databasePosition, databaseName))) {
- if (db -> exit_db)
- /* dictionary_exit */
- break;
+static lst_Position first_database_pos(void)
+{
+ return lst_init_position(DictConfig->dbl);
+}
- *db_found = 1;
+static dictDatabase *next_database(lst_Position * databasePosition,
+ const char *name)
+{
+ dictDatabase *db = NULL;
- result = DICT_PLUGIN_RESULT_NOTFOUND;
+ assert(databasePosition);
- matches_count = dict_search_words (
- l,
- preprocessed_words, db, strategy,
- &error,
- &result, &extra_result, &extra_result_size);
+ if (!name)
+ return NULL;
- if (matches < 0)
- matches = 0;
+ if (*name == '*' || *name == '!') {
+ if (*databasePosition) {
+ do {
+ db = lst_get_position(*databasePosition);
- if (result == DICT_PLUGIN_RESULT_PREPROCESS){
- for (i=0; i < matches_count; ++i){
- dw = lst_pop (l);
- switch (dw -> def_size){
- case -1:
- p = xstrdup (dw -> word);
- lst_append (preprocessed_words, p);
- break;
- case 0:
- break;
- default:
- p = xmalloc (1 + dw -> def_size);
- memcpy (p, dw -> def, dw -> def_size);
- p [dw -> def_size] = 0;
+ *databasePosition = lst_next_position(*databasePosition);
+ } while (db && (!db->available || db->invisible));
+ }
+ return db;
+ } else {
+ while (*databasePosition) {
+ db = lst_get_position(*databasePosition);
+ *databasePosition = lst_next_position(*databasePosition);
- lst_append (preprocessed_words, p);
+ if (db) {
+ if (!db->invisible && db->available &&
+ !strcmp(db->databaseName, name)) {
+ return db;
+ }
+ } else {
+ return NULL;
}
+ }
- dict_destroy_datum (dw);
- }
- }else{
- matches += matches_count;
+ return NULL;
+ }
+}
- if (result == DICT_PLUGIN_RESULT_EXIT)
- break;
+static int count_databases(void)
+{
+ int count = 0;
+ const dictDatabase *db;
- if (*databaseName == '*')
- continue;
- else if (!matches && *databaseName == '!')
- continue;
+ lst_Position databasePosition = first_database_pos();
- break;
- }
- }
+ while (NULL != (db = next_database(&databasePosition, "*"))) {
+ assert(!db->invisible);
- destroy_word_list (preprocessed_words);
+ if (!db->exit_db)
+ ++count;
+ }
- return error ? -matches : matches;
+ return count;
}
-static void daemon_show_db( const char *cmdline, int argc, const char **argv )
+static void destroy_word_list(lst_List l)
{
- int count;
- const dictDatabase *db;
-
- lst_Position databasePosition;
+ char *word;
- if (argc != 2) {
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
+ while (lst_length(l)) {
+ word = lst_pop(l);
+ if (word)
+ xfree(word);
+ }
+ lst_destroy(l);
+}
- if (!(count = count_databases())) {
- daemon_printf( "%d no databases present\n", CODE_NO_DATABASES );
- } else {
- daemon_printf( "%d %d databases present\n",
- CODE_DATABASE_LIST, count );
+/*
+ Search for all words in word_list in the database db
+ */
+static int dict_search_words(lst_List * l,
+ lst_List word_list,
+ const dictDatabase * db,
+ int strategy,
+ int *error, int *result,
+ const dictPluginData ** extra_result,
+ int *extra_result_size)
+{
+ lst_Position word_list_pos;
+ int mc = 0;
+ int matches_count = 0;
+ const char *word;
+
+ word_list_pos = lst_init_position(word_list);
+ while (word_list_pos) {
+ word = lst_get_position(word_list_pos);
+
+ if (word) {
+ matches_count = dict_search(l, word, db, strategy,
+ daemonMime,
+ result, extra_result,
+ extra_result_size);
- databasePosition = first_database_pos ();
+ if (*result == DICT_PLUGIN_RESULT_PREPROCESS) {
+ assert(matches_count > 0);
- daemon_mime();
- while ((db = next_database(&databasePosition, "*"))) {
- assert (!db->invisible);
+ xfree(lst_get_position(word_list_pos));
+ lst_set_position(word_list_pos, NULL);
+ }
- if (db -> exit_db)
- continue;
+ if (matches_count < 0) {
+ *error = 1;
+ matches_count = abs(matches_count);
+ mc += matches_count;
+ break;
+ }
- daemon_printf(
- "%s \"%s\"\n",
- db->databaseName, db->databaseShort );
- }
- daemon_printf( ".\n" );
- daemon_ok( CODE_OK, "ok", NULL );
- }
-}
-
-static void daemon_show_strat( const char *cmdline, int argc, const char **argv )
-{
- int i;
-
- int strat_count = get_strategy_count ();
- dictStrategy const * const * strats = get_strategies ();
-
- if (argc != 2) {
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
-
- if (strat_count){
- daemon_printf( "%d %d strategies present\n",
- CODE_STRATEGY_LIST, strat_count );
- daemon_mime();
-
- for (i = 0; i < strat_count; i++) {
- daemon_printf( "%s \"%s\"\n",
- strats [i] -> name, strats [i] -> description );
- }
-
- daemon_printf( ".\n" );
- daemon_ok( CODE_OK, "ok", NULL );
- }else{
- daemon_printf( "%d no strategies available\n", CODE_NO_STRATEGIES );
- }
-}
-
-void daemon_show_info(
- const char *cmdline,
- int argc, const char **argv )
-{
- char *buf=NULL;
- dictWord *dw;
- const dictDatabase *db;
- lst_List list;
- const char *info_entry_name = DICT_INFO_ENTRY_NAME;
-
- lst_Position databasePosition = first_database_pos ();
-
- if (argc != 3) {
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- return;
- }
-
- if ((argv[2][0] == '*' || argv[2][0] == '!') && argv[2][1] == '\0') {
- daemon_printf( "%d invalid database, use SHOW DB for list\n",
- CODE_INVALID_DB );
- return;
- }
-
- list = lst_create();
- while ((db = next_database(&databasePosition, argv[2]))) {
- if (db -> databaseInfo && db -> databaseInfo [0] != '@'){
- daemon_printf( "%d information for %s\n",
- CODE_DATABASE_INFO, argv[2] );
- daemon_mime();
- daemon_text(db -> databaseInfo, 1);
- daemon_ok( CODE_OK, "ok", NULL );
- return;
- }
-
- if (db -> databaseInfo && db -> databaseInfo [0] == '@')
- info_entry_name = db -> databaseInfo + 1;
-
- if (dict_search (
- list,
- info_entry_name,
- db, DICT_STRAT_EXACT, 0,
- NULL, NULL, NULL))
- {
- int i=1;
- int list_size = lst_length (list);
-
- daemon_printf( "%d information for %s\n",
- CODE_DATABASE_INFO, argv[2] );
- daemon_mime();
-
- if (db -> virtual_db){
- daemon_printf ("The virtual dictionary `%s' includes the following:\n\n",
- db -> databaseName);
- }
+ mc += matches_count;
+ }
- for (i=1; i <= list_size; ++i){
- dw = lst_nth_get( list, i );
+ word_list_pos = lst_next_position(word_list_pos);
+ }
- daemon_printf ("============ %s ============\n",
- dw -> database -> databaseName);
+ return mc;
+}
- buf = dict_data_obtain( dw -> database, dw );
+int dict_search_databases(lst_List * l, lst_Position databasePosition, /* NULL for global database list */
+ const char *databaseName, const char *word,
+ int strategy, int *db_found)
+{
+ int matches = -1;
+ int matches_count = 0;
+ int error = 0;
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
- if (buf)
- daemon_text (buf, 0);
- }
+ const dictDatabase *db;
+ dictWord *dw;
+ char *p;
- daemon_text ("\n", 1);
- daemon_ok( CODE_OK, "ok", NULL );
+ lst_List preprocessed_words;
+ int i;
- dict_destroy_list (list);
+ int result;
+ const dictPluginData *extra_result;
+ int extra_result_size;
- return;
- } else {
-#ifdef USE_PLUGIN
- call_dictdb_free (DictConfig->dbl);
-#endif
+ *db_found = 0;
- dict_destroy_list( list );
- daemon_printf( "%d information for %s\n",
- CODE_DATABASE_INFO, argv[2] );
- daemon_mime();
- daemon_text( "No information available\n" , 1);
- daemon_ok( CODE_OK, "ok", NULL );
- return;
- }
- }
+ if (!databasePosition)
+ databasePosition = first_database_pos();
- dict_destroy_list( list );
- daemon_printf( "%d invalid database, use SHOW DB for list\n",
- CODE_INVALID_DB );
-}
+ preprocessed_words = lst_create();
+ lst_append(preprocessed_words, xstrdup(word));
-static int daemon_get_max_dbname_length ()
-{
- size_t max_len = 0;
- size_t curr_len = 0;
+ while (!error && (db = next_database(&databasePosition, databaseName))) {
+ if (db->exit_db)
+ /* dictionary_exit */
+ break;
+
+ *db_found = 1;
- const dictDatabase *db;
+ result = DICT_PLUGIN_RESULT_NOTFOUND;
- lst_Position databasePosition = first_database_pos ();
+ matches_count = dict_search_words(l,
+ preprocessed_words, db, strategy,
+ &error,
+ &result, &extra_result,
+ &extra_result_size);
+
+ if (matches < 0)
+ matches = 0;
+
+ if (result == DICT_PLUGIN_RESULT_PREPROCESS) {
+ for (i = 0; i < matches_count; ++i) {
+ dw = lst_pop(l);
+ switch (dw->def_size) {
+ case -1:
+ p = xstrdup(dw->word);
+ lst_append(preprocessed_words, p);
+ break;
+ case 0:
+ break;
+ default:
+ p = xmalloc(1 + dw->def_size);
+ memcpy(p, dw->def, dw->def_size);
+ p[dw->def_size] = 0;
- while (NULL != (db = next_database (&databasePosition, "*"))){
- assert (!db -> invisible);
+ lst_append(preprocessed_words, p);
+ }
- if (db -> databaseName){
- curr_len = strlen (db -> databaseName);
+ dict_destroy_datum(dw);
+ }
+ } else {
+ matches += matches_count;
- if (curr_len > max_len){
- max_len = curr_len;
- }
- }
- }
+ if (result == DICT_PLUGIN_RESULT_EXIT)
+ break;
- return (int) max_len;
-}
+ if (*databaseName == '*')
+ continue;
+ else if (!matches && *databaseName == '!')
+ continue;
-static void daemon_show_server (
- const char *cmdline,
- int argc, const char **argv)
-{
- FILE *str;
- char buffer[1024];
- const dictDatabase *db;
- double uptime;
+ break;
+ }
+ }
- int headwords;
+ destroy_word_list(preprocessed_words);
- int index_size;
- char index_size_uom;
+ return error ? -matches : matches;
+}
- int data_size;
- char data_size_uom;
- int data_length;
- char data_length_uom;
+static void daemon_show_db(const char *cmdline, int argc,
+ const char **argv)
+{
+ int count;
+ const dictDatabase *db;
+
+ lst_Position databasePosition;
+
+ if (argc != 2) {
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+
+ if (!(count = count_databases())) {
+ daemon_printf("%d no databases present\n", CODE_NO_DATABASES);
+ } else {
+ daemon_printf("%d %d databases present\n",
+ CODE_DATABASE_LIST, count);
+
+ databasePosition = first_database_pos();
+
+ daemon_mime();
+ while ((db = next_database(&databasePosition, "*"))) {
+ assert(!db->invisible);
+
+ if (db->exit_db)
+ continue;
+
+ daemon_printf("%s \"%s\"\n",
+ db->databaseName, db->databaseShort);
+ }
+ daemon_printf(".\n");
+ daemon_ok(CODE_OK, "ok", NULL);
+ }
+}
+
+static void daemon_show_strat(const char *cmdline, int argc,
+ const char **argv)
+{
+ int i;
+
+ int strat_count = get_strategy_count();
+ dictStrategy const *const *strats = get_strategies();
+
+ if (argc != 2) {
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+
+ if (strat_count) {
+ daemon_printf("%d %d strategies present\n",
+ CODE_STRATEGY_LIST, strat_count);
+ daemon_mime();
+
+ for (i = 0; i < strat_count; i++) {
+ daemon_printf("%s \"%s\"\n",
+ strats[i]->name, strats[i]->description);
+ }
+
+ daemon_printf(".\n");
+ daemon_ok(CODE_OK, "ok", NULL);
+ } else {
+ daemon_printf("%d no strategies available\n", CODE_NO_STRATEGIES);
+ }
+}
+
+void daemon_show_info(const char *cmdline, int argc, const char **argv)
+{
+ char *buf = NULL;
+ dictWord *dw;
+ const dictDatabase *db;
+ lst_List list;
+ const char *info_entry_name = DICT_INFO_ENTRY_NAME;
+
+ lst_Position databasePosition = first_database_pos();
+
+ if (argc != 3) {
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ return;
+ }
+
+ if ((argv[2][0] == '*' || argv[2][0] == '!') && argv[2][1] == '\0') {
+ daemon_printf("%d invalid database, use SHOW DB for list\n",
+ CODE_INVALID_DB);
+ return;
+ }
+
+ list = lst_create();
+ while ((db = next_database(&databasePosition, argv[2]))) {
+ if (db->databaseInfo && db->databaseInfo[0] != '@') {
+ daemon_printf("%d information for %s\n",
+ CODE_DATABASE_INFO, argv[2]);
+ daemon_mime();
+ daemon_text(db->databaseInfo, 1);
+ daemon_ok(CODE_OK, "ok", NULL);
+ return;
+ }
+
+ if (db->databaseInfo && db->databaseInfo[0] == '@')
+ info_entry_name = db->databaseInfo + 1;
+
+ if (dict_search(list,
+ info_entry_name,
+ db, DICT_STRAT_EXACT, 0, NULL, NULL, NULL)) {
+ int i = 1;
+ int list_size = lst_length(list);
+
+ daemon_printf("%d information for %s\n",
+ CODE_DATABASE_INFO, argv[2]);
+ daemon_mime();
+
+ if (db->virtual_db) {
+ daemon_printf
+ ("The virtual dictionary `%s' includes the following:\n\n",
+ db->databaseName);
+ }
- int max_dbname_len;
+ for (i = 1; i <= list_size; ++i) {
+ dw = lst_nth_get(list, i);
- lst_Position databasePosition = first_database_pos ();
+ daemon_printf("============ %s ============\n",
+ dw->database->databaseName);
- daemon_printf( "%d server information\n", CODE_SERVER_INFO );
- daemon_mime();
+ buf = dict_data_obtain(dw->database, dw);
- /* banner: dictd and OS */
- if (!site_info_no_banner){
- daemon_printf( "%s\n", dict_get_banner(0) );
- }
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
- /* uptime and forks */
- if (!site_info_no_uptime && !inetd){
- tim_stop("dictd");
- uptime = tim_get_real("dictd");
+ if (buf)
+ daemon_text(buf, 0);
+ }
- daemon_printf (
- "On %s: up %s, %d fork%s (%0.1f/hour)\n",
- net_hostname(),
- dict_format_time( uptime ),
- _dict_forks,
- _dict_forks > 1 ? "s" : "",
- (_dict_forks/uptime)*3600.0 );
+ daemon_text("\n", 1);
+ daemon_ok(CODE_OK, "ok", NULL);
- daemon_printf ("\n");
- }
+ dict_destroy_list(list);
- if (!site_info_no_dblist && count_databases()) {
- daemon_printf( "Database Headwords Index Data Uncompressed\n" );
+ return;
+ } else {
+#ifdef USE_PLUGIN
+ call_dictdb_free(DictConfig->dbl);
+#endif
- databasePosition = first_database_pos ();
+ dict_destroy_list(list);
+ daemon_printf("%d information for %s\n",
+ CODE_DATABASE_INFO, argv[2]);
+ daemon_mime();
+ daemon_text("No information available\n", 1);
+ daemon_ok(CODE_OK, "ok", NULL);
+ return;
+ }
+ }
- while (db = next_database (&databasePosition, "*"),
- db != NULL)
- {
- headwords = (db->index ? db->index->headwords : 0);
+ dict_destroy_list(list);
+ daemon_printf("%d invalid database, use SHOW DB for list\n",
+ CODE_INVALID_DB);
+}
- index_size = 0;
- index_size_uom = 'k';
+static int daemon_get_max_dbname_length()
+{
+ size_t max_len = 0;
+ size_t curr_len = 0;
- data_size = 0;
- data_size_uom = 'k';
- data_length = 0;
- data_length_uom= 'k';
+ const dictDatabase *db;
- max_dbname_len = 0;
+ lst_Position databasePosition = first_database_pos();
- assert (!db -> invisible);
+ while (NULL != (db = next_database(&databasePosition, "*"))) {
+ assert(!db->invisible);
- if (db->index){
- index_size = db->index->size/1024 > 10240 ?
- db->index->size/1024/1024 : db->index->size/1024;
- index_size_uom = db->index->size/1024 > 10240 ? 'M' : 'k';
- }
+ if (db->databaseName) {
+ curr_len = strlen(db->databaseName);
- if (db->data){
- data_size = db->data->size/1024 > 10240 ?
- db->data->size/1024/1024 : db->data->size/1024;
- data_size_uom = db->data->size/1024 > 10240 ? 'M' : 'k';
+ if (curr_len > max_len) {
+ max_len = curr_len;
+ }
+ }
+ }
- data_length = db->data->length/1024 > 10240 ?
- db->data->length/1024/1024 : db->data->length/1024;
- data_length_uom = db->data->length/1024 > 10240 ? 'M' : 'k';
- }
+ return (int) max_len;
+}
- max_dbname_len = daemon_get_max_dbname_length ();
+static void daemon_show_server(const char *cmdline,
+ int argc, const char **argv)
+{
+ FILE *str;
+ char buffer[1024];
+ const dictDatabase *db;
+ double uptime;
- daemon_printf(
- "%-*.*s %10i %10i %cB %10i %cB %10i %cB\n",
- max_dbname_len,
- max_dbname_len,
+ int headwords;
- db->databaseName,
- headwords,
+ int index_size;
+ char index_size_uom;
- index_size,
- index_size_uom,
+ int data_size;
+ char data_size_uom;
+ int data_length;
+ char data_length_uom;
- data_size,
- data_size_uom,
+ int max_dbname_len;
- data_length,
- data_length_uom);
- }
+ lst_Position databasePosition = first_database_pos();
- daemon_printf ("\n");
- }
+ daemon_printf("%d server information\n", CODE_SERVER_INFO);
+ daemon_mime();
- if (site_info && (str = fopen( site_info, "r" ))) {
- while ((fgets( buffer, 1000, str ))) daemon_printf( "%s", buffer );
- fclose( str );
- }
- daemon_printf( ".\n" );
- daemon_ok( CODE_OK, "ok", NULL );
-}
+ /* banner: dictd and OS */
+ if (!site_info_no_banner) {
+ daemon_printf("%s\n", dict_get_banner(0));
+ }
-static void daemon_show( const char *cmdline, int argc, const char **argv )
-{
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
-}
+ /* uptime and forks */
+ if (!site_info_no_uptime && !inetd) {
+ tim_stop("dictd");
+ uptime = tim_get_real("dictd");
-static void daemon_option_mime( const char *cmdline, int argc, const char **argv )
-{
- ++daemonMime;
- daemon_ok( CODE_OK, "ok - using MIME headers", NULL );
-}
+ daemon_printf("On %s: up %s, %d fork%s (%0.1f/hour)\n",
+ net_hostname(),
+ dict_format_time(uptime),
+ _dict_forks,
+ _dict_forks > 1 ? "s" : "",
+ (_dict_forks / uptime) * 3600.0);
-static void daemon_option( const char *cmdline, int argc, const char **argv )
-{
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
-}
+ daemon_printf("\n");
+ }
-static void daemon_client( const char *cmdline, int argc, const char **argv )
-{
- const char *pt = strchr( cmdline, ' ' );
-
- if (pt)
- daemon_log( DICT_LOG_CLIENT, "%.200s\n", pt + 1 );
- else
- daemon_log( DICT_LOG_CLIENT, "%.200s\n", cmdline );
- daemon_ok( CODE_OK, "ok", NULL );
-}
+ if (!site_info_no_dblist && count_databases()) {
+ daemon_printf
+ ("Database Headwords Index Data Uncompressed\n");
-static void daemon_auth( const char *cmdline, int argc, const char **argv )
-{
- char *buf;
- hsh_HashTable h = DictConfig->usl;
- const char *secret;
- struct MD5Context ctx;
- unsigned char digest[16];
- char hex[33];
- int i;
- int buf_size;
+ databasePosition = first_database_pos();
- if (argc != 3)
- daemon_printf( "%d syntax error, illegal parameters\n",
- CODE_ILLEGAL_PARAM );
- if (!h || !(secret = hsh_retrieve(h, argv[1]))) {
- daemon_log( DICT_LOG_AUTH, "%s@%s/%s denied: invalid username\n",
- argv[1], daemonHostname, daemonIP );
- daemon_printf( "%d auth denied\n", CODE_AUTH_DENIED );
- return;
- }
+ while (db = next_database(&databasePosition, "*"), db != NULL) {
+ headwords = (db->index ? db->index->headwords : 0);
- buf_size = strlen(daemonStamp) + strlen(secret) + 10;
- buf = alloca(buf_size);
- snprintf( buf, buf_size, "%s%s", daemonStamp, secret );
+ index_size = 0;
+ index_size_uom = 'k';
- MD5Init(&ctx);
- MD5Update(&ctx, (const unsigned char *) buf, strlen(buf));
- MD5Final(digest, &ctx);
+ data_size = 0;
+ data_size_uom = 'k';
+ data_length = 0;
+ data_length_uom = 'k';
- for (i = 0; i < 16; i++)
- snprintf( hex+2*i, 3, "%02x", digest[i] );
+ max_dbname_len = 0;
- hex[32] = '\0';
+ assert(!db->invisible);
- PRINTF(DBG_AUTH,("Got %s expected %s\n", argv[2], hex ));
+ if (db->index) {
+ index_size = db->index->size / 1024 > 10240 ?
+ db->index->size / 1024 / 1024 : db->index->size / 1024;
+ index_size_uom =
+ db->index->size / 1024 > 10240 ? 'M' : 'k';
+ }
- if (strcmp(hex,argv[2])) {
- daemon_log( DICT_LOG_AUTH, "%s@%s/%s denied: hash mismatch\n",
- argv[1], daemonHostname, daemonIP );
- daemon_printf( "%d auth denied\n", CODE_AUTH_DENIED );
- } else {
- daemon_printf( "%d authenticated\n", CODE_AUTH_OK );
- daemon_check_auth( argv[1] );
- }
-}
+ if (db->data) {
+ data_size = db->data->size / 1024 > 10240 ?
+ db->data->size / 1024 / 1024 : db->data->size / 1024;
+ data_size_uom = db->data->size / 1024 > 10240 ? 'M' : 'k';
+
+ data_length = db->data->length / 1024 > 10240 ?
+ db->data->length / 1024 / 1024 : db->data->length /
+ 1024;
+ data_length_uom =
+ db->data->length / 1024 > 10240 ? 'M' : 'k';
+ }
-static void daemon_status( const char *cmdline, int argc, const char **argv )
-{
- daemon_ok( CODE_STATUS, "status", "t" );
-}
+ max_dbname_len = daemon_get_max_dbname_length();
-static void daemon_help( const char *cmdline, int argc, const char **argv )
-{
- daemon_printf( "%d help text follows\n", CODE_HELP );
- daemon_mime();
- daemon_text(
- "DEFINE database word -- look up word in database\n"
- "MATCH database strategy word -- match word in database using strategy\n"
- "SHOW DB -- list all accessible databases\n"
- "SHOW DATABASES -- list all accessible databases\n"
- "SHOW STRAT -- list available matching strategies\n"
- "SHOW STRATEGIES -- list available matching strategies\n"
- "SHOW INFO database -- provide information about the database\n"
- "SHOW SERVER -- provide site-specific information\n"
- "OPTION MIME -- use MIME headers\n"
- "CLIENT info -- identify client to server\n"
- "AUTH user string -- provide authentication information\n"
- "STATUS -- display timing information\n"
- "HELP -- display this help information\n"
- "QUIT -- terminate connection\n\n"
- "The following commands are unofficial server extensions for debugging\n"
- "only. You may find them useful if you are using telnet as a client.\n"
- "If you are writing a client, you MUST NOT use these commands, since\n"
- "they won't be supported on any other server!\n\n"
- "D word -- DEFINE * word\n"
- "D database word -- DEFINE database word\n"
- "M word -- MATCH * . word\n"
- "M strategy word -- MATCH * strategy word\n"
- "M database strategy word -- MATCH database strategy word\n"
- "S -- STATUS\n"
- "H -- HELP\n"
- "Q -- QUIT\n"
- , 1);
- daemon_ok( CODE_OK, "ok", NULL );
+ daemon_printf("%-*.*s %10i %10i %cB %10i %cB %10i %cB\n",
+ max_dbname_len,
+ max_dbname_len,
+ db->databaseName,
+ headwords,
+ index_size,
+ index_size_uom,
+ data_size,
+ data_size_uom, data_length, data_length_uom);
+ }
+
+ daemon_printf("\n");
+ }
+
+ if (site_info && (str = fopen(site_info, "r"))) {
+ while ((fgets(buffer, 1000, str)))
+ daemon_printf("%s", buffer);
+ fclose(str);
+ }
+ daemon_printf(".\n");
+ daemon_ok(CODE_OK, "ok", NULL);
+}
+
+static void daemon_show(const char *cmdline, int argc, const char **argv)
+{
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+}
+
+static void daemon_option_mime(const char *cmdline, int argc,
+ const char **argv)
+{
+ ++daemonMime;
+ daemon_ok(CODE_OK, "ok - using MIME headers", NULL);
+}
+
+static void daemon_option(const char *cmdline, int argc, const char **argv)
+{
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+}
+
+static void daemon_client(const char *cmdline, int argc, const char **argv)
+{
+ const char *pt = strchr(cmdline, ' ');
+
+ if (pt)
+ daemon_log(DICT_LOG_CLIENT, "%.200s\n", pt + 1);
+ else
+ daemon_log(DICT_LOG_CLIENT, "%.200s\n", cmdline);
+ daemon_ok(CODE_OK, "ok", NULL);
+}
+
+static void daemon_auth(const char *cmdline, int argc, const char **argv)
+{
+ char *buf;
+ hsh_HashTable h = DictConfig->usl;
+ const char *secret;
+ struct MD5Context ctx;
+ unsigned char digest[16];
+ char hex[33];
+ int i;
+ int buf_size;
+
+ if (argc != 3)
+ daemon_printf("%d syntax error, illegal parameters\n",
+ CODE_ILLEGAL_PARAM);
+ if (!h || !(secret = hsh_retrieve(h, argv[1]))) {
+ daemon_log(DICT_LOG_AUTH, "%s@%s/%s denied: invalid username\n",
+ argv[1], daemonHostname, daemonIP);
+ daemon_printf("%d auth denied\n", CODE_AUTH_DENIED);
+ return;
+ }
+
+ buf_size = strlen(daemonStamp) + strlen(secret) + 10;
+ buf = alloca(buf_size);
+ snprintf(buf, buf_size, "%s%s", daemonStamp, secret);
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, (const unsigned char *) buf, strlen(buf));
+ MD5Final(digest, &ctx);
+
+ for (i = 0; i < 16; i++)
+ snprintf(hex + 2 * i, 3, "%02x", digest[i]);
+
+ hex[32] = '\0';
+
+ PRINTF(DBG_AUTH, ("Got %s expected %s\n", argv[2], hex));
+
+ if (strcmp(hex, argv[2])) {
+ daemon_log(DICT_LOG_AUTH, "%s@%s/%s denied: hash mismatch\n",
+ argv[1], daemonHostname, daemonIP);
+ daemon_printf("%d auth denied\n", CODE_AUTH_DENIED);
+ } else {
+ daemon_printf("%d authenticated\n", CODE_AUTH_OK);
+ daemon_check_auth(argv[1]);
+ }
+}
+
+static void daemon_status(const char *cmdline, int argc, const char **argv)
+{
+ daemon_ok(CODE_STATUS, "status", "t");
+}
+
+static void daemon_help(const char *cmdline, int argc, const char **argv)
+{
+ daemon_printf("%d help text follows\n", CODE_HELP);
+ daemon_mime();
+ daemon_text
+ ("DEFINE database word -- look up word in database\n"
+ "MATCH database strategy word -- match word in database using strategy\n"
+ "SHOW DB -- list all accessible databases\n"
+ "SHOW DATABASES -- list all accessible databases\n"
+ "SHOW STRAT -- list available matching strategies\n"
+ "SHOW STRATEGIES -- list available matching strategies\n"
+ "SHOW INFO database -- provide information about the database\n"
+ "SHOW SERVER -- provide site-specific information\n"
+ "OPTION MIME -- use MIME headers\n"
+ "CLIENT info -- identify client to server\n"
+ "AUTH user string -- provide authentication information\n"
+ "STATUS -- display timing information\n"
+ "HELP -- display this help information\n"
+ "QUIT -- terminate connection\n\n"
+ "The following commands are unofficial server extensions for debugging\n"
+ "only. You may find them useful if you are using telnet as a client.\n"
+ "If you are writing a client, you MUST NOT use these commands, since\n"
+ "they won't be supported on any other server!\n\n"
+ "D word -- DEFINE * word\n"
+ "D database word -- DEFINE database word\n"
+ "M word -- MATCH * . word\n"
+ "M strategy word -- MATCH * strategy word\n"
+ "M database strategy word -- MATCH database strategy word\n"
+ "S -- STATUS\n"
+ "H -- HELP\n"
+ "Q -- QUIT\n", 1);
+ daemon_ok(CODE_OK, "ok", NULL);
}
-static void daemon_quit( const char *cmdline, int argc, const char **argv )
+static void daemon_quit(const char *cmdline, int argc, const char **argv)
{
- daemon_ok( CODE_GOODBYE, "bye", "t" );
- daemon_terminate( 0, "quit" );
+ daemon_ok(CODE_GOODBYE, "bye", "t");
+ daemon_terminate(0, "quit");
}
/* The whole sub should be moved here, but I want to keep the diff small. */
-int _handleconn (int error);
+int _handleconn(int error);
-int dict_inetd (int error)
+int dict_inetd(int error)
{
- if (setjmp(env)) return 0;
+ if (setjmp(env))
+ return 0;
- daemonPort = -1;
- daemonIP = "inetd";
+ daemonPort = -1;
+ daemonIP = "inetd";
- daemonHostname = daemonIP;
+ daemonHostname = daemonIP;
- daemonS_in = 0;
- daemonS_out = 1;
+ daemonS_in = 0;
+ daemonS_out = 1;
- return _handleconn (error);
+ return _handleconn(error);
}
-int dict_daemon( int s, struct sockaddr_in *csin, int error )
+int dict_daemon(int s, struct sockaddr_storage *csin, char ***argv0,
+ int delay, int error)
{
- struct hostent *h;
-
- if (setjmp(env)) return 0;
+ static char hostname[NI_MAXHOST], service[NI_MAXSERV];
+
+ if (setjmp(env))
+ return 0;
- daemonPort = ntohs(csin->sin_port);
- daemonIP = str_find( inet_ntoa(csin->sin_addr) );
- if ((h = gethostbyaddr((void *)&csin->sin_addr,
- sizeof(csin->sin_addr), csin->sin_family))) {
- daemonHostname = str_find( h->h_name );
- } else
- daemonHostname = daemonIP;
+ getnameinfo((const struct sockaddr *) csin,
+ sizeof(struct sockaddr_storage), hostname, NI_MAXHOST,
+ service, NI_MAXSERV, NI_NUMERICSERV);
- daemonS_in = s;
- daemonS_out = s;
+ daemonPort = strtol(service, NULL, 10);
+ daemonIP = str_find(inet_ntopW((struct sockaddr *) csin));
+ daemonHostname = str_find(hostname);
+ daemonS_in = daemonS_out = s;
- return _handleconn (error);
+ return _handleconn(delay, error);
}
-int _handleconn (int error) {
- int query_count = 0;
- char buf[4096];
- int count;
- arg_List cmdline;
- int argc;
- char **argv;
- void (*command)(const char *, int, const char **);
+int _handleconn(int error)
+{
+ int query_count = 0;
+ char buf[4096];
+ int count;
+ arg_List cmdline;
+ int argc;
+ char **argv;
+ void (*command) (const char *, int, const char **);
- _dict_defines = 0;
- _dict_matches = 0;
- _dict_comparisons = 0;
+ _dict_defines = 0;
+ _dict_matches = 0;
+ _dict_comparisons = 0;
- tim_start( "t" );
- daemon_log( DICT_LOG_TRACE, "connected\n" );
- daemon_log( DICT_LOG_CONNECT, "%s/%s connected on port %d\n",
- daemonHostname, daemonIP, daemonPort );
- dict_setproctitle( "dictd: %s connected", daemonHostname );
+ tim_start("t");
+ daemon_log(DICT_LOG_TRACE, "connected\n");
+ daemon_log(DICT_LOG_CONNECT, "%s/%s connected on port %d\n",
+ daemonHostname, daemonIP, daemonPort);
+ dict_setproctitle("dictd: %s connected", daemonHostname);
- if (error) {
- daemon_printf( "%d server temporarily unavailable\n",
- CODE_TEMPORARILY_UNAVAILABLE );
- daemon_terminate( 0, "temporarily unavailable" );
- }
+ if (error) {
+ daemon_printf("%d server temporarily unavailable\n",
+ CODE_TEMPORARILY_UNAVAILABLE);
+ daemon_terminate(0, "temporarily unavailable");
+ }
- if (daemon_check_auth( NULL )) {
- daemon_log( DICT_LOG_AUTH, "%s/%s denied: ip/hostname rules\n",
- daemonHostname, daemonIP );
- daemon_printf( "%d access denied\n", CODE_ACCESS_DENIED );
- daemon_terminate( 0, "access denied" );
- }
+ if (daemon_check_auth(NULL)) {
+ daemon_log(DICT_LOG_AUTH, "%s/%s denied: ip/hostname rules\n",
+ daemonHostname, daemonIP);
+ daemon_printf("%d access denied\n", CODE_ACCESS_DENIED);
+ daemon_terminate(0, "access denied");
+ }
- daemon_banner();
+ daemon_banner();
- if (!_dict_daemon_limit_time)
- alarm (client_delay);
+ if (!_dict_daemon_limit_time)
+ alarm(client_delay);
- while (count = daemon_read( buf, 4000 ), count >= 0) {
- ++query_count;
+ while (count = daemon_read(buf, 4000), count >= 0) {
+ ++query_count;
- if (_dict_daemon_limit_queries &&
- query_count >= _dict_daemon_limit_queries)
- {
- daemon_terminate (0, "query limit");
- }
+ if (_dict_daemon_limit_queries &&
+ query_count >= _dict_daemon_limit_queries) {
+ daemon_terminate(0, "query limit");
+ }
- if (stdin2stdout_mode){
- daemon_printf( "# %s\n", buf );
- }
+ if (stdin2stdout_mode) {
+ daemon_printf("# %s\n", buf);
+ }
- if (!_dict_daemon_limit_time)
- alarm(0);
+ if (!_dict_daemon_limit_time)
+ alarm(0);
- tim_start( "c" );
- if (!count) {
+ tim_start("c");
+ if (!count) {
#if 0
- daemon_ok( CODE_OK, "ok", "c" );
+ daemon_ok(CODE_OK, "ok", "c");
#endif
- continue;
- }
+ continue;
+ }
- daemon_log( DICT_LOG_COMMAND, "%.80s\n", buf );
- cmdline = arg_argify(buf,0);
- arg_get_vector( cmdline, &argc, &argv );
- if ((command = lookup_command (argc, (const char **) argv))) {
- command(buf, argc, (const char **) argv);
- } else {
- daemon_printf( "%d unknown command\n", CODE_SYNTAX_ERROR );
- }
- arg_destroy(cmdline);
-
- if (!_dict_daemon_limit_time)
- alarm (client_delay);
- }
+ daemon_log(DICT_LOG_COMMAND, "%.80s\n", buf);
+ cmdline = arg_argify(buf, 0);
+ arg_get_vector(cmdline, &argc, &argv);
+ if ((command = lookup_command(argc, (const char **) argv))) {
+ command(buf, argc, (const char **) argv);
+ } else {
+ daemon_printf("%d unknown command\n", CODE_SYNTAX_ERROR);
+ }
+ arg_destroy(cmdline);
+
+ if (!_dict_daemon_limit_time)
+ alarm(client_delay);
+ }
#if 0
- printf( "%d %d\n", count, errno );
+ printf("%d %d\n", count, errno);
#endif
- daemon_terminate( 0, "close" );
- return 0;
+ daemon_terminate(0, "close");
+ return 0;
}
--- a/net.c
+++ b/net.c
@@ -1,18 +1,18 @@
-/* net.c --
+/* net.c --
* Created: Fri Feb 21 20:58:10 1997 by faith@dict.org
* Copyright 1997, 1998, 1999, 2000, 2002 Rickard E. Faith (faith@dict.org)
* Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
- *
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 1, or (at your option) any
* later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -25,7 +25,7 @@
#include "dictP.h"
#if HAVE_SYS_PARAM_H
-# include <sys/param.h>
+#include <sys/param.h>
#endif
#include <fcntl.h>
@@ -42,146 +42,180 @@
static char netHostname[MAXHOSTNAMELEN];
-const char *net_hostname( void )
+const char *inet_ntopW(struct sockaddr *sa)
{
- struct hostent *hostEntry;
- static char *hostname = NULL;
-
- if (!netHostname[0]) {
- memset( netHostname, 0, sizeof(netHostname) );
- gethostname( netHostname, sizeof(netHostname)-1 );
-
- if ((hostEntry = gethostbyname(netHostname))) {
- hostname = xstrdup(hostEntry->h_name);
- } else {
- hostname = xstrdup(netHostname);
- }
- }
-
- return hostname;
-}
-
-int net_connect_tcp( const char *host, const char *service )
-{
- struct hostent *hostEntry;
- struct servent *serviceEntry;
- struct protoent *protocolEntry;
- struct sockaddr_in ssin;
- int s;
- int hosts = 0;
- char **current;
-
- memset( &ssin, 0, sizeof(ssin) );
- ssin.sin_family = AF_INET;
-
- if ((serviceEntry = getservbyname(service, "tcp"))) {
- ssin.sin_port = serviceEntry->s_port;
- } else if (!(ssin.sin_port = htons(atoi(service))))
- return NET_NOSERVICE;
-
- if (!(protocolEntry = getprotobyname("tcp")))
- return NET_NOPROTOCOL;
-
- if ((hostEntry = gethostbyname(host))) {
- ++hosts;
- } else if ((ssin.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE))
- return NET_NOHOST;
-
- if (hosts) {
- for (current = hostEntry->h_addr_list; *current; current++) {
- memcpy( &ssin.sin_addr.s_addr, *current, hostEntry->h_length );
- PRINTF(DBG_VERBOSE,
- ("Trying %s (%s)\n",host,inet_ntoa(ssin.sin_addr)));
- if ((s = socket(PF_INET, SOCK_STREAM, protocolEntry->p_proto)) < 0)
- err_fatal_errno( __func__, "Can't open socket on port %d\n",
- ntohs(ssin.sin_port) );
- if (connect(s, (struct sockaddr *)&ssin, sizeof(ssin)) >= 0)
+ static char str[40];
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ return inet_ntop(sa->sa_family,
+ &(((struct sockaddr_in *) sa)->sin_addr), str,
+ 16);
+ case AF_INET6:
+ return inet_ntop(sa->sa_family,
+ &(((struct sockaddr_in6 *) sa)->sin6_addr), str,
+ 40);
+ default:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+}
+
+const char *net_hostname(void)
+{
+ struct hostent *hostEntry;
+ static char *hostname = NULL;
+
+ if (!netHostname[0]) {
+ memset(netHostname, 0, sizeof(netHostname));
+ gethostname(netHostname, sizeof(netHostname) - 1);
+
+ if ((hostEntry = gethostbyname(netHostname))) {
+ hostname = xstrdup(hostEntry->h_name);
+ } else {
+ hostname = xstrdup(netHostname);
+ }
+ }
+
+ return hostname;
+}
+
+int net_connect_tcp(const char *host, const char *service)
+{
+ struct addrinfo hints, *r, *rtmp;
+ int s;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+ if (getaddrinfo(host, service, &hints, &r) != 0)
+ return NET_NOHOST;
+
+ for (rtmp = r; r != NULL; r = r->ai_next) {
+ s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if (s < 0) {
+ if (r->ai_next != NULL)
+ continue;
+ else
+ err_fatal_errno(__FUNCTION__, "Can't open socket\n");
+ }
+
+ PRINTF(DBG_VERBOSE,
+ ("Trying %s (%s)...", host, inet_ntopW(r->ai_addr)));
+
+ if (connect(s, r->ai_addr, r->ai_addrlen) >= 0) {
+ PRINTF(DBG_VERBOSE, ("Connected."));
+ freeaddrinfo(rtmp);
return s;
- close(s);
- }
- } else {
- if ((s = socket(PF_INET, SOCK_STREAM, protocolEntry->p_proto)) < 0)
- err_fatal_errno( __func__, "Can't open socket on port %d\n",
- ntohs(ssin.sin_port) );
- if (connect(s, (struct sockaddr *)&ssin, sizeof(ssin)) >= 0)
- return s;
- close(s);
- }
-
- return NET_NOCONNECT;
-}
-
-int net_open_tcp (
- const char *address,
- const char *service,
- int queueLength)
-{
- struct servent *serviceEntry;
- struct protoent *protocolEntry;
- struct sockaddr_in ssin;
- int s;
- const int one = 1;
-
- memset( &ssin, 0, sizeof(ssin) );
- ssin.sin_family = AF_INET;
- ssin.sin_addr.s_addr = address ? inet_addr(address) : htonl(INADDR_ANY);
-
- if ((serviceEntry = getservbyname(service, "tcp"))) {
- ssin.sin_port = serviceEntry->s_port;
- } else if (!(ssin.sin_port = htons(atoi(service))))
- err_fatal( __func__, "Can't get \"%s\" service entry\n", service );
-
- if (!(protocolEntry = getprotobyname("tcp")))
- err_fatal( __func__, "Can't get \"tcp\" protocol entry\n" );
-
- if ((s = socket(PF_INET, SOCK_STREAM, protocolEntry->p_proto)) < 0)
- err_fatal_errno( __func__, "Can't open socket on port %d\n",
- ntohs(ssin.sin_port) );
-
- setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one) );
-
- if (bind(s, (struct sockaddr *)&ssin, sizeof(ssin)) < 0)
- err_fatal_errno( __func__, "Can't bind %s/tcp to port %d\n",
- service, ntohs(ssin.sin_port) );
-
- if (listen( s, queueLength ) < 0)
- err_fatal_errno( __func__, "Can't listen to %s/tcp on port %d\n",
- service, ntohs(ssin.sin_port) );
-
- return s;
-}
-
-int net_read( int s, char *buf, int maxlen )
-{
- int len;
- int n = 0;
- char c;
- char *pt = buf;
-
- *pt = '\0';
-
- for (len = 0; len < maxlen && (n = read( s, &c, 1 )) > 0; /*void*/) {
- switch (c) {
- case '\n': *pt = '\0'; return len;
- case '\r': break;
- default: *pt++ = c; ++len; break;
- }
- }
- *pt = '\0';
- if (!n) return len ? len : EOF;
- return n; /* error code */
-}
-
-int net_write( int s, const char *buf, int len )
-{
- int left = len;
- int count;
-
- while (left) {
- if ((count = write(s, buf, left)) != left) {
- if (count <= 0) return count; /* error code */
- }
- left -= count;
- }
- return len;
+ }
+
+ PRINTF(DBG_VERBOSE, ("Failed: %s\n", strerror(errno)));
+
+ close(s);
+ }
+ freeaddrinfo(rtmp);
+
+ return NET_NOCONNECT;
+}
+
+int net_open_tcp(const char *address, const char *service, int queueLength)
+{
+ struct addrinfo hints, *r, *rtmp;
+ int s = -1;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ if (getaddrinfo(address, service, &hints, &r) != 0)
+ err_fatal(__FUNCTION__,
+ "getaddrinfo: Failed, address = \"%s\", service = \"%s\"\n",
+ address, service);
+
+ for (rtmp = r; r != NULL; r = r->ai_next) {
+ s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+
+ if (s < 0) {
+ if (r->ai_next != NULL)
+ continue;
+ freeaddrinfo(rtmp);
+ err_fatal_errno(__FUNCTION__, "Can't open socket\n");
+ }
+
+ {
+ const int one = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ }
+
+ if (bind(s, r->ai_addr, r->ai_addrlen) < 0) {
+ if (r->ai_next != NULL) {
+ close(s);
+ continue;
+ }
+ freeaddrinfo(rtmp);
+ err_fatal_errno(__FUNCTION__, "Can't bind %s/tcp to %s\n",
+ service, address ? address : "ANY");
+ }
+
+ if (listen(s, queueLength) < 0) {
+ if (r->ai_next != NULL) {
+ close(s);
+ continue;
+ }
+ freeaddrinfo(rtmp);
+ err_fatal_errno(__FUNCTION__, "Can't listen to %s/tcp on %s\n",
+ service, address);
+ }
+ }
+ freeaddrinfo(rtmp);
+
+ return s;
+}
+
+int net_read(int s, char *buf, int maxlen)
+{
+ int len;
+ int n = 0;
+ char c;
+ char *pt = buf;
+
+ *pt = '\0';
+
+ for (len = 0; len < maxlen && (n = read(s, &c, 1)) > 0; /*void */ ) {
+ switch (c) {
+ case '\n':
+ *pt = '\0';
+ return len;
+ case '\r':
+ break;
+ default:
+ *pt++ = c;
+ ++len;
+ break;
+ }
+ }
+ *pt = '\0';
+ if (!n)
+ return len ? len : EOF;
+ return n; /* error code */
+}
+
+int net_write(int s, const char *buf, int len)
+{
+ int left = len;
+ int count;
+
+ while (left) {
+ if ((count = write(s, buf, left)) != left) {
+ if (count <= 0)
+ return count; /* error code */
+ }
+ left -= count;
+ }
+ return len;
}
--- a/net.h
+++ b/net.h
@@ -18,14 +18,14 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
-extern const char *net_hostname( void );
-extern int net_connect_tcp( const char *host, const char *service );
-extern int net_open_tcp (const char *address,
- const char *service, int queueLength);
-extern void net_detach( void );
-extern int net_read( int s, char *buf, int maxlen );
-extern int net_write( int s, const char *buf, int len );
+extern const char *inet_ntopW(struct sockaddr *sa);
+extern const char *net_hostname(void);
+extern int net_connect_tcp(const char *host, const char *service);
+extern int net_open_tcp(const char *address,
+ const char *service, int queueLength);
+extern void net_detach(void);
+extern int net_read(int s, char *buf, int maxlen);
+extern int net_write(int s, const char *buf, int len);
#define NET_NOHOST (-1)
#define NET_NOSERVICE (-2)