X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=9f24bd4c38ee4c3daa6ccd6a0bb3d1793aa4509c;hp=3189faf78d17b85850c3aa969706356176ab67fa;hb=53c17d9dc2f7c8355bbac800ed02862eb5780d4f;hpb=42d3d8a6486c495357574e5db0fc736834d8ba40 diff --git a/client/client.c b/client/client.c index 3189faf..9f24bd4 100644 --- a/client/client.c +++ b/client/client.c @@ -4,7 +4,49 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: client.c,v $ - * Revision 1.14 1995-06-19 12:37:41 quinn + * Revision 1.28 1995-12-14 11:09:31 quinn + * Added Explain record syntax to the format command. + * + * Revision 1.27 1995/12/12 16:37:02 quinn + * Added destroy element to data1_node. + * + * Revision 1.26 1995/12/12 14:11:00 quinn + * Minimal. + * + * Revision 1.25 1995/11/13 09:27:22 quinn + * Fiddling with the variant stuff. + * + * Revision 1.24 1995/10/30 12:41:13 quinn + * Added hostname lookup for server. + * + * Revision 1.23 1995/10/18 16:12:30 quinn + * Better diagnostics. + * + * Revision 1.22 1995/10/11 14:49:12 quinn + * Smallish. + * + * Revision 1.21 1995/09/29 17:01:47 quinn + * More Windows work + * + * Revision 1.20 1995/08/29 14:24:13 quinn + * Added second half of close-handshake + * + * Revision 1.19 1995/08/29 11:17:28 quinn + * Added code to receive close + * + * Revision 1.18 1995/08/28 12:21:27 quinn + * Client can now ask for simple element set names. + * + * Revision 1.17 1995/08/17 12:45:02 quinn + * Fixed minor problems with GRS-1. Added support in c&s. + * + * Revision 1.16 1995/08/15 12:00:04 quinn + * Updated External + * + * Revision 1.15 1995/06/22 09:28:03 quinn + * Fixed bug in SUTRS processing. + * + * Revision 1.14 1995/06/19 12:37:41 quinn * Added BER dumper. * * Revision 1.13 1995/06/16 10:29:11 quinn @@ -56,7 +98,11 @@ #include #include +#ifdef WINDOWS +#include +#else #include +#endif #include #ifdef _AIX #include @@ -90,9 +136,11 @@ static int setnumber = 0; /* current result set number */ static int smallSetUpperBound = 0; static int largeSetLowerBound = 1; static int mediumSetPresentNumber = 0; +static Z_ElementSetNames *elementSetNames = 0; static int setno = 1; /* current set offset */ static int protocol = PROTO_Z3950; /* current app protocol */ static int recordsyntax = VAL_USMARC; +static int sent_close = 0; static ODR_MEM session_mem; /* memory handle for init-response */ static Z_InitResponse *session = 0; /* session parameters */ static char last_scan[512] = "0"; @@ -110,15 +158,15 @@ static void send_apdu(Z_APDU *a) if (!z_APDU(out, &a, 0)) { - odr_perror(out, "Encoding APDU"); - exit(1); + odr_perror(out, "Encoding APDU"); + exit(1); } buf = odr_getbuf(out, &len, 0); odr_reset(out); /* release the APDU */ if (cs_put(conn, buf, len) < 0) { - fprintf(stderr, "cs_put: %s", cs_errlist[cs_errno(conn)]); - exit(1); + fprintf(stderr, "cs_put: %s", cs_errmsg(cs_errno(conn))); + exit(1); } } @@ -137,6 +185,9 @@ static void send_initRequest() ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1); ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2); + ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3); + + *req->maximumRecordSize = 1024*1024; req->idAuthentication = auth; @@ -151,29 +202,29 @@ static int process_initResponse(Z_InitResponse *res) session = res; if (!*res->result) - printf("Connection rejected by target.\n"); + printf("Connection rejected by target.\n"); else - printf("Connection accepted by target.\n"); + printf("Connection accepted by target.\n"); if (res->implementationId) - printf("ID : %s\n", res->implementationId); + printf("ID : %s\n", res->implementationId); if (res->implementationName) - printf("Name : %s\n", res->implementationName); + printf("Name : %s\n", res->implementationName); if (res->implementationVersion) - printf("Version: %s\n", res->implementationVersion); + printf("Version: %s\n", res->implementationVersion); if (res->userInformationField) { - printf("UserInformationfield:\n"); - if (!odr_external(print, (Odr_external**)&res-> userInformationField, - 0)) - { - odr_perror(print, "Printing userinfo\n"); - odr_reset(print); - } - if (res->userInformationField->which == ODR_EXTERNAL_octet) - { - printf("Guessing visiblestring:\n"); - printf("'%s'\n", res->userInformationField->u. octet_aligned->buf); - } + printf("UserInformationfield:\n"); + if (!z_External(print, (Z_External**)&res-> userInformationField, + 0)) + { + odr_perror(print, "Printing userinfo\n"); + odr_reset(print); + } + if (res->userInformationField->which == Z_External_octet) + { + printf("Guessing visiblestring:\n"); + printf("'%s'\n", res->userInformationField->u. octet_aligned->buf); + } } return 0; } @@ -186,55 +237,55 @@ int cmd_open(char *arg) if (conn) { - printf("Already connected.\n"); - return 0; + printf("Already connected.\n"); + return 0; } if (!*arg || sscanf(arg, "%[^:]:%s", type, addr) < 2) { - fprintf(stderr, "Usage: open (osi|tcp) ':' [tsel '/']host[':'port]\n"); - return 0; + fprintf(stderr, "Usage: open (osi|tcp) ':' [tsel '/']host[':'port]\n"); + return 0; } #ifdef USE_XTIMOSI if (!strcmp(type, "osi")) { - if (!(add = mosi_strtoaddr(addr))) - { - perror(arg); - return 0; - } - t = mosi_type; - protocol = PROTO_SR; + if (!(add = mosi_strtoaddr(addr))) + { + perror(arg); + return 0; + } + t = mosi_type; + protocol = PROTO_SR; } else #endif if (!strcmp(type, "tcp")) { - if (!(add = tcpip_strtoaddr(addr))) - { - perror(arg); - return 0; - } - t = tcpip_type; - protocol = PROTO_Z3950; + if (!(add = tcpip_strtoaddr(addr))) + { + perror(arg); + return 0; + } + t = tcpip_type; + protocol = PROTO_Z3950; } else { - fprintf(stderr, "Bad type: %s\n", type); - return 0; + fprintf(stderr, "Bad type: %s\n", type); + return 0; } if (!(conn = cs_create(t, 1, protocol))) { - perror("cs_create"); - return 0; + perror("cs_create"); + return 0; } printf("Connecting..."); fflush(stdout); if (cs_connect(conn, add) < 0) { - perror("connect"); - cs_close(conn); - conn = 0; - return 0; + perror("connect"); + cs_close(conn); + conn = 0; + return 0; } printf("Ok.\n"); send_initRequest(); @@ -248,9 +299,9 @@ int cmd_authentication(char *arg) if (!*arg) { - printf("Auth field set to null\n"); - auth = 0; - return 1; + printf("Auth field set to null\n"); + auth = 0; + return 1; } auth = &au; au.which = Z_IdAuthentication_open; @@ -261,44 +312,119 @@ int cmd_authentication(char *arg) /* SEARCH SERVICE ------------------------------ */ -void display_record(Z_DatabaseRecord *p) +static void display_variant(Z_Variant *v, int level) { - Odr_external *r = (Odr_external*) p; + int i; + + for (i = 0; i < v->num_triples; i++) + { + printf("%*sclass=%d,type=%d", level * 4, "", *v->triples[i]->class, + *v->triples[i]->type); + if (v->triples[i]->which == Z_Triple_internationalString) + printf(",value=%s\n", v->triples[i]->value.internationalString); + else + printf("\n"); + } +} + +static void display_grs1(Z_GenericRecord *r, int level) +{ + int i; + + if (!r) + return; + for (i = 0; i < r->num_elements; i++) + { + Z_TaggedElement *t; + + printf("%*s", level * 4, ""); + t = r->elements[i]; + printf("("); + if (t->tagType) + printf("%d,", *t->tagType); + else + printf("?,"); + if (t->tagValue->which == Z_StringOrNumeric_numeric) + printf("%d) ", *t->tagValue->u.numeric); + else + printf("%s) ", t->tagValue->u.string); + if (t->content->which == Z_ElementData_subtree) + { + printf("\n"); + display_grs1(t->content->u.subtree, level+1); + } + else if (t->content->which == Z_ElementData_string) + printf("%s\n", t->content->u.string); + else if (t->content->which == Z_ElementData_numeric) + printf("%d\n", *t->content->u.numeric); + else if (t->content->which == Z_ElementData_noDataRequested) + printf("[No data requested]\n"); + else if (t->content->which == Z_ElementData_elementEmpty) + printf("[Element empty]\n"); + else if (t->content->which == Z_ElementData_elementNotThere) + printf("[Element not there]\n"); + else + printf("??????\n"); + if (t->appliedVariant) + display_variant(t->appliedVariant, level+1); + if (t->metaData && t->metaData->supportedVariants) + { + int c; + + printf("%*s---- variant list\n", (level+1)*4, ""); + for (c = 0; c < t->metaData->num_supportedVariants; c++) + { + printf("%*svariant #%d\n", (level+1)*4, "", c); + display_variant(t->metaData->supportedVariants[c], level + 2); + } + } + } +} + +static void display_record(Z_DatabaseRecord *p) +{ + Z_External *r = (Z_External*) p; oident *ent = oid_getentbyoid(r->direct_reference); if (r->direct_reference) { - printf("Record type: "); - if (ent) - printf("%s\n", ent->desc); - else if (!odr_oid(print, &r->direct_reference, 0)) - { - odr_perror(print, "print oid"); - odr_reset(print); - } + printf("Record type: "); + if (ent) + printf("%s\n", ent->desc); + else if (!odr_oid(print, &r->direct_reference, 0)) + { + odr_perror(print, "print oid"); + odr_reset(print); + } } - if (r->which == ODR_EXTERNAL_octet && p->u.octet_aligned->len) - marc_display ((char*)p->u.octet_aligned->buf, stdout); + if (r->which == Z_External_octet && p->u.octet_aligned->len) + marc_display ((char*)p->u.octet_aligned->buf, stdout); else if (ent->value == VAL_SUTRS) { - Odr_oct *rc; - - if (!z_SUTRS(in, &rc, 0)) - { - odr_perror(in, "decoding SUTRS"); - odr_reset(in); - } - else - printf("%.*s", rc->len, rc->buf); + if (r->which != Z_External_sutrs) + { + printf("Expecting single SUTRS type for SUTRS.\n"); + return; + } + printf("%.*s", r->u.sutrs->len, r->u.sutrs->buf); + } + else if (ent->value == VAL_GRS1) + { + if (r->which != Z_External_grs1) + { + printf("Expecting single GRS type for GRS.\n"); + return; + } + display_grs1(r->u.grs1, 0); } else { - printf("Unknown record representation.\n"); - if (!odr_external(print, &r, 0)) - { - odr_perror(print, "Printing external"); - odr_reset(print); - } + printf("Unknown record representation.\n"); + if (!z_External(print, &r, 0)) + { + odr_perror(print, "Printing external"); + odr_reset(print); + } } } @@ -315,30 +441,30 @@ static void display_diagrec(Z_DiagRec *p) #ifdef Z_95 if (p->which != Z_DiagRec_defaultFormat) { - printf("Diagnostic record not in default format.\n"); - return; + printf("Diagnostic record not in default format.\n"); + return; } else - r = p->u.defaultFormat; + r = p->u.defaultFormat; #endif if (!(ent = oid_getentbyoid(r->diagnosticSetId)) || - ent->class != CLASS_DIAGSET || ent->value != VAL_BIB1) - printf("Missing or unknown diagset\n"); + ent->class != CLASS_DIAGSET || ent->value != VAL_BIB1) + printf("Missing or unknown diagset\n"); printf(" [%d] %s", *r->condition, diagbib1_str(*r->condition)); if (r->addinfo && *r->addinfo) - printf(" -- %s\n", r->addinfo); + printf(" -- %s\n", r->addinfo); else - printf("\n"); + printf("\n"); } static void display_nameplusrecord(Z_NamePlusRecord *p) { if (p->databaseName) - printf("[%s]", p->databaseName); + printf("[%s]", p->databaseName); if (p->which == Z_NamePlusRecord_surrogateDiagnostic) - display_diagrec(p->u.surrogateDiagnostic); + display_diagrec(p->u.surrogateDiagnostic); else - display_record(p->u.databaseRecord); + display_record(p->u.databaseRecord); } static void display_records(Z_Records *p) @@ -346,12 +472,12 @@ static void display_records(Z_Records *p) int i; if (p->which == Z_Records_NSD) - display_diagrec(p->u.nonSurrogateDiagnostic); + display_diagrec(p->u.nonSurrogateDiagnostic); else { - printf("Records: %d\n", p->u.databaseOrSurDiagnostics->num_records); - for (i = 0; i < p->u.databaseOrSurDiagnostics->num_records; i++) - display_nameplusrecord(p->u.databaseOrSurDiagnostics->records[i]); + printf("Records: %d\n", p->u.databaseOrSurDiagnostics->num_records); + for (i = 0; i < p->u.databaseOrSurDiagnostics->num_records; i++) + display_nameplusrecord(p->u.databaseOrSurDiagnostics->records[i]); } } @@ -380,41 +506,43 @@ static int send_searchRequest(char *arg) rpn = ccl_find_str(bibset, arg, &error, &pos); if (error) { - printf("CCL ERROR: %s\n", ccl_err_msg(error)); - return 0; + printf("CCL ERROR: %s\n", ccl_err_msg(error)); + return 0; } #endif #endif if (!strcmp(arg, "@big")) /* strictly for troublemaking */ { - static unsigned char big[2100]; - static Odr_oct bigo; - - /* send a very big referenceid to test transport stack etc. */ - memset(big, 'A', 2100); - bigo.len = bigo.size = 2100; - bigo.buf = big; - req->referenceId = &bigo; + static unsigned char big[2100]; + static Odr_oct bigo; + + /* send a very big referenceid to test transport stack etc. */ + memset(big, 'A', 2100); + bigo.len = bigo.size = 2100; + bigo.buf = big; + req->referenceId = &bigo; } if (setnumber >= 0) { - sprintf(setstring, "%d", ++setnumber); - req->resultSetName = setstring; + sprintf(setstring, "%d", ++setnumber); + req->resultSetName = setstring; } *req->smallSetUpperBound = smallSetUpperBound; *req->largeSetLowerBound = largeSetLowerBound; *req->mediumSetPresentNumber = mediumSetPresentNumber; if (smallSetUpperBound > 0 || (largeSetLowerBound > 1 && - mediumSetPresentNumber > 0)) + mediumSetPresentNumber > 0)) { - oident prefsyn; - - prefsyn.proto = protocol; - prefsyn.class = CLASS_RECSYN; - prefsyn.value = recordsyntax; - req->preferredRecordSyntax = odr_oiddup(out, oid_getoidbyent(&prefsyn)); + oident prefsyn; + + prefsyn.proto = protocol; + prefsyn.class = CLASS_RECSYN; + prefsyn.value = recordsyntax; + req->preferredRecordSyntax = odr_oiddup(out, oid_getoidbyent(&prefsyn)); + req->smallSetElementSetNames = + req->mediumSetElementSetNames = elementSetNames; } req->num_databaseNames = 1; req->databaseNames = &databaseNames; @@ -455,16 +583,16 @@ static int send_searchRequest(char *arg) static int process_searchResponse(Z_SearchResponse *res) { if (*res->searchStatus) - printf("Search was a success.\n"); + printf("Search was a success.\n"); else - printf("Search was a bloomin' failure.\n"); + printf("Search was a bloomin' failure.\n"); printf("Number of hits: %d, setno %d\n", - *res->resultCount, setnumber); + *res->resultCount, setnumber); printf("records returned: %d\n", - *res->numberOfRecordsReturned); + *res->numberOfRecordsReturned); setno += *res->numberOfRecordsReturned; if (res->records) - display_records(res->records); + display_records(res->records); return 0; } @@ -472,37 +600,37 @@ static int cmd_find(char *arg) { if (!*arg) { - printf("Find what?\n"); - return 0; + printf("Find what?\n"); + return 0; } if (!conn) { - printf("Not connected yet\n"); - return 0; + printf("Not connected yet\n"); + return 0; } if (!send_searchRequest(arg)) - return 0; + return 0; return 2; } static int cmd_ssub(char *arg) { if (!(smallSetUpperBound = atoi(arg))) - return 0; + return 0; return 1; } static int cmd_lslb(char *arg) { if (!(largeSetLowerBound = atoi(arg))) - return 0; + return 0; return 1; } static int cmd_mspn(char *arg) { if (!(mediumSetPresentNumber = atoi(arg))) - return 0; + return 0; return 1; } @@ -518,8 +646,8 @@ static int cmd_base(char *arg) { if (!*arg) { - printf("Usage: base \n"); - return 0; + printf("Usage: base \n"); + return 0; } strcpy(database, arg); return 1; @@ -529,13 +657,13 @@ static int cmd_setnames(char *arg) { if (setnumber < 0) { - printf("Set numbering enabled.\n"); - setnumber = 0; + printf("Set numbering enabled.\n"); + setnumber = 0; } else { - printf("Set numbering disabled.\n"); - setnumber = -1; + printf("Set numbering disabled.\n"); + setnumber = -1; } return 1; } @@ -546,6 +674,7 @@ static int send_presentRequest(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; char *p; @@ -553,16 +682,16 @@ static int send_presentRequest(char *arg) if ((p = strchr(arg, '+'))) { - nos = atoi(p + 1); - *p = 0; + nos = atoi(p + 1); + *p = 0; } if (*arg) - setno = atoi(arg); + setno = atoi(arg); if (setnumber >= 0) { - sprintf(setstring, "%d", setnumber); - req->resultSetId = setstring; + sprintf(setstring, "%d", setnumber); + req->resultSetId = setstring; } req->resultSetStartPoint = &setno; req->numberOfRecordsRequested = &nos; @@ -570,15 +699,53 @@ static int send_presentRequest(char *arg) prefsyn.class = CLASS_RECSYN; prefsyn.value = recordsyntax; req->preferredRecordSyntax = oid_getoidbyent(&prefsyn); + 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; } +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) + { + printf("Goodbye.\n"); + exit(0); + } + *res->closeReason = Z_Close_finished; + send_apdu(apdu); + printf("Sent response.\n"); + sent_close = 1; +} + static int cmd_show(char *arg) { if (!send_presentRequest(arg)) - return 0; + return 0; return 2; } @@ -592,18 +759,18 @@ int cmd_cancel(char *arg) { Z_APDU *apdu = zget_APDU(out, Z_APDU_triggerResourceControlRequest); Z_TriggerResourceControlRequest *req = - apdu->u.triggerResourceControlRequest; + apdu->u.triggerResourceControlRequest; bool_t false = 0; if (!session) { - printf("Session not initialized yet\n"); - return 0; + printf("Session not initialized yet\n"); + return 0; } if (!ODR_MASK_GET(session->options, Z_Options_triggerResourceCtrl)) { - printf("Target doesn't support cancel (trigger resource ctrl)\n"); - return 0; + printf("Target doesn't support cancel (trigger resource ctrl)\n"); + return 0; } *req->requestedAction = Z_TriggerResourceCtrl_cancel; req->resultSetWanted = &false; @@ -637,13 +804,13 @@ void display_term(Z_TermInfo *t) { if (t->term->which == Z_Term_general) { - printf("%.*s (%d)\n", t->term->u.general->len, t->term->u.general->buf, - t->globalOccurrences ? *t->globalOccurrences : -1); - sprintf(last_scan, "%.*s", t->term->u.general->len, - t->term->u.general->buf); + printf("%.*s (%d)\n", t->term->u.general->len, t->term->u.general->buf, + t->globalOccurrences ? *t->globalOccurrences : -1); + sprintf(last_scan, "%.*s", t->term->u.general->len, + t->term->u.general->buf); } else - printf("Term type not general.\n"); + printf("Term type not general.\n"); } void process_scanResponse(Z_ScanResponse *res) @@ -651,48 +818,48 @@ void process_scanResponse(Z_ScanResponse *res) int i; printf("SCAN: %d entries, position=%d\n", *res->numberOfEntriesReturned, - *res->positionOfTerm); + *res->positionOfTerm); if (*res->scanStatus != Z_Scan_success) - printf("Scan returned code %d\n", *res->scanStatus); + printf("Scan returned code %d\n", *res->scanStatus); if (!res->entries) - return; + return; if (res->entries->which == Z_ListEntries_entries) { - Z_Entries *ent = res->entries->u.entries; - - for (i = 0; i < ent->num_entries; i++) - if (ent->entries[i]->which == Z_Entry_termInfo) - { - printf("%c ", i + 1 == *res->positionOfTerm ? '*' : ' '); - display_term(ent->entries[i]->u.termInfo); - } - else - display_diagrec(ent->entries[i]->u.surrogateDiagnostic); + Z_Entries *ent = res->entries->u.entries; + + for (i = 0; i < ent->num_entries; i++) + if (ent->entries[i]->which == Z_Entry_termInfo) + { + printf("%c ", i + 1 == *res->positionOfTerm ? '*' : ' '); + display_term(ent->entries[i]->u.termInfo); + } + else + display_diagrec(ent->entries[i]->u.surrogateDiagnostic); } else - display_diagrec(res->entries->u.nonSurrogateDiagnostics->diagRecs[0]); + display_diagrec(res->entries->u.nonSurrogateDiagnostics->diagRecs[0]); } int cmd_scan(char *arg) { if (!session) { - printf("Session not initialized yet\n"); - return 0; + printf("Session not initialized yet\n"); + return 0; } if (!ODR_MASK_GET(session->options, Z_Options_scan)) { - printf("Target doesn't support scan\n"); - return 0; + printf("Target doesn't support scan\n"); + return 0; } if (*arg) { - if (send_scanrequest(arg, 5, 20) < 0) - return 0; + if (send_scanrequest(arg, 5, 20) < 0) + return 0; } else - if (send_scanrequest(last_scan, 1, 20) < 0) - return 0; + if (send_scanrequest(last_scan, 1, 20) < 0) + return 0; return 2; } @@ -700,32 +867,73 @@ int cmd_format(char *arg) { if (!arg || !*arg) { - printf("Usage: format \n"); - return 0; + printf("Usage: format \n"); + return 0; } if (!strcmp(arg, "sutrs")) { - printf("Preferred format is SUTRS.\n"); - recordsyntax = VAL_SUTRS; - return 1; + printf("Preferred format is SUTRS.\n"); + recordsyntax = VAL_SUTRS; + return 1; } else if (!strcmp(arg, "usmarc")) { - printf("Preferred format is USMARC\n"); - recordsyntax = VAL_USMARC; - return 1; + printf("Preferred format is USMARC\n"); + recordsyntax = VAL_USMARC; + return 1; } else if (!strcmp(arg, "danmarc")) { - printf("Preferred format is DANMARC\n"); - recordsyntax = VAL_DANMARC; - return 1; + printf("Preferred format is DANMARC\n"); + recordsyntax = VAL_DANMARC; + return 1; + } + else if (!strcmp(arg, "grs1")) + { + printf("Preferred format is GRS1\n"); + recordsyntax = VAL_GRS1; + return 1; + } + else if (!strcmp(arg, "explain")) + { + printf("Preferred format is Explain\n"); + recordsyntax = VAL_EXPLAIN; + return 1; } else { - printf("Specify one of {sutrs,usmarc,danmarc}.\n"); - return 0; + printf("Specify one of {sutrs,usmarc,danmarc,grs1}.\n"); + return 0; + } +} + +int cmd_elements(char *arg) +{ + static Z_ElementSetNames esn; + static char what[100]; + + if (!arg || !*arg) + { + printf("Usage: elements \n"); + return 0; } + strcpy(what, arg); + esn.which = Z_ElementSetNames_generic; + esn.u.generic = what; + elementSetNames = &esn; + return 1; +} + +int cmd_close(char *arg) +{ + Z_APDU *apdu = zget_APDU(out, Z_APDU_close); + Z_Close *req = apdu->u.close; + + *req->closeReason = Z_Close_finished; + send_apdu(apdu); + printf("Sent close request.\n"); + sent_close = 1; + return 2; } static void initialize(void) @@ -737,11 +945,11 @@ static void initialize(void) #endif if (!(out = odr_createmem(ODR_ENCODE)) || - !(in = odr_createmem(ODR_DECODE)) || - !(print = odr_createmem(ODR_PRINT))) + !(in = odr_createmem(ODR_DECODE)) || + !(print = odr_createmem(ODR_PRINT))) { - fprintf(stderr, "failed to allocate ODR streams\n"); - exit(1); + fprintf(stderr, "failed to allocate ODR streams\n"); + exit(1); } setvbuf(stdout, 0, _IONBF, 0); @@ -751,8 +959,8 @@ static void initialize(void) inf = fopen ("default.bib", "r"); if (inf) { - ccl_qual_file (bibset, inf); - fclose (inf); + ccl_qual_file (bibset, inf); + fclose (inf); } #endif #endif @@ -761,25 +969,27 @@ static void initialize(void) static int client(void) { static struct { - char *cmd; - int (*fun)(char *arg); - char *ad; + char *cmd; + int (*fun)(char *arg); + char *ad; } cmd[] = { - {"open", cmd_open, "('tcp'|'osi')':'['/'][':']"}, - {"quit", cmd_quit, ""}, - {"find", cmd_find, ""}, - {"base", cmd_base, ""}, - {"show", cmd_show, "['+'<#RECS>]"}, - {"scan", cmd_scan, ""}, - {"authentication", cmd_authentication, ""}, - {"lslb", cmd_lslb, ""}, - {"ssub", cmd_ssub, ""}, - {"mspn", cmd_mspn, ""}, - {"status", cmd_status, ""}, - {"setnames", cmd_setnames, ""}, - {"cancel", cmd_cancel, ""}, - {"format", cmd_format, ""}, - {0,0} + {"open", cmd_open, "('tcp'|'osi')':'['/'][':']"}, + {"quit", cmd_quit, ""}, + {"find", cmd_find, ""}, + {"base", cmd_base, ""}, + {"show", cmd_show, "['+'<#RECS>]"}, + {"scan", cmd_scan, ""}, + {"authentication", cmd_authentication, ""}, + {"lslb", cmd_lslb, ""}, + {"ssub", cmd_ssub, ""}, + {"mspn", cmd_mspn, ""}, + {"status", cmd_status, ""}, + {"setnames", cmd_setnames, ""}, + {"cancel", cmd_cancel, ""}, + {"format", cmd_format, ""}, + {"elements", cmd_elements, ""}, + {"close", cmd_close, ""}, + {0,0} }; char *netbuffer= 0; int netbufferlen = 0; @@ -788,113 +998,118 @@ static int client(void) while (1) { - int res; - fd_set input; - char line[1024], word[1024], arg[1024]; - - FD_ZERO(&input); - FD_SET(0, &input); - if (conn) - FD_SET(cs_fileno(conn), &input); - if ((res = select(20, &input, 0, 0, 0)) < 0) - { - perror("select"); - exit(1); - } - if (!res) - continue; - if (FD_ISSET(0, &input)) - { - /* quick & dirty way to get a command line. */ - if (!gets(line)) - break; - if ((res = sscanf(line, "%s %[^;]", word, arg)) <= 0) - { - strcpy(word, last_cmd); - *arg = '\0'; - } - else if (res == 1) - *arg = 0; - strcpy(last_cmd, word); - for (i = 0; cmd[i].cmd; i++) - if (!strncmp(cmd[i].cmd, word, strlen(word))) - { - res = (*cmd[i].fun)(arg); - break; - } - if (!cmd[i].cmd) /* dump our help-screen */ - { - printf("Unknown command: %s.\n", word); - printf("Currently recognized commands:\n"); - for (i = 0; cmd[i].cmd; i++) - printf(" %s %s\n", cmd[i].cmd, cmd[i].ad); - res = 1; - } - if (res < 2) - printf(C_PROMPT); - } - if (conn && FD_ISSET(cs_fileno(conn), &input)) - { - do - { - if ((res = cs_get(conn, &netbuffer, &netbufferlen)) < 0) - { - perror("cs_get"); - exit(1); - } - if (!res) - { - printf("Target closed connection.\n"); - exit(1); - } - odr_reset(in); /* release APDU from last round */ - odr_setbuf(in, netbuffer, res, 0); - if (!z_APDU(in, &apdu, 0)) - { - odr_perror(in, "Decoding incoming APDU"); - fprintf(stderr, "Packet dump:\n---------\n"); - odr_dumpBER(stderr, netbuffer, res); - fprintf(stderr, "---------\n"); - exit(1); - } + int res; + fd_set input; + char line[1024], word[1024], arg[1024]; + + FD_ZERO(&input); + FD_SET(0, &input); + if (conn) + FD_SET(cs_fileno(conn), &input); + if ((res = select(20, &input, 0, 0, 0)) < 0) + { + perror("select"); + exit(1); + } + if (!res) + continue; + if (FD_ISSET(0, &input)) + { + /* quick & dirty way to get a command line. */ + if (!gets(line)) + break; + if ((res = sscanf(line, "%s %[^;]", word, arg)) <= 0) + { + strcpy(word, last_cmd); + *arg = '\0'; + } + else if (res == 1) + *arg = 0; + strcpy(last_cmd, word); + for (i = 0; cmd[i].cmd; i++) + if (!strncmp(cmd[i].cmd, word, strlen(word))) + { + res = (*cmd[i].fun)(arg); + break; + } + if (!cmd[i].cmd) /* dump our help-screen */ + { + printf("Unknown command: %s.\n", word); + printf("Currently recognized commands:\n"); + for (i = 0; cmd[i].cmd; i++) + printf(" %s %s\n", cmd[i].cmd, cmd[i].ad); + res = 1; + } + if (res < 2) + printf(C_PROMPT); + } + if (conn && FD_ISSET(cs_fileno(conn), &input)) + { + do + { + if ((res = cs_get(conn, &netbuffer, &netbufferlen)) < 0) + { + perror("cs_get"); + exit(1); + } + if (!res) + { + printf("Target closed connection.\n"); + exit(1); + } + odr_reset(in); /* release APDU from last round */ + odr_setbuf(in, netbuffer, res, 0); + if (!z_APDU(in, &apdu, 0)) + { + odr_perror(in, "Decoding incoming APDU"); + fprintf(stderr, "[Near %d]\n", odr_offset(in)); + fprintf(stderr, "Packet dump:\n---------\n"); + odr_dumpBER(stderr, netbuffer, res); + fprintf(stderr, "---------\n"); + exit(1); + } #if 0 - if (!z_APDU(print, &apdu, 0)) - { - odr_perror(print, "Failed to print incoming APDU"); - odr_reset(print); - continue; - } + if (!z_APDU(print, &apdu, 0)) + { + odr_perror(print, "Failed to print incoming APDU"); + odr_reset(print); + continue; + } #endif - 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: - printf("Received presentResponse.\n"); - setno += - *apdu->u.presentResponse->numberOfRecordsReturned; - if (apdu->u.presentResponse->records) - display_records(apdu->u.presentResponse->records); - else - printf("No records.\n"); - break; - default: - printf("Received unknown APDU type (%d).\n", - apdu->which); - exit(1); - } - printf("Z> "); - fflush(stdout); - } - while (cs_more(conn)); - } + 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: + printf("Received presentResponse.\n"); + setno += + *apdu->u.presentResponse->numberOfRecordsReturned; + if (apdu->u.presentResponse->records) + display_records(apdu->u.presentResponse->records); + else + printf("No records.\n"); + break; + case Z_APDU_close: + printf("Target has closed the association.\n"); + process_close(apdu->u.close); + break; + default: + printf("Received unknown APDU type (%d).\n", + apdu->which); + exit(1); + } + printf(C_PROMPT); + fflush(stdout); + } + while (cs_more(conn)); + } } return 0; } @@ -903,8 +1118,8 @@ int main(int argc, char **argv) { initialize(); if (argc > 1) - cmd_open(argv[1]); + cmd_open(argv[1]); else - printf(C_PROMPT); + printf(C_PROMPT); return client(); }