libserver(8)            FreeBSD System Manager's Manual           libserver(8)

NAME
     libserver -- Multi-process TCP/UNIX Server-in-a-Library

SYNOPSIS
     #include<server.h>
     -I/usr/local/include -L/usr/local/lib -lserver

DESCRIPTION
     libserver implements a generic multi-process TCP or UNIX-domain server
     which is incapable of servicing connections on its own.  The programmer
     writes initialization functions, and a function to service connections,
     then compiles and links his or her code against the library to create a
     complete multi-process server.

USAGE
     An example echo server is included in the libserver distribution, named
     echo.c.  It is built automatically when libserver.so is built, but not
     installed by the Makefile.

     The programmer must not define any global symbol beginning with the five
     characters 'serv_', other than the names of the three programmer supplied
     functions, because the library reserves that namespace for its own use.

     The prototypes for the three functions the programmer must supply are
     declared in server.h.  You must define the functions to match the proto-
     types:

     void serv_init_func();
     void serv_child_init_func();
     void serv_service_connection();

     Libserver uses a multi-process model.  One master process forks and kills
     child processes, as needed, according to demand, once per second.  The
     child processes accept and service client connections.  The master
     process does not.

     In serv_init_func(), or in functions which it calls, the programmer must
     perform the initialization tasks his or her server needs to do, once at
     server start-up, before any child processes are forked.  serv_init_func()
     is called precisely once by libserver before the server attempts to
     change user and group to "nobody" or to the values specified by the -u
     and/or -g command-line options.  Therefore, if the server starts as root,
     serv_init_func() will execute as root.  serv_init_func() is executed
     before the server becomes a daemon, which means the standard streams will
     still be connected to the terminal it was started from, and error and
     informative messages may be sent there.  serv_init_func() is called
     before any of the command-line options are processed, except for the -f
     option.  Therefore, if the server has been started with the -r option,
     the server will not yet have set the current working directory when
     serv_init_func() is executed.

     In serv_child_init_func(), or in functions which it calls, the programmer
     may perform any other initialization tasks each child process needs to
     perform independently of its parent before it can begin servicing connec-
     tions.  For example, one may open unique database connections for each
     server child in serv_child_init_func().  serv_child_init_func() is called
     every time a new server child process is forked(), in the child process.
     serv_child_init_func() is executed after the server has changed user and
     group to "nobody" or to the values specified by the -u and/or -g command-
     line options.  When serv_child_init_func() is executed the standard
     streams will be connected to /dev/null.  Therefore errors must be
     reported using syslog(3).  When serv_child_init_func() is executed, the
     -r command-line option will have been processed to change the current
     working directory.

     Libserver recognizes several command-line options to configure itself,
     but does not allow user code direct access to the command line arguments.
     Instead, it recognizes an -f option, and assigns the value of this option
     to the global character pointer serv_config_file.  The code in
     serv_init_func() and/or serv_child_init_func() may then access the speci-
     fied configuration file.  Libserver does nothing with the value of
     serv_config_file.  If the -f option was not present on the command line,
     this variable will be NULL.

     If the programmer has shut-down tasks to perform when the master or child
     processes exit, he or she can register functions via atexit(3) in either
     serv_init_func() or serv_child_init_func().  Functions registered in
     serv_init_func() will be called by the master and all child processes
     when they exit.  Functions registered in serv_child_init_func() will only
     be called by the registering process when it exits.  If the programmer
     needs to perform a shut-down task only in the master process, then he or
     she is advised to use a global int to indicate whether a process is the
     master or a child.

     In scgi_init_func(), the programmer may install a function to be called
     periodically by the master process to perform maintenance tasks with:

     void serv_periodic( void (*)(), int );

     The function pointed to by first argument will be called periodically by
     the master process, the period being specified in seconds by the second
     argument.  This function may only be called from scgi_int_func() or from
     functions which that function calls.  Calling serv_periodic() from any
     other place in your code will have no effect, because only
     scgi_init_func() is invoked in the master process.  Setting the interval
     to a value <= 0, or setting the function to NULL, disables the periodic
     function.  Note that the server will be running as the user and group
     defined by the -u and -g options when the periodic function is invoked.

     One libserver library function which should be called from inside
     serv_init_func() to set the server's name:

     void serv_set_name( char * );

     If not set, or set to NULL, the server's name defaults to "server".  The
     server's name is used in two ways:

     o   When the server is running, stderr is connected to /dev/null.
         Errors, therefore, must be reported using syslog(3).  The library
         calls openlog() with the server's name as argument, to ensure log
         entries are identified by the server's name.

     o   The server's pidfile will be written to /var/run/, if the server is
         started as root.  The filename will be the server's name with ".pid"
         appended to it.  This file can be used by /usr/local/etc/rc.d/
         scripts to stop the server.  A sample script is included in the lib-
         server distribution.

     The third programmer-supplied function, serv_service_connection() is
     called once for every connection accepted by the server.  The programmer
     may use the buffered IO functions to communicate with the client via
     stdin and stdout.  If the programmer wishes to communicate with the non-
     buffered UNIX IO functions, he or she must use the fileno() function to
     determine the descriptors associated with stdout and stdin.  They will
     never be 0 or 1.  serv_request_handler() should return only when the
     server has finished servicing the current connection.

     Please examine the echo.c source for the example echo server.  It demon-
     strates the use of libserver concisely.

CONFIGURATION
     A server linked against libserver writes its pidfile into /var/run/, if
     it can (ie., it is started as root), and may be stopped with a SIGTERM.
     A sample rc.d script is provided in the libserver distribution.  To use
     the script, all occurrences of "server" must be replaced with the value
     you passed to serv_set_name(), and the script installed in
     /usr/local/etc/rc.d, renamed as the value you passed to serv_set_name().

     Two variables must be added to /etc/rc.conf.  For example (substituting
     "server" for your server's name):

     server_enable="YES"
     server_flags="-u www -g www -r /usr/local/server"

     If the "enable" variable is set to "YES", the server will be started at
     system start.  The following rc commands will be available:

     /usr/local/etc/rc.d/server start
     /usr/local/etc/rc.d/server stop
     /usr/local/etc/rc.d/server restart
     /usr/local/etc/rc.d/server status

     If you do not want the server started on system start, then set

     server_enable="NO"

     and use the following commands:

     /usr/local/etc/rc.d/server forcestart
     /usr/local/etc/rc.d/server forcestop
     /usr/local/etc/rc.d/server forcerestart
     /usr/local/etc/rc.d/server forcestatus

   COMMAND-LINE OPTIONS
     The following command-line options are recognized by libserver servers.
     All of these are optional.

     -r  The -r option specifies the server root directory, which libserver
         will make its current working directory.

     -l  By default, libserver listens on all TCP interfaces it can find capa-
         ble of IPv4 or IPv6.  The -l option instructs the library to listen
         on a UNIX-domain socket instead.  The path to the socket must be
         specified as this option's argument.  The server will create the
         socket when it starts, unlinking it first, if it already exists in
         the filesystem.  The owner and group of the socket will be changed to
         the values of the -u and -g options, or their defaults.  The permiss-
         sions of the socket will be set to srwxrwx---.  If this option is
         present on the command-line, then the -p and -i options may not be
         present.  The server will refuse to run if they are.

     -p  The -p option specifies the port to listen on.  This defaults to 1966
         if not specified.  Note that to bind to a port lower than 1024, the
         server must be started as root.

     -i  By default, libserver accepts connections on all interfaces it can
         find capable of IPv4 or IPv6.  The -i option, when present, overrides
         this behavior, by limiting libserver to accepting connections from a
         specified interface only.  The option accepts the IP address of the
         desired interface as an argument.  The address must be expressed in
         the presentation format for either IPv4 or IPv6.

     -m

     -n  libserver uses a multi-process model, with one master process forking
         or killing slave processes in response to client activity.  Only the
         slave processes service client requests.  The -n options specifies
         the number of idle slaves the master will attempt to keep ready at
         all times.  The -m option specifies the maximum number of slaves
         which may be running at any time.  The value specified must be equal
         to or greater than the value specified for -n.  The default value for
         -n is 3 and the default value for -m is 25.

     -u

     -g  The -u and the -g options may be used to specify the user and group
         for the server to change to after it has bound to the listening
         socket.  If not specified, both values default to "nobody".  Note
         that in order for a libserver server to change user the server must
         be started as root.  If not started as root, two error messages will
         be syslog()ed at start-up, complaining about the inability of the
         server to change user and group.  You can suppress them by providing
         values to -u and -g to override the default "nobody" with the actual
         user and group under which the server runs.

     -x  The -x option, if present, prevents libserver from becoming a daemon.
         It will then run in the foreground of the terminal where it was
         started, and may be stopped with signals (ie., Control-C).  Stderr
         will be connected to the terminal, so diagnostic output may be sent
         there when this option is present on the command-line.  The server
         also will not write its pidfile to /var/run/ when the -x option is
         used.

     -f  The -f option requires a filename as argument.  Libserver does noth-
         ing with this value, but assigns it to the global character pointer
         named serv_config_file.  This allows the code in serv_init_func()
         and/or serv_child_init_func() to read a configuration file, specified
         by the user, upon process start-up.

AUTHORS
     James Bailie <jimmy@mammothcheese.ca>
     http://www.mammothcheese.ca

                                 Dec 28, 2011