+ return cmd_update_common(arg, 0);
+}
+
+static int cmd_update_Z3950(int version, int action_no, const char *recid,
+ char *rec_buf, int rec_len);
+
+static int cmd_update_SRW(int action_no, const char *recid,
+ char *rec_buf, int rec_len);
+
+static int cmd_update_common(const char *arg, int version)
+{
+ char action[20], recid_buf[20];
+ const char *recid = 0;
+ char *rec_buf;
+ int rec_len;
+ int action_no;
+ int noread = 0;
+
+ *action = 0;
+ *recid_buf = 0;
+ sscanf (arg, "%19s %19s%n", action, recid_buf, &noread);
+ if (noread == 0)
+ {
+ printf("Use: update action recid [fname]\n");
+ printf(" where action is one of insert,replace,delete.update\n");
+ printf(" recid is some record ID. Use none for no ID\n");
+ printf(" fname is file of record to be updated\n");
+ return 0;
+ }
+
+ if (!strcmp (action, "insert"))
+ action_no = Z_IUOriginPartToKeep_recordInsert;
+ else if (!strcmp (action, "replace"))
+ action_no = Z_IUOriginPartToKeep_recordReplace;
+ else if (!strcmp (action, "delete"))
+ action_no = Z_IUOriginPartToKeep_recordDelete;
+ else if (!strcmp (action, "update"))
+ action_no = Z_IUOriginPartToKeep_specialUpdate;
+ else
+ {
+ printf ("Bad action: %s\n", action);
+ printf ("Possible values: insert, replace, delete, update\n");
+ return 0;
+ }
+
+ if (strcmp(recid_buf, "none")) /* none means no record ID */
+ recid = recid_buf;
+
+ arg += noread;
+ if (parse_cmd_doc(&arg, out, &rec_buf, &rec_len, 1) == 0)
+ return 0;
+
+#if YAZ_HAVE_XML2
+ if (protocol == PROTO_HTTP)
+ return cmd_update_SRW(action_no, recid, rec_buf, rec_len);
+#endif
+ return cmd_update_Z3950(version, action_no, recid, rec_buf, rec_len);
+}
+
+#if YAZ_HAVE_XML2
+static int cmd_update_SRW(int action_no, const char *recid,
+ char *rec_buf, int rec_len)
+{
+ if (!conn)
+ cmd_open(0);
+ if (!conn)
+ return 0;
+ else
+ {
+ Z_SRW_PDU *srw = yaz_srw_get(out, Z_SRW_update_request);
+ Z_SRW_updateRequest *sr = srw->u.update_request;
+
+ switch(action_no)
+ {
+ case Z_IUOriginPartToKeep_recordInsert:
+ sr->operation = "info:srw/action/1/create";
+ break;
+ case Z_IUOriginPartToKeep_recordReplace:
+ sr->operation = "info:srw/action/1/replace";
+ break;
+ case Z_IUOriginPartToKeep_recordDelete:
+ sr->operation = "info:srw/action/1/delete";
+ break;
+ }
+ if (rec_buf)
+ {
+ sr->record = yaz_srw_get_record(out);
+ sr->record->recordData_buf = rec_buf;
+ sr->record->recordData_len = rec_len;
+ sr->record->recordSchema = record_schema;
+ }
+ if (recid)
+ sr->recordId = odr_strdup(out, recid);
+ return send_srw(srw);
+ }
+}
+#endif
+
+static int cmd_update_Z3950(int version, int action_no, const char *recid,
+ char *rec_buf, int rec_len)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
+ Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
+ Z_External *r;
+ Z_External *record_this = 0;
+
+ if (rec_buf)
+ record_this = z_ext_record (out, VAL_TEXT_XML, rec_buf, rec_len);
+ else
+ {
+ if (!record_last)
+ {
+ printf ("No last record (update ignored)\n");
+ return 0;
+ }
+ record_this = record_last;
+ }
+
+ req->packageType =
+ yaz_oidval_to_z3950oid(out, CLASS_EXTSERV,
+ version == 0 ? VAL_DBUPDATE0 : VAL_DBUPDATE);
+
+ req->packageName = esPackageName;
+
+ req->referenceId = set_refid (out);
+
+ r = req->taskSpecificParameters = (Z_External *)
+ odr_malloc (out, sizeof(*r));
+ r->direct_reference = req->packageType;
+ r->indirect_reference = 0;
+ r->descriptor = 0;
+ if (version == 0)
+ {
+ Z_IU0OriginPartToKeep *toKeep;
+ Z_IU0SuppliedRecords *notToKeep;
+
+ r->which = Z_External_update0;
+ r->u.update0 = (Z_IU0Update *) odr_malloc(out, sizeof(*r->u.update0));
+ r->u.update0->which = Z_IUUpdate_esRequest;
+ r->u.update0->u.esRequest = (Z_IU0UpdateEsRequest *)
+ odr_malloc(out, sizeof(*r->u.update0->u.esRequest));
+ toKeep = r->u.update0->u.esRequest->toKeep = (Z_IU0OriginPartToKeep *)
+ odr_malloc(out, sizeof(*r->u.update0->u.esRequest->toKeep));
+
+ toKeep->databaseName = databaseNames[0];
+ toKeep->schema = 0;
+ toKeep->elementSetName = 0;
+
+ toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action));
+ *toKeep->action = action_no;
+
+ notToKeep = r->u.update0->u.esRequest->notToKeep = (Z_IU0SuppliedRecords *)
+ odr_malloc(out, sizeof(*r->u.update0->u.esRequest->notToKeep));
+ notToKeep->num = 1;
+ notToKeep->elements = (Z_IU0SuppliedRecords_elem **)
+ odr_malloc(out, sizeof(*notToKeep->elements));
+ notToKeep->elements[0] = (Z_IU0SuppliedRecords_elem *)
+ odr_malloc(out, sizeof(**notToKeep->elements));
+ notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque;
+ if (recid)
+ {
+ notToKeep->elements[0]->u.opaque = (Odr_oct *)
+ odr_malloc (out, sizeof(Odr_oct));
+ notToKeep->elements[0]->u.opaque->buf = (unsigned char *) recid;
+ notToKeep->elements[0]->u.opaque->size = strlen(recid);
+ notToKeep->elements[0]->u.opaque->len = strlen(recid);
+ }
+ else
+ notToKeep->elements[0]->u.opaque = 0;
+ notToKeep->elements[0]->supplementalId = 0;
+ notToKeep->elements[0]->correlationInfo = 0;
+ notToKeep->elements[0]->record = record_this;
+ }
+ else
+ {
+ Z_IUOriginPartToKeep *toKeep;
+ Z_IUSuppliedRecords *notToKeep;
+
+ r->which = Z_External_update;
+ r->u.update = (Z_IUUpdate *) odr_malloc(out, sizeof(*r->u.update));
+ r->u.update->which = Z_IUUpdate_esRequest;
+ r->u.update->u.esRequest = (Z_IUUpdateEsRequest *)
+ odr_malloc(out, sizeof(*r->u.update->u.esRequest));
+ toKeep = r->u.update->u.esRequest->toKeep = (Z_IUOriginPartToKeep *)
+ odr_malloc(out, sizeof(*r->u.update->u.esRequest->toKeep));
+
+ toKeep->databaseName = databaseNames[0];
+ toKeep->schema = 0;
+ toKeep->elementSetName = 0;
+ toKeep->actionQualifier = 0;
+ toKeep->action = (int *) odr_malloc(out, sizeof(*toKeep->action));
+ *toKeep->action = action_no;
+
+ notToKeep = r->u.update->u.esRequest->notToKeep = (Z_IUSuppliedRecords *)
+ odr_malloc(out, sizeof(*r->u.update->u.esRequest->notToKeep));
+ notToKeep->num = 1;
+ notToKeep->elements = (Z_IUSuppliedRecords_elem **)
+ odr_malloc(out, sizeof(*notToKeep->elements));
+ notToKeep->elements[0] = (Z_IUSuppliedRecords_elem *)
+ odr_malloc(out, sizeof(**notToKeep->elements));
+ notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque;
+ if (recid)
+ {
+ notToKeep->elements[0]->u.opaque = (Odr_oct *)
+ odr_malloc (out, sizeof(Odr_oct));
+ notToKeep->elements[0]->u.opaque->buf = (unsigned char *) recid;
+ notToKeep->elements[0]->u.opaque->size = strlen(recid);
+ notToKeep->elements[0]->u.opaque->len = strlen(recid);
+ }
+ else
+ notToKeep->elements[0]->u.opaque = 0;
+ notToKeep->elements[0]->supplementalId = 0;
+ notToKeep->elements[0]->correlationInfo = 0;
+ notToKeep->elements[0]->record = record_this;
+ }
+
+ send_apdu(apdu);
+
+ return 2;
+}
+
+static int cmd_xmles(const char *arg)
+{
+ if (only_z3950())
+ return 1;
+ else
+ {
+ char *asn_buf = 0;
+ int noread = 0;
+ char oid_str[51];
+ int oid_value_xmles = VAL_XMLES;
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest);
+ Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
+
+
+ Z_External *ext = (Z_External *) odr_malloc(out, sizeof(*ext));
+
+ req->referenceId = set_refid (out);
+ req->taskSpecificParameters = ext;
+ ext->indirect_reference = 0;
+ ext->descriptor = 0;
+ ext->which = Z_External_octet;
+ ext->u.single_ASN1_type = (Odr_oct *) odr_malloc (out, sizeof(Odr_oct));
+ sscanf(arg, "%50s%n", oid_str, &noread);
+ if (noread == 0)
+ {
+ printf("Missing OID for xmles\n");
+ return 0;
+ }
+ arg += noread;
+ oid_value_xmles = oid_getvalbyname(oid_str);
+ if (oid_value_xmles == VAL_NONE)
+ {
+ printf("Bad OID: %s\n", oid_str);
+ return 0;
+ }
+
+ if (parse_cmd_doc(&arg, out, &asn_buf,
+ &ext->u.single_ASN1_type->len, 0) == 0)
+ return 0;
+
+ ext->u.single_ASN1_type->buf = (unsigned char *) asn_buf;
+
+ req->packageType = yaz_oidval_to_z3950oid(out, CLASS_EXTSERV,
+ oid_value_xmles);
+
+ ext->direct_reference = yaz_oidval_to_z3950oid(out, CLASS_EXTSERV,
+ oid_value_xmles);
+ send_apdu(apdu);
+
+ return 2;
+ }
+}
+
+static int cmd_itemorder(const char *arg)
+{
+ char type[12];
+ int itemno;
+
+ if (only_z3950())
+ return 1;
+ if (sscanf (arg, "%10s %d", type, &itemno) != 2)
+ return 0;
+
+ printf("Item order request\n");
+ fflush(stdout);
+ send_itemorder(type, itemno);
+ return 2;
+}
+
+static void show_opt(const char *arg, void *clientData)
+{
+ printf ("%s ", arg);
+}
+
+static int cmd_zversion(const char *arg)
+{
+ if (*arg && arg)
+ z3950_version = atoi(arg);
+ else
+ printf ("version is %d\n", z3950_version);
+ return 0;
+}
+
+static int cmd_options(const char *arg)
+{
+ if (*arg)
+ {
+ int r;
+ int pos;
+ r = yaz_init_opt_encode(&z3950_options, arg, &pos);
+ if (r == -1)
+ printf("Unknown option(s) near %s\n", arg+pos);
+ }
+ else
+ {
+ yaz_init_opt_decode(&z3950_options, show_opt, 0);
+ printf ("\n");
+ }
+ return 0;
+}
+
+static int cmd_explain(const char *arg)
+{
+ if (protocol != PROTO_HTTP)
+ return 0;
+#if YAZ_HAVE_XML2
+ if (!conn)
+ cmd_open(0);
+ if (conn)
+ {
+ Z_SRW_PDU *sr = 0;
+
+ setno = 1;
+
+ /* save this for later .. when fetching individual records */
+ sr = yaz_srw_get(out, Z_SRW_explain_request);
+ if (recordsyntax_size > 0 && recordsyntax_list[0] == VAL_TEXT_XML)
+ sr->u.explain_request->recordPacking = "xml";
+ send_srw(sr);
+ return 2;
+ }
+#endif
+ return 0;
+}
+
+static int cmd_init(const char *arg)
+{
+ if (*arg)
+ {
+ strncpy (cur_host, arg, sizeof(cur_host)-1);
+ cur_host[sizeof(cur_host)-1] = 0;
+ }
+ if (only_z3950())
+ return 1;
+ send_initRequest(cur_host);
+ return 2;
+}
+
+static int cmd_sru(const char *arg)
+{
+ if (!*arg)
+ {
+ printf("SRU method is: %s\n", sru_method);
+ }
+ else
+ {
+ if (!yaz_matchstr(arg, "post"))
+ sru_method = "post";
+ else if (!yaz_matchstr(arg, "get"))
+ sru_method = "get";
+ else if (!yaz_matchstr(arg, "soap"))
+ sru_method = "soap";
+ else
+ {
+ printf("Unknown SRU method: %s\n", arg);
+ printf("Specify one of POST, GET, SOAP\n");
+ }
+ }
+ return 0;
+}
+
+static int cmd_find(const char *arg)
+{
+ if (!*arg)
+ {
+ printf("Find what?\n");
+ return 0;
+ }
+ if (protocol == PROTO_HTTP)
+ {
+#if YAZ_HAVE_XML2
+ if (!conn)
+ cmd_open(0);
+ if (!conn)
+ return 0;
+ if (!send_SRW_searchRequest(arg))
+ return 0;
+#else
+ return 0;
+#endif
+ }
+ else
+ {
+ if (!conn)
+ {
+ try_reconnect();
+
+ if (!conn) {
+ printf("Not connected yet\n");
+ return 0;
+ }
+ }
+ if (!send_searchRequest(arg))
+ return 0;
+ }
+ return 2;
+}
+
+static int cmd_delete(const char *arg)
+{
+ if (only_z3950())
+ return 0;
+ if (!send_deleteResultSetRequest(arg))
+ return 0;
+ return 2;
+}
+
+static int cmd_ssub(const char *arg)
+{
+ if (!(smallSetUpperBound = atoi(arg)))
+ return 0;
+ return 1;
+}
+
+static int cmd_lslb(const char *arg)
+{
+ if (!(largeSetLowerBound = atoi(arg)))
+ return 0;
+ return 1;
+}
+
+static int cmd_mspn(const char *arg)
+{
+ if (!(mediumSetPresentNumber = atoi(arg)))
+ return 0;
+ return 1;
+}
+
+static int cmd_status(const char *arg)
+{
+ printf("smallSetUpperBound: %d\n", smallSetUpperBound);
+ printf("largeSetLowerBound: %d\n", largeSetLowerBound);
+ printf("mediumSetPresentNumber: %d\n", mediumSetPresentNumber);
+ return 1;
+}
+
+static int cmd_setnames(const char *arg)
+{
+ if (*arg == '1') /* enable ? */
+ setnumber = 0;
+ else if (*arg == '0') /* disable ? */
+ setnumber = -1;
+ else if (setnumber < 0) /* no args, toggle .. */
+ setnumber = 0;
+ else
+ setnumber = -1;
+
+ if (setnumber >= 0)
+ printf("Set numbering enabled.\n");
+ else
+ printf("Set numbering disabled.\n");
+ return 1;
+}
+
+/* PRESENT SERVICE ----------------------------- */
+
+static void parse_show_args(const char *arg_c, char *setstring,
+ int *start, int *number)
+{
+ char arg[40];
+ char *p;
+
+ strncpy(arg, arg_c, sizeof(arg)-1);
+ arg[sizeof(arg)-1] = '\0';
+
+ if ((p = strchr(arg, '+')))
+ {
+ *number = atoi(p + 1);
+ *p = '\0';
+ }
+ if (*arg)
+ {
+ if (!strcmp(arg, "all"))
+ {
+ *number = last_hit_count;
+ *start = 1;
+ }
+ else
+ *start = atoi(arg);
+ }
+ if (p && (p=strchr(p+1, '+')))
+ strcpy (setstring, p+1);
+ else if (setnumber >= 0)
+ sprintf(setstring, "%d", setnumber);
+ else
+ *setstring = '\0';
+}
+
+static int send_presentRequest(const char *arg)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_presentRequest);
+ Z_PresentRequest *req = apdu->u.presentRequest;
+ Z_RecordComposition compo;
+ int nos = 1;
+ char setstring[100];
+
+ req->referenceId = set_refid (out);
+
+ parse_show_args(arg, setstring, &setno, &nos);
+ if (*setstring)
+ req->resultSetId = setstring;
+
+ req->resultSetStartPoint = &setno;
+ req->numberOfRecordsRequested = &nos;
+
+ if (recordsyntax_size == 1)
+ req->preferredRecordSyntax =
+ yaz_oidval_to_z3950oid(out, CLASS_RECSYN, recordsyntax_list[0]);
+
+ if (record_schema || recordsyntax_size >= 2)
+ {
+ req->recordComposition = &compo;
+ compo.which = Z_RecordComp_complex;
+ compo.u.complex = (Z_CompSpec *)
+ odr_malloc(out, sizeof(*compo.u.complex));
+ compo.u.complex->selectAlternativeSyntax = (bool_t *)
+ odr_malloc(out, sizeof(bool_t));
+ *compo.u.complex->selectAlternativeSyntax = 0;
+
+ compo.u.complex->generic = (Z_Specification *)
+ odr_malloc(out, sizeof(*compo.u.complex->generic));
+
+ compo.u.complex->generic->which = Z_Schema_oid;
+ if (!record_schema)
+ compo.u.complex->generic->schema.oid = 0;
+ else
+ {
+ compo.u.complex->generic->schema.oid =
+ yaz_str_to_z3950oid(out, CLASS_SCHEMA, record_schema);
+
+ if (!compo.u.complex->generic->schema.oid)
+ {
+ /* OID wasn't a schema! Try record syntax instead. */
+ compo.u.complex->generic->schema.oid = (Odr_oid *)
+ yaz_str_to_z3950oid(out, CLASS_RECSYN, record_schema);
+ }
+ }
+ if (!elementSetNames)
+ compo.u.complex->generic->elementSpec = 0;
+ else
+ {
+ compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
+ odr_malloc(out, sizeof(Z_ElementSpec));
+ compo.u.complex->generic->elementSpec->which =
+ Z_ElementSpec_elementSetName;
+ compo.u.complex->generic->elementSpec->u.elementSetName =
+ elementSetNames->u.generic;
+ }
+ compo.u.complex->num_dbSpecific = 0;
+ compo.u.complex->dbSpecific = 0;
+ if (recordsyntax_size >= 2)
+ {
+ int i;
+ compo.u.complex->num_recordSyntax = recordsyntax_size;
+ compo.u.complex->recordSyntax = (Odr_oid **)
+ odr_malloc(out, recordsyntax_size * sizeof(Odr_oid*));
+ for (i = 0; i < recordsyntax_size; i++)
+ compo.u.complex->recordSyntax[i] =
+ yaz_oidval_to_z3950oid(out, CLASS_RECSYN,
+ recordsyntax_list[i]);
+ }
+ else
+ {
+ compo.u.complex->num_recordSyntax = 0;
+ compo.u.complex->recordSyntax = 0;
+ }
+ }
+ else if (elementSetNames)
+ {
+ req->recordComposition = &compo;
+ compo.which = Z_RecordComp_simple;
+ compo.u.simple = elementSetNames;
+ }
+ send_apdu(apdu);
+ printf("Sent presentRequest (%d+%d).\n", setno, nos);
+ return 2;
+}
+
+#if YAZ_HAVE_XML2
+static int send_SRW_presentRequest(const char *arg)
+{
+ char setstring[100];
+ int nos = 1;
+ Z_SRW_PDU *sr = srw_sr;
+
+ if (!sr)
+ return 0;
+ parse_show_args(arg, setstring, &setno, &nos);
+ sr->u.request->startRecord = odr_intdup(out, setno);
+ sr->u.request->maximumRecords = odr_intdup(out, nos);
+ if (record_schema)
+ sr->u.request->recordSchema = record_schema;
+ if (recordsyntax_size == 1 && recordsyntax_list[0] == VAL_TEXT_XML)
+ sr->u.request->recordPacking = "xml";
+ return send_srw(sr);
+}
+#endif
+
+static void close_session (void)
+{
+ if (conn)
+ cs_close (conn);
+ conn = 0;
+ sent_close = 0;
+ odr_reset(out);
+ odr_reset(in);
+ odr_reset(print);
+ last_hit_count = 0;
+}
+
+void process_close(Z_Close *req)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_close);
+ Z_Close *res = apdu->u.close;
+
+ static char *reasons[] =
+ {
+ "finished",
+ "shutdown",
+ "system problem",
+ "cost limit reached",
+ "resources",
+ "security violation",
+ "protocolError",
+ "lack of activity",
+ "peer abort",
+ "unspecified"
+ };
+
+ printf("Reason: %s, message: %s\n", reasons[*req->closeReason],
+ req->diagnosticInformation ? req->diagnosticInformation : "NULL");
+ if (sent_close)
+ close_session ();
+ else
+ {
+ *res->closeReason = Z_Close_finished;
+ send_apdu(apdu);
+ printf("Sent response.\n");
+ sent_close = 1;
+ }
+}
+
+static int cmd_show(const char *arg)
+{
+ if (protocol == PROTO_HTTP)
+ {
+#if YAZ_HAVE_XML2
+ if (!conn)
+ cmd_open(0);
+ if (!conn)
+ return 0;
+ if (!send_SRW_presentRequest(arg))
+ return 0;
+#else
+ return 0;
+#endif
+ }
+ else
+ {
+ if (!conn)
+ {
+ printf("Not connected yet\n");
+ return 0;
+ }
+ if (!send_presentRequest(arg))
+ return 0;
+ }
+ return 2;
+}
+
+void exit_client(int code)
+{
+ file_history_save(file_history);
+ file_history_destroy(&file_history);
+ exit(code);
+}
+
+int cmd_quit(const char *arg)
+{
+ printf("See you later, alligator.\n");
+ xmalloc_trav ("");
+ exit_client(0);
+ return 0;
+}
+
+int cmd_cancel(const char *arg)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_triggerResourceControlRequest);
+ Z_TriggerResourceControlRequest *req =
+ apdu->u.triggerResourceControlRequest;
+ bool_t rfalse = 0;
+ char command[16];
+
+ *command = '\0';
+ sscanf(arg, "%15s", command);
+
+ if (only_z3950())
+ return 0;
+ if (session_initResponse &&
+ !ODR_MASK_GET(session_initResponse->options,
+ Z_Options_triggerResourceCtrl))
+ {
+ printf("Target doesn't support cancel (trigger resource ctrl)\n");
+ return 0;
+ }
+ *req->requestedAction = Z_TriggerResourceControlRequest_cancel;
+ req->resultSetWanted = &rfalse;
+ req->referenceId = set_refid (out);
+
+ send_apdu(apdu);
+ printf("Sent cancel request\n");
+ if (!strcmp(command, "wait"))
+ return 2;
+ return 1;
+}
+
+
+int cmd_cancel_find(const char *arg) {
+ int fres;
+ fres=cmd_find(arg);
+ if( fres > 0 ) {
+ return cmd_cancel("");
+ };
+ return fres;
+}
+
+int send_scanrequest(const char *query, int pp, int num, const char *term)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest);
+ Z_ScanRequest *req = apdu->u.scanRequest;
+
+ if (only_z3950())
+ return 0;
+ if (queryType == QueryType_CCL2RPN)
+ {
+ int error, pos;
+ struct ccl_rpn_node *rpn;
+
+ rpn = ccl_find_str (bibset, query, &error, &pos);
+ if (error)
+ {
+ printf("CCL ERROR: %s\n", ccl_err_msg(error));
+ return -1;
+ }
+ req->attributeSet =
+ yaz_oidval_to_z3950oid(out, CLASS_ATTSET, VAL_BIB1);
+ if (!(req->termListAndStartPoint = ccl_scan_query (out, rpn)))
+ {
+ printf("Couldn't convert CCL to Scan term\n");
+ return -1;
+ }
+ ccl_rpn_delete (rpn);
+ }
+ else
+ {
+ YAZ_PQF_Parser pqf_parser = yaz_pqf_create ();
+
+ if (!(req->termListAndStartPoint =
+ yaz_pqf_scan(pqf_parser, out, &req->attributeSet, query)))
+ {
+ const char *pqf_msg;
+ size_t off;
+ int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off);
+ int ioff = off;
+ printf("%*s^\n", ioff+7, "");
+ printf("Prefix query error: %s (code %d)\n", pqf_msg, code);
+ yaz_pqf_destroy (pqf_parser);
+ return -1;
+ }
+ yaz_pqf_destroy (pqf_parser);
+ }
+ if (term && *term)
+ {
+ if (req->termListAndStartPoint->term &&
+ req->termListAndStartPoint->term->which == Z_Term_general &&
+ req->termListAndStartPoint->term->u.general)
+ {
+ req->termListAndStartPoint->term->u.general->buf =
+ (unsigned char *) odr_strdup(out, term);
+ req->termListAndStartPoint->term->u.general->len =
+ req->termListAndStartPoint->term->u.general->size =
+ strlen(term);
+ }
+ }
+ req->referenceId = set_refid (out);
+ req->num_databaseNames = num_databaseNames;
+ req->databaseNames = databaseNames;
+ req->numberOfTermsRequested = #
+ req->preferredPositionInResponse = &pp;
+ req->stepSize = odr_intdup(out, scan_stepSize);
+ send_apdu(apdu);
+ return 2;
+}
+
+int send_sortrequest(const char *arg, int newset)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_sortRequest);
+ Z_SortRequest *req = apdu->u.sortRequest;
+ Z_SortKeySpecList *sksl = (Z_SortKeySpecList *)
+ odr_malloc (out, sizeof(*sksl));
+ char setstring[32];
+
+ if (only_z3950())
+ return 0;
+ if (setnumber >= 0)
+ sprintf (setstring, "%d", setnumber);
+ else
+ sprintf (setstring, "default");
+
+ req->referenceId = set_refid (out);
+
+ req->num_inputResultSetNames = 1;
+ req->inputResultSetNames = (Z_InternationalString **)
+ odr_malloc (out, sizeof(*req->inputResultSetNames));
+ req->inputResultSetNames[0] = odr_strdup (out, setstring);
+
+ if (newset && setnumber >= 0)
+ sprintf (setstring, "%d", ++setnumber);
+
+ req->sortedResultSetName = odr_strdup (out, setstring);
+
+ req->sortSequence = yaz_sort_spec (out, arg);
+ if (!req->sortSequence)
+ {
+ printf ("Missing sort specifications\n");
+ return -1;
+ }
+ send_apdu(apdu);
+ return 2;
+}
+
+void display_term(Z_TermInfo *t)
+{
+ if (t->displayTerm)
+ printf("%s", t->displayTerm);
+ else if (t->term->which == Z_Term_general)
+ {
+ printf("%.*s", t->term->u.general->len, t->term->u.general->buf);
+ sprintf(last_scan_line, "%.*s", t->term->u.general->len,
+ t->term->u.general->buf);
+ }
+ else
+ printf("Term (not general)");
+ if (t->globalOccurrences)
+ printf (" (%d)\n", *t->globalOccurrences);
+ else
+ printf ("\n");
+}
+
+void process_scanResponse(Z_ScanResponse *res)
+{
+ int i;
+ Z_Entry **entries = NULL;
+ int num_entries = 0;
+
+ printf("Received ScanResponse\n");
+ print_refid (res->referenceId);
+ printf("%d entries", *res->numberOfEntriesReturned);
+ if (res->positionOfTerm)
+ printf (", position=%d", *res->positionOfTerm);
+ printf ("\n");
+ if (*res->scanStatus != Z_Scan_success)
+ printf("Scan returned code %d\n", *res->scanStatus);
+ if (!res->entries)
+ return;
+ if ((entries = res->entries->entries))
+ num_entries = res->entries->num_entries;
+ for (i = 0; i < num_entries; i++)
+ {
+ int pos_term = res->positionOfTerm ? *res->positionOfTerm : -1;
+ if (entries[i]->which == Z_Entry_termInfo)
+ {
+ printf("%c ", i + 1 == pos_term ? '*' : ' ');
+ display_term(entries[i]->u.termInfo);
+ }
+ else
+ display_diagrecs(&entries[i]->u.surrogateDiagnostic, 1);
+ }
+ if (res->entries->nonsurrogateDiagnostics)
+ display_diagrecs (res->entries->nonsurrogateDiagnostics,
+ res->entries->num_nonsurrogateDiagnostics);
+}
+
+void process_sortResponse(Z_SortResponse *res)
+{
+ printf("Received SortResponse: status=");
+ switch (*res->sortStatus)
+ {
+ case Z_SortResponse_success:
+ printf ("success"); break;
+ case Z_SortResponse_partial_1:
+ printf ("partial"); break;
+ case Z_SortResponse_failure:
+ printf ("failure"); break;
+ default:
+ printf ("unknown (%d)", *res->sortStatus);
+ }
+ printf ("\n");
+ print_refid (res->referenceId);
+ if (res->diagnostics)
+ display_diagrecs(res->diagnostics,
+ res->num_diagnostics);
+}
+
+void process_deleteResultSetResponse (Z_DeleteResultSetResponse *res)
+{
+ printf("Got deleteResultSetResponse status=%d\n",
+ *res->deleteOperationStatus);
+ if (res->deleteListStatuses)
+ {
+ int i;
+ for (i = 0; i < res->deleteListStatuses->num; i++)
+ {
+ printf ("%s status=%d\n", res->deleteListStatuses->elements[i]->id,
+ *res->deleteListStatuses->elements[i]->status);
+ }
+ }
+}
+
+int cmd_sort_generic(const char *arg, int newset)
+{
+ if (only_z3950())
+ return 0;
+ if (session_initResponse &&
+ !ODR_MASK_GET(session_initResponse->options, Z_Options_sort))
+ {
+ printf("Target doesn't support sort\n");
+ return 0;
+ }
+ if (*arg)
+ {
+ if (send_sortrequest(arg, newset) < 0)
+ return 0;
+ return 2;
+ }
+ return 0;
+}
+
+int cmd_sort(const char *arg)
+{
+ return cmd_sort_generic (arg, 0);
+}
+
+int cmd_sort_newset (const char *arg)
+{
+ return cmd_sort_generic (arg, 1);
+}
+
+int cmd_scanstep(const char *arg)
+{
+ scan_stepSize = atoi(arg);
+ return 0;
+}
+
+int cmd_scanpos(const char *arg)
+{
+ int r = sscanf(arg, "%d", &scan_position);
+ if (r == 0)
+ scan_position = 1;
+ return 0;
+}
+
+int cmd_scansize(const char *arg)
+{
+ int r = sscanf(arg, "%d", &scan_size);
+ if (r == 0)
+ scan_size = 20;
+ return 0;
+}
+
+int cmd_scan(const char *arg)
+{
+ if (protocol == PROTO_HTTP)
+ {
+#if YAZ_HAVE_XML2
+ if (!conn)
+ cmd_open(0);
+ if (!conn)
+ return 0;
+ if (*arg)
+ {
+ if (send_SRW_scanRequest(arg, scan_position, scan_size) < 0)
+ return 0;
+ }
+ else
+ {
+ if (send_SRW_scanRequest(last_scan_line, 1, scan_size) < 0)
+ return 0;
+ }
+ return 2;
+#else
+ return 0;
+#endif
+ }
+ else
+ {
+ if (!conn)
+ {
+ try_reconnect();
+
+ if (!conn) {
+ printf("Session not initialized yet\n");
+ return 0;
+ }
+ }
+ if (session_initResponse &&
+ !ODR_MASK_GET(session_initResponse->options, Z_Options_scan))
+ {
+ printf("Target doesn't support scan\n");
+ return 0;
+ }
+ if (*arg)
+ {
+ strcpy (last_scan_query, arg);
+ if (send_scanrequest(arg, scan_position, scan_size, 0) < 0)
+ return 0;
+ }
+ else
+ {
+ if (send_scanrequest(last_scan_query, 1, scan_size, last_scan_line) < 0)
+ return 0;
+ }
+ return 2;
+ }
+}
+
+int cmd_schema(const char *arg)
+{
+ xfree(record_schema);
+ record_schema = 0;
+ if (arg && *arg)
+ record_schema = xstrdup(arg);
+ return 1;
+}
+
+int cmd_format(const char *arg)
+{
+ const char *cp = arg;
+ int nor;
+ int idx = 0;
+ oid_value nsyntax[RECORDSYNTAX_MAX];
+ char form_str[41];
+ if (!arg || !*arg)
+ {
+ printf("Usage: format <recordsyntax>\n");
+ return 0;
+ }
+ while (sscanf(cp, "%40s%n", form_str, &nor) >= 1 && nor > 0
+ && idx < RECORDSYNTAX_MAX)
+ {
+ nsyntax[idx] = oid_getvalbyname(form_str);
+ if (!strcmp(form_str, "none"))
+ break;
+ if (nsyntax[idx] == VAL_NONE)
+ {
+ printf ("unknown record syntax: %s\n", form_str);
+ return 0;
+ }
+ cp += nor;
+ idx++;
+ }
+ recordsyntax_size = idx;
+ memcpy(recordsyntax_list, nsyntax, idx * sizeof(*nsyntax));
+ return 1;
+}
+
+int cmd_elements(const char *arg)
+{
+ static Z_ElementSetNames esn;
+ static char what[100];
+
+ if (!arg || !*arg)
+ {
+ elementSetNames = 0;
+ return 1;
+ }
+ strcpy(what, arg);
+ esn.which = Z_ElementSetNames_generic;
+ esn.u.generic = what;
+ elementSetNames = &esn;
+ return 1;
+}
+
+int cmd_attributeset(const char *arg)
+{
+ char what[100];