Indentation. Variable sgml-local-catalogs set to nil.
[yaz-moved-to-github.git] / doc / frontend.xml
1 <!-- $Id: frontend.xml,v 1.8 2001-10-26 20:13:44 adam 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_SR</literal> or
221         <literal>PROTO_Z3950</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_name;
346     char *implementation_version;
347     int (*bend_sort) (void *handle, bend_sort_rr *rr);
348     int (*bend_search) (void *handle, bend_search_rr *rr);
349     int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
350     int (*bend_present) (void *handle, bend_present_rr *rr);
351     int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
352     int (*bend_delete)(void *handle, bend_delete_rr *rr);
353     int (*bend_scan)(void *handle, bend_scan_rr *rr);
354     int (*bend_segment)(void *handle, bend_segment_rr *rr);
355 } bend_initrequest;
356
357 typedef struct bend_initresult
358 {
359     int errcode;       /* 0==OK */
360     char *errstring;   /* system error string or NULL */
361     void *handle;      /* private handle to the backend module */
362 } bend_initresult;
363     </synopsis>
364
365     <para>
366      In general, the server frontend expects that the
367      <literal>bend_*result</literal> pointer that you return is valid at
368      least until the next call to a <literal>bend_* function</literal>.
369      This applies to all of the functions described herein. The parameter
370      structure passed to you in the call belongs to the server frontend, and
371      you should not make assumptions about its contents after the current
372      function call has completed. In other words, if you want to retain any
373      of the contents of a request structure, you should copy them.
374     </para>
375
376     <para>
377      The <literal>errcode</literal> should be zero if the initialization of
378      the backend went well. Any other value will be interpreted as an error.
379      The <literal>errstring</literal> isn't used in the current version, but
380      one option would be to stick it in the initResponse as a VisibleString.
381      The <literal>handle</literal> is the most important parameter. It should
382      be set to some value that uniquely identifies the current session to
383      the backend implementation. It is used by the frontend server in any
384      future calls to a backend function.
385      The typical use is to set it to point to a dynamically allocated state
386      structure that is private to your backend module.
387     </para>
388
389     <para>
390      The <literal>auth</literal> member holds the authentication information
391      part of the Z39.50 Initialize Request. Interpret this if your serves
392      requires authentication. 
393     </para>
394
395     <para>
396      The members <literal>peer_name</literal>,
397      <literal>implementation_name</literal> and
398      <literal>implementation_version</literal> holds DNS of client, name
399      of client (Z39.50) implementation - and version.
400     </para>
401
402     <para>
403      The <literal>bend_</literal> - members are set to NULL when
404      <function>bend_init</function> is called. Modify the pointers by
405      setting them to point to backend functions.
406     </para>
407
408    </sect2>
409
410    <sect2><title>Search and retrieve</title>
411
412     <para>We now describe the handlers that are required to support search -
413      and retrieve. You must support two functions - one for search - and one
414      for fetch (retrieval of one record). If desirable you can provide a
415      third handler which is called when a present request is received which
416      allows you to optimize retrieval of multiple-records.
417     </para>
418
419     <synopsis>
420 int (*bend_search) (void *handle, bend_search_rr *rr);
421
422 typedef struct {
423     char *setname;             /* name to give to this set */
424     int replace_set;           /* replace set, if it already exists */
425     int num_bases;             /* number of databases in list */
426     char **basenames;          /* databases to search */
427     Z_ReferenceId *referenceId;/* reference ID */
428     Z_Query *query;            /* query structure */
429     ODR stream;                /* encode stream */
430     ODR decode;                /* decode stream */
431     ODR print;                 /* print stream */
432
433     bend_request request;
434     bend_association association;
435     int *fd;
436     int hits;                  /* number of hits */
437     int errcode;               /* 0==OK */
438     char *errstring;           /* system error string or NULL */
439 } bend_search_rr;
440
441     </synopsis>
442
443     <para>
444      The <function>bend_search</function> handler is a fairly close
445      approximation of a protocol Search Request - and Response PDUs
446      The <literal>setname</literal> is the resultSetName from the protocol.
447      You are required to establish a mapping between the set name and whatever
448      your backend database likes to use.
449      Similarly, the <literal>replace_set</literal> is a boolean value
450      corresponding to the resultSetIndicator field in the protocol.
451      <literal>num_bases/basenames</literal> is a length of/array of character
452      pointers to the database names provided by the client.
453      The <literal>query</literal> is the full query structure as defined in
454      the protocol ASN.1 specification.
455      It can be either of the possible query types, and it's up to you to
456      determine if you can handle the provided query type.
457      Rather than reproduce the C interface here, we'll refer you to the
458      structure definitions in the file
459      <filename>include/yaz/z-core.h</filename>. If you want to look at the
460      attributeSetId OID of the RPN query, you can either match it against
461      your own internal tables, or you can use the
462      <literal>oid_getentbyoid</literal> function provided by &yaz;.
463     </para>
464
465     <para>
466      The structure contains a number of hits, and an
467      <literal>errcode/errstring</literal> pair. If an error occurs
468      during the search, or if you're unhappy with the request, you should
469      set the errcode to a value from the BIB-1 diagnostic set. The value
470      will then be returned to the user in a nonsurrogate diagnostic record
471      in the response. The <literal>errstring</literal>, if provided, will
472      go in the addinfo field. Look at the protocol definition for the
473      defined error codes, and the suggested uses of the addinfo field.
474     </para>
475
476
477     <synopsis>
478 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
479
480 typedef struct bend_fetch_rr {
481     char *setname;             /* set name */
482     int number;                /* record number */
483     Z_ReferenceId *referenceId;/* reference ID */
484     oid_value request_format;  /* One of the CLASS_RECSYN members */
485     int *request_format_raw;   /* same as above (raw OID) */
486     Z_RecordComposition *comp; /* Formatting instructions */
487     ODR stream;                /* encoding stream - memory source if req */
488     ODR print;                 /* printing stream */
489
490     char *basename;            /* name of database that provided record */
491     int len;                   /* length of record or -1 if structured */
492     char *record;              /* record */
493     int last_in_set;           /* is it?  */
494     oid_value output_format;   /* format */
495     int *output_format_raw;    /* used instead of above if not-null */
496     int errcode;               /* 0==success */
497     char *errstring;           /* system error string or NULL */
498     int surrogate_flag;        /* surrogate diagnostic */
499 } bend_fetch_rr;
500     </synopsis>
501
502     <para>
503      The frontend server calls the <function>bend_fetch</function> handler
504      when it needs database records to fulfill a Search Request or a Present
505      Request.
506      The <literal>setname</literal> is simply the name of the result set
507      that holds the reference to the desired record.
508      The <literal>number</literal> is the offset into the set (with 1
509      being the first record in the set). The <literal>format</literal> field
510      is the record format requested by the client (See section
511      <link linkend="oid">Object Identifiers</link>). The value
512      <literal>VAL_NONE</literal> indicates that the client did not
513      request a specific format. The <literal>stream</literal> argument
514      is an &odr; stream which should be used for
515      allocating space for structured data records.
516      The stream will be reset when all records have been assembled, and
517      the response package has been transmitted.
518      For unstructured data, the backend is responsible for maintaining a
519      static or dynamic buffer for the record between calls.
520     </para>
521
522     <para>
523      In the structure, the <literal>basename</literal> is the name of the
524      database that holds the
525      record. <literal>len</literal> is the length of the record returned, in
526      bytes, and <literal>record</literal> is a pointer to the record.
527      <literal>Last_in_set</literal> should be nonzero only if the record
528      returned is the last one in the given result set.
529      <literal>errcode</literal> and <literal>errstring</literal>, if
530      given, will be interpreted as a global error pertaining to the
531      set, and will be returned in a non-surrogate-diagnostic.
532      If you wish to return the error as a surrogate-diagnostic
533      (local error) you can do this by setting
534      <literal>surrogate_flag</literal> to 1 also.
535     </para>
536
537     <para>
538      If the <literal>len</literal> field has the value -1, then
539      <literal>record</literal> is assumed to point to a constructed data
540      type. The <literal>format</literal> field will be used to determine
541      which encoder should be used to serialize the data.
542     </para>
543
544     <note>
545      <para>
546       If your backend generates structured records, it should use
547       <function>odr_malloc()</function> on the provided stream for allocating
548       data: This allows the frontend server to keep track of the record sizes.
549      </para>
550     </note>
551
552     <para>
553      The <literal>format</literal> field is mapped to an object identifier
554      in the direct reference of the resulting EXTERNAL representation
555      of the record.
556     </para>
557
558     <note>
559      <para>
560       The current version of &yaz; only supports the direct reference mode.
561      </para>
562     </note>
563
564     <synopsis>
565 int (*bend_present) (void *handle, bend_present_rr *rr);
566
567 typedef struct {
568     char *setname;             /* set name */
569     int start;
570     int number;                /* record number */
571     oid_value format;          /* One of the CLASS_RECSYN members */
572     Z_ReferenceId *referenceId;/* reference ID */
573     Z_RecordComposition *comp; /* Formatting instructions */
574     ODR stream;                /* encoding stream */
575     ODR print;                 /* printing stream */
576     bend_request request;
577     bend_association association;
578
579     int hits;                  /* number of hits */
580     int errcode;               /* 0==OK */
581     char *errstring;           /* system error string or NULL */
582 } bend_present_rr;
583     </synopsis>
584
585     <para>
586      The <function>bend_present</function> handler is called when
587      the server receives a Present Request. The <literal>setname</literal>,
588      <literal>start</literal> and <literal>number</literal> is the
589      name of the result set - start position - and number of records to
590      be retrieved respectively. <literal>format</literal> and
591      <literal>comp</literal> is the preferred transfer syntax and element
592      specifications of the present request.
593     </para>
594     <para>
595      Note that this is handler serves as a supplement for
596      <function>bend_fetch</function> and need not to be defined in order to
597      support search - and retrieve. 
598     </para>
599
600    </sect2>
601
602    <sect2><title>Delete</title>
603
604     <para>
605      For back-ends that supports delete of a result set only one handler
606      must be defined.
607     </para>
608
609     <synopsis>
610 int (*bend_delete)(void *handle, bend_delete_rr *rr);
611
612 typedef struct bend_delete_rr {
613     int function;
614     int num_setnames;
615     char **setnames;
616     Z_ReferenceId *referenceId;
617     int delete_status;      /* status for the whole operation */
618     int *statuses;          /* status each set - indexed as setnames */
619     ODR stream;
620     ODR print; 
621 } bend_delete_rr;
622     </synopsis>
623
624     <note>
625      <para>
626       The delete set function definition is rather primitive, mostly because
627       we have had no practical need for it as of yet. If someone wants
628       to provide a full delete service, we'd be happy to add the
629       extra parameters that are required. Are there clients out there
630       that will actually delete sets they no longer need?
631      </para>
632     </note>
633
634    </sect2>
635
636    <sect2><title>scan</title>
637
638     <para>
639      For servers that wish to offer the scan service one handler
640      must be defined.
641     </para>
642
643     <synopsis>
644 int (*bend_delete)(void *handle, bend_delete_rr *rr);
645
646 typedef enum {
647     BEND_SCAN_SUCCESS,  /* ok */
648     BEND_SCAN_PARTIAL   /* not all entries could be found */
649 } bend_scan_status;
650
651 typedef struct bend_scan_rr {
652     int num_bases;      /* number of elements in databaselist */
653     char **basenames;   /* databases to search */
654     oid_value attributeset;
655     Z_ReferenceId *referenceId; /* reference ID */
656     Z_AttributesPlusTerm *term;
657     ODR stream;         /* encoding stream - memory source if required */
658     ODR print;          /* printing stream */
659
660     int *step_size;     /* step size */
661     int term_position;  /* desired index of term in result list/returned */
662     int num_entries;    /* number of entries requested/returned */
663
664     struct scan_entry *entries;
665     bend_scan_status status;
666     int errcode;
667     char *errstring;
668 } bend_scan_rr;
669     </synopsis>
670    </sect2>
671   </sect1>
672
673   <sect1 id="server.invocation"><title>Application Invocation</title>
674
675    <para>
676     The finished application has the following
677     invocation syntax (by way of <function>statserv_main()</function>):
678    </para>
679
680    <synopsis>
681     <replaceable>appname</replaceable> &lsqb;-szSiTu -a <replaceable>apdufile</replaceable> -l <replaceable>logfile</replaceable> -v <replaceable>loglevel</replaceable> -c <replaceable>config</replaceable>&rsqb;
682     &lsqb;listener ...&rsqb;
683    </synopsis>
684
685    <para>
686     The options are
687
688     <variablelist>
689
690      <varlistentry><term>-a <replaceable>file</replaceable></term>
691       <listitem><para>
692         Specify a file for dumping PDUs (for diagnostic purposes).
693         The special name &quot;-&quot; sends output to
694         <literal>stderr</literal>.
695        </para></listitem></varlistentry>
696
697      <varlistentry><term>-S</term>
698       <listitem><para>
699         Don't fork or make threads on connection requests. This is good for
700         debugging, but not recommended for real operation: Although the
701         server is asynchronous and non-blocking, it can be nice to keep
702         a software malfunction (okay then, a crash) from affecting all
703         current users.
704        </para></listitem></varlistentry>
705
706      <varlistentry><term>-T</term>
707       <listitem><para>
708         Operate the server in threaded mode. The server creates a thread
709         for each connection rather than a fork a process. Only available
710         on UNIX systems that offers POSIX threads.
711        </para></listitem></varlistentry>
712
713      <varlistentry><term>-s</term>
714       <listitem><para>
715         Use the SR protocol (obsolete).
716        </para></listitem></varlistentry>
717
718      <varlistentry><term>-z</term>
719       <listitem><para>
720         Use the Z39.50 protocol (default). These two options complement
721         each other. You can use both multiple times on the same command
722         line, between listener-specifications (see below). This way, you
723         can set up the server to listen for connections in both protocols
724         concurrently, on different local ports.
725        </para></listitem></varlistentry>
726
727      <varlistentry><term>-l <replaceable>file</replaceable></term>
728       <listitem><para>The logfile.
729        </para></listitem></varlistentry>
730
731      <varlistentry><term>-c <replaceable>config</replaceable></term>
732       <listitem><para>A user option that serves as a specifier for some
733         sort of configuration, e.g. a filename.
734         The argument to this option is transferred to member
735         <literal>configname</literal>of the
736         <literal>statserv_options_block</literal>.
737        </para></listitem></varlistentry>
738
739      <varlistentry><term>-v <replaceable>level</replaceable></term>
740       <listitem><para>
741         The log level. Use a comma-separated list of members of the set
742         {fatal,debug,warn,log,all,none}.
743        </para></listitem></varlistentry>
744
745      <varlistentry><term>-u <replaceable>userid</replaceable></term>
746       <listitem><para>
747         Set user ID. Sets the real UID of the server process to that of the
748         given user. It's useful if you aren't comfortable with having the
749         server run as root, but you need to start it as such to bind a
750         privileged port.
751        </para></listitem></varlistentry>
752
753      <varlistentry><term>-w <replaceable>dir</replaceable></term>
754       <listitem><para>
755         Working directory.
756        </para></listitem></varlistentry>
757
758      <varlistentry><term>-i</term>
759       <listitem><para>
760         Use this when running from the <application>inetd</application> server.
761        </para></listitem></varlistentry>
762
763      <varlistentry><term>-t <replaceable>minutes</replaceable></term>
764       <listitem><para>
765         Idle session timeout, in minutes.
766        </para></listitem></varlistentry>
767
768      <varlistentry><term>-k <replaceable>size</replaceable></term>
769       <listitem><para>
770         Maximum record size/message size, in kilobytes.
771        </para></listitem></varlistentry>
772
773     </variablelist>
774    </para>
775
776    <para>
777     A listener specification consists of a transport mode followed by a
778     colon (:) followed by a listener address. The transport mode is
779     either <literal>osi</literal> or <literal>tcp</literal>.
780    </para>
781
782    <para>
783     For TCP, an address has the form
784    </para>
785
786    <synopsis>
787     hostname | IP-number &lsqb;: portnumber&rsqb;
788    </synopsis>
789
790    <para>
791     The port number defaults to 210 (standard Z39.50 port).
792    </para>
793
794    <para>
795     For osi, the address form is
796    </para>
797
798    <synopsis>
799     &lsqb;t-selector /&rsqb; hostname | IP-number &lsqb;: portnumber&rsqb;
800    </synopsis>
801
802    <para>
803     The transport selector is given as a string of hex digits (with an even
804     number of digits). The default port number is 102 (RFC1006 port).
805    </para>
806
807    <para>
808     Examples
809    </para>
810
811    <screen>
812     tcp:dranet.dra.com
813
814     osi:0402/dbserver.osiworld.com:3000
815    </screen>
816
817    <para>
818     In both cases, the special hostname &quot;@&quot; is mapped to
819     the address INADDR_ANY, which causes the server to listen on any local
820     interface. To start the server listening on the registered ports for
821     Z39.50 and SR over OSI/RFC1006, and to drop root privileges once the
822     ports are bound, execute the server like this (from a root shell):
823    </para>
824
825    <screen>
826     my-server -u daemon tcp:@ -s osi:@
827    </screen>
828
829    <para>
830     You can replace <literal>daemon</literal> with another user, eg. your
831     own account, or a dedicated IR server account.
832     <literal>my-server</literal> should be the name of your
833     server application. You can test the procedure with the
834     <application>yaz-ztest</application> application.
835    </para>
836
837   </sect1>
838  </chapter>
839
840  <!-- Keep this comment at the end of the file
841  Local variables:
842  mode: sgml
843  sgml-omittag:t
844  sgml-shorttag:t
845  sgml-minimize-attributes:nil
846  sgml-always-quote-attributes:t
847  sgml-indent-step:1
848  sgml-indent-data:t
849  sgml-parent-document: "yaz.xml"
850  sgml-local-catalogs: nil
851  sgml-namecase-general:t
852  End:
853  -->