+ printf ("using ILL-request\n");
+ r->u.itemOrder->u.esRequest->notToKeep->itemRequest =
+ create_external_ILL_APDU(ILL_APDU_ILL_Request);
+ }
+ else if (!strcmp(type, "xml") || !strcmp(type, "3"))
+ {
+ const char *xml_buf =
+ "<itemorder>\n"
+ " <type>request</type>\n"
+ " <libraryNo>000200</libraryNo>\n"
+ " <borrowerTicketNo> 1212 </borrowerTicketNo>\n"
+ "</itemorder>";
+ r->u.itemOrder->u.esRequest->notToKeep->itemRequest =
+ z_ext_record (out, VAL_TEXT_XML, xml_buf, strlen(xml_buf));
+ }
+ else
+ r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0;
+
+ return r;
+}
+
+static int send_itemorder(const char *type, int itemno)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest);
+ Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
+ oident ItemOrderRequest;
+
+ ItemOrderRequest.proto = PROTO_Z3950;
+ ItemOrderRequest.oclass = CLASS_EXTSERV;
+ ItemOrderRequest.value = VAL_ITEMORDER;
+ req->packageType = odr_oiddup(out,oid_getoidbyent(&ItemOrderRequest));
+ req->packageName = esPackageName;
+
+ req->taskSpecificParameters = create_ItemOrderExternal(type, itemno);
+
+ send_apdu(apdu);
+ return 0;
+}
+
+static int only_z3950()
+{
+ if (protocol == PROTO_HTTP)
+ {
+ printf ("Not supported by SRW\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int cmd_update(const char *arg)
+{
+ Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
+ Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
+ Z_External *r;
+ int oid[OID_SIZE];
+ Z_IUOriginPartToKeep *toKeep;
+ Z_IUSuppliedRecords *notToKeep;
+ oident update_oid;
+ char action[20], recid[20], fname[80];
+ int action_no;
+ Z_External *record_this = 0;
+
+ if (only_z3950())
+ return 0;
+ *action = 0;
+ *recid = 0;
+ *fname = 0;
+ sscanf (arg, "%19s %19s %79s", action, recid, fname);
+
+ 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 (*fname)
+ {
+ FILE *inf;
+ struct stat status;
+ stat (fname, &status);
+ if (S_ISREG(status.st_mode) && (inf = fopen(fname, "r")))
+ {
+ size_t len = status.st_size;
+ char *buf = (char *) xmalloc (len);
+
+ fread (buf, 1, len, inf);
+
+ fclose (inf);
+
+ record_this = z_ext_record (out, VAL_TEXT_XML, buf, len);
+
+ xfree (buf);
+ }
+ else
+ {
+ printf ("File %s doesn't exist\n", fname);
+ return 0;
+ }
+ }
+ else
+ {
+ if (!record_last)
+ {
+ printf ("No last record (update ignored)\n");
+ return 0;
+ }
+ record_this = record_last;
+ }
+
+ update_oid.proto = PROTO_Z3950;
+ update_oid.oclass = CLASS_EXTSERV;
+ update_oid.value = VAL_DBUPDATE;
+ oid_ent_to_oid (&update_oid, oid);
+ req->packageType = odr_oiddup(out,oid);
+ req->packageName = esPackageName;
+
+ req->referenceId = set_refid (out);
+
+ r = req->taskSpecificParameters = (Z_External *)
+ odr_malloc (out, sizeof(*r));
+ r->direct_reference = odr_oiddup(out,oid);
+ r->indirect_reference = 0;
+ r->descriptor = 0;
+ 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_itemorder(const char *arg)
+{
+ char type[12];
+ int itemno;
+
+ if (only_z3950())
+ return 0;
+ if (sscanf (arg, "%10s %d", type, &itemno) != 2)
+ return 0;
+
+ printf("Item order request\n");
+ fflush(stdout);
+ send_itemorder(type, itemno);
+ return 2;
+}
+
+static int cmd_find(const char *arg)
+{
+ if (!*arg)
+ {
+ printf("Find what?\n");
+ return 0;
+ }
+ if (protocol == PROTO_HTTP)
+ {
+#if HAVE_XML2
+ if (!conn)
+ cmd_open(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 (!conn)
+ {
+ printf("Not connected yet\n");
+ return 0;
+ }
+ 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 (only_z3950())
+ return 0;
+ if (!(largeSetLowerBound = atoi(arg)))
+ return 0;
+ return 1;
+}
+
+static int cmd_mspn(const char *arg)
+{
+ if (only_z3950())
+ return 0;
+ 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)
+ *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;
+ oident prefsyn;
+ int nos = 1;
+ int oid[OID_SIZE];
+ 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;
+ prefsyn.proto = protocol;
+ prefsyn.oclass = CLASS_RECSYN;
+ prefsyn.value = recordsyntax;
+ req->preferredRecordSyntax =
+ odr_oiddup (out, oid_ent_to_oid(&prefsyn, oid));
+
+ if (schema)
+ {
+ oident prefschema;
+
+ prefschema.proto = protocol;
+ prefschema.oclass = CLASS_SCHEMA;
+ prefschema.value = oid_getvalbyname(schema);
+
+ 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;
+ compo.u.complex->generic->schema.oid = (Odr_oid *)
+ odr_oiddup(out, oid_ent_to_oid(&prefschema, oid));
+ if (!compo.u.complex->generic->schema.oid)
+ {
+ /* OID wasn't a schema! Try record syntax instead. */
+ prefschema.oclass = CLASS_RECSYN;
+ compo.u.complex->generic->schema.oid = (Odr_oid *)
+ odr_oiddup(out, oid_ent_to_oid(&prefschema, oid));
+ }
+ 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;
+ 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 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 (schema)
+ sr->u.request->recordSchema = schema;
+ return send_srw(sr);
+}
+#endif
+
+static void close_session (void)
+{
+ cs_close (conn);
+ conn = 0;
+ if (session_mem)
+ {
+ nmem_destroy (session_mem);
+ session_mem = NULL;
+ }
+ sent_close = 0;
+ odr_reset(out);
+ odr_reset(in);
+ odr_reset(print);
+}
+
+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",