X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=kernel%2Furp.c;h=ef3378c4b28e1138728b20242edb8ac411764f72;hb=918a8257a2f64e0965abc4c48eea774949c19883;hp=1197a6cc3af96e2e2f5ef9a6b8bed2068a717020;hpb=27f77c83ecdd2452bc6756bfdc6b9ebc9703298a;p=egate.git diff --git a/kernel/urp.c b/kernel/urp.c index 1197a6c..ef3378c 100644 --- a/kernel/urp.c +++ b/kernel/urp.c @@ -1,8 +1,130 @@ -/* Gateway kernel +/* + * Copyright (c) 1995, the EUROPAGATE consortium (see below). + * + * The EUROPAGATE consortium members are: + * + * University College Dublin + * Danmarks Teknologiske Videnscenter + * An Chomhairle Leabharlanna + * Consejo Superior de Investigaciones Cientificas + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation, in whole or in part, for any purpose, is hereby granted, + * provided that: + * + * 1. This copyright and permission notice appear in all copies of the + * software and its documentation. Notices of copyright or attribution + * which appear at the beginning of any file must remain unchanged. + * + * 2. The names of EUROPAGATE or the project partners may not be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * 3. Users of this software (implementors and gateway operators) agree to + * inform the EUROPAGATE consortium of their use of the software. This + * information will be used to evaluate the EUROPAGATE project and the + * software, and to plan further developments. The consortium may use + * the information in later publications. + * + * 4. Users of this software agree to make their best efforts, when + * documenting their use of the software, to acknowledge the EUROPAGATE + * consortium, and the role played by the software in their work. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE + * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF + * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND + * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* Gateway kernel - User Request Processor * Europagate, 1995 * * $Log: urp.c,v $ - * Revision 1.24 1995/03/28 11:42:35 adam + * Revision 1.48 1996/02/12 10:04:57 adam + * The gateway doesn't try to reconnect if it is already known that + * it will fail (connect_fail flag introduced). + * + * Revision 1.47 1996/01/18 13:54:48 adam + * Help gives help information about individual commands. + * Status without arguments gives list of available predefined targets. + * + * Revision 1.46 1995/07/28 10:51:09 adam + * Bug fix: account from previous session had effect when new target command + * was executed. + * + * Revision 1.45 1995/07/20 08:20:24 adam + * Minor changes. + * + * Revision 1.44 1995/07/11 12:28:53 adam + * New functions ccl_token_simple and ccl_token_del used. + * + * Revision 1.43 1995/07/11 11:49:13 adam + * LINE_MAX renamed to STR_LINE_MAX. + * + * Revision 1.42 1995/07/03 12:59:29 adam + * New option for eti: -c dir to chdir before start. + * Setting change: gw.max.show defaults to 100. + * + * Revision 1.41 1995/07/03 08:20:18 adam + * More help information and better diagnostics. + * + * Revision 1.40 1995/05/23 08:13:00 adam + * Minor changes. + * + * Revision 1.39 1995/05/22 14:57:30 adam + * Next default record position also set by last p=... in show. + * + * Revision 1.38 1995/05/19 13:26:00 adam + * Bug fixes. Better command line options. + * + * Revision 1.37 1995/05/18 12:03:09 adam + * Bug fixes and minor improvements. + * + * Revision 1.36 1995/05/17 10:51:33 adam + * Added a few more error checks to the show command. + * + * Revision 1.35 1995/05/16 09:40:43 adam + * LICENSE. Setting of CCL token names (and/or/not/set) in read_kernel_res. + * + * Revision 1.34 1995/05/04 10:40:08 adam + * More work on Def-settings. + * + * Revision 1.33 1995/05/03 16:34:19 adam + * CCL def command, i.e. user definitions - saved as resource files. + * + * Revision 1.32 1995/05/03 07:37:46 adam + * CCL commands stop/continue implemented. New functions gw_res_{int,bool} + * are used when possible. + * + * Revision 1.31 1995/05/01 12:43:38 adam + * First work on resource monitor program. + * + * Revision 1.30 1995/04/20 16:10:47 adam + * Modified to work with non-blocking zass-api. Not using non-blocking + * facility yet. + * + * Revision 1.29 1995/04/19 16:01:58 adam + * Some hacks to get the FIFO communication work!! Isn't reliable. + * Resource gw.account added - default account info. + * + * Revision 1.28 1995/04/19 13:19:09 adam + * New command: account - for authentication. + * + * Revision 1.27 1995/04/19 10:46:19 adam + * Persistency works much better now. New command: status - history-like + * + * Revision 1.26 1995/04/19 07:31:12 adam + * First work on Z39.50 persistence. + * + * Revision 1.25 1995/04/17 09:34:33 adam + * Timeout (idletime) adjustable. Minor changes in kernel. + * + * Revision 1.24 1995/03/28 11:42:35 adam * First use of string-queue utility. * * Revision 1.23 1995/03/28 08:01:28 adam @@ -83,6 +205,15 @@ * */ +/* + Todo: + info/status (other name?) + better persistence diagnostics + + Optional: + automatic information about target-aliases: name, query-support, etc. + */ + #include #include #include @@ -91,11 +222,15 @@ #include #include +#include +#include #include #include "kernel.h" -#define LINE_MAX 1024 -static char line_buf[LINE_MAX+1]; +static void present (const char *set, int offset, int number, + struct ccl_token *format_token); + +static char line_buf[STR_LINE_MAX+1]; static void put_esc_str (const char *s) { @@ -103,41 +238,23 @@ static void put_esc_str (const char *s) tty_emit (*s++); } -int lgets (char *buf, int max, int fd) -{ - int r, no = 0; - - --max; - while (no <= max) - { - if ((r=read (fd, buf+no, 1)) != 1) - { - if (r == -1) - gw_log (GW_LOG_WARN|GW_LOG_ERRNO, KERNEL_LOG, "read fail"); - buf[no] = '\0'; - return 0; - } - if (buf[no] == 1) - return 0; - if (buf[no++] == '\n') - break; - } - buf[no] = '\0'; - return 1; -} - -static int reopen_target (void) +int reopen_target (void) { const char *v; if (info.zass) gw_log (GW_LOG_WARN, KERNEL_LOG, "Zass free..."); - info.zass = zass_open (info.hostname, info.port); + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "reopen_target"); + info.zass = zass_open (info.hostname, info.port, NULL, /* complete */ + *info.account ? info.account : NULL); if (!info.zass) { + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Cannot connect to target %s:%d", + info.hostname, info.port); fprintf (reply_fd, "%s %s:%d\n", gw_res_get (info.kernel_res, "gw.err.connect", "Cannot connect to target"), info.hostname, info.port); + info.connect_failed = 1; return -1; } v = gw_res_get (info.kernel_res, "gw.description", NULL); @@ -151,45 +268,34 @@ static int reopen_target (void) "Connection established to"), info.hostname, info.port); if (*info.databases) - fprintf (reply_fd, "%s:\n%s\n", + fprintf (reply_fd, "%s: %s\n", gw_res_get (info.kernel_res, "gw.msg.databases", "Available databases"), info.databases); if (*info.database) - fprintf (reply_fd, "%s:\n%s\n", + fprintf (reply_fd, "%s: %s\n", gw_res_get (info.kernel_res, "gw.msg.database", "Selected databases"), info.database); + if (info.setno >= 0) + fprintf (reply_fd, "set=%d\n", info.setno); + else + fprintf (reply_fd, "set=Default\n"); return 0; } - -static struct command_word { +struct command_word { char *default_value; char *resource_suffix; -} command_tab [] = -{ -{ "find", "find"}, -{ "show", "show"}, -{ "base", "base" }, -{ "help", "help" }, -{ "info", "info" }, -{ "continue", "continue" }, -{ "status", "status" }, -{ "cancel", "cancel" }, -{ "target", "target" }, -{ "stop", "stop" }, -{ NULL, NULL } }; -static int command_search (struct command_word *tab, struct ccl_token *cmd, -const char *resource_prefix) +static int command_search_str (struct command_word *tab, const char *cmd_name, + int cmd_len, const char *resource_prefix) { int no = 1; assert (resource_prefix); assert (tab); - assert (cmd); while (tab->default_value) { char *cp, command_names[60]; @@ -208,8 +314,8 @@ const char *resource_prefix) if ((split = strchr (cp, ' '))) *split = '\0'; - if (cmd->len == strlen(cp) && - !memcmp (cmd->name, cp, cmd->len)) + if (cmd_len == strlen(cp) && + !memcmp (cmd_name, cp, cmd_len)) return no; if (!split) break; @@ -221,6 +327,12 @@ const char *resource_prefix) return 0; } +static int command_search (struct command_word *tab, struct ccl_token *cmd, + const char *resource_prefix) +{ + return command_search_str (tab, cmd->name, cmd->len, resource_prefix); +} + static struct error_no_struct { int no; char *resource_name; @@ -258,7 +370,7 @@ static int email_header (struct str_queue *sq, { *from_str = '\0'; *subject_str = '\0'; - while (str_queue_deq (sq, line_buf, LINE_MAX)) + while (str_queue_deq (sq, line_buf, STR_LINE_MAX)) { if (line_buf[0] == '\n') return 0; @@ -277,29 +389,83 @@ static void help_general (void) "Commands available in this service:\n")); } +static struct command_word command_tab [] = +{ +{ "find", "find"}, +{ "show", "show"}, +{ "base", "base" }, +{ "help", "help" }, +{ "info", "info" }, +{ "continue", "continue" }, +{ "status", "status" }, +{ "stop", "stop" }, +{ "target", "target" }, +{ "def", "def" }, +{ "account", "account" }, +{ NULL, NULL } +}; + + static int exec_help (struct ccl_token *list) { + int no = 0; static char *sep = "-------------------------------\\n"; - help_general (); + if (list->kind != CCL_TOK_EOL) + no = command_search_str (command_tab, list->name, list->len, + "ccl.command."); + if (!no) + help_general (); -#if 1 - put_esc_str (sep); - put_esc_str (gw_res_get (info.kernel_res, "gw.help.target", - "target - selects a given target\n")); + if (!no || no == 9) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.target", + "target - selects a given target\n")); + } - put_esc_str (sep); - put_esc_str (gw_res_get (info.kernel_res, "gw.help.base", + if (!no || no == 3) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.base", "base .. - selects databases\n")); + } - put_esc_str (sep); - put_esc_str (gw_res_get (info.kernel_res, "gw.help.find", - "find - performs a search request\n")); + if (!no || no == 1) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.find", + "find - performs a search\n")); + } + + if (!no || no == 2) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.show", + "show - retrieves and displays " + "records\n")); + } + + if (!no || no == 10) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.def", + "def user definitons\n")); + } + + if (!no || no == 11) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.account", + "account sets authentication\n")); + } + + if (!no || no == 7) + { + put_esc_str (sep); + put_esc_str (gw_res_get (info.kernel_res, "gw.help.status", + "status status information\n")); + } - put_esc_str (sep); - put_esc_str (gw_res_get (info.kernel_res, "gw.help.show", - "show - retrieves and displays " - "records\n")); -#endif return 0; } @@ -315,16 +481,24 @@ static void display_diag_error (int code, const char *addinfo) gw_res_get (info.kernel_res, str, ""), addinfo); } -static int exec_find (struct ccl_token *list) +static int exec_find (struct ccl_token *list, const char *search_str) { const struct zass_searchent *p; struct gw_user_set *us; + char setname[32]; + int autoshow; struct ccl_rpn_node *rpn; int error; const char *pos; - us = user_set_add ("Default", -1); + if (info.setno == -1) + strcpy (setname, "Default"); + else + sprintf (setname, "%d", info.setno); + info.next_position = 1; + if (info.setno >= 0) + info.setno++; rpn = ccl_find (info.bibset, list, &error, &pos); if (!rpn) { @@ -357,17 +531,83 @@ static int exec_find (struct ccl_token *list) gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Searching in database %s", info.database ); assert (info.zass); - p = zass_search (info.zass, rpn, "Default", info.database ); + p = zass_p_search (info.zass, rpn, setname, info.database, info.sets); if (!p) + { + fprintf (reply_fd, "%s\n", + gw_res_get (info.kernel_res, "gw.err.search.fail", + "Search fail.")); return -1; + } if (p->errcode != -1) { display_diag_error (p->errcode, p->errstring); return -2; } - fprintf (reply_fd, "%d %s\n", p->num, - gw_res_get (info.kernel_res, "gw.msg.hits", "hit(s)")); - us->hits = p->num; + fprintf (reply_fd, "%d %s %s\n", p->num, + gw_res_get (info.kernel_res, "gw.msg.hits", "hit(s) in set "), + setname); + us = user_set_add (setname, p->num, info.database, rpn, 1, search_str); + autoshow = gw_res_int (info.kernel_res, "gw.auto.show", 0); + if (autoshow && p->num > 0) + { + if (autoshow > p->num) + { + present (setname, 1, p->num, NULL); + info.next_position = 1+p->num; + } + else + { + present (setname, 1, autoshow, NULL); + info.next_position = 1+autoshow; + } + } + return 0; +} + +static int exec_account (struct ccl_token *list) +{ + if (list->kind != CCL_TOK_EOL) + { + int len = list->len; + memcpy (info.account, list->name, len); + info.target[len] = '\0'; + } + else + *info.account = '\0'; + info.account_in_session = 1; + return 0; +} + +void handle_target_list (const char *name, const char *value) +{ + GwRes res; + const char *p; + + if (strlen(name) < 10) + return; + if (memcmp (name, "gw.target.", 10)) + return; + fprintf (reply_fd, "%s\n", name+10); + res = gw_res_init (); + gw_res_merge (res, value); + p = gw_res_get (res, "gw.description", NULL); + if (p) + { + put_esc_str (p); + put_esc_str ("\\n"); + } + p = gw_res_get (res, "gw.databases", NULL); + if (p) + fprintf (reply_fd, " Databases: %s\n", p); + fprintf (reply_fd, "\n"); + gw_res_close (res); +} + +static int exec_target_list (void) +{ + gw_res_trav (info.kernel_res, NULL, handle_target_list); + fprintf (reply_fd, "\n"); return 0; } @@ -375,15 +615,38 @@ static int exec_target (struct ccl_token *list) { int len; if (list->kind == CCL_TOK_EOL) - return -1; + return exec_target_list (); len = list->len; memcpy (info.target, list->name, len); info.target [len] = '\0'; - + + if (!info.account_in_session) + *info.account = '\0'; + info.account_in_session = 0; read_kernel_res (); + info.connect_failed = 0; return reopen_target (); } +static void exec_status_r (struct gw_user_set *sp) +{ + if (!sp) + return; + exec_status_r (sp->prev); + fprintf (reply_fd, "%6s %7d %12.12s %.50s\n", sp->name, sp->hits, + sp->database, sp->search_str); +} + +static int exec_status (struct ccl_token *list) +{ + fprintf (reply_fd, "%s\n", + gw_res_get (info.kernel_res, + "gw.msg.statusline", + " Name Hits Database Find")); + exec_status_r (info.sets); + return 0; +} + static int exec_base (struct ccl_token *list) { struct ccl_token *li = list; @@ -417,13 +680,6 @@ static int exec_base (struct ccl_token *list) return 0; } -struct command_word show_tab [] = -{ -{ "f", "format"}, -{ "p", "position"}, -{ NULL, NULL } -}; - static void present (const char *set, int offset, int number, struct ccl_token *format_token) { @@ -432,19 +688,17 @@ static void present (const char *set, int offset, int number, int max_number; char format_str[16]; - max_number = atoi (gw_res_get (info.kernel_res, "gw.max.show", - "200")); + max_number = gw_res_int (info.kernel_res, "gw.max.show", 100); if (number > max_number) number = max_number; gw_log (GW_LOG_DEBUG, KERNEL_LOG, "present in set %s", set); gw_log (GW_LOG_DEBUG, KERNEL_LOG, "present of %d records from offset %d", number, offset); - zp = zass_present(info.zass, (char *) set, offset, number); + zp = zass_p_present(info.zass, (char *) set, offset, number); if (zp) { int i; zass_record *pp; - char path[128]; int record_log_fd = -1; const char *record_log_name; @@ -452,17 +706,16 @@ static void present (const char *set, int offset, int number, NULL); if (record_log_name) { - sprintf (path, "%s/%s", gw_res_get (info.kernel_res, - "gw.path", "."), - record_log_name ); - record_log_fd = open (path, O_WRONLY|O_CREAT|O_APPEND, 0666); + record_log_fd = open (record_log_name, + O_WRONLY|O_CREAT|O_APPEND, 0666); if (record_log_fd == -1) - gw_log (GW_LOG_WARN|GW_LOG_ERRNO, "Cannot open %s", path); + gw_log (GW_LOG_WARN|GW_LOG_ERRNO, "Cannot open %s", + record_log_name); } fprintf (reply_fd, gw_res_get (info.kernel_res, "gw.msg.records", - "Got %d records"), - zp->num); + "Got %d records from set %s"), + zp->num, set); fprintf (reply_fd, "\n"); for (i = 0, pp = zp->records; pp; pp = pp->next, i++) { @@ -492,6 +745,9 @@ static void present (const char *set, int offset, int number, if (rec) { #if USE_FML + strcpy (format_str, + gw_res_get (info.kernel_res, + "gw.display.format", "")); if (format_token) { len = format_token->len; @@ -500,7 +756,7 @@ static void present (const char *set, int offset, int number, memcpy (format_str, format_token->name, len); format_str[len] = '\0'; } - if (info.fml && format_token && + if (info.fml && *format_str && (!strcmp (format_str, "0") || !strcmp (format_str, "1") || !strcmp(format_str, "2"))) { @@ -528,6 +784,12 @@ static void present (const char *set, int offset, int number, static int exec_show (struct ccl_token *list) { + static struct command_word show_tab [] = + { + { "f", "format"}, + { "p", "position"}, + { NULL, NULL } + }; char tmp_str[20]; struct ccl_token *set_token = NULL; struct ccl_token *format_token = NULL; @@ -572,7 +834,19 @@ static int exec_show (struct ccl_token *list) li = li->next; } else + { + int len = li->len; + memcpy (tmp_str, li->name, len); + tmp_str[len] = '\0'; + if (atoi(tmp_str) <= 0) + { + fprintf (reply_fd, "%s\n", + gw_res_get (info.kernel_res, "gw.err.bad.show", + "Syntax error")); + return -3; + } li = li->next; + } } if (set_token) gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Got set=%.*s", set_token->len, @@ -608,6 +882,15 @@ static int exec_show (struct ccl_token *list) memcpy (tmp_str, li->name, len); tmp_str [len] = '\0'; number = atoi (tmp_str) - offset + 1; + if (number <= 0) + { + fprintf (reply_fd, "%s\n", + gw_res_get (info.kernel_res, + "gw.err.pos.show", + "Starting position " + "greater than ending position")); + return -3; + } } else { @@ -620,7 +903,7 @@ static int exec_show (struct ccl_token *list) } li = li->next; } - else + else if (li->kind == CCL_TOK_TERM) { len = li->len; memcpy (tmp_str, li->name, len); @@ -649,6 +932,7 @@ static int exec_show (struct ccl_token *list) if (offset+number-1 > us->hits) number = us->hits - offset+1; present (us->name, offset, number, format_token); + info.next_position = offset+number; } } else if (!no_of_present) /* display error message once! */ @@ -668,12 +952,20 @@ static int exec_show (struct ccl_token *list) us = user_set_search (NULL); if (us && us->hits != -1) /* proper result-set? */ { - default_show = atoi (gw_res_get (info.kernel_res, - "gw.default.show", "20")); - if (us->hits > default_show) - present (us->name, 1, default_show, format_token); - else if (us->hits > 0) - present (us->name, 1, us->hits, format_token); + default_show = gw_res_int (info.kernel_res, "gw.default.show", 20); + if (us->hits >= info.next_position + default_show) + { + present (us->name, info.next_position, default_show, + format_token); + info.next_position += default_show; + } + else if (us->hits >= info.next_position) + { + present (us->name, info.next_position, + us->hits - info.next_position + 1, + format_token); + info.next_position = us->hits + 1; + } } else /* display error message */ { @@ -686,42 +978,177 @@ static int exec_show (struct ccl_token *list) return 0; } -static int exec_command (const char *str) +static void show_def (void) { - struct ccl_token *cmd = ccl_tokenize (str); - int no; + fprintf (reply_fd, "format %s\n", gw_res_get + (info.kernel_res, "gw.display.format", "")); + fprintf (reply_fd, "autoshow %s\n", gw_res_get + (info.kernel_res, "gw.auto.show", "")); + fprintf (reply_fd, "defaultshow %s\n", gw_res_get + (info.kernel_res, "gw.default.show", "")); + fprintf (reply_fd, "language %s\n", gw_res_get + (info.kernel_res, "gw.language", "")); +} - if (cmd->kind != CCL_TOK_EOL && - (no = command_search (command_tab, cmd, "ccl.command."))) +static int exec_def (struct ccl_token *list) +{ + const char *name = NULL; + char value[128]; + char fname[256]; + static struct command_word def_tab [] = { - if (!info.zass && no != 9 && no != 4) - reopen_target (); - fprintf (reply_fd, "\n> %s\n", str); - if (!info.zass && (no == 1 || no == 2 || no == 3)) + { "reset", "reset" }, + { "show", "show" }, + { "f", "format"}, + { "autoshow", "autoshow" }, + { "defaultshow", "defaultshow" }, + { "lang", "language" }, + { NULL, NULL } + }; + + if (info.userid < 0) + return -1; + sprintf (fname, "user.%d.r", info.userid); + + if (list->kind == CCL_TOK_EOL) + show_def (); + else + { + int setting_no = command_search (def_tab, list, "ccl.token."); + + if (!setting_no) { - fprintf (reply_fd, "%s\n", - gw_res_get (info.kernel_res, "gw.err.no.target", - "No connection established - " - "command ignored")); + fprintf (reply_fd, "Unknown setting in def\n"); + return -1; + } + if (setting_no == 1) + { + unlink (fname); + read_kernel_res (); return 0; } - switch (no) + else if (setting_no == 2) + { + show_def (); + return 0; + } + list = list->next; + if (list->kind == CCL_TOK_EOL) + return 0; + strncpy (value, list->name, 127); + value[(size_t) list->len] = '\0'; + switch (setting_no) { - case 1: - return exec_find (cmd->next); - case 2: - return exec_show (cmd->next); case 3: - return exec_base (cmd->next); + name = "gw.display.format"; + break; case 4: - return exec_help (cmd->next); - case 9: - return exec_target (cmd->next); + name = "gw.auto.show"; + break; + case 5: + name = "gw.default.show"; + break; + case 6: + name = "gw.language"; + break; + default: + return 0; + } + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "update file %s with %s=%s", + fname, name, value); + gw_res_put (info.kernel_res, "gw.username", info.from_str, fname); + gw_res_put (info.kernel_res, name, value, fname); + gw_res_commit (info.kernel_res, fname); + if (setting_no == 6) + read_kernel_res (); + } + return 0; +} + + +/* + * exec_command: parse and execute ccl command in str. + * str: ccl command string + * stop_flag pointer to integer. On completion the integer + * is 1 (stop) or 2 (continue); 0 (other command) + * return: 0 success; non-zero otherwise + */ +static int exec_command (const char *str, int *stop_flag) +{ + struct ccl_token *cmd; + const char *cp = str; + int no; + + while (*cp && *cp != ' ' && *cp != '\n' && *cp != '\t' && *cp != '\r') + cp++; + + *stop_flag = 0; + no = command_search_str (command_tab, str, cp-str, "ccl.command."); + if (no) + { + if (no == 1 || no == 2 || no == 3) /* find/show/base? */ + { + if (!info.connect_failed && !info.zass) + /* open if not already opened */ + reopen_target (); + fprintf (reply_fd, "\n> %s\n", str); + if (!info.zass) /* fail? */ + { + fprintf (reply_fd, "\n%s\n", + gw_res_get (info.kernel_res, "gw.err.no.target", + "No connection established - " + "command ignored")); + return 0; + } + } + else + fprintf (reply_fd, "\n> %s\n", str); + switch (no) + { + case 1: /* find */ + cmd = ccl_tokenize (cp); + exec_find (cmd, str); + break; + case 2: /* show */ + cmd = ccl_tokenize (cp); + exec_show (cmd); + break; + case 3: /* base */ + cmd = ccl_token_simple (cp); + exec_base (cmd); + break; + case 4: /* help */ + cmd = ccl_token_simple (cp); + exec_help (cmd); + break; + case 6: /* continue */ + *stop_flag = 2; + return 0; + case 7: /* status */ + exec_status (cmd); + return 0; + case 8: /* stop */ + *stop_flag = 1; + return 0; + case 9: /* target */ + cmd = ccl_token_simple (cp); + exec_target (cmd); + break; + case 10: /* def */ + cmd = ccl_token_simple (cp); + exec_def (cmd); + break; + case 11: /* account */ + cmd = ccl_token_simple (cp); + exec_account (cmd); + break; default: + cmd = NULL; fprintf (reply_fd, "%s\n", gw_res_get (info.kernel_res, "gw.err.unimplemented", "Not implemented yet")); } + ccl_token_del (cmd); } else { @@ -734,37 +1161,37 @@ static int exec_command (const char *str) return 0; } -int urp (struct str_queue *queue) +int urp_start (int continuation, struct str_queue *queue) { - char from_str[128]; char subject_str[128]; - int command_no = 0; - char *reply_fname = NULL; - char *cp; - if (email_header (queue, from_str, subject_str)) + info.command_no = 0; + info.reply_fname = NULL; + + if (email_header (queue, info.from_str, subject_str)) { gw_log (GW_LOG_WARN, KERNEL_LOG, "No message body"); return -1; } tty_init (stdout, 40, 70); - if (*from_str) - { - reply_fname = tempnam (gw_res_get (info.kernel_res, - "gw.reply.tmp.dir", NULL), - gw_res_get (info.kernel_res, - "gw.reply.tmp.prefix", "gwr")); - - reply_fd = fopen (reply_fname, "w"); + if (*info.from_str) + { + info.reply_fname = (char *) + tempnam (gw_res_get (info.kernel_res, "gw.reply.tmp.dir", NULL), + gw_res_get (info.kernel_res, + "gw.reply.tmp.prefix", "gwr")); + + reply_fd = fopen (info.reply_fname, "w"); if (!reply_fd) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, KERNEL_LOG, "Cannot create %s", - reply_fname); + info.reply_fname); return -1; } tty_init (reply_fd, 0, 0); fprintf (reply_fd, "From: %s\n", - gw_res_get (info.kernel_res, "gw.msg.from","Email-gateway")); + gw_res_get (info.kernel_res, "gw.msg.from", + "Email-Z39.50 gateway")); fprintf (reply_fd, "Subject: "); if (*subject_str) fprintf (reply_fd, "Z39.50 Re: %s", subject_str); @@ -773,16 +1200,28 @@ int urp (struct str_queue *queue) "gw.msg.subject", "Your Query")); fprintf (reply_fd, "\n"); - gw_log (GW_LOG_ACCT, KERNEL_LOG, "User start %s", from_str); + gw_log (GW_LOG_ACCT, KERNEL_LOG, "User start %s", info.from_str); } else gw_log (GW_LOG_WARN, KERNEL_LOG, "No From in email header"); fprintf (reply_fd, "%s\n", gw_res_get (info.kernel_res, "gw.msg.greeting", "Email->Z39.50 gateway")); - while (str_queue_deq (queue, line_buf, LINE_MAX)) + if (continuation) + fprintf (reply_fd, "%s\n", gw_res_get (info.kernel_res, + "gw.msg.cont", + "Continued...")); + return 0; +} + +int urp_command (struct str_queue *queue) +{ + char *cp; + int stop_flag; + + while (str_queue_deq (queue, line_buf, STR_LINE_MAX)) { if (line_buf[0] == '\n') - if (command_no) + if (info.command_no) { while (str_queue_deq (queue, 0, 0)) ; @@ -793,41 +1232,50 @@ int urp (struct str_queue *queue) if ((cp = strchr (line_buf, '\n'))) *cp = '\0'; gw_log (GW_LOG_ACCT, KERNEL_LOG, "cmd: %s", line_buf); - ccl_token_and = gw_res_get (info.kernel_res, "ccl.token.and", "and"); - ccl_token_or = gw_res_get (info.kernel_res, "ccl.token.or", "or"); - ccl_token_not = gw_res_get (info.kernel_res, "ccl.token.not", "not"); - ccl_token_set = gw_res_get (info.kernel_res, "ccl.token.set", "set"); if (isalpha (line_buf[0])) - exec_command (line_buf); - command_no++; + { + exec_command (line_buf, &stop_flag); + if (stop_flag) + { + info.command_no++; /* prevent help! */ + while (str_queue_deq (queue, line_buf, STR_LINE_MAX)) + ; + return stop_flag; + } + } + info.command_no++; } - if (!command_no) + return 0; +} + +void urp_end (void) +{ + if (!info.command_no) { - fprintf (reply_fd, "%s\n", gw_res_get (info.kernel_res, - "gw.err.nullbody", - "No body")); + fprintf (reply_fd, "%s\n", + gw_res_get (info.kernel_res, "gw.err.nullbody", "No body")); help_general (); } - if (*from_str) + if (*info.from_str) { const char *mta; char cmd[256]; int mta_code; - assert (reply_fname); + assert (info.reply_fname); fclose (reply_fd); reply_fd = stdout; mta = gw_res_get (info.kernel_res, "gw.reply.mta", - "/usr/lib/sendmail"); - sprintf (cmd, "%s %s < %s", mta, from_str, reply_fname); - + "/usr/lib/sendmail"); + sprintf (cmd, "%s %s < %s", mta, info.from_str, info.reply_fname); mta_code = system (cmd); if (mta_code) gw_log (GW_LOG_FATAL, KERNEL_LOG, "Reply '%s' got exit code %d", cmd, mta_code); - unlink (reply_fname); - gw_log (GW_LOG_ACCT, KERNEL_LOG, "User end %s", from_str); + else + unlink (info.reply_fname); + gw_log (GW_LOG_ACCT, KERNEL_LOG, "User end %s", info.from_str); } - return 0; } +