X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=zlayer%2Fzaccess-yaz.c;h=4bd4d23a6173cbea5ffe21b66ce5f62c7fe0bca2;hb=7b58e36bc4c5a57dec46408bbfb3707638dd967a;hp=f8615d9dd7623f65cb152acce7dc18ddc9b1e4cd;hpb=f6164c93ea8b575c43586bd08b34122b37f5f7af;p=egate.git diff --git a/zlayer/zaccess-yaz.c b/zlayer/zaccess-yaz.c index f8615d9..4bd4d23 100644 --- a/zlayer/zaccess-yaz.c +++ b/zlayer/zaccess-yaz.c @@ -1,17 +1,89 @@ /* + * Copyright (c) 1995, the EUROPAGATE consortium (see below). + * + * The EUROPAGATE consortium members are: + * + * University College Dublin + * Danmarks Teknologiske Videnscenter + * An Chomhairle Leabharlanna + * Consejo Superior de Investigaciones Cientificas + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation, in whole or in part, for any purpose, is hereby granted, + * provided that: + * + * 1. This copyright and permission notice appear in all copies of the + * software and its documentation. Notices of copyright or attribution + * which appear at the beginning of any file must remain unchanged. + * + * 2. The names of EUROPAGATE or the project partners may not be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * 3. Users of this software (implementors and gateway operators) agree to + * inform the EUROPAGATE consortium of their use of the software. This + * information will be used to evaluate the EUROPAGATE project and the + * software, and to plan further developments. The consortium may use + * the information in later publications. + * + * 4. Users of this software agree to make their best efforts, when + * documenting their use of the software, to acknowledge the EUROPAGATE + * consortium, and the role played by the software in their work. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE + * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF + * ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND + * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* * Europagate, 1995 * * Z39.50 API for the Email gateway - YAZ version * * $Log: zaccess-yaz.c,v $ - * Revision 1.1 1995/04/17 11:26:53 quinn - * Added YAZ version of zaccess + * Revision 1.11 1995/07/03 08:20:50 adam + * Old directory. To be deleted. + * + * Revision 1.10 1995/05/16 09:41:46 adam + * LICENSE. Uses new versions of odr_{set,get}buf. + * + * Revision 1.9 1995/05/03 10:15:43 quinn + * Fixed bug in the get_record loop - crashed when diagrec was received. + * + * Revision 1.8 1995/04/28 14:18:38 quinn + * *** empty log message *** + * + * Revision 1.7 1995/04/21 16:29:32 quinn + * Fixed bugs. * + * Revision 1.6 1995/04/21 12:58:36 adam + * Bug fix. + * + * Revision 1.5 1995/04/20 15:25:32 quinn + * Asynch. API + * + * Revision 1.4 1995/04/19 16:02:28 adam + * Record type hack. + * + * Revision 1.3 1995/04/19 12:55:15 quinn + * Added auth. + * + * Revision 1.2 1995/04/19 09:24:02 quinn + * Fixed bug in zass_open - variable initialized after use + * + * Revision 1.1 1995/04/17 11:26:53 quinn + * Added YAZ version of zaccess * */ /* - * Interface to the Z39.50 toolkit. + * Interface to the YAZ Z39.50 toolkit. */ #include @@ -36,14 +108,14 @@ struct zass /* Z-assoc */ ODR encode; ODR decode; int fd; /* low-level socket (for select only) */ + int nonblocking; int maxrecordsize; int preferredmessagesize; - char *outbuf; /* intermediary buffer */ char *inbuf; int inbuflen; }; -static Z_APDU *get_apdu(struct zass *z) +static Z_APDU *get_apdu(struct zass *z, int *complete) { int res; Z_APDU *ap; @@ -51,16 +123,28 @@ static Z_APDU *get_apdu(struct zass *z) if ((res = cs_get(z->ass, &z->inbuf, &z->inbuflen)) <= 0) { gw_log(GW_LOG_WARN, ZASS_TYPE, "cs_get failed"); + if (complete) + *complete = 1; return 0; } + else if (res == 1) + { + if (complete) + *complete = 0; + return 0; + } odr_reset(z->decode); - odr_setbuf(z->decode, z->inbuf, res); + odr_setbuf(z->decode, z->inbuf, res, 0); if (!z_APDU(z->decode, &ap, 0)) { gw_log(GW_LOG_WARN, ZASS_TYPE, "decode: %s", odr_errlist[odr_geterror(z->decode)]); + if (complete) + *complete = 0; return 0; } + if (complete) + *complete = 1; return ap; } @@ -74,54 +158,55 @@ static int send_apdu(struct zass *z, Z_APDU *a) gw_log(GW_LOG_FATAL, ZASS_TYPE, "encoding initreq"); return -1; } - buf = odr_getbuf(z->encode, &len); + buf = odr_getbuf(z->encode, &len, NULL); if (cs_put(z->ass, buf, len) < 0) { gw_log(GW_LOG_FATAL, ZASS_TYPE, "cs_put"); return -1; } - odr_reset(z->encode); + odr_reset(z->encode); /* release odr_allocated structures */ return 0; } -static int send_initreq(struct zass *p) +static int send_initreq(struct zass *p, char *auth) { - Z_APDU a; - Z_InitRequest init; - Odr_bitmask options, protocolVersion; + Z_APDU *apdu; + Z_InitRequest *req; char name[512]; + Z_IdAuthentication idauth; - a.which = Z_APDU_initRequest; - a.u.initRequest = &init; - init.referenceId = 0; - init.options = &options; - ODR_MASK_ZERO(&options); - ODR_MASK_SET(&options, Z_Options_search); - ODR_MASK_SET(&options, Z_Options_present); - ODR_MASK_SET(&options, Z_Options_delSet); - init.protocolVersion = &protocolVersion; - ODR_MASK_ZERO(&protocolVersion); - ODR_MASK_SET(&protocolVersion, Z_ProtocolVersion_1); - ODR_MASK_SET(&protocolVersion, Z_ProtocolVersion_2); - init.preferredMessageSize = &p->preferredmessagesize; - init.maximumRecordSize = &p->maxrecordsize; - init.idAuthentication = 0; - init.implementationId = ZASS_ID; + apdu = zget_APDU (p->encode, Z_APDU_initRequest); + req = apdu->u.initRequest; + req->preferredMessageSize = &p->preferredmessagesize; + req->maximumRecordSize = &p->maxrecordsize; + + if (auth) + { + req->idAuthentication = &idauth; + idauth.which = Z_IdAuthentication_open; + idauth.u.open = auth; + } + else + req->idAuthentication = 0; sprintf(name, "%s (YAZ protocol layer)", ZASS_NAME); - init.implementationName = name; - init.implementationVersion = ZASS_VERSION; - init.userInformationField = 0; - if (send_apdu(p, &a) < 0) + req->implementationName = name; + req->implementationVersion = ZASS_VERSION; + if (send_apdu(p, apdu) < 0) return -1; return 0; } -static int receive_initres(struct zass *p) +int zass_fileno(ZASS a) +{ + return a->fd; +} + +int zass_openresult(ZASS p, int *complete) { Z_APDU *ap; Z_InitResponse *res; - if (!(ap = get_apdu(p))) + if (!(ap = get_apdu(p, complete))) return -1; if (ap->which != Z_APDU_initResponse) { @@ -149,7 +234,7 @@ static int receive_initres(struct zass *p) return 0; } -ZASS zass_open(char *host, int port) +ZASS zass_open(char *host, int port, int *complete, char *auth) { struct zass *p; char addstr[512]; @@ -160,6 +245,13 @@ ZASS zass_open(char *host, int port) gw_log(GW_LOG_FATAL|GW_LOG_ERRNO, ZASS_TYPE, "malloc"); return 0; } + if (complete) + { + *complete = 1; + p->nonblocking = 1; + } + else + p->nonblocking = 0; if (!(p->encode = odr_createmem(ODR_ENCODE)) || !(p->decode = odr_createmem(ODR_DECODE))) { @@ -168,17 +260,13 @@ ZASS zass_open(char *host, int port) } p->maxrecordsize = ZASS_MAXRECORDSIZE; p->preferredmessagesize = ZASS_PREFERREDMESSAGESIZE; - if (!(p->outbuf = malloc(p->maxrecordsize + 1024))) - { - gw_log(GW_LOG_FATAL|GW_LOG_ERRNO, ZASS_TYPE, "malloc"); - return 0; - } - odr_setbuf(p->encode, p->outbuf, p->maxrecordsize + 1024); if (!(p->ass = cs_create(tcpip_type, 1, CS_Z3950))) { gw_log(GW_LOG_FATAL|GW_LOG_ERRNO, ZASS_TYPE, "cs_create"); return 0; } + p->inbuf = 0; + p->inbuflen = 0; sprintf(addstr, "%s:%d", host, port); if (!(address = tcpip_strtoaddr(addstr))) { @@ -192,18 +280,25 @@ ZASS zass_open(char *host, int port) gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to connect to %s", addstr); return 0; } - gw_log(ZASS_DEBUG, ZASS_TYPE, "connected ok"); - if (send_initreq(p) < 0 || receive_initres(p) < 0) + gw_log(ZASS_DEBUG, ZASS_TYPE, "connected ok... initializing"); + if (send_initreq(p, auth) < 0) { - gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to initialize"); + gw_log(GW_LOG_FATAL, ZASS_TYPE, "Failed to send init"); return 0; } - gw_log(ZASS_DEBUG, ZASS_TYPE, "Sent init request"); - p->inbuf = 0; - p->inbuflen = 0; - return p; + if (p->nonblocking) + { + *complete = 0; + return p; + } + if (zass_openresult(p, complete) < 0) + return 0; + return p; /* all done */ } +/* + * Convert the egate (ccl2rpn) version of RPN to YAZ RPN. + */ static Z_RPNStructure *rpn2rpn(ODR o, struct ccl_rpn_node *q) { Z_RPNStructure *r = odr_malloc(o, sizeof(*r)); @@ -238,8 +333,15 @@ static Z_RPNStructure *rpn2rpn(ODR o, struct ccl_rpn_node *q) odr_malloc(o, sizeof(*a)); a->attributeType = odr_malloc(o, sizeof(int)); *a->attributeType = i->type; - a->attributeValue = odr_malloc(o, sizeof(*a)); +#ifdef Z_95 + a->attributeSet = 0; + a->which = Z_AttributeValue_numeric; + a->value.numeric = odr_malloc(o, sizeof(*a->value.numeric)); + *a->value.numeric = i->value; +#else + a->attributeValue = odr_malloc(o, sizeof(*a->attributeValue)); *a->attributeValue = i->value; +#endif } return r; case CCL_RPN_SET: @@ -247,7 +349,7 @@ static Z_RPNStructure *rpn2rpn(ODR o, struct ccl_rpn_node *q) r->u.simple = odr_malloc(o, sizeof(Z_Operand)); r->u.simple->which = Z_Operand_resultSetId; r->u.simple->u.resultSetId = odr_malloc(o, len = - strlen(q->u.setname)); + strlen(q->u.setname) + 1); memcpy(r->u.simple->u.resultSetId, q->u.setname, len); return r; case CCL_RPN_AND: case CCL_RPN_OR: case CCL_RPN_NOT: @@ -266,13 +368,13 @@ static Z_RPNStructure *rpn2rpn(ODR o, struct ccl_rpn_node *q) } } -static const struct zass_searchent *search_result(ZASS a) +const struct zass_searchent *zass_searchresult(ZASS a, int *complete) { static struct zass_searchent r; Z_APDU *apdu; Z_SearchResponse *res; - if (!(apdu = get_apdu(a))) + if (!(apdu = get_apdu(a, complete))) return 0; if (apdu->which != Z_APDU_searchResponse) { @@ -295,6 +397,24 @@ static const struct zass_searchent *search_result(ZASS a) oident *id; Z_DiagRec *dr = res->records->u.nonSurrogateDiagnostic; +#ifdef Z_95 + if (dr->which != Z_DiagRec_defaultFormat || + !(id = oid_getentbyoid + (dr->u.defaultFormat->diagnosticSetId)) || + id->class != CLASS_DIAGSET || + id->value != VAL_BIB1) + gw_log(GW_LOG_WARN, ZASS_TYPE, + "Missing or unknown diagset - ignoring error!"); + else + { + r.errcode = *dr->u.defaultFormat->condition; + if (dr->u.defaultFormat->addinfo) + { + strncpy(r.errstring, dr->u.defaultFormat->addinfo, 512); + r.errstring[511] = '\0'; + } + } +#else if (!(id = oid_getentbyoid(dr->diagnosticSetId)) || id->class != CLASS_DIAGSET || id->value != VAL_BIB1) gw_log(GW_LOG_WARN, ZASS_TYPE, @@ -308,18 +428,19 @@ static const struct zass_searchent *search_result(ZASS a) r.errstring[511] = '\0'; } } +#endif } } return &r; } const struct zass_searchent *zass_search(ZASS a, struct ccl_rpn_node *query, - char *resname, char *databases) + char *resname, char *databases, int *complete) { Z_Query q; Z_RPNQuery rpnq; - Z_APDU apdu; - Z_SearchRequest req; + Z_APDU *apdu; + Z_SearchRequest *req; oident bib1; int smallSetUpperBound = 0; int largeSetLowerBound = 1; @@ -327,17 +448,17 @@ const struct zass_searchent *zass_search(ZASS a, struct ccl_rpn_node *query, int replaceIndicator = 1; char *datab[100]; - apdu.which = Z_APDU_searchRequest; - apdu.u.searchRequest = &req; - req.referenceId = 0; - req.smallSetUpperBound = &smallSetUpperBound; - req.largeSetLowerBound = &largeSetLowerBound; - req.mediumSetPresentNumber = &mediumSetPresentNumber; - req.replaceIndicator = &replaceIndicator; - req.resultSetName = resname; - req.num_databaseNames = 0; - req.databaseNames = datab; - while (*databases && req.num_databaseNames < 100) + apdu = zget_APDU (a->encode, Z_APDU_searchRequest); + req = apdu->u.searchRequest; + + req->smallSetUpperBound = &smallSetUpperBound; + req->largeSetLowerBound = &largeSetLowerBound; + req->mediumSetPresentNumber = &mediumSetPresentNumber; + req->replaceIndicator = &replaceIndicator; + req->resultSetName = resname; + req->num_databaseNames = 0; + req->databaseNames = datab; + while (*databases && req->num_databaseNames < 100) { char *p = databases; int more; @@ -351,28 +472,33 @@ const struct zass_searchent *zass_search(ZASS a, struct ccl_rpn_node *query, *p = '\0'; if (p - databases) { - req.databaseNames[req.num_databaseNames] = odr_malloc(a->encode, + req->databaseNames[req->num_databaseNames] = odr_malloc(a->encode, (p - databases) + 1); - strcpy(req.databaseNames[req.num_databaseNames++], databases); + strcpy(req->databaseNames[req->num_databaseNames++], databases); } databases = p + more; } - req.smallSetElementSetNames = 0; - req.mediumSetElementSetNames = 0; - req.preferredRecordSyntax = 0; - req.query = &q; + req->query = &q; q.which = Z_Query_type_1; q.u.type_1 = &rpnq; bib1.proto = PROTO_Z3950; bib1.class = CLASS_ATTSET; bib1.value = VAL_BIB1; rpnq.attributeSetId = oid_getoidbyent(&bib1); + + if (complete) + *complete = 1; if (!(rpnq.RPNStructure = rpn2rpn(a->encode, query))) return 0; - if (send_apdu(a, &apdu) < 0) + if (send_apdu(a, apdu) < 0) return 0; - - return search_result(a); + if (complete) + { + *complete = 0; + return 0; + } + else + return zass_searchresult(a, complete); } /* @@ -383,6 +509,20 @@ void get_diagrec(zass_record ***p, Z_DiagRec *r) { **p = malloc(sizeof(***p)); (**p)->next = 0; +#ifdef Z_95 + (**p)->errstring[0] = '\0'; + if (r->which == Z_DiagRec_defaultFormat) + { + (**p)->errcode = *r->u.defaultFormat->condition; + if (r->u.defaultFormat->addinfo) + { + strncpy((**p)->errstring, r->u.defaultFormat->addinfo, 200); + (**p)->errstring[200] = 0; + } + } + else + (**p)->errcode = 0; +#else (**p)->errcode = *r->condition; if (r->addinfo) { @@ -391,6 +531,7 @@ void get_diagrec(zass_record ***p, Z_DiagRec *r) } else (**p)->errstring[0] = '\0'; +#endif (**p)->which = ZASS_REC_DIAG; *p = &(**p)->next; } @@ -446,8 +587,8 @@ void get_responserecords(zass_record ***p, Z_NamePlusRecordList *recs) gw_log(ZASS_DEBUG, ZASS_TYPE, "Got a record of %d bytes", r->u.octet_aligned->len); } + (*p) = &(**p)->next; } - (*p) = &(**p)->next; } } @@ -458,33 +599,41 @@ static void zass_records_free(zass_record *p) static int send_present(ZASS a, char *name, int start, int num, enum oid_value form) { - Z_APDU apdu; - Z_PresentRequest req; + Z_APDU *apdu; + Z_PresentRequest *req; +#if 0 oident recsyn; +#endif + + apdu = zget_APDU (a->encode, Z_APDU_presentRequest); + req = apdu->u.presentRequest; - apdu.which = Z_APDU_presentRequest; - apdu.u.presentRequest = &req; - req.referenceId = 0; - req.resultSetId = name; - req.resultSetStartPoint = &start; - req.numberOfRecordsRequested = # - req.elementSetNames = 0; + req->resultSetId = name; + req->resultSetStartPoint = &start; + req->numberOfRecordsRequested = # +#if 0 recsyn.proto = PROTO_Z3950; recsyn.class = CLASS_RECSYN; recsyn.value = form; - req.preferredRecordSyntax = oid_getoidbyent(&recsyn); - return send_apdu(a, &apdu); + req->preferredRecordSyntax = oid_getoidbyent(&recsyn); +#else + req->preferredRecordSyntax = 0; +#endif + return send_apdu(a, apdu); } /* * Note that 1== first record. + * TODO: make this baby operate in nonblocking mode, too. */ const struct zass_presentent *zass_present(ZASS a, char *resname, int start, - int num) + int num, int *complete) { static struct zass_presentent r; zass_record **rec = &r.records; + if (complete) + *complete = 1; r.num = 0; if (r.records) { @@ -500,8 +649,12 @@ const struct zass_presentent *zass_present(ZASS a, char *resname, int start, "Fetching %d records from # %d", num - r.num, start); if (send_present(a, resname, start, num - r.num, VAL_USMARC) < 0) return 0; - if (!(apdu = get_apdu(a))) + if (!(apdu = get_apdu(a, complete))) + { + if (complete) + *complete = 1; return 0; + } if (apdu->which != Z_APDU_presentResponse) { gw_log(GW_LOG_FATAL, ZASS_TYPE, "Expected presentresponse, got #%d", @@ -535,3 +688,9 @@ const struct zass_presentent *zass_present(ZASS a, char *resname, int start, while (num - r.num && start); return &r; } + +const struct zass_presentent *zass_presentresult(ZASS a, int *complete) +{ + *complete = 1; + return 0; +}