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>
16 #if HAVE_READLINE_READLINE_H
17 #include <readline/readline.h>
19 #if HAVE_READLINE_HISTORY_H
20 #include <readline/history.h>
28 static int next_token(const char **cpp, const char **t_start)
31 const char *cp = *cpp;
38 while (*cp && *cp != '"')
49 while (*cp && *cp != ' ' && *cp != '\r' && *cp != '\n')
58 return len; /* return -1 if no token was read .. */
61 static WRBUF next_token_new_wrbuf(const char **cpp)
65 int len = next_token(cpp, &start);
70 wrbuf_write(w, start, len);
74 static int is_command(const char *cmd_str, const char *this_str, int this_len)
76 int cmd_len = strlen(cmd_str);
77 if (cmd_len != this_len)
79 if (memcmp(cmd_str, this_str, cmd_len))
84 static void cmd_set(ZOOM_connection *c, ZOOM_resultset *r,
90 if (!(key = next_token_new_wrbuf(args)))
92 printf("missing argument for set\n");
95 if ((val = next_token_new_wrbuf(args)))
97 ZOOM_options_set(options, wrbuf_cstr(key), wrbuf_cstr(val));
101 ZOOM_options_set(options, wrbuf_cstr(key), 0);
105 static void cmd_get(ZOOM_connection *c, ZOOM_resultset *r,
106 ZOOM_options options,
110 if (!(key = next_token_new_wrbuf(args)))
112 printf("missing argument for get\n");
116 const char *val = ZOOM_options_get(options, wrbuf_cstr(key));
117 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
122 static void cmd_rget(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");
134 for (i = 0; i<MAX_CON; i++)
140 val = ZOOM_resultset_option_get(r[i], wrbuf_cstr(key));
141 printf("%s = %s\n", wrbuf_cstr(key), val ? val : "<null>");
147 static void cmd_close(ZOOM_connection *c, ZOOM_resultset *r,
148 ZOOM_options options,
153 host = next_token_new_wrbuf(args);
154 for (i = 0; i<MAX_CON; i++)
161 ZOOM_connection_destroy(c[i]);
164 else if ((h = ZOOM_connection_option_get(c[i], "host"))
165 && !strcmp(h, wrbuf_cstr(host)))
167 ZOOM_connection_destroy(c[i]);
175 static void display_records(ZOOM_connection c,
177 size_t start, size_t count, const char *type)
180 for (i = 0; i < count; i++)
182 size_t pos = i + start;
183 ZOOM_record rec = ZOOM_resultset_record(r, pos);
184 const char *db = ZOOM_record_get(rec, "database", 0);
186 if (ZOOM_record_error(rec, 0, 0, 0))
191 int error = ZOOM_record_error(rec, &msg, &addinfo, &diagset);
193 printf("%lld %s: %s (%s:%d) %s\n", (long long) pos,
194 (db ? db : "unknown"),
195 msg, diagset, error, addinfo ? addinfo : "none");
200 const char *render = ZOOM_record_get(rec, type, &len);
201 const char *opac_render = ZOOM_record_get(rec, "opac", &opac_len);
202 const char *syntax = ZOOM_record_get(rec, "syntax", 0);
203 const char *schema = ZOOM_record_get(rec, "schema", 0);
204 /* if rec is non-null, we got a record for display */
207 printf("%lld database=%s syntax=%s schema=%s\n",
208 (long long) pos, (db ? db : "unknown"), syntax,
209 schema ? schema : "unknown");
212 if (fwrite(render, 1, len, stdout) != (size_t) len)
214 printf("write to stdout failed\n");
220 if (fwrite(opac_render, 1, opac_len, stdout) != (size_t)
222 printf("write to stdout failed\n");
229 static void cmd_show(ZOOM_connection *c, ZOOM_resultset *r,
230 ZOOM_options options,
234 size_t start = 0, count = 1;
235 const char *type = "render";
236 WRBUF render_str = 0;
241 if ((tmp = next_token_new_wrbuf(args)))
243 start = atoi(wrbuf_cstr(tmp));
247 if ((tmp = next_token_new_wrbuf(args)))
249 count = atoi(wrbuf_cstr(tmp));
252 render_str = next_token_new_wrbuf(args);
255 type = wrbuf_cstr(render_str);
257 for (i = 0; i < MAX_CON; i++)
258 ZOOM_resultset_records(r[i], 0, start, count);
259 while (ZOOM_event(MAX_CON, c))
262 for (i = 0; i < MAX_CON; i++)
265 const char *errmsg, *addinfo, *dset;
266 /* display errors if any */
269 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
270 printf("%s error: %s (%s:%d) %s\n",
271 ZOOM_connection_option_get(c[i], "host"), errmsg,
272 dset, error, addinfo);
275 /* OK, no major errors. Display records... */
276 display_records(c[i], r[i], start, count, type);
280 wrbuf_destroy(render_str);
284 static void cmd_ext(ZOOM_connection *c, ZOOM_resultset *r,
285 ZOOM_options options,
288 ZOOM_package p[MAX_CON];
290 WRBUF ext_type_str = next_token_new_wrbuf(args);
292 for (i = 0; i<MAX_CON; i++)
296 p[i] = ZOOM_connection_package(c[i], 0);
297 ZOOM_package_send(p[i], ext_type_str ? wrbuf_cstr(ext_type_str):0);
303 while (ZOOM_event(MAX_CON, c))
306 for (i = 0; i<MAX_CON; i++)
309 const char *errmsg, *addinfo, *dset;
310 /* display errors if any */
313 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
314 printf("%s error: %s (%s:%d) %s\n",
315 ZOOM_connection_option_get(c[i], "host"), errmsg,
316 dset, error, addinfo);
321 v = ZOOM_package_option_get(p[i], "targetReference");
323 printf("targetReference: %s\n", v);
324 v = ZOOM_package_option_get(p[i], "xmlUpdateDoc");
326 printf("xmlUpdateDoc: %s\n", v);
328 ZOOM_package_destroy(p[i]);
331 wrbuf_destroy(ext_type_str);
334 static void cmd_debug(ZOOM_connection *c, ZOOM_resultset *r,
335 ZOOM_options options,
338 yaz_log_init_level(YLOG_ALL);
341 static void cmd_search(ZOOM_connection *c, ZOOM_resultset *r,
342 ZOOM_options options,
346 const char *query_str = *args;
349 s = ZOOM_query_create();
350 while (*query_str == ' ')
352 if (memcmp(query_str, "cql:", 4) == 0)
354 ZOOM_query_cql(s, query_str + 4);
356 else if (ZOOM_query_prefix(s, query_str))
358 printf("Bad PQF: %s\n", query_str);
361 for (i = 0; i<MAX_CON; i++)
366 ZOOM_resultset_destroy(r[i]);
370 r[i] = ZOOM_connection_search(c[i], s);
372 ZOOM_query_destroy(s);
374 while (ZOOM_event(MAX_CON, c))
377 for (i = 0; i<MAX_CON; i++)
380 const char *errmsg, *addinfo, *dset;
381 /* display errors if any */
384 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
385 printf("%s error: %s (%s:%d) %s\n",
386 ZOOM_connection_option_get(c[i], "host"), errmsg,
387 dset, error, addinfo);
390 /* OK, no major errors. Look at the result count */
391 int start = ZOOM_options_get_int(options, "start", 0);
392 int count = ZOOM_options_get_int(options, "count", 0);
394 printf("%s: %lld hits\n", ZOOM_connection_option_get(c[i], "host"),
395 (long long int) ZOOM_resultset_size(r[i]));
397 display_records(c[i], r[i], start, count, "render");
402 static void cmd_scan(ZOOM_connection *c, ZOOM_resultset *r,
403 ZOOM_options options,
406 const char *query_str = *args;
407 ZOOM_query query = ZOOM_query_create();
409 ZOOM_scanset s[MAX_CON];
411 while (*query_str == ' ')
414 if (memcmp(query_str, "cql:", 4) == 0)
416 ZOOM_query_cql(query, query_str + 4);
418 else if (ZOOM_query_prefix(query, query_str))
420 printf("Bad PQF: %s\n", query_str);
424 for (i = 0; i<MAX_CON; i++)
427 s[i] = ZOOM_connection_scan1(c[i], query);
431 ZOOM_query_destroy(query);
433 while (ZOOM_event(MAX_CON, c))
435 for (i = 0; i<MAX_CON; i++)
438 const char *errmsg, *addinfo, *dset;
439 /* display errors if any */
442 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
443 printf("%s error: %s (%s:%d) %s\n",
444 ZOOM_connection_option_get(c[i], "host"), errmsg,
445 dset, error, addinfo);
448 size_t p, sz = ZOOM_scanset_size(s[i]);
449 for (p = 0; p < sz; p++)
453 const char *term = ZOOM_scanset_display_term(s[i], p,
455 printf("%.*s %lld\n", (int) len, term, (long long int) occ);
457 ZOOM_scanset_destroy(s[i]);
462 static void cmd_sort(ZOOM_connection *c, ZOOM_resultset *r,
463 ZOOM_options options,
466 const char *sort_spec = *args;
469 while (*sort_spec == ' ')
472 for (i = 0; i<MAX_CON; i++)
475 ZOOM_resultset_sort(r[i], "yaz", sort_spec);
477 while (ZOOM_event(MAX_CON, c))
481 static void cmd_help(ZOOM_connection *c, ZOOM_resultset *r,
482 ZOOM_options options,
485 printf("connect <zurl>\n");
486 printf("search <pqf>\n");
487 printf("show [<start> [<count> [<type]]]\n");
488 printf("scan <term>\n");
490 printf("close <zurl>\n");
491 printf("ext <type>\n");
492 printf("set <option> [<value>]\n");
493 printf("get <option>\n");
495 printf("options:\n");
498 printf(" databaseName\n");
499 printf(" preferredRecordSyntax\n");
501 printf(" elementSetName\n");
502 printf(" maximumRecordSize\n");
503 printf(" preferredRecordSize\n");
505 printf(" piggyback\n");
508 printf(" password\n");
509 printf(" implementationName\n");
510 printf(" charset\n");
512 printf(" timeout\n");
515 static void cmd_connect(ZOOM_connection *c, ZOOM_resultset *r,
516 ZOOM_options options,
520 const char *errmsg, *addinfo, *dset;
522 WRBUF host = next_token_new_wrbuf(args);
525 printf("missing host after connect\n");
528 for (j = -1, i = 0; i<MAX_CON; i++)
531 if (c[i] && (h = ZOOM_connection_option_get(c[i], "host")) &&
532 !strcmp(h, wrbuf_cstr(host)))
534 ZOOM_connection_destroy(c[i]);
537 else if (c[i] == 0 && j == -1)
540 if (i == MAX_CON) /* no match .. */
544 printf("no more connection available\n");
548 i = j; /* OK, use this one is available */
550 c[i] = ZOOM_connection_create(options);
551 ZOOM_connection_connect(c[i], wrbuf_cstr(host), 0);
553 if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
554 printf("%s error: %s (%s:%d) %s\n",
555 ZOOM_connection_option_get(c[i], "host"), errmsg,
556 dset, error, addinfo);
560 static int cmd_parse(ZOOM_connection *c, ZOOM_resultset *r,
561 ZOOM_options options,
567 cmd_len = next_token(buf, &cmd_str);
570 if (is_command("quit", cmd_str, cmd_len))
572 else if (is_command("set", cmd_str, cmd_len))
573 cmd_set(c, r, options, buf);
574 else if (is_command("get", cmd_str, cmd_len))
575 cmd_get(c, r, options, buf);
576 else if (is_command("rget", cmd_str, cmd_len))
577 cmd_rget(c, r, options, buf);
578 else if (is_command("connect", cmd_str, cmd_len))
579 cmd_connect(c, r, options, buf);
580 else if (is_command("open", cmd_str, cmd_len))
581 cmd_connect(c, r, options, buf);
582 else if (is_command("search", cmd_str, cmd_len))
583 cmd_search(c, r, options, buf);
584 else if (is_command("find", cmd_str, cmd_len))
585 cmd_search(c, r, options, buf);
586 else if (is_command("show", cmd_str, cmd_len))
587 cmd_show(c, r, options, buf);
588 else if (is_command("close", cmd_str, cmd_len))
589 cmd_close(c, r, options, buf);
590 else if (is_command("help", cmd_str, cmd_len))
591 cmd_help(c, r, options, buf);
592 else if (is_command("ext", cmd_str, cmd_len))
593 cmd_ext(c, r, options, buf);
594 else if (is_command("debug", cmd_str, cmd_len))
595 cmd_debug(c, r, options, buf);
596 else if (is_command("scan", cmd_str, cmd_len))
597 cmd_scan(c, r, options, buf);
598 else if (is_command("sort", cmd_str, cmd_len))
599 cmd_sort(c, r, options, buf);
601 printf("unknown command %.*s\n", cmd_len, cmd_str);
605 void shell(ZOOM_connection *c, ZOOM_resultset *r,
606 ZOOM_options options)
612 const char *bp = buf;
613 #if HAVE_READLINE_READLINE_H
615 line_in=readline("ZOOM>");
618 #if HAVE_READLINE_HISTORY_H
620 add_history(line_in);
622 if(strlen(line_in) > 999) {
623 printf("Input line too long\n");
629 printf("ZOOM>"); fflush(stdout);
630 if (!fgets(buf, 999, stdin))
633 if ((cp = strchr(buf, '\n')))
635 if (!cmd_parse(c, r, options, &bp))
640 static void zoomsh(int argc, char **argv)
642 ZOOM_options options = ZOOM_options_create();
644 ZOOM_connection z39_con[MAX_CON];
645 ZOOM_resultset z39_res[MAX_CON];
647 for (i = 0; i<MAX_CON; i++)
653 for (i = 0; i<MAX_CON; i++)
657 for (i = 1; i<argc; i++)
659 const char *bp = argv[i];
660 res = cmd_parse(z39_con, z39_res, options, &bp);
661 if (res == 0) /* received quit */
664 if (res) /* do cmdline shell only if not quitting */
665 shell(z39_con, z39_res, options);
666 ZOOM_options_destroy(options);
668 for (i = 0; i<MAX_CON; i++)
670 ZOOM_connection_destroy(z39_con[i]);
671 ZOOM_resultset_destroy(z39_res[i]);
675 int main(int argc, char **argv)
677 const char *maskstr = 0;
678 if (argc > 2 && !strcmp(argv[1], "-v"))
684 else if (argc > 1 && !strncmp(argv[1], "-v", 2))
692 int mask = yaz_log_mask_str(maskstr);
693 yaz_log_init_level(mask);
701 * c-file-style: "Stroustrup"
702 * indent-tabs-mode: nil
704 * vim: shiftwidth=4 tabstop=8 expandtab