From: Adam Dickmeiss Date: Tue, 23 Oct 2001 21:00:19 +0000 (+0000) Subject: Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. X-Git-Tag: YAZ.1.8~21 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=69bcd68523a9a8da083faef16887100369152673 Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. --- diff --git a/CHANGELOG b/CHANGELOG index 67647a7..a34cef7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ Possible compatibility problems with earlier versions marked with '*'. +* Old Z39.50 codecs no longer supported. + +Added ZOOM C binding. See http://zoom.z3950.org/ + Renamed states for COMSTACKs to avoid confusion with events. Implemented cs_look and proper cs_rcvconnect. diff --git a/Makefile.am b/Makefile.am index 31fb0f2..f14cf4b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,8 +1,8 @@ -## $Id: Makefile.am,v 1.10 2000-10-11 10:40:56 adam Exp $ +## $Id: Makefile.am,v 1.11 2001-10-23 21:00:19 adam Exp $ AUTOMAKE_OPTIONS = foreign -DIST_SUBDIRS=util odr z39.50 asn ill zutil comstack ccl tab retrieval server lib include client ztest doc +DIST_SUBDIRS=util odr z39.50 ill zutil comstack ccl tab retrieval server lib zoom include client ztest doc SUBDIRS = @SUBDIRS_VAR@ diff --git a/README b/README index 979bd9b..6564608 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ Copyright (C) 1995-2001, Index Data ApS. See the file LICENSE for details. Compilation and installation instructions for YAZ - $Id: README,v 1.35 2001-04-06 12:26:45 adam Exp $ + $Id: README,v 1.36 2001-10-23 21:00:19 adam Exp $ The primary output of the source here is the lib/libyaz.a library, which contains support functions for implementing the server or client @@ -26,12 +26,12 @@ for verifying that the protocol works ok, and ztest.c shows an implementation of a 'backend' interface. yaz-client is a linemode Z39.50 client. It supports a fair amount of the -functionality of Z39.50v2/SR, but some things you need to enable or +functionality of Z39.50V3, but some things you need to enable or disable by recompilation. Its primary purpose is to excersise the package, and verify that the protocol works OK. It can be started by typing - yaz-client tcp::[/] + yaz-client [:[/]] at the UNIX prompt, to connect to a Z39.50 server. @@ -90,12 +90,12 @@ odr - Open Data Representation. This module implements the BER encoding rules. Documentation is found in the files odr-use.man and odr.txt. -z39.50 - This module implements the Z39.50 protocol. This module - does the same job as the old 'asn' module except that the source - files are auto-generated using an YAZ' ASN.1 Compiler (yaz-comp). +z39.50 - CODECS for the Z39.50 protocol. This module does the same job + as the old 'asn' module except that the source files are + auto-generated using an YAZ' ASN.1 Compiler (yaz-comp). zutil - This module implements a collection of Z39.50 utilities, such - as query parsing, EXTERNAL handling, etc. + as query parsing, etc. ill - This module implements the ISO ILL protocol. @@ -106,21 +106,18 @@ comstack - This module implements the transport transparency TCP/IP, and uses Peter Furniss' XTIMOSI package over RFC1006. Look for documentation in the file comstack.man. -rfc1006 - Xtimosi requires an implementation of the OSI transport - layer with an XTI-based API. Some systems (HP and DEC, - notably) provide this. For others, we provide an - implementation of the RFC1006 protocol (which is what - ISODE-based implementations often use). This module is not - needed if you don't use xtimosi, and it's not included in the - libyaz.a library. +zoom - An implementation of Mike Taylors Z39.50 Object Oriented + Model : ZOOM. If you'd like to build Z39.50 client applications + in C this may be good start. You'll find example programs in + this directory too. server - This is the implementation of the server frontend. It provides event-handling and server managament functions, and calls the backend primitives (best documentation of these is in the file include/yaz/backend.h). -client - A demonstration client. If we come upon a good design for a - higher level client API, that will live here. +client - A demonstration client for testing the protocol. It's bug'n + ugly. But, it supports many features. ztest - A demonstration server that implements a backend. @@ -129,10 +126,6 @@ include/yaz - The various header files. lib - The libraries. Primarily libyaz.a. The makefile gathers the libraries from previous modules into libyaz.a. -asn - Obsolete - replaced by the codecs in directory z39.50. - This module implements the Z39.50 protocol and is only provided - for backwareds compatibility. - To get more information or assistance, send mail to yaz-help@indexdata.dk. We maintain a mailing-list for the purpose of announcing new versions of diff --git a/buildconf.sh b/buildconf.sh index 3debbfc..6012912 100755 --- a/buildconf.sh +++ b/buildconf.sh @@ -1,8 +1,9 @@ #!/bin/sh -# $Id: buildconf.sh,v 1.3 2001-05-16 07:37:39 adam Exp $ +# $Id: buildconf.sh,v 1.4 2001-10-23 21:00:19 adam Exp $ +set -x +libtoolize --force || exit 2 aclocal || exit 1 -libtoolize --force >/dev/null 2>&1 || exit 2 -automake -a >/dev/null 2>&1 || exit 3 +automake -a || exit 3 autoconf || exit 4 if [ -f config.cache ]; then rm config.cache diff --git a/configure.in b/configure.in index 830a28f..d22c22d 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl YAZ Toolkit, Index Data 1994-2001 dnl See the file LICENSE for details. -dnl $Id: configure.in,v 1.49 2001-10-06 08:16:30 adam Exp $ +dnl $Id: configure.in,v 1.50 2001-10-23 21:00:19 adam Exp $ AC_INIT(include/yaz/yaz-version.h) AM_INIT_AUTOMAKE(yaz, 1.7) dnl @@ -15,20 +15,15 @@ dnl dnl ----- yaz-comp: The Yaz Compiler AC_SUBST(EXTRAMODULE) AC_SUBST(EXTRALIB) -AC_ARG_ENABLE(comp,[ --disable-comp use old encoders, i.e. disable the YAZ ASN.1 Compiler], , enable_comp=yes) -if test "$enable_comp" = "yes"; then - EXTRAMODULE="z39.50" - HFILE=${srcdir}/include/yaz/z-proto.h -else - EXTRAMODULE=asn - HFILE=${srcdir}/asn/prt-proto.h -fi + +EXTRAMODULE="z39.50 zutil" + AC_ARG_ENABLE(modules,[ --enable-modules=\"mod ..\" ill],[ if test "$enable_modules" != "no"; then EXTRAMODULE="$EXTRAMODULE $enable_modules" fi ],[ -EXTRAMODULE="$EXTRAMODULE ill ccl" +EXTRAMODULE="$EXTRAMODULE ill ccl zoom" ]) EXTRALIB="" for module in $EXTRAMODULE; do @@ -38,19 +33,6 @@ for module in $EXTRAMODULE; do fi AC_DEFINE_UNQUOTED(YAZ_MODULE_${module}) done - -AC_MSG_CHECKING(whether proto.h needs to be generated) -yaz_include=${srcdir}/include/yaz -if test -r ${yaz_include}/proto.h && cmp -s $HFILE ${yaz_include}/proto.h; then - AC_MSG_RESULT(no) -else - AC_MSG_RESULT(yes) - cp -f $HFILE ${yaz_include}/proto.h - if test "$enable_comp" != "yes"; then - cp ${srcdir}/asn/*.h ${yaz_include} - fi -fi -dnl dnl ----- Sockets checkBoth=0 AC_CHECK_FUNC(connect) @@ -194,7 +176,7 @@ if test -f ${srcdir}/lib/yaz-config.in; then fi sed s%yaz_echo_source=yes%yaz_echo_source=no%g < ${srcdir}/yaz-config.in >${srcdir}/lib/yaz-config.in dnl -SUBDIRS_VAR="util odr $EXTRAMODULE zutil comstack tab retrieval server include lib client ztest" +SUBDIRS_VAR="util odr comstack $EXTRAMODULE tab retrieval server include lib include client ztest" AC_SUBST(SUBDIRS_VAR) dnl ------ Makefiles dnl @@ -203,7 +185,6 @@ Makefile util/Makefile odr/Makefile z39.50/Makefile -asn/Makefile ill/Makefile zutil/Makefile comstack/Makefile @@ -214,6 +195,7 @@ server/Makefile include/Makefile include/yaz/Makefile lib/Makefile +zoom/Makefile client/Makefile ztest/Makefile doc/Makefile diff --git a/doc/Makefile.am b/doc/Makefile.am index 1efb114..dc42a5e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.14 2001-08-08 19:33:21 adam Exp $ +## $Id: Makefile.am,v 1.15 2001-10-23 21:00:19 adam Exp $ docdir=$(pkgdatadir)/doc @@ -37,7 +37,7 @@ XMLFILES=$(srcdir)/yaz.xml $(srcdir)/introduction.xml \ $(srcdir)/installation.xml $(srcdir)/indexdata.xml $(srcdir)/asn.xml \ $(srcdir)/tools.xml $(srcdir)/odr.xml $(srcdir)/comstack.xml \ $(srcdir)/frontend.xml $(srcdir)/license.xml $(srcdir)/future.xml \ - $(srcdir)/client.xml + $(srcdir)/client.xml $(srcdir)/zoom.xml $(srcdir)/book1.html: $(XMLFILES) $(srcdir)/yazhtml.dsl cd $(srcdir); jade -E14 -d yazhtml.dsl -t sgml xml.dcl yaz.xml diff --git a/doc/yaz.xml b/doc/yaz.xml index e89335c..0ee6c82 100644 --- a/doc/yaz.xml +++ b/doc/yaz.xml @@ -6,6 +6,7 @@ + @@ -18,8 +19,9 @@ ASN"> ODR"> COMSTACK"> + ZOOM"> ]> - + YAZ User's Guide and Reference @@ -47,6 +49,7 @@ &chap-introduction; &chap-installation; + &chap-zoom; &chap-client; &chap-asn; &chap-tools; @@ -68,7 +71,7 @@ sgml-always-quote-attributes:t sgml-indent-step:1 sgml-indent-data:t sgml-parent-document:nil -sgml-local-catalogs: "../../docbook/docbook.cat" +sgml-local-catalogs: "/usr/share/sgml/docbook/dtd/xml/4.1.2/docbook.cat" sgml-namecase-general:t End: --> diff --git a/doc/zoom.xml b/doc/zoom.xml new file mode 100644 index 0000000..1a0aa9e --- /dev/null +++ b/doc/zoom.xml @@ -0,0 +1,253 @@ + + ZOOM + + + &zoom; is an acronym for Z39.50 Object Oriented Model and is + an initiative started by Mike Taylor. The goal of &zoom; is to + provide a common Z39.50 client API not bound to a particular + programming language or toolkit. + + + The lack of a simple Z39.50 client API for &yaz; was more apparanet + than ever. So, when the first ZOOM specification was available + an implementation for &yaz; was developed. For the first time, it is + now easier to develop clients than servers with &yaz;. This + chapter describes the ZOOM C binding. Before going futher + reconsider whether C is still the programming language of your + choice. There are other language bindings available and others + are in active development. See the ZOOM website at + zoom.z3950.org for + more information. + + + + In order to fully understand this chapter you should read and + try the example programs zoomtst1.c, + zoomtst2.c, .. in the zoom + directory. + + + + The C language misses many features found in object oriented languages + such as C++, Java, etc. For example, you'll have to, manually, + destroy all objects you create, even though you may think of them as + temporary. Most objects has a _create - and a + _destroy variant. + All objects are in fact pointers to internal stuff, but you don't see + that because of typedefs. All destroy methods should gracefully ignore a + NULL pointer. + + Connections + + The connection object Z3950_connection describes + the connection between your client and a server. + + + #include <yaz/zoom.h> + + Z3950_connection Z3950_connection_new (const char *host, int portnum); + + Z3950_connection Z3950_connection_create (Z3950_options options); + + void Z3950_connection_connect(Z3950_connection c, const char *host, + int portnum); + void Z3950_connection_destroy (Z3950_connection c); + + + Connection objects are created with either function + Z3950_connection_new or + Z3950_connection_create. + The former both creates and attempts to establishes a network + connection with the target. The latter doesn't establishes + a connection immediately, thus allowing you to set specify options + before establishing network connection using function + Z3950_connection_connect. + If the portnumber, portnum, is zero, the + host is consulted for a port specification. + If no port is given, 210 is used. A colon denotes the beginning of + a port number in the host string. If the host string includes a + slash that specifies a database for the connection. + + + Connection objects should be destroyed using function + Z3950_connection_destroy. + + + const char *Z3950_connection_option (Z3950_connection c, + const char *key, + const char *val); + + + The Z3950_connection_option allows you to + inspect or set an option given by key + for the connection. + If val is non-NULL that + holds the new value for option. + Otherwise, if val is NULL + the option is unchanged. + The function returns the previous value of the option. + + + const char *Z3950_connection_host (Z3950_connection c); + + + + Function Z3950_connection_host returns + the host for the connection as specified in either a call to + Z3950_connection_new or + Z3950_connection_connect. + This function returns NULL if host isn't + set for the connection. + + + int Z3950_connection_error (Z3950_connection c, const char **cp, + const char **addinfo); + + + Use Z3950_connection_error to check for + errors for the last operation(s) performed. The function returns + zero if no errors occurred; non-zero otherwise indicating the error. + Pointers cp and addinfo + holds messages for the error and additional-info if passed as + non-NULL. + + + Search objects + + Search objects defines how result sets are obtained. They + act like queries. + + + Z3950_search Z3950_search_create(void); + + void Z3950_search_destroy(Z3950_search s); + + int Z3950_search_prefix(Z3950_search s, const char *str); + + int Z3950_search_sortby(Z3950_search s, const char *criteria); + + + Create search objects using Z3950_search_create + and destroy them by calling Z3950_search_destroy. + RPN-queries can be specified in PQF notation by using the + function Z3950_search_prefix. More + query types will be added later, such as CCL to RPN-mapping, CCL + query, etc. + In addition to a search a sort critieria may be set. Function + Z3950_search_sortby specifies a sort + criteria using the same string notation for sort as offered by + the YAZ client. + + + Result sets + + The result set describes a collection of records obtained from + search. + + + Z3950_resultset Z3950_connection_search(Z3950_connection, + Z3950_search q); + + Z3950_resultset Z3950_connection_search_pqf(Z3950_connection c, + const char *q); + + void Z3950_resultset_destroy(Z3950_resultset r); + + + Function Z3950_connection_search creates + a result set given a connection - and search object. + Destroy a result set by calling + Z3950_resultset_destroy. + Simple clients using YAZ' prefix query format may use + function Z3950_connection_search_pqf + instead. + + + const char *Z3950_resultset_option (Z3950_resultset r, + const char *key, + const char *val); + + int Z3950_resultset_size (Z3950_resultset r); + + void *Z3950_resultset_get (Z3950_resultset s, int pos, + const char *type, int *len); + void Z3950_resultset_records (Z3950_resultset r, + Z3950_record *recs, + size_t *cnt); + + + Description of result sets here. + + + Records + + A record object is a retrival record on the client side - + created from result sets. + + + Z3950_record Z3950_resultset_record (Z3950_resultset s, int pos); + + Z3950_record Z3950_resultset_record_immediate (Z3950_resultset s, + int pos); + + void *Z3950_record_get (Z3950_record rec, const char *type, + int *len); + + void Z3950_record_destroy (Z3950_record rec); + + + Options + + Most objects in &zoom; allows you to specify options to change + behaviour. From an implementation point of view a set of options + is just like an associate array / hash array, etc. + + + Z3950_options Z3950_options_create (void); + + Z3950_options Z3950_options_create_with_parent (Z3950_options parent); + + void Z3950_options_destroy (Z3950_options opt); + + + const char *Z3950_options_get (Z3950_options opt, const char *name); + + void Z3950_options_set (Z3950_options opt, const char *name, + const char *v); + + + typedef const char *(*Z3950_options_callback) + (void *handle, const char *name); + + Z3950_options_callback + Z3950_options_set_callback (Z3950_options opt, + Z3950_options_callback c, + void *handle); + + + Events + + If you're developing non-blocking applications you have to deal + with events. + + + int Z3950_event (int no, Z3950_connection *cs); + + + + + + diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 1e3e301..d769f69 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.11 2001-08-08 19:35:06 adam Exp $ +## $Id: Makefile.am,v 1.12 2001-10-23 21:00:19 adam Exp $ pkginclude_HEADERS= backend.h ccl.h comstack.h \ d1_attset.h d1_map.h data1.h diagbib1.h sortspec.h \ @@ -8,7 +8,7 @@ pkginclude_HEADERS= backend.h ccl.h comstack.h \ \ ill.h ill-core.h item-req.h z-accdes1.h z-accform1.h \ z-acckrb1.h z-core.h z-date.h z-diag1.h z-espec1.h z-estask.h z-exp.h \ - z-grs.h z-opac.h z-proto.h z-rrf1.h z-rrf2.h z-sum.h z-sutrs.h z-uifr1.h \ + z-grs.h z-opac.h z-rrf1.h z-rrf2.h z-sum.h z-sutrs.h z-uifr1.h \ z-univ.h zes-expi.h zes-exps.h zes-order.h zes-pquery.h \ - zes-psched.h zes-admin.h zes-pset.h zes-update.h zes-update0.h + zes-psched.h zes-admin.h zes-pset.h zes-update.h zes-update0.h zoom.h diff --git a/include/yaz/proto.h b/include/yaz/proto.h new file mode 100644 index 0000000..6d020d0 --- /dev/null +++ b/include/yaz/proto.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1998-2001, Index Data + * See the file LICENSE for details. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: proto.h,v $ + * Revision 1.1 2001-10-23 21:00:19 adam + * Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. + * + * Revision 1.7 2001/09/24 21:51:55 adam + * New Z39.50 OID utilities: yaz_oidval_to_z3950oid, yaz_str_to_z3950oid + * and yaz_z3950oid_to_str. + * + * Revision 1.6 2001/09/19 10:19:07 adam + * Z_SortCase_caseInsensitive was set to wrong value. + * + * Revision 1.5 2001/05/17 14:16:15 adam + * Added EXTERNAL handling for item update0 (1.0). + * + * Revision 1.4 2000/03/14 09:19:49 ian + * Added admin extended service encoders & decoders. + * + * Revision 1.3 2000/02/28 11:20:06 adam + * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL. + * + * Revision 1.2 1999/12/16 23:36:19 adam + * Implemented ILL protocol. Minor updates ASN.1 compiler. + * + * Revision 1.1 1999/11/30 13:47:11 adam + * Improved installation. Moved header files to include/yaz. + * + * Revision 1.2 1999/06/09 10:52:11 adam + * Added YAZ_EXPORT. + * + * Revision 1.1 1999/06/08 13:11:55 adam + * Fixed problem with proto.h. + * + * Revision 1.2 1999/04/20 10:37:04 adam + * Updated for ODR - added name parameter. + * + * Revision 1.1 1998/03/31 16:04:05 adam + * First version of proto.h which is almost compatible with the old one. + * + */ +#ifndef Z_PROTO_H +#define Z_PROTO_H + +#define Z_95 1 +#define ASN_COMPILED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +YAZ_BEGIN_CDECL + +#define Z_PRES_SUCCESS Z_PresentStatus_success +#define Z_PRES_PARTIAL_1 Z_PresentStatus_partial_1 +#define Z_PRES_PARTIAL_2 Z_PresentStatus_partial_2 +#define Z_PRES_PARTIAL_3 Z_PresentStatus_partial_3 +#define Z_PRES_PARTIAL_4 Z_PresentStatus_partial_4 +#define Z_PRES_FAILURE Z_PresentStatus_failure + +#define Z_RES_SUBSET Z_SearchResponse_subset +#define Z_RES_INTERIM Z_SearchResponse_interim +#define Z_RES_NONE Z_SearchResponse_none + +#define Z_SortStatus_success Z_SortResponse_success +#define Z_SortStatus_partial_1 Z_SortResponse_partial_1 +#define Z_SortStatus_failure Z_SortResponse_failure + +#define Z_SortRelation_ascending Z_SortKeySpec_ascending +#define Z_SortRelation_descending Z_SortKeySpec_descending +#define Z_SortRelation_ascendingByFreq Z_SortKeySpec_ascendingByFrequency +#define Z_SortRelation_descendingByFreq Z_SortKeySpec_descendingByfrequency + +#define Z_SortCase_caseSensitive Z_SortKeySpec_caseSensitive +#define Z_SortCase_caseInsensitive Z_SortKeySpec_caseInsensitive + +#define Z_TriggerResourceCtrl_resourceReport Z_TriggerResourceControlRequest_resourceReport +#define Z_TriggerResourceCtrl_resourceControl Z_TriggerResourceControlRequest_resourceControl +#define Z_TriggerResourceCtrl_cancel Z_TriggerResourceControlRequest_cancel + +#define Z_DeleteRequest_list Z_DeleteResultSetRequest_list +#define Z_DeleteRequest_all Z_DeleteResultSetRequest_all + +#define Z_AccessRequest_simpleForm Z_AccessControlRequest_simpleForm +#define Z_AccessRequest_externallyDefined Z_AccessControlRequest_externallyDefined + +#define Z_AccessResponse_simpleForm Z_AccessControlResponse_simpleForm +#define Z_AccessResponse_externallyDefined Z_AccessControlResponse_externallyDefined + +#define Z_ResourceReportStatus_success Z_ResourceReportResponse_success +#define Z_ResourceReportStatus_partial Z_ResourceReportResponse_partial +#define Z_ResourceReportStatus_failure_1 Z_ResourceReportResponse_failure_1 +#define Z_ResourceReportStatus_failure_2 Z_ResourceReportResponse_failure_2 +#define Z_ResourceReportStatus_failure_3 Z_ResourceReportResponse_failure_3 +#define Z_ResourceReportStatus_failure_4 Z_ResourceReportResponse_failure_4 +#define Z_ResourceReportStatus_failure_5 Z_ResourceReportResponse_failure_5 +#define Z_ResourceReportStatus_failure_6 Z_ResourceReportResponse_failure_6 + +#define Z_SortResultSetStatus_empty Z_SortResponse_empty +#define Z_SortResultSetStatus_interim Z_SortResponse_interim +#define Z_SortResultSetStatus_unchanged Z_SortResponse_unchanged +#define Z_SortResultSetStatus_none Z_SortResponse_none + +typedef Z_External Z_DatabaseRecord; +typedef struct Z_IOItemOrder Z_ItemOrder; + +YAZ_EXPORT Z_APDU *zget_APDU(ODR o, int which); +YAZ_EXPORT Z_Close *zget_Close (ODR o); +YAZ_EXPORT Odr_oid *yaz_oidval_to_z3950oid (ODR o, int oid_class, + int oid_value); +YAZ_EXPORT Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class, + const char *str); +YAZ_EXPORT const char *yaz_z3950oid_to_str (Odr_oid *oid, int *oid_class); + +YAZ_END_CDECL + +#include + +#endif diff --git a/include/yaz/wrbuf.h b/include/yaz/wrbuf.h index f16f939..f3bb57b 100644 --- a/include/yaz/wrbuf.h +++ b/include/yaz/wrbuf.h @@ -24,7 +24,10 @@ * OF THIS SOFTWARE. * * $Log: wrbuf.h,v $ - * Revision 1.3 2001-10-15 19:36:48 adam + * Revision 1.4 2001-10-23 21:00:19 adam + * Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. + * + * Revision 1.3 2001/10/15 19:36:48 adam * New function marc_display_wrbuf. * * Revision 1.2 2000/02/28 11:20:06 adam @@ -77,7 +80,8 @@ YAZ_EXPORT int wrbuf_puts(WRBUF b, const char *buf); (((b)->pos >= (b)->size ? wrbuf_grow(b, 1) : 0), \ (b)->buf[(b)->pos++] = (c), 0) -YAZ_EXPORT int marc_display_wrbuf (const char *buf, WRBUF wr, int debug); +YAZ_EXPORT int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, + int bsize); YAZ_END_CDECL diff --git a/include/yaz/z-proto.h b/include/yaz/z-proto.h deleted file mode 100644 index 9d84c00..0000000 --- a/include/yaz/z-proto.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1998-2000, Index Data - * See the file LICENSE for details. - * Sebastian Hammer, Adam Dickmeiss - * - * $Log: z-proto.h,v $ - * Revision 1.7 2001-09-24 21:51:55 adam - * New Z39.50 OID utilities: yaz_oidval_to_z3950oid, yaz_str_to_z3950oid - * and yaz_z3950oid_to_str. - * - * Revision 1.6 2001/09/19 10:19:07 adam - * Z_SortCase_caseInsensitive was set to wrong value. - * - * Revision 1.5 2001/05/17 14:16:15 adam - * Added EXTERNAL handling for item update0 (1.0). - * - * Revision 1.4 2000/03/14 09:19:49 ian - * Added admin extended service encoders & decoders. - * - * Revision 1.3 2000/02/28 11:20:06 adam - * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL. - * - * Revision 1.2 1999/12/16 23:36:19 adam - * Implemented ILL protocol. Minor updates ASN.1 compiler. - * - * Revision 1.1 1999/11/30 13:47:11 adam - * Improved installation. Moved header files to include/yaz. - * - * Revision 1.2 1999/06/09 10:52:11 adam - * Added YAZ_EXPORT. - * - * Revision 1.1 1999/06/08 13:11:55 adam - * Fixed problem with proto.h. - * - * Revision 1.2 1999/04/20 10:37:04 adam - * Updated for ODR - added name parameter. - * - * Revision 1.1 1998/03/31 16:04:05 adam - * First version of proto.h which is almost compatible with the old one. - * - */ -#ifndef Z_PROTO_H -#define Z_PROTO_H - -#define Z_95 1 -#define ASN_COMPILED 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -YAZ_BEGIN_CDECL - -#define Z_PRES_SUCCESS Z_PresentStatus_success -#define Z_PRES_PARTIAL_1 Z_PresentStatus_partial_1 -#define Z_PRES_PARTIAL_2 Z_PresentStatus_partial_2 -#define Z_PRES_PARTIAL_3 Z_PresentStatus_partial_3 -#define Z_PRES_PARTIAL_4 Z_PresentStatus_partial_4 -#define Z_PRES_FAILURE Z_PresentStatus_failure - -#define Z_RES_SUBSET Z_SearchResponse_subset -#define Z_RES_INTERIM Z_SearchResponse_interim -#define Z_RES_NONE Z_SearchResponse_none - -#define Z_SortStatus_success Z_SortResponse_success -#define Z_SortStatus_partial_1 Z_SortResponse_partial_1 -#define Z_SortStatus_failure Z_SortResponse_failure - -#define Z_SortRelation_ascending Z_SortKeySpec_ascending -#define Z_SortRelation_descending Z_SortKeySpec_descending -#define Z_SortRelation_ascendingByFreq Z_SortKeySpec_ascendingByFrequency -#define Z_SortRelation_descendingByFreq Z_SortKeySpec_descendingByfrequency - -#define Z_SortCase_caseSensitive Z_SortKeySpec_caseSensitive -#define Z_SortCase_caseInsensitive Z_SortKeySpec_caseInsensitive - -#define Z_TriggerResourceCtrl_resourceReport Z_TriggerResourceControlRequest_resourceReport -#define Z_TriggerResourceCtrl_resourceControl Z_TriggerResourceControlRequest_resourceControl -#define Z_TriggerResourceCtrl_cancel Z_TriggerResourceControlRequest_cancel - -#define Z_DeleteRequest_list Z_DeleteResultSetRequest_list -#define Z_DeleteRequest_all Z_DeleteResultSetRequest_all - -#define Z_AccessRequest_simpleForm Z_AccessControlRequest_simpleForm -#define Z_AccessRequest_externallyDefined Z_AccessControlRequest_externallyDefined - -#define Z_AccessResponse_simpleForm Z_AccessControlResponse_simpleForm -#define Z_AccessResponse_externallyDefined Z_AccessControlResponse_externallyDefined - -#define Z_ResourceReportStatus_success Z_ResourceReportResponse_success -#define Z_ResourceReportStatus_partial Z_ResourceReportResponse_partial -#define Z_ResourceReportStatus_failure_1 Z_ResourceReportResponse_failure_1 -#define Z_ResourceReportStatus_failure_2 Z_ResourceReportResponse_failure_2 -#define Z_ResourceReportStatus_failure_3 Z_ResourceReportResponse_failure_3 -#define Z_ResourceReportStatus_failure_4 Z_ResourceReportResponse_failure_4 -#define Z_ResourceReportStatus_failure_5 Z_ResourceReportResponse_failure_5 -#define Z_ResourceReportStatus_failure_6 Z_ResourceReportResponse_failure_6 - -#define Z_SortResultSetStatus_empty Z_SortResponse_empty -#define Z_SortResultSetStatus_interim Z_SortResponse_interim -#define Z_SortResultSetStatus_unchanged Z_SortResponse_unchanged -#define Z_SortResultSetStatus_none Z_SortResponse_none - -typedef Z_External Z_DatabaseRecord; -typedef struct Z_IOItemOrder Z_ItemOrder; - -YAZ_EXPORT Z_APDU *zget_APDU(ODR o, int which); -YAZ_EXPORT Z_Close *zget_Close (ODR o); -YAZ_EXPORT Odr_oid *yaz_oidval_to_z3950oid (ODR o, int oid_class, - int oid_value); -YAZ_EXPORT Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class, - const char *str); -YAZ_EXPORT const char *yaz_z3950oid_to_str (Odr_oid *oid, int *oid_class); - -YAZ_END_CDECL - -#include - -#endif diff --git a/include/yaz/zoom.h b/include/yaz/zoom.h new file mode 100644 index 0000000..67e389e --- /dev/null +++ b/include/yaz/zoom.h @@ -0,0 +1,141 @@ +/* + * Public header for ZOOM C. + * $Id: zoom.h,v 1.1 2001-10-23 21:00:19 adam Exp $ + */ +/* the types we use */ + +#include + +YAZ_BEGIN_CDECL + +typedef struct Z3950_options_p *Z3950_options; +typedef struct Z3950_search_p *Z3950_search; +typedef struct Z3950_connection_p *Z3950_connection; +typedef struct Z3950_resultset_p *Z3950_resultset; +typedef struct Z3950_task_p *Z3950_task; +typedef struct Z3950_record_p *Z3950_record; + +/* ----------------------------------------------------------- */ +/* connections */ + +/* create connection, connect to host, if portnum is 0, then port is +read from host string (e.g. myhost:9821) */ +Z3950_connection Z3950_connection_new (const char *host, int portnum); + +/* create connection, don't connect, apply options */ +Z3950_connection Z3950_connection_create (Z3950_options options); + +/* connect given existing connection */ +void Z3950_connection_connect(Z3950_connection c, const char *host, + int portnum); + +/* destroy connection (close connection also *) */ +void Z3950_connection_destroy (Z3950_connection c); + +/* set option for connection */ +const char *Z3950_connection_option (Z3950_connection c, const char *key, + const char *val); +/* return host for connection */ +const char *Z3950_connection_host (Z3950_connection c); + +/* return error code (0 == success, failure otherwise). cp + holds error string on failure, addinfo holds addititional info (if any) +*/ +int Z3950_connection_error (Z3950_connection c, const char **cp, + const char **addinfo); + +/* returns error code */ +int Z3950_connection_errcode (Z3950_connection c); +/* returns error message */ +const char *Z3950_connection_errmsg (Z3950_connection c); +/* returns additional info */ +const char *Z3950_connection_addinfo (Z3950_connection c); + +#define Z3950_ERROR_NONE 0 +#define Z3950_ERROR_CONNECT 10000 +#define Z3950_ERROR_MEMORY 10001 +#define Z3950_ERROR_ENCODE 10002 +#define Z3950_ERROR_DECODE 10003 +#define Z3950_ERROR_CONNECTION_LOST 10004 +#define Z3950_ERROR_INIT 10005 +#define Z3950_ERROR_INTERNAL 10006 +#define Z3950_ERROR_TIMEOUT 10007 + +/* ----------------------------------------------------------- */ +/* result sets */ + +/* create result set given a search */ +Z3950_resultset Z3950_connection_search(Z3950_connection, Z3950_search q); +/* create result set given PQF query */ +Z3950_resultset Z3950_connection_search_pqf(Z3950_connection c, const char *q); + +/* destroy result set */ +void Z3950_resultset_destroy(Z3950_resultset r); + +/* result set option */ +const char *Z3950_resultset_option (Z3950_resultset r, const char *key, + const char *val); +/* return size of result set (hit count, AKA resultCount) */ +int Z3950_resultset_size (Z3950_resultset r); + +/* return record at pos (starting from ), render given spec in type */ +void *Z3950_resultset_get (Z3950_resultset s, int pos, const char *type, + int *len); +/* retrieve records */ +void Z3950_resultset_records (Z3950_resultset r, Z3950_record *recs, + size_t *cnt); + +/* return record object at pos. Returns 0 if unavailable */ +Z3950_record Z3950_resultset_record (Z3950_resultset s, int pos); + +/* like Z3950_resultset_record - but never blocks .. */ +Z3950_record Z3950_resultset_record_immediate (Z3950_resultset s, int pos); + +/* ----------------------------------------------------------- */ +/* records */ + +/* Get record information, in a form given by type */ +void *Z3950_record_get (Z3950_record rec, const char *type, int *len); + +/* Destroy record */ +void Z3950_record_destroy (Z3950_record rec); + +/* ----------------------------------------------------------- */ +/* searches */ + +/* create search object */ +Z3950_search Z3950_search_create(void); +/* destroy it */ +void Z3950_search_destroy(Z3950_search s); +/* specify prefix query for search */ +int Z3950_search_prefix(Z3950_search s, const char *str); +/* specify sort criteria for search */ +int Z3950_search_sortby(Z3950_search s, const char *criteria); + + +/* ----------------------------------------------------------- */ +/* options */ +typedef const char *(*Z3950_options_callback)(void *handle, const char *name); + +Z3950_options_callback Z3950_options_set_callback (Z3950_options opt, + Z3950_options_callback c, + void *handle); +Z3950_options Z3950_options_create (void); +Z3950_options Z3950_options_create_with_parent (Z3950_options parent); +const char *Z3950_options_get (Z3950_options opt, const char *name); +void Z3950_options_set (Z3950_options opt, const char *name, const char *v); +void Z3950_options_destroy (Z3950_options opt); +int Z3950_options_get_bool (Z3950_options opt, const char *name, int defa); +int Z3950_options_get_int (Z3950_options opt, const char *name, int defa); +void Z3950_options_addref (Z3950_options opt); + +/* ----------------------------------------------------------- */ +/* events */ +/* poll for events on a number of connections. Returns positive + integer if event occurred ; zero if none occurred and no more + events are pending. The positive integer specifies the + connection for which the event occurred. There's no way to get + the details yet, sigh. */ +int Z3950_event (int no, Z3950_connection *cs); + +YAZ_END_CDECL diff --git a/lib/Makefile.am b/lib/Makefile.am index a6a4f57..740b32a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.14 2001-10-05 13:55:17 adam Exp $ +## $Id: Makefile.am,v 1.15 2001-10-23 21:00:19 adam Exp $ if ISTHR extra=libyazthread.la @@ -32,6 +32,6 @@ bin_SCRIPTS = yaz-config libyaz_la_LIBADD=../odr/libodr.la \ ../comstack/libcomstack.la ../server/libserver.la \ - ../zutil/libzutil.la ../util/libutil.la ../retrieval/libret.la \ + ../util/libutil.la ../retrieval/libret.la \ $(EXTRALIB) diff --git a/util/marcdisp.c b/util/marcdisp.c index 63956f7..ab2ef2f 100644 --- a/util/marcdisp.c +++ b/util/marcdisp.c @@ -3,7 +3,10 @@ * See the file LICENSE for details. * * $Log: marcdisp.c,v $ - * Revision 1.13 2001-10-15 19:36:48 adam + * Revision 1.14 2001-10-23 21:00:20 adam + * Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. + * + * Revision 1.13 2001/10/15 19:36:48 adam * New function marc_display_wrbuf. * * Revision 1.12 2000/10/02 11:07:44 adam @@ -56,7 +59,8 @@ #include #include -int marc_display_wrbuf (const char *buf, WRBUF wr, int debug) +int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, + int bsize) { int entry_p; int record_length; @@ -79,6 +83,9 @@ int marc_display_wrbuf (const char *buf, WRBUF wr, int debug) } return -1; } + /* ballout if bsize is known and record_length is than that */ + if (bsize != -1 && record_length > bsize) + return -1; if (isdigit(buf[10])) indicator_length = atoi_n (buf+10, 1); else @@ -185,7 +192,7 @@ int marc_display_ex (const char *buf, FILE *outf, int debug) int record_length; WRBUF wrbuf = wrbuf_alloc (); - record_length = marc_display_wrbuf (buf, wrbuf, debug); + record_length = marc_display_wrbuf (buf, wrbuf, debug, -1); if (!outf) outf = stdout; if (record_length > 0) diff --git a/yaz.spec b/yaz.spec index c93fa1e..ffc5458 100644 --- a/yaz.spec +++ b/yaz.spec @@ -20,7 +20,7 @@ using the ANSI/NISO Z39.50 protocol for Information Retrieval. %build CFLAGS="$RPM_OPT_FLAGS" \ - ./configure --prefix=/usr --enable-shared --enable-tcpd --enable-module=ill + ./configure --prefix=/usr --enable-shared --enable-tcpd make CFLAGS="$RPM_OPT_FLAGS" %install @@ -36,6 +36,7 @@ cd doc; make prefix=$RPM_BUILD_ROOT/usr install /usr/bin/yaz-ztest /usr/bin/yaz-config /usr/bin/yaz-comp +/usr/bin/zoomsh /usr/lib/libyaz.a /usr/lib/libyaz.so /usr/lib/libyaz.so.1 diff --git a/z39.50/Makefile.am b/z39.50/Makefile.am index a68ce22..b8a2ec9 100644 --- a/z39.50/Makefile.am +++ b/z39.50/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.6 2001-04-05 13:08:48 adam Exp $ +## $Id: Makefile.am,v 1.7 2001-10-23 21:00:20 adam Exp $ INCLUDES=-I$(top_srcdir)/include @@ -16,7 +16,7 @@ libz39_50_la_SOURCES = z-accdes1.c z-accform1.c z-acckrb1.c z-core.c \ z-diag1.c z-espec1.c z-estask.c z-exp.c z-grs.c z-opac.c z-uifr1.c \ z-rrf1.c z-rrf2.c z-sum.c z-sutrs.c \ zes-expi.c zes-exps.c zes-order.c zes-pquery.c zes-psched.c \ - zes-pset.c zes-update0.c z-date.c z-univ.c zes-update.c zes-admin.c + zes-pset.c zes-update0.c z-date.c z-univ.c zes-update.c zes-admin.c prt-ext.c # Rules for Z39.50 V3 $(srcdir)/z-accdes1.c \ diff --git a/z39.50/prt-ext.c b/z39.50/prt-ext.c new file mode 100644 index 0000000..d1d2d50 --- /dev/null +++ b/z39.50/prt-ext.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 1995-2001, Index Data. + * See the file LICENSE for details. + * + * $Log: prt-ext.c,v $ + * Revision 1.1 2001-10-23 21:00:20 adam + * Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util. + * + * Revision 1.7 2001/09/24 21:51:56 adam + * New Z39.50 OID utilities: yaz_oidval_to_z3950oid, yaz_str_to_z3950oid + * and yaz_z3950oid_to_str. + * + * Revision 1.6 2001/05/17 14:16:15 adam + * Added EXTERNAL handling for item update0 (1.0). + * + * Revision 1.5 2001/03/25 21:55:13 adam + * Added odr_intdup. Ztest server returns TaskPackage for ItemUpdate. + * + * Revision 1.4 2000/03/14 15:22:04 ian + * Added Admin external to choice table. + * + * Revision 1.3 2000/03/14 13:52:32 ian + * Added Admin Extended Service to External Choice + * + * Revision 1.2 1999/11/30 13:47:12 adam + * Improved installation. Moved header files to include/yaz. + * + * Revision 1.1 1999/06/08 10:10:16 adam + * New sub directory zutil. Moved YAZ Compiler to be part of YAZ tree. + * + * Revision 1.22 1999/05/26 15:24:26 adam + * Fixed minor bugs regarding DB Update (introduced by previous commit). + * + * Revision 1.21 1999/05/26 14:47:12 adam + * Implemented z_ext_record. + * + * Revision 1.20 1999/04/20 09:56:48 adam + * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun). + * Modified all encoders/decoders to reflect this change. + * + * Revision 1.19 1998/03/31 15:13:19 adam + * Development towards compiled ASN.1. + * + * Revision 1.18 1998/03/31 11:07:44 adam + * Furhter work on UNIverse resource report. + * Added Extended Services handling in frontend server. + * + * Revision 1.17 1998/03/20 14:46:06 adam + * Added UNIverse Resource Reports. + * + * Revision 1.16 1998/02/11 11:53:32 adam + * Changed code so that it compiles as C++. + * + * Revision 1.15 1998/02/10 15:31:46 adam + * Implemented date and time structure. Changed the Update Extended + * Service. + * + * Revision 1.14 1998/01/05 09:04:57 adam + * Fixed bugs in encoders/decoders - Not operator (!) missing. + * + * Revision 1.13 1997/05/14 06:53:22 adam + * C++ support. + * + * Revision 1.12 1997/04/30 08:52:02 quinn + * Null + * + * Revision 1.11 1996/10/10 12:35:13 quinn + * Added Update extended service. + * + * Revision 1.10 1996/10/09 15:54:55 quinn + * Added SearchInfoReport + * + * Revision 1.9 1996/06/10 08:53:36 quinn + * Added Summary,OPAC,ResourceReport + * + * Revision 1.8 1996/02/20 12:51:44 quinn + * Completed SCAN. Fixed problems with EXTERNAL. + * + * Revision 1.7 1995/10/12 10:34:38 quinn + * Added Espec-1. + * + * Revision 1.6 1995/09/29 17:11:55 quinn + * Smallish + * + * Revision 1.5 1995/09/27 15:02:42 quinn + * Modified function heads & prototypes. + * + * Revision 1.4 1995/08/29 11:17:16 quinn + * *** empty log message *** + * + * Revision 1.3 1995/08/21 09:10:18 quinn + * Smallish fixes to suppport new formats. + * + * Revision 1.2 1995/08/17 12:45:00 quinn + * Fixed minor problems with GRS-1. Added support in c&s. + * + * Revision 1.1 1995/08/15 13:37:41 quinn + * Improved EXTERNAL + * + * + */ + +#include + +/* + * The table below should be moved to the ODR structure itself and + * be an image of the association context: To help + * map indirect references when they show up. + */ +static Z_ext_typeent type_table[] = +{ + {VAL_SUTRS, Z_External_sutrs, (Odr_fun) z_SUTRS}, + {VAL_EXPLAIN, Z_External_explainRecord, (Odr_fun)z_ExplainRecord}, + {VAL_RESOURCE1, Z_External_resourceReport1, (Odr_fun)z_ResourceReport1}, + {VAL_RESOURCE2, Z_External_resourceReport2, (Odr_fun)z_ResourceReport2}, + {VAL_PROMPT1, Z_External_promptObject1, (Odr_fun)z_PromptObject1 }, + {VAL_GRS1, Z_External_grs1, (Odr_fun)z_GenericRecord}, + {VAL_EXTENDED, Z_External_extendedService, (Odr_fun)z_TaskPackage}, +#ifdef ASN_COMPILED + {VAL_ITEMORDER, Z_External_itemOrder, (Odr_fun)z_IOItemOrder}, +#else + {VAL_ITEMORDER, Z_External_itemOrder, (Odr_fun)z_ItemOrder}, +#endif + {VAL_DIAG1, Z_External_diag1, (Odr_fun)z_DiagnosticFormat}, + {VAL_ESPEC1, Z_External_espec1, (Odr_fun)z_Espec1}, + {VAL_SUMMARY, Z_External_summary, (Odr_fun)z_BriefBib}, + {VAL_OPAC, Z_External_OPAC, (Odr_fun)z_OPACRecord}, + {VAL_SEARCHRES1, Z_External_searchResult1, (Odr_fun)z_SearchInfoReport}, + {VAL_DBUPDATE, Z_External_update, (Odr_fun)z_IUUpdate}, + {VAL_DATETIME, Z_External_dateTime, (Odr_fun)z_DateTime}, + {VAL_UNIVERSE_REPORT, Z_External_universeReport, (Odr_fun)z_UniverseReport}, +#ifdef ASN_COMPILED + {VAL_ADMINSERVICE, Z_External_ESAdmin, (Odr_fun)z_Admin}, +#endif + {VAL_NONE, 0, 0} +}; + +Z_ext_typeent *z_ext_getentbyref(oid_value val) +{ + Z_ext_typeent *i; + + for (i = type_table; i->dref != VAL_NONE; i++) + if (i->dref == val) + return i; + return 0; +} + +int z_External(ODR o, Z_External **p, int opt, const char *name) +{ + oident *oid; + Z_ext_typeent *type; + + static Odr_arm arm[] = + { + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_single, + (Odr_fun)odr_any, 0}, + {ODR_IMPLICIT, ODR_CONTEXT, 1, Z_External_octet, + (Odr_fun)odr_octetstring, 0}, + {ODR_IMPLICIT, ODR_CONTEXT, 2, Z_External_arbitrary, + (Odr_fun)odr_bitstring, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_sutrs, + (Odr_fun)z_SUTRS, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_explainRecord, + (Odr_fun)z_ExplainRecord, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_resourceReport1, + (Odr_fun)z_ResourceReport1, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_resourceReport2, + (Odr_fun)z_ResourceReport2, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_promptObject1, + (Odr_fun)z_PromptObject1, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_grs1, + (Odr_fun)z_GenericRecord, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_extendedService, + (Odr_fun)z_TaskPackage, 0}, +#ifdef ASN_COMPILED + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_itemOrder, + (Odr_fun)z_IOItemOrder, 0}, +#else + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_itemOrder, + (Odr_fun)z_ItemOrder, 0}, +#endif + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_diag1, + (Odr_fun)z_DiagnosticFormat, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_espec1, + (Odr_fun)z_Espec1, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_summary, + (Odr_fun)z_BriefBib, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_OPAC, + (Odr_fun)z_OPACRecord, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_searchResult1, + (Odr_fun)z_SearchInfoReport, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_update, + (Odr_fun)z_IUUpdate, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_dateTime, + (Odr_fun)z_DateTime, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_universeReport, + (Odr_fun)z_UniverseReport, 0}, +#ifdef ASN_COMPILED + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_ESAdmin, + (Odr_fun)z_Admin, 0}, + {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_update0, + (Odr_fun)z_IU0Update, 0}, +#endif {-1, -1, -1, -1, 0, 0} + }; + + odr_implicit_settag(o, ODR_UNIVERSAL, ODR_EXTERNAL); + if (!odr_sequence_begin(o, p, sizeof(**p), name)) + return opt && odr_ok(o); + if (!(odr_oid(o, &(*p)->direct_reference, 1, 0) && + odr_integer(o, &(*p)->indirect_reference, 1, 0) && + odr_graphicstring(o, &(*p)->descriptor, 1, 0))) + return 0; + /* + * Do we know this beast? + */ + if (o->direction == ODR_DECODE && (*p)->direct_reference && + (oid = oid_getentbyoid((*p)->direct_reference)) && + (type = z_ext_getentbyref(oid->value))) + { + int zclass, tag, cons; + + /* + * We know it. If it's represented as an ASN.1 type, bias the CHOICE. + */ + if (!odr_peektag(o, &zclass, &tag, &cons)) + return opt && odr_ok(o); + if (zclass == ODR_CONTEXT && tag == 0 && cons == 1) + odr_choice_bias(o, type->what); + } + return + odr_choice(o, arm, &(*p)->u, &(*p)->which, name) && + odr_sequence_end(o); +} + +Z_External *z_ext_record(ODR o, int format, const char *buf, int len) +{ + Z_External *thisext; + + thisext = (Z_External *) odr_malloc(o, sizeof(*thisext)); + thisext->descriptor = 0; + thisext->indirect_reference = 0; + + thisext->direct_reference = + yaz_oidval_to_z3950oid (o, CLASS_RECSYN, format); + if (!thisext->direct_reference) + return 0; + + if (len < 0) /* Structured data */ + { + switch (format) + { + case VAL_SUTRS: + thisext->which = Z_External_sutrs; + break; + case VAL_GRS1: + thisext->which = Z_External_grs1; + break; + case VAL_EXPLAIN: + thisext->which = Z_External_explainRecord; + break; + case VAL_SUMMARY: + thisext->which = Z_External_summary; + break; + case VAL_OPAC: + thisext->which = Z_External_OPAC; + break; + case VAL_EXTENDED: + thisext->which = Z_External_extendedService; + break; + default: + return 0; + } + + /* + * We cheat on the pointers here. Obviously, the record field + * of the backend-fetch structure should have been a union for + * correctness, but we're stuck with this for backwards + * compatibility. + */ + thisext->u.grs1 = (Z_GenericRecord*) buf; + } + else if (format == VAL_SUTRS) /* SUTRS is a single-ASN.1-type */ + { + Odr_oct *sutrs = (Odr_oct *)odr_malloc(o, sizeof(*sutrs)); + + thisext->which = Z_External_sutrs; + thisext->u.sutrs = sutrs; + sutrs->buf = (unsigned char *)odr_malloc(o, len); + sutrs->len = sutrs->size = len; + memcpy(sutrs->buf, buf, len); + } + else + { + thisext->which = Z_External_octet; + if (!(thisext->u.octet_aligned = (Odr_oct *) + odr_malloc(o, sizeof(Odr_oct)))) + return 0; + if (!(thisext->u.octet_aligned->buf = (unsigned char *) + odr_malloc(o, len))) + return 0; + memcpy(thisext->u.octet_aligned->buf, buf, len); + thisext->u.octet_aligned->len = thisext->u.octet_aligned->size = len; + } + return thisext; +} + diff --git a/zoom/Makefile.am b/zoom/Makefile.am new file mode 100644 index 0000000..db63437 --- /dev/null +++ b/zoom/Makefile.am @@ -0,0 +1,29 @@ +## $Id: Makefile.am,v 1.1 2001-10-23 21:00:20 adam Exp $ +## Copyright (C) 2001, Index Data + +INCLUDES = -I$(top_srcdir)/include +noinst_LTLIBRARIES = libzoom.la +libzoom_la_SOURCES = zoom-opt.c zoom-c.c zoom-p.h + +zoomlibs = libzoom.la ../comstack/libcomstack.la ../z39.50/libz39.50.la ../zutil/libzutil.la ../odr/libodr.la ../util/libutil.la $(READLINE_LIBS) + +zoomsh_LDADD = $(zoomlibs) +zoomtst1_LDADD = $(zoomlibs) +zoomtst2_LDADD = $(zoomlibs) +zoomtst3_LDADD = $(zoomlibs) +zoomtst4_LDADD = $(zoomlibs) +zoomtst5_LDADD = $(zoomlibs) +zoomtst6_LDADD = $(zoomlibs) +zoomtst7_LDADD = $(zoomlibs) + +noinst_PROGRAMS = zoomtst1 zoomtst2 zoomtst3 zoomtst4 zoomtst5 zoomtst6 zoomtst7 +bin_PROGRAMS = zoomsh + +zoomtst1_SOURCES = zoomtst1.c +zoomtst2_SOURCES = zoomtst2.c +zoomtst3_SOURCES = zoomtst3.c +zoomtst4_SOURCES = zoomtst4.c +zoomtst5_SOURCES = zoomtst5.c +zoomtst6_SOURCES = zoomtst6.c +zoomtst7_SOURCES = zoomtst7.c +zoomsh_SOURCES = zoomsh.c diff --git a/zoom/zoom-c.c b/zoom/zoom-c.c new file mode 100644 index 0000000..51908f8 --- /dev/null +++ b/zoom/zoom-c.c @@ -0,0 +1,1460 @@ +/* + * $Id: zoom-c.c,v 1.1 2001-10-23 21:00:20 adam Exp $ + * + * ZOOM layer for C, connections, result sets, queries. + */ +#include +#include +#include +#include +#include +#include + +#include "zoom-p.h" + +static Z3950_record record_cache_lookup (Z3950_resultset r, + int pos, + const char *elementSetName); + +static void clear_error (Z3950_connection c) +{ + c->error = Z3950_ERROR_NONE; + xfree (c->addinfo); + c->addinfo = 0; +} + +Z3950_connection Z3950_connection_create (Z3950_options options) +{ + Z3950_connection c = xmalloc (sizeof(*c)); + + c->event_pending = 0; + c->cs = 0; + c->mask = 0; + c->state = STATE_IDLE; + c->error = Z3950_ERROR_NONE; + c->addinfo = 0; + c->buf_in = 0; + c->len_in = 0; + c->buf_out = 0; + c->len_out = 0; + c->resultsets = 0; + + c->options = Z3950_options_create_with_parent(options); + + c->host_port = 0; + c->proxy = 0; + + c->cookie_out = 0; + c->cookie_in = 0; + c->tasks = 0; + + c->odr_in = odr_createmem (ODR_DECODE); + c->odr_out = odr_createmem (ODR_ENCODE); + + c->async = 0; + return c; +} + +/* set database names. Take local databases (if set); otherwise + take databases given in ZURL (if set); otherwise use Default */ +static char **set_DatabaseNames (Z3950_connection con, int *num) +{ + char **databaseNames; + const char *c; + int no = 2; + const char *cp = Z3950_options_get (con->options, "databaseName"); + + if (!cp || !*cp) + { + cp = strchr (con->host_port, '/'); + if (cp) + cp++; + } + if (cp) + { + c = cp; + while ((c = strchr(c, '+'))) + { + c++; + no++; + } + } + else + cp = "Default"; + databaseNames = odr_malloc (con->odr_out, no * sizeof(*databaseNames)); + no = 0; + while (*cp) + { + c = strchr (cp, '+'); + if (!c) + c = cp + strlen(cp); + else if (c == cp) + { + cp++; + continue; + } + /* cp ptr to first char of db name, c is char + following db name */ + databaseNames[no] = odr_malloc (con->odr_out, 1+c-cp); + memcpy (databaseNames[no], cp, c-cp); + databaseNames[no++][c-cp] = '\0'; + cp = c; + if (*cp) + cp++; + } + databaseNames[no] = NULL; + *num = no; + return databaseNames; +} + +Z3950_connection Z3950_connection_new (const char *host, int portnum) +{ + Z3950_connection c = Z3950_connection_create (0); + + Z3950_connection_connect (c, host, portnum); + return c; +} + +void Z3950_connection_connect(Z3950_connection c, + const char *host, int portnum) +{ + const char *val; + + val = Z3950_options_get (c->options, "proxy"); + if (val && *val) + c->proxy = xstrdup (val); + else + c->proxy = 0; + + if (portnum) + { + char hostn[128]; + sprintf (hostn, "%.80s:%d", host, portnum); + c->host_port = xstrdup(hostn); + } + else + c->host_port = xstrdup(host); + + c->async = Z3950_options_get_bool (c->options, "async", 0); + + if (!c->async) + { + while (Z3950_event (1, &c)) + ; + } +} + +Z3950_search Z3950_search_create(void) +{ + Z3950_search s = xmalloc (sizeof(*s)); + + s->refcount = 1; + s->query = 0; + s->sort_spec = 0; + s->odr = odr_createmem (ODR_ENCODE); + + return s; +} + +const char *Z3950_connection_host (Z3950_connection c) +{ + return c->host_port; +} + +void Z3950_search_destroy(Z3950_search s) +{ + if (!s) + return; + + (s->refcount)--; + yaz_log (LOG_DEBUG, "Z3950_search_destroy count=%d", s->refcount); + if (s->refcount == 0) + { + odr_destroy (s->odr); + xfree (s); + } +} + +int Z3950_search_prefix(Z3950_search s, const char *str) +{ + s->query = odr_malloc (s->odr, sizeof(*s->query)); + s->query->which = Z_Query_type_1; + s->query->u.type_1 = p_query_rpn(s->odr, PROTO_Z3950, str); + if (!s->query->u.type_1) + return -1; + return 0; +} + +int Z3950_search_sortby(Z3950_search s, const char *criteria) +{ + s->sort_spec = yaz_sort_spec (s->odr, criteria); + if (!s->sort_spec) + return -1; + return 0; +} + +static int do_write(Z3950_connection c); + + +Z3950_task Z3950_connection_add_task (Z3950_connection c, int which) +{ + Z3950_task *taskp = &c->tasks; + while (*taskp) + taskp = &(*taskp)->next; + *taskp = xmalloc (sizeof(**taskp)); + (*taskp)->running = 0; + (*taskp)->which = which; + (*taskp)->u.resultset = 0; /* one null pointer there at least */ + (*taskp)->next = 0; + clear_error (c); + return *taskp; +} + +void Z3950_connection_remove_task (Z3950_connection c) +{ + Z3950_task task = c->tasks; + + if (task) + { + c->tasks = task->next; + switch (task->which) + { + case Z3950_TASK_SEARCH: + Z3950_resultset_destroy (task->u.resultset); + break; + case Z3950_TASK_RETRIEVE: + Z3950_resultset_destroy (task->u.resultset); + break; + default: + assert (0); + } + xfree (task); + } +} + +void Z3950_connection_remove_tasks (Z3950_connection c) +{ + while (c->tasks) + Z3950_connection_remove_task(c); +} + +void Z3950_connection_destroy(Z3950_connection c) +{ + Z3950_resultset r; + if (!c) + return; + if (c->cs) + cs_close (c->cs); + for (r = c->resultsets; r; r = r->next) + r->connection = 0; + + xfree (c->buf_in); + xfree (c->addinfo); + odr_destroy (c->odr_in); + odr_destroy (c->odr_out); + Z3950_options_destroy (c->options); + Z3950_connection_remove_tasks (c); + xfree (c->host_port); + xfree (c); +} + +void Z3950_resultset_addref (Z3950_resultset r) +{ + if (r) + (r->refcount)++; +} +Z3950_resultset Z3950_resultset_create () +{ + Z3950_resultset r = xmalloc (sizeof(*r)); + + r->refcount = 1; + r->size = 0; + r->odr = odr_createmem (ODR_ENCODE); + r->start = 0; + r->piggyback = 1; + r->count = 0; + r->record_cache = 0; + r->r_sort_spec = 0; + r->r_query = 0; + r->search = 0; + r->connection = 0; + r->next = 0; + return r; +} + +Z3950_resultset Z3950_connection_search_pqf(Z3950_connection c, const char *q) +{ + Z3950_resultset r; + Z3950_search s = Z3950_search_create(); + + Z3950_search_prefix (s, q); + + r = Z3950_connection_search (c, s); + Z3950_search_destroy (s); + return r; +} + +Z3950_resultset Z3950_connection_search(Z3950_connection c, Z3950_search q) +{ + Z3950_resultset r = Z3950_resultset_create (); + Z3950_task task; + + r->r_sort_spec = q->sort_spec; + r->r_query = q->query; + r->search = q; + + r->options = Z3950_options_create_with_parent(c->options); + + r->start = Z3950_options_get_int(r->options, "start", 0); + r->count = Z3950_options_get_int(r->options, "count", 0); + r->piggyback = Z3950_options_get_bool (r->options, "piggyback", 1); + r->connection = c; + + r->next = c->resultsets; + c->resultsets = r; + + task = Z3950_connection_add_task (c, Z3950_TASK_SEARCH); + task->u.resultset = r; + Z3950_resultset_addref (r); + + (q->refcount)++; + + if (!c->async) + { + while (Z3950_event (1, &c)) + ; + } + return r; +} + +void Z3950_resultset_destroy(Z3950_resultset r) +{ + if (!r) + return; + (r->refcount)--; + yaz_log (LOG_DEBUG, "destroy r = %p count=%d", r, r->refcount); + if (r->refcount == 0) + { + if (r->connection) + { + /* remove ourselves from the resultsets in connection */ + Z3950_resultset *rp = &r->connection->resultsets; + while (1) + { + assert (*rp); /* we must be in this list!! */ + if (*rp == r) + { /* OK, we're here - take us out of it */ + *rp = (*rp)->next; + break; + } + rp = &(*rp)->next; + } + } + Z3950_search_destroy (r->search); + Z3950_options_destroy (r->options); + odr_destroy (r->odr); + xfree (r); + } +} + +int Z3950_resultset_size (Z3950_resultset r) +{ + return r->size; +} + +static void do_close (Z3950_connection c) +{ + if (c->cs) + cs_close(c->cs); + c->cs = 0; + c->mask = 0; + c->state = STATE_IDLE; +} + +static void Z3950_resultset_retrieve (Z3950_resultset r, + int force_sync, int start, int count) +{ + Z3950_task task; + Z3950_connection c; + + if (!r) + return; + c = r->connection; + if (!c) + return; + task = Z3950_connection_add_task (c, Z3950_TASK_RETRIEVE); + task->u.resultset = r; + Z3950_resultset_addref (r); + + r->start = start; + r->count = count; + + if (!r->connection->async || force_sync) + while (r->connection && Z3950_event (1, &r->connection)) + ; +} + +void Z3950_resultset_records (Z3950_resultset r, Z3950_record *recs, + size_t *cnt) +{ + int force_present = 0; + int start, count; + + if (!r) + return ; + start = Z3950_options_get_int (r->options, "start", 0); + count = Z3950_options_get_int (r->options, "count", 0); + if (cnt && recs) + force_present = 1; + Z3950_resultset_retrieve (r, force_present, start, count); + if (force_present) + { + int i; + for (i = 0; i< *cnt; i++) + recs[i] = Z3950_resultset_record_immediate (r, i+start); + } +} + +static void do_connect (Z3950_connection c) +{ + void *add; + const char *effective_host; + + if (c->proxy) + effective_host = c->proxy; + else + effective_host = c->host_port; + + yaz_log (LOG_DEBUG, "do_connect host=%s", effective_host); + + assert (!c->cs); + c->cs = cs_create_host (effective_host, 0, &add); + + if (c->cs) + { + cs_connect (c->cs, add); + c->state = STATE_CONNECTING; + c->mask = Z3950_SELECT_READ | Z3950_SELECT_WRITE; + } + else + { + c->state = STATE_IDLE; + c->error = Z3950_ERROR_CONNECT; + } +} + +int z3950_connection_socket(Z3950_connection c) +{ + if (c->cs) + return cs_fileno(c->cs); + return -1; +} + +int z3950_connection_mask(Z3950_connection c) +{ + if (c->cs) + return c->mask; + return 0; +} + +static int encode_APDU(Z3950_connection c, Z_APDU *a, ODR out) +{ + char str[120]; + + assert (a); + sprintf (str, "send_APDU t=%p type=%d", c, a->which); + if (c->cookie_out) + { + Z_OtherInformation **oi; + yaz_oi_APDU(a, &oi); + yaz_oi_set_string_oidval(oi, out, VAL_COOKIE, 1, c->cookie_out); + } + if (!z_APDU(out, &a, 0, 0)) + { + FILE *outf = fopen("/tmp/apdu.txt", "w"); + if (outf) + { + ODR odr_pr = odr_createmem(ODR_PRINT); + fprintf (outf, "a=%p\n", a); + odr_setprint(odr_pr, outf); + z_APDU(odr_pr, &a, 0, 0); + odr_destroy(odr_pr); + fclose (outf); + } + c->error = Z3950_ERROR_ENCODE; + do_close (c); + return -1; + } + return 0; +} + +static int send_APDU (Z3950_connection c, Z_APDU *a) +{ + assert (a); + if (encode_APDU(c, a, c->odr_out)) + return -1; + c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0); + odr_reset(c->odr_out); + do_write (c); + return 0; +} + +static int Z3950_connection_send_init (Z3950_connection c) +{ + const char *impname; + Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_initRequest); + Z_InitRequest *ireq = apdu->u.initRequest; + Z_IdAuthentication *auth = odr_malloc(c->odr_out, sizeof(*auth)); + const char *auth_groupId = Z3950_options_get (c->options, "group"); + const char *auth_userId = Z3950_options_get (c->options, "user"); + const char *auth_password = Z3950_options_get (c->options, "pass"); + + ODR_MASK_SET(ireq->options, Z_Options_search); + ODR_MASK_SET(ireq->options, Z_Options_present); + ODR_MASK_SET(ireq->options, Z_Options_scan); + ODR_MASK_SET(ireq->options, Z_Options_sort); +#if 0 + ODR_MASK_SET(ireq->options, Z_Options_extendedServices); + ODR_MASK_SET(ireq->options, Z_Options_namedResultSets); +#endif + + ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_1); + ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_2); + ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_3); + + impname = Z3950_options_get (c->options, "implementationName"); + ireq->implementationName = + odr_malloc (c->odr_out, 15 + (impname ? strlen(impname) : 0)); + strcpy (ireq->implementationName, ""); + if (impname) + { + strcat (ireq->implementationName, impname); + strcat (ireq->implementationName, "/"); + } + strcat (ireq->implementationName, "ZOOM-C/YAZ"); + + *ireq->maximumRecordSize = + Z3950_options_get_int (c->options, "maximumRecordSize", 1024*1024); + *ireq->preferredMessageSize = + Z3950_options_get_int (c->options, "preferredMessageSize", 1024*1024); + + if (auth_groupId || auth_password) + { + Z_IdPass *pass = odr_malloc(c->odr_out, sizeof(*pass)); + int i = 0; + pass->groupId = 0; + if (auth_groupId && *auth_groupId) + { + pass->groupId = odr_malloc(c->odr_out, strlen(auth_groupId)+1); + strcpy(pass->groupId, auth_groupId); + i++; + } + pass->userId = 0; + if (auth_userId && *auth_userId) + { + pass->userId = odr_malloc(c->odr_out, strlen(auth_userId)+1); + strcpy(pass->userId, auth_userId); + i++; + } + pass->password = 0; + if (auth_password && *auth_password) + { + pass->password = odr_malloc(c->odr_out, strlen(auth_password)+1); + strcpy(pass->password, auth_password); + i++; + } + if (i) + { + auth->which = Z_IdAuthentication_idPass; + auth->u.idPass = pass; + ireq->idAuthentication = auth; + } + } + else if (auth_userId) + { + auth->which = Z_IdAuthentication_open; + auth->u.open = odr_malloc(c->odr_out, strlen(auth_userId)+1); + strcpy(auth->u.open, auth_userId); + ireq->idAuthentication = auth; + } + if (c->proxy) + yaz_oi_set_string_oidval(&ireq->otherInfo, c->odr_out, + VAL_PROXY, 1, c->host_port); + assert (apdu); + send_APDU (c, apdu); + + return 0; +} + +static int Z3950_connection_send_search (Z3950_connection c) +{ + Z3950_resultset r; + int lslb, ssub, mspn; + const char *syntax; + Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_searchRequest); + Z_SearchRequest *search_req = apdu->u.searchRequest; + const char *elementSetName; + const char *smallSetElementSetName; + const char *mediumSetElementSetName; + + assert (c->tasks); + assert (c->tasks->which == Z3950_TASK_SEARCH); + + r = c->tasks->u.resultset; + + elementSetName = + Z3950_options_get (r->options, "elementSetName"); + smallSetElementSetName = + Z3950_options_get (r->options, "smallSetElementSetName"); + mediumSetElementSetName = + Z3950_options_get (r->options, "mediumSetElementSetName"); + + if (!smallSetElementSetName) + smallSetElementSetName = elementSetName; + + if (!mediumSetElementSetName) + mediumSetElementSetName = elementSetName; + + assert (r); + assert (r->r_query); + + /* prepare query for the search request */ + search_req->query = r->r_query; + + search_req->databaseNames = + set_DatabaseNames (c, &search_req->num_databaseNames); + + /* get syntax (no need to provide unless piggyback is in effect) */ + syntax = Z3950_options_get (r->options, "preferredRecordSyntax"); + + lslb = Z3950_options_get_int (r->options, "largeSetLowerBound", -1); + ssub = Z3950_options_get_int (r->options, "smallSetUpperBound", -1); + mspn = Z3950_options_get_int (r->options, "mediumSetPresentNumber", -1); + if (lslb != -1 && ssub != -1 && mspn != -1) + { + /* So're a Z39.50 expert? Let's hope you don't do sort */ + *search_req->largeSetLowerBound = lslb; + *search_req->smallSetUpperBound = ssub; + *search_req->mediumSetPresentNumber = mspn; + } + else if (r->start == 0 && r->count > 0 + && r->piggyback && !r->r_sort_spec) + { + /* Regular piggyback - do it unless we're going to do sort */ + *search_req->largeSetLowerBound = 2000000000; + *search_req->smallSetUpperBound = r->count; + *search_req->mediumSetPresentNumber = r->count; + smallSetElementSetName = 0; /* no need to provide this */ + } + else + { + /* non-piggyback. Need not provide elementsets or syntaxes .. */ + smallSetElementSetName = 0; + mediumSetElementSetName = 0; + syntax = 0; + } + if (smallSetElementSetName && *smallSetElementSetName) + { + Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn)); + + esn->which = Z_ElementSetNames_generic; + esn->u.generic = odr_strdup (c->odr_out, smallSetElementSetName); + search_req->smallSetElementSetNames = esn; + } + if (mediumSetElementSetName && *mediumSetElementSetName) + { + Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn)); + + esn->which = Z_ElementSetNames_generic; + esn->u.generic = odr_strdup (c->odr_out, mediumSetElementSetName); + search_req->mediumSetElementSetNames = esn; + } + if (syntax) + search_req->preferredRecordSyntax = + yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, syntax); + + /* send search request */ + send_APDU (c, apdu); + r->r_query = 0; + return 1; +} + +static void response_diag (Z3950_connection c, Z_DiagRec *p) +{ + Z_DefaultDiagFormat *r; + char *addinfo = 0; + + xfree (c->addinfo); + c->addinfo = 0; + if (p->which != Z_DiagRec_defaultFormat) + { + c->error = Z3950_ERROR_DECODE; + return; + } + r = p->u.defaultFormat; + switch (r->which) + { + case Z_DefaultDiagFormat_v2Addinfo: + addinfo = r->u.v2Addinfo; + break; + case Z_DefaultDiagFormat_v3Addinfo: + addinfo = r->u.v3Addinfo; + break; + } + if (addinfo) + c->addinfo = xstrdup (addinfo); + c->error = *r->condition; +} + +Z3950_record Z3950_record_dup (Z3950_record srec) +{ + char *buf; + int size; + ODR odr_enc; + Z3950_record nrec; + + odr_enc = odr_createmem(ODR_ENCODE); + if (!z_NamePlusRecord (odr_enc, &srec->npr, 0, 0)) + return 0; + buf = odr_getbuf (odr_enc, &size, 0); + + nrec = xmalloc (sizeof(*nrec)); + nrec->odr = odr_createmem(ODR_DECODE); + nrec->wrbuf_marc = 0; + odr_setbuf (nrec->odr, buf, size, 0); + z_NamePlusRecord (nrec->odr, &nrec->npr, 0, 0); + + odr_destroy (odr_enc); + return nrec; +} + +Z3950_record Z3950_resultset_record_immediate (Z3950_resultset s, int pos) +{ + Z3950_record rec = record_cache_lookup (s, pos, 0); + if (!rec) + return 0; + return Z3950_record_dup (rec); +} + +Z3950_record Z3950_resultset_record (Z3950_resultset r, int pos) +{ + Z3950_resultset_retrieve (r, 1, pos, 1); + return Z3950_resultset_record_immediate (r, pos); +} + +void Z3950_record_destroy (Z3950_record rec) +{ + if (!rec) + return; + if (rec->wrbuf_marc) + wrbuf_free (rec->wrbuf_marc, 1); + odr_destroy (rec->odr); + xfree (rec); +} + +void *Z3950_record_get (Z3950_record rec, const char *type, int *len) +{ + Z_NamePlusRecord *npr; + if (!rec) + return 0; + npr = rec->npr; + if (!npr) + return 0; + if (!strcmp (type, "database")) + { + return npr->databaseName; + } + else if (!strcmp (type, "syntax")) + { + if (npr->which == Z_NamePlusRecord_databaseRecord) + { + Z_External *r = (Z_External *) npr->u.databaseRecord; + oident *ent = oid_getentbyoid(r->direct_reference); + if (ent) + return ent->desc; + } + return "none"; + } + else if (!strcmp (type, "render")) + { + if (npr->which == Z_NamePlusRecord_databaseRecord) + { + Z_External *r = (Z_External *) npr->u.databaseRecord; + oident *ent = oid_getentbyoid(r->direct_reference); + + if (r->which == Z_External_sutrs) + { + *len = r->u.sutrs->len; + return r->u.sutrs->buf; + } + else if (r->which == Z_External_octet) + { + switch (ent->value) + { + case VAL_SOIF: + case VAL_HTML: + case VAL_SUTRS: + break; + case VAL_TEXT_XML: + case VAL_APPLICATION_XML: + break; + default: + if (!rec->wrbuf_marc) + rec->wrbuf_marc = wrbuf_alloc(); + if (marc_display_wrbuf (r->u.octet_aligned->buf, + rec->wrbuf_marc, 0, + r->u.octet_aligned->len) > 0) + { + *len = wrbuf_len(rec->wrbuf_marc); + return wrbuf_buf(rec->wrbuf_marc); + } + } + *len = r->u.octet_aligned->len; + return r->u.octet_aligned->buf; + } + else if (r->which == Z_External_grs1) + { + *len = 5; + return "GRS-1"; + } + } + return 0; + } + return 0; +} + +void *Z3950_resultset_get (Z3950_resultset s, int pos, const char *type, + int *len) +{ + Z3950_record rec = record_cache_lookup (s, pos, 0); + return Z3950_record_get (rec, type, len); +} + +static void record_cache_add (Z3950_resultset r, + Z_NamePlusRecord *npr, + int pos, + const char *elementSetName) +{ + Z3950_record_cache rc; + + for (rc = r->record_cache; rc; rc = rc->next) + { + if (pos == rc->pos) + { + if ((!elementSetName && !rc->elementSetName) + || (elementSetName && rc->elementSetName && + !strcmp (elementSetName, rc->elementSetName))) + { + /* not destroying rc->npr (it's handled by nmem )*/ + rc->rec.npr = npr; + /* keeping wrbuf_marc too */ + return; + } + } + + } + rc = odr_malloc (r->odr, sizeof(*rc)); + rc->rec.npr = npr; + rc->rec.odr = 0; + rc->rec.wrbuf_marc = 0; + if (elementSetName) + rc->elementSetName = odr_strdup (r->odr, elementSetName); + else + rc->elementSetName = 0; + rc->pos = pos; + rc->next = r->record_cache; + r->record_cache = rc; +} + +static Z3950_record record_cache_lookup (Z3950_resultset r, + int pos, + const char *elementSetName) +{ + Z3950_record_cache rc; + + for (rc = r->record_cache; rc; rc = rc->next) + { + if (pos == rc->pos) + { + if ((!elementSetName && !rc->elementSetName) + || (elementSetName && rc->elementSetName && + !strcmp (elementSetName, rc->elementSetName))) + return &rc->rec; + } + } + return 0; +} + +static void handle_records (Z3950_connection c, Z_Records *sr, + int present_phase) +{ + Z3950_resultset resultset; + + if (!c->tasks) + return ; + if (c->tasks->which != Z3950_TASK_SEARCH && + c->tasks->which != Z3950_TASK_RETRIEVE) + return ; + + resultset = c->tasks->u.resultset; + + if (sr && sr->which == Z_Records_NSD) + { + Z_DiagRec dr, *dr_p = &dr; + dr.which = Z_DiagRec_defaultFormat; + dr.u.defaultFormat = sr->u.nonSurrogateDiagnostic; + + response_diag (c, dr_p); + } + else if (sr && sr->which == Z_Records_multipleNSD) + { + if (sr->u.multipleNonSurDiagnostics->num_diagRecs >= 1) + response_diag(c, sr->u.multipleNonSurDiagnostics->diagRecs[0]); + else + c->error = Z3950_ERROR_DECODE; + } + else + { + if (resultset->count + resultset->start > resultset->size) + resultset->count = resultset->size - resultset->start; + if (resultset->count < 0) + resultset->count = 0; + if (sr && sr->which == Z_Records_DBOSD) + { + int i; + NMEM nmem = odr_extract_mem (c->odr_in); + Z_NamePlusRecordList *p = + sr->u.databaseOrSurDiagnostics; + for (i = 0; inum_records; i++) + { + record_cache_add (resultset, p->records[i], + i+ resultset->start, 0); + } + /* transfer our response to search_nmem .. we need it later */ + nmem_transfer (resultset->odr->mem, nmem); + nmem_destroy (nmem); + if (present_phase && p->num_records == 0) + { + /* present response and we didn't get any records! */ + c->error = Z3950_ERROR_DECODE; + } + } + else if (present_phase) + { + /* present response and we didn't get any records! */ + c->error = Z3950_ERROR_DECODE; + } + } +} + +static void handle_present_response (Z3950_connection c, Z_PresentResponse *pr) +{ + handle_records (c, pr->records, 1); +} + +static void handle_search_response (Z3950_connection c, Z_SearchResponse *sr) +{ + Z3950_resultset resultset; + + yaz_log (LOG_DEBUG, "got search response"); + + if (!c->tasks || c->tasks->which != Z3950_TASK_SEARCH) + return ; + + resultset = c->tasks->u.resultset; + + resultset->size = *sr->resultCount; + handle_records (c, sr->records, 0); +} + +static void sort_response (Z3950_connection c, Z_SortResponse *res) +{ + if (res->diagnostics && res->num_diagnostics > 0) + response_diag (c, res->diagnostics[0]); +} + +static int send_sort (Z3950_connection c) +{ + Z3950_resultset resultset; + + if (!c->tasks || c->tasks->which != Z3950_TASK_SEARCH) + return 0; + + resultset = c->tasks->u.resultset; + + if (c->error) + { + resultset->r_sort_spec = 0; + return 0; + } + if (resultset->r_sort_spec) + { + Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_sortRequest); + Z_SortRequest *req = apdu->u.sortRequest; + + req->num_inputResultSetNames = 1; + req->inputResultSetNames = (Z_InternationalString **) + odr_malloc (c->odr_out, sizeof(*req->inputResultSetNames)); + req->inputResultSetNames[0] = odr_strdup (c->odr_out, "default"); + req->sortedResultSetName = odr_strdup (c->odr_out, "default"); + req->sortSequence = resultset->r_sort_spec; + resultset->r_sort_spec = 0; + send_APDU (c, apdu); + return 1; + } + return 0; +} + +static int send_present (Z3950_connection c) +{ + Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_presentRequest); + Z_PresentRequest *req = apdu->u.presentRequest; + int i = 0; + const char *syntax = + Z3950_options_get (c->options, "preferredRecordSyntax"); + const char *element = + Z3950_options_get (c->options, "elementSetName"); + Z3950_resultset resultset; + + if (!c->tasks) + return 0; + if (c->tasks->which != Z3950_TASK_SEARCH && + c->tasks->which != Z3950_TASK_RETRIEVE) + return 0; + + resultset = c->tasks->u.resultset; + + if (c->error) /* don't continue on error */ + return 0; + if (resultset->start < 0) + return 0; + for (i = 0; icount; i++) + { + Z3950_record rec = + record_cache_lookup (resultset, i + resultset->start, 0); + if (!rec) + break; + } + if (i == resultset->count) + return 0; + + resultset->start += i; + resultset->count -= i; + *req->resultSetStartPoint = resultset->start + 1; + *req->numberOfRecordsRequested = resultset->count; + assert (*req->numberOfRecordsRequested > 0); + + if (syntax && *syntax) + req->preferredRecordSyntax = + yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, syntax); + + if (element && *element) + { + Z_ElementSetNames *esn = odr_malloc (c->odr_out, sizeof(*esn)); + Z_RecordComposition *compo = odr_malloc (c->odr_out, sizeof(*compo)); + + esn->which = Z_ElementSetNames_generic; + esn->u.generic = odr_strdup (c->odr_out, element); + compo->which = Z_RecordComp_simple; + compo->u.simple = esn; + req->recordComposition = compo; + } + send_APDU (c, apdu); + return 1; +} + +static int Z3950_connection_exec_task (Z3950_connection c) +{ + Z3950_task task = c->tasks; + + yaz_log (LOG_DEBUG, "Z3950_connection_exec_task"); + if (!task) + return 0; + if (c->error != Z3950_ERROR_NONE || !c->cs) + { + Z3950_connection_remove_tasks (c); + return 0; + } + yaz_log (LOG_DEBUG, "Z3950_connection_exec_task type=%d", task->which); + if (task->running) + return 0; + task->running = 1; + switch (task->which) + { + case Z3950_TASK_SEARCH: + /* see if search hasn't been sent yet. */ + if (Z3950_connection_send_search (c)) + return 1; + break; + case Z3950_TASK_RETRIEVE: + if (send_present (c)) + return 1; + break; + } + Z3950_connection_remove_task (c); + return 0; +} + +static int send_sort_present (Z3950_connection c) +{ + int r = send_sort (c); + if (!r) + r = send_present (c); + return r; +} + +static void handle_apdu (Z3950_connection c, Z_APDU *apdu) +{ + Z_InitResponse *initrs; + + yaz_log (LOG_DEBUG, "hande_apdu type=%d", apdu->which); + c->mask = 0; + switch(apdu->which) + { + case Z_APDU_initResponse: + initrs = apdu->u.initResponse; + if (!*initrs->result) + { + c->error = Z3950_ERROR_INIT; + } + else + { + char *cookie = + yaz_oi_get_string_oidval (&apdu->u.initResponse->otherInfo, + VAL_COOKIE, 1, 0); + xfree (c->cookie_in); + c->cookie_in = 0; + if (cookie) + c->cookie_in = xstrdup(cookie); + Z3950_connection_exec_task (c); + } + break; + case Z_APDU_searchResponse: + handle_search_response (c, apdu->u.searchResponse); + if (!send_sort_present (c)) + Z3950_connection_remove_task (c); + break; + case Z_APDU_presentResponse: + handle_present_response (c, apdu->u.presentResponse); + if (!send_present (c)) + Z3950_connection_remove_task (c); + break; + case Z_APDU_sortResponse: + sort_response (c, apdu->u.sortResponse); + if (!send_present (c)) + Z3950_connection_remove_task (c); + } +} + +static int do_read (Z3950_connection c) +{ + int r; + Z_APDU *apdu; + + r = cs_get (c->cs, &c->buf_in, &c->len_in); + if (r == 1) + return 0; + if (r <= 0) + { + c->error= Z3950_ERROR_CONNECTION_LOST; + do_close (c); + } + else + { + odr_reset (c->odr_in); + odr_setbuf (c->odr_in, c->buf_in, r, 0); + if (!z_APDU (c->odr_in, &apdu, 0, 0)) + { + c->error = Z3950_ERROR_DECODE; + do_close (c); + } + else + { + handle_apdu (c, apdu); + } + } + return 1; +} + +static int do_write_ex (Z3950_connection c, char *buf_out, int len_out) +{ + int r; + + if ((r=cs_put (c->cs, buf_out, len_out)) < 0) + { + if (c->state == STATE_CONNECTING) + c->error = Z3950_ERROR_CONNECT; + else + c->error = Z3950_ERROR_CONNECTION_LOST; + do_close (c); + return 1; + } + else if (r == 1) + { + c->state = STATE_ESTABLISHED; + c->mask = Z3950_SELECT_READ|Z3950_SELECT_WRITE; + } + else + { + c->state = STATE_ESTABLISHED; + c->mask = Z3950_SELECT_READ; + } + return 0; +} + +static int do_write(Z3950_connection c) +{ + return do_write_ex (c, c->buf_out, c->len_out); +} + +const char *Z3950_connection_option (Z3950_connection c, const char *key, + const char *val) +{ + const char *old_val = Z3950_options_get (c->options, key); + if (val) + { + Z3950_options_set (c->options, key, val); + } + return old_val; +} + +const char *Z3950_resultset_option (Z3950_resultset r, const char *key, + const char *val) +{ + const char *old_val = Z3950_options_get (r->options, key); + if (val) + { + Z3950_options_set (r->options, key, val); + } + return old_val; +} + + +int Z3950_connection_errcode (Z3950_connection c) +{ + return Z3950_connection_error (c, 0, 0); +} + +const char *Z3950_connection_errmsg (Z3950_connection c) +{ + const char *msg; + Z3950_connection_error (c, &msg, 0); + return msg; +} + +const char *Z3950_connection_addinfo (Z3950_connection c) +{ + const char *addinfo; + Z3950_connection_error (c, 0, &addinfo); + return addinfo; +} + +int Z3950_connection_error (Z3950_connection c, const char **cp, + const char **addinfo) +{ + int error = c->error; + if (cp) + { + switch (error) + { + case Z3950_ERROR_NONE: + *cp = "No error"; break; + case Z3950_ERROR_CONNECT: + *cp = "Connect failed"; break; + case Z3950_ERROR_MEMORY: + *cp = "Out of memory"; break; + case Z3950_ERROR_ENCODE: + *cp = "Encoding failed"; break; + case Z3950_ERROR_DECODE: + *cp = "Decoding failed"; break; + case Z3950_ERROR_CONNECTION_LOST: + *cp = "Connection lost"; break; + case Z3950_ERROR_INIT: + *cp = "Init rejected"; break; + case Z3950_ERROR_INTERNAL: + *cp = "Internal failure"; break; + case Z3950_ERROR_TIMEOUT: + *cp = "Timeout"; break; + default: + *cp = diagbib1_str (error); + } + } + if (addinfo) + { + if (c->addinfo) + *addinfo = c->addinfo; + else + *addinfo = ""; + } + return c->error; +} + +int Z3950_connection_do_io(Z3950_connection c, int mask) +{ +#if 0 + int r = cs_look(c->cs); + yaz_log (LOG_LOG, "Z3950_connection_do_io c=%p mask=%d cs_look=%d", + c, mask, r); + + if (r == CS_NONE) + { + c->error = Z3950_ERROR_CONNECT; + do_close (c); + } + else if (r == CS_CONNECT) + { + yaz_log (LOG_LOG, "calling rcvconnect"); + if (cs_rcvconnect (c->cs) < 0) + { + c->error = Z3950_ERROR_CONNECT; + do_close (c); + } + else + Z3950_connection_send_init (c); + } + else + { + if (mask & Z3950_SELECT_READ) + do_read (c); + if (c->cs && (mask & Z3950_SELECT_WRITE)) + do_write (c); + } +#else + yaz_log (LOG_DEBUG, "Z3950_connection_do_io c=%p mask=%d", c, mask); + if (c->state == STATE_CONNECTING) + { + if (mask & Z3950_SELECT_WRITE) + Z3950_connection_send_init (c); + else + { + c->error = Z3950_ERROR_CONNECT; + do_close (c); + } + } + else if (c->state == STATE_ESTABLISHED) + { + if (mask & Z3950_SELECT_READ) + do_read (c); + if (c->cs && (mask & Z3950_SELECT_WRITE)) + do_write (c); + } + else + { + c->error = Z3950_ERROR_INTERNAL; + do_close (c); + } +#endif + c->event_pending = 1; + return 1; +} + +int Z3950_event (int no, Z3950_connection *cs) +{ + struct timeval tv; + fd_set input, output; + int i, r; + int max_fd = 0; + + for (i = 0; ievent_pending) + { + c->event_pending = 0; + return i+1; + } + } + + tv.tv_sec = 15; + tv.tv_usec = 0; + + FD_ZERO (&input); + FD_ZERO (&output); + r = 0; + for (i = 0; ics && c->host_port && c->error == Z3950_ERROR_NONE) + { + do_connect (c); + return i+1; + } + else + { + if (Z3950_connection_exec_task (c)) + return i+1; + } + } + yaz_log (LOG_DEBUG, "no more events"); + return 0; + } + r = select (max_fd+1, &input, &output, 0, &tv); + + for (i = 0; imask) + { + /* no timeout and real socket */ + if (FD_ISSET(fd, &input)) + mask += Z3950_SELECT_READ; + if (FD_ISSET(fd, &output)) + mask += Z3950_SELECT_WRITE; + if (mask) + Z3950_connection_do_io(c, mask); + } + if (r == 0 && c->mask) + { + /* timeout and this connection was waiting */ + c->error = Z3950_ERROR_TIMEOUT; + c->event_pending = 1; + } + } + for (i = 0; ievent_pending) + { + c->event_pending = 0; + return i+1; + } + } + return 0; +} diff --git a/zoom/zoom-opt.c b/zoom/zoom-opt.c new file mode 100644 index 0000000..ddb5a89 --- /dev/null +++ b/zoom/zoom-opt.c @@ -0,0 +1,134 @@ +/* + * $Id: zoom-opt.c,v 1.1 2001-10-23 21:00:20 adam Exp $ + * + * ZOOM layer for C, options handling + */ +#include +#include +#include + +#include "zoom-p.h" + +Z3950_options Z3950_options_create (void) +{ + return Z3950_options_create_with_parent (0); +} + +Z3950_options Z3950_options_create_with_parent (Z3950_options parent) +{ + Z3950_options opt = xmalloc (sizeof(*opt)); + + opt->refcount = 1; + opt->callback_func = 0; + opt->callback_handle = 0; + opt->entries = 0; + opt->parent= parent; + if (parent) + (parent->refcount)++; + return opt; +} + +void Z3950_options_addref (Z3950_options opt) +{ + (opt->refcount)++; +} + +Z3950_options_callback Z3950_options_set_callback ( + Z3950_options opt, + Z3950_options_callback callback_func, + void *callback_handle) +{ + Z3950_options_callback callback_old; + + assert (opt); + callback_old = opt->callback_func; + opt->callback_func = callback_func; + opt->callback_handle = callback_handle; + return callback_old; +} + +void Z3950_options_destroy (Z3950_options opt) +{ + if (!opt) + return; + (opt->refcount)--; + if (opt->refcount == 0) + { + struct Z3950_options_entry *e; + + Z3950_options_destroy (opt->parent); + e = opt->entries; + while (e) + { + struct Z3950_options_entry *e0 = e; + xfree (e->name); + xfree (e->value); + e = e->next; + xfree (e0); + } + xfree (opt); + } +} + +void Z3950_options_set (Z3950_options opt, const char *name, const char *value) +{ + struct Z3950_options_entry **e; + + e = &opt->entries; + while (*e) + { + if (!strcmp((*e)->name, name)) + { + xfree ((*e)->value); + (*e)->value = xstrdup(value); + return; + } + e = &(*e)->next; + } + *e = xmalloc (sizeof(**e)); + (*e)->name = xstrdup (name); + (*e)->value = xstrdup (value); + (*e)->next = 0; +} + +const char *Z3950_options_get (Z3950_options opt, const char *name) +{ + const char *v = 0; + if (!opt) + return 0; + if (opt->callback_func) + v = (*opt->callback_func)(opt->callback_handle, name); + if (!v) + { + struct Z3950_options_entry *e; + for (e = opt->entries; e; e = e->next) + if (!strcmp(e->name, name)) + { + v = e->value; + break; + } + } + if (!v) + return Z3950_options_get(opt->parent, name); + return v; +} + +int Z3950_options_get_bool (Z3950_options opt, const char *name, int defa) +{ + const char *v = Z3950_options_get (opt, name); + + if (!v) + return defa; + if (!strcmp (v, "1") || !strcmp(v, "T")) + return 1; + return 0; +} + +int Z3950_options_get_int (Z3950_options opt, const char *name, int defa) +{ + const char *v = Z3950_options_get (opt, name); + + if (!v || !*v) + return defa; + return atoi(v); +} diff --git a/zoom/zoom-p.h b/zoom/zoom-p.h new file mode 100644 index 0000000..3383d34 --- /dev/null +++ b/zoom/zoom-p.h @@ -0,0 +1,112 @@ +/* + * Private C header for ZOOM C. + * $Id: zoom-p.h,v 1.1 2001-10-23 21:00:20 adam Exp $ + */ +#include +#include +#include +#include + +struct Z3950_search_p { + Z_Query *query; + Z_SortKeySpecList *sort_spec; + int refcount; + ODR odr; +}; + +#define STATE_IDLE 0 +#define STATE_CONNECTING 1 +#define STATE_ESTABLISHED 2 + +#define Z3950_SELECT_READ 1 +#define Z3950_SELECT_WRITE 2 + +struct Z3950_connection_p { + COMSTACK cs; + char *host_port; + int error; + char *addinfo; + int state; + int mask; + ODR odr_in; + ODR odr_out; + char *buf_in; + int len_in; + char *buf_out; + int len_out; + char *proxy; + char *cookie_out; + char *cookie_in; + int async; + int event_pending; + Z3950_task tasks; + Z3950_options options; + Z3950_resultset resultsets; +}; + + +struct Z3950_options_entry { + char *name; + char *value; + struct Z3950_options_entry *next; +}; + +struct Z3950_options_p { + int refcount; + void *callback_handle; + Z3950_options_callback callback_func; + struct Z3950_options_entry *entries; + Z3950_options parent; +}; + +typedef struct Z3950_record_cache_p *Z3950_record_cache; + +struct Z3950_resultset_p { + Z_Query *r_query; + Z_SortKeySpecList *r_sort_spec; + Z3950_search search; + int refcount; + int size; + int start; + int count; + int piggyback; + ODR odr; + Z3950_record_cache record_cache; + Z3950_options options; + Z3950_connection connection; + Z3950_resultset next; +}; + +struct Z3950_record_p { + ODR odr; + WRBUF wrbuf_marc; + Z_NamePlusRecord *npr; +}; + +struct Z3950_record_cache_p { + struct Z3950_record_p rec; + char *elementSetName; + int pos; + Z3950_record_cache next; +}; + +struct Z3950_task_p { + int running; + int which; + union { +#define Z3950_TASK_SEARCH 1 + Z3950_resultset resultset; +#define Z3950_TASK_RETRIEVE 2 + /** also resultset here */ + + } u; + Z3950_task next; +}; + +#ifndef YAZ_DATE +COMSTACK cs_create_host(const char *type_and_host, int blocking, void **vp); +Odr_oid *yaz_str_to_z3950oid (ODR o, int oid_class, const char *str); +Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg); +#else +#include +#endif diff --git a/zoom/zoomsh.c b/zoom/zoomsh.c new file mode 100644 index 0000000..2f3897f --- /dev/null +++ b/zoom/zoomsh.c @@ -0,0 +1,394 @@ +/* + * $Id: zoomsh.c,v 1.1 2001-10-23 21:00:20 adam Exp $ + * + * ZOOM-C Shell + */ + +#include +#include +#include +#include + +#define HAVE_READLINE_READLINE_H 1 +#define HAVE_READLINE_HISTORY_H 1 + +#if HAVE_READLINE_READLINE_H +#include +#endif +#if HAVE_READLINE_HISTORY_H +#include +#endif + +#include + +#include + +#define MAX_CON 100 + +static int next_token (const char **cpp, const char **t_start) +{ + int len = 0; + const char *cp = *cpp; + while (*cp == ' ') + cp++; + *t_start = cp; + while (*cp && *cp != ' ') + { + cp++; + len++; + } + *cpp = cp; + return len; +} + +static int next_token_copy (const char **cpp, char *buf_out, int buf_max) +{ + const char *start; + int len = next_token (cpp, &start); + if (!len) + { + *buf_out = 0; + return 0; + } + if (len >= buf_max) + len = buf_max-1; + memcpy (buf_out, start, len); + buf_out[len] = '\0'; + return len; +} + +static int is_command (const char *cmd_str, const char *this_str, int this_len) +{ + int cmd_len = strlen(cmd_str); + if (cmd_len != this_len) + return 0; + if (memcmp (cmd_str, this_str, cmd_len)) + return 0; + return 1; +} + +static void cmd_set (Z3950_connection *c, Z3950_resultset *r, + Z3950_options options, + const char **args) +{ + char key[40], val[80]; + + if (!next_token_copy (args, key, sizeof(key))) + { + printf ("missing argument for set\n"); + return ; + } + if (!next_token_copy (args, val, sizeof(val))) + { + const char *val = Z3950_options_get(options, key); + printf ("%s = %s\n", key, val ? val : ""); + } + else + Z3950_options_set(options, key, val); +} + +static void cmd_close (Z3950_connection *c, Z3950_resultset *r, + Z3950_options options, + const char **args) +{ + char host[60]; + int i; + next_token_copy (args, host, sizeof(host)); + for (i = 0; i\n"); + printf ("search \n"); + printf ("show [ []\n"); + printf ("quit\n"); + printf ("close \n"); + printf ("set