3f55ce16c6
Clean up SPEC file, make the package building again. OBS-URL: https://build.opensuse.org/request/show/642025 OBS-URL: https://build.opensuse.org/package/show/Education/dictd?expand=0&rev=4
10217 lines
271 KiB
Diff
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)
|