removed unused variables
[yaz-moved-to-github.git] / zoom / zoomsh.c
1 /*
2  * $Id: zoomsh.c,v 1.11 2002-06-05 21:09:20 adam Exp $
3  *
4  * ZOOM-C Shell
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11
12 #if HAVE_READLINE_READLINE_H
13 #include <readline/readline.h> 
14 #endif
15 #if HAVE_READLINE_HISTORY_H
16 #include <readline/history.h>
17 #endif
18
19 #include <yaz/xmalloc.h>
20
21 #include <yaz/zoom.h>
22
23 #define MAX_CON 100
24
25 static int next_token (const char **cpp, const char **t_start)
26 {
27     int len = 0;
28     const char *cp = *cpp;
29     while (*cp == ' ')
30         cp++;
31     *t_start = cp;
32     while (*cp && *cp != ' ' && *cp != '\r' && *cp != '\n')
33     {
34         cp++;
35         len++;
36     }
37     *cpp = cp;
38     return len;
39 }
40
41 static int next_token_copy (const char **cpp, char *buf_out, int buf_max)
42 {
43     const char *start;
44     int len = next_token (cpp, &start);
45     if (!len)
46     {
47         *buf_out = 0;
48         return 0;
49     }
50     if (len >= buf_max)
51         len = buf_max-1;
52     memcpy (buf_out, start, len);
53     buf_out[len] = '\0';
54     return len;
55 }
56
57 static int is_command (const char *cmd_str, const char *this_str, int this_len)
58 {
59     int cmd_len = strlen(cmd_str);
60     if (cmd_len != this_len)
61         return 0;
62     if (memcmp (cmd_str, this_str, cmd_len))
63         return 0;
64     return 1;
65 }
66
67 static void cmd_set (ZOOM_connection *c, ZOOM_resultset *r,
68                      ZOOM_options options,
69                      const char **args)
70 {
71     char key[40], val[80];
72
73     if (!next_token_copy (args, key, sizeof(key)))
74     {
75         printf ("missing argument for set\n");
76         return ;
77     }
78     if (!next_token_copy (args, val, sizeof(val)))
79         ZOOM_options_set(options, key, 0);
80     else
81         ZOOM_options_set(options, key, val);
82 }
83
84 static void cmd_get (ZOOM_connection *c, ZOOM_resultset *r,
85                      ZOOM_options options,
86                      const char **args)
87 {
88     char key[40];
89     if (!next_token_copy (args, key, sizeof(key)))
90     {
91         printf ("missing argument for get\n");
92     }
93     else
94     {
95         const char *val = ZOOM_options_get(options, key);
96         printf ("%s = %s\n", key, val ? val : "<null>");
97     }
98 }
99
100 static void cmd_close (ZOOM_connection *c, ZOOM_resultset *r,
101                        ZOOM_options options,
102                        const char **args)
103 {
104     char host[60];
105     int i;
106     next_token_copy (args, host, sizeof(host));
107     for (i = 0; i<MAX_CON; i++)
108     {
109         const char *h;
110         if (!c[i])
111             continue;
112         if ((h = ZOOM_connection_option_get(c[i], "host"))
113             && !strcmp (h, host))
114         {
115             ZOOM_connection_destroy (c[i]);
116             c[i] = 0;
117         }
118         else if (*host == '\0')
119         {
120             ZOOM_connection_destroy (c[i]);
121             c[i] = 0;
122         }
123     }
124 }
125
126 static void display_records (ZOOM_connection c,
127                              ZOOM_resultset r,
128                              int start, int count)
129 {
130     int i;
131     for (i = 0; i<count; i++)
132     {
133         int pos = i + start;
134         ZOOM_record rec = ZOOM_resultset_record (r, pos);
135         const char *db = ZOOM_record_get (rec, "database", 0);
136         int len;
137         const char *render = ZOOM_record_get (rec, "render", &len);
138         const char *syntax = ZOOM_record_get (rec, "syntax", 0);
139         /* if rec is non-null, we got a record for display */
140         if (rec)
141         {
142             printf ("%d %s %s\n", pos+1, (db ? db : "unknown"), syntax);
143             if (render)
144                 fwrite (render, 1, len, stdout);
145             printf ("\n");
146         }
147     }
148 }
149
150 static void cmd_show (ZOOM_connection *c, ZOOM_resultset *r,
151                       ZOOM_options options,
152                       const char **args)
153 {
154     int i;
155     char start_str[10], count_str[10];
156
157     if (next_token_copy (args, start_str, sizeof(start_str)))
158         ZOOM_options_set (options, "start", start_str);
159
160     if (next_token_copy (args, count_str, sizeof(count_str)))
161         ZOOM_options_set (options, "count", count_str);
162
163     for (i = 0; i<MAX_CON; i++)
164         ZOOM_resultset_records (r[i], 0, atoi(start_str), atoi(count_str));
165     while (ZOOM_event (MAX_CON, c))
166         ;
167
168     for (i = 0; i<MAX_CON; i++)
169     {
170         int error;
171         const char *errmsg, *addinfo;
172         /* display errors if any */
173         if (!c[i])
174             continue;
175         if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
176             fprintf (stderr, "%s error: %s (%d) %s\n",
177                      ZOOM_connection_option_get(c[i], "host"), errmsg,
178                      error, addinfo);
179         else if (r[i])
180         {
181             /* OK, no major errors. Display records... */
182             int start = ZOOM_options_get_int (options, "start", 0);
183             int count = ZOOM_options_get_int (options, "count", 0);
184             display_records (c[i], r[i], start, count);
185         }
186     }
187 }
188
189 static void cmd_ext (ZOOM_connection *c, ZOOM_resultset *r,
190                      ZOOM_options options,
191                      const char **args)
192 {
193     ZOOM_package p[MAX_CON];
194     
195     int i;
196     
197     for (i = 0; i<MAX_CON; i++)
198     {
199         if (c[i])
200         {
201             p[i] = ZOOM_connection_package (c[i], 0);
202             ZOOM_package_send(p[i], "itemorder");
203         }
204         else
205             p[i] = 0;
206     }
207
208     while (ZOOM_event (MAX_CON, c))
209         ;
210
211     for (i = 0; i<MAX_CON; i++)
212     {
213         int error;
214         const char *errmsg, *addinfo;
215         /* display errors if any */
216         if (!p[i])
217             continue;
218         if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
219             fprintf (stderr, "%s error: %s (%d) %s\n",
220                      ZOOM_connection_option_get(c[i], "host"), errmsg,
221                      error, addinfo);
222         else if (p[i])
223         {
224             printf ("ok\n");
225         }
226         ZOOM_package_destroy (p[i]);
227     }
228 }
229
230 static void cmd_search (ZOOM_connection *c, ZOOM_resultset *r,
231                         ZOOM_options options,
232                         const char **args)
233 {
234     ZOOM_query s;
235     int i;
236     
237     s = ZOOM_query_create ();
238     if (ZOOM_query_prefix (s, *args))
239     {
240         fprintf (stderr, "Bad PQF: %s\n", *args);
241         return;
242     }
243     for (i = 0; i<MAX_CON; i++)
244     {
245         if (c[i])
246         {
247             ZOOM_resultset_destroy (r[i]);
248             r[i] = 0;
249         }
250         if (c[i])
251             r[i] = ZOOM_connection_search (c[i], s);
252     }
253
254     while (ZOOM_event (MAX_CON, c))
255         ;
256
257     for (i = 0; i<MAX_CON; i++)
258     {
259         int error;
260         const char *errmsg, *addinfo;
261         /* display errors if any */
262         if (!c[i])
263             continue;
264         if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
265             fprintf (stderr, "%s error: %s (%d) %s\n",
266                      ZOOM_connection_option_get(c[i], "host"), errmsg,
267                      error, addinfo);
268         else if (r[i])
269         {
270             /* OK, no major errors. Look at the result count */
271             int start = ZOOM_options_get_int (options, "start", 0);
272             int count = ZOOM_options_get_int (options, "count", 0);
273
274             printf ("%s: %d hits\n", ZOOM_connection_option_get(c[i], "host"),
275                     ZOOM_resultset_size(r[i]));
276             /* and display */
277             display_records (c[i], r[i], start, count);
278         }
279     }
280     ZOOM_query_destroy (s);
281 }
282
283 static void cmd_help (ZOOM_connection *c, ZOOM_resultset *r,
284                       ZOOM_options options,
285                       const char **args)
286 {
287     printf ("connect <zurl>\n");
288     printf ("search <pqf>\n");
289     printf ("show [<start> [<count>]\n");
290     printf ("quit\n");
291     printf ("close <zurl>\n");
292     printf ("set <option> [<value>]\n");
293     printf ("get <option>\n");
294     printf ("\n");
295     printf ("options:\n");
296     printf (" start\n");
297     printf (" count\n");
298     printf (" databaseName\n");
299     printf (" preferredRecordSyntax\n");
300     printf (" proxy\n");
301     printf (" elementSetName\n");
302     printf (" maximumRecordSize\n");
303     printf (" preferredRecordSize\n");
304     printf (" async\n");
305     printf (" piggyback\n");
306     printf (" group\n");
307     printf (" user\n");
308     printf (" pass\n");
309     printf (" implementationName\n");
310     printf (" charset\n");
311     printf (" lang\n");
312 }
313
314 static void cmd_connect (ZOOM_connection *c, ZOOM_resultset *r,
315                          ZOOM_options options,
316                          const char **args)
317 {
318     int error;
319     const char *errmsg, *addinfo;
320     char host[60];
321     int j, i;
322     if (!next_token_copy (args, host, sizeof(host)))
323     {
324         printf ("missing host after connect\n");
325         return ;
326     }
327     for (j = -1, i = 0; i<MAX_CON; i++)
328     {
329         const char *h;
330         if (c[i] && (h = ZOOM_connection_option_get(c[i], "host")) &&
331             !strcmp (h, host))
332         {
333             ZOOM_connection_destroy (c[i]);
334             break;
335         }
336         else if (c[i] == 0 && j == -1)
337             j = i;
338     }
339     if (i == MAX_CON)  /* no match .. */
340     {
341         if (j == -1)
342         {
343             printf ("no more connection available\n");
344             return;
345         }
346         i = j;   /* OK, use this one is available */
347     }
348     c[i] = ZOOM_connection_create (options);
349     ZOOM_connection_connect (c[i], host, 0);
350
351     if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
352         printf ("%s error: %s (%d) %s\n",
353                 ZOOM_connection_option_get(c[i], "host"),
354                 errmsg, error, addinfo);
355     
356 }
357
358 static int cmd_parse (ZOOM_connection *c, ZOOM_resultset *r,
359                       ZOOM_options options, 
360                       const char **buf)
361 {
362     int cmd_len;
363     const char *cmd_str;
364
365     cmd_len = next_token (buf, &cmd_str);
366     if (!cmd_len)
367         return 1;
368     if (is_command ("quit", cmd_str, cmd_len))
369         return 0;
370     else if (is_command ("set", cmd_str, cmd_len))
371         cmd_set (c, r, options, buf);
372     else if (is_command ("get", cmd_str, cmd_len))
373         cmd_get (c, r, options, buf);
374     else if (is_command ("connect", cmd_str, cmd_len))
375         cmd_connect (c, r, options, buf);
376     else if (is_command ("open", cmd_str, cmd_len))
377         cmd_connect (c, r, options, buf);
378     else if (is_command ("search", cmd_str, cmd_len))
379         cmd_search (c, r, options, buf);
380     else if (is_command ("find", cmd_str, cmd_len))
381         cmd_search (c, r, options, buf);
382     else if (is_command ("show", cmd_str, cmd_len))
383         cmd_show (c, r, options, buf);
384     else if (is_command ("close", cmd_str, cmd_len))
385         cmd_close (c, r, options, buf);
386     else if (is_command ("help", cmd_str, cmd_len))
387         cmd_help(c, r, options, buf);
388     else if (is_command ("ext", cmd_str, cmd_len))
389         cmd_ext(c, r, options, buf);
390     else
391         printf ("unknown command %.*s\n", cmd_len, cmd_str);
392     return 2;
393 }
394
395 void shell(ZOOM_connection *c, ZOOM_resultset *r,
396            ZOOM_options options)
397 {
398     while (1)
399     {
400         char buf[1000];
401         char *cp;
402         const char *bp = buf;
403 #if HAVE_READLINE_READLINE_H
404         char* line_in;
405         line_in=readline("ZOOM>");
406         if (!line_in)
407             break;
408 #if HAVE_READLINE_HISTORY_H
409         if (*line_in)
410             add_history(line_in);
411 #endif
412         if(strlen(line_in) > 999) {
413             fprintf(stderr,"Input line too long\n");
414             break;
415         };
416         strcpy(buf,line_in);
417         free (line_in);
418 #else    
419         printf ("ZOOM>"); fflush (stdout);
420         if (!fgets (buf, 999, stdin))
421             break;
422 #endif 
423         if ((cp = strchr(buf, '\n')))
424             *cp = '\0';
425         if (!cmd_parse (c, r, options, &bp))
426             break;
427     }
428 }
429
430 int main (int argc, char **argv)
431 {
432     ZOOM_options options = ZOOM_options_create();
433     int i, res;
434     ZOOM_connection z39_con[MAX_CON];
435     ZOOM_resultset  z39_res[MAX_CON];
436     for (i = 0; i<MAX_CON; i++)
437     {
438         z39_con[i] = 0;
439         z39_res[i] = 0;
440     }
441
442     for (i = 0; i<MAX_CON; i++)
443         z39_con[i] = 0;
444
445     res = 1;
446     for (i = 1; i<argc; i++)
447     {
448         const char *bp = argv[i];
449         res = cmd_parse(z39_con, z39_res, options, &bp);
450         if (res == 0)  /* received quit */
451             break;
452     }
453     if (res)  /* do cmdline shell only if not quitting */
454         shell(z39_con, z39_res, options);
455     ZOOM_options_destroy(options);
456
457     for (i = 0; i<MAX_CON; i++)
458     {
459         ZOOM_connection_destroy(z39_con[i]);
460         ZOOM_resultset_destroy(z39_res[i]);
461     }
462     exit (0);
463 }