SOAP, SRW codecs and HTTP transport for YAZ using libxml2.
[yaz-moved-to-github.git] / srwapps / srw-gateway.c
diff --git a/srwapps/srw-gateway.c b/srwapps/srw-gateway.c
deleted file mode 100644 (file)
index aa0f458..0000000
+++ /dev/null
@@ -1,911 +0,0 @@
-/* $Id: srw-gateway.c,v 1.2 2003-01-20 13:04:50 adam Exp $
-   Copyright (C) 2002-2003
-   Index Data Aps
-
-This file is part of the YAZ toolkit.
-
-See the file LICENSE.
-*/
-
-/*
- * TODO:
- *
- * TTL for targets. Separate thread for cleanup.
- * External target config and aliases.
- */
-
-/* note that soapH.h defines _REENTRANT so we check for it here */
-#ifdef _REENTRANT
-#include <pthread.h>
-#define USE_THREADS 1
-#else
-#define USE_THREADS 0
-#endif
-
-#include <yaz/srw-util.h>
-#include <yaz/xmalloc.h>
-#include <yaz/zoom.h>
-#include <yaz/log.h>
-#include <yaz/options.h>
-#include <yaz/wrbuf.h>
-
-#define RESULT_SETS 0
-#define SRW_DEBUG 1
-
-struct tset {
-    ZOOM_resultset m_r;
-    long m_expiry_sec;   /* date of creation */
-    int m_idle_time;
-    char *m_query;
-    char *m_schema;
-    struct tset *m_next;
-};
-
-struct target {
-    ZOOM_connection m_c;
-    char *m_name;
-    int m_in_use;
-    struct tset *m_sets;
-    struct target *next;
-};
-
-struct srw_prop {
-    int optimize_level;
-    int idle_time;
-    int max_sets;
-    xslt_maps maps;
-};
-
-static cql_transform_t cql_transform_handle = 0;
-static struct target *target_list = 0;
-#if USE_THREADS
-static pthread_mutex_t target_mutex = PTHREAD_MUTEX_INITIALIZER;
-#define mylock(x) pthread_mutex_lock(x)
-#define myunlock(x) pthread_mutex_unlock(x)
-#else
-#define mylock(x)
-#define myunlock(x)
-#endif
-
-#define ERROR_NO_TARGET -1
-#define ERROR_BAD_CQL   10
-
-static int diag_bib1_to_srw (int code)
-{
-    static int map[] = {
-        1, 1,
-        2, 2,
-        3, 11,
-        4, 35,
-        5, 12,
-        6, 30,
-        7, 30,
-        8, 32,
-        9, 29,
-        10, 10,
-        11, 12,
-        13, 61,
-        14, 63,
-        15, 68,
-        16, 70,
-        17, 70,
-        18, 50,
-        19, 55,
-        20, 56, 
-        21, 52,
-        22, 50,
-        /* 23-26 no map */
-        27, 51,
-        28, 52,
-        29, 52,
-        30, 51,
-        31, 52,
-        32, 52,
-        33, 52,
-        /* 100 -105 */
-        106, 66,
-        107, 11,
-        108, 10,
-        109, 2,
-        110, 37,
-        /* 111- 112 */
-        113, 10,
-        114, 16,
-        115, 16,
-        116, 16,
-        117, 19,
-        118, 22,
-        119, 32,
-        120, 28,
-        121, 15,
-        122, 32,
-        123, 22,
-        124, 24,
-        125, 36,
-        126, 36, 
-        127, 36,
-        128, 51,
-        129, 39,
-        130, 43,
-        131, 40,
-        132, 42,
-        201, 44,
-        202, 41,
-        203, 43,
-        /* 205 */
-        0
-    };
-    const int *p = map;
-    while (*p)
-    {
-        if (code == *p)
-            return p[1];
-        p += 2;
-    }
-    return 0;
-}
-
-static int searchRetrieve(void *userinfo,
-                          struct soap * soap,
-                          xsd__string  *query,
-                          struct xcql__operandType *xQuery,    
-                          xsd__string *sortKeys,
-                          struct xsort__xSortKeysType *xSortKeys,
-                          xsd__integer *startRecord,
-                          xsd__integer *maximumRecords,
-                          xsd__string *recordSchema,
-                          xsd__string *recordPacking,
-                          struct zs__searchRetrieveResponse *res);
-static int explain (void *userinfo,
-                    struct soap *soap,
-                    struct zs__explainResponse *explainResponse);
-
-struct target *target_use (const char *action, const char *query,
-                           const char *schema, struct tset **set,
-                           struct srw_prop *prop)
-{
-    char name[80];
-    struct target *l = 0;
-    struct timeval tv;
-    struct tset **ssp = 0;
-    long now;
-    int no_sets = 0;
-
-    gettimeofday(&tv, 0);
-    now = tv.tv_sec;
-
-    if (strlen(action) >= 80)
-        action = "localhost:210";
-    if (strchr(action, '/') || strchr(action, ':'))
-        strcpy (name, action);
-    else
-    {
-        strcpy (name, "localhost/");
-        if (*action == '\0')
-            strcat (name, "Default");
-        else
-            strcat (name, action);
-    }
-
-    /* See if we have the target and the same query */
-    if (query)
-        for (l = target_list; l; l = l->next)
-            if (!l->m_in_use && !strcmp (l->m_name, name))
-            {
-                struct tset *s = l->m_sets;
-                for (; s; s = s->m_next)
-                    if (!strcmp(s->m_query, query) && 
-                        !strcmp (s->m_schema, schema))
-                    {
-                        *set = s;
-                        return l;
-                    }
-            }
-    
-    /* OK, see if we have the target, then.. */
-    for (l = target_list; l; l = l->next)
-        if (!strcmp (l->m_name, name) && !l->m_in_use)
-        {
-            struct tset *s = l->m_sets;
-            for (; s; s = s->m_next)
-                /* if m_expiry_sec is 0, the condition is true below */
-                if (s->m_expiry_sec < now)
-                {
-                    xfree (s->m_query);
-                    s->m_query = xstrdup("");
-                    xfree (s->m_schema);
-                    s->m_schema = xstrdup("");
-                    ZOOM_resultset_destroy(s->m_r);
-                    s->m_r = 0;
-                    *set = s;
-                    return l;
-                }
-            break;
-        }
-    if (!l)
-    {
-        /* allright. Have to make a new one */
-        l = xmalloc (sizeof(*l));
-        l->m_name = xstrdup (name);
-        l->m_in_use = 1;
-        l->m_c = 0;
-        l->m_sets = 0;
-        l->next = target_list;
-        target_list = l;
-    }
-    for (ssp = &l->m_sets; *ssp; ssp = &(*ssp)->m_next)
-        no_sets++;
-    *ssp = xmalloc(sizeof(**ssp));
-    (*ssp)->m_next = 0;
-    (*ssp)->m_query = xstrdup("");
-    (*ssp)->m_schema = xstrdup("");
-    (*ssp)->m_r = 0;
-    (*ssp)->m_expiry_sec = 0;
-    (*ssp)->m_idle_time = (no_sets >= prop->max_sets ? 0 : prop->idle_time);
-    *set = *ssp;
-    return l;
-}
-
-static void target_destroy (struct target *t)
-{
-    struct target **tp;
-
-    mylock(&target_mutex);
-
-    for (tp = &target_list; *tp; tp = &(*tp)->next)
-        if (*tp == t)
-        {
-            struct tset *s = t->m_sets;
-            while (s)
-            {
-                struct tset *s_next = s->m_next;
-                xfree (s->m_query);
-                xfree (s->m_schema);
-                ZOOM_resultset_destroy (s->m_r);
-                xfree (s);
-                s = s_next;
-            }
-
-            *tp = t->next;
-
-            ZOOM_connection_destroy (t->m_c);
-
-            xfree (t->m_name);
-            xfree (t);
-            break;
-        }
-    myunlock(&target_mutex);
-}
-    
-static void target_leave (struct target *l)
-{
-    mylock(&target_mutex);
-    l->m_in_use = 0;
-
-    if (1)
-    {
-        struct tset *s = l->m_sets;
-        for (; s; s = s->m_next)
-            yaz_log(LOG_LOG, " set %s q=%s", 
-                    (s->m_r ? ZOOM_resultset_option_get(s->m_r,"setname"):""),
-                    s->m_query);
-    }
-    myunlock(&target_mutex);
-}
-
-#if USE_THREADS
-static void *p_serve (void *p)
-{
-    struct soap *soap = p;
-    yaz_srw_serve(soap, searchRetrieve, explain);
-}
-#endif
-
-
-static void standalone(struct soap *soap, const char *host, int port,
-                       int max_thr, struct srw_prop *properties)
-{
-    struct soap **soap_thr = malloc (sizeof(*soap_thr) * max_thr);
-#if USE_THREADS
-    pthread_t *tid = malloc (sizeof(pthread_t) * max_thr);
-#endif
-    int m, s, i;
-    int cno = 0;
-    int stop = 0;
-    char fname[40];
-    
-    m = soap_bind(soap, 0, port, 100);
-    if (m < 0)
-    {
-        yaz_log (LOG_WARN|LOG_ERRNO, "Cannot bind to %d", port);
-        stop = 1;
-    }
-
-    for (i = 0; i<max_thr; i++)
-        soap_thr[i] = 0;
-
-    while (!stop)
-    {
-        for (i = 0; i<max_thr; i++)
-        {
-            s = soap_accept(soap);
-            if (s < 0)
-                break;
-            cno++;
-            if (!soap_thr[i])
-            {
-                soap_thr[i] = soap_new();
-                if (!soap_thr[i])
-                {
-                    stop = 1;
-                    break;
-                }
-            }
-            else
-            {
-#if USE_THREADS
-                if (max_thr > 1)          /* static mode for max_thr <= 1 */
-                    pthread_join(tid[i], 0);
-#endif
-                soap_end(soap_thr[i]);
-            }
-
-#if SRW_DEBUG
-            sprintf (fname, "srw.recv.%05d.log", cno);
-           remove (fname);
-            soap_set_recv_logfile(soap_thr[i], fname);
-            
-            sprintf (fname, "srw.sent.%05d.log", cno);
-           remove (fname);
-            soap_set_sent_logfile(soap_thr[i], fname);
-            
-            sprintf (fname, "srw.test.%05d.log", cno);
-           remove (fname);
-            soap_set_test_logfile(soap_thr[i], fname);
-
-            yaz_log (LOG_LOG, "starting session %d %ld.%ld.%ld.%ld", cno,
-                     (long) (soap->ip>>24) & 0xff,
-                     (long) (soap->ip>>16) & 0xff,
-                     (long) (soap->ip>>8) & 0xff,
-                     (long) soap->ip & 0xff);
-#endif
-            soap_thr[i]->encodingStyle = 0;
-            soap_thr[i]->socket = s;
-            soap_thr[i]->user = properties;
-#if USE_THREADS
-            if (max_thr <= 1)
-                yaz_srw_serve(soap_thr[i],
-                              searchRetrieve, explain);  /* static mode .. */
-            else
-                pthread_create(&tid[i], 0, p_serve, soap_thr[i]);
-#else
-            yaz_srw_serve(soap_thr[i],
-                          searchRetrieve, explain);  /* static mode .. */
-#endif
-        }
-    }
-#if USE_THREADS
-    free (tid);
-#endif
-    free (soap_thr);
-}
-
-static void reconnect (struct target *t)
-{
-    struct tset *s;
-
-    for (s = t->m_sets; s; s = s->m_next)
-    {
-        ZOOM_resultset_destroy(s->m_r);
-        s->m_r = 0;
-    }
-    ZOOM_connection_destroy (t->m_c);
-
-    t->m_c = ZOOM_connection_create (0);
-    ZOOM_connection_connect (t->m_c, t->m_name, 0);
-}
-
-int explain (void *userinfo,
-             struct soap *soap,
-             struct zs__explainResponse *explainResponse)
-{
-    explainResponse->Explain = 
-        "<explain>\n"
-        "  <!-- not implemented -->\n"
-        "</explain>\n";
-    return SOAP_OK;
-}
-
-int fetchone(struct soap *soap, struct srw_prop *properties,
-             ZOOM_record zrec, const char *schema,
-             char **rec_data, char **rec_schema)
-{
-    xslt_map_result res;
-    int xml_len;
-    const char *xml_rec = ZOOM_record_get(zrec, "xml", &xml_len);
-    if (!xml_rec)
-    {
-        return 65;
-    }
-    if (!strcmp(schema, "MARC21") || !strcmp(schema, "http://www.loc.gov/marcxml/"))
-    {
-        *rec_data = soap_malloc (soap, xml_len+1);
-        memcpy (*rec_data, xml_rec, xml_len);
-        (*rec_data)[xml_len] = 0;
-        *rec_schema = "http://www.loc.gov/marcxml/";
-    }
-    else if ((res = xslt_map (properties->maps, "MARC21",
-                              schema, xml_rec, xml_len)))
-    {
-        int len = xslt_map_result_len(res);
-        char *buf = xslt_map_result_buf(res);
-
-        *rec_data = soap_malloc (soap, len+1);
-        memcpy (*rec_data, buf, len);
-        (*rec_data)[len] = 0;
-        
-        *rec_schema = soap_malloc(soap,
-                                  strlen(xslt_map_result_schema(res)) + 1);
-        strcpy(*rec_schema, xslt_map_result_schema(res));
-        
-        xslt_map_free (res);
-    }
-    else
-    {
-        *rec_data = soap_malloc(soap, strlen(schema)+1);
-        strcpy(*rec_data, schema);
-        return 66;
-    }
-    return 0;
-}
-                
-int searchRetrieve(void *userinfo,
-                   struct soap * soap,
-                   xsd__string  *query,
-                   struct xcql__operandType *xQuery,   
-                   xsd__string *sortKeys,
-                   struct xsort__xSortKeysType *xSortKeys,
-                   xsd__integer *startRecord,
-                   xsd__integer *maximumRecords,
-                   xsd__string *recordSchema,
-                   xsd__string *recordPacking,
-                   struct zs__searchRetrieveResponse *res)
-{
-    const char *msg = 0, *addinfo = 0;
-    const char *schema = recordSchema ? *recordSchema : "";
-    struct target *t = 0;
-    struct tset *s = 0;
-    int error = 0;
-    struct srw_prop *properties = (struct srw_prop*) userinfo;
-    WRBUF wr_log = wrbuf_alloc();
-
-    char pqf_buf[1024];
-    char zurl[81];
-
-    *pqf_buf = '\0';
-    *zurl = '\0';
-    yaz_log (LOG_LOG, "HTTP: %s", soap->endpoint);
-    if (*soap->endpoint)
-    {
-        const char *cp = strstr(soap->endpoint, "//");
-       if (cp)
-            cp = cp+2;             /* skip method// */
-       else
-            cp = soap->endpoint;
-       cp = strstr(cp, "/"); 
-       if (cp)
-        {
-            size_t len;
-            cp++;
-            len = strlen(cp);
-            if (len > 80)
-                len = 80;
-            if (len)
-                memcpy (zurl, cp, len);
-            zurl[len] = '\0';
-        }
-    }
-    else
-    {
-        const char *cp = getenv("PATH_INFO");
-        if (cp && cp[0] && cp[1])
-        {
-            size_t len;
-            cp++;  /* skip / */
-            len = strlen(cp);
-            if (len > 80)
-                len = 80;
-            if (len)
-                memcpy (zurl, cp, len);
-            zurl[len] = '\0';
-        }
-    }
-    if (query)
-    {
-        CQL_parser cql_parser = cql_parser_create();
-        int r = cql_parser_string(cql_parser, *query);
-
-        if (r)
-        {
-            yaz_log (LOG_LOG, "cql failed: %s", *query);
-            error = ERROR_BAD_CQL;
-        }
-        else
-        {
-            struct cql_node *tree = cql_parser_result(cql_parser);
-            error = cql_transform_buf (cql_transform_handle, tree,
-                                       pqf_buf, sizeof(pqf_buf));
-            if (error)
-                cql_transform_error(cql_transform_handle, &addinfo);
-            cql_parser_destroy(cql_parser);
-            yaz_log (LOG_LOG, "cql OK: %s", *query);
-        }
-    }
-    else if (xQuery)
-    {
-        struct cql_node *tree = xcql_to_cqlnode(xQuery);
-        yaz_log (LOG_LOG, "xcql");
-        cql_transform_buf (cql_transform_handle, tree,
-                           pqf_buf, sizeof(pqf_buf));
-        cql_node_destroy(tree);
-    }
-    if (!error)
-    {
-        mylock(&target_mutex);
-        t = target_use (zurl, *pqf_buf ? pqf_buf : 0, schema, &s, properties);
-        myunlock(&target_mutex);
-    }
-
-    if (!error && !t->m_c)
-    {
-        reconnect(t);
-        if (ZOOM_connection_error (t->m_c, &msg, &addinfo))
-        {
-            yaz_log (LOG_LOG, "%s: connect failed", t->m_name);
-            error = ERROR_NO_TARGET;
-        }
-        else
-            yaz_log (LOG_LOG, "%s: connect ok", t->m_name);
-    }
-    if (!error && t->m_c &&  *pqf_buf)
-    {
-        if (properties->optimize_level <=1 ||
-            strcmp (pqf_buf, s->m_query) ||
-            strcmp (schema, s->m_schema))
-        {
-            /* not the same query: remove result set .. */
-            ZOOM_resultset_destroy (s->m_r);
-            s->m_r = 0;
-        }
-        else
-        {
-            /* same query: retrieve (instead of doing search) */
-            if (maximumRecords && *maximumRecords > 0)
-            {
-                int start = startRecord ? *startRecord : 1;
-                yaz_log (LOG_LOG, "%s: present start=%d count=%d pqf=%s",
-                         t->m_name, start, *maximumRecords, pqf_buf);
-                wrbuf_printf (wr_log, "%s: present start=%d count=%d pqf=%s",
-                              t->m_name, start, *maximumRecords, pqf_buf);
-                ZOOM_resultset_records (s->m_r, 0, start-1, *maximumRecords);
-                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
-                if (error == ZOOM_ERROR_CONNECTION_LOST ||
-                    error == ZOOM_ERROR_CONNECT)
-                {
-                    reconnect (t);
-                    if ((error = ZOOM_connection_error (t->m_c, &msg,
-                                                    &addinfo)))
-                    {
-                        yaz_log (LOG_LOG, "%s: connect failed", t->m_name);
-                        error = ERROR_NO_TARGET;
-                    }
-                }
-                else if (error)
-                {
-                    yaz_log (LOG_LOG, "%s: present failed bib1-code=%d",
-                             t->m_name, error);
-                    error = diag_bib1_to_srw(error);
-                }
-            }
-            else
-            {
-                yaz_log (LOG_LOG, "%s: matched search pqf=%s",
-                         t->m_name, pqf_buf);
-                wrbuf_printf (wr_log, "%s: matched search pqf=%s",
-                         t->m_name, pqf_buf);
-            }
-        }
-        if (!error && !s->m_r) 
-        {   /* no result set usable. We must search ... */
-            int pass;
-            for (pass = 0; pass < 2; pass++)
-            {
-                char val[30];
-                int start = startRecord ? *startRecord : 1;
-                int count = maximumRecords ? *maximumRecords : 0;
-                
-                sprintf (val, "%d", start-1);
-                ZOOM_connection_option_set (t->m_c, "start", val);
-                
-                sprintf (val, "%d", count);
-                ZOOM_connection_option_set (t->m_c, "count", val);
-                
-                ZOOM_connection_option_set (t->m_c, "preferredRecordSyntax", 
-                                            "usmarc");
-                
-                xfree (s->m_query);
-                s->m_query = xstrdup (pqf_buf);
-
-                xfree (s->m_schema);
-                s->m_schema = xstrdup (schema);
-                
-                yaz_log (LOG_LOG, "%s: search start=%d count=%d pqf=%s",
-                         t->m_name, start, count, pqf_buf);
-                
-                wrbuf_printf (wr_log, "%s: search start=%d count=%d pqf=%s",
-                              t->m_name, start, count, pqf_buf);
-                
-                s->m_r = ZOOM_connection_search_pqf (t->m_c, s->m_query);
-                
-                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
-                if (!error)
-                    break;
-                if (error != ZOOM_ERROR_CONNECTION_LOST &&
-                    error != ZOOM_ERROR_CONNECT)
-                {
-                    yaz_log (LOG_LOG, "%s: search failed bib1-code=%d",
-                             t->m_name, error);
-                    error = diag_bib1_to_srw(error);
-                    break;
-                }
-                yaz_log (LOG_LOG, "%s: reconnect (search again)", t->m_name);
-
-                /* try once more */
-                reconnect(t);
-
-                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
-
-                if (error)
-                {
-                    error = ERROR_NO_TARGET;
-                    break;
-                }
-            }
-        }
-    }
-    
-    if (!error && t->m_c && s->m_r)
-    {
-        yaz_log (LOG_LOG, "%s: %d hits", t->m_name,
-                 ZOOM_resultset_size(s->m_r));
-        res->numberOfRecords = ZOOM_resultset_size(s->m_r);
-        
-        if (maximumRecords)
-        {
-            int i, j = 0;
-            int offset = startRecord ? *startRecord -1 : 0;
-            res->records.record =
-                soap_malloc(soap, sizeof(*res->records.record) *
-                            *maximumRecords);
-            
-            for (i = 0; i < *maximumRecords; i++)
-            {
-                char *rec_data = 0;
-                char *rec_schema = 0;
-                ZOOM_record zrec = ZOOM_resultset_record (s->m_r, offset + i);
-                if (!zrec)
-                {
-                    error = 65;
-                    addinfo = schema;
-                    break;
-                }
-                error = fetchone(soap, properties, zrec, schema,
-                                 &rec_data, &rec_schema);
-                if (error)
-                {
-                    addinfo = rec_data;
-                    break;
-                }
-                res->records.record[j] = 
-                    soap_malloc(soap, sizeof(**res->records.record));
-                res->records.record[j]->recordData = rec_data;
-                res->records.record[j]->recordSchema = rec_schema;
-                j++;
-            }
-            res->records.__sizeRecords = j;
-        }
-        else
-            res->numberOfRecords = 0;
-    }
-    if (error)
-    {
-        if (s)
-        {
-            ZOOM_resultset_destroy (s->m_r);
-            s->m_r = 0;
-        }
-        if (error == ERROR_NO_TARGET)
-        {
-            addinfo = zurl;
-            ZOOM_connection_destroy (t->m_c);
-            t->m_c = 0;
-        }
-        else
-        {
-            res->diagnostics.__sizeDiagnostics = 1;
-            res->diagnostics.diagnostic =
-                soap_malloc (soap, sizeof(*res->diagnostics.diagnostic));
-            res->diagnostics.diagnostic[0] =
-                soap_malloc (soap, sizeof(**res->diagnostics.diagnostic));
-            
-            res->diagnostics.diagnostic[0]->code = error;
-            if (addinfo)
-            {
-                res->diagnostics.diagnostic[0]->details =
-                    soap_malloc (soap, strlen(addinfo) + 1);
-                strcpy (res->diagnostics.diagnostic[0]->details, addinfo);
-            }
-            else
-                res->diagnostics.diagnostic[0]->details = 0;
-        }
-    }
-    else
-    {
-        if (s->m_r)
-        {
-            struct timeval tv;
-            const char *setname = ZOOM_resultset_option_get(s->m_r, "setname");
-            if (strcmp(setname, "default") && s->m_idle_time)
-            {
-                res->resultSetId = soap_malloc(soap, strlen(setname));
-                strcpy(res->resultSetId, setname);
-                res->resultSetIdleTime = s->m_idle_time;
-                gettimeofday(&tv, 0);
-                s->m_expiry_sec = res->resultSetIdleTime + tv.tv_sec + 2;
-            } else {
-                s->m_expiry_sec = 0;
-            }
-        }
-    }
-
-    if (t)
-    {
-        if (properties->optimize_level > 0)
-            target_leave(t);
-        else
-            target_destroy(t);
-    }
-    wrbuf_free(wr_log, 1);
-    if (error == ERROR_NO_TARGET)
-        return soap_receiver_fault(soap, "Cannot connect to Z39.50 target", 0);
-    return SOAP_OK;
-}
-
-int main(int argc, char **argv)
-{
-    struct soap soap;
-    int ret;
-    int port = 0;
-    int no_threads = 40;
-    char *arg;
-    const char *host = 0;
-    struct srw_prop properties;
-
-    properties.optimize_level = 2;
-    properties.idle_time = 300;
-    properties.max_sets = 30;
-    properties.maps = 0;
-            
-    while ((ret = options("dO:T:l:hVp:s:x:i:", argv, argc, &arg)) != -2)
-    {
-        switch(ret)
-        {
-        case 0:
-            port = atoi(arg);
-            break;
-        case 'O':
-            properties.optimize_level = atoi(arg);
-            break;
-        case 'T':
-            no_threads = atoi(arg);
-            if (no_threads < 1 || no_threads > 200)
-                no_threads = 40;
-            break;
-        case 's':
-            if (!properties.maps)
-            {
-                properties.maps = xslt_maps_create();
-                if (xslt_maps_file(properties.maps, arg))
-                {
-                    fprintf (stderr, "maps file %s could not be opened\n",
-                             arg);
-                    exit(1);
-                }
-            }
-            break;
-        case 'l':
-            yaz_log_init_file(arg);
-            break;
-        case 'V':
-            puts ("Version: $Id: srw-gateway.c,v 1.2 2003-01-20 13:04:50 adam Exp $"
-#if SRW_DEBUG
-            " DEBUG"
-#endif
-                );
-            exit (0);
-        case 'p':
-            if (cql_transform_handle == 0)
-                cql_transform_handle = cql_transform_open_fname(arg);
-            break;
-        case 'x':
-            properties.max_sets = atoi(arg);
-            break;
-        case 'i':
-            properties.idle_time = atoi(arg);
-            break;
-        case 'h':
-            printf ("srw-gateway [options] <port>\n");
-            printf ("  port  port for standalone service; If port is omitted, CGI is used.\n");
-            printf ("  -O n     optimize level. >= 1 cache connections, >=2 cache result sets.\n");
-#if USE_THREADS
-            printf ("  -T n     number of threads.\n");
-#else
-            printf ("  -T       unsupported in this version.\n");
-#endif
-            printf ("  -l file  log to file (instead of stderr).\n");
-            printf ("  -p file  PQF properties.\n");
-            printf ("  -s file  schema maps.\n");
-            printf ("  -i time  idle time.\n");
-            printf ("  -x sets  live sets.\n");
-            printf ("  -V       show version.\n");
-            exit (1);
-        default:
-            fprintf (stderr, "srw-gateway: bad option -%s ; use -h for help\n",
-                     arg);
-            exit (1);
-            break;
-            
-        }
-    }
-    if (!cql_transform_handle)
-        cql_transform_handle = cql_transform_open_fname("pqf.properties");
-    if (!properties.maps)
-    {
-        properties.maps = xslt_maps_create();
-        xslt_maps_file(properties.maps, "maps.xml");
-    }
-    soap.encodingStyle = 0;
-    if (port == 0 && getenv("QUERY_STRING"))
-    {
-        properties.optimize_level = 0;
-
-        yaz_log_init_file("srw.log");
-        yaz_log (LOG_LOG, "CGI begin");
-        soap_init(&soap);
-        soap.user = &properties;
-
-        yaz_srw_serve(&soap, searchRetrieve, explain);
-
-        soap_end(&soap);
-        yaz_log (LOG_LOG, "CGI end");
-    }
-    else if (port)
-    {
-        if (!cql_transform_handle)
-        {
-            fprintf(stderr, "no properties file; use option -p to specify\n");
-            exit (1);
-        }
-        yaz_log (LOG_LOG, "standalone service on port %d", port);
-        
-        soap_init(&soap);
-
-        standalone(&soap, host, port, no_threads, &properties);
-    }
-    else
-    {
-        fprintf(stderr, "srw-gateway: no port specified. Use -h for help\n");
-    }
-    xslt_maps_free(properties.maps);
-    return 0;
-}