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