From: Adam Dickmeiss Date: Mon, 27 Mar 1995 08:23:57 +0000 (+0000) Subject: First use of gip interface and gw-db. X-Git-Url: http://sru.miketaylor.org.uk/cgi-bin?a=commitdiff_plain;h=85fbcb1d1ff2c358bd8cb35f74f057cbb27108c3;p=egate.git First use of gip interface and gw-db. First work on eti program. --- diff --git a/kernel/Makefile b/kernel/Makefile index 6d4063d..3d46052 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -2,7 +2,11 @@ # Europagate, 1995 # # $Log: Makefile,v $ -# Revision 1.11 1995/03/03 17:19:09 adam +# Revision 1.12 1995/03/27 08:23:57 adam +# First use of gip interface and gw-db. +# First work on eti program. +# +# Revision 1.11 1995/03/03 17:19:09 adam # Smarter presentation. Bug fix in email header interpretation. # # Revision 1.10 1995/03/01 14:32:24 adam @@ -46,23 +50,31 @@ ZLIB=$(ZPRE)/libz3950.a INCLUDE=-I../include CFLAGS=-g -Wall -TPROG1=kernel -O=main.o urp.o ttyemit.o CPP=$(CC) -E +DEFS=$(INCLUDE) -DUSE_FML=1 USELIBS1=../lib/ccl.a ../lib/fml.a ../lib/libzass.a ../lib/libres+log.a \ ../lib/util.a $(ZLIB) $(REGEXOBJ) -DEFS=$(INCLUDE) -DUSE_FML=1 -all: $(TPROG1) +PROG1=kernel +O1=main.o urp.o ttyemit.o + +PROG2=eti +O2=eti.o + +all: $(PROG1) $(PROG2) + +$(PROG1): $(O1) $(USELIBS1) + $(CC) $(CFLAGS) -o $(PROG1) $(O1) $(USELIBS1) $(NETLIB) -$(TPROG1): $(O) $(USELIBS1) - $(CC) $(CFLAGS) -o $(TPROG1) $(O) $(USELIBS1) $(NETLIB) +$(PROG2): $(O2) $(USELIBS1) + $(CC) $(CFLAGS) -o $(PROG2) $(O2) $(USELIBS1) $(NETLIB) .c.o: $(CC) -c $(DEFS) $(CFLAGS) $< clean: - rm -f *.log *.[oa] $(TPROG1) $(TPROG2) core mon.out gmon.out errlist *~ + rm -f *.log *.[oa] $(PROG1) $(PROG2) + rm -f core mon.out gmon.out errlist *~ fifo.* depend: depend2 diff --git a/kernel/default.res b/kernel/default.res index fe79d7e..82e4bb4 100644 --- a/kernel/default.res +++ b/kernel/default.res @@ -1,5 +1,5 @@ # Email gateway - general kernel resources -# $Id: default.res,v 1.13 1995/03/03 17:19:11 adam Exp $ +# $Id: default.res,v 1.14 1995/03/27 08:23:59 adam Exp $ # # Important directories, programs, etc. gw.reply.mta: /usr/lib/sendmail @@ -115,46 +115,46 @@ gw.bib1.diag.132: Unsupported proximity unit code # Help messages gw.help.target: Command:\n - \ttarget host[:port]\n + \ttarget [:]\n \n The target command selects exactly one target . The is a normal internet domain hostname. The optional argument specifies the port number to use. Normally, this does not need to be specified. \n -gw.help.database: Command:\n - \tbase base1 base2 ...\n +gw.help.base: Command:\n + \tbase 1 2 ...\n \n The base command selects one or more databases. However, some targets do not allow the selection of more than one database. \n gw.help.find: Command:\n - \tfind query\n\n + \tfind \n\n The find command issues a search request based on the specified . A query consists of one or more s separated - by boolean operators , i.e.:\n\n + by boolean operators , i.e.:\n \tquery = search-element bool-operator search-element ...\n\n There are three boolean operators (| means or):\n \tbool-operator = and | or | not\n\n A search-element has three forms. The first and simplest is when it consists of one or more search-terms as in:\n - \tsearch-element = search-term ...\n\n + \t = ...\n\n In the second form, qualifiers are specified:\n - \tsearch-element = qualifier relation search-term ...\n\n + \t = ...\n\n A qualifier directs the search to a specified index register. The relation is:\n - \trelation = > | < | >= | <= | = | <>\n\n + \t = > | < | >= | <= | = | <>\n\n The third type of is the result-set reference:\n - \tsearch-element = s = name\n\n + \t = s=\n\n Parentheses may be used to create recursive definitions.\n\n Some examples, may be in order:\n \tfind network\n This query consists of one , which in turn consists of - one . The query search for the token "network".\n\n + one . The query searches for the word "network".\n\n \tfind computer network\n This is the same as above, but there are two search terms. The phrase "computer network" is searched.\n\n - \tfind ti=computer and au=knuth or donald + \tfind ti=computer and au=knuth or donald\n There are three s. The first and second use qualifiers; the last one doesn't. The search is equivalent to:\n \tfind (ti=computer and au=knuth) or donald\n @@ -165,17 +165,17 @@ gw.help.find: Command:\n Note: The result-set reference faclility is unavailable at the moment. \n gw.help.show: Command:\n - \tshow show-spec ...\n\n + \tshow ...\n\n The show command retrieves records. A is a combination of record position specifications and a presentation format specification. A show command with no retrieves 10 records and displays them in the full format. A show-spec of the form:\n - \tf = type\n + \tf = \n sets the the format to . Currently, there are three formats: 0 - full, 1 - medium, 2 compact format. Record positions can be specified by the form:\n - \tp = from - to\n + \tp = - \n Here and are two integers specifying the record positions.\n Example:\n diff --git a/kernel/eti.c b/kernel/eti.c new file mode 100644 index 0000000..f901a10 --- /dev/null +++ b/kernel/eti.c @@ -0,0 +1,175 @@ +/* Gateway kernel + * Europagate, 1995 + * + * $Log: eti.c,v $ + * Revision 1.1 1995/03/27 08:24:00 adam + * First use of gip interface and gw-db. + * First work on eti program. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define LINE_MAX 1024 +static char line_buf[LINE_MAX+1]; + +static char *module = "eti"; + +static int email_header (FILE *inf, char *from_str, char *subject_str) +{ + *from_str = '\0'; + *subject_str = '\0'; + while (fgets (line_buf, LINE_MAX, inf)) + { + if (line_buf[0] == '\n') + return 0; + if (strncmp (line_buf, "From ", 5) == 0) + sscanf (line_buf+4, "%s", from_str); + if (strncmp (line_buf, "Subject: ", 9) == 0 && + sscanf (line_buf+9, "%s", subject_str+1) == 1) + strcpy (subject_str, line_buf+9); + } + return 1; +} + +static int kernel_active (int id) +{ + char active_name[1024]; + int fd; + + sprintf (active_name, "kernel.pid.%d", id); + fd = open (active_name, O_RDONLY); + if (fd == -1) + return 0; + close (fd); + return 1; +} + +int main (int argc, char **argv) +{ + char from_str[LINE_MAX+1]; + char subject_str[LINE_MAX+1]; + char line_str[LINE_MAX+1]; + GW_DB user_db; + GIP gip; + void *user_info; + size_t info_length; + int id; + int r; + char fifo_client_name[1024]; + char fifo_server_name[1024]; + + gw_log_init (*argv); + gw_log_level (GW_LOG_ALL); + gw_log_file (GW_LOG_ALL, "eti.log"); + r = email_header (stdin, from_str, subject_str); + if (! *from_str) + { + gw_log (GW_LOG_WARN, module, "No \"From\" in mail"); + exit (1); + } + gw_log (GW_LOG_STAT, module, "Mail from %s", from_str); + user_db = gw_db_open ("user.db", 1); + + r = gw_db_lookup (user_db, from_str, strlen(from_str), + &user_info, &info_length); + if (r == 0) + { + gw_log (GW_LOG_STAT, module, "New user"); + id = gw_db_seq_no (user_db); + r = gw_db_insert (user_db, from_str, strlen(from_str), + &id, sizeof(id)); + gw_log (GW_LOG_STAT, module, "Added user with id %d", id); + } + else if (r == 1) + { + if (sizeof(id) != info_length) + { + gw_log (GW_LOG_FATAL, module, "Bad id-size"); + exit (1); + } + memcpy (&id, user_info, sizeof(id)); + gw_log (GW_LOG_STAT, module, "Found with id %d", id); + } + else + { + gw_log (GW_LOG_FATAL, module, "gw_db_lookup fail"); + } + sprintf (fifo_server_name, "fifo.s.%d", id); + sprintf (fifo_client_name, "fifo.c.%d", id); + + gip = gipc_initialize (fifo_client_name); + if (kernel_active (id)) + { + gw_log (GW_LOG_DEBUG, module, "Kernel already active"); + gipc_open (gip, fifo_server_name, 0); + } + else + { + pid_t pid; + int i; + char **argv_p; + char userid_option[20]; + + argv_p = malloc (sizeof(*argv_p)*(argc+2)); + if (!argv_p) + { + gw_log (GW_LOG_FATAL, module, "Malloc fail"); + exit (1); + } + argv_p[0] = "kernel"; + for (i = 1; i #endif -int urp (FILE *inf); +int urp (int fd); struct gw_user_set { char *name; /* name of result set */ @@ -86,4 +90,6 @@ void user_set_init (void); void tty_emit (int ch); void tty_init (FILE *out, int min, int max); +int lgets (char *buf, int max, int fd); + #define KERNEL_LOG "kernel" diff --git a/kernel/main.c b/kernel/main.c index 977dfee..1fa110e 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2,7 +2,11 @@ * Europagate, 1995 * * $Log: main.c,v $ - * Revision 1.10 1995/03/01 14:32:25 adam + * Revision 1.11 1995/03/27 08:24:02 adam + * First use of gip interface and gw-db. + * First work on eti program. + * + * Revision 1.10 1995/03/01 14:32:25 adam * Better diagnostics. Default is, that only one database selected when * several are known. * @@ -44,15 +48,114 @@ #include #include #include +#include +#include +#include +#include +#include #include "kernel.h" FILE *reply_fd = stdout; struct gw_kernel_info info; +static void mk_active (int userid) +{ + char active_name[1024]; + char pid_buf[30]; + int fd; + + sprintf (active_name, "kernel.pid.%d", userid); + fd = open (active_name, O_WRONLY|O_CREAT, 0666); + if (fd == -1) + { + gw_log (GW_LOG_FATAL, "Cannot create %s", active_name); + exit (1); + } + sprintf (pid_buf, "%ld", (long) getpid()); + write (fd, pid_buf, strlen(pid_buf)); + close (fd); +} + +static void rm_active (int userid) +{ + char active_name[1024]; + + sprintf (active_name, "kernel.pid.%d", userid); + unlink (active_name); +} + +static void kernel_events (int userid) +{ + char fifo_client_name[1024]; + char fifo_server_name[1024]; + GIP gip; + fd_set set_r; + int r, gip_fd; + struct timeval tv; + + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "kernel event loop"); + + sprintf (fifo_client_name, "fifo.c.%d", userid); + sprintf (fifo_server_name, "fifo.s.%d", userid); + + gip = gips_initialize (fifo_server_name); + gips_open (gip, fifo_client_name); + gip_fd = gip_infileno (gip); + + while (1) + { + FD_ZERO (&set_r); + FD_SET (gip_fd, &set_r); + tv.tv_sec = 60; + tv.tv_usec = 0; + + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "IPC select"); + r = select (gip_fd+1, &set_r, NULL, NULL, &tv); + if (r == -1) + { + gw_log (GW_LOG_FATAL, KERNEL_LOG, "select fail"); + exit (1); + } + if (r == 0) + { + gw_log (GW_LOG_STAT, KERNEL_LOG, "Timeout"); + break; + } + if (FD_ISSET (gip_fd, &set_r)) + { + char command[128], *cp; + + if (!(lgets (command, 127, gip_fd))) + break; + if ((cp = strchr (command, '\n'))) + *cp = '\0'; + gw_log (GW_LOG_STAT, KERNEL_LOG, "IPC: %s", command); + if (!strcmp (command, "mail")) + { + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "Incoming mail...\n"); + urp (gip_fd); + } + else if (!strcmp (command, "stop")) + { + gw_log (GW_LOG_DEBUG, KERNEL_LOG, "stop"); + break; + } + else + { + gw_log (GW_LOG_WARN, KERNEL_LOG, "Unknown IPC: %s", command); + } + } + } + gips_close (gip); + gips_destroy (gip); +} + int main (int argc, char **argv) { + int userid = -1; + info.kernel_res = NULL; info.default_res = "default.res"; info.override_res = NULL; @@ -164,6 +267,20 @@ int main (int argc, char **argv) exit (1); } break; + case 'i': + if (argv[0][2]) + userid = atoi (argv[0]+2); + else if (argc > 0) + { + --argc; + userid = atoi (*++argv); + } + else + { + gw_log (GW_LOG_FATAL, KERNEL_LOG, "missing user id"); + exit (1); + } + break; default: gw_log (GW_LOG_FATAL, KERNEL_LOG, "unknown option %s", *argv); exit (1); @@ -173,7 +290,14 @@ int main (int argc, char **argv) info.default_res = *argv; } read_kernel_res (); - urp (stdin); + if (userid != -1) + { + mk_active (userid); + kernel_events (userid); + rm_active (userid); + } + else + urp (0); return 0; } diff --git a/kernel/urp.c b/kernel/urp.c index 81c4c34..f3d61bc 100644 --- a/kernel/urp.c +++ b/kernel/urp.c @@ -2,7 +2,11 @@ * Europagate, 1995 * * $Log: urp.c,v $ - * Revision 1.20 1995/03/03 17:19:17 adam + * Revision 1.21 1995/03/27 08:24:04 adam + * First use of gip interface and gw-db. + * First work on eti program. + * + * Revision 1.20 1995/03/03 17:19:17 adam * Smarter presentation. Bug fix in email header interpretation. * * Revision 1.19 1995/03/02 09:32:11 adam @@ -88,6 +92,29 @@ 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, 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) { const char *v; @@ -215,11 +242,11 @@ static char *error_no_search (struct error_no_struct *tab, int no) return NULL; } -static int email_header (FILE *inf, char *from_str, char *subject_str) +static int email_header (int fd, char *from_str, char *subject_str) { *from_str = '\0'; *subject_str = '\0'; - while (fgets (line_buf, LINE_MAX, inf)) + while (lgets (line_buf, LINE_MAX, fd)) { if (line_buf[0] == '\n') return 0; @@ -240,18 +267,23 @@ static void help_general (void) static int exec_help (struct ccl_token *list) { + static char *sep = "-------------------------------\\n"; 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")); + 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")); + put_esc_str (sep); put_esc_str (gw_res_get (info.kernel_res, "gw.help.show", "show - retrieves and displays " "records\n")); @@ -690,14 +722,14 @@ static int exec_command (const char *str) return 0; } -int urp (FILE *inf) +int urp (int fd) { char from_str[128]; char subject_str[128]; int command_no = 0; char *reply_fname = NULL; - if (email_header (inf, from_str, subject_str)) + if (email_header (fd, from_str, subject_str)) { gw_log (GW_LOG_WARN, KERNEL_LOG, "No message body"); return -1; @@ -734,13 +766,17 @@ int urp (FILE *inf) 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 (fgets (line_buf, LINE_MAX, inf)) + while (lgets (line_buf, LINE_MAX, fd)) { char *cp; if (line_buf[0] == '\n') if (command_no) + { + while (lgets (line_buf, LINE_MAX, fd)) + ; break; + } else continue; if ((cp = strchr (line_buf, '\n')))