source: trunk/gsdl/packages/yaz/client/yaz_zclient.c@ 2650

Last change on this file since 2650 was 2650, checked in by jrm21, 23 years ago

added an error check - now returns an error string for some errors instead of
continuing (and later causing problems).

  • Property svn:keywords set to Author Date Id Revision
File size: 59.1 KB
Line 
1/*
2 * Copyright (c) 1995-2000, Index Data
3 * See the file LICENSE for details.
4 * Sebastian Hammer, Adam Dickmeiss
5 *
6 * $Log$
7 * Revision 1.4 2001/07/12 03:33:16 jrm21
8 * added an error check - now returns an error string for some errors instead of
9 * continuing (and later causing problems).
10 *
11 * Revision 1.3 2001/06/13 04:22:26 jrm21
12 * don't add <a href> tags for USMARC field 856 (online access), as it is not
13 * guaranteed to be a URL - just some text describing online access...
14 *
15 * Revision 1.2 2000/10/26 06:37:46 jrm21
16 * Now makes hyperlinks for MARC field 856 (Electronic Access/Location),
17 * so you too can point and click...
18 *
19 * Revision 1.1 2000/08/03 03:10:01 johnmcp
20 * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
21 *
22 * Revision 1.1.2.1 2000/05/24 23:24:29 johnmcp
23 * added some of the YAZ toolkit code for z39.50 client.
24 *
25 * Revision 1.95 2000/02/28 11:20:05 adam
26 * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL.
27 *
28 */
29
30/* Modified for the GreenStone Digital Library project - johnmcp */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <ctype.h> /* for isdigit() */
36#include <time.h>
37
38/* don't need functions from here, maybe only the other header files:
39function atoi_n needed by marc_display()
40#include <yaz/yconfig.h>
41#include <yaz/xmalloc.h>
42#include <yaz/log.h>
43#include <yaz/tpath.h>
44#include <yaz/options.h>
45#include <yaz/wrbuf.h>
46#include <yaz/nmem.h>
47#include <yaz/readconf.h>
48*/
49#include <yaz/yaz-util.h>
50
51#include <yaz/tcpip.h>
52
53#include <yaz/proto.h>
54
55/* only defines marc_display[_ex] (), which could be inline. May need
56 yaz/yconfig.h header file */
57#include <yaz/marcdisp.h>
58#include <yaz/diagbib1.h>
59
60#include <yaz/pquery.h>
61
62#ifdef ASN_COMPILED
63#include <yaz/ill.h>
64#endif
65
66#if HAVE_READLINE_READLINE_H
67#include <readline/readline.h>
68#endif
69#if HAVE_READLINE_HISTORY_H
70#include <readline/history.h>
71#endif
72
73#define C_PROMPT "Z> "
74
75static ODR out, in, print; /* encoding and decoding streams */
76static FILE *apdu_file = 0;
77static COMSTACK conn = 0; /* our z-association */
78static Z_IdAuthentication *auth = 0; /* our current auth definition */
79static char *databaseNames[128];
80static Z_External *record_last = 0;
81static int num_databaseNames = 0;
82static int setnumber = 0; /* current result set number */
83static int smallSetUpperBound = 0;
84static int largeSetLowerBound = 1;
85static int mediumSetPresentNumber = 0;
86static Z_ElementSetNames *elementSetNames = 0;
87static int setno = 1; /* current set offset */
88static enum oid_proto protocol = PROTO_Z3950; /* current app protocol */
89static enum oid_value recordsyntax = VAL_USMARC;
90static enum oid_value schema = VAL_NONE;
91static int sent_close = 0;
92static NMEM session_mem = NULL; /* memory handle for init-response */
93static Z_InitResponse *session = 0; /* session parameters */
94static char last_scan[512] = "0";
95static FILE *marcdump = 0;
96static char *refid = NULL;
97/*johnmcp*/
98Z_InitResponse *z_initresponse;
99typedef enum {
100 QueryType_Prefix,
101 QueryType_CCL,
102 QueryType_CCL2RPN
103} QueryType;
104
105static QueryType queryType = QueryType_Prefix;
106/*static QueryType queryType = QueryType_CCL;*/
107
108static void send_apdu(Z_APDU *a)
109{
110 char *buf;
111 int len;
112
113 if (!z_APDU(out, &a, 0, 0))
114 {
115 odr_perror(out, "Encoding APDU");
116 exit(1);
117 }
118 if (apdu_file)
119 {
120 z_APDU(print, &a, 0, 0);
121 odr_reset(print);
122 }
123 buf = odr_getbuf(out, &len, 0);
124 /* printf ("sending APDU of size %d\n", len); */
125 if (cs_put(conn, buf, len) < 0)
126 {
127 fprintf(stderr, "cs_put: %s", cs_errmsg(cs_errno(conn)));
128 exit(1);
129 }
130 odr_reset(out); /* release the APDU structure */
131}
132
133static void print_refid (Z_ReferenceId *id)
134{
135 if (id)
136 {
137 printf ("ReferenceId: '%.*s'\n", id->len, id->buf);
138 }
139}
140
141static Z_ReferenceId *set_refid (ODR out)
142{
143 Z_ReferenceId *id;
144 if (!refid)
145 return 0;
146 id = (Z_ReferenceId *) odr_malloc (out, sizeof(*id));
147 id->size = id->len = strlen(refid);
148 id->buf = (unsigned char *) odr_malloc (out, id->len);
149 memcpy (id->buf, refid, id->len);
150 return id;
151}
152
153/* INIT SERVICE ------------------------------- */
154
155static void send_initRequest()
156{
157 Z_APDU *apdu = zget_APDU(out, Z_APDU_initRequest);
158 Z_InitRequest *req = apdu->u.initRequest;
159
160 ODR_MASK_SET(req->options, Z_Options_search);
161 ODR_MASK_SET(req->options, Z_Options_present);
162 ODR_MASK_SET(req->options, Z_Options_namedResultSets);
163 ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
164 ODR_MASK_SET(req->options, Z_Options_scan);
165 ODR_MASK_SET(req->options, Z_Options_sort);
166 ODR_MASK_SET(req->options, Z_Options_extendedServices);
167 ODR_MASK_SET(req->options, Z_Options_delSet);
168
169 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
170 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
171 ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
172
173 *req->maximumRecordSize = 1024*1024;
174 *req->preferredMessageSize = 1024*1024;
175
176 req->idAuthentication = auth;
177
178 send_apdu(apdu);
179}
180
181char *z_get_initResponse()
182{
183 char *buffer;
184 size_t needed_length;
185 char *text_id="ID: ";
186 char *text_name="<br>\nName: ";
187 char *text_ver="<br>\nVersion: ";
188 int counter;
189
190 buffer=NULL;
191 /* save session parameters for later use */
192 /* session_mem = odr_extract_mem(in);
193 session = res; */
194 if (!*session->result)
195 return NULL;
196
197 /* work out total string length needed. Note strlen(NULL) is a bad thing
198 to do. */
199 needed_length=strlen(text_id)+strlen(text_name)+strlen(text_ver)+
200 (session->implementationId?strlen(session->implementationId):0) +
201 (session->implementationName?strlen(session->implementationName):0) +
202 (session->implementationVersion?strlen(session->implementationVersion)
203 :0) +
204 (session->userInformationField?
205 strlen(session->userInformationField->u.octet_aligned->buf):0) +
206 1 /* for null char */ ;
207 if ((buffer=malloc((sizeof(char *)) * needed_length))==NULL) {
208 fprintf(stderr,"Malloc failed while initialising z39.50 server\n");
209 return (NULL);
210 }
211 /* can't pass NULL to sprintf as a (char *) */
212 sprintf(buffer,"%s%s%s%s%s%s",
213 session->implementationId?text_id:"",
214 session->implementationId?session->implementationId:"",
215 session->implementationName?text_name:"",
216 session->implementationName?session->implementationName:"",
217 session->implementationVersion?text_ver:"",
218 session->implementationVersion?session->implementationVersion:""
219 );
220
221 /* if version 3, also check the other-information parameter of the
222 response. (But check version is 3 first) */
223 if (session->otherInfo)
224 /**** From prt-proto.h *********** (comment added by johnmcp)
225 typedef struct Z_OtherInformationUnit
226 . { Z_InfoCategory *category; / * OPTIONAL * /
227 . int which;
228 #define Z_OtherInfo_characterInfo 0
229 #define Z_OtherInfo_binaryInfo 1
230 #define Z_OtherInfo_externallyDefinedInfo 2
231 #define Z_OtherInfo_oid 3
232 . union
233 . {
234 . char *characterInfo;
235 . Odr_oct *binaryInfo;
236 . Z_External *externallyDefinedInfo;
237 . Odr_oid *oid;
238 . } information;
239 . } Z_OtherInformationUnit;
240
241 typedef struct Z_OtherInformation
242 {
243 int num_elements;
244 Z_OtherInformationUnit **list;
245 } Z_OtherInformation;
246 ************/
247 for (counter=0;counter<session->otherInfo->num_elements;counter++)
248 if (session->otherInfo->list[counter]->which ==
249 Z_OtherInfo_characterInfo)
250 {
251 /* add this extra string to our buffer */
252 int where=strlen(buffer);
253 buffer=realloc(buffer,where+
254 strlen(session->otherInfo->list[counter]->
255 information.characterInfo));
256 strcpy(buffer+where,
257 session->otherInfo->list[counter]->
258 information.characterInfo);
259 }
260 return (buffer);
261}
262
263static int cmd_base(char *arg)
264{
265 int i;
266 char *cp;
267
268 if (!*arg)
269 {
270 printf("Usage: base <database> <database> ...\n");
271 return 0;
272 }
273 for (i = 0; i<num_databaseNames; i++)
274 xfree (databaseNames[i]);
275 num_databaseNames = 0;
276 while (1)
277 {
278 if (!(cp = strchr(arg, ' ')))
279 cp = arg + strlen(arg);
280 if (cp - arg < 1)
281 break;
282 databaseNames[num_databaseNames] = (char *)xmalloc (1 + cp - arg);
283 memcpy (databaseNames[num_databaseNames], arg, cp - arg);
284 databaseNames[num_databaseNames++][cp - arg] = '\0';
285 if (!*cp)
286 break;
287 arg = cp+1;
288 }
289 return 1;
290}
291
292
293int z_cmd_open(char *host_and_port, char *base)
294{
295 void *add;
296 CS_TYPE t;
297
298 if (conn)
299 {
300 printf("Already connected.\n");
301
302 cs_close (conn);
303 conn = NULL;
304 if (session_mem)
305 {
306 nmem_destroy (session_mem);
307 session_mem = NULL;
308 }
309 }
310
311 cmd_base (base);
312 t = tcpip_type;
313 protocol = PROTO_Z3950;
314
315 if (!(conn = cs_create(t, 1, protocol)))
316 {
317 perror("cs_create");
318 return 1;
319 }
320 if (!(add = cs_straddr(conn, host_and_port)))
321 {
322 perror(host_and_port);
323 return 1;
324 }
325
326 if (cs_connect(conn, add) < 0)
327 {
328 perror("connect");
329 cs_close(conn);
330 conn = 0;
331 return 1;
332 }
333 /* if here, we connected OK */
334 send_initRequest();
335 return 0;
336}
337
338int cmd_authentication(char *arg)
339{
340 static Z_IdAuthentication au;
341 static char open[256];
342
343 if (!*arg)
344 {
345 printf("Auth field set to null\n");
346 auth = 0;
347 return 1;
348 }
349 auth = &au;
350 au.which = Z_IdAuthentication_open;
351 au.u.open = open;
352 strcpy(open, arg);
353 return 1;
354}
355
356/* SEARCH SERVICE ------------------------------ */
357
358static void display_variant(Z_Variant *v, int level)
359{
360 int i;
361
362 for (i = 0; i < v->num_triples; i++)
363 {
364 printf("%*sclass=%d,type=%d", level * 4, "", *v->triples[i]->zclass,
365 *v->triples[i]->type);
366 if (v->triples[i]->which == Z_Triple_internationalString)
367 printf(",value=%s\n", v->triples[i]->value.internationalString);
368 else
369 printf("\n");
370 }
371}
372
373static void display_grs1(Z_GenericRecord *r, int level)
374{
375 int i;
376
377 if (!r)
378 return;
379 for (i = 0; i < r->num_elements; i++)
380 {
381 Z_TaggedElement *t;
382
383 printf("%*s", level * 4, "");
384 t = r->elements[i];
385 printf("(");
386 if (t->tagType)
387 printf("%d,", *t->tagType);
388 else
389 printf("?,");
390 if (t->tagValue->which == Z_StringOrNumeric_numeric)
391 printf("%d) ", *t->tagValue->u.numeric);
392 else
393 printf("%s) ", t->tagValue->u.string);
394 if (t->content->which == Z_ElementData_subtree)
395 {
396 printf("\n");
397 display_grs1(t->content->u.subtree, level+1);
398 }
399 else if (t->content->which == Z_ElementData_string)
400 printf("%s\n", t->content->u.string);
401 else if (t->content->which == Z_ElementData_numeric)
402 printf("%d\n", *t->content->u.numeric);
403 else if (t->content->which == Z_ElementData_oid)
404 {
405 int *ip = t->content->u.oid;
406 oident *oent;
407
408 if ((oent = oid_getentbyoid(t->content->u.oid)))
409 printf("OID: %s\n", oent->desc);
410 else
411 {
412 printf("{");
413 while (ip && *ip >= 0)
414 printf(" %d", *(ip++));
415 printf(" }\n");
416 }
417 }
418 else if (t->content->which == Z_ElementData_noDataRequested)
419 printf("[No data requested]\n");
420 else if (t->content->which == Z_ElementData_elementEmpty)
421 printf("[Element empty]\n");
422 else if (t->content->which == Z_ElementData_elementNotThere)
423 printf("[Element not there]\n");
424 else
425 printf("??????\n");
426 if (t->appliedVariant)
427 display_variant(t->appliedVariant, level+1);
428 if (t->metaData && t->metaData->supportedVariants)
429 {
430 int c;
431
432 printf("%*s---- variant list\n", (level+1)*4, "");
433 for (c = 0; c < t->metaData->num_supportedVariants; c++)
434 {
435 printf("%*svariant #%d\n", (level+1)*4, "", c);
436 display_variant(t->metaData->supportedVariants[c], level + 2);
437 }
438 }
439 }
440}
441
442static void print_record(const unsigned char *buf, size_t len)
443{
444 size_t i;
445 for (i = 0; i<len; i++)
446 if ((buf[i] <= 126 && buf[i] >= 32) || strchr ("\n\r\t\f", buf[i]))
447 fputc (buf[i], stdout);
448 else
449 printf ("\\X%02X", buf[i]);
450 /* add newline if not already added ... */
451 if (i <= 0 || buf[i-1] != '\n')
452 fputc ('\n', stdout);
453}
454
455static void display_record(Z_DatabaseRecord *p)
456{
457 Z_External *r = (Z_External*) p;
458 oident *ent = oid_getentbyoid(r->direct_reference);
459
460 record_last = r;
461 /*
462 * Tell the user what we got.
463 */
464 if (r->direct_reference)
465 {
466 printf("Record type: ");
467 if (ent)
468 printf("%s\n", ent->desc);
469 else if (!odr_oid(print, &r->direct_reference, 0, 0))
470 {
471 odr_perror(print, "print oid");
472 odr_reset(print);
473 }
474 }
475 /* Check if this is a known, ASN.1 type tucked away in an octet string */
476 if (ent && r->which == Z_External_octet)
477 {
478 Z_ext_typeent *type = z_ext_getentbyref(ent->value);
479 void *rr;
480
481 if (type)
482 {
483 /*
484 * Call the given decoder to process the record.
485 */
486 odr_setbuf(in, (char*)p->u.octet_aligned->buf,
487 p->u.octet_aligned->len, 0);
488 if (!(*type->fun)(in, (char **)&rr, 0, 0))
489 {
490 odr_perror(in, "Decoding constructed record.");
491 fprintf(stderr, "[Near %d]\n", odr_offset(in));
492 fprintf(stderr, "Packet dump:\n---------\n");
493 odr_dumpBER(stderr, (char*)p->u.octet_aligned->buf,
494 p->u.octet_aligned->len);
495 fprintf(stderr, "---------\n");
496 exit(1);
497 }
498 /*
499 * Note: we throw away the original, BER-encoded record here.
500 * Do something else with it if you want to keep it.
501 */
502 r->u.sutrs = (Z_SUTRS *) rr; /* we don't actually check the type here. */
503 r->which = type->what;
504 }
505 }
506 if (ent && ent->value == VAL_SOIF)
507 print_record((const unsigned char *) r->u.octet_aligned->buf, r->u.octet_aligned->len);
508 else if (r->which == Z_External_octet && p->u.octet_aligned->len)
509 {
510 /* johnmcp - this is called for USmarc for demo server, at least */
511 const char *octet_buf = (char*)p->u.octet_aligned->buf;
512 if (ent->value == VAL_TEXT_XML || ent->value == VAL_APPLICATION_XML ||
513 ent->value == VAL_HTML)
514 print_record((const unsigned char *) octet_buf,
515 p->u.octet_aligned->len);
516 else
517 {
518 /* johnmcp - here marc_display does the work */
519 if (marc_display (octet_buf, NULL) <= 0)
520 {
521 printf ("ISO2709 decoding failed, dumping record as is:\n");
522 print_record((const unsigned char*) octet_buf,
523 p->u.octet_aligned->len);
524 }
525 }
526 if (marcdump) /*here (false) */
527 fwrite (octet_buf, 1, p->u.octet_aligned->len, marcdump);
528 }
529 else if (ent && ent->value == VAL_SUTRS)
530 {
531 if (r->which != Z_External_sutrs)
532 {
533 printf("Expecting single SUTRS type for SUTRS.\n");
534 return;
535 }
536 print_record(r->u.sutrs->buf, r->u.sutrs->len);
537 }
538 else if (ent && ent->value == VAL_GRS1)
539 {
540 if (r->which != Z_External_grs1)
541 {
542 printf("Expecting single GRS type for GRS.\n");
543 return;
544 }
545 display_grs1(r->u.grs1, 0);
546 }
547 else
548 {
549 printf("Unknown record representation.\n");
550 if (!z_External(print, &r, 0, 0))
551 {
552 odr_perror(print, "Printing external");
553 odr_reset(print);
554 }
555 }
556}
557
558
559static void display_diagrecs(Z_DiagRec **pp, int num)
560{
561 int i;
562 oident *ent;
563 Z_DefaultDiagFormat *r;
564
565 printf("Diagnostic message(s) from database:\n");
566 for (i = 0; i<num; i++)
567 {
568 Z_DiagRec *p = pp[i];
569 if (p->which != Z_DiagRec_defaultFormat)
570 {
571 printf("Diagnostic record not in default format.\n");
572 return;
573 }
574 else
575 r = p->u.defaultFormat;
576 if (!(ent = oid_getentbyoid(r->diagnosticSetId)) ||
577 ent->oclass != CLASS_DIAGSET || ent->value != VAL_BIB1)
578 printf("Missing or unknown diagset\n");
579 printf(" [%d] %s", *r->condition, diagbib1_str(*r->condition));
580#ifdef ASN_COMPILED
581 switch (r->which)
582 {
583 case Z_DefaultDiagFormat_v2Addinfo:
584 printf (" -- v2 addinfo '%s'\n", r->u.v2Addinfo);
585 break;
586 case Z_DefaultDiagFormat_v3Addinfo:
587 printf (" -- v3 addinfo '%s'\n", r->u.v3Addinfo);
588 break;
589 }
590#else
591 if (r->addinfo && *r->addinfo)
592 printf(" -- '%s'\n", r->addinfo);
593 else
594 printf("\n");
595#endif
596 }
597}
598
599
600static void display_nameplusrecord(Z_NamePlusRecord *p)
601{
602 if (p->databaseName)
603 printf("[%s]", p->databaseName);
604 if (p->which == Z_NamePlusRecord_surrogateDiagnostic)
605 display_diagrecs(&p->u.surrogateDiagnostic, 1);
606 else if (p->which == Z_NamePlusRecord_databaseRecord)
607 display_record(p->u.databaseRecord);
608}
609
610static void display_records(Z_Records *p)
611{
612 int i;
613
614 if (p->which == Z_Records_NSD)
615 {
616#ifdef ASN_COMPILED
617 Z_DiagRec dr, *dr_p = &dr;
618 dr.which = Z_DiagRec_defaultFormat;
619 dr.u.defaultFormat = p->u.nonSurrogateDiagnostic;
620 display_diagrecs (&dr_p, 1);
621#else
622 display_diagrecs (&p->u.nonSurrogateDiagnostic, 1);
623#endif
624 }
625 else if (p->which == Z_Records_multipleNSD)
626 display_diagrecs (p->u.multipleNonSurDiagnostics->diagRecs,
627 p->u.multipleNonSurDiagnostics->num_diagRecs);
628 else
629 {
630 printf("Records: %d\n", p->u.databaseOrSurDiagnostics->num_records);
631 for (i = 0; i < p->u.databaseOrSurDiagnostics->num_records; i++)
632 display_nameplusrecord(p->u.databaseOrSurDiagnostics->records[i]);
633 }
634}
635
636
637static int send_searchRequest(char *arg)
638{
639 Z_APDU *apdu = zget_APDU(out, Z_APDU_searchRequest);
640 Z_SearchRequest *req = apdu->u.searchRequest;
641 Z_Query query;
642 int oid[OID_SIZE];
643 char setstring[100];
644 Z_RPNQuery *RPNquery;
645 /* Odr_oct ccl_query; */
646
647 req->referenceId = set_refid (out);
648 if (!strcmp(arg, "@big")) /* strictly for troublemaking */
649 {
650 static unsigned char big[2100];
651 static Odr_oct bigo;
652
653 /* send a very big referenceid to test transport stack etc. */
654 memset(big, 'A', 2100);
655 bigo.len = bigo.size = 2100;
656 bigo.buf = big;
657 req->referenceId = &bigo;
658 }
659
660 if (setnumber >= 0)
661 {
662 sprintf(setstring, "%d", ++setnumber);
663 req->resultSetName = setstring;
664 }
665 *req->smallSetUpperBound = smallSetUpperBound;
666 *req->largeSetLowerBound = largeSetLowerBound;
667 *req->mediumSetPresentNumber = mediumSetPresentNumber;
668 if (smallSetUpperBound > 0 || (largeSetLowerBound > 1 &&
669 mediumSetPresentNumber > 0))
670 {
671 oident prefsyn;
672
673 prefsyn.proto = protocol;
674 prefsyn.oclass = CLASS_RECSYN;
675 prefsyn.value = recordsyntax;
676 req->preferredRecordSyntax =
677 odr_oiddup(out, oid_ent_to_oid(&prefsyn, oid));
678 req->smallSetElementSetNames =
679 req->mediumSetElementSetNames = elementSetNames;
680 }
681 req->num_databaseNames = num_databaseNames;
682 req->databaseNames = databaseNames;
683
684 req->query = &query;
685 /* johnmcp - this is where we choose our query format. either ccl or rpn */
686 /* switch (queryType)
687 {
688 case QueryType_Prefix: */
689 query.which = Z_Query_type_1;
690 RPNquery = p_query_rpn (out, protocol, arg);
691 if (!RPNquery)
692 {
693 printf("Prefix query error\n");
694 return (-1);
695 }
696 query.u.type_1 = RPNquery;
697 /* break;
698 case QueryType_CCL:
699 query.which = Z_Query_type_2;
700 query.u.type_2 = &ccl_query;
701 ccl_query.buf = (unsigned char*) arg;
702 ccl_query.len = strlen(arg);
703 break;
704 default:
705 printf ("Unsupported query type\n");
706 return 0;
707 }*/
708 send_apdu(apdu);
709 setno = 1;
710 /* printf("Sent searchRequest.\n"); */
711 return 0;
712}
713
714static int process_searchResponse(Z_SearchResponse *res)
715{
716 print_refid (res->referenceId);
717 if (!(*res->searchStatus)) {
718 /* this should return an error instead of 0 docs found... one day... */
719 return 0;
720 }
721 setno += *res->numberOfRecordsReturned;
722 if (res->records)
723 display_records(res->records);
724 return *res->resultCount;
725}
726
727static void print_level(int iLevel)
728{
729 int i;
730 for (i = 0; i < iLevel * 4; i++)
731 printf(" ");
732}
733
734static void print_int(int iLevel, const char *pTag, int *pInt)
735{
736 if (pInt != NULL)
737 {
738 print_level(iLevel);
739 printf("%s: %d\n", pTag, *pInt);
740 }
741}
742
743static void print_string(int iLevel, const char *pTag, const char *pString)
744{
745 if (pString != NULL)
746 {
747 print_level(iLevel);
748 printf("%s: %s\n", pTag, pString);
749 }
750}
751
752static void print_oid(int iLevel, const char *pTag, Odr_oid *pOid)
753{
754 if (pOid != NULL)
755 {
756 int *pInt = pOid;
757
758 print_level(iLevel);
759 printf("%s:", pTag);
760 for (; *pInt != -1; pInt++)
761 printf(" %d", *pInt);
762 printf("\n");
763 }
764}
765
766static void print_referenceId(int iLevel, Z_ReferenceId *referenceId)
767{
768 if (referenceId != NULL)
769 {
770 int i;
771
772 print_level(iLevel);
773 printf("Ref Id (%d, %d): ", referenceId->len, referenceId->size);
774 for (i = 0; i < referenceId->len; i++)
775 printf("%c", referenceId->buf[i]);
776 printf("\n");
777 }
778}
779
780static void print_string_or_numeric(int iLevel, const char *pTag, Z_StringOrNumeric *pStringNumeric)
781{
782 if (pStringNumeric != NULL)
783 {
784 switch (pStringNumeric->which)
785 {
786 case Z_StringOrNumeric_string:
787 print_string(iLevel, pTag, pStringNumeric->u.string);
788 break;
789
790 case Z_StringOrNumeric_numeric:
791 print_int(iLevel, pTag, pStringNumeric->u.numeric);
792 break;
793
794 default:
795 print_level(iLevel);
796 printf("%s: valid type for Z_StringOrNumeric\n", pTag);
797 break;
798 }
799 }
800}
801
802static void print_universe_report_duplicate(int iLevel, Z_UniverseReportDuplicate *pUniverseReportDuplicate)
803{
804 if (pUniverseReportDuplicate != NULL)
805 {
806 print_level(iLevel);
807 printf("Universe Report Duplicate: \n");
808 iLevel++;
809 print_string_or_numeric(iLevel, "Hit No", pUniverseReportDuplicate->hitno);
810 }
811}
812
813static void print_universe_report_hits(int iLevel, Z_UniverseReportHits *pUniverseReportHits)
814{
815 if (pUniverseReportHits != NULL)
816 {
817 print_level(iLevel);
818 printf("Universe Report Hits: \n");
819 iLevel++;
820 print_string_or_numeric(iLevel, "Database", pUniverseReportHits->database);
821 print_string_or_numeric(iLevel, "Hits", pUniverseReportHits->hits);
822 }
823}
824
825static void print_universe_report(int iLevel, Z_UniverseReport *pUniverseReport)
826{
827 if (pUniverseReport != NULL)
828 {
829 print_level(iLevel);
830 printf("Universe Report: \n");
831 iLevel++;
832 print_int(iLevel, "Total Hits", pUniverseReport->totalHits);
833 switch (pUniverseReport->which)
834 {
835 case Z_UniverseReport_databaseHits:
836 print_universe_report_hits(iLevel, pUniverseReport->u.databaseHits);
837 break;
838
839 case Z_UniverseReport_duplicate:
840 print_universe_report_duplicate(iLevel, pUniverseReport->u.duplicate);
841 break;
842
843 default:
844 print_level(iLevel);
845 printf("Type: %d\n", pUniverseReport->which);
846 break;
847 }
848 }
849}
850
851static void print_external(int iLevel, Z_External *pExternal)
852{
853 if (pExternal != NULL)
854 {
855 print_level(iLevel);
856 printf("External: \n");
857 iLevel++;
858 print_oid(iLevel, "Direct Reference", pExternal->direct_reference);
859 print_int(iLevel, "InDirect Reference", pExternal->indirect_reference);
860 print_string(iLevel, "Descriptor", pExternal->descriptor);
861 switch (pExternal->which)
862 {
863 case Z_External_universeReport:
864 print_universe_report(iLevel, pExternal->u.universeReport);
865 break;
866
867 default:
868 print_level(iLevel);
869 printf("Type: %d\n", pExternal->which);
870 break;
871 }
872 }
873}
874
875static int process_resourceControlRequest (Z_ResourceControlRequest *req)
876{
877 printf ("Received ResourceControlRequest.\n");
878 print_referenceId(1, req->referenceId);
879 print_int(1, "Suspended Flag", req->suspendedFlag);
880 print_int(1, "Partial Results Available", req->partialResultsAvailable);
881 print_int(1, "Response Required", req->responseRequired);
882 print_int(1, "Triggered Request Flag", req->triggeredRequestFlag);
883 print_external(1, req->resourceReport);
884 return 0;
885}
886
887void process_ESResponse(Z_ExtendedServicesResponse *res)
888{
889 printf("process_ESResponse status=");
890 switch (*res->operationStatus)
891 {
892 case Z_ExtendedServicesResponse_done:
893 printf ("done\n");
894 break;
895 case Z_ExtendedServicesResponse_accepted:
896 printf ("accepted\n");
897 break;
898 case Z_ExtendedServicesResponse_failure:
899 printf ("failure\n");
900 display_diagrecs(res->diagnostics, res->num_diagnostics);
901 break;
902 }
903}
904
905#ifdef ASN_COMPILED
906
907const char *get_ill_element (void *clientData, const char *element)
908{
909 if (!strcmp (element, "ill,transaction-id,transaction-group-qualifier"))
910 return "1";
911 if (!strcmp (element, "ill,transaction-id,transaction-qualifier"))
912 return "1";
913 return 0;
914}
915
916#endif
917
918
919/* PRESENT SERVICE ----------------------------- */
920static int z_send_getbriefrecords(int starting, int set, int howmany) {
921 Z_APDU *apdu = zget_APDU(out, Z_APDU_presentRequest);
922 Z_PresentRequest *req = apdu->u.presentRequest;
923 Z_RecordComposition compo;
924 oident prefsyn;
925 int nos = 1;
926 int oid[OID_SIZE];
927 /* char *p;*/
928 char setstring[100];
929
930 req->referenceId = set_refid (out);
931 nos = howmany;
932
933 setno = starting;
934 setnumber=1;
935 sprintf(setstring, "%d", setnumber);
936 req->resultSetId = setstring;
937 req->resultSetStartPoint = &setno;
938 req->numberOfRecordsRequested = &nos;
939 prefsyn.proto = protocol;
940 prefsyn.oclass = CLASS_RECSYN;
941 prefsyn.value = recordsyntax;
942 req->preferredRecordSyntax =
943 odr_oiddup (out, oid_ent_to_oid(&prefsyn, oid));
944
945 if (schema != VAL_NONE)
946 {
947 oident prefschema;
948
949 prefschema.proto = protocol;
950 prefschema.oclass = CLASS_SCHEMA;
951 prefschema.value = schema;
952
953 req->recordComposition = &compo;
954 compo.which = Z_RecordComp_complex;
955 compo.u.complex = (Z_CompSpec *)
956 odr_malloc(out, sizeof(*compo.u.complex));
957 compo.u.complex->selectAlternativeSyntax = (bool_t *)
958 odr_malloc(out, sizeof(bool_t));
959 *compo.u.complex->selectAlternativeSyntax = 0;
960
961 compo.u.complex->generic = (Z_Specification *)
962 odr_malloc(out, sizeof(*compo.u.complex->generic));
963 compo.u.complex->generic->schema = (Odr_oid *)
964 odr_oiddup(out, oid_ent_to_oid(&prefschema, oid));
965 if (!compo.u.complex->generic->schema)
966 {
967 /* OID wasn't a schema! Try record syntax instead. */
968 prefschema.oclass = CLASS_RECSYN;
969 compo.u.complex->generic->schema = (Odr_oid *)
970 odr_oiddup(out, oid_ent_to_oid(&prefschema, oid));
971 }
972 if (!elementSetNames)
973 compo.u.complex->generic->elementSpec = 0;
974 else
975 {
976 compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
977 odr_malloc(out, sizeof(Z_ElementSpec));
978 compo.u.complex->generic->elementSpec->which =
979 Z_ElementSpec_elementSetName;
980 compo.u.complex->generic->elementSpec->u.elementSetName =
981 elementSetNames->u.generic;
982 }
983 compo.u.complex->num_dbSpecific = 0;
984 compo.u.complex->dbSpecific = 0;
985 compo.u.complex->num_recordSyntax = 0;
986 compo.u.complex->recordSyntax = 0;
987 }
988 else if (elementSetNames)
989 {
990 req->recordComposition = &compo;
991 compo.which = Z_RecordComp_simple;
992 compo.u.simple = elementSetNames;
993 }
994 send_apdu(apdu);
995 return 0;
996}
997
998void process_close(Z_Close *req)
999{
1000 Z_APDU *apdu = zget_APDU(out, Z_APDU_close);
1001 Z_Close *res = apdu->u.close;
1002
1003 static char *reasons[] =
1004 {
1005 "finished",
1006 "shutdown",
1007 "system problem",
1008 "cost limit reached",
1009 "resources",
1010 "security violation",
1011 "protocolError",
1012 "lack of activity",
1013 "peer abort",
1014 "unspecified"
1015 };
1016
1017 printf("Reason: %s, message: %s\n", reasons[*req->closeReason],
1018 req->diagnosticInformation ? req->diagnosticInformation : "NULL");
1019 if (sent_close)
1020 {
1021 cs_close (conn);
1022 conn = NULL;
1023 if (session_mem)
1024 {
1025 nmem_destroy (session_mem);
1026 session_mem = NULL;
1027 }
1028 sent_close = 0;
1029 }
1030 else
1031 {
1032 *res->closeReason = Z_Close_finished;
1033 send_apdu(apdu);
1034 printf("Sent response.\n");
1035 sent_close = 1;
1036 }
1037}
1038
1039
1040
1041int cmd_quit(char *arg)
1042{
1043 printf("See you later, alligator.\n");
1044 exit(0);
1045 return 0;
1046}
1047
1048int cmd_cancel(char *arg)
1049{
1050 Z_APDU *apdu = zget_APDU(out, Z_APDU_triggerResourceControlRequest);
1051 Z_TriggerResourceControlRequest *req =
1052 apdu->u.triggerResourceControlRequest;
1053 bool_t rfalse = 0;
1054
1055 if (!conn)
1056 {
1057 printf("Session not initialized yet\n");
1058 return 0;
1059 }
1060 if (!ODR_MASK_GET(session->options, Z_Options_triggerResourceCtrl))
1061 {
1062 printf("Target doesn't support cancel (trigger resource ctrl)\n");
1063 return 0;
1064 }
1065 *req->requestedAction = Z_TriggerResourceCtrl_cancel;
1066 req->resultSetWanted = &rfalse;
1067
1068 send_apdu(apdu);
1069 printf("Sent cancel request\n");
1070 return 2;
1071}
1072
1073int send_scanrequest(char *string, int pp, int num)
1074{
1075 Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest);
1076 Z_ScanRequest *req = apdu->u.scanRequest;
1077
1078 if (!(req->termListAndStartPoint =
1079 p_query_scan(out, protocol, &req->attributeSet, string)))
1080 {
1081 printf("Prefix query error\n");
1082 return -1;
1083 }
1084 req->referenceId = set_refid (out);
1085 req->num_databaseNames = num_databaseNames;
1086 req->databaseNames = databaseNames;
1087 req->numberOfTermsRequested = &num;
1088 req->preferredPositionInResponse = &pp;
1089 send_apdu(apdu);
1090 return 2;
1091}
1092
1093int send_sortrequest(char *arg, int newset)
1094{
1095 Z_APDU *apdu = zget_APDU(out, Z_APDU_sortRequest);
1096 Z_SortRequest *req = apdu->u.sortRequest;
1097 Z_SortKeySpecList *sksl = (Z_SortKeySpecList *)
1098 odr_malloc (out, sizeof(*sksl));
1099 char setstring[32];
1100 char sort_string[32], sort_flags[32];
1101 int off;
1102 int oid[OID_SIZE];
1103 oident bib1;
1104
1105 if (setnumber >= 0)
1106 sprintf (setstring, "%d", setnumber);
1107 else
1108 sprintf (setstring, "default");
1109
1110 req->referenceId = set_refid (out);
1111
1112#ifdef ASN_COMPILED
1113 req->num_inputResultSetNames = 1;
1114 req->inputResultSetNames = (Z_InternationalString **)
1115 odr_malloc (out, sizeof(*req->inputResultSetNames));
1116 req->inputResultSetNames[0] = odr_strdup (out, setstring);
1117#else
1118 req->inputResultSetNames =
1119 (Z_StringList *)odr_malloc (out, sizeof(*req->inputResultSetNames));
1120 req->inputResultSetNames->num_strings = 1;
1121 req->inputResultSetNames->strings =
1122 (char **)odr_malloc (out, sizeof(*req->inputResultSetNames->strings));
1123 req->inputResultSetNames->strings[0] =
1124 odr_strdup (out, setstring);
1125#endif
1126
1127 if (newset && setnumber >= 0)
1128 sprintf (setstring, "%d", ++setnumber);
1129
1130 req->sortedResultSetName = odr_strdup (out, setstring);
1131
1132 req->sortSequence = sksl;
1133 sksl->num_specs = 0;
1134 sksl->specs = (Z_SortKeySpec **)odr_malloc (out, sizeof(sksl->specs) * 20);
1135
1136 bib1.proto = protocol;
1137 bib1.oclass = CLASS_ATTSET;
1138 bib1.value = VAL_BIB1;
1139 while ((sscanf (arg, "%31s %31s%n", sort_string, sort_flags, &off)) == 2
1140 && off > 1)
1141 {
1142 int i;
1143 char *sort_string_sep;
1144 Z_SortKeySpec *sks = (Z_SortKeySpec *)odr_malloc (out, sizeof(*sks));
1145 Z_SortKey *sk = (Z_SortKey *)odr_malloc (out, sizeof(*sk));
1146
1147 arg += off;
1148 sksl->specs[sksl->num_specs++] = sks;
1149 sks->sortElement = (Z_SortElement *)odr_malloc (out, sizeof(*sks->sortElement));
1150 sks->sortElement->which = Z_SortElement_generic;
1151 sks->sortElement->u.generic = sk;
1152
1153 if ((sort_string_sep = strchr (sort_string, '=')))
1154 {
1155 Z_AttributeElement *el = (Z_AttributeElement *)odr_malloc (out, sizeof(*el));
1156 sk->which = Z_SortKey_sortAttributes;
1157 sk->u.sortAttributes =
1158 (Z_SortAttributes *)odr_malloc (out, sizeof(*sk->u.sortAttributes));
1159 sk->u.sortAttributes->id = oid_ent_to_oid(&bib1, oid);
1160 sk->u.sortAttributes->list =
1161 (Z_AttributeList *)odr_malloc (out, sizeof(*sk->u.sortAttributes->list));
1162 sk->u.sortAttributes->list->num_attributes = 1;
1163 sk->u.sortAttributes->list->attributes =
1164 (Z_AttributeElement **)odr_malloc (out,
1165 sizeof(*sk->u.sortAttributes->list->attributes));
1166 sk->u.sortAttributes->list->attributes[0] = el;
1167 el->attributeSet = 0;
1168 el->attributeType = (int *)odr_malloc (out, sizeof(*el->attributeType));
1169 *el->attributeType = atoi (sort_string);
1170 el->which = Z_AttributeValue_numeric;
1171 el->value.numeric = (int *)odr_malloc (out, sizeof(*el->value.numeric));
1172 *el->value.numeric = atoi (sort_string_sep + 1);
1173 }
1174 else
1175 {
1176 sk->which = Z_SortKey_sortField;
1177 sk->u.sortField = odr_strdup (out, sort_string);
1178 }
1179 sks->sortRelation = (int *)odr_malloc (out, sizeof(*sks->sortRelation));
1180 *sks->sortRelation = Z_SortRelation_ascending;
1181 sks->caseSensitivity = (int *)odr_malloc (out, sizeof(*sks->caseSensitivity));
1182 *sks->caseSensitivity = Z_SortCase_caseSensitive;
1183
1184#ifdef ASN_COMPILED
1185 sks->which = Z_SortKeySpec_null;
1186 sks->u.null = odr_nullval ();
1187#else
1188 sks->missingValueAction = NULL;
1189#endif
1190
1191 for (i = 0; sort_flags[i]; i++)
1192 {
1193 switch (sort_flags[i])
1194 {
1195 case 'a':
1196 case 'A':
1197 case '>':
1198 *sks->sortRelation = Z_SortRelation_descending;
1199 break;
1200 case 'd':
1201 case 'D':
1202 case '<':
1203 *sks->sortRelation = Z_SortRelation_ascending;
1204 break;
1205 case 'i':
1206 case 'I':
1207 *sks->caseSensitivity = Z_SortCase_caseInsensitive;
1208 break;
1209 case 'S':
1210 case 's':
1211 *sks->caseSensitivity = Z_SortCase_caseSensitive;
1212 break;
1213 }
1214 }
1215 }
1216 if (!sksl->num_specs)
1217 {
1218 printf ("Missing sort specifications\n");
1219 return -1;
1220 }
1221 send_apdu(apdu);
1222 return 2;
1223}
1224
1225void display_term(Z_TermInfo *t)
1226{
1227 if (t->term->which == Z_Term_general)
1228 {
1229 printf("%.*s (%d)\n", t->term->u.general->len, t->term->u.general->buf,
1230 t->globalOccurrences ? *t->globalOccurrences : -1);
1231 sprintf(last_scan, "%.*s", t->term->u.general->len,
1232 t->term->u.general->buf);
1233 }
1234 else
1235 printf("Term type not general.\n");
1236}
1237
1238void process_scanResponse(Z_ScanResponse *res)
1239{
1240 int i;
1241 Z_Entry **entries = NULL;
1242 int num_entries = 0;
1243
1244 printf("Received ScanResponse\n");
1245 print_refid (res->referenceId);
1246 printf("%d entries", *res->numberOfEntriesReturned);
1247 if (res->positionOfTerm)
1248 printf (", position=%d", *res->positionOfTerm);
1249 printf ("\n");
1250 if (*res->scanStatus != Z_Scan_success)
1251 printf("Scan returned code %d\n", *res->scanStatus);
1252 if (!res->entries)
1253 return;
1254 if ((entries = res->entries->entries))
1255 num_entries = res->entries->num_entries;
1256 for (i = 0; i < num_entries; i++)
1257 {
1258 int pos_term = res->positionOfTerm ? *res->positionOfTerm : -1;
1259 if (entries[i]->which == Z_Entry_termInfo)
1260 {
1261 printf("%c ", i + 1 == pos_term ? '*' : ' ');
1262 display_term(entries[i]->u.termInfo);
1263 }
1264 else
1265 display_diagrecs(&entries[i]->u.surrogateDiagnostic, 1);
1266 }
1267 if (res->entries->nonsurrogateDiagnostics)
1268 display_diagrecs (res->entries->nonsurrogateDiagnostics,
1269 res->entries->num_nonsurrogateDiagnostics);
1270}
1271
1272void process_sortResponse(Z_SortResponse *res)
1273{
1274 printf("Received SortResponse: status=");
1275 switch (*res->sortStatus)
1276 {
1277 case Z_SortStatus_success:
1278 printf ("success"); break;
1279 case Z_SortStatus_partial_1:
1280 printf ("partial"); break;
1281 case Z_SortStatus_failure:
1282 printf ("failure"); break;
1283 default:
1284 printf ("unknown (%d)", *res->sortStatus);
1285 }
1286 printf ("\n");
1287 print_refid (res->referenceId);
1288#ifdef ASN_COMPILED
1289 if (res->diagnostics)
1290 display_diagrecs(res->diagnostics,
1291 res->num_diagnostics);
1292#else
1293 if (res->diagnostics)
1294 display_diagrecs(res->diagnostics->diagRecs,
1295 res->diagnostics->num_diagRecs);
1296#endif
1297}
1298
1299void process_deleteResultSetResponse (Z_DeleteResultSetResponse *res)
1300{
1301 printf("Got deleteResultSetResponse status=%d\n",
1302 *res->deleteOperationStatus);
1303 if (res->deleteListStatuses)
1304 {
1305 int i;
1306 for (i = 0; i < res->deleteListStatuses->num; i++)
1307 {
1308 printf ("%s status=%d\n", res->deleteListStatuses->elements[i]->id,
1309 *res->deleteListStatuses->elements[i]->status);
1310 }
1311 }
1312}
1313
1314int cmd_sort_generic(char *arg, int newset)
1315{
1316 if (!conn)
1317 {
1318 printf("Session not initialized yet\n");
1319 return 0;
1320 }
1321 if (!ODR_MASK_GET(session->options, Z_Options_sort))
1322 {
1323 printf("Target doesn't support sort\n");
1324 return 0;
1325 }
1326 if (*arg)
1327 {
1328 if (send_sortrequest(arg, newset) < 0)
1329 return 0;
1330 return 2;
1331 }
1332 return 0;
1333}
1334
1335int cmd_sort(char *arg)
1336{
1337 return cmd_sort_generic (arg, 0);
1338}
1339
1340int cmd_sort_newset (char *arg)
1341{
1342 return cmd_sort_generic (arg, 1);
1343}
1344
1345int cmd_scan(char *arg)
1346{
1347 if (!conn)
1348 {
1349 printf("Session not initialized yet\n");
1350 return 0;
1351 }
1352 if (!ODR_MASK_GET(session->options, Z_Options_scan))
1353 {
1354 printf("Target doesn't support scan\n");
1355 return 0;
1356 }
1357 if (*arg)
1358 {
1359 if (send_scanrequest(arg, 1, 20) < 0)
1360 return 0;
1361 }
1362 else
1363 if (send_scanrequest(last_scan, 1, 20) < 0)
1364 return 0;
1365 return 2;
1366}
1367
1368int cmd_schema(char *arg)
1369{
1370 if (!arg || !*arg)
1371 {
1372 schema = VAL_NONE;
1373 return 1;
1374 }
1375 schema = oid_getvalbyname (arg);
1376 if (schema == VAL_NONE)
1377 {
1378 printf ("unknown schema\n");
1379 return 0;
1380 }
1381 return 1;
1382}
1383
1384int cmd_format(char *arg)
1385{
1386 if (!arg || !*arg)
1387 {
1388 printf("Usage: format <recordsyntax>\n");
1389 return 0;
1390 }
1391 recordsyntax = oid_getvalbyname (arg);
1392 if (recordsyntax == VAL_NONE)
1393 {
1394 printf ("unknown record syntax\n");
1395 return 0;
1396 }
1397 return 1;
1398}
1399
1400int cmd_elements(char *arg)
1401{
1402 static Z_ElementSetNames esn;
1403 static char what[100];
1404
1405 if (!arg || !*arg)
1406 {
1407 elementSetNames = 0;
1408 return 1;
1409 }
1410 strcpy(what, arg);
1411 esn.which = Z_ElementSetNames_generic;
1412 esn.u.generic = what;
1413 elementSetNames = &esn;
1414 return 1;
1415}
1416
1417int cmd_attributeset(char *arg)
1418{
1419 char what[100];
1420
1421 if (!arg || !*arg)
1422 {
1423 printf("Usage: attributeset <setname>\n");
1424 return 0;
1425 }
1426 sscanf(arg, "%s", what);
1427 if (p_query_attset (what))
1428 {
1429 printf("Unknown attribute set name\n");
1430 return 0;
1431 }
1432 return 1;
1433}
1434
1435int cmd_querytype (char *arg)
1436{
1437 if (!strcmp (arg, "ccl"))
1438 queryType = QueryType_CCL;
1439 else if (!strcmp (arg, "prefix") || !strcmp(arg, "rpn"))
1440 queryType = QueryType_Prefix;
1441 else
1442 {
1443 printf ("Querytype must be one of:\n");
1444 printf (" prefix - Prefix query\n");
1445 printf (" ccl - CCL query\n");
1446 return 0;
1447 }
1448 return 1;
1449}
1450
1451int cmd_refid (char *arg)
1452{
1453 xfree (refid);
1454 refid = NULL;
1455 if (*arg)
1456 {
1457 refid = (char *) xmalloc (strlen(arg)+1);
1458 strcpy (refid, arg);
1459 }
1460 return 1;
1461}
1462
1463int z_cmd_close(char *arg)
1464{
1465 Z_APDU *apdu;
1466 Z_Close *req;
1467 if (!conn)
1468 return 1;
1469
1470 apdu = zget_APDU(out, Z_APDU_close);
1471 req = apdu->u.close;
1472 *req->closeReason = Z_Close_finished;
1473 send_apdu(apdu);
1474 sent_close = 1;
1475 return 0;
1476}
1477
1478void z_initialize(void)
1479{
1480 nmem_init();
1481 if (!(out = odr_createmem(ODR_ENCODE)) ||
1482 !(in = odr_createmem(ODR_DECODE)) ||
1483 !(print = odr_createmem(ODR_PRINT)))
1484 {
1485 fprintf(stderr, "failed to allocate ODR streams\n");
1486 exit(1);
1487 }
1488 setvbuf(stdout, 0, _IONBF, 0);
1489 if (apdu_file)
1490 odr_setprint(print, apdu_file);
1491
1492 cmd_base("Default");
1493}
1494
1495static int z_getAPDU (Z_APDU **ret_apdu) {
1496 int res;
1497
1498 char *netbuffer= 0;
1499 int netbufferlen = 0;
1500 Z_APDU *apdu;
1501
1502 if ((res = cs_get(conn, &netbuffer, &netbufferlen)) < 0) {
1503 perror("cs_get");
1504 exit(1);
1505 }
1506 if (!res) {
1507 printf("Target closed connection.\n");
1508 exit(1);
1509 }
1510 odr_reset(in); /* release APDU from last round */
1511 record_last = 0;
1512 odr_setbuf(in, netbuffer, res, 0);
1513 /* johnmcp */
1514 if (!z_APDU(in, &apdu, 0, 0))
1515 {
1516 odr_perror(in, "Decoding incoming APDU");
1517 fprintf(stderr, "[Near %d]\n", odr_offset(in));
1518 fprintf(stderr, "Packet dump:\n---------\n");
1519 odr_dumpBER(stderr, netbuffer, res);
1520 fprintf(stderr, "---------\n");
1521 if (apdu_file)
1522 z_APDU(print, &apdu, 0, 0);
1523 exit(1);
1524 }
1525 if (apdu_file && !z_APDU(print, &apdu, 0, 0))
1526 {
1527 odr_perror(print, "Failed to print incoming APDU");
1528 odr_reset(print);
1529 return -1; /* was continue */
1530 }
1531 (*ret_apdu)=apdu;
1532 return 0;
1533}
1534
1535
1536/* returns number found, arg is query string */
1537int z_cmd_dosearch(char *arg)
1538{
1539 Z_APDU *apdu;
1540 int matching;
1541 int ret_val;
1542 ret_val=send_searchRequest(arg);
1543 if (ret_val==-1) {
1544 /* prefix query error */
1545 return (-1);
1546 }
1547 z_getAPDU(&apdu);
1548 /* check return value??? */
1549 if (apdu->which != Z_APDU_searchResponse)
1550 {
1551 printf("sendsearchRequest() was not replied with a searchResponse!\n");
1552 return (-2);
1553 }
1554 /* let's keep going anyway... */
1555 matching=process_searchResponse(apdu->u.searchResponse);
1556 /* this assumes we want to take action on failure (-1) here rather than
1557 whereever we were called from */
1558 return (matching);
1559}
1560
1561/* src must be NULL-terminated */
1562static char *safeappendstr(char *dest, size_t *allocsize,
1563 size_t *offset, char *src) {
1564 /* allocsize is the amount of space currently allocated to dest,
1565 offset is how far into dest we want to append src */
1566 if (*offset + strlen(src) >= *allocsize) {
1567 *allocsize+=strlen(src)+64; /* add some extra space to save on reallocs */
1568 if ((dest=realloc(dest,*allocsize))==NULL) {
1569 fprintf(stderr, "malloc failed while decoding marc record.\n");
1570 return (NULL);
1571 }
1572 }
1573 strcpy(dest+(*offset), src);
1574 *offset+=strlen(src);
1575 return (dest);
1576}
1577
1578static char *getmarcfields(Z_DatabaseRecord *p, int titleonly) {
1579 /* this code is based on marc_display(), with a couple of lines taken from
1580 display_record() in the original client. */
1581 /* if titleonly is non-zero, we only get a (the?) title field, otherwise
1582 return the whole thing */
1583 const char *buf=(char *)p->u.octet_aligned->buf;
1584 char *title; /* our string to return */
1585 int title_maxlen=0; /* amount of space currently allocated */
1586 int title_curlen=0; /* amount of space actually used */
1587 int entry_p;
1588 int record_length;
1589 int indicator_length;
1590 int identifier_length;
1591 int base_address;
1592 int length_data_entry;
1593 int length_starting;
1594 int length_implementation;
1595 FILE *outf;
1596
1597 /* if (!outf) */
1598 outf = stdout;
1599
1600 /* initialise our title. Start with 64 chars */
1601 title_maxlen=64;
1602 if((title=malloc(title_maxlen))==NULL) {
1603 /* not quite sure where stderr will be going, but.... */
1604 fprintf(stderr,"Malloc failed while decoding marc record\n");
1605 return NULL;
1606 }
1607
1608 if (!titleonly) {
1609 strcpy(title,"<table border=1>\n");
1610 title_curlen=strlen(title);
1611 }
1612 else title_curlen=0;
1613
1614 record_length = atoi_n (buf, 5);
1615 if (record_length < 25)
1616 return (NULL); /* -1 */
1617 if (isdigit(buf[10]))
1618 indicator_length = atoi_n (buf+10, 1);
1619 else
1620 indicator_length = 2;
1621 if (isdigit(buf[11]))
1622 identifier_length = atoi_n (buf+11, 1);
1623 else
1624 identifier_length = 2;
1625 base_address = atoi_n (buf+12, 4);
1626
1627 length_data_entry = atoi_n (buf+20, 1);
1628 length_starting = atoi_n (buf+21, 1);
1629 length_implementation = atoi_n (buf+22, 1);
1630
1631 if (0) /* debug */
1632 {
1633 fprintf (outf, "Record length %5d\n", record_length);
1634 fprintf (outf, "Indicator length %5d\n", indicator_length);
1635 fprintf (outf, "Identifier length %5d\n", identifier_length);
1636 fprintf (outf, "Base address %5d\n", base_address);
1637 fprintf (outf, "Length data entry %5d\n", length_data_entry);
1638 fprintf (outf, "Length starting %5d\n", length_starting);
1639 fprintf (outf, "Length implementation %5d\n", length_implementation);
1640 }
1641 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
1642 {
1643 entry_p += 3+length_data_entry+length_starting;
1644 if (entry_p >= record_length)
1645 return (NULL); /* -1 */
1646 }
1647 base_address = entry_p+1;
1648 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
1649 {
1650 int data_length;
1651 int data_offset;
1652 int end_offset;
1653 int i /*, j*/ ;
1654 int startofstring;
1655 int whichtag;
1656 short int abbrtitle=0;
1657 char tag[4];
1658 memcpy (tag, buf+entry_p, 3);
1659 entry_p += 3;
1660 tag[3] = '\0';
1661 whichtag=atoi(tag);
1662 if (0) /* debug */
1663 fprintf (outf, "Tag: ");
1664 /* johnmcp
1665 Relevant tags (for "main entry") - assume only one of these is set,
1666 as we will only return the first one found.
1667 100=personal name
1668 110=corporate name
1669 111=meeting name
1670 130=uniform title
1671 subfields: $a=personal name, $c=title/other, $d=date
1672
1673 210=Abbreviated Title
1674 222=Key title
1675 240=uniform title
1676 243=collective uniform title
1677 245=title statement
1678 246=varying form of title
1679 247=former title or title variations
1680 subfields: $a=abbrev. title $b=qualifying info $2=source
1681 . $6=linkage $8=link field and sequence number.
1682 */
1683 /*fprintf (outf, "%s ", tag); */
1684 data_length = atoi_n (buf+entry_p, length_data_entry);
1685 entry_p += length_data_entry;
1686 data_offset = atoi_n (buf+entry_p, length_starting);
1687 entry_p += length_starting;
1688 i = data_offset + base_address;
1689 end_offset = i+data_length-1;
1690
1691 if (0) /* debug */
1692 fprintf (outf, " Ind: ");
1693
1694 /* memcmp (tag,"00",2) is true, then we DON'T have a control tag
1695 ie less than 10. */
1696 /*if (memcmp (tag, "00", 2) && indicator_length)
1697 {
1698 for (j = 0; j<indicator_length; j++)
1699 fprintf (outf, "%c", buf[i++]);
1700 }
1701 */
1702 if (whichtag>=10) i+=indicator_length;
1703 /* the control fields (<10) don't have leading chars. */
1704
1705
1706 if (0) /* debug */
1707 fprintf (outf, " Fields: ");
1708
1709 /* If we only want the title, then skip other fields */
1710 if (titleonly &&(whichtag<200||whichtag>249)) {
1711 /* skip this record */
1712 continue;
1713 i=end_offset;
1714 }
1715
1716 /* either titleonly is 0, or titleonly is 1 and whichtag is between
1717 200 and 249... */
1718 if (!titleonly) {
1719 /* This should probably be read in from a separate file.
1720 This is also hard-coded for USMARC/MARC21 fieldnames!!! */
1721
1722 /* print out what kind of tag this is */
1723 char *tagname;
1724 char *field_control1="<tr><td>Marc Control Number:</td><td>";
1725 char *field_control3="<tr><td>Marc Organisation Code:</td><td>";
1726 char *field_control5="<tr><td>Marc record Date Info.:</td><td>";
1727 char *field_control8="<tr><td>Control Field (Marc info):</td><td>";
1728 char *field_loc_nr="<tr><td>Lib. of Congress control #:</td><td>";
1729 char *field_issn="<tr><td>ISSN Number:</td><td>";
1730 char *field_catalog="<tr><td>Catalog agency:</td><td>";
1731 char *field_lang="<tr><td>3-letter language code(s):</td><td>";
1732 char *field_areacode="<tr><td>Geographic Area code:</td><td>";
1733 char *field_cn_loc="<tr><td>Lib. of Congress Call #:</td><td>";
1734 char *field_cn_dewdec="<tr><td>Dewey Decimal Call #:</td><td>";
1735 char *field_cn_other="<tr><td>Other Classification Info.:</td><td>";
1736 char *field_cn_gd="<tr><td>Govt. Document Call #:</td><td>";
1737 char *field_personalname="<tr><td>Personal Name:</td><td>";
1738 char *field_meetingname="<tr><td>Meeting Name:</td><td>";
1739 char *field_maintitle="<tr><td>Title:</td><td>";
1740 char *field_edition="<tr><td><Edition Information:</td><td>";
1741 char *field_publication="<tr><td>Publication Info.:</td><td>";
1742 char *field_physdesc="<tr><td>Physical Description:</td><td>";
1743 char *field_series_title="<tr><td>Series Title:</td><td>";
1744 char *field_series_statement="<tr><td>Series Statement:</td><td>";
1745 char *field_note_general="<tr><td>Note:</td><td>";
1746 char *field_note_bib="<tr><td>Bibliographic Note:</td><td>";
1747 char *field_note_summary="<tr><td>Summary Note:</td><td>";
1748 char *field_sub_note="<tr><td>Subject Notes:</td><td>";
1749 char *field_sub_topic="<tr><td>Subject - Topic:</td><td>";
1750 char *field_sub_geog="<tr><td>Subject - Location:</td><td>";
1751 char *field_added_persname="<tr><td>Author Note - Name:</td><td>";
1752 char *field_added_corpname="<tr><td>Author - Organisation:</td><td>";
1753 char *field_uniform_title="<tr><td>Extra Title Information:</td><td>";
1754 char *field_host_item="<tr><td>In:</td><td>";
1755 char *field_series_corpname="<tr><td>Series - Organisation:</td><td>";
1756 /*char *field_url="<tr><td>Electronic Access</td><td><a href=\"";*/
1757 char *field_url="<tr><td>Electronic Access</td><td>";
1758 /*char *field_other="<tr><td>(other field):</td><td>";*/
1759 char tag_num[100];
1760 switch (whichtag) {
1761 case (1): {tagname=field_control1;break;}
1762 case (3): {tagname=field_control3;break;}
1763 case (5): {tagname=field_control5;break;}
1764 case (8): {tagname=field_control8;break;}
1765 case (10): {tagname=field_loc_nr;break;}
1766 case (20): {tagname=field_issn;break;}
1767 case (40): {tagname=field_catalog;break;}
1768 case (41): {tagname=field_lang;break;}
1769 case (43): {tagname=field_areacode;break;}
1770 case (50): {tagname=field_cn_loc;break;}
1771 case (82): {tagname=field_cn_dewdec;break;}
1772 case (84): {tagname=field_cn_other;break;}
1773 case (86): {tagname=field_cn_gd;break;}
1774 case (100): {tagname=field_personalname;break;}
1775 case (111): {tagname=field_meetingname;break;}
1776 case (245): {tagname=field_maintitle;break;}
1777 case (250): {tagname=field_edition;break;}
1778 case (260): {tagname=field_publication;break;}
1779 case (300): {tagname=field_physdesc;break;}
1780 case (440): {tagname=field_series_title;break;}
1781 case (490): {tagname=field_series_statement;break;}
1782 case (500): {tagname=field_note_general;break;}
1783 case (504): {tagname=field_note_bib;break;}
1784 case (520): {tagname=field_note_summary;break;}
1785 case (630): {tagname=field_sub_note;break;}
1786 case (650): {tagname=field_sub_topic;break;}
1787 case (651): {tagname=field_sub_geog;break;}
1788 case (700): {tagname=field_added_persname;break;}
1789 case (710): {tagname=field_added_corpname;break;}
1790 case (730): {tagname=field_uniform_title;break;}
1791 case (773): {tagname=field_host_item;break;}
1792 case (810): {tagname=field_series_corpname;break;}
1793 case (856): {tagname=field_url;break;}
1794 default:
1795 if (whichtag>=90&&whichtag<=99)
1796 tagname="<tr><td>(obsolete field) Call #:</td><td>";
1797 else {
1798 /*tagname=field_other;*/
1799
1800 /*.*********** Following line "causes" (ie exposes) a seg fault
1801 in realloc(title,...). What is causing this????.
1802 ANSWER: The trailing '\0' needs to be explicit :-) */
1803 sprintf(tag_num,"<tr><td>(field %d)</td><td>\n\0",whichtag);
1804 tagname=tag_num;
1805 }
1806 }
1807
1808 /* add the field type */
1809 title=safeappendstr(title, &title_maxlen, &title_curlen, tagname);
1810 }
1811
1812 /* go through current field in current record */
1813 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
1814 {
1815 /* this loop goes through byte by byte, to find end-of-field or
1816 end-of-record separator tags */
1817
1818 /* if (memcmp (tag, "00", 2) && identifier_length)*/
1819 if ( ((titleonly==1&&whichtag==245)||(titleonly==0))
1820 && identifier_length)
1821 {
1822 if (buf[i]==ISO2709_IDFS) {
1823 /* this implies sub-fields for this field */
1824 /* skip sub-field tag, but wrap $a sub-field with <b> & </b>
1825 for HTML if titleonly==1 */
1826 if (buf[i+1]=='a' && titleonly) {
1827 abbrtitle=1;
1828 title=safeappendstr(title,&title_maxlen,&title_curlen,"<b>");
1829 }
1830 i+=identifier_length;
1831 }
1832 /* find end of this (sub-)field */
1833 startofstring=i;
1834 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
1835 buf[i] != ISO2709_FS && i < end_offset)
1836 i++;
1837 /*fprintf (outf, "%c", buf[i++]);*/
1838
1839 /* this only happens the first time around */
1840 if (i==startofstring) continue;
1841
1842 /* now put from $startofstring$ until $i$ into our
1843 string to return */
1844
1845 if (title_curlen+(i-startofstring)>=title_maxlen) {
1846 /* we need to make more room - add max(64,needed) bytes */
1847 if (title_curlen+(i-startofstring)-title_maxlen>63)
1848 title_maxlen+=(i-startofstring)+1;/*+1 for trailing \0 */
1849 else
1850 title_maxlen+=64;
1851 if ((title=realloc(title,title_maxlen))==NULL) {
1852 fprintf(stderr,"malloc failed decoding marc record\n");
1853 return (NULL);
1854 }
1855 }
1856
1857 strncpy(title+title_curlen,buf+startofstring,i-startofstring);
1858 title_curlen+=(i-startofstring);
1859 *(title+title_curlen)='\0';
1860 /* overwrite ISO2709_?S with \0 */
1861 /* *(title+title_curlen+i-startofstring)='\0';*/
1862 /*safeappendstr(title,&title_maxlen,
1863 &title_curlen,buf+startofstring);*/
1864
1865 /* if 'main' title, close HTML </B> tag */
1866 if (abbrtitle) {
1867 title=safeappendstr(title,&title_maxlen,&title_curlen,"</b>");
1868 abbrtitle=0;
1869 }
1870 /* end of this marc sub--field
1871 buf[i]==ISO2709_RS if end of record.
1872 buf[i]==ISO2709_FS if end of field,
1873 buf[i]==ISO2709_IDFS if end of sub-field. */
1874 if (titleonly==0) {
1875 if (buf[i]==ISO2709_IDFS) {
1876 /* there is a following sub-field, so only add whitespace */
1877 title=safeappendstr(title,&title_maxlen,&title_curlen," ");
1878 }
1879 else {
1880 /* end of record, so close HTML table row */
1881#if 0
1882 if (whichtag==856) /* special case: this is a url! */
1883 title=safeappendstr(title,&title_maxlen,&title_curlen,
1884 "\">Uniform Resource Locator</a>");
1885#endif
1886 title=safeappendstr(title, &title_maxlen, &title_curlen,
1887 "</td></tr>\n");
1888 }
1889 } /* end of if (titleonly==0) */
1890 } /* end of if ( ((titleonly==1&&....... */
1891 else { /* whichtag not matched (if titleonly) */
1892 /*fprintf (outf, "%c", buf[i++]);*/
1893 /* skip this char for now - should ideally skip whole field */
1894 i++;
1895 }
1896 } /* end of while loop - at end of field or record */
1897 /*fprintf (outf, "\n");*/
1898 /*if (i < end_offset)
1899 fprintf (outf, "-- separator but not at end of field\n");
1900 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
1901 fprintf (outf, "-- no separator at end of field\n");
1902 */
1903 }
1904
1905 /* at end of whole record. */
1906 if (!titleonly)
1907 title=safeappendstr(title, &title_maxlen, &title_curlen, "</table>\n");
1908 return (title);
1909
1910}
1911static char *getrecordtitle(Z_DatabaseRecord *record) {
1912 return(getmarcfields(record,1));
1913}
1914
1915char *z_getfullRecord(int start) {
1916 Z_APDU *apdu;
1917 Z_DatabaseRecord *record;
1918 char *fullrecord;
1919
1920 fullrecord=NULL;
1921 z_send_getbriefrecords(start,1,1); /* for now, use getbriefrecords */
1922 z_getAPDU(&apdu);
1923
1924 if (apdu->which != Z_APDU_presentResponse) {
1925 /* out-of-order packets.... */
1926 fprintf(stderr,"Not a present response to present request\n");
1927 return NULL;
1928 }
1929
1930 /* just do some double checking */
1931 if (*apdu->u.presentResponse->numberOfRecordsReturned!=1 ||
1932 !apdu->u.presentResponse->records ) {
1933 /* something bad has happened... johnmcp */
1934 fprintf (stderr,"Error occured in yaz while getting record (GSDL)\n");
1935 }
1936
1937 switch (apdu->u.presentResponse->records->which) {
1938 case Z_Records_DBOSD: break; /* do nothing - this is a record */
1939
1940 /* otherwise we got a diagnostic message... */
1941 case Z_Records_NSD:
1942 switch (apdu->u.presentResponse->records->u.nonSurrogateDiagnostic->which){
1943 /* these are both represented as char* in yaz, so either is OK */
1944 /* case Z_DefaultDiagForm_v2Addinfo:
1945 case Z_DefaultDiagForm_v3Addinfo: --wrong names*/
1946 case Z_DiagnosticFormat_s_defaultDiagRec:
1947 case Z_DiagnosticFormat_s_explicitDiagnostic:
1948 return apdu->u.presentResponse->records->u.nonSurrogateDiagnostic
1949 ->u.v2Addinfo; /* return the error message */
1950 default: ; /* this should happen for v3 of the spec... */
1951 }
1952 case Z_Records_multipleNSD: ; /* should handle one day... */
1953 }
1954
1955 record=apdu->u.presentResponse->records->u.databaseOrSurDiagnostics->
1956 records[0]->u.databaseRecord;
1957
1958 return(getmarcfields(record,0));
1959}
1960
1961char **z_getrecordTitles(/*int resultset,*/ int starting, int howmany) {
1962 Z_APDU *apdu;
1963 char **titles;
1964 /* titles will be an array of strings. The first element will really
1965 be an int, saying how many strings follow. Ie 1st string in titles[1] */
1966 int count;
1967 int i;
1968
1969 titles=NULL;
1970
1971 /* WE SHOULD SET THE RECORD FORMAT SOMEWHERE..... USMARC (default)
1972 but may also want SUTRS support. */
1973
1974 /* sends a presentRequest - we need to know the set number - johnmcp */
1975 z_send_getbriefrecords(starting, 1, howmany);
1976 /* CHECK RETURN VALUE (currently only 0) */
1977
1978
1979 z_getAPDU(&apdu);
1980 if (apdu->which != Z_APDU_presentResponse) {
1981 /* we got out-of-sync.... */
1982 fprintf(stderr,"Not a present response to present request\n");
1983 return NULL;
1984 }
1985
1986 print_refid (apdu->u.presentResponse->referenceId);
1987 count=*apdu->u.presentResponse->numberOfRecordsReturned;
1988 setno += count;
1989 if (apdu->u.presentResponse->records) {
1990 /* extract the titles from each record, and return it as an array of
1991 strings */
1992 if (count==1 &&
1993 apdu->u.presentResponse->records->which!=Z_Records_DBOSD) {
1994 /* apdu->u.presentResponse->records->which gives a type:
1995 1=databaseOrSurDiagnostics | 2=nonSurrogateDiagnostic |
1996 3=multipleNonSurDiagnostics.
1997 Type 1 implies it is a database record. FROM z-core.h,
1998 NOT prt-proto.h!!!!! */
1999
2000 /* for type 2:
2001 apdu->u.presentResponse->records->u.nonSurrogateDiagnostic->which:
2002 1=v2Addinfo | 2=v3Addinfo, and u.v[23]Addinfo is a (char *).
2003
2004 */
2005 titles=malloc(sizeof(char *));
2006 titles[0]=(char *)0;
2007 /* could put error message and titles[1], and set titles[0] to -1. */
2008
2009
2010 }
2011 else /* more than 1 rec returned, so ?has? to be db records (dblcheck!!)*/
2012 {
2013 titles=malloc(sizeof(char *)*count + 1);
2014 /* check malloc succeeded... */
2015 titles[0]=(char *)count;
2016 for (i=1;i<=count;i++) {
2017 titles[i]=getrecordtitle(apdu->u.presentResponse->records->
2018 u.databaseOrSurDiagnostics->records[i-1]->
2019 u.databaseRecord);
2020 }
2021 }
2022 }
2023 else {
2024 titles=malloc(sizeof(char *));
2025 titles[0]=(char *)0;
2026 }
2027 /* printf ("nextResultSetPosition = %d\n",
2028 *apdu->u.presentResponse->nextResultSetPosition); */
2029 return (titles);
2030}
2031
2032
2033int z_getnextAPDU()
2034{
2035 Z_APDU *apdu;
2036 apdu=NULL;
2037
2038 z_getAPDU(&apdu);
2039
2040 switch(apdu->which)
2041 {
2042 case Z_APDU_initResponse:
2043 /* save session parameters for later use */
2044 session_mem = odr_extract_mem(in);
2045 session=apdu->u.initResponse;
2046 /*process_initResponse();*/
2047 break;
2048 case Z_APDU_searchResponse:
2049 process_searchResponse(apdu->u.searchResponse);
2050 break;
2051 case Z_APDU_scanResponse:
2052 process_scanResponse(apdu->u.scanResponse);
2053 break;
2054 case Z_APDU_presentResponse:
2055 print_refid (apdu->u.presentResponse->referenceId);
2056 setno +=
2057 *apdu->u.presentResponse->numberOfRecordsReturned;
2058 if (apdu->u.presentResponse->records)
2059 display_records(apdu->u.presentResponse->records);
2060 else
2061 printf("No records.\n");
2062 printf ("nextResultSetPosition = %d\n",
2063 *apdu->u.presentResponse->nextResultSetPosition);
2064 break;
2065 case Z_APDU_sortResponse:
2066 process_sortResponse(apdu->u.sortResponse);
2067 break;
2068 case Z_APDU_extendedServicesResponse:
2069 printf("Got extended services response\n");
2070 process_ESResponse(apdu->u.extendedServicesResponse);
2071 break;
2072 case Z_APDU_close:
2073 printf("Target has closed the association.\n");
2074 process_close(apdu->u.close);
2075 break;
2076 case Z_APDU_resourceControlRequest:
2077 process_resourceControlRequest
2078 (apdu->u.resourceControlRequest);
2079 break;
2080 case Z_APDU_deleteResultSetResponse:
2081 process_deleteResultSetResponse(apdu->u.
2082 deleteResultSetResponse);
2083 break;
2084 default:
2085 printf("Received unknown APDU type (%d).\n",
2086 apdu->which);
2087 exit(1);
2088 }
2089
2090 /*while (conn && cs_more(conn));*/
2091 return 0;
2092}
Note: See TracBrowser for help on using the repository browser.