- static struct {
- char *cmd;
- int (*fun)(char *arg);
- char *ad;
- } cmd[] = {
- {"open", cmd_open, "('tcp'|'osi')':'[<tsel>'/']<host>[':'<port>]"},
- {"quit", cmd_quit, ""},
- {"find", cmd_find, "<query>"},
- {"delete", cmd_delete, "<setname>"},
- {"base", cmd_base, "<base-name>"},
- {"show", cmd_show, "<rec#>['+'<#recs>['+'<setname>]]"},
- {"scan", cmd_scan, "<term>"},
- {"sort", cmd_sort, "<sortkey> <flag> <sortkey> <flag> ..."},
- {"sort+", cmd_sort_newset, "<sortkey> <flag> <sortkey> <flag> ..."},
- {"authentication", cmd_authentication, "<acctstring>"},
- {"lslb", cmd_lslb, "<largeSetLowerBound>"},
- {"ssub", cmd_ssub, "<smallSetUpperBound>"},
- {"mspn", cmd_mspn, "<mediumSetPresentNumber>"},
- {"status", cmd_status, ""},
- {"setnames", cmd_setnames, ""},
- {"cancel", cmd_cancel, ""},
- {"format", cmd_format, "<recordsyntax>"},
- {"schema", cmd_schema, "<schema>"},
- {"elements", cmd_elements, "<elementSetName>"},
- {"close", cmd_close, ""},
- {"attributeset", cmd_attributeset, "<attrset>"},
- {"querytype", cmd_querytype, "<type>"},
- {"refid", cmd_refid, "<id>"},
- {"itemorder", cmd_itemorder, "ill|item <itemno>"},
- {"update", cmd_update, "<item>"},
- {"packagename", cmd_packagename, "<packagename>"},
-#ifdef ASN_COMPILED
- /* Server Admin Functions */
- {"adm-reindex", cmd_adm_reindex, "<database-name>"},
- {"adm-truncate", cmd_adm_truncate, "('database'|'index')<object-name>"},
- {"adm-create", cmd_adm_create, ""},
- {"adm-drop", cmd_adm_drop, "('database'|'index')<object-name>"},
- {"adm-import", cmd_adm_import, "<record-type> <dir> <pattern>"},
- {"adm-refresh", cmd_adm_refresh, ""},
- {"adm-commit", cmd_adm_commit, ""},
- {"adm-shutdown", cmd_adm_shutdown, ""},
- {"adm-startup", cmd_adm_startup, ""},
+ char l1[30];
+
+ *l1 = 0;
+ if (sscanf(arg, "%29s", l1) < 1)
+ {
+ printf("Display character set is `%s'\n",
+ outputCharset ? outputCharset: "none");
+ }
+ else
+ {
+ xfree(outputCharset);
+ outputCharset = 0;
+ if (!strcmp(l1, "auto") && codeset)
+ {
+ if (codeset)
+ {
+ printf("Display character set: %s\n", codeset);
+ outputCharset = xstrdup(codeset);
+ }
+ else
+ printf("No codeset found on this system\n");
+ }
+ else if (strcmp(l1, "-") && strcmp(l1, "none"))
+ outputCharset = xstrdup(l1);
+ }
+ return 1;
+}
+
+int cmd_negcharset(const char *arg)
+{
+ char l1[30];
+
+ *l1 = 0;
+ if (sscanf(arg, "%29s %d %d", l1, &negotiationCharsetRecords,
+ &negotiationCharsetVersion) < 1)
+ {
+ printf("Negotiation character set `%s'\n",
+ negotiationCharset ? negotiationCharset: "none");
+ if (negotiationCharset)
+ {
+ printf("Records in charset %s\n", negotiationCharsetRecords ?
+ "yes" : "no");
+ printf("Charneg version %d\n", negotiationCharsetVersion);
+ }
+ }
+ else
+ {
+ xfree(negotiationCharset);
+ negotiationCharset = NULL;
+ if (*l1 && strcmp(l1, "-") && strcmp(l1, "none"))
+ {
+ negotiationCharset = xstrdup(l1);
+ printf("Character set negotiation : %s\n", negotiationCharset);
+ }
+ }
+ return 1;
+}
+
+int cmd_charset(const char* arg)
+{
+ char l1[30], l2[30], l3[30], l4[30];
+
+ *l1 = *l2 = *l3 = *l4 = '\0';
+ if (sscanf(arg, "%29s %29s %29s %29s", l1, l2, l3, l4) < 1)
+ {
+ cmd_negcharset("");
+ cmd_displaycharset("");
+ cmd_marccharset("");
+ cmd_querycharset("");
+ }
+ else
+ {
+ cmd_negcharset(l1);
+ if (*l2)
+ cmd_displaycharset(l2);
+ if (*l3)
+ cmd_marccharset(l3);
+ if (*l4)
+ cmd_querycharset(l4);
+ }
+ return 1;
+}
+
+int cmd_lang(const char* arg)
+{
+ if (*arg == '\0') {
+ printf("Current language is `%s'\n", yazLang ? yazLang : "none");
+ return 1;
+ }
+ xfree(yazLang);
+ yazLang = NULL;
+ if (*arg)
+ yazLang = xstrdup(arg);
+ return 1;
+}
+
+int cmd_source(const char* arg, int echo )
+{
+ /* first should open the file and read one line at a time.. */
+ FILE* includeFile;
+ char line[102400], *cp;
+
+ if(strlen(arg)<1) {
+ fprintf(stderr,"Error in source command use a filename\n");
+ return -1;
+ }
+
+ includeFile = fopen(arg, "r");
+
+ if(!includeFile) {
+ fprintf(stderr,"Unable to open file %s for reading\n",arg);
+ return -1;
+ }
+
+ while(!feof(includeFile)) {
+ memset(line,0,sizeof(line));
+ fgets(line,sizeof(line),includeFile);
+
+ if(strlen(line) < 2) continue;
+ if(line[0] == '#') continue;
+
+ if ((cp = strrchr(line, '\n')))
+ *cp = '\0';
+
+ if( echo ) {
+ printf( "processing line: %s\n",line );
+ };
+ process_cmd_line(line);
+ }
+
+ if(fclose(includeFile)<0) {
+ perror("unable to close include file");
+ exit(1);
+ }
+ return 1;
+}
+
+int cmd_source_echo(const char* arg)
+{
+ cmd_source(arg, 1);
+ return 1;
+}
+
+int cmd_source_noecho(const char* arg)
+{
+ cmd_source(arg, 0);
+ return 1;
+}
+
+
+int cmd_subshell(const char* args)
+{
+ if(strlen(args))
+ system(args);
+ else
+ system(getenv("SHELL"));
+
+ printf("\n");
+ return 1;
+}
+
+int cmd_set_berfile(const char *arg)
+{
+ if (ber_file && ber_file != stdout && ber_file != stderr)
+ fclose(ber_file);
+ if (!strcmp(arg, ""))
+ ber_file = 0;
+ else if (!strcmp(arg, "-"))
+ ber_file = stdout;
+ else
+ ber_file = fopen(arg, "a");
+ return 1;
+}
+
+int cmd_set_apdufile(const char *arg)
+{
+ if(apdu_file && apdu_file != stderr && apdu_file != stderr)
+ fclose(apdu_file);
+ if (!strcmp(arg, ""))
+ apdu_file = 0;
+ else if (!strcmp(arg, "-"))
+ apdu_file = stderr;
+ else
+ {
+ apdu_file = fopen(arg, "a");
+ if (!apdu_file)
+ perror("unable to open apdu log file");
+ }
+ if (apdu_file)
+ odr_setprint(print, apdu_file);
+ return 1;
+}
+
+int cmd_set_cclfile(const char* arg)
+{
+ FILE *inf;
+
+ bibset = ccl_qual_mk();
+ inf = fopen(arg, "r");
+ if (!inf)
+ perror("unable to open CCL file");
+ else
+ {
+ ccl_qual_file(bibset, inf);
+ fclose(inf);
+ }
+ strcpy(ccl_fields,arg);
+ return 0;
+}
+
+int cmd_set_cqlfile(const char* arg)
+{
+ cql_transform_t newcqltrans;
+
+ if ((newcqltrans = cql_transform_open_fname(arg)) == 0) {
+ perror("unable to open CQL file");
+ return 0;
+ }
+ if (cqltrans != 0)
+ cql_transform_close(cqltrans);
+
+ cqltrans = newcqltrans;
+ strcpy(cql_fields, arg);
+ return 0;
+}
+
+int cmd_set_auto_reconnect(const char* arg)
+{
+ if(strlen(arg)==0) {
+ auto_reconnect = ! auto_reconnect;
+ } else if(strcmp(arg,"on")==0) {
+ auto_reconnect = 1;
+ } else if(strcmp(arg,"off")==0) {
+ auto_reconnect = 0;
+ } else {
+ printf("Error use on or off\n");
+ return 1;
+ }
+
+ if (auto_reconnect)
+ printf("Set auto reconnect enabled.\n");
+ else
+ printf("Set auto reconnect disabled.\n");
+
+ return 0;
+}
+
+
+int cmd_set_auto_wait(const char* arg)
+{
+ if(strlen(arg)==0) {
+ auto_wait = ! auto_wait;
+ } else if(strcmp(arg,"on")==0) {
+ auto_wait = 1;
+ } else if(strcmp(arg,"off")==0) {
+ auto_wait = 0;
+ } else {
+ printf("Error use on or off\n");
+ return 1;
+ }
+
+ if (auto_wait)
+ printf("Set auto wait enabled.\n");
+ else
+ printf("Set auto wait disabled.\n");
+
+ return 0;
+}
+
+int cmd_set_marcdump(const char* arg)
+{
+ if(marc_file && marc_file != stderr) { /* don't close stdout*/
+ fclose(marc_file);
+ }
+
+ if (!strcmp(arg, ""))
+ marc_file = 0;
+ else if (!strcmp(arg, "-"))
+ marc_file = stderr;
+ else
+ {
+ marc_file = fopen(arg, "a");
+ if (!marc_file)
+ perror("unable to open marc log file");
+ }
+ return 1;
+}
+
+/*
+ this command takes 3 arge {name class oid}
+*/
+int cmd_register_oid(const char* args) {
+ static struct {
+ char* className;
+ oid_class oclass;
+ } oid_classes[] = {
+ {"appctx",CLASS_APPCTX},
+ {"absyn",CLASS_ABSYN},
+ {"attset",CLASS_ATTSET},
+ {"transyn",CLASS_TRANSYN},
+ {"diagset",CLASS_DIAGSET},
+ {"recsyn",CLASS_RECSYN},
+ {"resform",CLASS_RESFORM},
+ {"accform",CLASS_ACCFORM},
+ {"extserv",CLASS_EXTSERV},
+ {"userinfo",CLASS_USERINFO},
+ {"elemspec",CLASS_ELEMSPEC},
+ {"varset",CLASS_VARSET},
+ {"schema",CLASS_SCHEMA},
+ {"tagset",CLASS_TAGSET},
+ {"general",CLASS_GENERAL},
+ {0,(enum oid_class) 0}
+ };
+ char oname_str[101], oclass_str[101], oid_str[101];
+ int i;
+ oid_class oidclass = CLASS_GENERAL;
+ Odr_oid oid[OID_SIZE];
+
+ if (sscanf(args, "%100[^ ] %100[^ ] %100s",
+ oname_str,oclass_str, oid_str) < 1) {
+ printf("Error in register command \n");
+ return 0;
+ }
+
+ for (i = 0; oid_classes[i].className; i++) {
+ if (!strcmp(oid_classes[i].className, oclass_str))
+ {
+ oidclass=oid_classes[i].oclass;
+ break;
+ }
+ }
+
+ if(!(oid_classes[i].className)) {
+ printf("Unknown oid class %s\n",oclass_str);
+ return 0;
+ }
+
+ oid_dotstring_to_oid(oid_str, oid);
+
+ if (yaz_oid_add(yaz_oid_std(), oidclass, oname_str, oid))
+ {
+ printf("oid %s already exists, registration failed\n",
+ oname_str);
+ }
+ return 1;
+}
+
+int cmd_push_command(const char* arg)
+{
+#if HAVE_READLINE_HISTORY_H
+ if(strlen(arg)>1)
+ add_history(arg);
+#else
+ fprintf(stderr,"Not compiled with the readline/history module\n");
+#endif
+ return 1;
+}
+
+void source_rc_file(const char *rc_file)
+{
+ /* If rc_file != NULL, source that. Else
+ Look for .yazclientrc and read it if it exists.
+ If it does not exist, read $HOME/.yazclientrc instead */
+ struct stat statbuf;
+
+ if (rc_file)
+ {
+ if (stat(rc_file, &statbuf) == 0)
+ cmd_source(rc_file, 0);
+ else
+ {
+ fprintf(stderr, "yaz_client: cannot source '%s'\n", rc_file);
+ exit(1);
+ }
+ }
+ else
+ {
+ char fname[1000];
+ strcpy(fname, ".yazclientrc");
+ if (stat(fname, &statbuf)==0)
+ {
+ cmd_source(fname, 0);
+ }
+ else
+ {
+ const char* homedir = getenv("HOME");
+ if (homedir)
+ {
+ sprintf(fname, "%.800s/%s", homedir, ".yazclientrc");
+ if (stat(fname, &statbuf)==0)
+ cmd_source(fname, 0);
+ }
+ }
+ }
+}
+
+void add_to_readline_history(void *client_data, const char *line)
+{
+#if HAVE_READLINE_HISTORY_H
+ if (strlen(line))
+ add_history(line);
+#endif
+}
+
+static void initialize(const char *rc_file)
+{
+ FILE *inf;
+ int i;
+
+ if (!(out = odr_createmem(ODR_ENCODE)) ||
+ !(in = odr_createmem(ODR_DECODE)) ||
+ !(print = odr_createmem(ODR_PRINT)))
+ {
+ fprintf(stderr, "failed to allocate ODR streams\n");
+ exit(1);
+ }
+
+ setvbuf(stdout, 0, _IONBF, 0);
+ if (apdu_file)
+ odr_setprint(print, apdu_file);
+
+ bibset = ccl_qual_mk();
+ inf = fopen(ccl_fields, "r");
+ if (inf)
+ {
+ ccl_qual_file(bibset, inf);
+ fclose(inf);
+ }
+
+ cqltrans = cql_transform_open_fname(cql_fields);
+ /* If this fails, no problem: we detect cqltrans == 0 later */
+
+#if HAVE_READLINE_READLINE_H
+ rl_attempted_completion_function =
+ (char **(*)(const char *, int, int)) readline_completer;
+#endif
+ for(i = 0; i < maxOtherInfosSupported; ++i) {
+ extraOtherInfos[i].oid[0] = -1;
+ extraOtherInfos[i].value = 0;
+ }
+
+ cmd_format("usmarc");
+
+ source_rc_file(rc_file);
+
+ file_history = file_history_new();
+ file_history_load(file_history);
+ file_history_trav(file_history, 0, add_to_readline_history);
+}
+
+
+#if HAVE_GETTIMEOFDAY
+struct timeval tv_start;
+#endif
+
+#if YAZ_HAVE_XML2
+static void handle_srw_record(Z_SRW_record *rec)
+{
+ if (rec->recordPosition)
+ {
+ printf("pos=%d", *rec->recordPosition);
+ setno = *rec->recordPosition + 1;
+ }
+ if (rec->recordSchema)
+ printf(" schema=%s", rec->recordSchema);
+ printf("\n");
+ if (rec->recordData_buf && rec->recordData_len)
+ {
+ fwrite(rec->recordData_buf, 1, rec->recordData_len, stdout);
+ if (marc_file)
+ fwrite(rec->recordData_buf, 1, rec->recordData_len, marc_file);
+ }
+ else
+ printf("No data!");
+ printf("\n");
+}
+
+static void handle_srw_explain_response(Z_SRW_explainResponse *res)
+{
+ handle_srw_record(&res->record);
+}
+
+static void handle_srw_response(Z_SRW_searchRetrieveResponse *res)
+{
+ int i;
+
+ printf("Received SRW SearchRetrieve Response\n");
+
+ for (i = 0; i<res->num_diagnostics; i++)
+ {
+ if (res->diagnostics[i].uri)
+ printf("SRW diagnostic %s\n",
+ res->diagnostics[i].uri);
+ else
+ printf("SRW diagnostic missing or could not be decoded\n");
+ if (res->diagnostics[i].message)
+ printf("Message: %s\n", res->diagnostics[i].message);
+ if (res->diagnostics[i].details)
+ printf("Details: %s\n", res->diagnostics[i].details);
+ }
+ if (res->numberOfRecords)
+ printf("Number of hits: %d\n", *res->numberOfRecords);
+ for (i = 0; i<res->num_records; i++)
+ handle_srw_record(res->records + i);
+}
+
+static void handle_srw_scan_term(Z_SRW_scanTerm *term)
+{
+ if (term->displayTerm)
+ printf("%s:", term->displayTerm);
+ else if (term->value)
+ printf("%s:", term->value);
+ else
+ printf("No value:");
+ if (term->numberOfRecords)
+ printf(" %d", *term->numberOfRecords);
+ if (term->whereInList)
+ printf(" %s", term->whereInList);
+ if (term->value && term->displayTerm)
+ printf(" %s", term->value);
+
+ strcpy(last_scan_line, term->value);
+ printf("\n");
+}
+
+static void handle_srw_scan_response(Z_SRW_scanResponse *res)
+{
+ int i;
+
+ printf("Received SRW Scan Response\n");
+
+ for (i = 0; i<res->num_diagnostics; i++)
+ {
+ if (res->diagnostics[i].uri)
+ printf("SRW diagnostic %s\n",
+ res->diagnostics[i].uri);
+ else
+ printf("SRW diagnostic missing or could not be decoded\n");
+ if (res->diagnostics[i].message)
+ printf("Message: %s\n", res->diagnostics[i].message);
+ if (res->diagnostics[i].details)
+ printf("Details: %s\n", res->diagnostics[i].details);
+ }
+ if (res->terms)
+ for (i = 0; i<res->num_terms; i++)
+ handle_srw_scan_term(res->terms + i);
+}
+
+static void http_response(Z_HTTP_Response *hres)
+{
+ int ret = -1;
+ const char *connection_head = z_HTTP_header_lookup(hres->headers,
+ "Connection");
+ if (!yaz_srw_check_content_type(hres))
+ printf("Content type does not appear to be XML\n");
+ else
+ {
+ Z_SOAP *soap_package = 0;
+ ODR o = odr_createmem(ODR_DECODE);
+ Z_SOAP_Handler soap_handlers[3] = {
+ {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
+ {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
+ {0, 0, 0}
+ };
+ ret = z_soap_codec(o, &soap_package,
+ &hres->content_buf, &hres->content_len,
+ soap_handlers);
+ if (!ret && soap_package->which == Z_SOAP_generic)
+ {
+ Z_SRW_PDU *sr = (Z_SRW_PDU *) soap_package->u.generic->p;
+ if (sr->which == Z_SRW_searchRetrieve_response)
+ handle_srw_response(sr->u.response);
+ else if (sr->which == Z_SRW_explain_response)
+ handle_srw_explain_response(sr->u.explain_response);
+ else if (sr->which == Z_SRW_scan_response)
+ handle_srw_scan_response(sr->u.scan_response);
+ else if (sr->which == Z_SRW_update_response)
+ printf("Got update response. Status: %s\n",
+ sr->u.update_response->operationStatus);
+ else
+ ret = -1;
+ }
+ else if (soap_package && (soap_package->which == Z_SOAP_fault
+ || soap_package->which == Z_SOAP_error))
+ {
+ printf("HTTP Error Status=%d\n", hres->code);
+ printf("SOAP Fault code %s\n",
+ soap_package->u.fault->fault_code);
+ printf("SOAP Fault string %s\n",
+ soap_package->u.fault->fault_string);
+ if (soap_package->u.fault->details)
+ printf("SOAP Details %s\n",
+ soap_package->u.fault->details);
+ }
+ else
+ {
+ printf("z_soap_codec failed. (no SOAP error)\n");
+ ret = -1;
+ }
+ odr_destroy(o);
+ }
+ if (ret)
+ {
+ if (hres->code != 200)
+ {
+ printf("HTTP Error Status=%d\n", hres->code);
+ }
+ else
+ {
+ printf("Decoding of SRW package failed\n");
+ }
+ close_session();
+ }
+ else
+ {
+ if (!strcmp(hres->version, "1.0"))
+ {
+ /* HTTP 1.0: only if Keep-Alive we stay alive.. */
+ if (!connection_head || strcmp(connection_head, "Keep-Alive"))
+ close_session();
+ }
+ else
+ {
+ /* HTTP 1.1: only if no close we stay alive .. */
+ if (connection_head && !strcmp(connection_head, "close"))
+ close_session();
+ }
+ }
+}