Implemented and-list and or-list for CCL module.
[yaz-moved-to-github.git] / client / client.c
index 13cb16c..d7e71f8 100644 (file)
@@ -1,10 +1,56 @@
 /*
- * Copyright (c) 1995-1999, Index Data
+ * Copyright (c) 1995-2000, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: client.c,v $
- * Revision 1.91  1999-12-16 23:36:19  adam
+ * Revision 1.105  2000-10-02 11:07:44  adam
+ * Added peer_name member for bend_init handler. Changed the YAZ
+ * client so that tcp: can be avoided in target spec.
+ *
+ * Revision 1.104  2000/09/04 08:58:15  adam
+ * Added prefix yaz_ for most logging utility functions.
+ *
+ * Revision 1.103  2000/08/10 08:41:26  adam
+ * Fixes for ILL.
+ *
+ * Revision 1.102  2000/05/18 11:57:04  adam
+ * Client display time elapsed.
+ *
+ * Revision 1.101  2000/04/05 07:39:54  adam
+ * Added shared library support (libtool).
+ *
+ * Revision 1.100  2000/03/20 19:29:59  adam
+ * Minor change.
+ *
+ * Revision 1.99  2000/03/20 19:06:25  adam
+ * Added Segment request for fronend server. Work on admin for client.
+ *
+ * Revision 1.98  2000/03/16 13:55:49  ian
+ * Added commands for sending shutdown and startup admin requests via the admin ES.
+ *
+ * Revision 1.97  2000/03/14 14:06:04  ian
+ * Minor change to order of debugging output for send_apdu,
+ * fixed encoding of admin request.
+ *
+ * Revision 1.96  2000/03/14 09:27:07  ian
+ * Added code to enable sending of admin extended service requests
+ *
+ * Revision 1.95  2000/02/28 11:20:05  adam
+ * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL.
+ *
+ * Revision 1.94  2000/01/31 13:15:21  adam
+ * Removed uses of assert(3). Cleanup of ODR. CCL parser update so
+ * that some characters are not surrounded by spaces in resulting term.
+ * ILL-code updates.
+ *
+ * Revision 1.93  2000/01/15 09:39:50  adam
+ * Implemented ill_get_ILLRequest. More ILL testing for client.
+ *
+ * Revision 1.92  1999/12/21 16:24:48  adam
+ * More robust ISO2709 handling (in case of real bad formats).
+ *
+ * Revision 1.91  1999/12/16 23:36:19  adam
  * Implemented ILL protocol. Minor updates ASN.1 compiler.
  *
  * Revision 1.90  1999/11/30 13:47:11  adam
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include <assert.h>
 
 #include <yaz/yaz-util.h>
 
 #include <readline/history.h>
 #endif
 
+#include "admin.h"
+
 #define C_PROMPT "Z> "
 
 static ODR out, in, print;              /* encoding and decoding streams */
 static FILE *apdu_file = 0;
 static COMSTACK conn = 0;               /* our z-association */
 static Z_IdAuthentication *auth = 0;    /* our current auth definition */
-static char *databaseNames[128];
+char *databaseNames[128];
+int num_databaseNames = 0;
 static Z_External *record_last = 0;
-static int num_databaseNames = 0;
 static int setnumber = 0;               /* current result set number */
 static int smallSetUpperBound = 0;
 static int largeSetLowerBound = 1;
@@ -370,22 +417,28 @@ static QueryType queryType = QueryType_Prefix;
 static CCL_bibset bibset;               /* CCL bibset handle */
 #endif
 
-static void send_apdu(Z_APDU *a)
+ODR getODROutputStream()
+{
+    return out;
+}
+
+void send_apdu(Z_APDU *a)
 {
     char *buf;
     int len;
 
-    if (!z_APDU(out, &a, 0, 0))
-    {
-        odr_perror(out, "Encoding APDU");
-        exit(1);
-    }
     if (apdu_file)
     {
         z_APDU(print, &a, 0, 0);
         odr_reset(print);
     }
+    if (!z_APDU(out, &a, 0, 0))
+    {
+        odr_perror(out, "Encoding APDU");
+        exit(1);
+    }
     buf = odr_getbuf(out, &len, 0);
+    /* printf ("sending APDU of size %d\n", len); */
     if (cs_put(conn, buf, len) < 0)
     {
         fprintf(stderr, "cs_put: %s", cs_errmsg(cs_errno(conn)));
@@ -511,7 +564,8 @@ static int cmd_base(char *arg)
 int cmd_open(char *arg)
 {
     void *add;
-    char type[100], addr[100], base[100];
+    char type_and_host[101], base[101];
+    char *host = 0;
     CS_TYPE t;
 
     if (conn)
@@ -527,37 +581,23 @@ int cmd_open(char *arg)
        }
     }
     base[0] = '\0';
-    if (!*arg || sscanf(arg, "%[^:]:%[^/]/%s", type, addr, base) < 2)
-    {
-        fprintf(stderr, "Usage: open (osi|tcp) ':' [tsel '/']host[':'port]\n");
-        return 0;
-    }
+    if (sscanf (arg, "%100[^/]/%100s", type_and_host, base) < 1)
+       return 0;
+    if (strncmp (type_and_host, "tcp:", 4) == 0)
+       host = type_and_host + 4;
+    else
+       host = type_and_host;
     if (*base)
         cmd_base (base);
-    if (!strcmp(type, "tcp"))
-    {
-       t = tcpip_type;
-       protocol = PROTO_Z3950;
-    }
-    else
-#ifdef USE_XTIMOSI
-    if (!strcmp(type, "osi"))
-    {
-        t = mosi_type;
-        protocol = PROTO_SR;
-    }
-    else
-#endif
-    {
-       fprintf(stderr, "Bad type: %s\n", type);
-       return 0;
-    }
+    t = tcpip_type;
+    protocol = PROTO_Z3950;
+
     if (!(conn = cs_create(t, 1, protocol)))
     {
         perror("cs_create");
         return 0;
     }
-    if (!(add = cs_straddr(conn, addr)))
+    if (!(add = cs_straddr(conn, host)))
     {
        perror(arg);
        return 0;
@@ -745,15 +785,23 @@ static void display_record(Z_DatabaseRecord *p)
        }
     }
     if (ent && ent->value == VAL_SOIF)
-        print_record(r->u.octet_aligned->buf, r->u.octet_aligned->len);
+        print_record((const unsigned char *) r->u.octet_aligned->buf, r->u.octet_aligned->len);
     else if (r->which == Z_External_octet && p->u.octet_aligned->len)
     {
         const char *octet_buf = (char*)p->u.octet_aligned->buf;
        if (ent->value == VAL_TEXT_XML || ent->value == VAL_APPLICATION_XML ||
             ent->value == VAL_HTML)
-            print_record(octet_buf, p->u.octet_aligned->len);
+            print_record((const unsigned char *) octet_buf,
+                         p->u.octet_aligned->len);
        else
-            marc_display (octet_buf, NULL);
+        {
+            if (marc_display (octet_buf, NULL) <= 0)
+            {
+                printf ("ISO2709 decoding failed, dumping record as is:\n");
+                print_record((const unsigned char*) octet_buf,
+                              p->u.octet_aligned->len);
+            }
+        }
         if (marcdump)
             fwrite (octet_buf, 1, p->u.octet_aligned->len, marcdump);
     }
@@ -988,7 +1036,11 @@ static int send_searchRequest(char *arg)
     case QueryType_CCL2RPN:
         query.which = Z_Query_type_1;
         RPNquery = ccl_rpn_query(out, rpn);
-        assert(RPNquery);
+       if (!RPNquery)
+       {
+           printf ("Couldn't convert from CCL to RPN\n");
+           return 0;
+       }
         bib1.proto = protocol;
         bib1.oclass = CLASS_ATTSET;
         bib1.value = VAL_BIB1;
@@ -1204,19 +1256,47 @@ void process_ESResponse(Z_ExtendedServicesResponse *res)
 }
 
 #ifdef ASN_COMPILED
+
+const char *get_ill_element (void *clientData, const char *element)
+{
+    printf ("%s\n", element);
+    return 0;
+}
+
 static Z_External *create_external_itemRequest()
 {
-    ILL_ItemRequest *req = ill_get_ItemRequest(out);
+    struct ill_get_ctl ctl;
+    ILL_ItemRequest *req;
     Z_External *r = 0;
+    int item_request_size = 0;
+    char *item_request_buf = 0;
+
+    ctl.odr = out;
+    ctl.clientData = 0;
+    ctl.f = get_ill_element;
 
+    req = ill_get_ItemRequest(&ctl, "ill", 0);
+    if (!req)
+        printf ("ill_get_ItemRequest failed\n");
+       
     if (!ill_ItemRequest (out, &req, 0, 0))
+    {
+       if (apdu_file)
+       {
+           ill_ItemRequest(print, &req, 0, 0);
+           odr_reset(print);
+       }
+       item_request_buf = odr_getbuf (out, &item_request_size, 0);
+       if (item_request_buf)
+           odr_setbuf (out, item_request_buf, item_request_size, 1);
+        printf ("Couldn't encode ItemRequest, size %d\n", item_request_size);
        return 0;
+    }
     else
     {
        oident oid;
-       int itemRequest_size = 0;
-       char *itemRequest_buf = odr_getbuf (out, &itemRequest_size, 0);
        
+       item_request_buf = odr_getbuf (out, &item_request_size, 0);
        oid.proto = PROTO_GENERAL;
        oid.oclass = CLASS_GENERAL;
        oid.value = VAL_ISO_ILL_1;
@@ -1229,11 +1309,12 @@ static Z_External *create_external_itemRequest()
        
        r->u.single_ASN1_type = (Odr_oct *)
            odr_malloc (out, sizeof(*r->u.single_ASN1_type));
-       r->u.single_ASN1_type->buf = odr_malloc (out, itemRequest_size);
-       r->u.single_ASN1_type->len = itemRequest_size;
-       r->u.single_ASN1_type->size = itemRequest_size;
-       memcpy (r->u.single_ASN1_type->buf, itemRequest_buf, itemRequest_size);
-       printf ("len = %d\n", itemRequest_size);
+       r->u.single_ASN1_type->buf = odr_malloc (out, item_request_size);
+       r->u.single_ASN1_type->len = item_request_size;
+       r->u.single_ASN1_type->size = item_request_size;
+       memcpy (r->u.single_ASN1_type->buf, item_request_buf,
+               item_request_size);
+       printf ("len = %d\n", item_request_size);
     }
     return r;
 }
@@ -1243,7 +1324,71 @@ static Z_External *create_external_itemRequest()
     return 0;
 }
 #endif
-static Z_External *CreateItemOrderExternal(int itemno)
+
+#ifdef ASN_COMPILED
+static Z_External *create_external_ILLRequest()
+{
+    struct ill_get_ctl ctl;
+    ILL_Request *req;
+    Z_External *r = 0;
+    int ill_request_size = 0;
+    char *ill_request_buf = 0;
+       
+    ctl.odr = out;
+    ctl.clientData = 0;
+    ctl.f = get_ill_element;
+
+    req = ill_get_ILLRequest(&ctl, "ill", 0);
+
+    if (!ill_Request (out, &req, 0, 0))
+    {
+       if (apdu_file)
+       {
+           printf ("-------------------\n");
+           ill_Request(print, &req, 0, 0);
+           odr_reset(print);
+           printf ("-------------------\n");
+       }
+       ill_request_buf = odr_getbuf (out, &ill_request_size, 0);
+       if (ill_request_buf)
+           odr_setbuf (out, ill_request_buf, ill_request_size, 1);
+        printf ("Couldn't encode ILL-Request, size %d\n", ill_request_size);
+       return 0;
+    }
+    else
+    {
+       oident oid;
+       ill_request_buf = odr_getbuf (out, &ill_request_size, 0);
+       
+       oid.proto = PROTO_GENERAL;
+       oid.oclass = CLASS_GENERAL;
+       oid.value = VAL_ISO_ILL_1;
+       
+       r = (Z_External *) odr_malloc (out, sizeof(*r));
+       r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); 
+       r->indirect_reference = 0;
+       r->descriptor = 0;
+       r->which = Z_External_single;
+       
+       r->u.single_ASN1_type = (Odr_oct *)
+           odr_malloc (out, sizeof(*r->u.single_ASN1_type));
+       r->u.single_ASN1_type->buf = odr_malloc (out, ill_request_size);
+       r->u.single_ASN1_type->len = ill_request_size;
+       r->u.single_ASN1_type->size = ill_request_size;
+       memcpy (r->u.single_ASN1_type->buf, ill_request_buf, ill_request_size);
+       printf ("len = %d\n", ill_request_size);
+    }
+    return r;
+}
+#else
+static Z_External *create_external_ILLRequest()
+{
+    return 0;
+}
+#endif
+
+
+static Z_External *create_ItemOrderExternal(const char *type, int itemno)
 {
     Z_External *r = (Z_External *) odr_malloc(out, sizeof(Z_External));
     oident ItemOrderRequest;
@@ -1290,34 +1435,36 @@ static Z_External *CreateItemOrderExternal(int itemno)
        (int *) odr_malloc(out, sizeof(int));
     *r->u.itemOrder->u.esRequest->notToKeep->resultSetItem->item = itemno;
 
-    r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 
-       create_external_itemRequest();
+    if (!strcmp (type, "item") || !strcmp(type, "2"))
+    {
+       printf ("using item-request\n");
+       r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 
+           create_external_itemRequest();
+    }
+    else if (!strcmp(type, "ill") || !strcmp(type, "1"))
+    {
+       printf ("using ILL-request\n");
+       r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 
+           create_external_ILLRequest();
+    }
+    else
+       r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0;
     return r;
 }
 
-/* II : Added to do DALI Item Order Extended services request */
-static int send_itemorder(char *arg)
+static int send_itemorder(const char *type, int itemno)
 {
-    int itemno = -1;
     Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
     oident ItemOrderRequest;
 
-    if (*arg)
-        itemno = atoi(arg);
-
-    /* Set up item order request */
-
-    /* Package type, Using protocol ILL ( But that's not in the oid.h file yet */
-    /* create an object of class Extended Service, value Item Order            */
     ItemOrderRequest.proto = PROTO_Z3950;
     ItemOrderRequest.oclass = CLASS_EXTSERV;
     ItemOrderRequest.value = VAL_ITEMORDER;
     req->packageType = odr_oiddup(out,oid_getoidbyent(&ItemOrderRequest));
     req->packageName = "1.Extendedserveq";
 
-    /* ** taskSpecificParameters ** */
-    req->taskSpecificParameters = CreateItemOrderExternal(itemno);
+    req->taskSpecificParameters = create_ItemOrderExternal(type, itemno);
 
     send_apdu(apdu);
     return 0;
@@ -1383,10 +1530,15 @@ static int cmd_update(char *arg)
 /* II : Added to do DALI Item Order Extended services request */
 static int cmd_itemorder(char *arg)
 {
+    char type[12];
+    int itemno;
+
+    if (sscanf (arg, "%10s %d", type, &itemno) != 2)
+       return 0;
+
     printf("Item order request\n");
     fflush(stdout);
-
-    send_itemorder(arg);
+    send_itemorder(type, itemno);
     return(2);
 }
 
@@ -2120,14 +2272,30 @@ static int client(int wait)
        {"attributeset", cmd_attributeset, "<attrset>"},
         {"querytype", cmd_querytype, "<type>"},
        {"refid", cmd_refid, "<id>"},
-       {"itemorder", cmd_itemorder, "<item>"},
+       {"itemorder", cmd_itemorder, "ill|item <itemno>"},
        {"update", cmd_update, "<item>"},
+#ifdef ASN_COMPILED
+       /* Server Admin Functions */
+       {"adm-reindex", cmd_adm_reindex, "<database-name>"},
+       {"adm-truncate", cmd_adm_truncate, "('database'|'index')<object-name>"},
+       {"adm-create", cmd_adm_create, ""},
+       {"adm-drop", cmd_adm_drop, "('database'|'index')<object-name>"},
+       {"adm-import", cmd_adm_import, "<record-type> <dir> <pattern>"},
+       {"adm-refresh", cmd_adm_refresh, ""},
+       {"adm-commit", cmd_adm_commit, ""},
+       {"adm-shutdown", cmd_adm_shutdown, ""},
+       {"adm-startup", cmd_adm_startup, ""},
+#endif
         {0,0}
     };
     char *netbuffer= 0;
     int netbufferlen = 0;
     int i;
     Z_APDU *apdu;
+#if HAVE_GETTIMEOFDAY
+    struct timeval tv_start, tv_end;
+    gettimeofday (&tv_start, 0);
+#endif
 
     while (1)
     {
@@ -2174,6 +2342,10 @@ static int client(int wait)
            if ((end_p = strchr (line, '\n')))
                *end_p = '\0';
 #endif 
+#if HAVE_GETTIMEOFDAY
+           gettimeofday (&tv_start, 0);
+#endif
+
             if ((res = sscanf(line, "%s %[^;]", word, arg)) <= 0)
             {
                 strcpy(word, last_cmd);
@@ -2202,9 +2374,11 @@ static int client(int wait)
            }
         }
        wait = 0;
+       if (conn
 #ifdef USE_SELECT
-        if (conn && FD_ISSET(cs_fileno(conn), &input))
+           && FD_ISSET(cs_fileno(conn), &input)
 #endif
+           )
         {
             do
             {
@@ -2228,6 +2402,8 @@ static int client(int wait)
                     fprintf(stderr, "Packet dump:\n---------\n");
                     odr_dumpBER(stderr, netbuffer, res);
                     fprintf(stderr, "---------\n");
+                   if (apdu_file)
+                       z_APDU(print, &apdu, 0, 0);
                     exit(1);
                 }
                 if (apdu_file && !z_APDU(print, &apdu, 0, 0))
@@ -2284,6 +2460,15 @@ static int client(int wait)
                 }
             }
             while (conn && cs_more(conn));
+#if HAVE_GETTIMEOFDAY
+           gettimeofday (&tv_end, 0);
+           if (1)
+           {
+               printf ("Elapsed: %.6f\n", (double) tv_end.tv_usec /
+                                                1e6 + tv_end.tv_sec -
+                  ((double) tv_start.tv_usec / 1e6 + tv_start.tv_sec));
+           }
+#endif
         }
     }
     return 0;
@@ -2322,10 +2507,10 @@ int main(int argc, char **argv)
                 apdu_file=fopen(arg, "a");
             break;
        case 'v':
-           log_init (log_mask_str(arg), "", NULL);
+           yaz_log_init (yaz_log_mask_str(arg), "", NULL);
            break;
         default:
-            fprintf (stderr, "Usage: %s [-m <marclog>] [ -m <apdulog>] "
+            fprintf (stderr, "Usage: %s [-m <marclog>] [ -a <apdulog>] "
                              "[<server-addr>]\n",
                      prog);
             exit (1);