+ 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");
+
+ file_history = file_history_new();
+
+ source_rc_file(rc_file);
+
+ 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=" ODR_INT_PRINTF, *rec->recordPosition);
+ setno = *rec->recordPosition + 1;
+ }
+ if (rec->recordSchema)
+ printf(" schema=%s", rec->recordSchema);
+ printf("\n");
+ if (rec->recordData_buf && rec->recordData_len)
+ {
+ printf("%.*s", rec->recordData_len, rec->recordData_buf);
+ marc_file_write(rec->recordData_buf, rec->recordData_len);
+ }
+ 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: " ODR_INT_PRINTF "\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(" " ODR_INT_PRINTF, *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 (hres->code != 200)
+ {
+ printf("HTTP Error Status=%d\n", hres->code);
+ }
+
+ 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
+ {
+ printf("Decoding of SRW package failed\n");
+ ret = -1;
+ }
+ }
+ else if (soap_package && (soap_package->which == Z_SOAP_fault
+ || soap_package->which == Z_SOAP_error))
+ {
+ 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)
+ close_session(); /* close session on error */
+ 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();
+ }
+ }
+}
+#endif
+
+static void wait_and_handle_response(int one_response_only)
+{
+ int reconnect_ok = 1;
+ int res;
+ char *netbuffer= 0;
+ int netbufferlen = 0;
+#if HAVE_GETTIMEOFDAY
+ int got_tv_end = 0;
+ struct timeval tv_end;
+#endif
+ Z_GDU *gdu;
+
+ while(conn)
+ {
+ res = cs_get(conn, &netbuffer, &netbufferlen);
+ if (reconnect_ok && res <= 0 && protocol == PROTO_HTTP)
+ {
+ cs_close(conn);
+ conn = 0;
+ session_connect(cur_host);
+ reconnect_ok = 0;
+ if (conn)
+ {
+ char *buf_out;
+ int len_out;
+
+ buf_out = odr_getbuf(out, &len_out, 0);
+
+ do_hex_dump(buf_out, len_out);
+
+ cs_put(conn, buf_out, len_out);
+
+ odr_reset(out);
+ continue;
+ }
+ }
+ else if (res <= 0)
+ {
+ printf("Target closed connection\n");
+ close_session();
+ break;
+ }
+#if HAVE_GETTIMEOFDAY
+ if (got_tv_end == 0)
+ gettimeofday(&tv_end, 0); /* count first one only */
+ got_tv_end++;
+#endif
+ odr_reset(out);
+ odr_reset(in); /* release APDU from last round */
+ record_last = 0;
+ do_hex_dump(netbuffer, res);
+ odr_setbuf(in, netbuffer, res, 0);
+
+ if (!z_GDU(in, &gdu, 0, 0))
+ {
+ FILE *f = ber_file ? ber_file : stdout;
+ odr_perror(in, "Decoding incoming APDU");
+ fprintf(f, "[Near %ld]\n", (long) odr_offset(in));
+ fprintf(f, "Packet dump:\n---------\n");
+ odr_dumpBER(f, netbuffer, res);
+ fprintf(f, "---------\n");
+ if (apdu_file)
+ {
+ z_GDU(print, &gdu, 0, 0);
+ odr_reset(print);
+ }
+ if (conn && cs_more(conn))
+ continue;
+ break;
+ }
+ if (ber_file)
+ odr_dumpBER(ber_file, netbuffer, res);
+ if (apdu_file && !z_GDU(print, &gdu, 0, 0))
+ {
+ odr_perror(print, "Failed to print incoming APDU");
+ odr_reset(print);
+ continue;
+ }
+ if (gdu->which == Z_GDU_Z3950)
+ {
+ Z_APDU *apdu = gdu->u.z3950;
+ switch(apdu->which)
+ {
+ case Z_APDU_initResponse:
+ process_initResponse(apdu->u.initResponse);
+ break;
+ case Z_APDU_searchResponse:
+ process_searchResponse(apdu->u.searchResponse);
+ break;
+ case Z_APDU_scanResponse:
+ process_scanResponse(apdu->u.scanResponse);
+ break;
+ case Z_APDU_presentResponse:
+ print_refid(apdu->u.presentResponse->referenceId);
+ setno +=
+ *apdu->u.presentResponse->numberOfRecordsReturned;
+ if (apdu->u.presentResponse->records)
+ display_records(apdu->u.presentResponse->records);
+ else
+ printf("No records.\n");
+ printf("nextResultSetPosition = " ODR_INT_PRINTF "\n",
+ *apdu->u.presentResponse->nextResultSetPosition);
+ break;
+ case Z_APDU_sortResponse:
+ process_sortResponse(apdu->u.sortResponse);
+ break;
+ case Z_APDU_extendedServicesResponse:
+ printf("Got extended services response\n");
+ process_ESResponse(apdu->u.extendedServicesResponse);
+ break;
+ case Z_APDU_close:
+ printf("Target has closed the association.\n");
+ process_close(apdu->u.close);
+ break;
+ case Z_APDU_resourceControlRequest:
+ process_resourceControlRequest
+ (apdu->u.resourceControlRequest);
+ break;
+ case Z_APDU_deleteResultSetResponse:
+ process_deleteResultSetResponse(apdu->u.
+ deleteResultSetResponse);
+ break;
+ default:
+ printf("Received unknown APDU type (%d).\n",
+ apdu->which);
+ close_session();
+ }
+ }
+#if YAZ_HAVE_XML2
+ else if (gdu->which == Z_GDU_HTTP_Response)
+ {
+ http_response(gdu->u.HTTP_Response);
+ }
+#endif
+ if (one_response_only)
+ break;
+ if (conn && !cs_more(conn))
+ break;