1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2010 Index Data
3 * See the file LICENSE for details.
7 \brief ZOOM C command line tool (shell)
14 #include <yaz/wrbuf.h>
17 #if HAVE_READLINE_READLINE_H
18 #include <readline/readline.h>
20 #if HAVE_READLINE_HISTORY_H
21 #include <readline/history.h>
29 static void process_events(ZOOM_connection *c)
33 yaz_log(YLOG_DEBUG, "process_events");
34 while ((i = ZOOM_event(MAX_CON, c)) != 0)
36 int peek = ZOOM_connection_peek_event(c[i-1]);
37 int event = ZOOM_connection_last_event(c[i-1]);
38 yaz_log(YLOG_DEBUG, "no = %d peek = %d event = %d %s", i-1,
41 ZOOM_get_event_str(event));
45 static int next_token(const char **cpp, const char **t_start)
48 const char *cp = *cpp;
55 while (*cp && *cp != '"')
66 while (*cp && *cp != ' ' && *cp != '\r' && *cp != '\n')
75 return len; /* return -1 if no token was read .. */
78 static WRBUF next_token_new_wrbuf(const char **cpp)
82 int len = next_token(cpp, &start);
87 wrbuf_write(w, start, len);
91 static int is_command(const char *cmd_str, const char *this_str, int this_len)
93 int cmd_len = strlen(cmd_str);
94 if (cmd_len != this_len)
96 if (memcmp(cmd_str, this_str, cmd_len))
101 static void cmd_set(ZOOM_connection *c, ZOOM_resultset *r,
102 ZOOM_options options,
107 if (!(key = next_token_new_wrbuf(args)))
109 printf("missing argument for set\n");
112 if ((val = next_token_new_wrbuf(args)))
114 ZOOM_options_set(options, wrbuf_cstr(key), wrbuf_cstr(val));
118 ZOOM_options_set(options, wrbuf_cstr(key), 0);
122 static void cmd_get(ZOOM_connection *c, ZOOM_resultset *r,
123 ZOOM_options options,
127 if (!(key = next_token_new_wrbuf(args)))
129 printf("missing argument for get\n");
133 const char *val = ZOOM_options_get(options, wrbuf_cstr(key));
134 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
139 static void cmd_rget(ZOOM_connection *c, ZOOM_resultset *r,
140 ZOOM_options options,
144 if (!(key = next_token_new_wrbuf(args)))
146 printf("missing argument for get\n");
151 for (i = 0; i<MAX_CON; i++)
157 val = ZOOM_resultset_option_get(r[i], wrbuf_cstr(key));
158 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
164 static void cmd_close(ZOOM_connection *c, ZOOM_resultset *r,
165 ZOOM_options options,
170 host = next_token_new_wrbuf(args);
171 for (i = 0; i<MAX_CON; i++)
178 ZOOM_connection_destroy(c[i]);
181 else if ((h = ZOOM_connection_option_get(c[i], "host"))
182 && !strcmp(h, wrbuf_cstr(host)))
184 ZOOM_connection_destroy(c[i]);
192 static void display_records(ZOOM_connection c,
194 size_t start, size_t count, const char *type)
197 for (i = 0; i < count; i++)
199 size_t pos = i + start;
200 ZOOM_record rec = ZOOM_resultset_record(r, pos);
201 const char *db = ZOOM_record_get(rec, "database", 0);
203 if (ZOOM_record_error(rec, 0, 0, 0))
208 int error = ZOOM_record_error(rec, &msg, &addinfo, &diagset);
210 printf("%lld %s: %s (%s:%d) %s\n", (long long) pos,
211 (db ? db : "unknown"),
212 msg, diagset, error, addinfo ? addinfo : "none");
217 const char *render = ZOOM_record_get(rec, type, &len);
218 const char *syntax = ZOOM_record_get(rec, "syntax", 0);
219 const char *schema = ZOOM_record_get(rec, "schema", 0);
220 /* if rec is non-null, we got a record for display */
223 printf("%lld database=%s syntax=%s schema=%s\n",
224 (long long) pos, (db ? db : "unknown"), syntax,
225 schema ? schema : "unknown");
228 if (fwrite(render, 1, len, stdout) != (size_t) len)
230 printf("write to stdout failed\n");
239 static void cmd_show(ZOOM_connection *c, ZOOM_resultset *r,
240 ZOOM_options options,
244 size_t start = 0, count = 1;
245 const char *type = "render";
246 WRBUF render_str = 0;
251 if ((tmp = next_token_new_wrbuf(args)))
253 start = atoi(wrbuf_cstr(tmp));
257 if ((tmp = next_token_new_wrbuf(args)))
259 count = atoi(wrbuf_cstr(tmp));
262 render_str = next_token_new_wrbuf(args);
265 type = wrbuf_cstr(render_str);
267 for (i = 0; i < MAX_CON; i++)
268 ZOOM_resultset_records(r[i], 0, start, count);
271 for (i = 0; i < MAX_CON; i++)
274 const char *errmsg, *addinfo, *dset;
275 /* display errors if any */
278 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
279 printf("%s error: %s (%s:%d) %s\n",
280 ZOOM_connection_option_get(c[i], "host"), errmsg,
281 dset, error, addinfo);
284 /* OK, no major errors. Display records... */
285 display_records(c[i], r[i], start, count, type);
289 wrbuf_destroy(render_str);
293 static void display_facets(ZOOM_facet_field *facets, int count) {
295 printf("Facets: \n");
296 for (index = 0; index < count; index++) {
298 const char *facet_name = ZOOM_facet_field_name(facets[index]);
299 printf(" %s: \n", facet_name);
300 for (term_index = 0; term_index < ZOOM_facet_field_term_count(facets[index]); term_index++) {
302 const char *term = ZOOM_facet_field_get_term(facets[index], term_index, &freq);
303 printf(" %s(%d) \n", term, freq);
308 static void cmd_facets(ZOOM_connection *c, ZOOM_resultset *r,
309 ZOOM_options options,
313 size_t start = 0, count = 1;
314 const char *type = "render";
315 WRBUF render_str = 0;
321 if ((tmp = next_token_new_wrbuf(args)))
323 start = atoi(wrbuf_cstr(tmp));
327 if ((tmp = next_token_new_wrbuf(args)))
329 count = atoi(wrbuf_cstr(tmp));
332 render_str = next_token_new_wrbuf(args);
335 type = wrbuf_cstr(render_str);
339 for (i = 0; i < MAX_CON; i++)
342 const char *errmsg, *addinfo, *dset;
343 /* display errors if any */
346 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
347 printf("%s error: %s (%s:%d) %s\n",
348 ZOOM_connection_option_get(c[i], "host"), errmsg,
349 dset, error, addinfo);
352 int num_facets = ZOOM_resultset_facets_size(r[i]);
354 ZOOM_facet_field *facets = ZOOM_resultset_facets(r[i]);
355 display_facets(facets, num_facets);
360 wrbuf_destroy(render_str);
364 static void cmd_ext(ZOOM_connection *c, ZOOM_resultset *r,
365 ZOOM_options options,
368 ZOOM_package p[MAX_CON];
370 WRBUF ext_type_str = next_token_new_wrbuf(args);
372 for (i = 0; i<MAX_CON; i++)
376 p[i] = ZOOM_connection_package(c[i], 0);
377 ZOOM_package_send(p[i], ext_type_str ? wrbuf_cstr(ext_type_str):0);
385 for (i = 0; i<MAX_CON; i++)
388 const char *errmsg, *addinfo, *dset;
389 /* display errors if any */
392 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
393 printf("%s error: %s (%s:%d) %s\n",
394 ZOOM_connection_option_get(c[i], "host"), errmsg,
395 dset, error, addinfo);
400 v = ZOOM_package_option_get(p[i], "targetReference");
402 printf("targetReference: %s\n", v);
403 v = ZOOM_package_option_get(p[i], "xmlUpdateDoc");
405 printf("xmlUpdateDoc: %s\n", v);
407 ZOOM_package_destroy(p[i]);
410 wrbuf_destroy(ext_type_str);
413 static void cmd_debug(ZOOM_connection *c, ZOOM_resultset *r,
414 ZOOM_options options,
417 yaz_log_init_level(YLOG_ALL);
420 static void cmd_search(ZOOM_connection *c, ZOOM_resultset *r,
421 ZOOM_options options,
425 const char *query_str = *args;
428 s = ZOOM_query_create();
429 while (*query_str == ' ')
431 if (memcmp(query_str, "cql:", 4) == 0)
433 ZOOM_query_cql(s, query_str + 4);
435 else if (ZOOM_query_prefix(s, query_str))
437 printf("Bad PQF: %s\n", query_str);
440 for (i = 0; i<MAX_CON; i++)
445 ZOOM_resultset_destroy(r[i]);
449 r[i] = ZOOM_connection_search(c[i], s);
451 ZOOM_query_destroy(s);
455 for (i = 0; i<MAX_CON; i++)
458 const char *errmsg, *addinfo, *dset;
459 /* display errors if any */
462 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
463 printf("%s error: %s (%s:%d) %s\n",
464 ZOOM_connection_option_get(c[i], "host"), errmsg,
465 dset, error, addinfo);
468 /* OK, no major errors. Look at the result count */
469 int start = ZOOM_options_get_int(options, "start", 0);
470 int count = ZOOM_options_get_int(options, "count", 0);
472 printf("%s: %lld hits\n", ZOOM_connection_option_get(c[i], "host"),
473 (long long int) ZOOM_resultset_size(r[i]));
475 display_records(c[i], r[i], start, count, "render");
480 static void cmd_scan(ZOOM_connection *c, ZOOM_resultset *r,
481 ZOOM_options options,
484 const char *query_str = *args;
485 ZOOM_query query = ZOOM_query_create();
487 ZOOM_scanset s[MAX_CON];
489 while (*query_str == ' ')
492 if (memcmp(query_str, "cql:", 4) == 0)
494 ZOOM_query_cql(query, query_str + 4);
496 else if (ZOOM_query_prefix(query, query_str))
498 printf("Bad PQF: %s\n", query_str);
502 for (i = 0; i<MAX_CON; i++)
505 s[i] = ZOOM_connection_scan1(c[i], query);
509 ZOOM_query_destroy(query);
513 for (i = 0; i<MAX_CON; i++)
516 const char *errmsg, *addinfo, *dset;
517 /* display errors if any */
520 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
521 printf("%s error: %s (%s:%d) %s\n",
522 ZOOM_connection_option_get(c[i], "host"), errmsg,
523 dset, error, addinfo);
526 size_t p, sz = ZOOM_scanset_size(s[i]);
527 for (p = 0; p < sz; p++)
531 const char *term = ZOOM_scanset_display_term(s[i], p,
533 printf("%.*s %lld\n", (int) len, term, (long long int) occ);
535 ZOOM_scanset_destroy(s[i]);
540 static void cmd_sort(ZOOM_connection *c, ZOOM_resultset *r,
541 ZOOM_options options,
544 const char *sort_spec = *args;
547 while (*sort_spec == ' ')
550 for (i = 0; i<MAX_CON; i++)
553 ZOOM_resultset_sort(r[i], "yaz", sort_spec);
558 static void cmd_help(ZOOM_connection *c, ZOOM_resultset *r,
559 ZOOM_options options,
562 printf("connect <zurl>\n");
563 printf("search <pqf>\n");
564 printf("show [<start> [<count> [<type]]]\n");
566 printf("scan <term>\n");
568 printf("close <zurl>\n");
569 printf("ext <type>\n");
570 printf("set <option> [<value>]\n");
571 printf("get <option>\n");
573 printf("options:\n");
576 printf(" databaseName\n");
577 printf(" preferredRecordSyntax\n");
579 printf(" elementSetName\n");
580 printf(" maximumRecordSize\n");
581 printf(" preferredRecordSize\n");
583 printf(" piggyback\n");
586 printf(" password\n");
587 printf(" implementationName\n");
588 printf(" charset\n");
590 printf(" timeout\n");
594 static void cmd_connect(ZOOM_connection *c, ZOOM_resultset *r,
595 ZOOM_options options,
599 const char *errmsg, *addinfo, *dset;
601 WRBUF host = next_token_new_wrbuf(args);
604 printf("missing host after connect\n");
607 for (j = -1, i = 0; i<MAX_CON; i++)
610 if (c[i] && (h = ZOOM_connection_option_get(c[i], "host")) &&
611 !strcmp(h, wrbuf_cstr(host)))
613 ZOOM_connection_destroy(c[i]);
616 else if (c[i] == 0 && j == -1)
619 if (i == MAX_CON) /* no match .. */
623 printf("no more connection available\n");
627 i = j; /* OK, use this one is available */
629 c[i] = ZOOM_connection_create(options);
630 ZOOM_connection_connect(c[i], wrbuf_cstr(host), 0);
632 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
633 printf("%s error: %s (%s:%d) %s\n",
634 ZOOM_connection_option_get(c[i], "host"), errmsg,
635 dset, error, addinfo);
639 static int cmd_parse(ZOOM_connection *c, ZOOM_resultset *r,
640 ZOOM_options options,
646 cmd_len = next_token(buf, &cmd_str);
649 if (is_command("quit", cmd_str, cmd_len))
651 else if (is_command("set", cmd_str, cmd_len))
652 cmd_set(c, r, options, buf);
653 else if (is_command("get", cmd_str, cmd_len))
654 cmd_get(c, r, options, buf);
655 else if (is_command("rget", cmd_str, cmd_len))
656 cmd_rget(c, r, options, buf);
657 else if (is_command("connect", cmd_str, cmd_len))
658 cmd_connect(c, r, options, buf);
659 else if (is_command("open", cmd_str, cmd_len))
660 cmd_connect(c, r, options, buf);
661 else if (is_command("search", cmd_str, cmd_len))
662 cmd_search(c, r, options, buf);
663 else if (is_command("facets", cmd_str, cmd_len))
664 cmd_facets(c, r, options, buf);
665 else if (is_command("find", cmd_str, cmd_len))
666 cmd_search(c, r, options, buf);
667 else if (is_command("show", cmd_str, cmd_len))
668 cmd_show(c, r, options, buf);
669 else if (is_command("close", cmd_str, cmd_len))
670 cmd_close(c, r, options, buf);
671 else if (is_command("help", cmd_str, cmd_len))
672 cmd_help(c, r, options, buf);
673 else if (is_command("ext", cmd_str, cmd_len))
674 cmd_ext(c, r, options, buf);
675 else if (is_command("debug", cmd_str, cmd_len))
676 cmd_debug(c, r, options, buf);
677 else if (is_command("scan", cmd_str, cmd_len))
678 cmd_scan(c, r, options, buf);
679 else if (is_command("sort", cmd_str, cmd_len))
680 cmd_sort(c, r, options, buf);
682 printf("unknown command %.*s\n", cmd_len, cmd_str);
686 void shell(ZOOM_connection *c, ZOOM_resultset *r,
687 ZOOM_options options)
693 const char *bp = buf;
694 #if HAVE_READLINE_READLINE_H
696 line_in=readline("ZOOM>");
699 #if HAVE_READLINE_HISTORY_H
701 add_history(line_in);
703 if(strlen(line_in) > 999) {
704 printf("Input line too long\n");
710 printf("ZOOM>"); fflush(stdout);
711 if (!fgets(buf, 999, stdin))
714 if ((cp = strchr(buf, '\n')))
716 if (!cmd_parse(c, r, options, &bp))
721 static void zoomsh(int argc, char **argv)
723 ZOOM_options options = ZOOM_options_create();
725 ZOOM_connection z39_con[MAX_CON];
726 ZOOM_resultset z39_res[MAX_CON];
728 for (i = 0; i<MAX_CON; i++)
734 for (i = 0; i<MAX_CON; i++)
738 for (i = 1; i<argc; i++)
740 const char *bp = argv[i];
741 res = cmd_parse(z39_con, z39_res, options, &bp);
742 if (res == 0) /* received quit */
745 if (res) /* do cmdline shell only if not quitting */
746 shell(z39_con, z39_res, options);
747 ZOOM_options_destroy(options);
749 for (i = 0; i<MAX_CON; i++)
751 ZOOM_connection_destroy(z39_con[i]);
752 ZOOM_resultset_destroy(z39_res[i]);
756 int main(int argc, char **argv)
758 const char *maskstr = 0;
759 if (argc > 2 && !strcmp(argv[1], "-v"))
765 else if (argc > 1 && !strncmp(argv[1], "-v", 2))
773 int mask = yaz_log_mask_str(maskstr);
774 yaz_log_init_level(mask);
782 * c-file-style: "Stroustrup"
783 * indent-tabs-mode: nil
785 * vim: shiftwidth=4 tabstop=8 expandtab