Add trivial support for implementation_id specified by backend.
[yaz-moved-to-github.git] / doc / frontend.xml
1 <!-- $Id: frontend.xml,v 1.11 2002-03-05 12:45:48 mike Exp $ -->
2  <chapter id="server"><title>Generic server</title>
3   <sect1><title>Introduction</title>
4
5    <para>
6     If you aren't into documentation, a good way to learn how the
7     back end interface works is to look at the <filename>backend.h</filename>
8     file. Then, look at the small dummy-server in
9     <filename>ztest/ztest.c</filename>. The <filename>backend.h</filename>
10     file also makes a good reference, once you've chewed your way through
11     the prose of this file.
12    </para>
13
14    <para>
15     If you have a database system that you would like to make available by
16     means of Z39.50, &yaz; basically offers your two options. You
17     can use the APIs provided by the &asn;, &odr;, and &comstack;
18     modules to
19     create and decode PDUs, and exchange them with a client.
20     Using this low-level interface gives you access to all fields and
21     options of the protocol, and you can construct your server as close
22     to your existing database as you like.
23     It is also a fairly involved process, requiring
24     you to set up an event-handling mechanism, protocol state machine,
25     etc. To simplify server implementation, we have implemented a compact
26     and simple, but reasonably full-functioned server-frontend that will
27     handle most of the protocol mechanics, while leaving you to
28     concentrate on your database interface.
29    </para>
30
31    <note>
32     <para>
33      The backend interface was designed in anticipation of a specific
34      integration task, while still attempting to achieve some degree of
35      generality. We realize fully that there are points where the
36      interface can be improved significantly. If you have specific
37      functions or parameters that you think could be useful, send us a
38      mail (or better, sign on to the mailing list referred to in the
39      top-level README file). We will try to fit good suggestions into future
40      releases, to the extent that it can be done without requiring
41      too many structural changes in existing applications.
42     </para>
43    </note>
44   </sect1>
45   
46   <sect1 id="server.frontend"><title>The Database Frontend</title>
47
48    <para>
49     We refer to this software as a generic database frontend. Your
50     database system is the <emphasis>backend database</emphasis>, and the
51     interface between the two is called the <emphasis>backend API</emphasis>.
52     The backend API consists of a small number of function handlers and
53     structure definitions. You are required to provide the
54     <function>main()</function> routine for the server (which can be
55     quite simple), as well as a set of handlers to match each of the prototypes.
56     The interface functions that you write can use any mechanism you like
57     to communicate with your database system: You might link the whole
58     thing together with your database application and access it by
59     function calls; you might use IPC to talk to a database server
60     somewhere; or you might link with third-party software that handles
61     the communication for you (like a commercial database client library).
62     At any rate, the handlers will perform the tasks of:
63    </para>
64
65    <itemizedlist>
66
67     <listitem><para>
68       Initialization.
69      </para></listitem>
70
71     <listitem><para>
72       Searching.
73      </para></listitem>
74
75     <listitem><para>
76       Fetching records.
77      </para></listitem>
78
79     <listitem><para>
80       Scanning the database index (optional - if you wish to implement SCAN).
81      </para></listitem>
82
83     <listitem><para>
84       Extended Services (optional).
85      </para></listitem>
86     
87     <listitem><para>
88       Result-Set Delete (optional).
89      </para></listitem>
90
91     <listitem><para>
92       Result-Set Sort (optional).
93      </para></listitem>
94     
95    </itemizedlist>
96
97    <para>
98     (more functions will be added in time to support as much of
99     Z39.50-1995 as possible).
100    </para>
101
102   </sect1>
103   <sect1 id="server.backend"><title>The Backend API</title>
104
105    <para>
106     The header file that you need to use the interface are in the
107     <filename>include/yaz</filename> directory. It's called
108     <filename>backend.h</filename>. It will include other files from
109     the <filename>include/yaz</filename> directory, so you'll
110     probably want to use the -I option of your compiler to tell it
111     where to find the files. When you run
112     <literal>make</literal> in the top-level &yaz; directory,
113     everything you need to create your server is to link with the
114     <filename>lib/libyaz.la</filename> library.
115    </para>
116   </sect1>
117
118   <sect1 id="server.main"><title>Your main() Routine</title>
119
120    <para>
121     As mentioned, your <function>main()</function> routine can be quite brief.
122     If you want to initialize global parameters, or read global configuration
123     tables, this is the place to do it. At the end of the routine, you should
124     call the function
125    </para>
126
127    <synopsis>
128 int statserv_main(int argc, char **argv,
129                   bend_initresult *(*bend_init)(bend_initrequest *r),
130                   void (*bend_close)(void *handle));
131    </synopsis>
132
133    <para>
134     The third and fourth arguments are pointers to handlers. Handler
135     <function>bend_init</function> is called whenever the server receives
136     an Initialize Request, so it serves as a Z39.50 session initializer. The
137     <function>bend_close</function> handler is called when the session is
138     closed.
139    </para>
140
141    <para>
142     <function>statserv_main</function> will establish listening sockets
143     according to the parameters given. When connection requests are received,
144     the event handler will typically <function>fork()</function> and
145     create a sub-process to handle a new connection.
146     Alternatively the server may be setup to create threads for each
147     connection.
148     If you do use global variables and forking, you should be aware, then,
149     that these cannot be shared between associations, unless you explicitly
150     disable forking by command line parameters. 
151    </para>
152    
153    <para>
154     The server provides a mechanism for controlling some of its behavior
155     without using command-line options. The function
156    </para>
157
158    <synopsis>
159 statserv_options_block *statserv_getcontrol(void);
160    </synopsis>
161
162    <para>
163     will return a pointer to a <literal>struct statserv_options_block</literal>
164     describing the current default settings of the server. The structure
165     contains these elements:
166     
167     <variablelist>
168      <varlistentry><term>
169        <literal>int dynamic</literal></term><listitem><para>
170         A boolean value, which determines whether the server
171         will fork on each incoming request (TRUE), or not (FALSE). Default is
172         TRUE. This flag is only read by UNIX-based servers (WIN32 based servers
173         doesn't fork).
174        </para></listitem></varlistentry>
175      
176      <varlistentry><term>
177        <literal>int threads</literal></term><listitem><para>
178         A boolean value, which determines whether the server
179         will create a thread on each incoming request (TRUE), or not (FALSE).
180         Default is FALSE. This flag is only read by UNIX-based servers
181         that offer POSIX Threads support.
182         WIN32-based servers always operate in threaded mode.
183        </para></listitem></varlistentry>
184      
185      <varlistentry><term>
186        <literal>int inetd</literal></term><listitem><para>
187         A boolean value, which determines whether the server
188         will operates under a UNIX INET daemon (inetd). Default is FALSE.
189        </para></listitem></varlistentry>
190      
191      <varlistentry><term>
192        <literal>int loglevel</literal></term><listitem><para>
193         Set this by ORing the constants defined in
194         <filename>include/yaz/yaz-log.h</filename>.
195        </para></listitem></varlistentry>
196      
197      <varlistentry><term>
198        <literal>char logfile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
199       <listitem><para>File for diagnostic output (&quot;&quot;: stderr).
200        </para></listitem></varlistentry>
201      
202      <varlistentry><term>
203        <literal>char apdufile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
204       <listitem><para>
205         Name of file for logging incoming and outgoing APDUs
206         (&quot;&quot;: don't log APDUs, &quot;-&quot;:
207         <literal>stderr</literal>).
208        </para></listitem></varlistentry>
209
210      <varlistentry><term>
211       <literal>char default_listen&lsqb;1024&rsqb;</literal></term>
212       <listitem><para>Same form as the command-line specification of
213         listener address. &quot;&quot;: no default listener address.
214         Default is to listen at &quot;tcp:@:9999&quot;. You can only
215         specify one default listener address in this fashion.
216        </para></listitem></varlistentry>
217
218      <varlistentry><term>
219       <literal>enum oid_proto default_proto;</literal></term>
220       <listitem><para>Either <literal>PROTO_Z3950</literal> or
221         <literal>PROTO_SR</literal>.
222         Default is <literal>PROTO_Z39_50</literal>.
223        </para></listitem></varlistentry>
224      
225      <varlistentry><term>
226        <literal>int idle_timeout;</literal></term>
227       <listitem><para>Maximum session idletime, in minutes. Zero indicates
228         no (infinite) timeout. Default is 120 minutes.
229        </para></listitem></varlistentry>
230      
231      <varlistentry><term>
232        <literal>int maxrecordsize;</literal></term>
233       <listitem><para>Maximum permissible record (message) size. Default
234         is 1Mb. This amount of memory will only be allocated if a
235         client requests a very large amount of records in one operation
236         (or a big record).
237         Set it to a lower number if you are worried about resource
238         consumption on your host system.
239        </para></listitem></varlistentry>
240
241      <varlistentry><term>
242        <literal>char configname&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
243       <listitem><para>Passed to the backend when a new connection is received.
244        </para></listitem></varlistentry>
245
246      <varlistentry><term>
247        <literal>char setuid&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
248       <listitem><para>Set user id to the user specified, after binding
249         the listener addresses.
250        </para></listitem></varlistentry>
251      
252      <varlistentry><term>
253        <literal>void (*bend_start)(struct statserv_options_block *p)</literal>
254       </term>
255       <listitem><para>Pointer to function which is called after the
256         command line options have been parsed - but before the server
257         starts listening.
258         For forked UNIX servers this handler is called in the mother
259         process; for threaded servers this handler is called in the
260         main thread.
261         The default value of this pointer is NULL in which case it
262         isn't invoked by the frontend server.
263         When the server operates as an NT service this handler is called
264         whenever the service is started. 
265        </para></listitem></varlistentry>
266      
267      <varlistentry><term>
268        <literal>void (*bend_stop)(struct statserv_options_block *p)</literal>
269       </term>
270       <listitem><para>Pointer to function which is called whenever the server
271         has stopped listening for incoming connections. This function pointer
272         has a default value of NULL in which case it isn't called.
273         When the server operates as an NT service this handler is called
274         whenever the service is stopped.
275        </para></listitem></varlistentry>
276
277      <varlistentry><term>
278        <literal>void *handle</literal></term>
279       <listitem><para>User defined pointer (default value NULL).
280         This is a per-server handle that can be used to specify "user-data".
281         Do not confuse this with the session-handle as returned by bend_init.
282        </para></listitem></varlistentry>
283
284     </variablelist>
285    </para>
286
287    <para>
288     The pointer returned by <literal>statserv_getcontrol</literal> points to
289     a static area. You are allowed to change the contents of the structure,
290     but the changes will not take effect before you call
291    </para>
292    
293    <synopsis>
294 void statserv_setcontrol(statserv_options_block *block);
295    </synopsis>
296
297    <note>
298     <para>
299      that you should generally update this structure before calling
300      <function>statserv_main()</function>.
301     </para>
302    </note>
303   </sect1>
304
305   <sect1 id="server.backendfunctions"><title>The Backend Functions</title>
306
307    <para>
308     For each service of the protocol, the backend interface declares one or
309     two functions. You are required to provide implementations of the
310     functions representing the services that you wish to implement.
311    </para>
312
313    <sect2><title>Init</title>
314
315     <synopsis>
316 bend_initresult (*bend_init)(bend_initrequest *r);
317     </synopsis>
318
319     <para>
320      This handler is called once for each new connection request, after
321      a new process/thread has been created, and an Initialize Request has
322      been received from the client. The pointer to the
323      <function>bend_init</function> handler is passed in the call to
324      <function>statserv_start</function>.
325     </para>
326     <para>
327      Unlike previous versions of YAZ, the <function>bend_init</function> also
328      serves as a handler that defines the Z39.50 services that the backend
329      wish to support. Pointers to <emphasis>all</emphasis> service handlers,
330      including search - and fetch must be specified here in this handler.
331     </para>
332     <para>
333      The request  - and result structures are defined as
334     </para>
335
336     <synopsis>
337 typedef struct bend_initrequest
338 {
339     Z_IdAuthentication *auth;
340     ODR stream;                /* encoding stream */
341     ODR print;                 /* printing stream */
342     Z_ReferenceId *referenceId;/* reference ID */
343     char *peer_name;           /* dns host of peer (client) */
344
345     char *implementation_id;
346     char *implementation_name;
347     char *implementation_version;
348     int (*bend_sort) (void *handle, bend_sort_rr *rr);
349     int (*bend_search) (void *handle, bend_search_rr *rr);
350     int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
351     int (*bend_present) (void *handle, bend_present_rr *rr);
352     int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
353     int (*bend_delete)(void *handle, bend_delete_rr *rr);
354     int (*bend_scan)(void *handle, bend_scan_rr *rr);
355     int (*bend_segment)(void *handle, bend_segment_rr *rr);
356 } bend_initrequest;
357
358 typedef struct bend_initresult
359 {
360     int errcode;       /* 0==OK */
361     char *errstring;   /* system error string or NULL */
362     void *handle;      /* private handle to the backend module */
363 } bend_initresult;
364     </synopsis>
365
366     <para>
367      In general, the server frontend expects that the
368      <literal>bend_*result</literal> pointer that you return is valid at
369      least until the next call to a <literal>bend_* function</literal>.
370      This applies to all of the functions described herein. The parameter
371      structure passed to you in the call belongs to the server frontend, and
372      you should not make assumptions about its contents after the current
373      function call has completed. In other words, if you want to retain any
374      of the contents of a request structure, you should copy them.
375     </para>
376
377     <para>
378      The <literal>errcode</literal> should be zero if the initialization of
379      the backend went well. Any other value will be interpreted as an error.
380      The <literal>errstring</literal> isn't used in the current version, but
381      one option would be to stick it in the initResponse as a VisibleString.
382      The <literal>handle</literal> is the most important parameter. It should
383      be set to some value that uniquely identifies the current session to
384      the backend implementation. It is used by the frontend server in any
385      future calls to a backend function.
386      The typical use is to set it to point to a dynamically allocated state
387      structure that is private to your backend module.
388     </para>
389
390     <para>
391      The <literal>auth</literal> member holds the authentication information
392      part of the Z39.50 Initialize Request. Interpret this if your serves
393      requires authentication. 
394     </para>
395
396     <para>
397      The members <literal>peer_name</literal>,
398      <literal>implementation_id</literal>,
399      <literal>implementation_name</literal> and
400      <literal>implementation_version</literal> holds DNS of client, ID of implementor, name
401      of client (Z39.50) implementation - and version.
402     </para>
403
404     <para>
405      The <literal>bend_</literal> - members are set to NULL when
406      <function>bend_init</function> is called. Modify the pointers by
407      setting them to point to backend functions.
408     </para>
409
410    </sect2>
411
412    <sect2><title>Search and retrieve</title>
413
414     <para>We now describe the handlers that are required to support search -
415      and retrieve. You must support two functions - one for search - and one
416      for fetch (retrieval of one record). If desirable you can provide a
417      third handler which is called when a present request is received which
418      allows you to optimize retrieval of multiple-records.
419     </para>
420
421     <synopsis>
422 int (*bend_search) (void *handle, bend_search_rr *rr);
423
424 typedef struct {
425     char *setname;             /* name to give to this set */
426     int replace_set;           /* replace set, if it already exists */
427     int num_bases;             /* number of databases in list */
428     char **basenames;          /* databases to search */
429     Z_ReferenceId *referenceId;/* reference ID */
430     Z_Query *query;            /* query structure */
431     ODR stream;                /* encode stream */
432     ODR decode;                /* decode stream */
433     ODR print;                 /* print stream */
434
435     bend_request request;
436     bend_association association;
437     int *fd;
438     int hits;                  /* number of hits */
439     int errcode;               /* 0==OK */
440     char *errstring;           /* system error string or NULL */
441 } bend_search_rr;
442
443     </synopsis>
444
445     <para>
446      The <function>bend_search</function> handler is a fairly close
447      approximation of a protocol Search Request - and Response PDUs
448      The <literal>setname</literal> is the resultSetName from the protocol.
449      You are required to establish a mapping between the set name and whatever
450      your backend database likes to use.
451      Similarly, the <literal>replace_set</literal> is a boolean value
452      corresponding to the resultSetIndicator field in the protocol.
453      <literal>num_bases/basenames</literal> is a length of/array of character
454      pointers to the database names provided by the client.
455      The <literal>query</literal> is the full query structure as defined in
456      the protocol ASN.1 specification.
457      It can be either of the possible query types, and it's up to you to
458      determine if you can handle the provided query type.
459      Rather than reproduce the C interface here, we'll refer you to the
460      structure definitions in the file
461      <filename>include/yaz/z-core.h</filename>. If you want to look at the
462      attributeSetId OID of the RPN query, you can either match it against
463      your own internal tables, or you can use the
464      <literal>oid_getentbyoid</literal> function provided by &yaz;.
465     </para>
466
467     <para>
468      The structure contains a number of hits, and an
469      <literal>errcode/errstring</literal> pair. If an error occurs
470      during the search, or if you're unhappy with the request, you should
471      set the errcode to a value from the BIB-1 diagnostic set. The value
472      will then be returned to the user in a nonsurrogate diagnostic record
473      in the response. The <literal>errstring</literal>, if provided, will
474      go in the addinfo field. Look at the protocol definition for the
475      defined error codes, and the suggested uses of the addinfo field.
476     </para>
477
478
479     <synopsis>
480 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
481
482 typedef struct bend_fetch_rr {
483     char *setname;             /* set name */
484     int number;                /* record number */
485     Z_ReferenceId *referenceId;/* reference ID */
486     oid_value request_format;  /* One of the CLASS_RECSYN members */
487     int *request_format_raw;   /* same as above (raw OID) */
488     Z_RecordComposition *comp; /* Formatting instructions */
489     ODR stream;                /* encoding stream - memory source if req */
490     ODR print;                 /* printing stream */
491
492     char *basename;            /* name of database that provided record */
493     int len;                   /* length of record or -1 if structured */
494     char *record;              /* record */
495     int last_in_set;           /* is it?  */
496     oid_value output_format;   /* format */
497     int *output_format_raw;    /* used instead of above if not-null */
498     int errcode;               /* 0==success */
499     char *errstring;           /* system error string or NULL */
500     int surrogate_flag;        /* surrogate diagnostic */
501 } bend_fetch_rr;
502     </synopsis>
503
504     <para>
505      The frontend server calls the <function>bend_fetch</function> handler
506      when it needs database records to fulfill a Search Request or a Present
507      Request.
508      The <literal>setname</literal> is simply the name of the result set
509      that holds the reference to the desired record.
510      The <literal>number</literal> is the offset into the set (with 1
511      being the first record in the set). The <literal>format</literal> field
512      is the record format requested by the client (See section
513      <link linkend="oid">Object Identifiers</link>). The value
514      <literal>VAL_NONE</literal> indicates that the client did not
515      request a specific format. The <literal>stream</literal> argument
516      is an &odr; stream which should be used for
517      allocating space for structured data records.
518      The stream will be reset when all records have been assembled, and
519      the response package has been transmitted.
520      For unstructured data, the backend is responsible for maintaining a
521      static or dynamic buffer for the record between calls.
522     </para>
523
524     <para>
525      In the structure, the <literal>basename</literal> is the name of the
526      database that holds the
527      record. <literal>len</literal> is the length of the record returned, in
528      bytes, and <literal>record</literal> is a pointer to the record.
529      <literal>Last_in_set</literal> should be nonzero only if the record
530      returned is the last one in the given result set.
531      <literal>errcode</literal> and <literal>errstring</literal>, if
532      given, will be interpreted as a global error pertaining to the
533      set, and will be returned in a non-surrogate-diagnostic.
534      If you wish to return the error as a surrogate-diagnostic
535      (local error) you can do this by setting
536      <literal>surrogate_flag</literal> to 1 also.
537     </para>
538
539     <para>
540      If the <literal>len</literal> field has the value -1, then
541      <literal>record</literal> is assumed to point to a constructed data
542      type. The <literal>format</literal> field will be used to determine
543      which encoder should be used to serialize the data.
544     </para>
545
546     <note>
547      <para>
548       If your backend generates structured records, it should use
549       <function>odr_malloc()</function> on the provided stream for allocating
550       data: This allows the frontend server to keep track of the record sizes.
551      </para>
552     </note>
553
554     <para>
555      The <literal>format</literal> field is mapped to an object identifier
556      in the direct reference of the resulting EXTERNAL representation
557      of the record.
558     </para>
559
560     <note>
561      <para>
562       The current version of &yaz; only supports the direct reference mode.
563      </para>
564     </note>
565
566     <synopsis>
567 int (*bend_present) (void *handle, bend_present_rr *rr);
568
569 typedef struct {
570     char *setname;             /* set name */
571     int start;
572     int number;                /* record number */
573     oid_value format;          /* One of the CLASS_RECSYN members */
574     Z_ReferenceId *referenceId;/* reference ID */
575     Z_RecordComposition *comp; /* Formatting instructions */
576     ODR stream;                /* encoding stream */
577     ODR print;                 /* printing stream */
578     bend_request request;
579     bend_association association;
580
581     int hits;                  /* number of hits */
582     int errcode;               /* 0==OK */
583     char *errstring;           /* system error string or NULL */
584 } bend_present_rr;
585     </synopsis>
586
587     <para>
588      The <function>bend_present</function> handler is called when
589      the server receives a Present Request. The <literal>setname</literal>,
590      <literal>start</literal> and <literal>number</literal> is the
591      name of the result set - start position - and number of records to
592      be retrieved respectively. <literal>format</literal> and
593      <literal>comp</literal> is the preferred transfer syntax and element
594      specifications of the present request.
595     </para>
596     <para>
597      Note that this is handler serves as a supplement for
598      <function>bend_fetch</function> and need not to be defined in order to
599      support search - and retrieve. 
600     </para>
601
602    </sect2>
603
604    <sect2><title>Delete</title>
605
606     <para>
607      For back-ends that supports delete of a result set only one handler
608      must be defined.
609     </para>
610
611     <synopsis>
612 int (*bend_delete)(void *handle, bend_delete_rr *rr);
613
614 typedef struct bend_delete_rr {
615     int function;
616     int num_setnames;
617     char **setnames;
618     Z_ReferenceId *referenceId;
619     int delete_status;      /* status for the whole operation */
620     int *statuses;          /* status each set - indexed as setnames */
621     ODR stream;
622     ODR print; 
623 } bend_delete_rr;
624     </synopsis>
625
626     <note>
627      <para>
628       The delete set function definition is rather primitive, mostly because
629       we have had no practical need for it as of yet. If someone wants
630       to provide a full delete service, we'd be happy to add the
631       extra parameters that are required. Are there clients out there
632       that will actually delete sets they no longer need?
633      </para>
634     </note>
635
636    </sect2>
637
638    <sect2><title>scan</title>
639
640     <para>
641      For servers that wish to offer the scan service one handler
642      must be defined.
643     </para>
644
645     <synopsis>
646 int (*bend_delete)(void *handle, bend_delete_rr *rr);
647
648 typedef enum {
649     BEND_SCAN_SUCCESS,  /* ok */
650     BEND_SCAN_PARTIAL   /* not all entries could be found */
651 } bend_scan_status;
652
653 typedef struct bend_scan_rr {
654     int num_bases;      /* number of elements in databaselist */
655     char **basenames;   /* databases to search */
656     oid_value attributeset;
657     Z_ReferenceId *referenceId; /* reference ID */
658     Z_AttributesPlusTerm *term;
659     ODR stream;         /* encoding stream - memory source if required */
660     ODR print;          /* printing stream */
661
662     int *step_size;     /* step size */
663     int term_position;  /* desired index of term in result list/returned */
664     int num_entries;    /* number of entries requested/returned */
665
666     struct scan_entry *entries;
667     bend_scan_status status;
668     int errcode;
669     char *errstring;
670 } bend_scan_rr;
671     </synopsis>
672    </sect2>
673   </sect1>
674
675   <sect1 id="server.invocation"><title>Application Invocation</title>
676
677    <para>
678     The finished application has the following
679     invocation syntax (by way of <function>statserv_main()</function>):
680    </para>
681
682    <synopsis>
683     <replaceable>appname</replaceable> &lsqb;-szSiTu -a <replaceable>apdufile</replaceable> -l <replaceable>logfile</replaceable> -v <replaceable>loglevel</replaceable> -c <replaceable>config</replaceable>&rsqb;
684     &lsqb;listener ...&rsqb;
685    </synopsis>
686
687    <para>
688     The options are
689
690     <variablelist>
691
692      <varlistentry><term><literal>-a </literal>
693        <replaceable>file</replaceable></term>
694       <listitem><para>
695         Specify a file for dumping PDUs (for diagnostic purposes).
696         The special name &quot;-&quot; sends output to
697         <literal>stderr</literal>.
698        </para></listitem></varlistentry>
699
700      <varlistentry><term><literal>-S</literal></term>
701       <listitem><para>
702         Don't fork or make threads on connection requests. This is good for
703         debugging, but not recommended for real operation: Although the
704         server is asynchronous and non-blocking, it can be nice to keep
705         a software malfunction (okay then, a crash) from affecting all
706         current users.
707        </para></listitem></varlistentry>
708
709      <varlistentry><term><literal>-T</literal></term>
710       <listitem><para>
711         Operate the server in threaded mode. The server creates a thread
712         for each connection rather than a fork a process. Only available
713         on UNIX systems that offers POSIX threads.
714        </para></listitem></varlistentry>
715
716      <varlistentry><term><literal>-s</literal></term>
717       <listitem><para>
718         Use the SR protocol (obsolete).
719        </para></listitem></varlistentry>
720
721      <varlistentry><term><literal>-z</literal></term>
722       <listitem><para>
723         Use the Z39.50 protocol (default). These two options complement
724         each other. You can use both multiple times on the same command
725         line, between listener-specifications (see below). This way, you
726         can set up the server to listen for connections in both protocols
727         concurrently, on different local ports.
728        </para></listitem></varlistentry>
729
730      <varlistentry><term><literal>-l </literal>
731        <replaceable>file</replaceable></term>
732       <listitem><para>The logfile.
733        </para></listitem></varlistentry>
734
735      <varlistentry><term><literal>-c </literal>
736        <replaceable>config</replaceable></term>
737       <listitem><para>A user option that serves as a specifier for some
738         sort of configuration, e.g. a filename.
739         The argument to this option is transferred to member
740         <literal>configname</literal>of the
741         <literal>statserv_options_block</literal>.
742        </para></listitem></varlistentry>
743
744      <varlistentry><term><literal>-v </literal>
745        <replaceable>level</replaceable></term>
746       <listitem><para>
747         The log level. Use a comma-separated list of members of the set
748         {fatal,debug,warn,log,all,none}.
749        </para></listitem></varlistentry>
750
751      <varlistentry><term><literal>-u </literal>
752        <replaceable>userid</replaceable></term>
753       <listitem><para>
754         Set user ID. Sets the real UID of the server process to that of the
755         given user. It's useful if you aren't comfortable with having the
756         server run as root, but you need to start it as such to bind a
757         privileged port.
758        </para></listitem></varlistentry>
759
760      <varlistentry><term><literal>-w </literal>
761        <replaceable>dir</replaceable></term>
762       <listitem><para>
763         Working directory.
764        </para></listitem></varlistentry>
765
766      <varlistentry><term><literal>-i</literal></term>
767       <listitem><para>
768         Use this to make the the server run from the
769         <application>inetd</application> server (UNIX only).
770        </para></listitem></varlistentry>
771      
772      <varlistentry><term><literal>-install</literal></term>
773       <listitem><para>
774         Use this to install the server as an NT service (Windows 2000/NT only). 
775         Control the server by going to the Services in the Control Panel.
776        </para></listitem></varlistentry>
777      
778      <varlistentry><term><literal>-remove</literal></term>
779       <listitem><para>
780         Use this to remove the server from the NT services (Windows 2000/NT only). 
781        </para></listitem></varlistentry>
782
783      <varlistentry><term><literal>-t </literal>
784        <replaceable>minutes</replaceable></term>
785       <listitem><para>
786         Idle session timeout, in minutes.
787        </para></listitem></varlistentry>
788
789      <varlistentry><term><literal>-k </literal>
790       <replaceable>size</replaceable></term>
791       <listitem><para>
792         Maximum record size/message size, in kilobytes.
793        </para></listitem></varlistentry>
794
795     </variablelist>
796    </para>
797
798    <para>
799     A listener specification consists of a transport mode followed by a
800     colon (:) followed by a listener address. The transport mode is
801     either <literal>tcp</literal> or <literal>ssl</literal>.
802    </para>
803
804    <para>
805     For TCP and SSL, an address has the form
806    </para>
807
808    <synopsis>
809     hostname | IP-number &lsqb;: portnumber&rsqb;
810    </synopsis>
811
812    <para>
813     The port number defaults to 210 (standard Z39.50 port).
814    </para>
815
816    <para>
817     Examples
818    </para>
819
820    <screen>
821     tcp:dranet.dra.com
822
823     ssl:ssl.enterprise.com:3000
824    </screen>
825
826    <para>
827     In both cases, the special hostname &quot;@&quot; is mapped to
828     the address <literal>INADDR_ANY</literal>, which causes the
829     server to listen on any local interface. 
830    </para>
831
832   </sect1>
833  </chapter>
834
835  <!-- Keep this comment at the end of the file
836  Local variables:
837  mode: sgml
838  sgml-omittag:t
839  sgml-shorttag:t
840  sgml-minimize-attributes:nil
841  sgml-always-quote-attributes:t
842  sgml-indent-step:1
843  sgml-indent-data:t
844  sgml-parent-document: "yaz.xml"
845  sgml-local-catalogs: nil
846  sgml-namecase-general:t
847  End:
848  -->