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>
18 #if HAVE_READLINE_READLINE_H
19 #include <readline/readline.h>
21 #if HAVE_READLINE_HISTORY_H
22 #include <readline/history.h>
30 static void process_events(ZOOM_connection *c)
34 yaz_log(YLOG_DEBUG, "process_events");
35 while ((i = ZOOM_event(MAX_CON, c)) != 0)
37 int peek = ZOOM_connection_peek_event(c[i-1]);
38 int event = ZOOM_connection_last_event(c[i-1]);
39 yaz_log(YLOG_DEBUG, "no = %d peek = %d event = %d %s", i-1,
42 ZOOM_get_event_str(event));
46 static int next_token(const char **cpp, const char **t_start)
49 const char *cp = *cpp;
56 while (*cp && *cp != '"')
67 while (*cp && *cp != ' ' && *cp != '\r' && *cp != '\n')
76 return len; /* return -1 if no token was read .. */
79 static WRBUF next_token_new_wrbuf(const char **cpp)
83 int len = next_token(cpp, &start);
88 wrbuf_write(w, start, len);
92 static int is_command(const char *cmd_str, const char *this_str, int this_len)
94 int cmd_len = strlen(cmd_str);
95 if (cmd_len != this_len)
97 if (memcmp(cmd_str, this_str, cmd_len))
102 static void cmd_set(ZOOM_connection *c, ZOOM_resultset *r,
103 ZOOM_options options,
108 if (!(key = next_token_new_wrbuf(args)))
110 printf("missing argument for set\n");
113 if ((val = next_token_new_wrbuf(args)))
115 ZOOM_options_set(options, wrbuf_cstr(key), wrbuf_cstr(val));
119 ZOOM_options_set(options, wrbuf_cstr(key), 0);
123 static void cmd_get(ZOOM_connection *c, ZOOM_resultset *r,
124 ZOOM_options options,
128 if (!(key = next_token_new_wrbuf(args)))
130 printf("missing argument for get\n");
134 const char *val = ZOOM_options_get(options, wrbuf_cstr(key));
135 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
140 static void cmd_rget(ZOOM_connection *c, ZOOM_resultset *r,
141 ZOOM_options options,
145 if (!(key = next_token_new_wrbuf(args)))
147 printf("missing argument for get\n");
152 for (i = 0; i<MAX_CON; i++)
158 val = ZOOM_resultset_option_get(r[i], wrbuf_cstr(key));
159 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
165 static void cmd_close(ZOOM_connection *c, ZOOM_resultset *r,
166 ZOOM_options options,
171 host = next_token_new_wrbuf(args);
172 for (i = 0; i<MAX_CON; i++)
179 ZOOM_connection_destroy(c[i]);
182 else if ((h = ZOOM_connection_option_get(c[i], "host"))
183 && !strcmp(h, wrbuf_cstr(host)))
185 ZOOM_connection_destroy(c[i]);
193 static void display_records(ZOOM_connection c,
195 size_t start, size_t count, const char *type)
198 for (i = 0; i < count; i++)
200 size_t pos = i + start;
201 ZOOM_record rec = ZOOM_resultset_record(r, pos);
202 const char *db = ZOOM_record_get(rec, "database", 0);
204 if (ZOOM_record_error(rec, 0, 0, 0))
209 int error = ZOOM_record_error(rec, &msg, &addinfo, &diagset);
211 printf("%lld %s: %s (%s:%d) %s\n", (long long) pos,
212 (db ? db : "unknown"),
213 msg, diagset, error, addinfo ? addinfo : "none");
218 const char *render = ZOOM_record_get(rec, type, &len);
219 const char *syntax = ZOOM_record_get(rec, "syntax", 0);
220 const char *schema = ZOOM_record_get(rec, "schema", 0);
221 /* if rec is non-null, we got a record for display */
224 printf("%lld database=%s syntax=%s schema=%s\n",
225 (long long) pos, (db ? db : "unknown"), syntax,
226 schema ? schema : "unknown");
229 if (fwrite(render, 1, len, stdout) != (size_t) len)
231 printf("write to stdout failed\n");
240 static void cmd_show(ZOOM_connection *c, ZOOM_resultset *r,
241 ZOOM_options options,
245 size_t start = 0, count = 1;
246 const char *type = "render";
247 WRBUF render_str = 0;
252 if ((tmp = next_token_new_wrbuf(args)))
254 start = atoi(wrbuf_cstr(tmp));
258 if ((tmp = next_token_new_wrbuf(args)))
260 count = atoi(wrbuf_cstr(tmp));
263 render_str = next_token_new_wrbuf(args);
266 type = wrbuf_cstr(render_str);
268 for (i = 0; i < MAX_CON; i++)
269 ZOOM_resultset_records(r[i], 0, start, count);
272 for (i = 0; i < MAX_CON; i++)
275 const char *errmsg, *addinfo, *dset;
276 /* display errors if any */
279 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
280 printf("%s error: %s (%s:%d) %s\n",
281 ZOOM_connection_option_get(c[i], "host"), errmsg,
282 dset, error, addinfo);
285 /* OK, no major errors. Display records... */
286 display_records(c[i], r[i], start, count, type);
290 wrbuf_destroy(render_str);
294 static void display_facets(ZOOM_facet_field *facets, int count) {
296 printf("Facets: \n");
297 for (index = 0; index < count; index++) {
299 const char *facet_name = ZOOM_facet_field_name(facets[index]);
300 printf(" %s: \n", facet_name);
301 for (term_index = 0; term_index < ZOOM_facet_field_term_count(facets[index]); term_index++) {
303 const char *term = ZOOM_facet_field_get_term(facets[index], term_index, &freq);
304 printf(" %s(%d) \n", term, freq);
309 static void cmd_facets(ZOOM_connection *c, ZOOM_resultset *r,
310 ZOOM_options options,
314 size_t start = 0, count = 1;
315 const char *type = "render";
316 WRBUF render_str = 0;
322 if ((tmp = next_token_new_wrbuf(args)))
324 start = atoi(wrbuf_cstr(tmp));
328 if ((tmp = next_token_new_wrbuf(args)))
330 count = atoi(wrbuf_cstr(tmp));
333 render_str = next_token_new_wrbuf(args);
336 type = wrbuf_cstr(render_str);
340 for (i = 0; i < MAX_CON; i++)
343 const char *errmsg, *addinfo, *dset;
344 /* display errors if any */
347 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
348 printf("%s error: %s (%s:%d) %s\n",
349 ZOOM_connection_option_get(c[i], "host"), errmsg,
350 dset, error, addinfo);
353 int num_facets = ZOOM_resultset_facets_size(r[i]);
355 ZOOM_facet_field *facets = ZOOM_resultset_facets(r[i]);
356 display_facets(facets, num_facets);
361 wrbuf_destroy(render_str);
365 static void cmd_ext(ZOOM_connection *c, ZOOM_resultset *r,
366 ZOOM_options options,
369 ZOOM_package p[MAX_CON];
371 WRBUF ext_type_str = next_token_new_wrbuf(args);
373 for (i = 0; i<MAX_CON; i++)
377 p[i] = ZOOM_connection_package(c[i], 0);
378 ZOOM_package_send(p[i], ext_type_str ? wrbuf_cstr(ext_type_str):0);
386 for (i = 0; i<MAX_CON; i++)
389 const char *errmsg, *addinfo, *dset;
390 /* display errors if any */
393 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
394 printf("%s error: %s (%s:%d) %s\n",
395 ZOOM_connection_option_get(c[i], "host"), errmsg,
396 dset, error, addinfo);
401 v = ZOOM_package_option_get(p[i], "targetReference");
403 printf("targetReference: %s\n", v);
404 v = ZOOM_package_option_get(p[i], "xmlUpdateDoc");
406 printf("xmlUpdateDoc: %s\n", v);
408 ZOOM_package_destroy(p[i]);
411 wrbuf_destroy(ext_type_str);
414 static void cmd_debug(ZOOM_connection *c, ZOOM_resultset *r,
415 ZOOM_options options,
418 yaz_log_init_level(YLOG_ALL);
421 static void cmd_search(ZOOM_connection *c, ZOOM_resultset *r,
422 ZOOM_options options,
426 const char *query_str = *args;
429 s = ZOOM_query_create();
430 while (*query_str == ' ')
432 if (memcmp(query_str, "cql:", 4) == 0)
434 ZOOM_query_cql(s, query_str + 4);
436 else if (ZOOM_query_prefix(s, query_str))
438 printf("Bad PQF: %s\n", query_str);
441 for (i = 0; i<MAX_CON; i++)
446 ZOOM_resultset_destroy(r[i]);
450 r[i] = ZOOM_connection_search(c[i], s);
452 ZOOM_query_destroy(s);
456 for (i = 0; i<MAX_CON; i++)
459 const char *errmsg, *addinfo, *dset;
460 /* display errors if any */
463 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
464 printf("%s error: %s (%s:%d) %s\n",
465 ZOOM_connection_option_get(c[i], "host"), errmsg,
466 dset, error, addinfo);
469 /* OK, no major errors. Look at the result count */
470 int start = ZOOM_options_get_int(options, "start", 0);
471 int count = ZOOM_options_get_int(options, "count", 0);
474 printf("%s: %lld hits\n", ZOOM_connection_option_get(c[i], "host"),
475 (long long int) ZOOM_resultset_size(r[i]));
477 facet_num = ZOOM_resultset_facets_size(r[i]);
480 ZOOM_facet_field *facets = ZOOM_resultset_facets(r[i]);
482 for (facet_idx = 0; facet_idx < facet_num; facet_idx++)
484 const char *name = ZOOM_facet_field_name(facets[facet_idx]);
486 size_t term_num = ZOOM_facet_field_term_count(facets[facet_idx]);
487 printf("facet: %s\n", name);
488 for (term_idx = 0; term_idx < term_num; term_idx++ )
492 ZOOM_facet_field_get_term(facets[facet_idx], term_idx, &freq);
493 printf("term: %s %d\n", term, freq);
498 display_records(c[i], r[i], start, count, "render");
503 static void cmd_scan(ZOOM_connection *c, ZOOM_resultset *r,
504 ZOOM_options options,
507 const char *query_str = *args;
508 ZOOM_query query = ZOOM_query_create();
510 ZOOM_scanset s[MAX_CON];
512 while (*query_str == ' ')
515 if (memcmp(query_str, "cql:", 4) == 0)
517 ZOOM_query_cql(query, query_str + 4);
519 else if (ZOOM_query_prefix(query, query_str))
521 printf("Bad PQF: %s\n", query_str);
525 for (i = 0; i<MAX_CON; i++)
528 s[i] = ZOOM_connection_scan1(c[i], query);
532 ZOOM_query_destroy(query);
536 for (i = 0; i<MAX_CON; i++)
539 const char *errmsg, *addinfo, *dset;
540 /* display errors if any */
543 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
544 printf("%s error: %s (%s:%d) %s\n",
545 ZOOM_connection_option_get(c[i], "host"), errmsg,
546 dset, error, addinfo);
549 size_t p, sz = ZOOM_scanset_size(s[i]);
550 for (p = 0; p < sz; p++)
554 const char *term = ZOOM_scanset_display_term(s[i], p,
556 printf("%.*s %lld\n", (int) len, term, (long long int) occ);
558 ZOOM_scanset_destroy(s[i]);
563 static void cmd_sort(ZOOM_connection *c, ZOOM_resultset *r,
564 ZOOM_options options,
567 const char *sort_spec = *args;
570 while (*sort_spec == ' ')
573 for (i = 0; i<MAX_CON; i++)
576 ZOOM_resultset_sort(r[i], "yaz", sort_spec);
581 static void cmd_help(ZOOM_connection *c, ZOOM_resultset *r,
582 ZOOM_options options,
585 printf("connect <zurl>\n");
586 printf("search <pqf>\n");
587 printf("show [<start> [<count> [<type]]]\n");
589 printf("scan <term>\n");
591 printf("close <zurl>\n");
592 printf("ext <type>\n");
593 printf("set <option> [<value>]\n");
594 printf("get <option>\n");
596 printf("options:\n");
599 printf(" databaseName\n");
600 printf(" preferredRecordSyntax\n");
602 printf(" elementSetName\n");
603 printf(" maximumRecordSize\n");
604 printf(" preferredRecordSize\n");
606 printf(" piggyback\n");
609 printf(" password\n");
610 printf(" implementationName\n");
611 printf(" charset\n");
613 printf(" timeout\n");
617 static void cmd_connect(ZOOM_connection *c, ZOOM_resultset *r,
618 ZOOM_options options,
622 const char *errmsg, *addinfo, *dset;
624 WRBUF host = next_token_new_wrbuf(args);
627 printf("missing host after connect\n");
630 for (j = -1, i = 0; i<MAX_CON; i++)
633 if (c[i] && (h = ZOOM_connection_option_get(c[i], "host")) &&
634 !strcmp(h, wrbuf_cstr(host)))
636 ZOOM_connection_destroy(c[i]);
639 else if (c[i] == 0 && j == -1)
642 if (i == MAX_CON) /* no match .. */
646 printf("no more connection available\n");
650 i = j; /* OK, use this one is available */
652 c[i] = ZOOM_connection_create(options);
653 ZOOM_connection_connect(c[i], wrbuf_cstr(host), 0);
655 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
656 printf("%s error: %s (%s:%d) %s\n",
657 ZOOM_connection_option_get(c[i], "host"), errmsg,
658 dset, error, addinfo);
662 static int cmd_parse(ZOOM_connection *c, ZOOM_resultset *r,
663 ZOOM_options options,
669 cmd_len = next_token(buf, &cmd_str);
672 if (is_command("quit", cmd_str, cmd_len))
674 else if (is_command("set", cmd_str, cmd_len))
675 cmd_set(c, r, options, buf);
676 else if (is_command("get", cmd_str, cmd_len))
677 cmd_get(c, r, options, buf);
678 else if (is_command("rget", cmd_str, cmd_len))
679 cmd_rget(c, r, options, buf);
680 else if (is_command("connect", cmd_str, cmd_len))
681 cmd_connect(c, r, options, buf);
682 else if (is_command("open", cmd_str, cmd_len))
683 cmd_connect(c, r, options, buf);
684 else if (is_command("search", cmd_str, cmd_len))
685 cmd_search(c, r, options, buf);
686 else if (is_command("facets", cmd_str, cmd_len))
687 cmd_facets(c, r, options, buf);
688 else if (is_command("find", cmd_str, cmd_len))
689 cmd_search(c, r, options, buf);
690 else if (is_command("show", cmd_str, cmd_len))
691 cmd_show(c, r, options, buf);
692 else if (is_command("close", cmd_str, cmd_len))
693 cmd_close(c, r, options, buf);
694 else if (is_command("help", cmd_str, cmd_len))
695 cmd_help(c, r, options, buf);
696 else if (is_command("ext", cmd_str, cmd_len))
697 cmd_ext(c, r, options, buf);
698 else if (is_command("debug", cmd_str, cmd_len))
699 cmd_debug(c, r, options, buf);
700 else if (is_command("scan", cmd_str, cmd_len))
701 cmd_scan(c, r, options, buf);
702 else if (is_command("sort", cmd_str, cmd_len))
703 cmd_sort(c, r, options, buf);
705 printf("unknown command %.*s\n", cmd_len, cmd_str);
709 void shell(ZOOM_connection *c, ZOOM_resultset *r,
710 ZOOM_options options)
716 const char *bp = buf;
717 #if HAVE_READLINE_READLINE_H
719 line_in=readline("ZOOM>");
722 #if HAVE_READLINE_HISTORY_H
724 add_history(line_in);
726 if(strlen(line_in) > 999) {
727 printf("Input line too long\n");
733 printf("ZOOM>"); fflush(stdout);
734 if (!fgets(buf, 999, stdin))
737 if ((cp = strchr(buf, '\n')))
739 if (!cmd_parse(c, r, options, &bp))
744 static void zoomsh(int argc, char **argv)
746 ZOOM_options options = ZOOM_options_create();
748 ZOOM_connection z39_con[MAX_CON];
749 ZOOM_resultset z39_res[MAX_CON];
751 for (i = 0; i<MAX_CON; i++)
757 for (i = 0; i<MAX_CON; i++)
761 for (i = 1; i<argc; i++)
763 const char *bp = argv[i];
764 res = cmd_parse(z39_con, z39_res, options, &bp);
765 if (res == 0) /* received quit */
768 if (res) /* do cmdline shell only if not quitting */
769 shell(z39_con, z39_res, options);
770 ZOOM_options_destroy(options);
772 for (i = 0; i<MAX_CON; i++)
774 ZOOM_connection_destroy(z39_con[i]);
775 ZOOM_resultset_destroy(z39_res[i]);
779 int main(int argc, char **argv)
781 const char *maskstr = 0;
782 if (argc > 2 && !strcmp(argv[1], "-v"))
788 else if (argc > 1 && !strncmp(argv[1], "-v", 2))
796 int mask = yaz_log_mask_str(maskstr);
797 yaz_log_init_level(mask);
805 * c-file-style: "Stroustrup"
806 * indent-tabs-mode: nil
808 * vim: shiftwidth=4 tabstop=8 expandtab