Fixed scan continuation line not being set for displayTerm being ste
[yaz-moved-to-github.git] / client / client.c
index d8edfe1..c158b00 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: client.c,v 1.334 2007-04-16 21:53:08 adam Exp $
+ * $Id: client.c,v 1.350 2007-08-21 13:19:44 adam Exp $
  */
 /** \file client.c
  *  \brief yaz-client program
@@ -63,6 +63,7 @@
 #include <yaz/diagbib1.h>
 #include <yaz/otherinfo.h>
 #include <yaz/charneg.h>
+#include <yaz/query-charset.h>
 
 #include <yaz/pquery.h>
 #include <yaz/sortspec.h>
@@ -133,6 +134,7 @@ static int  negotiationCharsetRecords = 1;
 static int  negotiationCharsetVersion = 3;
 static char *outputCharset = 0;
 static char *marcCharset = 0;
+static char *queryCharset = 0;
 static char* yazLang = 0;
 
 static char last_cmd[32] = "?";
@@ -169,12 +171,9 @@ static cql_transform_t cqltrans = 0; /* CQL context-set handle */
 int rl_attempted_completion_over = 0;
 #endif
 
-/* set this one to 1, to avoid decode of unknown MARCs  */
-#define AVOID_MARC_DECODE 1
-
 #define maxOtherInfosSupported 10
-struct {
-    int oid[OID_SIZE];
+struct eoi {
+    Odr_oid oid[OID_SIZE];
     char* value;
 } extraOtherInfos[maxOtherInfosSupported];
 
@@ -184,6 +183,7 @@ char **readline_completer(char *text, int start, int end);
 #endif
 static char *command_generator(const char *text, int state);
 int cmd_register_tab(const char* arg);
+int cmd_querycharset(const char *arg);
 
 static void close_session (void);
 
@@ -349,7 +349,8 @@ static void send_initRequest(const char* type_and_host)
         
         yaz_oi_APDU(apdu, &p);
         
-        if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) {
+        if ((p0=yaz_oi_update(p, out, NULL, 0, 0)))
+        {
             ODR_MASK_SET(req->options, Z_Options_negotiationModel);
             
             p0->which = Z_OtherInfo_externallyDefinedInfo;
@@ -360,7 +361,21 @@ static void send_initRequest(const char* type_and_host)
                                               negotiationCharsetRecords);
         }
     }
-    
+    else if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
+    {
+        Z_OtherInformation **p;
+        Z_OtherInformationUnit *p0;
+        
+        yaz_oi_APDU(apdu, &p);
+        
+        if ((p0=yaz_oi_update(p, out, NULL, 0, 0)))
+        {
+            p0->which = Z_OtherInfo_externallyDefinedInfo;
+            p0->information.externallyDefinedInfo =
+                yaz_set_proposal_charneg(out, 0, 0, 0, 0, 0);
+        }
+
+    }
     if (send_apdu(apdu))
         printf("Sent initrequest.\n");
 }
@@ -415,11 +430,9 @@ static int process_initResponse(Z_InitResponse *res)
             }
             else if (uif->which == Z_External_single) 
             {
-                const int *oclc_oid = yaz_string_to_oid(yaz_oid_std(),
-                                                        CLASS_GENERAL,
-                                                        "OCLC-userInfo");
                 Odr_any *sat = uif->u.single_ASN1_type;
-                if (!oid_oidcmp(uif->direct_reference, oclc_oid))
+                if (!oid_oidcmp(uif->direct_reference,
+                                yaz_oid_userinfo_oclc_userinfo))
                 {
                     Z_OCLC_UserInformation *oclc_ui;
                     ODR decode = odr_createmem(ODR_DECODE);
@@ -453,27 +466,32 @@ static int process_initResponse(Z_InitResponse *res)
     
         Z_CharSetandLanguageNegotiation *p =
                 yaz_get_charneg_record(res->otherInfo);
-        
-        if (p) {
-            
+
+        if (p) 
+        {
             char *charset=NULL, *lang=NULL;
             int selected;
             
             yaz_get_response_charneg(session_mem, p, &charset, &lang,
                                      &selected);
 
-            if (outputCharset && negotiationCharset) {
-                    odr_set_charset (out, charset, outputCharset);
-                    odr_set_charset (in, outputCharset, charset);
+            printf("Accepted character set : %s\n", charset ? charset:"none");
+            printf("Accepted code language : %s\n", lang ? lang:"none");
+            printf("Accepted records in ...: %d\n", selected );
+
+            if (outputCharset && charset)
+            {
+                printf("Converting between %s and %s\n",
+                       outputCharset, charset);
+                odr_set_charset(out, charset, outputCharset);
+                odr_set_charset(in, outputCharset, charset);
+                cmd_querycharset(charset);
             }
-            else {
-                    odr_set_charset (out, 0, 0);
-                    odr_set_charset (in, 0, 0);
+            else
+            {
+                odr_set_charset(out, 0, 0);
+                odr_set_charset(in, 0, 0);
             }
-            
-            printf("Accepted character set : %s\n", charset);
-            printf("Accepted code language : %s\n", lang ? lang : "none");
-            printf("Accepted records in ...: %d\n", selected );
         }
     }
     fflush (stdout);
@@ -622,7 +640,7 @@ static int parse_cmd_doc(const char **arg, ODR out, char **buf,
             return 0;
         }
         *len = fsize;
-        *buf = odr_malloc(out, fsize);
+        *buf = (char *) odr_malloc(out, fsize);
         if (fread(*buf, 1, fsize, inf) != fsize)
         {
             printf("Unable to read %s\n", fname);
@@ -857,7 +875,7 @@ static void print_record(const unsigned char *buf, size_t len)
 
 static void display_record(Z_External *r)
 {
-    const int *oid = r->direct_reference;
+    const Odr_oid *oid = r->direct_reference;
     
     record_last = r;
     /*
@@ -865,7 +883,7 @@ static void display_record(Z_External *r)
      */
     if (oid)
     {
-        int oclass;
+        oid_class oclass;
         char oid_name_buf[OID_STR_MAX];
         const char *oid_name
             =  yaz_oid_to_string_buf(oid, &oclass, oid_name_buf);
@@ -932,16 +950,7 @@ static void display_record(Z_External *r)
         }
         else
         {
-            const int *oidsuffix = oid_oidlen(oid) > 1 
-                ? oid + oid_oidlen(oid)-2 : 0;
-            if ( 
-#if AVOID_MARC_DECODE
-                /* primitive check for a marc OID 5.1-29 except 16 */
-                oidsuffix[0] == 5 && oidsuffix[1] < 30 && oidsuffix[1] != 16
-#else
-                1
-#endif
-                )
+            if (oid && yaz_oid_is_iso2709(oid))
             {
                 const char *result;
                 size_t rlen;
@@ -1159,7 +1168,7 @@ static void display_diagrecs(Z_DiagRec **pp, int num)
             printf("Missing diagset\n");
         else
         {
-            int oclass;
+            oid_class oclass;
             char diag_name_buf[OID_STR_MAX];
             const char *diag_name = 0;
             diag_name = yaz_oid_to_string_buf
@@ -1258,7 +1267,7 @@ static int send_srw(Z_SRW_PDU *sr)
     Z_GDU *gdu;
     char *path = 0;
 
-    path = odr_malloc(out, 2+strlen(databaseNames[0]));
+    path = (char *) odr_malloc(out, 2+strlen(databaseNames[0]));
     *path = '/';
     strcpy(path+1, databaseNames[0]);
 
@@ -1405,6 +1414,22 @@ static int send_SRW_searchRequest(const char *arg)
 }
 #endif
 
+static void query_charset_convert(Z_RPNQuery *q)
+{
+    if (queryCharset && outputCharset)
+    {
+        yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset);
+        if (!cd)
+        {
+            printf("Conversion from %s to %s unsupported\n",
+                   outputCharset, queryCharset);
+            return;
+        }
+        yaz_query_charset_convert_rpnquery(q, out, cd);
+        yaz_iconv_close(cd);
+    }
+}
+
 static int send_searchRequest(const char *arg)
 {
     Z_APDU *apdu = zget_APDU(out, Z_APDU_searchRequest);
@@ -1510,6 +1535,7 @@ static int send_searchRequest(const char *arg)
             return 0;
         }
         yaz_pqf_destroy (pqf_parser);
+        query_charset_convert(RPNquery);
         query.u.type_1 = RPNquery;
         break;
     case QueryType_CCL:
@@ -1526,6 +1552,7 @@ static int send_searchRequest(const char *arg)
             printf ("Couldn't convert from CCL to RPN\n");
             return 0;
         }
+        query_charset_convert(RPNquery);
         query.u.type_1 = RPNquery;
         ccl_rpn_delete (rpn);
         break;
@@ -1688,7 +1715,7 @@ static void print_oid(int iLevel, const char *pTag, Odr_oid *pOid)
 {
     if (pOid != NULL)
     {
-        int *pInt = pOid;
+        Odr_oid *pInt = pOid;
 
         print_level(iLevel);
         printf("%s:", pTag);
@@ -1888,6 +1915,20 @@ void process_ESResponse(Z_ExtendedServicesResponse *res)
                 }
             }
         }
+        if (ext->which == Z_External_itemOrder)
+        {
+            Z_IOTaskPackage *otp = ext->u.itemOrder->u.taskPackage;
+            if (otp && otp->targetPart && otp->targetPart->itemRequest)
+            {
+                Z_External *ext = otp->targetPart->itemRequest;
+                if (ext->which == Z_External_octet)
+                {
+                    Odr_oct *doc = ext->u.octet_aligned;
+                    printf("Got itemRequest doc %.*s\n",
+                           doc->len, doc->buf);
+                }
+            }
+        }
     }
     if (res->taskPackage && res->taskPackage->which == Z_External_octet)
     {
@@ -1932,10 +1973,8 @@ static Z_External *create_external_itemRequest(void)
     }
     else
     {
-        const int *ill_oid = yaz_string_to_oid(yaz_oid_std(),
-                                               CLASS_GENERAL, "ISOILL-1");
         r = (Z_External *) odr_malloc (out, sizeof(*r));
-        r->direct_reference = odr_oiddup(out, ill_oid);
+        r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1);
         r->indirect_reference = 0;
         r->descriptor = 0;
         r->which = Z_External_single;
@@ -1985,13 +2024,10 @@ static Z_External *create_external_ILL_APDU(int which)
     }
     else
     {
-        const int *ill_oid = yaz_string_to_oid(yaz_oid_std(),
-                                               CLASS_GENERAL, "ISOILL-1");
-
         ill_request_buf = odr_getbuf (out, &ill_request_size, 0);
         
         r = (Z_External *) odr_malloc (out, sizeof(*r));
-        r->direct_reference = odr_oiddup(out, ill_oid);
+        r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1);
         r->indirect_reference = 0;
         r->descriptor = 0;
         r->which = Z_External_single;
@@ -2015,10 +2051,7 @@ static Z_External *create_external_ILL_APDU(int which)
 static Z_External *create_ItemOrderExternal(const char *type, int itemno)
 {
     Z_External *r = (Z_External *) odr_malloc(out, sizeof(Z_External));
-    const int *itemorder_oid = yaz_string_to_oid(yaz_oid_std(),
-                                                 CLASS_EXTSERV,
-                                                 "Item order");
-    r->direct_reference = odr_oiddup(out, itemorder_oid);
+    r->direct_reference = odr_oiddup(out, yaz_oid_extserv_item_order);
     r->indirect_reference = 0;
     r->descriptor = 0;
 
@@ -2066,8 +2099,6 @@ static Z_External *create_ItemOrderExternal(const char *type, int itemno)
     }
     else if (!strcmp(type, "xml") || !strcmp(type, "3"))
     {
-        const int *oid_xml = yaz_string_to_oid(yaz_oid_std(),
-                                               CLASS_RECSYN, "xml");
         const char *xml_buf =
             "<itemorder>\n"
             "  <type>request</type>\n"
@@ -2075,7 +2106,7 @@ static Z_External *create_ItemOrderExternal(const char *type, int itemno)
             "  <borrowerTicketNo> 1212 </borrowerTicketNo>\n"
             "</itemorder>";
         r->u.itemOrder->u.esRequest->notToKeep->itemRequest =
-            z_ext_record_oid(out, oid_xml, xml_buf, strlen(xml_buf));
+            z_ext_record_oid(out, yaz_oid_recsyn_xml, xml_buf, strlen(xml_buf));
     }
     else
         r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0;
@@ -2088,12 +2119,9 @@ static int send_itemorder(const char *type, int itemno)
     Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest);
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
 
-    const int *itemorder_oid = yaz_string_to_oid(yaz_oid_std(),
-                                                 CLASS_EXTSERV,
-                                                 "Item order");
     req->referenceId = set_refid (out);
 
-    req->packageType = odr_oiddup(out, itemorder_oid);
+    req->packageType = odr_oiddup(out, yaz_oid_extserv_item_order);
     req->packageName = esPackageName;
 
     req->taskSpecificParameters = create_ItemOrderExternal(type, itemno);
@@ -2231,11 +2259,9 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid,
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
     Z_External *r;
     Z_External *record_this = 0;
-    const int *oid_xml = yaz_string_to_oid(yaz_oid_std(),
-                                           CLASS_RECSYN, "xml");
-
     if (rec_buf)
-        record_this = z_ext_record_oid(out, oid_xml, rec_buf, rec_len);
+        record_this = z_ext_record_oid(out, yaz_oid_recsyn_xml,
+                                       rec_buf, rec_len);
     else
     {
         if (!record_last)
@@ -2246,11 +2272,10 @@ static int cmd_update_Z3950(int version, int action_no, const char *recid,
         record_this = record_last;
     }
 
-    req->packageType =
-        yaz_string_to_oid_odr(yaz_oid_std(),
-                              CLASS_EXTSERV, 
-                              version == 0 ? "DB. Update (first version)" :
-                              "DB. Update", out);
+    req->packageType = odr_oiddup(out, (version == 0 ? 
+       yaz_oid_extserv_database_update_first_version :
+       yaz_oid_extserv_database_update));
+
     req->packageName = esPackageName;
     
     req->referenceId = set_refid (out);
@@ -2358,7 +2383,7 @@ static int cmd_xmles(const char *arg)
     {
         char *asn_buf = 0;
         int noread = 0;
-        int *oid;
+        Odr_oid *oid;
         char oid_str[51];
         Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest);
         Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
@@ -2878,7 +2903,8 @@ int cmd_cancel_find(const char *arg) {
     return fres;
 }
 
-int send_scanrequest(const char *query, int pp, int num, const char *term)
+int send_scanrequest(const char *set,  const char *query,
+                     int pp, int num, const char *term)
 {
     Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest);
     Z_ScanRequest *req = apdu->u.scanRequest;
@@ -2924,6 +2950,18 @@ int send_scanrequest(const char *query, int pp, int num, const char *term)
         }
         yaz_pqf_destroy (pqf_parser);
     }
+    if (queryCharset && outputCharset)
+    {
+        yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset);
+        if (!cd)
+        {
+            printf("Conversion from %s to %s unsupported\n",
+                   outputCharset, queryCharset);
+            return -1;
+        }
+        yaz_query_charset_convert_apt(req->termListAndStartPoint, out, cd);
+        yaz_iconv_close(cd);
+    }
     if (term && *term)
     {
         if (req->termListAndStartPoint->term &&
@@ -2943,6 +2981,11 @@ int send_scanrequest(const char *query, int pp, int num, const char *term)
     req->numberOfTermsRequested = &num;
     req->preferredPositionInResponse = &pp;
     req->stepSize = odr_intdup(out, scan_stepSize);
+
+    if (set)
+        yaz_oi_set_string_oid(&req->otherInfo, out,
+                              yaz_oid_userinfo_scan_set, 1, set);
+
     send_apdu(apdu);
     return 2;
 }
@@ -2989,13 +3032,13 @@ void display_term(Z_TermInfo *t)
     if (t->displayTerm)
         printf("%s", t->displayTerm);
     else if (t->term->which == Z_Term_general)
-    {
         printf("%.*s", t->term->u.general->len, t->term->u.general->buf);
-        sprintf(last_scan_line, "%.*s", t->term->u.general->len,
-            t->term->u.general->buf);
-    }
     else
         printf("Term (not general)");
+    if (t->term->which == Z_Term_general)
+        sprintf(last_scan_line, "%.*s", t->term->u.general->len,
+            t->term->u.general->buf);
+
     if (t->globalOccurrences)
         printf (" (%d)\n", *t->globalOccurrences);
     else
@@ -3123,7 +3166,7 @@ int cmd_scansize(const char *arg)
     return 0;
 }
 
-int cmd_scan(const char *arg)
+static int cmd_scan_common(const char *set, const char *arg)
 {
     if (protocol == PROTO_HTTP)
     {
@@ -3167,18 +3210,37 @@ int cmd_scan(const char *arg)
         if (*arg)
         {
             strcpy (last_scan_query, arg);
-            if (send_scanrequest(arg, scan_position, scan_size, 0) < 0)
+            if (send_scanrequest(set, arg, 
+                                 scan_position, scan_size, 0) < 0)
                 return 0;
         }
         else
         {
-            if (send_scanrequest(last_scan_query, 1, scan_size, last_scan_line) < 0)
+            if (send_scanrequest(set, last_scan_query, 
+                                 1, scan_size, last_scan_line) < 0)
                 return 0;
         }
         return 2;
     }
 }
 
+int cmd_scan(const char *arg)
+{
+    return cmd_scan_common(0, arg);
+}
+
+int cmd_setscan(const char *arg)
+{
+    char setstring[100];
+    int nor;
+    if (sscanf(arg, "%99s%n", setstring, &nor) < 1)
+    {
+        printf("missing set for setscan\n");
+        return 0;
+    }
+    return cmd_scan_common(setstring, arg + nor);
+}
+
 int cmd_schema(const char *arg)
 {
     xfree(record_schema);
@@ -3316,11 +3378,29 @@ int cmd_marccharset(const char *arg)
     }
     xfree (marcCharset);
     marcCharset = 0;
-    if (strcmp(l1, "-"))
+    if (strcmp(l1, "-") && strcmp(l1, "none"))
         marcCharset = xstrdup(l1);
     return 1;
 }
 
+int cmd_querycharset(const char *arg)
+{
+    char l1[30];
+
+    *l1 = 0;
+    if (sscanf(arg, "%29s", l1) < 1)
+    {
+        printf("Query character set is `%s'\n", 
+               queryCharset ? queryCharset: "none");
+        return 1;
+    }
+    xfree (queryCharset);
+    queryCharset = 0;
+    if (strcmp(l1, "-") && strcmp(l1, "none"))
+        queryCharset = xstrdup(l1);
+    return 1;
+}
+
 int cmd_displaycharset(const char *arg)
 {
     char l1[30];
@@ -3359,11 +3439,14 @@ int cmd_negcharset(const char *arg)
     if (sscanf(arg, "%29s %d %d", l1, &negotiationCharsetRecords,
                &negotiationCharsetVersion) < 1)
     {
-        printf("Current negotiation character set is `%s'\n", 
+        printf("Negotiation character set `%s'\n", 
                negotiationCharset ? negotiationCharset: "none");  
-        printf("Records in charset %s\n", negotiationCharsetRecords ? 
-               "yes" : "no");
-        printf("Charneg version %d\n", negotiationCharsetVersion);
+        if (negotiationCharset)
+        {
+            printf("Records in charset %s\n", negotiationCharsetRecords ? 
+                   "yes" : "no");
+            printf("Charneg version %d\n", negotiationCharsetVersion);
+        }
     }
     else
     {
@@ -3380,14 +3463,15 @@ int cmd_negcharset(const char *arg)
 
 int cmd_charset(const char* arg)
 {
-    char l1[30], l2[30], l3[30];
+    char l1[30], l2[30], l3[30], l4[30];
 
-    *l1 = *l2 = *l3 = 0;
-    if (sscanf(arg, "%29s %29s %29s", l1, l2, l3) < 1)
+    *l1 = *l2 = *l3 = *l4 = '\0';
+    if (sscanf(arg, "%29s %29s %29s %29s", l1, l2, l3, l4) < 1)
     {
         cmd_negcharset("");
         cmd_displaycharset("");
         cmd_marccharset("");
+        cmd_querycharset("");
     }
     else
     {
@@ -3396,6 +3480,8 @@ int cmd_charset(const char* arg)
             cmd_displaycharset(l2);
         if (*l3)
             cmd_marccharset(l3);
+        if (*l4)
+            cmd_querycharset(l4);
     }
     return 1;
 }
@@ -3403,7 +3489,7 @@ int cmd_charset(const char* arg)
 int cmd_lang(const char* arg)
 {
     if (*arg == '\0') {
-        printf("Current language is `%s'\n", (yazLang)?yazLang:NULL);
+        printf("Current language is `%s'\n", yazLang ? yazLang : "none");
         return 1;
     }
     xfree (yazLang);
@@ -3632,8 +3718,8 @@ int cmd_register_oid(const char* args) {
     };
     char oname_str[101], oclass_str[101], oid_str[101];  
     int i;
-    int oidclass = CLASS_GENERAL;
-    int oid[OID_SIZE];
+    oid_class oidclass = CLASS_GENERAL;
+    Odr_oid oid[OID_SIZE];
 
     if (sscanf (args, "%100[^ ] %100[^ ] %100s",
                 oname_str,oclass_str, oid_str) < 1) {
@@ -3675,19 +3761,42 @@ int cmd_push_command(const char* arg)
     return 1;
 }
 
-void source_rcfile(void)
+void source_rc_file(const char *rc_file)
 {
-    /*  Look for a $HOME/.yazclientrc and source it if it exists */
+    /*  If rc_file != NULL, source that. Else
+        Look for .yazclientrc and read it if it exists. 
+        If it does not exist, read  $HOME/.yazclientrc instead */
     struct stat statbuf;
-    char fname[1000];
-    char* homedir = getenv("HOME");
 
-    sprintf(fname, "%.500s%s%s", homedir ? homedir : "",
-            homedir ? "/" : "",
-            ".yazclientrc");
-
-    if (stat(fname,&statbuf)==0)
-        cmd_source(fname, 0 );
+    if (rc_file)
+    {
+        if (stat(rc_file, &statbuf) == 0)
+            cmd_source(rc_file, 0);
+        else
+        {
+            fprintf(stderr, "yaz_client: cannot source '%s'\n", rc_file);
+            exit(1);
+        }
+    }
+    else
+    {
+        char fname[1000];
+        strcpy(fname, ".yazclientrc");
+        if (stat(fname, &statbuf)==0)
+        {
+            cmd_source(fname, 0);
+        }
+        else
+        {
+            const char* homedir = getenv("HOME");
+            if (homedir)
+            {
+                sprintf(fname, "%.800s/%s", homedir, ".yazclientrc");
+                if (stat(fname, &statbuf)==0)
+                    cmd_source(fname, 0);
+            }
+        }
+    }
 }
 
 void add_to_readline_history(void *client_data, const char *line)
@@ -3698,7 +3807,7 @@ void add_to_readline_history(void *client_data, const char *line)
 #endif
 }
 
-static void initialize(void)
+static void initialize(const char *rc_file)
 {
     FILE *inf;
     int i;
@@ -3727,7 +3836,8 @@ static void initialize(void)
     /* If this fails, no problem: we detect cqltrans == 0 later */
 
 #if HAVE_READLINE_READLINE_H
-    rl_attempted_completion_function = (CPPFunction*)readline_completer;
+    rl_attempted_completion_function = 
+        (char **(*)(const char *, int, int)) readline_completer;
 #endif
     for(i = 0; i < maxOtherInfosSupported; ++i) {
         extraOtherInfos[i].oid[0] = -1;
@@ -3736,7 +3846,7 @@ static void initialize(void)
 
     cmd_format("usmarc");
     
-    source_rcfile();
+    source_rc_file(rc_file);
 
     file_history = file_history_new();
     file_history_load(file_history);
@@ -3844,11 +3954,11 @@ static void handle_srw_scan_response(Z_SRW_scanResponse *res)
 static void http_response(Z_HTTP_Response *hres)
 {
     int ret = -1;
-    const char *content_type = z_HTTP_header_lookup(hres->headers,
-                                                    "Content-Type");
     const char *connection_head = z_HTTP_header_lookup(hres->headers,
                                                        "Connection");
-    if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
+    if (!yaz_srw_check_content_type(hres))
+        printf("Content type does not appear to be XML\n");
+    else
     {
         Z_SOAP *soap_package = 0;
         ODR o = odr_createmem(ODR_DECODE);
@@ -3862,7 +3972,7 @@ static void http_response(Z_HTTP_Response *hres)
                            soap_handlers);
         if (!ret && soap_package->which == Z_SOAP_generic)
         {
-            Z_SRW_PDU *sr = soap_package->u.generic->p;
+            Z_SRW_PDU *sr = (Z_SRW_PDU *) soap_package->u.generic->p;
             if (sr->which == Z_SRW_searchRetrieve_response)
                 handle_srw_response(sr->u.response);
             else if (sr->which == Z_SRW_explain_response)
@@ -4142,7 +4252,7 @@ int cmd_set_otherinfo(const char* args)
     else
     {
         NMEM oid_tmp = nmem_create();
-        const int *oid =
+        const Odr_oid *oid =
             yaz_string_to_oid_nmem(yaz_oid_std(),
                                    CLASS_GENERAL, oidstr, oid_tmp);
         oid_oidcpy(extraOtherInfos[otherinfoNo].oid, oid);
@@ -4185,7 +4295,7 @@ int cmd_list_otherinfo(const char* args)
         if (extraOtherInfos[i].value)
         {
             char name_oid[OID_STR_MAX];
-            int oclass;
+            oid_class oclass;
             const char *name =
                 yaz_oid_to_string_buf(extraOtherInfos[i].oid, &oclass,
                                       name_oid);
@@ -4202,7 +4312,7 @@ int cmd_list_otherinfo(const char* args)
             if (extraOtherInfos[i].value)
             {
                 char name_oid[OID_STR_MAX];
-                int oclass;
+                oid_class oclass;
                 const char *name =
                     yaz_oid_to_string_buf(extraOtherInfos[i].oid, &oclass,
                                           name_oid);
@@ -4210,7 +4320,6 @@ int cmd_list_otherinfo(const char* args)
                        i, name ? name : "null",
                        extraOtherInfos[i].value);
             }
-            
         }
     }
     return 0;
@@ -4353,6 +4462,7 @@ static struct {
     {"delete", cmd_delete, "<setname>",NULL,0,NULL},
     {"base", cmd_base, "<base-name>",NULL,0,NULL},
     {"show", cmd_show, "<rec#>['+'<#recs>['+'<setname>]]",NULL,0,NULL},
+    {"setscan", cmd_setscan, "<term>",NULL,0,NULL},
     {"scan", cmd_scan, "<term>",NULL,0,NULL},
     {"scanstep", cmd_scanstep, "<size>",NULL,0,NULL},
     {"scanpos", cmd_scanpos, "<size>",NULL,0,NULL},
@@ -4383,6 +4493,7 @@ static struct {
     {"negcharset", cmd_negcharset, "<nego_charset>",NULL,0,NULL},
     {"displaycharset", cmd_displaycharset, "<output_charset>",NULL,0,NULL},
     {"marccharset", cmd_marccharset, "<charset_name>",NULL,0,NULL},
+    {"querycharset", cmd_querycharset, "<charset_name>",NULL,0,NULL},
     {"lang", cmd_lang, "<language_code>",NULL,0,NULL},
     {"source", cmd_source_echo, "<filename>",NULL,1,NULL},
     {".", cmd_source_echo, "<filename>",NULL,1,NULL},
@@ -4743,6 +4854,7 @@ int main(int argc, char **argv)
     char *open_command = 0;
     char *auth_command = 0;
     char *arg;
+    const char *rc_file = 0;
     int ret;
     
 #if HAVE_LOCALE_H
@@ -4765,8 +4877,9 @@ int main(int argc, char **argv)
     ODR_MASK_SET(&z3950_options, Z_Options_sort);
     ODR_MASK_SET(&z3950_options, Z_Options_extendedServices);
     ODR_MASK_SET(&z3950_options, Z_Options_delSet);
+    ODR_MASK_SET(&z3950_options, Z_Options_negotiationModel);
 
-    while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2)
+    while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:f:", argv, argc, &arg)) != -2)
     {
         switch (ret)
         {
@@ -4784,9 +4897,28 @@ int main(int argc, char **argv)
                 exit(1);
             }
             break;
+        case 'a':
+            if (!strcmp(arg, "-"))
+                apdu_file=stderr;
+            else
+                apdu_file=fopen(arg, "a");
+            break;
+        case 'b':
+            if (!strcmp(arg, "-"))
+                ber_file=stderr;
+            else
+                ber_file=fopen(arg, "a");
+            break;
+        case 'c':
+            strncpy (ccl_fields, arg, sizeof(ccl_fields)-1);
+            ccl_fields[sizeof(ccl_fields)-1] = '\0';
+            break;
         case 'd':
             dump_file_prefix = arg;
             break;
+        case 'f':
+            rc_file = arg;
+            break;
         case 'k':
             kilobytes = atoi(arg);
             break;
@@ -4797,34 +4929,15 @@ int main(int argc, char **argv)
                 exit (1);
             }
             break;
-        case 't':
-            outputCharset = xstrdup(arg);
-            break;
-        case 'c':
-            strncpy (ccl_fields, arg, sizeof(ccl_fields)-1);
-            ccl_fields[sizeof(ccl_fields)-1] = '\0';
+        case 'p':
+            yazProxy = xstrdup(arg);
             break;
         case 'q':
             strncpy (cql_fields, arg, sizeof(cql_fields)-1);
             cql_fields[sizeof(cql_fields)-1] = '\0';
             break;
-        case 'b':
-            if (!strcmp(arg, "-"))
-                ber_file=stderr;
-            else
-                ber_file=fopen(arg, "a");
-            break;
-        case 'a':
-            if (!strcmp(arg, "-"))
-                apdu_file=stderr;
-            else
-                apdu_file=fopen(arg, "a");
-            break;
-        case 'x':
-            hex_dump = 1;
-            break;
-        case 'p':
-            yazProxy = xstrdup(arg);
+        case 't':
+            outputCharset = xstrdup(arg);
             break;
         case 'u':
             if (!auth_command)
@@ -4840,24 +4953,31 @@ int main(int argc, char **argv)
         case 'V':
             show_version();
             break;
+        case 'x':
+            hex_dump = 1;
+            break;
         default:
             fprintf (stderr, "Usage: %s "
-                     " [-a <apdulog>]"
+                     " [-a apdulog]"
                      " [-b berdump]"
-                     " [-d dump]\n"
-                     " [-c cclfields]"
+                     " [-c cclfile]"
+                     " [-d dump]"
+                     " [-f cmdfile]"
                      " [-k size]"
-                     " [-m <marclog>]\n" 
-                     " [-p <proxy-addr>]"
-                     " [-q cqlfields]"
-                     " [-u <auth>]"
+                     " [-m marclog]" 
+                     " [-p proxy-addr]"
+                     " [-q cqlfile]"
+                     " [-t dispcharset]"
+                     " [-u auth]"
+                     " [-v loglevel]"
                      " [-V]"
-                     " [<server-addr>]\n",
+                     " [-x]"
+                     " [server-addr]\n",
                      prog);
             exit (1);
         }      
     }
-    initialize();
+    initialize(rc_file);
     if (auth_command)
     {
 #ifdef HAVE_GETTIMEOFDAY