First version of email gateway kernel. Email requests are read
[egate.git] / kernel / urp.c
1 /* Gateway kernel
2  * Europagate, 1995
3  *
4  * $Log: urp.c,v $
5  * Revision 1.1  1995/02/15 17:45:30  adam
6  * First version of email gateway kernel. Email requests are read
7  * from stdin. The output is transferred to an MTA if 'From' is
8  * found in the header - or stdout if absent. No Z39.50 client is used.
9  *
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <ctype.h>
16 #include <string.h>
17
18 #include "kernel.h"
19
20 #define LINE_MAX 256
21
22 static char line_buf[LINE_MAX+1];
23
24 static struct command_word {
25     char *default_value;
26     char *resource_suffix;
27 } command_tab [] = 
28 {
29 {   "find", "find"},
30 {   "show", "show"},
31 {   "base", "base" },
32 {   "help", "help" },
33 {   "info", "info" },
34 {   "continue", "continue" },
35 {   "status", "status" },
36 {   "cancel", "cancel" },
37 {   NULL, NULL }
38 };
39
40 static int command_search (struct command_word *tab, struct ccl_token *cmd,
41 const char *resource_prefix)
42 {
43     int no = 1;
44
45     assert (resource_prefix);
46     assert (tab);
47     assert (cmd);
48     while (tab->default_value)
49     {
50         char *cp, command_names[60];
51         char resource_name[60];
52         const char *v;
53
54         sprintf (resource_name, "%s%s", resource_prefix,
55                  tab->resource_suffix);
56         v = gw_res_get (kernel_res, resource_name, tab->default_value);
57         assert (v);
58         strcpy (command_names, v);
59         cp = command_names;
60         while (1)
61         {
62             char *split;
63
64             if ((split = strchr (cp, ' ')))
65                 *split = '\0';
66             if (cmd->len == strlen(cp) &&
67                 !memcmp (cmd->name, cp, cmd->len))
68                 return no;
69             if (!split)
70                 break;
71             cp = split+1;
72         }        
73         no++;
74         tab++;
75     }
76     return 0;
77 }
78
79 static int email_header (FILE *inf, char *from_str)
80 {
81     *from_str = '\0';
82     while (fgets (line_buf, LINE_MAX, inf))
83     {
84         if (line_buf[0] == '\n')
85             return 0;
86         if (strncmp (line_buf, "From ", 5) == 0)
87             sscanf (line_buf+4, "%s", from_str);
88     }
89     return 1;
90 }
91
92 static int exec_find (struct ccl_token *list)
93 {
94     struct ccl_rpn_node *rpn;
95     int error;
96     const char *pos;
97
98     rpn = ccl_find (bibset, list, &error, &pos);
99     if (!rpn)
100     {
101         fprintf (reply_fd, " %*s^ - ", pos - line_buf, " ");
102         fprintf (reply_fd, "%s\n", ccl_err_msg (error));
103         return -1;
104     }
105     ccl_pr_tree (rpn, reply_fd);
106     fprintf (reply_fd, "\n");
107     return 0;
108 }
109
110 static int exec_command (const char *str)
111 {
112     struct ccl_token *cmd = ccl_tokenize (str);
113     int no;
114
115     ccl_token_and = gw_res_get (kernel_res, "ccl.token.and", "and");
116     ccl_token_or = gw_res_get (kernel_res, "ccl.token.or", "or");
117     ccl_token_not = gw_res_get (kernel_res, "ccl.token.not", "not");
118     ccl_token_set = gw_res_get (kernel_res, "ccl.token.set", "set");
119     
120     fprintf (reply_fd, "> %s", str);
121     if (cmd->kind == CCL_TOK_TERM &&
122         (no = command_search (command_tab, cmd, "ccl.command.")))
123     {
124         switch (no)
125         {
126         case 1:
127             return exec_find (cmd->next);
128             break;
129         case 2:
130             fprintf (reply_fd, " show found\n");
131             break;
132         default:
133             fprintf (reply_fd, " unimplemented command\n");
134         }
135     }
136     else
137         fprintf (reply_fd, "  ^ unknown command\n");
138     return 0;
139 }
140
141 int urp (FILE *inf)
142 {
143     char from_str[128];
144     int command_no = 0;
145     char *reply_fname = NULL;
146
147     if (email_header (inf, from_str))
148     {
149         gw_log (GW_LOG_WARN, "urp", "No message body");
150         return -1;
151     }
152     if (*from_str)
153     {
154         reply_fname = tempnam (gw_res_get (kernel_res,
155                                            "gw.reply.tmp.dir", NULL),
156                                gw_res_get (kernel_res,
157                                            "gw.reply.tmp.prefix", "gwr"));
158                                                  
159         reply_fd = fopen (reply_fname, "w");
160         if (!reply_fd)
161         {
162             gw_log (GW_LOG_FATAL, "urp", "Cannot create %s",
163                     reply_fname);
164             return -1;
165         }
166     }
167     fprintf (reply_fd, "%s\n", gw_res_get (kernel_res, "gw.msg.greeting",
168                                            "Email->Z39.50 gateway"));
169     while (fgets (line_buf, LINE_MAX, inf))
170     {
171         if (line_buf[0] == '\n')
172             break;
173         if (isalpha (line_buf[0]))
174             exec_command (line_buf);
175         command_no++;
176     }
177     if (!command_no)
178         fprintf (reply_fd, "%s\n", gw_res_get (kernel_res, "gw.err.nullbody",
179                                                "No body"));
180     if (*from_str)
181     {
182         const char *mta;
183         char cmd[256];
184         int mta_code;
185
186         assert (reply_fname);
187         fclose (reply_fd);
188         reply_fd = stdout;
189
190         mta = gw_res_get (kernel_res, "gw.reply.mta", "/usr/lib/sendmail");
191         sprintf (cmd, "%s %s < %s", mta, from_str, reply_fname);
192         
193         mta_code = system (cmd);
194         if (mta_code)
195             gw_log (GW_LOG_FATAL, "urp", "Reply '%s' got exit code %d",
196                     cmd, mta_code);
197         unlink (reply_fname);        
198     }
199     return 0;
200 }