1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 Index Data
3 * See the file LICENSE for details.
6 \brief ZOOM C command line tool (shell)
15 #include <yaz/wrbuf.h>
17 #include <yaz/options.h>
19 #if HAVE_READLINE_READLINE_H
20 #include <readline/readline.h>
22 #if HAVE_READLINE_HISTORY_H
23 #include <readline/history.h>
31 static void process_events(ZOOM_connection *c)
35 yaz_log(YLOG_DEBUG, "process_events");
36 while ((i = ZOOM_event(MAX_CON, c)) != 0)
38 int peek = ZOOM_connection_peek_event(c[i-1]);
39 int event = ZOOM_connection_last_event(c[i-1]);
40 yaz_log(YLOG_DEBUG, "no = %d peek = %d event = %d %s", i-1,
43 ZOOM_get_event_str(event));
47 static int next_token_chars(const char **cpp, const char **t_start,
48 const char *tok_chars)
51 const char *cp = *cpp;
58 while (*cp && *cp != '"')
69 while (*cp && !strchr(tok_chars, *cp))
78 return len; /* return -1 if no token was read .. */
81 static int next_token(const char **cpp, const char **t_start)
83 return next_token_chars(cpp, t_start, "\r\n ");
87 static WRBUF next_token_new_wrbuf(const char **cpp)
91 int len = next_token(cpp, &start);
96 wrbuf_write(w, start, len);
100 static int is_command(const char *cmd_str, const char *this_str, int this_len)
102 int cmd_len = strlen(cmd_str);
103 if (cmd_len != this_len)
105 if (memcmp(cmd_str, this_str, cmd_len))
110 static void cmd_set(ZOOM_connection *c, ZOOM_resultset *r,
111 ZOOM_options options,
118 if (!(key = next_token_new_wrbuf(args)))
120 printf("missing argument for set\n");
123 val_len = next_token_chars(args, &val_buf, "");
125 ZOOM_options_setl(options, wrbuf_cstr(key), val_buf, val_len);
127 ZOOM_options_set(options, wrbuf_cstr(key), 0);
131 static void cmd_get(ZOOM_connection *c, ZOOM_resultset *r,
132 ZOOM_options options,
136 if (!(key = next_token_new_wrbuf(args)))
138 printf("missing argument for get\n");
142 const char *val = ZOOM_options_get(options, wrbuf_cstr(key));
143 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
148 static void cmd_rget(ZOOM_connection *c, ZOOM_resultset *r,
149 ZOOM_options options,
153 if (!(key = next_token_new_wrbuf(args)))
155 printf("missing argument for get\n");
160 for (i = 0; i<MAX_CON; i++)
166 val = ZOOM_resultset_option_get(r[i], wrbuf_cstr(key));
167 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
173 static void cmd_close(ZOOM_connection *c, ZOOM_resultset *r,
174 ZOOM_options options,
179 host = next_token_new_wrbuf(args);
180 for (i = 0; i<MAX_CON; i++)
187 ZOOM_connection_destroy(c[i]);
190 else if ((h = ZOOM_connection_option_get(c[i], "host"))
191 && !strcmp(h, wrbuf_cstr(host)))
193 ZOOM_connection_destroy(c[i]);
201 static void display_records(ZOOM_connection c,
203 size_t start, size_t count, const char *type)
206 for (i = 0; i < count; i++)
208 size_t pos = i + start;
209 ZOOM_record rec = ZOOM_resultset_record(r, pos);
210 const char *db = ZOOM_record_get(rec, "database", 0);
212 if (ZOOM_record_error(rec, 0, 0, 0))
217 int error = ZOOM_record_error(rec, &msg, &addinfo, &diagset);
219 printf("%lld %s: %s (%s:%d) %s\n", (long long) pos,
220 (db ? db : "unknown"),
221 msg, diagset, error, addinfo ? addinfo : "none");
226 const char *render = ZOOM_record_get(rec, type, &len);
227 const char *syntax = ZOOM_record_get(rec, "syntax", 0);
228 const char *schema = ZOOM_record_get(rec, "schema", 0);
229 /* if rec is non-null, we got a record for display */
232 printf("%lld database=%s syntax=%s schema=%s\n",
233 (long long) pos, (db ? db : "unknown"), syntax,
234 schema ? schema : "unknown");
237 if (fwrite(render, 1, len, stdout) != (size_t) len)
239 printf("write to stdout failed\n");
248 static void cmd_show(ZOOM_connection *c, ZOOM_resultset *r,
249 ZOOM_options options,
253 size_t start = 0, count = 1;
254 const char *type = "render";
255 WRBUF render_str = 0;
260 if ((tmp = next_token_new_wrbuf(args)))
262 start = atoi(wrbuf_cstr(tmp));
266 if ((tmp = next_token_new_wrbuf(args)))
268 count = atoi(wrbuf_cstr(tmp));
271 render_str = next_token_new_wrbuf(args);
274 type = wrbuf_cstr(render_str);
276 for (i = 0; i < MAX_CON; i++)
277 ZOOM_resultset_records(r[i], 0, start, count);
280 for (i = 0; i < MAX_CON; i++)
283 const char *errmsg, *addinfo, *dset;
284 /* display errors if any */
287 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
288 printf("%s error: %s (%s:%d) %s\n",
289 ZOOM_connection_option_get(c[i], "host"), errmsg,
290 dset, error, addinfo);
293 /* OK, no major errors. Display records... */
294 display_records(c[i], r[i], start, count, type);
298 wrbuf_destroy(render_str);
302 static void display_facets(ZOOM_facet_field *facets, int count) {
304 printf("Facets: \n");
305 for (index = 0; index < count; index++) {
307 const char *facet_name = ZOOM_facet_field_name(facets[index]);
308 printf(" %s: \n", facet_name);
309 for (term_index = 0; term_index < ZOOM_facet_field_term_count(facets[index]); term_index++) {
311 const char *term = ZOOM_facet_field_get_term(facets[index], term_index, &freq);
312 printf(" %s(%d) \n", term, freq);
317 static void cmd_facets(ZOOM_connection *c, ZOOM_resultset *r,
318 ZOOM_options options,
325 for (i = 0; i < MAX_CON; i++)
328 const char *errmsg, *addinfo, *dset;
329 /* display errors if any */
332 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
333 printf("%s error: %s (%s:%d) %s\n",
334 ZOOM_connection_option_get(c[i], "host"), errmsg,
335 dset, error, addinfo);
338 int num_facets = ZOOM_resultset_facets_size(r[i]);
340 ZOOM_facet_field *facets = ZOOM_resultset_facets(r[i]);
341 display_facets(facets, num_facets);
347 static void cmd_ext(ZOOM_connection *c, ZOOM_resultset *r,
348 ZOOM_options options,
351 ZOOM_package p[MAX_CON];
353 WRBUF ext_type_str = next_token_new_wrbuf(args);
355 for (i = 0; i<MAX_CON; i++)
359 p[i] = ZOOM_connection_package(c[i], 0);
360 ZOOM_package_send(p[i], ext_type_str ? wrbuf_cstr(ext_type_str):0);
368 for (i = 0; i<MAX_CON; i++)
371 const char *errmsg, *addinfo, *dset;
372 /* display errors if any */
375 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
376 printf("%s error: %s (%s:%d) %s\n",
377 ZOOM_connection_option_get(c[i], "host"), errmsg,
378 dset, error, addinfo);
383 v = ZOOM_package_option_get(p[i], "targetReference");
385 printf("targetReference: %s\n", v);
386 v = ZOOM_package_option_get(p[i], "xmlUpdateDoc");
388 printf("xmlUpdateDoc: %s\n", v);
390 ZOOM_package_destroy(p[i]);
393 wrbuf_destroy(ext_type_str);
396 static void cmd_debug(ZOOM_connection *c, ZOOM_resultset *r,
397 ZOOM_options options,
400 yaz_log_init_level(YLOG_ALL);
403 static void cmd_search(ZOOM_connection *c, ZOOM_resultset *r,
404 ZOOM_options options,
408 const char *query_str = *args;
411 s = ZOOM_query_create();
412 while (*query_str == ' ')
414 if (memcmp(query_str, "cql:", 4) == 0)
416 ZOOM_query_cql(s, query_str + 4);
418 else if (ZOOM_query_prefix(s, query_str))
420 printf("Bad PQF: %s\n", query_str);
423 for (i = 0; i<MAX_CON; i++)
428 ZOOM_resultset_destroy(r[i]);
432 r[i] = ZOOM_connection_search(c[i], s);
434 ZOOM_query_destroy(s);
438 for (i = 0; i<MAX_CON; i++)
441 const char *errmsg, *addinfo, *dset;
442 /* display errors if any */
445 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
446 printf("%s error: %s (%s:%d) %s\n",
447 ZOOM_connection_option_get(c[i], "host"), errmsg,
448 dset, error, addinfo);
451 /* OK, no major errors. Look at the result count */
452 int start = ZOOM_options_get_int(options, "start", 0);
453 int count = ZOOM_options_get_int(options, "count", 0);
456 printf("%s: %lld hits\n", ZOOM_connection_option_get(c[i], "host"),
457 (long long int) ZOOM_resultset_size(r[i]));
459 facet_num = ZOOM_resultset_facets_size(r[i]);
462 ZOOM_facet_field *facets = ZOOM_resultset_facets(r[i]);
464 for (facet_idx = 0; facet_idx < facet_num; facet_idx++)
466 const char *name = ZOOM_facet_field_name(facets[facet_idx]);
468 size_t term_num = ZOOM_facet_field_term_count(facets[facet_idx]);
469 printf("facet: %s\n", name);
470 for (term_idx = 0; term_idx < term_num; term_idx++ )
474 ZOOM_facet_field_get_term(facets[facet_idx], term_idx, &freq);
475 printf("term: %s %d\n", term, freq);
480 display_records(c[i], r[i], start, count, "render");
485 static void cmd_scan(ZOOM_connection *c, ZOOM_resultset *r,
486 ZOOM_options options,
489 const char *query_str = *args;
490 ZOOM_query query = ZOOM_query_create();
492 ZOOM_scanset s[MAX_CON];
494 while (*query_str == ' ')
497 if (memcmp(query_str, "cql:", 4) == 0)
499 ZOOM_query_cql(query, query_str + 4);
501 else if (ZOOM_query_prefix(query, query_str))
503 printf("Bad PQF: %s\n", query_str);
507 for (i = 0; i<MAX_CON; i++)
510 s[i] = ZOOM_connection_scan1(c[i], query);
514 ZOOM_query_destroy(query);
518 for (i = 0; i<MAX_CON; i++)
521 const char *errmsg, *addinfo, *dset;
522 /* display errors if any */
525 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
526 printf("%s error: %s (%s:%d) %s\n",
527 ZOOM_connection_option_get(c[i], "host"), errmsg,
528 dset, error, addinfo);
531 size_t p, sz = ZOOM_scanset_size(s[i]);
532 for (p = 0; p < sz; p++)
536 const char *term = ZOOM_scanset_display_term(s[i], p,
538 printf("%.*s %lld\n", (int) len, term, (long long int) occ);
540 ZOOM_scanset_destroy(s[i]);
545 static void cmd_sort(ZOOM_connection *c, ZOOM_resultset *r,
546 ZOOM_options options,
549 const char *sort_spec = *args;
552 while (*sort_spec == ' ')
555 for (i = 0; i<MAX_CON; i++)
558 ZOOM_resultset_sort(r[i], "yaz", sort_spec);
563 static void cmd_help(ZOOM_connection *c, ZOOM_resultset *r,
564 ZOOM_options options,
567 printf("connect <zurl>\n");
568 printf("search <pqf>\n");
569 printf("show [<start> [<count> [<type]]]\n");
571 printf("scan <term>\n");
573 printf("close <zurl>\n");
574 printf("ext <type>\n");
575 printf("set <option> [<value>]\n");
576 printf("get <option>\n");
578 printf("options:\n");
581 printf(" databaseName\n");
582 printf(" preferredRecordSyntax\n");
584 printf(" elementSetName\n");
585 printf(" maximumRecordSize\n");
586 printf(" preferredRecordSize\n");
588 printf(" piggyback\n");
591 printf(" password\n");
592 printf(" implementationName\n");
593 printf(" charset\n");
595 printf(" timeout\n");
599 static void cmd_connect(ZOOM_connection *c, ZOOM_resultset *r,
600 ZOOM_options options,
604 const char *errmsg, *addinfo, *dset;
606 WRBUF host = next_token_new_wrbuf(args);
609 printf("missing host after connect\n");
612 for (j = -1, i = 0; i<MAX_CON; i++)
615 if (c[i] && (h = ZOOM_connection_option_get(c[i], "host")) &&
616 !strcmp(h, wrbuf_cstr(host)))
618 ZOOM_connection_destroy(c[i]);
621 else if (c[i] == 0 && j == -1)
624 if (i == MAX_CON) /* no match .. */
628 printf("no more connection available\n");
632 i = j; /* OK, use this one is available */
634 c[i] = ZOOM_connection_create(options);
635 ZOOM_connection_connect(c[i], wrbuf_cstr(host), 0);
637 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
638 printf("%s error: %s (%s:%d) %s\n",
639 ZOOM_connection_option_get(c[i], "host"), errmsg,
640 dset, error, addinfo);
644 static int cmd_parse(ZOOM_connection *c, ZOOM_resultset *r,
645 ZOOM_options options,
651 cmd_len = next_token(buf, &cmd_str);
654 if (is_command("quit", cmd_str, cmd_len))
656 else if (is_command("set", cmd_str, cmd_len))
657 cmd_set(c, r, options, buf);
658 else if (is_command("get", cmd_str, cmd_len))
659 cmd_get(c, r, options, buf);
660 else if (is_command("rget", cmd_str, cmd_len))
661 cmd_rget(c, r, options, buf);
662 else if (is_command("connect", cmd_str, cmd_len))
663 cmd_connect(c, r, options, buf);
664 else if (is_command("open", cmd_str, cmd_len))
665 cmd_connect(c, r, options, buf);
666 else if (is_command("search", cmd_str, cmd_len))
667 cmd_search(c, r, options, buf);
668 else if (is_command("facets", cmd_str, cmd_len))
669 cmd_facets(c, r, options, buf);
670 else if (is_command("find", cmd_str, cmd_len))
671 cmd_search(c, r, options, buf);
672 else if (is_command("show", cmd_str, cmd_len))
673 cmd_show(c, r, options, buf);
674 else if (is_command("close", cmd_str, cmd_len))
675 cmd_close(c, r, options, buf);
676 else if (is_command("help", cmd_str, cmd_len))
677 cmd_help(c, r, options, buf);
678 else if (is_command("ext", cmd_str, cmd_len))
679 cmd_ext(c, r, options, buf);
680 else if (is_command("debug", cmd_str, cmd_len))
681 cmd_debug(c, r, options, buf);
682 else if (is_command("scan", cmd_str, cmd_len))
683 cmd_scan(c, r, options, buf);
684 else if (is_command("sort", cmd_str, cmd_len))
685 cmd_sort(c, r, options, buf);
687 printf("unknown command %.*s\n", cmd_len, cmd_str);
691 void shell(ZOOM_connection *c, ZOOM_resultset *r,
692 ZOOM_options options)
698 const char *bp = buf;
699 #if HAVE_READLINE_READLINE_H
701 line_in=readline("ZOOM>");
704 #if HAVE_READLINE_HISTORY_H
706 add_history(line_in);
708 if(strlen(line_in) > 999) {
709 printf("Input line too long\n");
715 printf("ZOOM>"); fflush(stdout);
716 if (!fgets(buf, 999, stdin))
719 if ((cp = strchr(buf, '\n')))
721 if (!cmd_parse(c, r, options, &bp))
726 static void zoomsh(int argc, char **argv)
728 ZOOM_options zoom_options = ZOOM_options_create();
730 ZOOM_connection z39_con[MAX_CON];
731 ZOOM_resultset z39_res[MAX_CON];
733 for (i = 0; i<MAX_CON; i++)
742 int option_ret = options("v:", argv, argc, &arg);
743 const char *bp = arg;
747 res = cmd_parse(z39_con, z39_res, zoom_options, &bp);
748 /* returns res == 0 on quit */
750 case YAZ_OPTIONS_EOF:
751 shell(z39_con, z39_res, zoom_options);
755 mask = yaz_log_mask_str(arg);
756 yaz_log_init_level(mask);
759 fprintf(stderr, "zoomsh: [-v] [commands]\n");
764 for (i = 0; i<MAX_CON; i++)
766 ZOOM_connection_destroy(z39_con[i]);
767 ZOOM_resultset_destroy(z39_res[i]);
771 int main(int argc, char **argv)
779 * c-file-style: "Stroustrup"
780 * indent-tabs-mode: nil
782 * vim: shiftwidth=4 tabstop=8 expandtab