Old Z39.50 codecs gone. Added ZOOM. WRBUF MARC display util.
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 23 Oct 2001 21:00:19 +0000 (21:00 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 23 Oct 2001 21:00:19 +0000 (21:00 +0000)
32 files changed:
CHANGELOG
Makefile.am
README
buildconf.sh
configure.in
doc/Makefile.am
doc/yaz.xml
doc/zoom.xml [new file with mode: 0644]
include/yaz/Makefile.am
include/yaz/proto.h [new file with mode: 0644]
include/yaz/wrbuf.h
include/yaz/z-proto.h [deleted file]
include/yaz/zoom.h [new file with mode: 0644]
lib/Makefile.am
util/marcdisp.c
yaz.spec
z39.50/Makefile.am
z39.50/prt-ext.c [new file with mode: 0644]
zoom/Makefile.am [new file with mode: 0644]
zoom/zoom-c.c [new file with mode: 0644]
zoom/zoom-opt.c [new file with mode: 0644]
zoom/zoom-p.h [new file with mode: 0644]
zoom/zoomsh.c [new file with mode: 0644]
zoom/zoomtst1.c [new file with mode: 0644]
zoom/zoomtst2.c [new file with mode: 0644]
zoom/zoomtst3.c [new file with mode: 0644]
zoom/zoomtst4.c [new file with mode: 0644]
zoom/zoomtst5.c [new file with mode: 0644]
zoom/zoomtst6.c [new file with mode: 0644]
zoom/zoomtst7.c [new file with mode: 0644]
zutil/Makefile.am
zutil/prt-ext.c [deleted file]

index 67647a7..a34cef7 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
 Possible compatibility problems with earlier versions marked with '*'.
 
 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.
 Renamed states for COMSTACKs to avoid confusion with events.
 
 Implemented cs_look and proper cs_rcvconnect.
index 31fb0f2..f14cf4b 100644 (file)
@@ -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 
 
 
 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@
 
 
 SUBDIRS = @SUBDIRS_VAR@
 
diff --git a/README b/README
index 979bd9b..6564608 100644 (file)
--- 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 
 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
 
 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
 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
 
 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:<hostname>:<port>[/<database>]
+  yaz-client <hostname>[:<port>[/<database>]]
 
 at the UNIX prompt, to connect to a Z39.50 server.
 
 
 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.
 
        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
 
 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.
 
 
 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.
 
        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).
 
 
 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.
 
 
 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.
 
 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
 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
index 3debbfc..6012912 100755 (executable)
@@ -1,8 +1,9 @@
 #!/bin/sh
 #!/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
 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
 autoconf || exit 4
 if [ -f config.cache ]; then
        rm config.cache
index 830a28f..d22c22d 100644 (file)
@@ -1,6 +1,6 @@
 dnl YAZ Toolkit, Index Data 1994-2001
 dnl See the file LICENSE for details.
 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
 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)
 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
 ],[
 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
 ])
 EXTRALIB=""
 for module in $EXTRAMODULE; do
@@ -38,19 +33,6 @@ for module in $EXTRAMODULE; do
        fi
        AC_DEFINE_UNQUOTED(YAZ_MODULE_${module})
 done
        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)
 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
 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
 AC_SUBST(SUBDIRS_VAR)
 dnl ------ Makefiles
 dnl
@@ -203,7 +185,6 @@ Makefile
 util/Makefile
 odr/Makefile
 z39.50/Makefile
 util/Makefile
 odr/Makefile
 z39.50/Makefile
-asn/Makefile
 ill/Makefile
 zutil/Makefile
 comstack/Makefile
 ill/Makefile
 zutil/Makefile
 comstack/Makefile
@@ -214,6 +195,7 @@ server/Makefile
 include/Makefile
 include/yaz/Makefile
 lib/Makefile
 include/Makefile
 include/yaz/Makefile
 lib/Makefile
+zoom/Makefile
 client/Makefile
 ztest/Makefile
 doc/Makefile
 client/Makefile
 ztest/Makefile
 doc/Makefile
index 1efb114..dc42a5e 100644 (file)
@@ -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
 
 
 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)/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
 
 $(srcdir)/book1.html: $(XMLFILES) $(srcdir)/yazhtml.dsl
        cd $(srcdir); jade -E14 -d yazhtml.dsl -t sgml xml.dcl yaz.xml
index e89335c..0ee6c82 100644 (file)
@@ -6,6 +6,7 @@
      <!ENTITY yaz "YAZ">
      <!ENTITY chap-introduction SYSTEM "introduction.xml">
      <!ENTITY chap-installation SYSTEM "installation.xml">
      <!ENTITY yaz "YAZ">
      <!ENTITY chap-introduction SYSTEM "introduction.xml">
      <!ENTITY chap-installation SYSTEM "installation.xml">
+     <!ENTITY chap-zoom SYSTEM "zoom.xml">
      <!ENTITY chap-client SYSTEM "client.xml">
      <!ENTITY chap-asn SYSTEM "asn.xml">
      <!ENTITY chap-tools SYSTEM "tools.xml">
      <!ENTITY chap-client SYSTEM "client.xml">
      <!ENTITY chap-asn SYSTEM "asn.xml">
      <!ENTITY chap-tools SYSTEM "tools.xml">
@@ -18,8 +19,9 @@
      <!ENTITY asn "<acronym>ASN</acronym>">
      <!ENTITY odr "<acronym>ODR</acronym>">
      <!ENTITY comstack "<acronym>COMSTACK</acronym>">
      <!ENTITY asn "<acronym>ASN</acronym>">
      <!ENTITY odr "<acronym>ODR</acronym>">
      <!ENTITY comstack "<acronym>COMSTACK</acronym>">
+     <!ENTITY zoom "<acronym>ZOOM</acronym>">
 ]>
 ]>
-<!-- $Id: yaz.xml,v 1.6 2001-10-22 13:57:24 adam Exp $ -->
+<!-- $Id: yaz.xml,v 1.7 2001-10-23 21:00:19 adam Exp $ -->
 <book>
  <bookinfo>
   <title>YAZ User's Guide and Reference</title>
 <book>
  <bookinfo>
   <title>YAZ User's Guide and Reference</title>
@@ -47,6 +49,7 @@
  
  &chap-introduction;
  &chap-installation;
  
  &chap-introduction;
  &chap-installation;
+ &chap-zoom;
  &chap-client;
  &chap-asn;
  &chap-tools;
  &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-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:
 -->
 sgml-namecase-general:t
 End:
 -->
diff --git a/doc/zoom.xml b/doc/zoom.xml
new file mode 100644 (file)
index 0000000..1a0aa9e
--- /dev/null
@@ -0,0 +1,253 @@
+<!-- $Id: zoom.xml,v 1.1 2001-10-23 21:00:19 adam Exp $ -->
+ <chapter><title>ZOOM</title>
+  
+  <para>
+   &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.
+  </para>
+  <para>
+   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
+   <ulink url="http://zoom.z3950.org/">zoom.z3950.org</ulink> for
+   more information.
+  </para>
+
+  <para>
+   In order to fully understand this chapter you should read and
+   try the example programs <literal>zoomtst1.c</literal>,
+   <literal>zoomtst2.c</literal>, .. in the <literal>zoom</literal>
+   directory.
+  </para>
+
+  <para>
+   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 <literal>_create</literal> - and a
+   <literal>_destroy</literal> 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
+   <literal>NULL</literal> pointer.
+  </para>
+  <sect1><title>Connections</title>
+   <para>The connection object Z3950_connection describes
+   the connection between your client and a server.
+   </para>
+   <synopsis>
+   #include &lt;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);
+   </synopsis>
+   <para>
+    Connection objects are created with either function
+    <function>Z3950_connection_new</function> or 
+    <function>Z3950_connection_create</function>.
+    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
+    <function>Z3950_connection_connect</function>. 
+    If the portnumber, <literal>portnum</literal>, is zero, the
+    <literal>host</literal> 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.
+   </para>
+   <para>
+    Connection objects should be destroyed using function
+    <function>Z3950_connection_destroy</function>.
+   </para>
+   <synopsis>
+    const char *Z3950_connection_option (Z3950_connection c,
+                                         const char *key,
+                                         const char *val);
+   </synopsis>
+   <para>
+    The <function>Z3950_connection_option</function> allows you to
+    inspect or set an option given by <parameter>key</parameter>
+    for the connection.
+    If <parameter>val</parameter> is non-<literal>NULL</literal> that
+    holds the new value for option.
+    Otherwise, if <parameter>val</parameter> is <literal>NULL</literal>
+    the option is unchanged.
+    The function returns the previous value of the option.
+   </para>
+   <synopsis>
+     const char *Z3950_connection_host (Z3950_connection c);
+
+   </synopsis>
+   <para>
+     Function <function>Z3950_connection_host</function> returns
+     the host for the connection as specified in either a call to
+     <function>Z3950_connection_new</function> or 
+     <function>Z3950_connection_connect</function>.
+     This function returns <literal>NULL</literal> if host isn't
+     set for the connection.
+   </para>
+   <synopsis>
+     int Z3950_connection_error (Z3950_connection c, const char **cp,
+                                 const char **addinfo);
+   </synopsis>
+   <para>
+     Use <function>Z3950_connection_error</function> 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 <parameter>cp</parameter> and <parameter>addinfo</parameter>
+     holds messages for the error and additional-info if passed as
+     non-<literal>NULL</literal>.
+   </para>
+  </sect1>
+  <sect1><title>Search objects</title>
+   <para>
+     Search objects defines how result sets are obtained. They
+     act like queries.
+   </para>
+   <synopsis>
+     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);
+   </synopsis>
+   <para>
+     Create search objects using <function>Z3950_search_create</function>
+     and destroy them by calling <function>Z3950_search_destroy</function>.
+     RPN-queries can be specified in PQF notation by using the
+     function <function>Z3950_search_prefix</function>. 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
+     <function>Z3950_search_sortby</function> specifies a sort
+     criteria using the same string notation for sort as offered by
+     the YAZ client.
+   </para>
+  </sect1>
+  <sect1><title>Result sets</title>
+   <para>
+     The result set describes a collection of records obtained from
+     search.
+   </para>
+   <synopsis>
+     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);
+   </synopsis>
+   <para>
+     Function <function>Z3950_connection_search</function> creates
+     a result set given a connection - and search object.
+     Destroy a result set by calling
+     <function>Z3950_resultset_destroy</function>.
+     Simple clients using YAZ' prefix query format may use
+     function <function>Z3950_connection_search_pqf</function>
+     instead.
+   </para>
+   <synopsis>
+     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);
+   </synopsis>
+   <para>
+     Description of result sets here.
+   </para>
+  </sect1>
+  <sect1><title>Records</title>
+   <para>
+     A record object is a retrival record on the client side -
+     created from result sets.
+   </para>
+   <synopsis>
+     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);
+   </synopsis>
+  </sect1>
+  <sect1><title>Options</title>
+   <para>
+     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.
+   </para>
+   <synopsis>
+     Z3950_options Z3950_options_create (void);
+
+     Z3950_options Z3950_options_create_with_parent (Z3950_options parent);
+
+     void Z3950_options_destroy (Z3950_options opt);
+   </synopsis>
+   <synopsis>
+     const char *Z3950_options_get (Z3950_options opt, const char *name);
+
+     void Z3950_options_set (Z3950_options opt, const char *name,
+                             const char *v);
+   </synopsis>
+   <synopsis>
+     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);
+   </synopsis>
+  </sect1>
+  <sect1><title>Events</title>
+   <para>
+     If you're developing non-blocking applications you have to deal 
+     with events.
+   </para>
+   <synopsis>
+     int Z3950_event (int no, Z3950_connection *cs);
+   </synopsis>
+  </sect1>
+ </chapter>
+ <!-- Keep this comment at the end of the file
+ Local variables:
+ mode: sgml
+ sgml-omittag:t
+ sgml-shorttag:t
+ sgml-minimize-attributes:nil
+ sgml-always-quote-attributes:t
+ sgml-indent-step:1
+ sgml-indent-data:t
+ sgml-parent-document: "yaz.xml"
+ sgml-local-catalogs: "../../docbook/docbook.cat"
+ sgml-namecase-general:t
+ End:
+ -->
index 1e3e301..d769f69 100644 (file)
@@ -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 \
 
 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 \
  \
  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 \
  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 (file)
index 0000000..6d020d0
--- /dev/null
@@ -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 <yaz/yaz-version.h>
+#include <yaz/z-accdes1.h>
+#include <yaz/z-accform1.h>
+#include <yaz/z-acckrb1.h>
+#include <yaz/z-core.h>
+#include <yaz/z-diag1.h>
+#include <yaz/z-espec1.h>
+#include <yaz/z-estask.h>
+#include <yaz/z-exp.h>
+#include <yaz/z-grs.h>
+#include <yaz/z-opac.h>
+#include <yaz/z-rrf1.h>
+#include <yaz/z-rrf2.h>
+#include <yaz/z-sum.h>
+#include <yaz/z-sutrs.h>
+#include <yaz/z-uifr1.h>
+#include <yaz/zes-expi.h>
+#include <yaz/zes-exps.h>
+#include <yaz/zes-order.h>
+#include <yaz/zes-pquery.h>
+#include <yaz/zes-psched.h>
+#include <yaz/zes-pset.h>
+#include <yaz/zes-update.h>
+#include <yaz/zes-admin.h>
+#include <yaz/z-date.h>
+#include <yaz/z-univ.h>
+#include <yaz/zes-update0.h>
+
+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 <yaz/prt-ext.h>
+
+#endif
index f16f939..f3bb57b 100644 (file)
  * OF THIS SOFTWARE.
  *
  * $Log: wrbuf.h,v $
  * 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
  * 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)
 
     (((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
 
 
 YAZ_END_CDECL
 
diff --git a/include/yaz/z-proto.h b/include/yaz/z-proto.h
deleted file mode 100644 (file)
index 9d84c00..0000000
+++ /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 <yaz/yaz-version.h>
-#include <yaz/z-accdes1.h>
-#include <yaz/z-accform1.h>
-#include <yaz/z-acckrb1.h>
-#include <yaz/z-core.h>
-#include <yaz/z-diag1.h>
-#include <yaz/z-espec1.h>
-#include <yaz/z-estask.h>
-#include <yaz/z-exp.h>
-#include <yaz/z-grs.h>
-#include <yaz/z-opac.h>
-#include <yaz/z-rrf1.h>
-#include <yaz/z-rrf2.h>
-#include <yaz/z-sum.h>
-#include <yaz/z-sutrs.h>
-#include <yaz/z-uifr1.h>
-#include <yaz/zes-expi.h>
-#include <yaz/zes-exps.h>
-#include <yaz/zes-order.h>
-#include <yaz/zes-pquery.h>
-#include <yaz/zes-psched.h>
-#include <yaz/zes-pset.h>
-#include <yaz/zes-update.h>
-#include <yaz/zes-admin.h>
-#include <yaz/z-date.h>
-#include <yaz/z-univ.h>
-#include <yaz/zes-update0.h>
-
-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 <yaz/prt-ext.h>
-
-#endif
diff --git a/include/yaz/zoom.h b/include/yaz/zoom.h
new file mode 100644 (file)
index 0000000..67e389e
--- /dev/null
@@ -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/yconfig.h>
+
+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
index a6a4f57..740b32a 100644 (file)
@@ -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
 
 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 \
 
 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)
 
  $(EXTRALIB)
 
index 63956f7..ab2ef2f 100644 (file)
@@ -3,7 +3,10 @@
  * See the file LICENSE for details.
  *
  * $Log: marcdisp.c,v $
  * 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
  * New function marc_display_wrbuf.
  *
  * Revision 1.12  2000/10/02 11:07:44  adam
@@ -56,7 +59,8 @@
 #include <yaz/wrbuf.h>
 #include <yaz/yaz-util.h>
 
 #include <yaz/wrbuf.h>
 #include <yaz/yaz-util.h>
 
-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;
 {
     int entry_p;
     int record_length;
@@ -79,6 +83,9 @@ int marc_display_wrbuf (const char *buf, WRBUF wr, int debug)
        }
         return -1;
     }
        }
         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
     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 ();
     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)
     if (!outf)
        outf = stdout;
     if (record_length > 0)
index c93fa1e..ffc5458 100644 (file)
--- 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" \
 %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
 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/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
 /usr/lib/libyaz.a
 /usr/lib/libyaz.so
 /usr/lib/libyaz.so.1
index a68ce22..b8a2ec9 100644 (file)
@@ -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
 
 
 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 \
  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 \
 
 # 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 (file)
index 0000000..d1d2d50
--- /dev/null
@@ -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 <yaz/proto.h>
+
+/*
+ * 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 (file)
index 0000000..db63437
--- /dev/null
@@ -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 (file)
index 0000000..51908f8
--- /dev/null
@@ -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 <assert.h>
+#include <yaz/xmalloc.h>
+#include <yaz/otherinfo.h>
+#include <yaz/log.h>
+#include <yaz/pquery.h>
+#include <yaz/diagbib1.h>
+
+#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; i<p->num_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; i<resultset->count; 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; i<no; i++)
+    {
+       Z3950_connection c = cs[i];
+       if (c && c->event_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; i<no; i++)
+    {
+       Z3950_connection c = cs[i];
+       int fd, mask;
+       
+       if (!c)
+           continue;
+       fd = z3950_connection_socket(c);
+       mask = z3950_connection_mask(c);
+
+       if (fd == -1)
+           continue;
+       if (max_fd < fd)
+           max_fd = fd;
+       if (mask & Z3950_SELECT_READ)
+       {
+           FD_SET (fd, &input);
+           r++;
+       }
+       if (mask & Z3950_SELECT_WRITE)
+       {
+           FD_SET (fd, &output);
+           r++;
+       }
+    }
+    if (!r)
+    {
+       for (i = 0; i<no; i++)
+       {
+           Z3950_connection c = cs[i];
+           if (!c)
+               continue;
+           if (!c->cs && 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; i<no; i++)
+    {
+       Z3950_connection c = cs[i];
+       int fd, mask;
+
+       if (!c)
+           continue;
+       fd = z3950_connection_socket(c);
+       mask = 0;
+       if (r && c->mask)
+       {
+           /* 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; i<no; i++)
+    {
+       Z3950_connection c = cs[i];
+       if (!c)
+           continue;
+       if (c->event_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 (file)
index 0000000..ddb5a89
--- /dev/null
@@ -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 <assert.h>
+#include <yaz/xmalloc.h>
+#include <yaz/log.h>
+
+#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 (file)
index 0000000..3383d34
--- /dev/null
@@ -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 <yaz/proto.h>
+#include <yaz/comstack.h>
+#include <yaz/wrbuf.h>
+#include <yaz/zoom.h>
+
+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 <yaz/sortspec.h>
+#endif
diff --git a/zoom/zoomsh.c b/zoom/zoomsh.c
new file mode 100644 (file)
index 0000000..2f3897f
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * $Id: zoomsh.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * ZOOM-C Shell
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define HAVE_READLINE_READLINE_H 1
+#define HAVE_READLINE_HISTORY_H 1
+
+#if HAVE_READLINE_READLINE_H
+#include <readline/readline.h> 
+#endif
+#if HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+#endif
+
+#include <yaz/xmalloc.h>
+
+#include <yaz/zoom.h>
+
+#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 : "<null>");
+    }
+    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<MAX_CON; i++)
+    {
+       const char *h;
+       if (!c[i])
+           continue;
+       if ((h = Z3950_connection_host(c[i])) && !strcmp (h, host))
+       {
+           Z3950_connection_destroy (c[i]);
+           c[i] = 0;
+       }
+       else if (*host == '\0')
+       {
+           Z3950_connection_destroy (c[i]);
+           c[i] = 0;
+       }
+    }
+}
+
+static void display_records (Z3950_connection c,
+                            Z3950_resultset r,
+                            int start, int count)
+{
+    int i;
+    for (i = 0; i<count; i++)
+    {
+       int pos = i + start;
+       const char *db = Z3950_resultset_get (r, pos, "database", 0);
+       int len;
+       const char *rec = Z3950_resultset_get (r, pos, "render", &len);
+       const char *syntax = Z3950_resultset_get (r, pos, "syntax", 0);
+       /* if rec is non-null, we got a record for display */
+       if (rec)
+       {
+           printf ("%d %s %s\n", pos+1, (db ? db : "unknown"), syntax);
+           if (rec)
+               fwrite (rec, 1, len, stdout);
+           putchar ('\n');
+       }
+    }
+}
+
+static void cmd_show (Z3950_connection *c, Z3950_resultset *r,
+                     Z3950_options options,
+                     const char **args)
+{
+    int i;
+    char start_str[10], count_str[10];
+
+    if (next_token_copy (args, start_str, sizeof(start_str)))
+       Z3950_options_set (options, "start", start_str);
+
+    if (next_token_copy (args, count_str, sizeof(count_str)))
+       Z3950_options_set (options, "count", count_str);
+
+    for (i = 0; i<MAX_CON; i++)
+       Z3950_resultset_records (r[i], 0, 0);
+    while (Z3950_event (MAX_CON, c))
+       ;
+
+    for (i = 0; i<MAX_CON; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       /* display errors if any */
+       if (!c[i])
+           continue;
+       if ((error = Z3950_connection_error(c[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n",
+                    Z3950_connection_host(c[i]), errmsg,
+                    error, addinfo);
+       else if (r[i])
+       {
+           /* OK, no major errors. Display records... */
+           int start = Z3950_options_get_int (options, "start", 0);
+           int count = Z3950_options_get_int (options, "count", 0);
+           display_records (c[i], r[i], start, count);
+       }
+    }
+}
+
+static void cmd_search (Z3950_connection *c, Z3950_resultset *r,
+                       Z3950_options options,
+                       const char **args)
+{
+    Z3950_search s;
+    int i;
+    
+    s = Z3950_search_create ();
+    if (Z3950_search_prefix (s, *args))
+    {
+       fprintf (stderr, "Bad PQF: %s\n", *args);
+       return;
+    }
+    for (i = 0; i<MAX_CON; i++)
+    {
+       if (c[i])
+       {
+           Z3950_resultset_destroy (r[i]);
+           r[i] = 0;
+       }
+       if (c[i])
+           r[i] = Z3950_connection_search (c[i], s);
+    }
+
+    while (Z3950_event (MAX_CON, c))
+       ;
+
+    for (i = 0; i<MAX_CON; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       /* display errors if any */
+       if (!c[i])
+           continue;
+       if ((error = Z3950_connection_error(c[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n",
+                    Z3950_connection_host(c[i]), errmsg,
+                    error, addinfo);
+       else if (r[i])
+       {
+           /* OK, no major errors. Look at the result count */
+           int start = Z3950_options_get_int (options, "start", 0);
+           int count = Z3950_options_get_int (options, "count", 0);
+
+           printf ("%s: %d hits\n", Z3950_connection_host(c[i]),
+                   Z3950_resultset_size(r[i]));
+           /* and display */
+           display_records (c[i], r[i], start, count);
+       }
+    }
+    Z3950_search_destroy (s);
+}
+
+static void cmd_help (Z3950_connection *c, Z3950_resultset *r,
+                     Z3950_options options,
+                     const char **args)
+{
+    printf ("connect <zurl>\n");
+    printf ("search <pqf>\n");
+    printf ("show [<start> [<count>]\n");
+    printf ("quit\n");
+    printf ("close <zurl>\n");
+    printf ("set <option> [<value>]]\n");
+    printf ("\n");
+    printf ("options:\n");
+    printf (" start\n");
+    printf (" count\n");
+    printf (" databaseName\n");
+    printf (" preferredRecordSyntax\n");
+    printf (" proxy\n");
+    printf (" elementSetName\n");
+    printf (" maximumRecordSize\n");
+    printf (" preferredRecordSize\n");
+    printf (" async\n");
+    printf (" piggyback\n");
+    printf (" group\n");
+    printf (" user\n");
+    printf (" pass\n");
+    printf (" implementationName\n");
+}
+
+static void cmd_connect (Z3950_connection *c, Z3950_resultset *r,
+                        Z3950_options options,
+                        const char **args)
+{
+    int error;
+    const char *errmsg, *addinfo;
+    char host[60];
+    int j, i;
+    if (!next_token_copy (args, host, sizeof(host)))
+    {
+       printf ("missing host after connect\n");
+       return ;
+    }
+    for (j = -1, i = 0; i<MAX_CON; i++)
+    {
+       const char *h;
+       if (c[i] && (h = Z3950_connection_host(c[i])) &&
+           !strcmp (h, host))
+       {
+           Z3950_connection_destroy (c[i]);
+           break;
+       }
+       else if (c[i] == 0 && j == -1)
+           j = i;
+    }
+    if (i == MAX_CON)  /* no match .. */
+    {
+       if (j == -1)
+       {
+           printf ("no more connection available\n");
+           return;
+       }
+       i = j;   /* OK, use this one is available */
+    }
+    c[i] = Z3950_connection_create (options);
+    Z3950_connection_connect (c[i], host, 0);
+
+    if ((error = Z3950_connection_error(c[i], &errmsg, &addinfo)))
+       printf ("%s error: %s (%d) %s\n", Z3950_connection_host(c[i]),
+               errmsg, error, addinfo);
+    
+}
+
+static int cmd_parse (Z3950_connection *c, Z3950_resultset *r,
+                     Z3950_options options, 
+                     const char **buf)
+{
+    int cmd_len;
+    const char *cmd_str;
+
+    cmd_len = next_token (buf, &cmd_str);
+    if (!cmd_len)
+       return 1;
+    if (is_command ("quit", cmd_str, cmd_len))
+       return 0;
+    else if (is_command ("set", cmd_str, cmd_len))
+       cmd_set (c, r, options, buf);
+    else if (is_command ("connect", cmd_str, cmd_len))
+       cmd_connect (c, r, options, buf);
+    else if (is_command ("search", cmd_str, cmd_len))
+       cmd_search (c, r, options, buf);
+    else if (is_command ("show", cmd_str, cmd_len))
+       cmd_show (c, r, options, buf);
+    else if (is_command ("close", cmd_str, cmd_len))
+       cmd_close (c, r, options, buf);
+    else if (is_command ("help", cmd_str, cmd_len))
+       cmd_help(c, r, options, buf);
+    else
+       printf ("unknown command %.*s\n", cmd_len, cmd_str);
+    return 2;
+}
+
+void shell(Z3950_connection *c, Z3950_resultset *r, Z3950_options options)
+{
+    while (1)
+    {
+        char buf[1000];
+       const char *bp = buf;
+#if HAVE_READLINE_READLINE_H
+       char* line_in;
+       line_in=readline("ZOOM>");
+       if (!line_in)
+           break;
+#if HAVE_READLINE_HISTORY_H
+       if (*line_in)
+           add_history(line_in);
+#endif
+       if(strlen(line_in) > 999) {
+           fprintf(stderr,"Input line too long\n");
+           break;
+       };
+       strcpy(buf,line_in);
+       free (line_in);
+#else    
+       printf ("ZOOM>"); fflush (stdout);
+       if (!fgets (buf, 999, stdin))
+           break;
+#endif 
+       if (!cmd_parse (c, r, options, &bp))
+           break;
+    }
+}
+
+int main (int argc, char **argv)
+{
+    Z3950_options options = Z3950_options_create();
+    int i, res;
+    Z3950_connection z39_con[MAX_CON];
+    Z3950_resultset  z39_res[MAX_CON];
+    for (i = 0; i<MAX_CON; i++)
+    {
+       z39_con[i] = 0;
+       z39_res[i] = 0;
+    }
+
+    for (i = 0; i<MAX_CON; i++)
+       z39_con[i] = 0;
+
+    res = 1;
+    for (i = 1; i<argc; i++)
+    {
+       const char *bp = argv[i];
+       res = cmd_parse(z39_con, z39_res, options, &bp);
+       if (res == 0)  /* received quit */
+           break;
+    }
+    if (res)  /* do cmdline shell only if not quitting */
+       shell(z39_con, z39_res, options);
+    Z3950_options_destroy(options);
+
+    for (i = 0; i<MAX_CON; i++)
+    {
+       Z3950_connection_destroy(z39_con[i]);
+       Z3950_resultset_destroy(z39_res[i]);
+    }
+    exit (0);
+}
diff --git a/zoom/zoomtst1.c b/zoom/zoomtst1.c
new file mode 100644 (file)
index 0000000..08c6bb8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * $Id: zoomtst1.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Synchronous single-target client doing search (but no retrieval)
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <yaz/zoom.h>
+
+int main(int argc, char **argv)
+{
+    Z3950_connection z;
+    Z3950_resultset r;
+    int error;
+    const char *errmsg, *addinfo;
+
+    if (argc != 3)
+    {
+        fprintf (stderr, "usage:\n%s target query\n", *argv);
+        fprintf (stderr, " eg.  bagel.indexdata.dk/gils computer\n");
+        exit (1);
+    }
+    z = Z3950_connection_new (argv[1], 0);
+    
+    if ((error = Z3950_connection_error(z, &errmsg, &addinfo)))
+    {
+       fprintf (stderr, "Error: %s (%d) %s\n", errmsg, error, addinfo);
+       exit (2);
+    }
+
+    r = Z3950_connection_search_pqf (z, argv[2]);
+    if ((error = Z3950_connection_error(z, &errmsg, &addinfo)))
+       fprintf (stderr, "Error: %s (%d) %s\n", errmsg, error, addinfo);
+    else
+       printf ("Result count: %d\n", Z3950_resultset_size(r));
+    Z3950_resultset_destroy (r);
+    Z3950_connection_destroy (z);
+    exit (0);
+}
diff --git a/zoom/zoomtst2.c b/zoom/zoomtst2.c
new file mode 100644 (file)
index 0000000..ed0b82f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * $Id: zoomtst2.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Asynchronous single-target client performing search (no retrieval)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <yaz/zoom.h>
+
+int main(int argc, char **argv)
+{
+    Z3950_connection z;
+    Z3950_resultset r;
+    int error;
+    const char *errmsg, *addinfo;
+
+    if (argc < 3)
+    {
+       fprintf (stderr, "usage:\n%s target query\n", *argv);
+       fprintf (stderr,
+                "Verify: aasynchronous single-target client\n");
+       exit (1);
+    }
+
+    /* create connection (don't connect yet) */
+    z = Z3950_connection_create(0);
+
+    /* option: set async operation */
+    Z3950_connection_option (z, "async", "1");
+
+    /* connect to target and initialize */
+    Z3950_connection_connect (z, argv[1], 0);
+
+    /* search using prefix query format */
+    r = Z3950_connection_search_pqf (z, argv[2]);
+
+    /* block here: only one connection */
+    while (Z3950_event (1, &z))
+       ;
+
+    /* see if any error occurred */
+    if ((error = Z3950_connection_error(z, &errmsg, &addinfo)))
+    {
+       fprintf (stderr, "Error: %s (%d) %s\n", errmsg, error, addinfo);
+       exit (2);
+    }
+    else /* OK print hit count */
+       printf ("Result count: %d\n", Z3950_resultset_size(r)); 
+    Z3950_resultset_destroy (r);
+    Z3950_connection_destroy (z);
+    exit (0);
+}
diff --git a/zoom/zoomtst3.c b/zoom/zoomtst3.c
new file mode 100644 (file)
index 0000000..d03bd62
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * $Id: zoomtst3.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Asynchronous multi-target client doing search and piggyback retrieval
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <yaz/xmalloc.h>
+
+#include <yaz/zoom.h>
+
+int main(int argc, char **argv)
+{
+    int i;
+    int no = argc-2;
+    Z3950_connection z[500]; /* allow at most 500 connections */
+    Z3950_resultset r[500];  /* and result sets .. */
+    Z3950_options o = Z3950_options_create ();
+
+    if (argc < 3)
+    {
+       fprintf (stderr, "usage:\n%s target1 target2 ... targetN query\n",
+                *argv);
+       exit (1);
+    }
+    if (no > 500)
+        no = 500;
+
+    /* async mode */
+    Z3950_options_set (o, "async", "1");
+
+    /* get first 10 records of result set (using piggyback) */
+    Z3950_options_set (o, "count", "10");
+
+    /* preferred record syntax */
+    Z3950_options_set (o, "preferredRecordSyntax", "usmarc");
+    Z3950_options_set (o, "elementSetName", "F");
+
+    /* connect to all */
+    for (i = 0; i<no; i++)
+    {
+       /* create connection - pass options (they are the same for all) */
+       z[i] = Z3950_connection_create (o);
+
+       /* connect and init */
+       Z3950_connection_connect (z[i], argv[1+i], 0);
+    }
+    /* search all */
+    for (i = 0; i<no; i++)
+        r[i] = Z3950_connection_search_pqf (z[i], argv[argc-1]);
+
+    /* network I/O. pass number of connections and array of connections */
+    while (Z3950_event (no, z))
+       ;
+    
+    /* no more to be done. Inspect results */
+    for (i = 0; i<no; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       /* display errors if any */
+       if ((error = Z3950_connection_error(z[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n", argv[i+1], errmsg,
+                    error, addinfo);
+       else
+       {
+           /* OK, no major errors. Look at the result count */
+           int pos;
+           printf ("%s: %d hits\n", argv[i+1], Z3950_resultset_size(r[i]));
+           /* go through all records at target */
+           for (pos = 0; pos < 10; pos++)
+           {
+               int len; /* length of buffer rec */
+               const char *rec =
+                   Z3950_resultset_get (r[i], pos, "render", &len);
+               /* if rec is non-null, we got a record for display */
+               if (rec)
+               {
+                   printf ("%d\n", pos+1);
+                   if (rec)
+                       fwrite (rec, 1, len, stdout);
+                   putchar ('\n');
+               }
+           }
+       }
+    }
+    /* destroy and exit */
+    for (i = 0; i<no; i++)
+    {
+        Z3950_resultset_destroy (r[i]);
+        Z3950_connection_destroy (z[i]);
+    }
+    Z3950_options_destroy(o);
+    exit (0);
+}
diff --git a/zoom/zoomtst4.c b/zoom/zoomtst4.c
new file mode 100644 (file)
index 0000000..7e3339d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * $Id: zoomtst4.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Asynchronous multi-target going through proxy doing search and retrieve
+ * using present.
+ */
+
+#include <stdio.h>
+#include <yaz/xmalloc.h>
+
+#include <yaz/zoom.h>
+
+const char *my_callback (void *handle, const char *name)
+{
+    if (!strcmp (name, "async"))
+       return "1";
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    int no = argc-3;
+    Z3950_connection z[500]; /* allow at most 500 connections */
+    Z3950_resultset r[500];  /* and result sets .. */
+    Z3950_search s;
+    Z3950_options o = Z3950_options_create ();
+
+    if (argc < 4)
+    {
+       fprintf (stderr, "usage:\n%s proxy target1 .. targetN query\n",
+                *argv);
+       exit (2);
+    }
+    if (no > 500)
+        no = 500;
+
+    /* function my_callback called when reading options .. */
+    Z3950_options_set_callback (o, my_callback, 0);
+
+    /* get 20 (at most) records from offset 5 */
+    Z3950_options_set (o, "start", "5");
+    Z3950_options_set (o, "count", "20");
+
+    /* set proxy */
+    Z3950_options_set (o, "proxy", argv[1]);
+    
+    /* create query */
+    s = Z3950_search_create ();
+    if (Z3950_search_prefix (s, argv[argc-1]))
+    {
+       printf ("bad PQF: %s\n", argv[argc-1]);
+       exit (1);
+    }
+    /* connect - and search all */
+    for (i = 0; i<no; i++)
+    {
+       z[i] = Z3950_connection_create (o);
+       Z3950_connection_connect (z[i], argv[i+2], 0);
+        r[i] = Z3950_connection_search (z[i], s);
+    }
+
+    /* network I/O */
+    while (Z3950_event (no, z))
+       ;
+
+    /* handle errors */
+    for (i = 0; i<no; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       if ((error = Z3950_connection_error(z[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n",
+                    Z3950_connection_host(z[i]), errmsg, error, addinfo);
+    }
+
+    /* destroy stuff and exit */
+    Z3950_search_destroy (s);
+    for (i = 0; i<no; i++)
+    {
+        Z3950_resultset_destroy (r[i]);
+        Z3950_connection_destroy (z[i]);
+    }
+    Z3950_options_destroy(o);
+    exit (0);
+}
diff --git a/zoom/zoomtst5.c b/zoom/zoomtst5.c
new file mode 100644 (file)
index 0000000..4acb072
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * $Id: zoomtst5.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Asynchronous multi-target client doing search, sort and present
+ */
+
+#include <stdio.h>
+#include <yaz/nmem.h>
+#include <yaz/xmalloc.h>
+
+#include <yaz/zoom.h>
+
+const char *my_callback (void *handle, const char *name)
+{
+    if (!strcmp (name, "async"))
+       return "1";
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    int no = argc-3;
+    Z3950_connection z[500]; /* allow at most 500 connections */
+    Z3950_resultset r[500];  /* and result sets .. */
+    Z3950_search s;
+    Z3950_options o;
+
+    nmem_init ();
+
+    o = Z3950_options_create ();
+    if (argc < 4)
+    {
+       fprintf (stderr, "usage:\n%s target1 .. targetN query sort\n",
+                *argv);
+       exit (2);
+    }
+    if (no > 500)
+        no = 500;
+
+    /* function my_callback called when reading options .. */
+    Z3950_options_set_callback (o, my_callback, 0);
+
+    /* get 20 (at most) records from beginning */
+    Z3950_options_set (o, "count", "20");
+
+    Z3950_options_set (o, "implementationName", "sortapp");
+    Z3950_options_set (o, "preferredRecordSyntax", "usmarc");
+    Z3950_options_set (o, "elementSetName", "B");
+
+    /* create query */
+    s = Z3950_search_create ();
+    if (Z3950_search_prefix (s, argv[argc-2]))
+    {
+       printf ("bad PQF: %s\n", argv[argc-2]);
+       exit (1);
+    }
+    if (Z3950_search_sortby (s, argv[argc-1]))
+    {
+       printf ("bad sort spec: %s\n", argv[argc-1]);
+       exit (1);
+    }
+    /* connect - and search all */
+    for (i = 0; i<no; i++)
+    {
+       z[i] = Z3950_connection_create (o);
+       Z3950_connection_connect (z[i], argv[i+1], 0);
+        r[i] = Z3950_connection_search (z[i], s);
+    }
+
+    /* network I/O */
+    while (Z3950_event (no, z))
+       ;
+
+    /* handle errors */
+    for (i = 0; i<no; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       if ((error = Z3950_connection_error(z[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n",
+                    Z3950_connection_host(z[i]),
+                    errmsg, error, addinfo);
+       else
+       {
+           /* OK, no major errors. Look at the result count */
+           int pos;
+           printf ("%s: %d hits\n", Z3950_connection_host(z[i]),
+                   Z3950_resultset_size(r[i]));
+           /* go through all records at target */
+           for (pos = 0; pos < 20; pos++)
+           {
+               Z3950_record rec;
+               const char *db, *syntax, *str;
+               int len;
+
+               rec = Z3950_resultset_record (r[i], pos);
+               /* get database for record and record itself at pos */
+
+               db = Z3950_record_get (rec,  "database", 0);
+               str = Z3950_record_get (rec, "render", &len);
+               syntax = Z3950_record_get (rec, "syntax", &len);
+               /* if rec is non-null, we got a record for display */
+               if (str)
+               {
+                   printf ("%d %s %s\n", pos+1, syntax, 
+                           (db ? db : "unknown"));
+                   if (rec)
+                       fwrite (str, 1, len, stdout);
+                   putchar ('\n');
+               }
+               Z3950_record_destroy (rec);
+           }
+       }
+    }
+
+    /* destroy stuff and exit */
+    Z3950_search_destroy (s);
+    for (i = 0; i<no; i++)
+    {
+        Z3950_resultset_destroy (r[i]);
+        Z3950_connection_destroy (z[i]);
+    }
+    Z3950_options_destroy(o);
+    nmem_exit ();
+    xmalloc_trav("");
+    exit (0);
+}
diff --git a/zoom/zoomtst6.c b/zoom/zoomtst6.c
new file mode 100644 (file)
index 0000000..e3ea841
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * $Id: zoomtst6.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * Asynchronous multi-target client doing two searches
+ */
+
+#include <stdio.h>
+#include <yaz/nmem.h>
+#include <yaz/xmalloc.h>
+
+#include <yaz/zoom.h>
+
+static void display_records (const char *tname, Z3950_resultset r)
+{
+    /* OK, no major errors. Look at the result count */
+    int pos;
+    printf ("%s: %d hits\n", tname, Z3950_resultset_size(r));
+    /* go through all records at target */
+    for (pos = 0; pos < 20; pos++)
+    {
+       /* get database for record and record itself at pos */
+       const char *db = Z3950_resultset_get (r, pos, "database", 0);
+       int len;
+       const char *rec = Z3950_resultset_get (r, pos, "render", &len);
+       /* if rec is non-null, we got a record for display */
+       if (rec)
+       {
+           printf ("%d %s\n", pos+1, (db ? db : "unknown"));
+           if (rec)
+               fwrite (rec, 1, len, stdout);
+           putchar ('\n');
+       }
+    }
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    int no = argc-3;
+    Z3950_connection z[500];  /* allow at most 500 connections */
+    Z3950_resultset r1[500];  /* and result sets .. */
+    Z3950_resultset r2[500];  /* and result sets .. */
+    Z3950_search s;
+    Z3950_options o;
+
+    nmem_init ();
+
+    o = Z3950_options_create ();
+    if (argc < 4)
+    {
+       fprintf (stderr, "usage:\n%s target1 .. targetN query1 query2\n",
+                *argv);
+       exit (1);
+    }
+    if (no > 500)
+        no = 500;
+
+    Z3950_options_set (o, "async", "1");
+
+    /* get 3 (at most) records from beginning */
+    Z3950_options_set (o, "count", "3");
+
+    Z3950_options_set (o, "preferredRecordSyntax", "sutrs");
+    Z3950_options_set (o, "elementSetName", "B");
+
+    /* create query */
+    s = Z3950_search_create ();
+    if (Z3950_search_prefix (s, argv[argc-2]))
+    {
+       printf ("bad PQF: %s\n", argv[argc-2]);
+       exit (2);
+    }
+    /* connect - and search all */
+    for (i = 0; i<no; i++)
+    {
+       z[i] = Z3950_connection_create (o);
+       Z3950_connection_connect (z[i], argv[i+1], 0);
+        r1[i] = Z3950_connection_search (z[i], s);
+    }
+    if (Z3950_search_prefix (s, argv[argc-1]))
+    {
+       printf ("bad sort spec: %s\n", argv[argc-1]);
+       exit (2);
+    }
+    /* queue second search */
+    for (i = 0; i<no; i++)
+        r2[i] = Z3950_connection_search (z[i], s);
+
+    /* network I/O */
+    while (Z3950_event (no, z))
+       ;
+
+    /* handle errors */
+    for (i = 0; i<no; i++)
+    {
+       int error;
+       const char *errmsg, *addinfo;
+       if ((error = Z3950_connection_error(z[i], &errmsg, &addinfo)))
+           fprintf (stderr, "%s error: %s (%d) %s\n",
+                    Z3950_connection_host(z[i]),
+                    errmsg, error, addinfo);
+       else
+       {
+           display_records (Z3950_connection_host(z[i]), r1[i]);
+           display_records (Z3950_connection_host(z[i]), r2[i]);
+       }
+    }
+    /* destroy stuff and exit */
+    Z3950_search_destroy (s);
+    for (i = 0; i<no; i++)
+    {
+        Z3950_connection_destroy (z[i]);
+        Z3950_resultset_destroy (r1[i]);
+        Z3950_resultset_destroy (r2[i]);
+    }
+    Z3950_options_destroy(o);
+    nmem_exit ();
+    xmalloc_trav("");
+    exit (0);
+}
diff --git a/zoom/zoomtst7.c b/zoom/zoomtst7.c
new file mode 100644 (file)
index 0000000..939d8bc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * $Id: zoomtst7.c,v 1.1 2001-10-23 21:00:20 adam Exp $
+ *
+ * API test..
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <yaz/xmalloc.h>
+#include <yaz/nmem.h>
+
+#include <yaz/zoom.h>
+
+int main(int argc, char **argv)
+{
+    int i, j, block;
+    Z3950_connection z;
+    Z3950_resultset r[10];  /* and result sets .. */
+    Z3950_options o;
+
+    nmem_init ();
+
+    o = Z3950_options_create ();
+
+    for (block = 0; block < 3; block++)
+    {
+       switch (block)
+       {
+       case 0:
+           printf ("blocking - not calling Z3950_events\n");
+           break;
+       case 1:
+           printf ("blocking - calling Z3950_events\n");
+           break;
+       case 2:
+           printf ("non-blocking - calling Z3950_events\n");
+           break;
+       }
+       if (block > 1)
+           Z3950_options_set (o, "async", "1");
+       for (i = 0; i<10; i++)
+       {
+           char host[40];
+           printf ("session %2d", i);
+           sprintf (host, "localhost:9999/%d", i);
+           z = Z3950_connection_create (o);
+           Z3950_connection_connect (z, host, 0);
+           
+           for (j = 0; j < 10; j++)
+           {
+               Z3950_record recs[2];
+               size_t recs_count = 2;
+               char query[40];
+               Z3950_search s = Z3950_search_create ();
+               
+               sprintf (query, "i%dr%d", i, j);
+               
+               if (Z3950_search_prefix (s, query))
+               {
+                   printf ("bad PQF: %s\n", query);
+                   exit (2);
+               }
+               Z3950_options_set (o, "start", "0");
+               Z3950_options_set (o, "count", "0");
+               
+               r[j] = Z3950_connection_search (z, s); /* non-piggy */
+               
+               Z3950_options_set (o, "count", "2");
+               Z3950_resultset_records (r[j], 0, 0);  /* first two */
+               
+               Z3950_options_set (o, "start", "1");
+               Z3950_options_set (o, "count", "2");
+               Z3950_resultset_records (r[j], recs, &recs_count);  /* third */
+               Z3950_resultset_records (r[j], 0, 0);  /* ignored */
+
+               if (Z3950_resultset_size (r[j]) > 2)
+               {
+                   if (!recs[0])
+                   {
+                       fprintf (stderr, "\nrecord missing\n");
+                       exit (1);
+                   }
+               }
+               Z3950_record_destroy (recs[0]);
+               Z3950_record_destroy (recs[1]);
+               
+               Z3950_search_destroy (s);
+
+               putchar ('.');
+               if (block > 0)
+                   while (Z3950_event (1, &z))
+                       ;
+           }
+           for (j = 0; j<i; j++)
+               Z3950_resultset_destroy (r[j]);
+           Z3950_connection_destroy (z);
+           for (; j < 10; j++)
+               Z3950_resultset_destroy (r[j]);
+           printf ("10 searches, 20 presents done\n");
+       }
+       
+       for (i = 0; i<1; i++)
+       {
+           Z3950_search s = Z3950_search_create ();
+           char host[40];
+
+           printf ("session %2d", i+10);
+           sprintf (host, "localhost:9999/%d", i);
+           z = Z3950_connection_create (o);
+           Z3950_connection_connect (z, host, 0);
+           
+           for (j = 0; j < 10; j++)
+           {
+               char query[40];
+               
+               sprintf (query, "i%dr%d", i, j);
+               
+               Z3950_options_set (o, "count", "0");
+               
+               r[j] = Z3950_connection_search_pqf (z, query);
+
+               putchar ('.');
+               if (block > 0)
+                   while (Z3950_event (1, &z))
+                       ;
+           }
+           Z3950_connection_destroy (z);
+           
+           Z3950_options_set (o, "count", "1");
+           for (j = 0; j < 10; j++)
+           {
+               Z3950_resultset_records (r[j], 0, 0);
+               if (block > 0)
+                   while (Z3950_event (1, &z))
+                       ;
+           }
+           for (j = 0; j < 10; j++)
+               Z3950_resultset_destroy (r[j]);
+           Z3950_search_destroy (s);
+           printf ("10 searches, 10 ignored presents done\n");
+       }
+    }
+    Z3950_options_destroy (o);
+    nmem_exit ();
+    xmalloc_trav("");
+
+    exit (0);
+}
+
+
+    
index e1d7fc1..f612628 100644 (file)
@@ -1,9 +1,9 @@
-## $Id: Makefile.am,v 1.7 2001-09-24 21:51:56 adam Exp $
+## $Id: Makefile.am,v 1.8 2001-10-23 21:00:20 adam Exp $
 noinst_LTLIBRARIES = libzutil.la
 
 INCLUDES=-I$(top_srcdir)/include 
 
 LIBS =
 
 noinst_LTLIBRARIES = libzutil.la
 
 INCLUDES=-I$(top_srcdir)/include 
 
 LIBS =
 
-libzutil_la_SOURCES = zget.c prt-ext.c yaz-ccl.c diagbib1.c logrpn.c \
+libzutil_la_SOURCES = zget.c yaz-ccl.c diagbib1.c logrpn.c \
   otherinfo.c pquery.c sortspec.c z3950oid.c
   otherinfo.c pquery.c sortspec.c z3950oid.c
diff --git a/zutil/prt-ext.c b/zutil/prt-ext.c
deleted file mode 100644 (file)
index a2a4f91..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 1995-2001, Index Data.
- * See the file LICENSE for details.
- *
- * $Log: prt-ext.c,v $
- * 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 <yaz/proto.h>
-
-/*
- * 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;
-}
-