Import upstream 2.3.14 upstream
authorPierre Habouzit <madcoder@debian.org>
Mon, 26 Nov 2007 14:57:13 +0000 (15:57 +0100)
committerPierre Habouzit <madcoder@debian.org>
Mon, 26 Nov 2007 14:57:13 +0000 (15:57 +0100)
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
198 files changed:
AUDIT [new file with mode: 0644]
CHANGELOG [new file with mode: 0644]
COPYRIGHT [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
README [new file with mode: 0644]
TODO [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
config.guess [new file with mode: 0755]
config.h.in [new file with mode: 0644]
config.sub [new file with mode: 0755]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
contrib/empty.conf [new file with mode: 0644]
contrib/xinetd [new file with mode: 0755]
contrib/xinetd.conf [new file with mode: 0644]
contrib/xinetd.d/chargen-dgram [new file with mode: 0644]
contrib/xinetd.d/chargen-stream [new file with mode: 0644]
contrib/xinetd.d/daytime-dgram [new file with mode: 0644]
contrib/xinetd.d/daytime-stream [new file with mode: 0644]
contrib/xinetd.d/discard-dgram [new file with mode: 0644]
contrib/xinetd.d/discard-stream [new file with mode: 0644]
contrib/xinetd.d/echo-dgram [new file with mode: 0644]
contrib/xinetd.d/echo-stream [new file with mode: 0644]
contrib/xinetd.d/ftp-sensor [new file with mode: 0644]
contrib/xinetd.d/tcpmux-server [new file with mode: 0644]
contrib/xinetd.d/time-dgram [new file with mode: 0644]
contrib/xinetd.d/time-stream [new file with mode: 0644]
install-sh [new file with mode: 0755]
libs/include/.cvsignore [new file with mode: 0644]
libs/lib/.cvsignore [new file with mode: 0644]
libs/man/.cvsignore [new file with mode: 0644]
libs/src/misc/COPYRIGHT [new file with mode: 0644]
libs/src/misc/Makefile.in [new file with mode: 0644]
libs/src/misc/README [new file with mode: 0644]
libs/src/misc/install-sh [new file with mode: 0755]
libs/src/misc/m_env.3 [new file with mode: 0644]
libs/src/misc/m_env.c [new file with mode: 0644]
libs/src/misc/m_env.h [new file with mode: 0644]
libs/src/misc/misc.3 [new file with mode: 0644]
libs/src/misc/misc.c [new file with mode: 0644]
libs/src/misc/misc.h [new file with mode: 0644]
libs/src/portable/Makefile.in [new file with mode: 0644]
libs/src/portable/compat.h [new file with mode: 0644]
libs/src/portable/cvt.c [new file with mode: 0644]
libs/src/portable/difftime.c [new file with mode: 0644]
libs/src/portable/fake-getaddrinfo.c [new file with mode: 0644]
libs/src/portable/fake-getaddrinfo.h [new file with mode: 0644]
libs/src/portable/fake-getnameinfo.c [new file with mode: 0644]
libs/src/portable/inet_aton.c [new file with mode: 0644]
libs/src/portable/inet_ntop.c [new file with mode: 0644]
libs/src/portable/libportable.h [new file with mode: 0644]
libs/src/portable/strcasecmp.c [new file with mode: 0644]
libs/src/portable/strerror.c [new file with mode: 0644]
libs/src/pset/COPYRIGHT [new file with mode: 0644]
libs/src/pset/Makefile.in [new file with mode: 0644]
libs/src/pset/install-sh [new file with mode: 0755]
libs/src/pset/ops.c [new file with mode: 0644]
libs/src/pset/pset.3 [new file with mode: 0644]
libs/src/pset/pset.c [new file with mode: 0644]
libs/src/pset/pset.h [new file with mode: 0644]
libs/src/pset/psi.3 [new file with mode: 0644]
libs/src/sio/COPYRIGHT [new file with mode: 0644]
libs/src/sio/Makefile.in [new file with mode: 0644]
libs/src/sio/README [new file with mode: 0644]
libs/src/sio/Sprint.3 [new file with mode: 0644]
libs/src/sio/impl.h [new file with mode: 0644]
libs/src/sio/install-sh [new file with mode: 0755]
libs/src/sio/sio.3 [new file with mode: 0644]
libs/src/sio/sio.c [new file with mode: 0644]
libs/src/sio/sio.h [new file with mode: 0644]
libs/src/sio/sioconf.h [new file with mode: 0644]
libs/src/sio/siosup.c [new file with mode: 0644]
libs/src/sio/sprint.c [new file with mode: 0644]
libs/src/str/CHANGELOG [new file with mode: 0644]
libs/src/str/COPYRIGHT [new file with mode: 0644]
libs/src/str/Makefile.in [new file with mode: 0644]
libs/src/str/README [new file with mode: 0644]
libs/src/str/install-sh [new file with mode: 0755]
libs/src/str/str.h [new file with mode: 0644]
libs/src/str/strparse.3 [new file with mode: 0644]
libs/src/str/strparse.c [new file with mode: 0644]
libs/src/str/strparse.h [new file with mode: 0644]
libs/src/str/strprint.3 [new file with mode: 0644]
libs/src/str/strprint.c [new file with mode: 0644]
libs/src/str/strutil.3 [new file with mode: 0644]
libs/src/str/strutil.c [new file with mode: 0644]
libs/src/xlog/CHANGELOG [new file with mode: 0644]
libs/src/xlog/COPYRIGHT [new file with mode: 0644]
libs/src/xlog/Makefile.in [new file with mode: 0644]
libs/src/xlog/filelog.c [new file with mode: 0644]
libs/src/xlog/filelog.h [new file with mode: 0644]
libs/src/xlog/impl.h [new file with mode: 0644]
libs/src/xlog/install-sh [new file with mode: 0755]
libs/src/xlog/slog.c [new file with mode: 0644]
libs/src/xlog/slog.h [new file with mode: 0644]
libs/src/xlog/util.c [new file with mode: 0644]
libs/src/xlog/xlog.3 [new file with mode: 0644]
libs/src/xlog/xlog.c [new file with mode: 0644]
libs/src/xlog/xlog.h [new file with mode: 0644]
xinetd.spec [new file with mode: 0644]
xinetd.spec.in [new file with mode: 0644]
xinetd/Makefile.in [new file with mode: 0644]
xinetd/access.c [new file with mode: 0644]
xinetd/access.h [new file with mode: 0644]
xinetd/addr.c [new file with mode: 0644]
xinetd/addr.h [new file with mode: 0644]
xinetd/attr.h [new file with mode: 0644]
xinetd/builtins.c [new file with mode: 0644]
xinetd/builtins.h [new file with mode: 0644]
xinetd/child.c [new file with mode: 0644]
xinetd/child.h [new file with mode: 0644]
xinetd/conf.c [new file with mode: 0644]
xinetd/conf.h [new file with mode: 0644]
xinetd/confparse.c [new file with mode: 0644]
xinetd/confparse.h [new file with mode: 0644]
xinetd/connection.c [new file with mode: 0644]
xinetd/connection.h [new file with mode: 0644]
xinetd/defs.h [new file with mode: 0644]
xinetd/env.c [new file with mode: 0644]
xinetd/env.h [new file with mode: 0644]
xinetd/ident.c [new file with mode: 0644]
xinetd/ident.h [new file with mode: 0644]
xinetd/includedir.c [new file with mode: 0644]
xinetd/includedir.h [new file with mode: 0644]
xinetd/inet.c [new file with mode: 0644]
xinetd/inet.h [new file with mode: 0644]
xinetd/init.c [new file with mode: 0644]
xinetd/init.h [new file with mode: 0644]
xinetd/int.c [new file with mode: 0644]
xinetd/int.h [new file with mode: 0644]
xinetd/intcommon.c [new file with mode: 0644]
xinetd/intcommon.h [new file with mode: 0644]
xinetd/internals.c [new file with mode: 0644]
xinetd/internals.h [new file with mode: 0644]
xinetd/itox.8 [new file with mode: 0644]
xinetd/itox.c [new file with mode: 0644]
xinetd/log.c [new file with mode: 0644]
xinetd/log.h [new file with mode: 0644]
xinetd/logctl.c [new file with mode: 0644]
xinetd/logctl.h [new file with mode: 0644]
xinetd/main.c [new file with mode: 0644]
xinetd/main.h [new file with mode: 0644]
xinetd/mask.h [new file with mode: 0644]
xinetd/msg.c [new file with mode: 0644]
xinetd/msg.h [new file with mode: 0644]
xinetd/nvlists.c [new file with mode: 0644]
xinetd/nvlists.h [new file with mode: 0644]
xinetd/options.c [new file with mode: 0644]
xinetd/options.h [new file with mode: 0644]
xinetd/parse.c [new file with mode: 0644]
xinetd/parse.h [new file with mode: 0644]
xinetd/parsers.c [new file with mode: 0644]
xinetd/parsers.h [new file with mode: 0644]
xinetd/parsesup.c [new file with mode: 0644]
xinetd/parsesup.h [new file with mode: 0644]
xinetd/reconfig.c [new file with mode: 0644]
xinetd/reconfig.h [new file with mode: 0644]
xinetd/redirect.c [new file with mode: 0644]
xinetd/redirect.h [new file with mode: 0644]
xinetd/retry.c [new file with mode: 0644]
xinetd/retry.h [new file with mode: 0644]
xinetd/sample.conf [new file with mode: 0644]
xinetd/sconf.c [new file with mode: 0644]
xinetd/sconf.h [new file with mode: 0644]
xinetd/sconst.h [new file with mode: 0644]
xinetd/sensor.c [new file with mode: 0644]
xinetd/sensor.h [new file with mode: 0644]
xinetd/server.c [new file with mode: 0644]
xinetd/server.h [new file with mode: 0644]
xinetd/service.c [new file with mode: 0644]
xinetd/service.h [new file with mode: 0644]
xinetd/signals.c [new file with mode: 0644]
xinetd/signals.h [new file with mode: 0644]
xinetd/special.c [new file with mode: 0644]
xinetd/special.h [new file with mode: 0644]
xinetd/state.h [new file with mode: 0644]
xinetd/tcpint.c [new file with mode: 0644]
xinetd/tcpint.h [new file with mode: 0644]
xinetd/time.c [new file with mode: 0644]
xinetd/timex.h [new file with mode: 0644]
xinetd/udpint.c [new file with mode: 0644]
xinetd/udpint.h [new file with mode: 0644]
xinetd/util.c [new file with mode: 0644]
xinetd/util.h [new file with mode: 0644]
xinetd/xconfig.h [new file with mode: 0644]
xinetd/xconv-new.pl [new file with mode: 0755]
xinetd/xconv.pl [new file with mode: 0755]
xinetd/xconv.pl.8 [new file with mode: 0644]
xinetd/xgetloadavg.c [new file with mode: 0644]
xinetd/xgetloadavg.h [new file with mode: 0644]
xinetd/xinetd.conf.man [new file with mode: 0644]
xinetd/xinetd.log.man [new file with mode: 0644]
xinetd/xinetd.man [new file with mode: 0644]
xinetd/xmdns.c [new file with mode: 0644]
xinetd/xmdns.h [new file with mode: 0644]
xinetd/xtimer.c [new file with mode: 0644]
xinetd/xtimer.h [new file with mode: 0644]

diff --git a/AUDIT b/AUDIT
new file mode 100644 (file)
index 0000000..91e6733
--- /dev/null
+++ b/AUDIT
@@ -0,0 +1,173 @@
+This is the xinetd-2.3.0 audit status.  The audit has been performed
+in order to make the Owl (http://www.openwall.com/Owl/) xinetd package
+reasonably secure and of course with the hope that others will find
+the results and patches useful as well.
+
+Much of xinetd's logic is left unaudited (other than for generic bug
+classes listed below).  In particular, this applies to all network
+access control checks.
+
+To summarize the results, xinetd may be reasonably safe to use with
+these patches, but the code remains far from clean and certain bugs
+are there by design.
+
+The format of this list is one item per line, with subitems indented.
+If a line doesn't start with a '+', that item hasn't been completed
+(audited and/or patched).
+
+None of the PATCH'es are a part of xinetd-2.3.0; they will be in the
+Owl package and hopefully will get incorporated into future versions
+of xinetd.
+
+-- 
+Solar Designer <solar@openwall.com>
+
++BUGS  strx_* functions (danger: don't always NUL-terminate)
++PATCH         bug: shouldn't write NUL when len <= 0
++PATCH         may overflow with huge precision values (bad for format bugs)
++BUGS  strx_* calls: some assume NUL-termination, but none look dangerous
++PATCH         __xlog_explain_errno forgets to update size
++PATCH         child.c: child_process may not NUL-terminate name
++PATCH         init.c: syscall_failed may not NUL-terminate err
++PATCH         shutdown.c: safe, but should use print_buf_size-1
++PATCH         signals.c: sig_name should use sizeof(signame_buf)-1
++OK    str_* calls
++OK            none :-)
++OK    strcat, strcpy calls (testsuite calls not checked)
++OK    strn* calls
++PATCH         some inefficient, but correct
++BUGS  memcpy, memmove, bcopy calls
++PATCH         addr.c: addrlist_dump() copies ipv6 address into ipv4 struct
++PATCH         addr.c: host_addr() trusts hep->h_length from gethostbyname()
++PATCH         parsers.c: redir_parser() wouldn't build/work when NO_INET_ATON
++PATCH         parsers.c: redir_parser() wrongly relies on sizeof(he->h_addr)
++PATCH         parsers.c: bind_parser() same as the above
+               the use of sizeof() is inconsistent (not always of dst arg)
++PATCH         should change bcopy to memcpy/memmove as appropriate
++BUGS  sio_memcopy calls
++OK            sio.c
++BUGS          siosup.c is too complicated in its handling of data sizes
++OK                    expand() is only called with old_size < new_size
++?                     buffer_setup() isn't obviously correct, but is safe
++OK                    __sio_extend_buffer is correct
++PATCH                         comment to sio.h: aux buffer is right below buf
++PATCH                 __sio_get_events may cause bufentries < 0 (->overflow)
++OK    conn_setaddr calls: safe, but could use sizeof((cp)->co_remote_address)
++OK    sprintf calls
++BUGS  sscanf calls
++PATCH         addr.c: explicit_mask() has single-byte overflow of saddr[]
++BUGS  formats
++OK            fprintf, sprintf, fscanf, sscanf
++OK            syslog (but relies on %.*s for non-NUL-terminated buffers)
++OK            strx_*
++OK            svc_logprint, prepare_buffer
++BUGS          msg, parsemsg
++PATCH                 intcommon.c: int_init() passes fmt as wrong arg
++PATCH                 (non-security) should never have '\n' in format
++OK            tabprint
++OK            Sprint
++OK            ostimer.c: terminate
++PATCH         xlog_write() is called on untrusted input w/o XLOG_NO_ERRNO
++OK    ident -- looks mostly safe
++OK            SIGALRM + longjmp() used safely:
++OK                    no static accesses, no stdio between START/STOP_TIMER
++OK                    immediate return on timeout (-> no clobbering issues)
++OK                    signal mask after longjmp() is unimportant
++PATCH                 could be safer to also reset SIGALRM handler
++PATCH         verify_line() modifies buf, which is then logged on error
+               will log control chars from remote
++BUGS  builtins
++OK            time, daytime, sensor: NO_FORK && stream (safe: FNDELAY)
++PATCH         accept() return value never checked
++PATCH         bad_port_check(): should deny all <1024 (53/udp is just as bad)
++PATCH         stream_daytime writes to wrong fd when wait = yes (gets EPIPE)
++PATCH         *_time sends sizeof(time_t): wrong on at least linux-alpha
+               xadmin_handler(): the command parser is unreliable (use sio?)
++BUGS  record (shutdown.c)
+               connect_back may be used for portscanning of own machine
+               write() return values not checked
++PATCH         will only handle traditional (obsolete) crypt(3) hashes
+               special.c: stream_shutdown() will log control chars from remote
+       intercept (int[.c]*, {tcp,udp}int.c) -- checked for generic bugs ONLY
+               tcpint.c: si_exit() may leave open fd from accept()
++BUGS  signal races, longjmp clobbering
++BUGS          __ostimer_interrupt:
++PATCH                 call_level should be volatile
++PATCH                 should use &ret_env, not (char *)ret_env (may differ)
++BUGS                  ret_env modified non-atomically (with 2 TIMER_LONGJMP's)
++PATCH                         should set have_env before and make it volatile
++PATCH                 may leave an altered signal mask on longjmp()
+                               should fallback to plain longjmp in configure
++OK                    __ostimer_{add,remove} only called with signals blocked
++OK                    timer_s fields not volatile, safe due to block _calls_
++BUGS          check uses of TIMER_LONGJMP flag
++BUGS                  confparse.c: get_conf() may jump out of malloc(), etc
+                               no other uses, perhaps just disable CONF_TIMEOUT
++OK            ident.c: mostly safe (see above)
++BUGS          signals.c: bad_signal(): only on crashes, so not a big issue
++PATCH                 *count should be volatile to really avoid looping
+                       does calls which may cause another SIGSEGV w/o a bug
++PATCH                 may leave an altered signal mask on longjmp()
++BUGS          signals.c: general_handler()
+                       sio and non-reentrant libc calls on unexpected signal
++BUGS          signals.c: handle_signal(), my_handler(): events may be lost
+                       my_handler may be re-entered, but M_SET isn't atomic:
+                               should split ps.flags into int-per-flag
++OK            main.c: main(): setjmp() placed in a way avoiding clobbering
++BUGS          access.c: parent_access_control(), alrm_ena() (cps feature)
+                       alrm_ena() may cause re-entry into syslog(), etc
+                       SIGALRM handler may be never reset, or --
+                       the handler and/or alarm may be reset for other needs
+                               should use the timer queues, not OS timers
++BUGS          int.c: int_sighandler(), intcommon.c: int_init()
+                       int_sighandler() may cause re-entry into msg(), etc
+                               installed for multiple signals, doesn't block
+                               may interrupt msg() in main and cause re-entry
++PATCH         redirect.c: redir_sigpipe() should use _exit(2), not exit(3)
++BUGS  fd_set overflows
+               intcommon.c: sets INT_REMOTE(ip) w/o fd_set size check
+                       {tcp,udp}int.c: si_mux(), di_mux() FD_SET w/o fd check
+               internals.c: socket_mask_copy w/o fd checks
+               main_loop(): select() on read_mask w/o fd checks
+               service.c: svc_activate(): could check ps.rws.mask_max here
+               (many files) all references to ps.rws.socket_mask are unchecked
+               redirect.c: redir_handler() no checks for rdfd, msfd
+               should use fd_grow similarly to OpenBSD inetd
++PATCH         workaround: reduce RLIMIT_NOFILE to FD_SETSIZE
++BUGS  __sio_descriptors overflows
++PATCH         sio functions forget to check fd against n_descriptors
++BUGS  get_fd_limit(), Smorefds()
++PATCH         assume RLIMIT_NOFILE is small (not RLIM_INFINITY)
++OK            orig_max_descriptors and max_descriptors are rlim_t, not int
++BUGS  potential fd leaks to services
++PATCH         init.c: setup_file_descriptors() relies on the rlimit only
+               returns from close() never checked -- fixed the worst one
++BUGS  child.c: set_credentials()
++PATCH         should fail if !ps.ros.is_superuser && user/group requested
++OK            is otherwise fail-close and resets groups (fixed long ago)
++BUGS  gethostby*, getaddrinfo (some are common with memcpy bugs)
++PATCH         addr.c: host_addr() trusts hep->h_length from gethostbyname()
+               addr.c: host_addr() INET6 doesn't check res->ai_family
+               parsers.c: {redir,bind}_parser() don't check res->ai_family
++PATCH         parsers.c: redir_parser() wrongly relies on sizeof(he->h_addr)
++PATCH         parsers.c: bind_parser() same as the above
++PATCH getpwnam unnecessarily leaves password hashes in address space on BSD
+---
++PATCH gcc format attributes
++      build with gcc -Wall -Wcast-align (x86, alpha) -- mostly clean
++PATCH         many unused vars with ipv6
++PATCH         parsers.c, inet.c: stores strtol() to int, then needs long
++PATCH         several format strings don't match arguments
++      build with ccc -msg_enable level4 or higher
++PATCH         CC= from configure doesn't get into Makefile's
+               lots of warnings (250 KB of output), the code is just not clean
++PATCH                 some really need fixing
+-      use wrapper functions around either strx_* or vsnprintf()?
++              not a good idea, tested strx_* against snprintf instead
+?      define strz_* wrappers around strx_*, which would always NUL-terminate
++PATCH atoi -> strtol with long to int overflow checks
+---
+       should limit logging rate (= rate of permitted sessions, popa3d-like)
+       should drop privileges for ident lookups, builtins, and records
+       should have options to build --without-{ident,builtins,record,intercept}
+               should generate manpages accordingly
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..bb81de2
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,909 @@
+
+This file describes the changes to xinetd. The base version is 2.0.0.
+
+2.0.0: (not released)
+
+2.0.1: (not released)
+
+2.0.2:
+       Changes to the Makefile.
+       Trivial mods to the usage() function
+
+2.0.3:
+       Changes to the Makefile.
+       Fixed a bug in the usage() function
+
+2.0.4:
+       Distribution versions of the Makefile no longer contain any 
+       references to options.opt
+
+2.0.5:
+       1) Clarified what an "unlisted RPC service" is in the man page
+       2) Fixed a bug in remote_address_check which caused access to be denied
+               for all hosts if no_access was set and only_from was not set.
+       3) Fixed a bug which caused arbitrary syslog levels if the log_type
+               was specified as SYSLOG in the "defaults" entry
+
+2.0.6:
+       bug fix in child.c: replaced strx_sprint with strx_print when naming
+       interceptor processes
+
+
+-------------------------------------------------------------------------------
+
+2.1.0: (not released)
+       This was mostly a clean-up of 2.0
+       List of changes:
+
+       A. The man page has been split into 3 parts:
+                       xinetd.man                      :       man page describing the program
+                       xinetd.conf.man :       man page describing the configuration file 
+                                                                               This file now includes figures about the
+                                                                               overhead of interception.
+                       xinetd.log.man          :       man page describing the log file
+       B. New service attributes
+                       rpc_number                      : to support unlisted RPC services
+                       nice                                    : to set the nice value of forked servers
+       C. The IDONLY service flag was added
+       D. Now uses the timer library unless NO_TIMERS is defined. If NO_TIMERS
+               is not defined, the following are also available:
+                       a) a new option, -cc, to do periodic consistency checks
+                       b) timeout for reconfiguration
+       E.      Configuration file man page now mentions that access control is 
+               based on IP-address instead of domain address.
+       F.      The interception code now sets the TCP_NODELAY option.
+       G. The timeout when contacting a remote identification server is
+               configurable both when the service request has been accepted and 
+               when the request is rejected. In the former case it defaults to
+               infinity while in the latter it defaults to 30 sec.
+       H. The log line ids are now constants in an include file.
+       I. The fsma library is no longer used.
+       J. Most structure fields were renamed; certain functions were renamed too.
+               Access to structure fields is now via macros.
+       K. A bug in not restoring the number of descriptors to the soft limit
+               was fixed.
+       L. The -pid option works
+       M. New internal services:
+                       "servers"               : lists active servers
+                       "services"              : lists active services
+
+2.1.1:
+       xinetd produces more meaningful messages if it can't start logging
+
+2.1.2:
+       Fixed 2 bugs:
+               1) xinetd would request a port number for unlisted RPC services
+                       One could get around this by simply specifying the port attribute
+                       for the service; the specified value would be ignored anyway.
+               2) xinetd initialization might fail sometimes in function msg_init()
+                       syslog logging was specified (i.e. the option -syslog was used)
+                       The cause of this bug was that the 
+                               xlog_control( xlog, XLOG_GETFD, &fd ) 
+                       operation will not fail for xlogs connected to syslog and
+                       the value of 'fd' would be used in the subsequent fcntl(). That
+                       value is arbitrary since 'fd' is a local variable.
+                       If 'fd' did not happen to refer to an open descriptor, the program 
+                       would terminate since the fcntl() would fail (btw, the success
+                       of the fcntl() call would be harmless if 'fd' happened to
+                       refer to an open descriptor).
+
+2.1.3:
+       Bug fix:
+               only_from/no_access addresses would get inverted on little-endian
+               machines when such addresses were specified using the numeric notation
+               (for example, 128.138.45.3). This bug was in the numeric_addr function
+               which did not convert the result of inet_addr to host-byte-order.
+               A work around for the bug would be to use the factorized address 
+               notation (for example, 128.138.45.{3})
+
+2.1.4:
+       Bug fixes:
+               1) in dgram_echo(), sin_len was not being set before the invocation of
+                       recvfrom
+               2) in finger_shutdown(), it was possible for Srdline() to return NULL
+                       (if the remote end would close the socket without sending anything).
+                       If the RECORD option was set in the log_on_failure flags, this
+                       would cause the forked xinetd process which did the recording to
+                       die since it would try to dereference a NULL pointer.
+
+
+2.1.5:
+       Bug fixes:
+               1) in exec_server() service descriptor might be closed when
+                  execing server. This made it impossible to start servers
+                       for 'nowait' services.  The bug occurred only Ultrix version
+                       4.3a or (probably) later (bug discovered and fix provided
+                       by doug@seas.smu.edu)
+               
+               2) for systems that supported supplementary group id's, the
+                       set_credentials() function did not set those group id's
+                       (they were being inherited from xinetd). Now initgroups(3)
+                       is called to set the supplementary group id's properly.
+                       (bug discovered and fix provided by maf+@osu.edu)
+
+2.1.6:
+       Bug fixes:
+               1) xinetd will crash after reconfiguration if there is a running
+                       server for a service that was removed from the configuration and
+                       which logs on exit.
+               2) xinetd forked process falls in infinite loop if identd server
+                       sends a reply that is missing the ending CR-LF.
+                       (bug discovered and fix provided by Laurent.Wacrenier@gin.obspm.fr).
+
+       We also change the LOGUSER_SUCCESS_TIMEOUT constant in config.h from
+       0 seconds (i.e. infinite timeout) to 30 seconds. This avoids infinite
+       waits in case the remote host does not send a RST reply when we attempt
+       to connect to the IDENTD port, and there is no server listening at
+       that port.
+
+
+2.1.7:
+       Bug fix: the HOST flag in the 'log_on_success' attribute was ignored;
+                               the code was incorrectly checking if the HOST flag was
+                               set in the log_on_failure attribute
+                               (bug discovered by frolich@corrine.cpc.cs.ucf.edu)
+
+2.1.8.1: 
+       Added support for TCP redirect to a remote host.
+               --bbraun
+
+2.1.8.2: 
+       Added support for binding to specific interface.
+               --bbraun
+
+2.1.8.3:
+       Changed redirect so that a remote port can be specified as well.
+               --bbraun
+
+2.1.8.4 10/98:
+       Changed use of varargs to be more modern (and actually work on IRIX 6.5)
+       Added use of 1.2.3.4/24 style address ranges for access control
+               --bbraun
+2.1.8.4p2 11/98:
+       Fixed stupid error with logging of ip addresses.  
+       Pointed out by Todd R. Eigenschink
+2.1.8.4p3 11/98:
+       Fixed to compile correctly under HPUX
+               Includes fixes from Pavel Roskin <pavel_roskin@geocities.com>
+2.1.8.4p4 11/98:
+       Fixed to compile correctly under BSDi
+2.1.8.4p5 11/98:
+       Fixed Linux libc5 to work with RPC.
+               Pointed out by Frodo Looijaard <frodol@dds.nl>
+2.1.8.4p8 11/98:
+       Minor jump because I went through many revisions of testing things
+       - Fixed littleendian bug with 1.2.3.4/26 style access control
+       - Added support for inet_addr instead of inet_aton, as Solaris 2.5.1
+       does not support inet_aton.
+               Both the previous bugs were found with the help of
+                       Thomas E. (tht@inlink.com)
+       - Went entirely to stdarg.h version of variable arguement handling,
+       since some newer platforms doen't handle varargs.h style very
+       gracefully.  If this breaks too many older architectures I'll
+       ifdef all the old stuff back in...
+2.1.8.5 11/98:
+       Fixed /tmp/xinetd.dump symlink problem pointed out on 
+               BugTraq by Balazs Nagy <julian7@KVA.HU>
+2.1.8.5p1 1/99:
+       Fixed compilation problems on BSD systems.
+2.1.8.5p2 1/99:
+       Fixed compilation problems on AIX 4.1.x/powerpc
+2.1.8.5p3 3/99:
+       Fixed compilation problems on FreeBSD 
+               Thanks to  Sascha Schumann <schumann@schell.de>
+       Fixed a bug in sio/sprint.c
+               Thanks to Steven Stanfield <sstanf@reston.wcom.net>
+2.1.8.6b1 4/99:
+       Rudimentary administrative interface added (use the service name
+               xadmin).
+       Supports the "banner" directive, which is the name of the file
+               that will be splatted when a connection is denied.
+       Has a fixed open() on the dump file that is much better.
+               Thanks to Steven Stanfield <sstanf@reston.wcom.net>
+       $REMOTE_HOST environment variable is set to the name of the
+               remote host.  Currently, if no name is available, it is set to NULL.
+2.1.8.6b2 4/99:
+       Fixed a problem with shells that don't define $PWD
+2.1.8.6b3 4/99:
+       Fixed a problem I introduced with automagic port selection
+       If both a port and a protocol are specified, no checks are done.
+               xinetd will believe the config, even if /etc/services says 
+               otherwise.
+       xadmin service is an internal service now, just like tcp echo, etc.
+               Use the INTERNAL flag.
+       xadmin service now just calls server_dump when a "show run" command
+               is executed.
+       Added a NAMEINARGS flag, so that you can use tcpd with xinetd.
+               Normally, xinetd takes argv[0] from the "server" directive.
+               This prevents tcpd from working properly.  Now, you can use
+               tcp wrappers like this:
+               service telnet
+               {
+                       scoket_type = stream
+                       protocol = tcp
+                       flags = NAMEINARGS
+                       wait = no
+                       user = root
+                       server = /usr/libexec/tcpd
+                       server_args = /usr/libexec/telnetd
+               }
+2.1.86b4 4/99:
+        Added support for libwrap.  Compile with --with-libwrap.  Access 
+        checking is done with libwrap (if compiled in) first, then with 
+        xinetd's internal access control.
+2.1.8.6b5 4/99:
+       Some versions of libwrap needed allow_severity.  Added it.
+               Changed severity to INFO from WARNING.
+2.1.8.6b6 7/99:
+       Added ability to use names for the bind and redirect
+               functions.  They lookup the name, and use the
+               first address it returns.  They only do the
+               lookup once.
+       Added "interface" as an alias to "bind"
+       Fixed potential bug with redirection losing data. 
+               Pointed out by Solar Designer
+       Fixed potential bug in the parsing of xadmin commands.
+               Pointed out by Solar Designer
+       Changed default location of the dump file to /var/run/xinetd.dump
+               configurable in config.h
+       Added Solar Designer's per_source feature.  Allows you to limit
+               the number of services spawned per source address.
+       Added Solar Designer's supplementary groups fix.
+2.1.8.6b7 7/99:
+       Updated the make files to not require absolute paths.  This
+               will help with people having problems with the LOCATION
+               Makefile variable.
+       Updated configure to compile properly with Debian's version
+               of libwrap and glibc (look for yp_get_default_domain in nsl)
+       If banner directive is used, banner is printed regardless of access
+               control.  It is actually printed before access control check 
+               take place.  banner_success and banner_fail are added to 
+               explicitly give a message depending on access control.
+       Added banner_success option.  This is a banner that is printed when
+               access to the service is granted.  This is before any attempt
+               to execute the server has been made.  The service may still fail
+               but it will not be for access control reasons.
+       Added banner_fail option.  This is a banner that is printed when 
+               access to the service has been denied.  This allows you to 
+               inform your users that they are doing something bad and they 
+               shouldn't be doing it anymore.
+       Added max_load option.  This option allows the operator to specify
+               the max load at which to run the service.  If the machine 
+               reaches the specified max load level, connections are denied to
+               that service.  Each service can have a different max_load, and 
+               it can be listed in the default service.  Linux is working,
+               Solaris is kind of wierd.  Solaris people should try it, but
+               don't use it as a real security mechanism yet.  2.6 and 2.7 
+               should be fine.  I'm not sure about 2.5.1 and earlier.
+2.1.8.7 10/99:
+       Fixed per_source to actually work properly.
+       Added the NODELAY flag.  This will set the TCP_NODELAY sockopt
+               on the socket.  If the service is not a TCP service, then
+               this flag has no effect.
+       Updated the man page with more explicit definition of the "groups"
+               attribute.
+       Includes xconv.pl to replace itox.  xconv.pl handles most of the
+               inetd.conf files I've seen, including the use of tcpd,
+               even though it is recommended that you compile with
+               libwrap instead of using tcpd.
+       Includes a man page to itox donated by Norbert Veber of Debian.
+       Updates to configure and Makefile to better handle the configuration
+               of install directories.  Again, changes donated by Debian group.
+       Updates to itox to handle user.group syntax and checking on "wait".
+2.1.8.8pre1 11/99
+       Fixed a problem with the banner_fail parser.
+       Added IPv6 support to xinetd.
+2.1.8.8pre2 12/99
+       Added the option "cps".  This allows you to disable a service if
+               the rate of incoming connections is too great.  This number 
+               may be set higher than the instances or per_source number.
+               This is used as a last ditch measure, if someone is bombarding
+               a service, and either 1) logs are piling up because of failed
+               attempts, or 2) way too much is happening, ditch the service.
+               This actually does a close() on the socket, so nothing is
+               listening to that port anymore.  All connections will fail.
+2.1.8.8pre3 12/99
+       Made the options mask_t an unsigned long long (64bits on x86)
+               instead of an unsigned.  xinetd was running out of bits
+               to store options in.  Eventually, a real solution will
+               need to be implemented, but this works for the short term.
+               This may break on compilers that don't understand 
+               long long's.  Be aware.  Most modern compilers are ok.
+       Added the option "enabled", similar to the "disabled" function.
+               If "enabled" is used, only the services listed in the
+               enabled line are available, regardless of what other
+               services are configured.
+       Changed the behavior of only_from and no_access.  First, if you
+               specify a host by _name_ in only_from or no_access, a lookup
+               happens when a client connects.  The _canonical_ name that
+               is returned is compared to the name specified in the access
+               control option.  If the _names_ match, access is granted
+               or denied.  See the readme for more information.
+       Added the ability to specify .domain.com to the access control
+               options.  This is very similar to tcp wrapper's method
+               of specifying domain access.  If the connecting client's
+               reverse lookup returns a name that ends in .domain.com
+               then access is granted or denied.  See the readme for
+               more information.
+2.1.8.8pre4 12/99
+       The enable function didn't work.  It worked for one entry, but
+               more than 1 entry would not be recognized and xinetd
+               would exit with no services available.  I believe this
+               has been fixed.
+       limits.h is included in parsers.c now, because of LONG_MIN and
+               LONG_MAX.  Some setups would automagically include limits.h
+               through the other include files, and some wouldn't.  This
+               should fix compile problems on those that don't.
+       Added a check for sys_siglist in the configuration script.  This
+               is better than statically defining #ifdef's in signals.c.
+2.1.8.8pre5 12/99
+       Fixed numeric addresses being entered in the only_from field.
+               host_addr parser was identifying them and marking them as
+               HOST_ADDRs instead of NUMERIC_ADDRS.
+2.1.8.8pre6 1/100
+       Fixed year formatting in log to print 00 instead of 100.
+2.1.8.8pre7 1/00
+       Fixed the TIMEOFFSET macro in builtins.c so the 'time' service printed
+               the correct output.
+2.1.8.8pre8 1/00
+       Fixed a problem where banners would not work saying "could not find
+               banner: bannername<garbage here>".
+2.1.8.8pre9 1/00
+       The dump file was logging the ip address incorrectly for only_from
+               addresses.  For some reason xntoa() was reporting the wrong
+               address.  Changed to inet_ntoa, and works fine.
+       BSDI 4.1 was not compiling correctly, "inet_ntoa" not found.
+               This is because BSDI4.x switched to using bind 8 resolver
+               libraries, so you have to include <arpa/inet.h> to #define
+               all these functions to __func_name.  
+       Some BSD's don't let you set the group permissions of a process to NULL,
+               so you get the setgroups(0,NULL) error whenever a connection
+               is made.  To avoid this, set 'groups = yes' and be aware of the
+               extra group permissions the server may be running with.  A message
+               to this effect has been added to the syslog error, so confusion is
+               minimized.
+2.1.8.8pre10 2/00
+       Fixed a syntax error when compiling IPv6 support.
+2.1.8.8pre11 2/00
+       Always call no_control_tty().  This calls setsid() and fixes a problem
+               under FreeBSD.
+2.1.8.8 2/00
+       Bumped version number.
+2.1.8.9pre1
+       Added the "include" directive.  You can now include other files
+               into your .conf file.  "include filename"
+       Added preliminary an inetd compatibility mode.  Start xinetd
+               with -inetd-compat and specify /etc/inetd.conf as your
+               configuration file.
+2.1.8.9pre2 
+       Fixed up RPC support
+2.1.8.9pre3
+       Incorporated patches for Mac OS X and Tru64 support.
+       Also incorporated a patch for the includedir directive.
+2.1.8.9pre4
+       Incorporated a patch to allow logging to the AUTHPRIV level.
+               patch from Trond Eivind Glomsr.
+       Numerous cleanups.  Mostly superficial, but gets rid of *lots*
+               of compile warnings when using -Wall.  These cleanups
+               may have affected portability issues...
+       Support for Darwin!  Now compiles and runs fine.  Note that
+               xinetd doing mmap didn't work right (always lost the
+               first byte of the file).  Workaround is to disable
+               mmapped io for Darwin.
+       Added a DISABLE flag for services, that will prevent a service
+               from starting.
+       Added a "disable" boolean for services that does the same thing
+               as the DISABLE flag.
+       "groups" can now be specified in the defaults section.
+2.1.8.9pre5
+       Implemented better error checking in redirect.c, so hopefully
+               it will detect error conditions more reliably and
+               prevent lots of child xinetd's running unecisarily.
+       Ramon Krikken sent a redirector implementation that replaced
+               the two process redirection with a single process using
+               select.  Modifications to his patch were integrated.
+       includedir parses only regular files, or symlinks to regular
+               files, that do not begin with '.'.  
+       Added includedir to the xinetd.conf man page.
+2.1.8.9pre6
+       Fixed a bug in the access lists.  If you specified a host by
+               name in only_from, any connection from a host without
+               a reverse dns entry would be accepted.
+2.1.8.9pre8
+       Now allows you to specify multiple instances of the same service
+               as long as all but one is disabled.
+       Fixed a documentation issue in the xinetd.conf man page.
+               The user attribute can be specified for an unlisted
+               service, just not an internal service.
+       When including files with "includedir", it parses the files
+               in alphabetical order, as determined by strcmp().
+       Under Solaris, I've removed the no_control_tty() call in
+               child.c.  This was causing some confusion.  xinetd
+               its self still calls no_control_tty().
+       Fixed a compile error with --with-inet6
+       Changed the exiting behavior: xinetd now kills only the
+               RPC services and internal services (like redir) when
+               it exits (or does a hard reconfigure).  This keeps things
+               like telnet sessions open across restarts of xinetd
+               (assuming you are using REUSE).
+2.1.8.9pre9
+       Fixed a potential bug in parsing of filenames from includedir.
+       Possibly fixed tcp wait=yes handling.
+       Fixed man pages so they say they're installed in the sections
+               they are really installed into.
+       Added .cvsignore to empty directories
+2.1.8.9pre10
+       Hopefully fixed a few compile errors on architectures such
+               as DUNIX and Darwin.
+       When compiled with libwrap support, xinetd passes the server
+               name to be checked in hosts.{allow,deny} instead of
+               the service name.  Behavior should now match tcpd.
+       Incorporated Trond's pidfile patch.  You can now specify -pidfile
+               on the command line, and xinetd will make a 
+               /var/run/xinetd.pid file.  Note that this _replaces_ the
+               -pid option.
+2.1.8.9pre11
+       Removed '\n's from syslog messages.  Also moved some of the 
+               syslog()'s to pasemsg()'s.
+       Added a patch from mob@de.uu.net to make the bind attribute 
+               specifiable in the default section.
+       Added the KEEPALIVE flag, which sets the SO_KEEPALIVE socketopt
+               on tcp sockets.
+       Added a patch from Trond at RedHat that will hopefully fix some
+               of the remaining tcp wait=yes problems.
+       More paranoid handling of access control in addr.c
+       Always allow access to the internal pseudo services.
+       For internal services and libwrap, access control is performed 
+               by the service name (instead of the server, since there
+               is no server).
+       The last two entries together fix problems with segfaults when
+               doing access control.
+       If a hostname is specified in only_from, xinetd will try to 
+               match the connecting address to any of the IP addresses
+               associated with the hostname in only_from.
+       For redirection services with libwrap support, the service name
+               is used for access control rather than the server name, since
+               the server name makes no sense.
+2.1.8.9pre12
+       Remove the pidfile when exiting.
+       Added a -stayalive option to keep xinetd running even when there are
+               no services available.
+2.1.8.9pre13
+       Added paranoid access control for the udp internal servers.
+               Do not reply to udp packets on dangerous ports 
+               (avoid looping echo services).
+       For libwrap, if the server isn't specified use the service
+               _id_ instead of the service name (this usually is the
+               service name).  This makes more sense for things like
+               the internal servers (echo-stream instead of using echo,
+               which will get echo-stream and echo-dgram)
+       Included an rlimit patch from Nick Burrett, which should help
+               keep some nasty users at bay.  He's even updated the
+               man page.  This patch brings a tear to my eye.
+
+2.1.8.9pre14
+       Moved the libwrap and address checking to the child process.
+               The purpose of this is to move the expensive checking
+               into the child process (such as name resolution, exec()'ing,
+               etc), but leave some of the lighter weigh checking in the
+               parent in an attempt to prevent DoS'.
+       Incorporated Charles Levert's NOLIBWRAP patch.  This adds a flag,
+               NOLIBWRAP, which will turn off libwrap access control for
+               a single service.  This is a good thing when you're wanting
+               to use tcpd with a service.  It's also useful when wanting
+               libwrap for some lesser used services, but the high volume
+               ones need higher performance.
+       Included Motonobu Ichimura's patches for v6.  The first one sets
+               v6 services with incoming v4mapped or compatible addresses
+               to AF_INET instead of AF_INET6.  This should make incoming
+               v4 connections to v4 servers work correctly.
+       Motonobu Ichimura's second patch adds the service attribute
+               v6config, which allows a v6 service to only accept v6 
+               connections.
+       Moved most of the configured defines into a config.h.
+               This involved renaming xinetd/config.h to xinetd/xconfig.h
+       The configure system actually works with --srcdir now.
+               You can build xinetd from a directory other than the source
+               directory now.
+       Minor cleanups to remove warnings with -Wall
+
+2.1.8.9pre15 5/20/2001
+       Added Steve Grubb's SENSOR patch which provides a SENSOR flag and 
+               deny_time attribute. These will help to stop script kiddies 
+               doing port scans by turning off all access to all services 
+               on all IP addresses until the timeout expires.
+       Cleaned up pset stuff in the lib section.
+       Continued fixing warnings produced by -Wall
+       Added "child" security check for internal services.
+       Fixed some possible memory leaks.
+       Changed snprintf to the internal strx_nprint() function, standardizing
+               on that.  Removed the need for the snprintf() implementation 
+               for systems lacking snprintf().
+       Another attempt to fix the tcp wait condition.
+               TCP wait services were being accept()'d when they shouldn't
+               This caused services such as linuxconf, which accept()
+               their own connections, to fail.
+       Fixed a problem with displaying bound and redirected addresses in
+               the xadmin service.
+       Don't print banner always and banner success twice.
+       Converted to ANSI C style prototypes instead of K&R.
+       Use spaces instead of 3 character tabs.
+       Use POSIX types for network, time, and other length specific purposes.
+       Make the initial log message of compile time options atomic.
+       When grow()'ing the environment variables, initialize things to 
+               prevent bad pointers.
+       Mitigated consequences of possible SIGCHLD race with intercepted 
+               services.
+       Removed all remnants of varargs syntax, and have completely moved
+               to the stdarg style syntax.
+       Added BSD/OS loadavg support from Robert Brewer at LavaNet.
+       Fixed a potential buffer overflow when using USERID.
+               Found by zen-parse.
+       Added permissions to the pidfile's open call.
+               Suggested by zen-parse.
+       Changed xinetd's umask to 022 from 0.
+2.1.8.9pre16 6/13/2001
+       Attempted to fix IPv6 support broken in the pre15 release. -Steve Grubb
+       Moved remote_address_check ahead of the libwrap checks.  This is needed
+               so that SENSORS work without modifying the hosts.allow file if 
+               tcp_wrappers is compiled in. -Steve Grubb
+       Added missing includes to several library files
+       Fixed bug where DISABLE flag was being set/cleared in xflags rather 
+               than types. -Matthias Andree
+       Fixed memory leak in attr_check. -Steve Grubb
+        Continued converting to ANSI C prototypes. -Steve Grubb
+        Fixed reads in service.c to continue through interupts. -Steve Grubb
+        Corrected Includedir directive. -Solar Designer
+       Changed umask to OR 022 with the current umask. -Solar Designer  
+       Cleaned up the address list dump to format the different addresses 
+               types correctly. -Steve Grubb
+       Cleaned up parsing of address lists. -Steve Grubb
+       Integrated support for building on OS X.
+       Added wait/nowait support to "small services".
+       Fixed IPv6 support for "small services".
+       Added "umask" keyword to specify service's umask in octal.
+       Umask situation is described in the umask section of xinetd.conf.man
+       Inspect all configuration files. Will now emit warnings if any are 
+               world writeable, symlinks, or not owned by root.-Steve Grubb
+2.3.0
+       Fixed a bounds checking case in strx* functions.
+               Pointed out by Sebastian Krahmer.
+2.3.1
+       Reworked all headers in xinetd directory. -Steve Grubb
+       Fixed redirect & shutdown to read & write through signal 
+               interrupts. -Steve Grubb
+       Inspect all servers. Prints warnings for things that look funny.
+       Applied _many_ security and reliability fixes,
+               see AUDIT. -Solar Designer
+       Removed the Soft Reconfigure capability.  Soft Reconfigure is now
+               the same as Hard Reconfigure (SIGUSR1 = SIGUSR2).
+                       -Steve Grubb
+       Attempt to fix segfaulting seen since 2.3.0.
+               -Steve Grubb
+       Moved the re-enable service after cps violation to run off of the 
+               flags system to avoid re-entrancy issues. -Steve Grubb
+       Only call drain if service is active. Deactivated services close 
+               the descriptor. -Steve Grubb
+       Reorganized flags to process terminating children first, -Steve Grubb
+2.3.2
+       more K&R -> ANSI prototype -Steve Grubb
+       Stop using C++ keywords (even though this is really C...) -Steve Grubb
+       Fix a heap overrun in grow().  -teg@redhat.com 
+       Fix a parse error with multiple explict masks.
+       If protocol is not specified, but socket type is, infer protocol
+               from socket type.  -Ahmon Dancy
+       Added a check to the return value of env_addstr() in child.c to
+               make sure we aren't exec()ing with an invalid environment.
+       Wrap the remaining <stdint.h> includes with autoconf macros.
+       Removed all unused functions. -Steve Grubb
+       Don't use SIGALRM for the cps directive.  Instead, do a generic
+               timer routine that evolves around the main event loop.
+2.3.3
+       Fixed the filelog problem of printing garbage.
+       Fixed the RPC parser to correctly handle RPC version ranges again.
+
+2.3.4
+       Removed the old flags construct and replaced it with the timers
+               added in 2.3.2.  This will handle multiple of the same 
+               signals occuring before the event loop cycles.
+       Removed all the old timer code that uses SIGALRM, and replace it
+               with the timer code from 2.3.2.  The conf timer bit the
+               dust along the way, since the event loop hasn't started
+               by the time the conf parser started.  It was never built
+               anyway, so not a big loss.
+       Made xinetd unlink its pidfile properly.
+               - Solar Designer
+       Enabled loadavg support for Darwin.
+       Remove the exit when user or group is specified and xinetd is not root.
+               Enables running xinetd as non-root again.
+       Fixed various portability issues:
+               - strerror for SunOS 4
+               - difftime for SunOS 4
+               - inet_aton for Solaris 2.5.1
+               - uint{16,32,64}_t for systems without them
+               - rlim_t for systems without them.
+       Moved compat.c into the portable library, where it belonged.
+               Added finer testing of the {e,f,g}cvt functions in autoconf.
+       Begin transition to combined IPv4/IPv6 support.  Add compatibility
+               code from OpenSSH into the portable library.
+       Made socket_type or protocol optional (only need to specify one)
+       Removed syslog()'s, replaced with internal msg().
+       Fixed a parsing bug when specified server is invalid.
+       Change the signal handling.  Signal handlers write their signal
+               to a pipe, which wakes up the main select(), and the
+               signal is then dealt with.
+       Removed the looping option.  The cps directive duplicated much
+               of the functionality.
+       Fixed a bug re-enabling internal wait services.
+       Continue syncing IPv4 and IPv6 code.
+               Made a flag to specify IPv4 or IPv6 based service.
+               Redirect currently only redirects between IPv4<->IPv4 or
+                       IPv6<->IPv6.  It should handle IPv4<->IPv6 and 
+                       vice versa
+       Fixed the reconfig case where a bind directive changes.
+       SIGHUP now reconfigures xinetd.  
+       SIGUSR1 now dumps the internal state.
+       SIGUSR2 still reconfigures xinetd, but will be deprecated in
+               future releases.
+       Fixed a warning of redefined SA macro with some tcp wrapper
+               header files.
+       Make the configuration keyword comparisons case insensitive.
+               This allows things like Service foo { blah } instead
+               of just service foo { blah }.
+       Merged IPv4 and IPv6 support.  The only difference between 
+               compiling with IPv6 support is that services default to
+               being IPv6.  Manually set the service to IPv6 (or IPv4)
+               with the IPv{4,6} service flags.
+        The only_from numeric address specification works for IPv6 addresses,
+               and mixing IPv4 style address specifications will now match
+               for IPv4 mapped addresses on IPv6 services.
+       Fixed an environment variable setting problem.
+       Fixed a misuse of the sio routines in the banner routines.  This
+               will probably fix a variety of bugs related to banners.
+       More code cleanups. -Steve Grubb.
+       Pass the expected size of the address structure used to bind()
+               calls rather than the total memory allocated.
+       Fix some compile errors and warnings on BSD/OS.
+       Prevent some possible unnecissary DNS lookups.
+       Makefiles now accept make -j.  This is only mildly useful at the
+               moment, since the main chunk of xinetd blocks on all the
+               libraries being built first, and the libraries are small
+               but somewhat serialized.
+       Fixed a problem with the access control on builtin services.
+               (Introduced in the development cycle)
+       Removed libpq. It is no longer needed. -Steve Grubb
+       Removed the %n processing from __sio_converter(). It is not used and 
+               would cause a core dump if it was. -Steve Grubb
+       Make the man page match the new signal change.  - Steve Grubb
+       Fix some potential problems with only_from access.
+       Start using "const".  Go const happy.
+       All services now essentially default to having the REUSE flag.
+               The -reuse option and the REUSE flag are now silently ignored.
+       When dumping service configs, print out the redir config information,
+               also fixes a hostname lookup problem when using systems
+               that have a too strict getnameinfo().
+               Also print the CPS directive information.
+       Print out symbolic system names that don't have strsignal(), but do
+               have sys_siglist[].
+       Fix a potential crasher in xtimer_add().
+       Add %q and %ll modifiers to the sio library for displaying quad_t's or
+               long long's.  
+       Restructure the argument parsing a little to reduce global memory usage.
+       Fixed bug in service parameter verification. Prior versions did not 
+               verify that all require attributes were specified.
+        Disable the service when a parse error is detected for its 
+               configuration. (Steve Grubb)
+2.3.5
+       Included patch from Trond at RedHat to check signal pipe if there are
+               no services running. 
+       Update the access_times parser to disable service if there is a parse 
+               error. Also corrected ti_add too. -Steve Grubb
+        Updated all parsers to propagate errors so service will be 
+               disabled. -Steve Grubb
+       Updated internal services to check the signal pipe 
+               periodically. -Steve Grubb
+       Updated sendsig to wait for termed children so zombies aren't created
+               and ports are clear to rebind to on hard_reconfig. -Steve Grubb
+        Included a patch from Hendrik Visage for a problem with ident.
+2.3.6
+       Updated only_from to 'and' both the remote address and the specified
+               portion if a network mask type address is used. -Steve Grubb
+       Updated explicit_mask to chose NUMERIC_ADDR if mask is 32. -Steve Grubb
+       Many parser updates. -Steve Grubb
+       Propogate default attributes even if not specified. log_on_success, 
+               log_on_failure, passenv were the main items affected by this 
+               problem. only_from and no_access now conform to this new
+               propogation technique. -Steve Grubb
+       Xremove now uses domain names in addition to ip addresses. -Steve Grubb
+       Moved sensor code into its own file and changed it to use timer
+               facility. -Steve Grubb
+       Reworked remote_addr check & addrlist_match to not cache IP addresses 
+               and corrected several algorithmic problems. -Steve Grubb
+       Off-by-one error corrected in pset_delete. -Steve Grubb
+       Updated attrfill to use IPv4 addresses if bind specified. -Steve Grubb
+       Fixed bug in libwrap code to check server better for NULL -Steve Grubb
+       Added better testing of configuration if NAMEINARGS flag 
+               is set. -Steve Grubb
+       Updated config.guess & config.sub. -Thomas Seyrat
+       Added an rpm spec file. -Steve Grubb
+       Removed sio/suite directory. It appears that key files have been 
+               deleted in the past so it no longer works. -Steve Grubb
+        Make the file descriptor buffer allocation dynamic.  This substantially
+                reduces xinetd's normal memory footprint (~760KB). -Rob Braun
+        Work around bugs in Mac OS X's getrlimit/setrlimit which causes them
+                to be almost unusable. -Rob Braun
+2.3.7
+       Added fixes or workarounds for issues introduced after 2.3.3
+               including the signal pipe leak into child processes (a
+               security hole). -Solar Designer
+       Made xinetd unlink its pidfile when there turns out to be no
+               services configured on reload. -Solar Designer
+2.3.8
+       Reworked redirect to better detect problems in its configuration. Also,
+               redirect now allows service names for port numbers. -Steve Grubb
+       Reworked attribute checking in confparse & updated attr.h. -Steve Grubb
+       Ensure that children have the default signal handlers installed.
+       Added support for DNS service registration ala Rendezvous.
+       Fixed some compile errors on Mac OS X, FreeBSD, and OpenBSD.
+       Added preliminary support for tcpmux -Philip Armstrong
+       Update the xinetd man page to document the -version option.
+       Now ignores the --with-inet6 compile option.
+               Services will default to IPv4 unless configured otherwise.
+       Bring back the inetd.conf parser in a different form.  Parse all
+               the xinetd config files first, then parse /etc/inetd.conf,
+               and add services from there (if it exists).
+               Use the -inetd_compat option to read inetd.conf.
+       IPv6 updates for bind_parser, only_from, and no_access. -Steve Grubb
+2.3.9
+       Fixed bug uncovered by IPv6 updates for bind parser. In the id_parser,
+               a test was being performed for uniqueness. It relied on the
+               address already being given.  However, the address may not be
+               known if more than one record came back from the getaddrinfo 
+               function call. -Steve Grubb
+       Added code to service_fill to resolve port if unspecified. -Steve Grubb
+       Consolidated duplicate services tests into check_entry. -Steve Grubb
+       Fixed a bug with access control & internal services.
+       Make sure we byteswap the value returned by time services.
+       Fix an omission with the tcpmux integration.
+       Fixed a race when there's 1 service configured and it is a wait service.
+2.3.10
+       Close the service descriptors on fork.  This only matters for internal
+               forking services, since anything that calls exec() will get
+               those closed automagically.  This will help reduce the file
+               discriptors used by the daemon when using some internal services
+       Fix a numbering bug with xinetd's internal flag representation that
+               was manifesting its self as all services being disabled upon
+               recieving a SIGUSR2 (hard reconfig)
+       Don't pass a hostname to dns registration calls, it'll pick a hostname
+               automagically.
+       Remove CLEANUP and other dead code.
+       Make sure tcp internal non-forking services close their filedescriptors.
+       Added syslog facilities for the xinetd log configuration to match SUS.
+               - Steve Grubb
+       Start reporting the Per Source value when dumping debugging output
+               - Steve Grubb
+       Correct the fake-getnameinfo.h to include appropriate macros.
+               - Steve Grubb
+       Up the default CPS value to 50 from 10.
+       Document the default CPS values in the xinetd.conf man page.
+       Fix a closing of the connection when there's an error handling the 
+               service.  - Steve Grubb
+       Fixed a bug in the includedir path where a reference was kept to
+               free()'d memory.
+       Fixed a bug in the consistency check mechanism where it would
+               report the signal pipe as a problem.
+       Clear memory before freeing it.  This isn't strictly necessary,
+               but aids in debugging.
+       Add the pid to debugging messages.
+       Remove access control calls for special services.  The access control
+               functions must always allow these services anyway.
+       Fixed a bug with reconfiguring services using the interface attribute.
+               -- Adam Lukosek
+       Fixed a bug with deallocating dns registrations.
+       Fixed a bug where tcp_wrappers would not identify an internal service
+               since the internal service has no executable.  -Steve Grubb
+       Sclose was being used on the config file descriptor.  Since sio
+               never touches the descriptor, it failed to close it.
+               - Steve Grubb
+       Fix a potential memory leak with bind_addr and service reconfig.
+               - Andrey Alekseyev
+       Fix a reconfig timing issue.
+               - Andrey Alekseyev
+2.3.11
+       Fix some compile time errors on Solaris
+       Fixed a bounds check in Sdone().  Patch from Dmitry V. Levin
+       Added FreeBSD loadavg support.  Patch from Vanilla I. Shu
+       TCPMUX parser updates. -Steve Grubb
+       TCPMUX was causing core dumps due to changes made in 2.3.10's 
+               child_process(), reverted changes. -Philip Armstrong
+       Remove RECORD logging option. -Steve Grubb
+       Change Sclose to make sure it always closes the fd. -Steve Grubb
+       Added better error handling to filelog.c. -Steve Grubb
+       Error messages now go to syslog instead of stderr in 
+               strparse.c. -Steve Grubb
+       Fixed memory leaks found with valgrind. -Steve Grubb
+       Correct problems with bind specified in the default 
+               section. -Steve Grubb
+       Use Sclose to close banner commands. -Jay Fenlason
+       Correct banner to match man pages. -Jay Fenlason
+2.3.12
+       Cleanup some signal handling if not defined. -MARUYAMA Shinichi
+       Make ident protocol work properly for multi-homed hosts. -Alan Sundell
+       Code cleanup for const warnings. -Steve Grubb
+       Make redirect protocol independent. -Cougar
+       Make reconfig iterate over all services. Some may be in "not started"
+               state and were being missed. -Steve Grubb
+       Make redirected, forking builtins, & tcpmux close all listening
+               descriptors so reconfig works. -Jay Fenlason
+       Add support for the IPV6_V6ONLY socket option.  Don't assume
+               a default setting, as the default seems to be in flux.
+       Address compare in readjust was wrong. Its now corrected to handle
+               each address family separately. -Steve Grubb
+       Add command line option to not fork. This will allow xinetd to be
+               started by init or daemontools. -Matthias Andree
+       Fixed a leak in reconfig. If log_type = file is used for a service and
+               SIGHUP is sent to xinetd, it leaked a file descriptor and 
+               44 bytes of memory per service using FILE. -Steve Grubb
+       Change all close() calls to Sclose() to prevent future 
+               problems. -Steve Grubb
+       Fixed bug if service name is unparsable and in an included directory
+               that caused xinetd to core dump. -Steve Grubb
+       Fixed bug where address lists had "version" uninitialized when the 
+               list used hostnames with no dots in the name. -Steve Grubb
+       Numerous memory leaks when parsing errors occurred. -Steve Grubb
+       Remove the servers and xadmin internal services.
+       Update addrlist_match to use the address part of the IPv6 address
+               structure. -Christof Meerwald 
+       Correct looping problems for udp connections rejected by the child
+               access controls. -Steve Grubb
+       Added TRAFFIC logging option to report total bytes in and out for a 
+               redirected service. -Christof Meerwald 
+       Correct a double-free condition if a retry was scheduled. -Steve Grubb
+       Add filename to parse messages. -Steve Grubb
+       Improve port error messages after parsing. -Steve Grubb
+       Sclose dump_fd if SIO error causes dump abort. -Steve Grubb
+       Smorefds wasn't allocating the proper amount of sio descriptor space
+               if the fd was > 5 over its last known fd. -Steve Grubb
+2.3.13
+       Add NULL entry to success_log_options to properly end the
+                nvlist. -Steve Grubb
+       Portability updates to libportable.h. -Matthias Andree
+       Occasionally Smorefds didn't allocate more fds as 
+               expected. -Jay Fenlason
+       Address list parsing considered the comma in factorized addresses to be
+               an error. Updated test to allow factorized address. -Steve Grubb
+       When parsing inet.conf, the filename wasn't being set for subsequent 
+               messages. -Steve Grubb
+       Fix addrlist_match to correctly handle IPv4 mapped IPv6 addresses.
+               -Christof Meerwald
+       Fixed a bug where reloading configuration would core dump if file 
+               logging was enabled in defaults and a connection existed when
+               SIGHUP was received. -Steve Grubb
+       If too many connections hit and exhausts the file descriptors 
+               such that accept fails, deactivate the service like the 
+               cps access control does. This problem was reported 
+               by David Cook. -Steve Grubb
+       Updated rpm.spec file and added default config files to contrib 
+               directory. -Steve Grubb
+       Allow group & user to be specified by numeric value. -Steve Grubb
+
+2.3.14
+       Applied patch from Art Haas for gcc 3.5 compat.
+       Flush the descriptor after writing a banner. -Jay Fenlason
+       Don't assume char is signed in the udp drain() function -Don Provan
+       If log remote user is on, a descriptor between 0-2 is likely to
+               be opened. Call msg_suspend before dup'ing socket to
+               avoid this bug. -Glen Johnson
+       Added confparse() RPC patch from RedHat's RHEL4 srpm.
+       Fixed some service release bugs with accesses to dangling pointers.
+       Updated BACKLOG to 64 from 7
+       Updated xconv.pl to understand ":" in inetd.conf files from
+               FreeBSD ports patch.
+       Added howl support for mdns advertising.
+       Added a libwrap service attribute to specify the service name
+               to check access via libwrap.
+       Make some type cleanups to fix some warnings.
+       Parse things as unsigned instead of signed where it makes sense.
+               Based on a patch from Tony Ernst.
+       Remove the <1024 port check for UDP builtin services.
+               This check has been rather antiquated for years.
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644 (file)
index 0000000..2d32df3
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,51 @@
+ORIGINAL LICENSE:
+This software is
+
+(c) Copyright 1992 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution and that this copyright notice is also included in any 
+redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
+
+Modifications:
+Version: 2.1.8.7-current
+Copyright 1998-2001 by Rob Braun
+
+Sensor Addition
+Version: 2.1.8.9pre14a
+Copyright 2001 by Steve Grubb
+
+This is an exerpt from an email I recieved from the original author, allowing
+xinetd as maintained by me, to use the higher version numbers:
+
+I appreciate your maintaining the version string guidelines as specified
+in the copyright. But I did not mean them to last as long as they did.
+
+So, if you want, you may use any 2.N.* (N >= 3) version string for future       
+xinetd versions that you release. Note that I am excluding the 2.2.* line;      
+using that would only create confusion. Naming the next release 2.3.0           
+would put to rest the confusion about 2.2.1 and 2.1.8.*.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..0f5c65d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,25 @@
+Generic install:
+./configure
+make
+make install
+xinetd/xconv.pl < /etc/inetd.conf > /tmp/xinetd.conf
+Edit the /etc/xinetd.conf file to your liking.
+
+Options to configure:
+--prefix=/path        to specify the directory prefix for installing xinetd.
+
+Check the README file for a description of the following options:
+--with-libwrap=[path] to specify that you would like libwrap compiled in.
+--with-loadavg
+
+Other options, such as what signals do what, where the default paths
+point for things like the config file and the debug dump file, default
+limitations, etc can all be configured in xinetd/config.h
+
+Please take a look at the config file before using it.  A default config
+file is in xinetd/sample.conf.  I can almost guarantee you'll have
+problems if you use the default config file.
+
+xconv.pl is a perl script that will convert your old inetd.conf file to
+xinetd.conf syntax.  This does a pretty decent job on most inetd.conf
+files I've encountered.  
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..7511efd
--- /dev/null
@@ -0,0 +1,123 @@
+CC = @CC@
+
+INSTALL_CMD = @INSTALL@
+
+RANLIB = @RANLIB@
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+DAEMONDIR = @sbindir@
+MANDIR = @mandir@
+topdir = @top_srcdir@
+
+LIBS = -lsio -lstr -lmisc -lxlog -lportable -lpset @LIBS@
+
+CFLAGS += @CFLAGS@ 
+DCFLAGS = -Wall -Wredundant-decls -W -Wfloat-equal -Wundef -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Wmissing-format-attribute -Wshadow -Wpointer-arith -g
+
+
+DEFS = @DEFS@
+
+SIO_DEFS  = @DEFS@
+MISC_DEFS = @DEFS@
+LIB_DEFS = @DEFS@ 
+PROG_DEFS = @DEFS@
+
+LIBMAKEDEFS = CC='$(CC)' CFLAGS='$(CFLAGS) -I../../include'
+PROGMAKEDEFS = CC='$(CC)' CFLAGS='$(CFLAGS) -I../libs/include' LDFLAGS='$(LDFLAGS) -L../libs/lib'
+DEBUGLIBMAKEDEFS = CC='$(CC)' CFLAGS='$(DCFLAGS) -I../../include'
+DEBUGMAKEDEFS = CC='$(CC)' CFLAGS='$(DCFLAGS) -I../libs/include' LDFLAGS='$(LDFLAGS) -L../libs/lib'
+
+MANDATORY_LIBS = portable sio str misc xlog pset 
+ALL_LIBS       = portable sio str misc xlog pset 
+
+build: makelibs makeprog
+
+debug: debugmakelibs debugmakeprog
+
+makeprog: makelibs
+       cd xinetd ; $(MAKE) $(PROGMAKEDEFS)
+
+debugmakeprog:
+       cd xinetd ; $(MAKE) $(DEBUGMAKEDEFS)
+
+makelibs: libmisc libportable libpset libsio libstr libxlog
+
+debugmakelibs: dlibmisc dlibportable dlibpset dlibsio dlibstr dlibxlog
+
+libmisc: libstr
+       cd libs/src/misc ; $(MAKE) $(LIBMAKEDEFS) install
+libportable:
+       cd libs/src/portable ; $(MAKE) $(LIBMAKEDEFS) install
+libpset:
+       cd libs/src/pset ; $(MAKE) $(LIBMAKEDEFS) install
+libsio: libportable
+       cd libs/src/sio ; $(MAKE) $(LIBMAKEDEFS) install
+libstr: libsio
+       cd libs/src/str ; $(MAKE) $(LIBMAKEDEFS) install
+libxlog: libsio libstr
+       cd libs/src/xlog ; $(MAKE) $(LIBMAKEDEFS) install
+
+dlibmisc: dlibstr
+       cd libs/src/misc ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+dlibportable:
+       cd libs/src/portable ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+dlibpset:
+       cd libs/src/pset ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+dlibsio: dlibportable
+       cd libs/src/sio ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+dlibstr: dlibsio
+       cd libs/src/str ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+dlibxlog: dlibsio dlibstr
+       cd libs/src/xlog ; $(MAKE) $(DEBUGLIBMAKEDEFS) install
+
+install: build
+       for i in $(DAEMONDIR) $(BINDIR) $(MANDIR)/man5 $(MANDIR)/man8 ; do \
+          test -d $$i || mkdir -p $$i ; done
+       $(INSTALL_CMD) -m 755 xinetd/xinetd $(DAEMONDIR)
+       $(INSTALL_CMD) -m 755 xinetd/itox $(DAEMONDIR)
+       $(INSTALL_CMD) -m 755 $(SRCDIR)/xinetd/xconv.pl $(DAEMONDIR)
+       $(INSTALL_CMD) -m 644 $(SRCDIR)/xinetd/xinetd.conf.man $(MANDIR)/man5/xinetd.conf.5
+       $(INSTALL_CMD) -m 644 $(SRCDIR)/xinetd/xinetd.log.man $(MANDIR)/man8/xinetd.log.8
+       $(INSTALL_CMD) -m 644 $(SRCDIR)/xinetd/xinetd.man $(MANDIR)/man8/xinetd.8
+       $(INSTALL_CMD) -m 644 $(SRCDIR)/xinetd/itox.8 $(MANDIR)/man8/itox.8
+       $(INSTALL_CMD) -m 644 $(SRCDIR)/xinetd/xconv.pl.8 $(MANDIR)/man8/xconv.pl.8
+       @echo "You must put your xinetd.conf in /etc/xinetd.conf"
+       @echo "There is a sample config file in xinetd/sample.conf and you can"
+       @echo "use xconv.pl to convert your old inetd.conf file to an xinetd format"
+
+uninstall:
+       rm -f $(DAEMONDIR)/xinetd
+       rm -f $(DAEMONDIR)/itox
+       rm -f $(DAEMONDIR)/xconv.pl
+       rm -f $(MANDIR)/man5/xinetd.conf.5
+       rm -f $(MANDIR)/man8/xinetd.log.8
+       rm -f $(MANDIR)/man8/xinetd.8
+       rm -f $(MANDIR)/man8/itox.8
+distclean: clean
+       rm -f config.cache config.log Makefile config.status xinetd/itox
+       rm -f config.h @srcdir@/libs/include/* @srcdir@/libs/man/*
+       for lib in $(ALL_LIBS) ; do \
+               cd @srcdir@/libs/src/$$lib ; $(MAKE) distclean ; \
+               cd ../../.. ; \
+       done
+       cd xinetd ; $(MAKE) distclean
+
+clean: cleanlibs cleanprog 
+       rm -f @srcdir@/libs/lib/*.a 
+
+cleanlibs:
+       for lib in $(ALL_LIBS) ; do \
+               cd @srcdir@/libs/src/$$lib ; $(MAKE) clean ; \
+               cd ../../.. ; \
+       done
+
+cleanprog:
+       cd xinetd ; $(MAKE) clean
+
+spotless: clean
+       rm -f @srcdir@/libs/include/*.h @srcdir@/libs/man/*.3
+       cd libs ; for i in lib include man ; do rm $$i/* ; done
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..8fa0e42
--- /dev/null
+++ b/README
@@ -0,0 +1,126 @@
+xinetd is a powerful replacement for inetd.
+Original site: http://www.xinetd.org
+xinetd has access control mechanisms, extensive logging capabilities,
+the ability to make services available based on time, can place
+limits on the number of servers that can be started, and has deployable
+defence mechanisms to protect against port scanners, among other things.
+
+There are a number of differences between xinetd and inetd.  The 
+largest difference to the end user is the config file.  xinetd's 
+config file format is more C like, and somewhat similar to bind 8's.
+
+*** NOTE ***
+xinetd's reconfig signal is now SIGHUP.  SIGUSR2 still works for now,
+but should be considered deprecated.  The state dump signal is now
+SIGUSR1.
+***      ***
+
+There are a couple of compile time options to xinetd:  
+--------------------------------------------------------------------------
+
+--with-libwrap  : This option to the configure script tells xinetd
+to compile in support for tcp wrappers.  You must already have libwrap
+installed on your system.  This option will have xinetd pay attention
+to your /etc/hosts.{allow|deny} files.  With this option turned on,
+xinetd will first look at your /etc/hosts.{allow|deny} files, then
+if access is granted, it goes through xinetd's internal access control
+mechanisms.  Note that xinetd passes the server name if there is one,
+otherwise it uses the service id, *not* the service name to libwrap - 
+this is a change from previous behaviour.
+
+--with-loadavg  : This option to the configure script tells xinetd
+to compile in support for the max_load configuration option.  This
+option allows you to have certain services disabled when the system
+load gets above a specified level.  This is highly operating system
+specific.  It currently has been tested on linux, and there is
+developmental support for solaris 2.6 and higher.
+
+--with-inet6    : Services default to IPv6 (PF_INET6) sockets.
+Now that IPv6 support is fully integrated into xinetd, this option
+is almost meaningless.  IPv6 sockets are available with the "IPv6"
+service flag, even without this option.
+
+--with-howl=PATH: Adds howl mdns advertising support to xinetd.
+PATH is the prefix where howl is installed, such as /usr/local,
+/usr, etc.  PATH is not optional.  configure will not automatically
+detect howl's installed location.
+
+Access Control:
+--------------------------------------------------------------------------
+As of xinetd 2.1.8.8pre3 there is a change in the handling of 
+names specified in the access control directives, only_from and
+no_access.  For numerical entries in these fields, nothing has
+changed.
+
+The way it used to be:  When xinetd started, it would lookup the
+name(s) specified.  It would then collect all the IP addresses
+associated with that name, and store them in the access control
+lists.  This led to problems of acls being out of date, and 
+access controls being messed up when names were specified.  It did
+have the advantage of not waiting for a lookup to happen when you
+connected.
+
+The way it is now:  xinetd keeps all the names you specify on the
+access control directives.  When a client attempts to connect to
+a service, a reverse lookup is performed on the client's IP address.
+The canonical name returned is compared with the specified names.
+If the first character of the name being specified in the config
+file is a '.', then all hosts within that domain are matched.
+For example, if I put .synack.net, all hosts with a reverse mapping
+that are in .synack.net domain, are matched.
+
+libwrap support:
+----------------------------------------------------------------------
+For libwrap access control, the access control is done by the
+server name for the service.  So, if you have an entry like this:
+service telnet
+{
+     ...
+        server = /usr/sbin/in.telnetd
+        ...
+}
+Your corresponding hosts.{allow|deny} entry would look something
+like this:
+in.telnetd: ALL
+
+However, many services don't have a "server".  Internal services
+and redirection services don't have a "server" line in the configuration
+file.  For these services, the service name is used.  For example:
+server telnet
+{
+       ...
+       redirect = 10.0.0.1 23
+       ...
+}
+Your hosts.{allow|deny} entry would look something like this:
+telnet: ALL
+
+So, in general, if a service has a "server" attribute to it, access
+control is performed based on that entry.  If a service does not have
+a "server" attribute, (internal and redirection services) then access
+control is based on the service name.
+This is only for libwrap access control.
+
+itox:
+--------------------------------------------------------------------------
+I will continue to keep itox in the distribution, and fix any bugs or
+compatibility issues that come to my attention, but I probably won't
+get around to adding features.  If someone else would like to pick this
+up, let me know and I'd be happy to incorporate changes.
+I have made a quick perl script (xconv.pl) to replace itox.  xconv.pl
+does a straight translation of inetd.conf file syntax to xinetd.conf.
+It handles tcpd correctly, warns on the use of rpc services, 
+sets the REUSE flag, and handles groups properly if your inetd.conf file 
+supports them.
+
+xinetd was originally written by panos@cs.colorado.edu.  At least one other
+version of xinetd has been seen floating around the net.  This version is
+being maintained by Rob Braun (bbraun@synack.net) and bug reports for this
+version should be directed there.
+
+Known bugs: On some BSD's, you may need to set 'groups = yes' in your services.
+If you need this, and you don't specify 'groups = yes', you'll get a log 
+message telling you it is needed, when you connect to a service.
+
+Bug reports/comments/suggestions/flames for this version should be sent
+to bbraun@synack.net
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..2553edb
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+Make IPv4 <-> IPv6 redirection work
+Re-add the -loop option to set the default state of the cps directive.
+Optimize the Makefiles for -j
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..6e6f32c
--- /dev/null
@@ -0,0 +1,27 @@
+dnl Check for variable types.
+dnl
+AC_DEFUN(XINETD_CHECK_TYPE,
+[AC_REQUIRE([AC_HEADER_STDC])dnl
+AC_MSG_CHECKING(for $1)
+AC_CACHE_VAL(xinetd_cv_type_$1,
+[AC_EGREP_CPP($1, [#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif], xinetd_cv_type_$1=yes, xinetd_cv_type_$1=no)])dnl
+AC_MSG_RESULT($xinetd_cv_type_$1)
+if test $xinetd_cv_type_$1 = no; then
+   AC_DEFINE($1, $2)
+fi
+])
diff --git a/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..ed2e03b
--- /dev/null
@@ -0,0 +1,1321 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+         if test $? = 0 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       rm -f $dummy.c $dummy.o $dummy.rel ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    alpha:OSF1:*:*)
+       if test $UNAME_RELEASE = "V4.0"; then
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+       fi
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       cat <<EOF >$dummy.s
+       .data
+\$Lformat:
+       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
+
+       .text
+       .globl main
+       .align 4
+       .ent main
+main:
+       .frame \$30,16,\$26,0
+       ldgp \$29,0(\$27)
+       .prologue 1
+       .long 0x47e03d80 # implver \$0
+       lda \$2,-1
+       .long 0x47e20c21 # amask \$2,\$1
+       lda \$16,\$Lformat
+       mov \$0,\$17
+       not \$1,\$18
+       jsr \$26,printf
+       ldgp \$29,0(\$26)
+       mov 0,\$16
+       jsr \$26,exit
+       .end main
+EOF
+       eval $set_cc_for_build
+       $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+       if test "$?" = 0 ; then
+               case `./$dummy` in
+                       0-0)
+                               UNAME_MACHINE="alpha"
+                               ;;
+                       1-0)
+                               UNAME_MACHINE="alphaev5"
+                               ;;
+                       1-1)
+                               UNAME_MACHINE="alphaev56"
+                               ;;
+                       1-101)
+                               UNAME_MACHINE="alphapca56"
+                               ;;
+                       2-303)
+                               UNAME_MACHINE="alphaev6"
+                               ;;
+                       2-307)
+                               UNAME_MACHINE="alphaev67"
+                               ;;
+                       2-1307)
+                               UNAME_MACHINE="alphaev68"
+                               ;;
+               esac
+       fi
+       rm -f $dummy.s $dummy
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit 0 ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit 0 ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD $dummy.c -o $dummy \
+         && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+               rm -f $dummy.c $dummy
+               echo rs6000-ibm-aix3.2.5
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit 0 ;;
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+                   if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+                   rm -f $dummy.c $dummy
+               fi ;;
+       esac
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3D:*:*:*)
+       echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:3*)
+       echo i386-pc-interix3
+       exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i386-pc-interix
+       exit 0 ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       rm -f $dummy.c
+       test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit 0 ;;               
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       rm -f $dummy.c
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit 0 ;;
+    i*86:*:5:[78]*)
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit 0 ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit 0 ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Darwin:*:*)
+       echo `uname -p`-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit 0 ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..f66130a
--- /dev/null
@@ -0,0 +1,133 @@
+#undef HAVE_STRERROR
+
+#undef HAVE_SETENV
+
+#undef HAVE_SYS_RESOURCE_H
+
+#undef HAVE_ISATTY
+
+#undef HAVE_UNISTD_H
+
+#undef HAVE_GETPAGESIZE
+
+#undef HAVE_MMAP
+
+#undef HAVE_MEMCPY
+
+#undef HAVE_WAITPID
+
+#undef HAVE_SIGVEC
+
+#undef HAVE_SETSID
+
+#undef HAVE_STRFTIME
+
+#undef HAVE_SYS_TYPES_H
+
+#undef HAVE_SYS_TERMIOS_H
+
+#undef HAVE_TERMIOS_H
+
+#undef HAVE_SYS_IOCTL_H
+
+#undef HAVE_RPC_RPC_H
+
+#undef HAVE_RPC_RPCENT_H
+
+#undef HAVE_SYS_SELECT_H
+
+#undef HAVE_SYS_FILE_H
+
+#undef HAVE_MACHINE_REG_H
+
+#undef HAVE_FTW_H
+
+#undef HAVE_NETDB_H
+
+#undef HAVE_LIBCRYPT
+
+#undef HAVE_ARPA_INET_H
+
+#undef HAVE_GRP_H
+
+#undef HAVE_RPC_PMAP_CLNT_H
+
+#undef HAVE_SYS_SOCKET_H
+
+#undef HAVE_SYS_SIGNAL_H
+
+#undef HAVE_STRSIGNAL
+
+#undef HAVE_SYS_SIGLIST
+
+#undef HAVE_CRYPT_H
+
+#undef HAVE_STDINT_H
+
+#undef HAVE_STDBOOL_H
+
+#undef HAVE_SYS_FILIO_H
+
+#undef HAVE_KSTAT_H
+
+#undef NO_INET_ATON
+
+#undef HAVE_STRUCT_ADDRINFO
+
+#undef HAVE_GAI_STRERROR
+
+#undef HAVE_FREEADDRINFO
+
+#undef HAVE_GETADDRINFO
+
+#undef HAVE_DIFFTIME
+
+#undef HAVE_GETNAMEINFO
+
+#undef HAVE_INET_NTOP
+
+#undef HAVE_STRUCT_IN6_ADDR
+
+#undef HAVE_STRUCT_SOCKADDR_IN6
+
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+#undef HAVE_FCVT
+
+#undef HAVE_ECVT
+
+#undef HAVE_GCVT
+
+#undef HAVE_STRCASECMP
+
+#undef HAVE_MDNS
+
+#undef HAVE_DNSREGISTRATION
+
+#undef HAVE_HOWL
+
+/* OS specific */
+#undef solaris
+
+/* Options */
+#undef HAVE_LIBWRAP
+#undef LIBWRAP
+
+#undef HAVE_LOADAVG
+
+#undef uint16_t
+#undef uint32_t
+#undef uint64_t
+#undef gid_t
+#undef uid_t
+#undef socklen_t
+#undef rlim_t
+
+/* Versioning Information */
+#define XINETD_VERSION "xinetd Version 2.3.14"
+#define MISC_VERSION   "MISC Version 1.2.2"
+#define PSET_VERSION   "PSET Version 1.2.0"
+#define SIO_VERSION    "SIO Version 1.6.2"
+#define STR_VERSION    "STR Version 1.4.1"
+#define TIMER_VERSION  "TIMER Version 1.2.2"
+#define XLOG_VERSION   "XLOG Version 1.1.2"
diff --git a/config.sub b/config.sub
new file mode 100755 (executable)
index 0000000..f365797
--- /dev/null
@@ -0,0 +1,1443 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-07'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+       | c4x | clipper \
+       | d10v | d30v | dsp16xx \
+       | fr30 \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | m32r | m68000 | m68k | m88k | mcore \
+       | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+       | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+       | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+       | mipsisa32 | mipsisa64 \
+       | mn10200 | mn10300 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armv*-* \
+       | avr-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c54x-* \
+       | clipper-* | cydra-* \
+       | d10v-* | d30v-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fr30-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | m32r-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+       | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+       | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+        pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2)
+               basic_machine=i686-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+        sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3d)
+               basic_machine=alpha-cray
+               os=-unicos
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       windows32)
+               basic_machine=i386-pc
+               os=-windows32-msvcrt
+               ;;
+        xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh3 | sh4 | sh3eb | sh4eb)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv9 | sparcv9b)
+               basic_machine=sparc-sun
+               ;;
+        cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       c4x*)
+               basic_machine=c4x-none
+               os=-coff
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto*)
+               os=-nto-qnx
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+        pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+        *-gould)
+               os=-sysv
+               ;;
+        *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+        *-sgi)
+               os=-irix
+               ;;
+        *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -vxsim* | -vxworks*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..416848d
--- /dev/null
+++ b/configure
@@ -0,0 +1,11419 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="xinetd/main.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB CPP EGREP LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+             localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-howl=PATH        Compile in howl support.
+                          PATH is the prefix where howl is installed,
+                          and is not optional.
+  --with-loadavg=PATH   Compile in loadavg support.
+
+  --with-inet6    Compile in ipv6 support. (obsolete)
+  --with-libwrap=PATH   Compile in libwrap (tcp_wrappers) support.
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+          test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=$`echo $ac_var`
+       echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_target_alias=$target_alias
+test "x$ac_cv_target_alias" = "x" &&
+  ac_cv_target_alias=$ac_cv_host_alias
+ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6
+target=$ac_cv_target
+target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+
+echo "$as_me:$LINENO: checking for main in -lcompat" >&5
+echo $ECHO_N "checking for main in -lcompat... $ECHO_C" >&6
+if test "${ac_cv_lib_compat_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcompat  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_compat_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_compat_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_compat_main" >&5
+echo "${ECHO_T}$ac_cv_lib_compat_main" >&6
+if test $ac_cv_lib_compat_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCOMPAT 1
+_ACEOF
+
+  LIBS="-lcompat $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5
+echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6
+if test "${ac_cv_search_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_gethostbyname=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_gethostbyname="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_gethostbyname" = no; then
+  for ac_lib in nsl socket resolv; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_gethostbyname="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_search_gethostbyname" >&6
+if test "$ac_cv_search_gethostbyname" != no; then
+  test "$ac_cv_search_gethostbyname" = "none required" || LIBS="$ac_cv_search_gethostbyname $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for library containing getnameinfo" >&5
+echo $ECHO_N "checking for library containing getnameinfo... $ECHO_C" >&6
+if test "${ac_cv_search_getnameinfo+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_getnameinfo=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getnameinfo ();
+int
+main ()
+{
+getnameinfo ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_getnameinfo="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_getnameinfo" = no; then
+  for ac_lib in nsl socket resolv; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getnameinfo ();
+int
+main ()
+{
+getnameinfo ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_getnameinfo="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_getnameinfo" >&5
+echo "${ECHO_T}$ac_cv_search_getnameinfo" >&6
+if test "$ac_cv_search_getnameinfo" != no; then
+  test "$ac_cv_search_getnameinfo" = "none required" || LIBS="$ac_cv_search_getnameinfo $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for library containing inet_ntop" >&5
+echo $ECHO_N "checking for library containing inet_ntop... $ECHO_C" >&6
+if test "${ac_cv_search_inet_ntop+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_inet_ntop=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_ntop ();
+int
+main ()
+{
+inet_ntop ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_inet_ntop="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_inet_ntop" = no; then
+  for ac_lib in nsl socket resolv; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_ntop ();
+int
+main ()
+{
+inet_ntop ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_inet_ntop="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_inet_ntop" >&5
+echo "${ECHO_T}$ac_cv_search_inet_ntop" >&6
+if test "$ac_cv_search_inet_ntop" != no; then
+  test "$ac_cv_search_inet_ntop" = "none required" || LIBS="$ac_cv_search_inet_ntop $LIBS"
+
+fi
+
+
+
+for ac_func in getnameinfo inet_ntop
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in difftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+echo "$as_me:$LINENO: checking for difftime in -lm" >&5
+echo $ECHO_N "checking for difftime in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_difftime+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char difftime ();
+int
+main ()
+{
+difftime ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_difftime=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_difftime=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_difftime" >&5
+echo "${ECHO_T}$ac_cv_lib_m_difftime" >&6
+if test $ac_cv_lib_m_difftime = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+fi
+done
+
+
+for ac_func in fcvt
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+echo "$as_me:$LINENO: checking for fcvt in -lm" >&5
+echo $ECHO_N "checking for fcvt in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_fcvt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char fcvt ();
+int
+main ()
+{
+fcvt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_fcvt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_fcvt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_fcvt" >&5
+echo "${ECHO_T}$ac_cv_lib_m_fcvt" >&6
+if test $ac_cv_lib_m_fcvt = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+fi
+done
+
+
+for ac_func in ecvt
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+echo "$as_me:$LINENO: checking for ecvt in -lm" >&5
+echo $ECHO_N "checking for ecvt in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_ecvt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char ecvt ();
+int
+main ()
+{
+ecvt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_ecvt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_ecvt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_ecvt" >&5
+echo "${ECHO_T}$ac_cv_lib_m_ecvt" >&6
+if test $ac_cv_lib_m_ecvt = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+fi
+done
+
+
+for ac_func in gcvt
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+echo "$as_me:$LINENO: checking for gcvt in -lm" >&5
+echo $ECHO_N "checking for gcvt in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_gcvt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gcvt ();
+int
+main ()
+{
+gcvt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_gcvt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_gcvt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_gcvt" >&5
+echo "${ECHO_T}$ac_cv_lib_m_gcvt" >&6
+if test $ac_cv_lib_m_gcvt = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+fi
+done
+
+
+echo "$as_me:$LINENO: checking for strerror" >&5
+echo $ECHO_N "checking for strerror... $ECHO_C" >&6
+if test "${ac_cv_func_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define strerror to an innocuous variant, in case <limits.h> declares strerror.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define strerror innocuous_strerror
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strerror (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strerror
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_strerror) || defined (__stub___strerror)
+choke me
+#else
+char (*f) () = strerror;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != strerror;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_strerror=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strerror=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strerror" >&5
+echo "${ECHO_T}$ac_cv_func_strerror" >&6
+if test $ac_cv_func_strerror = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for strcasecmp" >&5
+echo $ECHO_N "checking for strcasecmp... $ECHO_C" >&6
+if test "${ac_cv_func_strcasecmp+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define strcasecmp to an innocuous variant, in case <limits.h> declares strcasecmp.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define strcasecmp innocuous_strcasecmp
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strcasecmp (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strcasecmp
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strcasecmp ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_strcasecmp) || defined (__stub___strcasecmp)
+choke me
+#else
+char (*f) () = strcasecmp;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != strcasecmp;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_strcasecmp=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strcasecmp=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strcasecmp" >&5
+echo "${ECHO_T}$ac_cv_func_strcasecmp" >&6
+if test $ac_cv_func_strcasecmp = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRCASECMP 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for socket" >&5
+echo $ECHO_N "checking for socket... $ECHO_C" >&6
+if test "${ac_cv_func_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define socket to an innocuous variant, in case <limits.h> declares socket.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define socket innocuous_socket
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char socket (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef socket
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_socket) || defined (__stub___socket)
+choke me
+#else
+char (*f) () = socket;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != socket;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_socket" >&5
+echo "${ECHO_T}$ac_cv_func_socket" >&6
+if test $ac_cv_func_socket = yes; then
+  :
+else
+
+echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+
+echo "$as_me:$LINENO: checking for socket in -lnsl" >&5
+echo $ECHO_N "checking for socket in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_nsl_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_socket" >&6
+if test $ac_cv_lib_nsl_socket = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for inet_aton" >&5
+echo $ECHO_N "checking for inet_aton... $ECHO_C" >&6
+if test "${ac_cv_func_inet_aton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define inet_aton to an innocuous variant, in case <limits.h> declares inet_aton.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define inet_aton innocuous_inet_aton
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char inet_aton (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef inet_aton
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_aton ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_inet_aton) || defined (__stub___inet_aton)
+choke me
+#else
+char (*f) () = inet_aton;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != inet_aton;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_inet_aton=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_inet_aton" >&5
+echo "${ECHO_T}$ac_cv_func_inet_aton" >&6
+if test $ac_cv_func_inet_aton = yes; then
+  :
+else
+
+echo "$as_me:$LINENO: checking for inet_aton in -lnsl" >&5
+echo $ECHO_N "checking for inet_aton in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_inet_aton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_aton ();
+int
+main ()
+{
+inet_aton ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_nsl_inet_aton=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_aton" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_inet_aton" >&6
+if test $ac_cv_lib_nsl_inet_aton = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+else
+
+echo "$as_me:$LINENO: checking for inet_aton in -lsocket" >&5
+echo $ECHO_N "checking for inet_aton in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_inet_aton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_aton ();
+int
+main ()
+{
+inet_aton ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_inet_aton=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_inet_aton" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_inet_aton" >&6
+if test $ac_cv_lib_socket_inet_aton = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+
+echo "$as_me:$LINENO: checking for inet_aton in -lresolv" >&5
+echo $ECHO_N "checking for inet_aton in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_inet_aton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_aton ();
+int
+main ()
+{
+inet_aton ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_resolv_inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_resolv_inet_aton=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_inet_aton" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_inet_aton" >&6
+if test $ac_cv_lib_resolv_inet_aton = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRESOLV 1
+_ACEOF
+
+  LIBS="-lresolv $LIBS"
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define NO_INET_ATON 1
+_ACEOF
+
+fi
+
+fi
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for setenv" >&5
+echo $ECHO_N "checking for setenv... $ECHO_C" >&6
+if test "${ac_cv_func_setenv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define setenv to an innocuous variant, in case <limits.h> declares setenv.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define setenv innocuous_setenv
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char setenv (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef setenv
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char setenv ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_setenv) || defined (__stub___setenv)
+choke me
+#else
+char (*f) () = setenv;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != setenv;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_setenv=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_setenv=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_setenv" >&5
+echo "${ECHO_T}$ac_cv_func_setenv" >&6
+if test $ac_cv_func_setenv = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SETENV 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for strsignal" >&5
+echo $ECHO_N "checking for strsignal... $ECHO_C" >&6
+if test "${ac_cv_func_strsignal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define strsignal to an innocuous variant, in case <limits.h> declares strsignal.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define strsignal innocuous_strsignal
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strsignal (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strsignal
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strsignal ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_strsignal) || defined (__stub___strsignal)
+choke me
+#else
+char (*f) () = strsignal;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != strsignal;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_strsignal=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strsignal=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strsignal" >&5
+echo "${ECHO_T}$ac_cv_func_strsignal" >&6
+if test $ac_cv_func_strsignal = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRSIGNAL 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for sys_siglist in -lc" >&5
+echo $ECHO_N "checking for sys_siglist in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_sys_siglist+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sys_siglist ();
+int
+main ()
+{
+sys_siglist ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_sys_siglist=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_sys_siglist=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_sys_siglist" >&5
+echo "${ECHO_T}$ac_cv_lib_c_sys_siglist" >&6
+if test $ac_cv_lib_c_sys_siglist = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_SIGLIST 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for gai_strerror" >&5
+echo $ECHO_N "checking for gai_strerror... $ECHO_C" >&6
+if test "${ac_cv_func_gai_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define gai_strerror to an innocuous variant, in case <limits.h> declares gai_strerror.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define gai_strerror innocuous_gai_strerror
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char gai_strerror (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef gai_strerror
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gai_strerror ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_gai_strerror) || defined (__stub___gai_strerror)
+choke me
+#else
+char (*f) () = gai_strerror;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != gai_strerror;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_gai_strerror=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_gai_strerror=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gai_strerror" >&5
+echo "${ECHO_T}$ac_cv_func_gai_strerror" >&6
+if test $ac_cv_func_gai_strerror = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAI_STRERROR 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for freeaddrinfo" >&5
+echo $ECHO_N "checking for freeaddrinfo... $ECHO_C" >&6
+if test "${ac_cv_func_freeaddrinfo+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define freeaddrinfo to an innocuous variant, in case <limits.h> declares freeaddrinfo.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define freeaddrinfo innocuous_freeaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char freeaddrinfo (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef freeaddrinfo
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char freeaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_freeaddrinfo) || defined (__stub___freeaddrinfo)
+choke me
+#else
+char (*f) () = freeaddrinfo;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != freeaddrinfo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_freeaddrinfo=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_freeaddrinfo=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_freeaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_freeaddrinfo" >&6
+if test $ac_cv_func_freeaddrinfo = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREEADDRINFO 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for getaddrinfo" >&5
+echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6
+if test "${ac_cv_func_getaddrinfo+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define getaddrinfo innocuous_getaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char getaddrinfo (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getaddrinfo
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_getaddrinfo) || defined (__stub___getaddrinfo)
+choke me
+#else
+char (*f) () = getaddrinfo;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != getaddrinfo;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_getaddrinfo=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getaddrinfo=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6
+if test $ac_cv_func_getaddrinfo = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETADDRINFO 1
+_ACEOF
+
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/termios.h termios.h sys/ioctl.h sys/select.h rpc/rpc.h rpc/rpcent.h sys/file.h ftw.h machine/reg.h netdb.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+if test "${ac_cv_header_sys_resource_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for sys/resource.h" >&5
+echo $ECHO_N "checking for sys/resource.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_resource_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_resource_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_resource_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/resource.h usability" >&5
+echo $ECHO_N "checking sys/resource.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/resource.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/resource.h presence" >&5
+echo $ECHO_N "checking sys/resource.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/resource.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/resource.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/resource.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/resource.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/resource.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/resource.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/resource.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/resource.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/resource.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/resource.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for sys/resource.h" >&5
+echo $ECHO_N "checking for sys/resource.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_resource_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_sys_resource_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_resource_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_resource_h" >&6
+
+fi
+if test $ac_cv_header_sys_resource_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_RESOURCE_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_arpa_inet_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for arpa/inet.h" >&5
+echo $ECHO_N "checking for arpa/inet.h... $ECHO_C" >&6
+if test "${ac_cv_header_arpa_inet_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_arpa_inet_h" >&5
+echo "${ECHO_T}$ac_cv_header_arpa_inet_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking arpa/inet.h usability" >&5
+echo $ECHO_N "checking arpa/inet.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <arpa/inet.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking arpa/inet.h presence" >&5
+echo $ECHO_N "checking arpa/inet.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <arpa/inet.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: arpa/inet.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: arpa/inet.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: arpa/inet.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: arpa/inet.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: arpa/inet.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: arpa/inet.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: arpa/inet.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: arpa/inet.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: arpa/inet.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for arpa/inet.h" >&5
+echo $ECHO_N "checking for arpa/inet.h... $ECHO_C" >&6
+if test "${ac_cv_header_arpa_inet_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_arpa_inet_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_arpa_inet_h" >&5
+echo "${ECHO_T}$ac_cv_header_arpa_inet_h" >&6
+
+fi
+if test $ac_cv_header_arpa_inet_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_ARPA_INET_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_grp_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for grp.h" >&5
+echo $ECHO_N "checking for grp.h... $ECHO_C" >&6
+if test "${ac_cv_header_grp_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_grp_h" >&5
+echo "${ECHO_T}$ac_cv_header_grp_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking grp.h usability" >&5
+echo $ECHO_N "checking grp.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <grp.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking grp.h presence" >&5
+echo $ECHO_N "checking grp.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <grp.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: grp.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: grp.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: grp.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: grp.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: grp.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: grp.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: grp.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: grp.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: grp.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: grp.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: grp.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for grp.h" >&5
+echo $ECHO_N "checking for grp.h... $ECHO_C" >&6
+if test "${ac_cv_header_grp_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_grp_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_grp_h" >&5
+echo "${ECHO_T}$ac_cv_header_grp_h" >&6
+
+fi
+if test $ac_cv_header_grp_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_GRP_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_rpc_pmap_clnt_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for rpc/pmap_clnt.h" >&5
+echo $ECHO_N "checking for rpc/pmap_clnt.h... $ECHO_C" >&6
+if test "${ac_cv_header_rpc_pmap_clnt_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_rpc_pmap_clnt_h" >&5
+echo "${ECHO_T}$ac_cv_header_rpc_pmap_clnt_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking rpc/pmap_clnt.h usability" >&5
+echo $ECHO_N "checking rpc/pmap_clnt.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <rpc/pmap_clnt.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking rpc/pmap_clnt.h presence" >&5
+echo $ECHO_N "checking rpc/pmap_clnt.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <rpc/pmap_clnt.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: rpc/pmap_clnt.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: rpc/pmap_clnt.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for rpc/pmap_clnt.h" >&5
+echo $ECHO_N "checking for rpc/pmap_clnt.h... $ECHO_C" >&6
+if test "${ac_cv_header_rpc_pmap_clnt_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_rpc_pmap_clnt_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_rpc_pmap_clnt_h" >&5
+echo "${ECHO_T}$ac_cv_header_rpc_pmap_clnt_h" >&6
+
+fi
+if test $ac_cv_header_rpc_pmap_clnt_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_RPC_PMAP_CLNT_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_sys_socket_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for sys/socket.h" >&5
+echo $ECHO_N "checking for sys/socket.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_socket_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_socket_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_socket_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/socket.h usability" >&5
+echo $ECHO_N "checking sys/socket.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/socket.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/socket.h presence" >&5
+echo $ECHO_N "checking sys/socket.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/socket.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/socket.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/socket.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/socket.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/socket.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/socket.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/socket.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/socket.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/socket.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/socket.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for sys/socket.h" >&5
+echo $ECHO_N "checking for sys/socket.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_socket_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_sys_socket_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_socket_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_socket_h" >&6
+
+fi
+if test $ac_cv_header_sys_socket_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_SOCKET_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_sys_signal_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for sys/signal.h" >&5
+echo $ECHO_N "checking for sys/signal.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_signal_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_signal_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_signal_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/signal.h usability" >&5
+echo $ECHO_N "checking sys/signal.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/signal.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/signal.h presence" >&5
+echo $ECHO_N "checking sys/signal.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/signal.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/signal.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/signal.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/signal.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/signal.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/signal.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/signal.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/signal.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/signal.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/signal.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for sys/signal.h" >&5
+echo $ECHO_N "checking for sys/signal.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_signal_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_sys_signal_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_signal_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_signal_h" >&6
+
+fi
+if test $ac_cv_header_sys_signal_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_SIGNAL_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_crypt_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for crypt.h" >&5
+echo $ECHO_N "checking for crypt.h... $ECHO_C" >&6
+if test "${ac_cv_header_crypt_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_crypt_h" >&5
+echo "${ECHO_T}$ac_cv_header_crypt_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking crypt.h usability" >&5
+echo $ECHO_N "checking crypt.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <crypt.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking crypt.h presence" >&5
+echo $ECHO_N "checking crypt.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <crypt.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: crypt.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: crypt.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: crypt.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: crypt.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: crypt.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: crypt.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: crypt.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: crypt.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: crypt.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: crypt.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: crypt.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for crypt.h" >&5
+echo $ECHO_N "checking for crypt.h... $ECHO_C" >&6
+if test "${ac_cv_header_crypt_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_crypt_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_crypt_h" >&5
+echo "${ECHO_T}$ac_cv_header_crypt_h" >&6
+
+fi
+if test $ac_cv_header_crypt_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_CRYPT_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_stdint_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for stdint.h" >&5
+echo $ECHO_N "checking for stdint.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdint_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdint_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdint_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking stdint.h usability" >&5
+echo $ECHO_N "checking stdint.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <stdint.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking stdint.h presence" >&5
+echo $ECHO_N "checking stdint.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdint.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: stdint.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: stdint.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: stdint.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: stdint.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: stdint.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: stdint.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: stdint.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: stdint.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: stdint.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdint.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: stdint.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for stdint.h" >&5
+echo $ECHO_N "checking for stdint.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdint_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_stdint_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdint_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdint_h" >&6
+
+fi
+if test $ac_cv_header_stdint_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_STDINT_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for stdbool.h" >&5
+echo $ECHO_N "checking for stdbool.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking stdbool.h usability" >&5
+echo $ECHO_N "checking stdbool.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <stdbool.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking stdbool.h presence" >&5
+echo $ECHO_N "checking stdbool.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdbool.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: stdbool.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: stdbool.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: stdbool.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: stdbool.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: stdbool.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: stdbool.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: stdbool.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdbool.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: stdbool.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for stdbool.h" >&5
+echo $ECHO_N "checking for stdbool.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_stdbool_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6
+
+fi
+if test $ac_cv_header_stdbool_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_STDBOOL_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_sys_filio_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for sys/filio.h" >&5
+echo $ECHO_N "checking for sys/filio.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_filio_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_filio_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_filio_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/filio.h usability" >&5
+echo $ECHO_N "checking sys/filio.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/filio.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/filio.h presence" >&5
+echo $ECHO_N "checking sys/filio.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/filio.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/filio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/filio.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/filio.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/filio.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/filio.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/filio.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/filio.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/filio.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/filio.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for sys/filio.h" >&5
+echo $ECHO_N "checking for sys/filio.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_filio_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_sys_filio_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_filio_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_filio_h" >&6
+
+fi
+if test $ac_cv_header_sys_filio_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_FILIO_H 1
+_ACEOF
+
+fi
+
+
+if test "${ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for DNSServiceDiscovery/DNSServiceDiscovery.h" >&5
+echo $ECHO_N "checking for DNSServiceDiscovery/DNSServiceDiscovery.h... $ECHO_C" >&6
+if test "${ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h" >&5
+echo "${ECHO_T}$ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking DNSServiceDiscovery/DNSServiceDiscovery.h usability" >&5
+echo $ECHO_N "checking DNSServiceDiscovery/DNSServiceDiscovery.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking DNSServiceDiscovery/DNSServiceDiscovery.h presence" >&5
+echo $ECHO_N "checking DNSServiceDiscovery/DNSServiceDiscovery.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: DNSServiceDiscovery/DNSServiceDiscovery.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for DNSServiceDiscovery/DNSServiceDiscovery.h" >&5
+echo $ECHO_N "checking for DNSServiceDiscovery/DNSServiceDiscovery.h... $ECHO_C" >&6
+if test "${ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h" >&5
+echo "${ECHO_T}$ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h" >&6
+
+fi
+if test $ac_cv_header_DNSServiceDiscovery_DNSServiceDiscovery_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_DNSREGISTRATION 1
+_ACEOF
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MDNS 1
+_ACEOF
+
+fi
+
+
+
+
+# Check whether --with-howl or --without-howl was given.
+if test "${with_howl+set}" = set; then
+  withval="$with_howl"
+   OLDCFLAGS=$CFLAGS; CFLAGS="-I$withval/include/howl/ $CFLAGS";
+     OLDLDFLAGS=$LDFLAGS; LDFLAGS="-L$withval/lib/ $LDFLAGS";
+     OLDCPPFLAGS=$CPPFLAGS; CPPFLAGS="-I$withval/include/howl/ $CPPFLAGS";
+     as_ac_Header=`echo "ac_cv_header_$withval/include/howl/howl.h" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $withval/include/howl/howl.h" >&5
+echo $ECHO_N "checking for $withval/include/howl/howl.h... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $withval/include/howl/howl.h usability" >&5
+echo $ECHO_N "checking $withval/include/howl/howl.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$withval/include/howl/howl.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $withval/include/howl/howl.h presence" >&5
+echo $ECHO_N "checking $withval/include/howl/howl.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$withval/include/howl/howl.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $withval/include/howl/howl.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $withval/include/howl/howl.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $withval/include/howl/howl.h" >&5
+echo $ECHO_N "checking for $withval/include/howl/howl.h... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_HOWL 1
+_ACEOF
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MDNS 1
+_ACEOF
+
+else
+  CFLAGS=$OLDCFLAGS; LDFLAGS=$OLDLDFLAGS; CPPFLAGS=$OLDCPPFLAGS;
+fi
+
+
+     echo "$as_me:$LINENO: checking for sw_discovery_publish in -lhowl" >&5
+echo $ECHO_N "checking for sw_discovery_publish in -lhowl... $ECHO_C" >&6
+if test "${ac_cv_lib_howl_sw_discovery_publish+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhowl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sw_discovery_publish ();
+int
+main ()
+{
+sw_discovery_publish ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_howl_sw_discovery_publish=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_howl_sw_discovery_publish=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_howl_sw_discovery_publish" >&5
+echo "${ECHO_T}$ac_cv_lib_howl_sw_discovery_publish" >&6
+if test $ac_cv_lib_howl_sw_discovery_publish = yes; then
+  LIBS="-lhowl $LIBS"
+else
+
+        OLDLIBS=$LIBS; LIBS="-lpthread $LIBS";
+        echo "$as_me:$LINENO: checking for main in -lhowl" >&5
+echo $ECHO_N "checking for main in -lhowl... $ECHO_C" >&6
+if test "${ac_cv_lib_howl_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhowl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_howl_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_howl_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_howl_main" >&5
+echo "${ECHO_T}$ac_cv_lib_howl_main" >&6
+if test $ac_cv_lib_howl_main = yes; then
+  LIBS="-lhowl $LIBS"
+else
+  LIBS=$OLDLIBS
+fi
+
+
+fi
+
+
+fi;
+
+echo "$as_me:$LINENO: checking for uint16_t" >&5
+echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_uint16_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "uint16_t" >/dev/null 2>&1; then
+  xinetd_cv_type_uint16_t=yes
+else
+  xinetd_cv_type_uint16_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_uint16_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_uint16_t" >&6
+if test $xinetd_cv_type_uint16_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define uint16_t unsigned short
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for uint32_t" >&5
+echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_uint32_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "uint32_t" >/dev/null 2>&1; then
+  xinetd_cv_type_uint32_t=yes
+else
+  xinetd_cv_type_uint32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_uint32_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_uint32_t" >&6
+if test $xinetd_cv_type_uint32_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define uint32_t unsigned int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for uint64_t" >&5
+echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_uint64_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "uint64_t" >/dev/null 2>&1; then
+  xinetd_cv_type_uint64_t=yes
+else
+  xinetd_cv_type_uint64_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_uint64_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_uint64_t" >&6
+if test $xinetd_cv_type_uint64_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define uint64_t unsigned long long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for uid_t" >&5
+echo $ECHO_N "checking for uid_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_uid_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "uid_t" >/dev/null 2>&1; then
+  xinetd_cv_type_uid_t=yes
+else
+  xinetd_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_uid_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_uid_t" >&6
+if test $xinetd_cv_type_uid_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define uid_t unsigned int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for gid_t" >&5
+echo $ECHO_N "checking for gid_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_gid_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "gid_t" >/dev/null 2>&1; then
+  xinetd_cv_type_gid_t=yes
+else
+  xinetd_cv_type_gid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_gid_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_gid_t" >&6
+if test $xinetd_cv_type_gid_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define gid_t unsigned int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_socklen_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "socklen_t" >/dev/null 2>&1; then
+  xinetd_cv_type_socklen_t=yes
+else
+  xinetd_cv_type_socklen_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_socklen_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_socklen_t" >&6
+if test $xinetd_cv_type_socklen_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define socklen_t unsigned int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for rlim_t" >&5
+echo $ECHO_N "checking for rlim_t... $ECHO_C" >&6
+if test "${xinetd_cv_type_rlim_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_RLIM_T
+#include <sys/resource.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "rlim_t" >/dev/null 2>&1; then
+  xinetd_cv_type_rlim_t=yes
+else
+  xinetd_cv_type_rlim_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $xinetd_cv_type_rlim_t" >&5
+echo "${ECHO_T}$xinetd_cv_type_rlim_t" >&6
+if test $xinetd_cv_type_rlim_t = no; then
+   cat >>confdefs.h <<\_ACEOF
+#define rlim_t long long
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking for struct addrinfo" >&5
+echo $ECHO_N "checking for struct addrinfo... $ECHO_C" >&6
+if test "${ac_cv_have_struct_addrinfo+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+int
+main ()
+{
+ struct addrinfo s; s.ai_flags = AI_PASSIVE;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   ac_cv_have_struct_addrinfo="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_struct_addrinfo="no"
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_struct_addrinfo" >&5
+echo "${ECHO_T}$ac_cv_have_struct_addrinfo" >&6
+if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
+        cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_ADDRINFO 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for struct in6_addr" >&5
+echo $ECHO_N "checking for struct in6_addr... $ECHO_C" >&6
+if test "${ac_cv_have_struct_in6_addr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+int
+main ()
+{
+ struct in6_addr s; s.s6_addr[0] = 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   ac_cv_have_struct_in6_addr="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_struct_in6_addr="no"
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_struct_in6_addr" >&5
+echo "${ECHO_T}$ac_cv_have_struct_in6_addr" >&6
+if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
+        cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_IN6_ADDR 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for struct sockaddr_in6" >&5
+echo $ECHO_N "checking for struct sockaddr_in6... $ECHO_C" >&6
+if test "${ac_cv_have_struct_sockaddr_in6+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+int
+main ()
+{
+ struct sockaddr_in6 s; s.sin6_family = 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   ac_cv_have_struct_sockaddr_in6="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_struct_sockaddr_in6="no"
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_struct_sockaddr_in6" >&5
+echo "${ECHO_T}$ac_cv_have_struct_sockaddr_in6" >&6
+if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
+        cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for struct sockaddr_storage" >&5
+echo $ECHO_N "checking for struct sockaddr_storage... $ECHO_C" >&6
+if test "${ac_cv_have_struct_sockaddr_storage+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+main ()
+{
+ struct sockaddr_storage s;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   ac_cv_have_struct_sockaddr_storage="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_struct_sockaddr_storage="no"
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_struct_sockaddr_storage" >&5
+echo "${ECHO_T}$ac_cv_have_struct_sockaddr_storage" >&6
+if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
+        cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+_ACEOF
+
+fi
+
+
+case "$target_os" in
+
+solaris*)
+       cat >>confdefs.h <<\_ACEOF
+#define N0_SIGLIST 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define solaris 1
+_ACEOF
+
+
+       echo "$as_me:$LINENO: checking whether to compile in loadavg" >&5
+echo $ECHO_N "checking whether to compile in loadavg... $ECHO_C" >&6
+
+# Check whether --with-loadavg or --without-loadavg was given.
+if test "${with_loadavg+set}" = set; then
+  withval="$with_loadavg"
+   case "$withval" in
+               no)
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+                       ;;
+               yes)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+echo "$as_me:$LINENO: checking for main in -lkstat" >&5
+echo $ECHO_N "checking for main in -lkstat... $ECHO_C" >&6
+if test "${ac_cv_lib_kstat_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkstat  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_kstat_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_kstat_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_kstat_main" >&5
+echo "${ECHO_T}$ac_cv_lib_kstat_main" >&6
+if test $ac_cv_lib_kstat_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBKSTAT 1
+_ACEOF
+
+  LIBS="-lkstat $LIBS"
+
+fi
+
+                       if test "${ac_cv_header_kstat_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for kstat.h" >&5
+echo $ECHO_N "checking for kstat.h... $ECHO_C" >&6
+if test "${ac_cv_header_kstat_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_kstat_h" >&5
+echo "${ECHO_T}$ac_cv_header_kstat_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking kstat.h usability" >&5
+echo $ECHO_N "checking kstat.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <kstat.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking kstat.h presence" >&5
+echo $ECHO_N "checking kstat.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <kstat.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: kstat.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: kstat.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: kstat.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: kstat.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: kstat.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: kstat.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: kstat.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: kstat.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: kstat.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: kstat.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: kstat.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for kstat.h" >&5
+echo $ECHO_N "checking for kstat.h... $ECHO_C" >&6
+if test "${ac_cv_header_kstat_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_kstat_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_kstat_h" >&5
+echo "${ECHO_T}$ac_cv_header_kstat_h" >&6
+
+fi
+if test $ac_cv_header_kstat_h = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_KSTAT_H 1
+_ACEOF
+
+fi
+
+
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+               *)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+       ;;
+osf*)
+       LDFLAGS=-oldstyle_liblookup
+       echo "$as_me:$LINENO: checking whether to compile in loadavg" >&5
+echo $ECHO_N "checking whether to compile in loadavg... $ECHO_C" >&6
+
+# Check whether --with-loadavg or --without-loadavg was given.
+if test "${with_loadavg+set}" = set; then
+  withval="$with_loadavg"
+   case "$withval" in
+               no)
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+                       ;;
+               yes)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+               *)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+       ;;
+linux*|freebsd*)
+
+echo "$as_me:$LINENO: checking for main in -lcrypt" >&5
+echo $ECHO_N "checking for main in -lcrypt... $ECHO_C" >&6
+if test "${ac_cv_lib_crypt_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_crypt_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_main" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_main" >&6
+if test $ac_cv_lib_crypt_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+
+
+       echo "$as_me:$LINENO: checking whether to compile in loadavg" >&5
+echo $ECHO_N "checking whether to compile in loadavg... $ECHO_C" >&6
+
+# Check whether --with-loadavg or --without-loadavg was given.
+if test "${with_loadavg+set}" = set; then
+  withval="$with_loadavg"
+   case "$withval" in
+               no)
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+                       ;;
+               yes)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+               *)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+       ;;
+darwin* | "Mac OS"*)
+       ac_cv_prog_RANLIB="ranlib"
+       # AC_CHECK_FUNCS doesn't look in the proper header file...
+       cat >>confdefs.h <<\_ACEOF
+#define HAVE_ISATTY 1
+_ACEOF
+
+       CFLAGS="$CFLAGS -no-cpp-precomp"
+       echo "$as_me:$LINENO: checking whether to compile in loadavg" >&5
+echo $ECHO_N "checking whether to compile in loadavg... $ECHO_C" >&6
+
+# Check whether --with-loadavg or --without-loadavg was given.
+if test "${with_loadavg+set}" = set; then
+  withval="$with_loadavg"
+   case "$withval" in
+               no)
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+                       ;;
+               yes)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+               *)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+       ;;
+*bsdi*)
+       echo "$as_me:$LINENO: checking whether to compile in loadavg" >&5
+echo $ECHO_N "checking whether to compile in loadavg... $ECHO_C" >&6
+
+# Check whether --with-loadavg or --without-loadavg was given.
+if test "${with_loadavg+set}" = set; then
+  withval="$with_loadavg"
+   case "$withval" in
+               no)
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+                       ;;
+               yes)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define bsdi 1
+_ACEOF
+
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+               *)
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+                       cat >>confdefs.h <<\_ACEOF
+#define bsdi 1
+_ACEOF
+
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOADAVG 1
+_ACEOF
+
+                       ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+       ;;
+esac
+
+
+echo "$as_me:$LINENO: checking for crypt in -lc" >&5
+echo $ECHO_N "checking for crypt in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_crypt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char crypt ();
+int
+main ()
+{
+crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_crypt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_crypt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_crypt" >&5
+echo "${ECHO_T}$ac_cv_lib_c_crypt" >&6
+if test $ac_cv_lib_c_crypt = yes; then
+  :
+else
+
+ echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
+echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6
+if test "${ac_cv_lib_crypt_crypt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char crypt ();
+int
+main ()
+{
+crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_crypt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_crypt_crypt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6
+if test $ac_cv_lib_crypt_crypt = yes; then
+
+  LIBS="-lcrypt $LIBS"
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+fi
+
+fi
+
+
+echo "$as_me:$LINENO: checking for log10 in -lm" >&5
+echo $ECHO_N "checking for log10 in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_log10+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char log10 ();
+int
+main ()
+{
+log10 ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_log10=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_log10=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_log10" >&5
+echo "${ECHO_T}$ac_cv_lib_m_log10" >&6
+if test $ac_cv_lib_m_log10 = yes; then
+   LIBS="-lm $LIBS"
+fi
+
+
+echo "$as_me:$LINENO: checking whether to default to ipv6" >&5
+echo $ECHO_N "checking whether to default to ipv6... $ECHO_C" >&6
+
+# Check whether --with-inet6 or --without-inet6 was given.
+if test "${with_inet6+set}" = set; then
+  withval="$with_inet6"
+  echo "$as_me:$LINENO: result: ignored" >&5
+echo "${ECHO_T}ignored" >&6
+else
+  echo "$as_me:$LINENO: result: ignored" >&5
+echo "${ECHO_T}ignored" >&6
+fi;
+
+echo "$as_me:$LINENO: checking whether to use libwrap" >&5
+echo $ECHO_N "checking whether to use libwrap... $ECHO_C" >&6
+
+# Check whether --with-libwrap or --without-libwrap was given.
+if test "${with_libwrap+set}" = set; then
+  withval="$with_libwrap"
+   case "$withval" in
+       no)
+               echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+               ;;
+       yes)
+               echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+               echo "$as_me:$LINENO: checking for request_init in -lwrap" >&5
+echo $ECHO_N "checking for request_init in -lwrap... $ECHO_C" >&6
+if test "${ac_cv_lib_wrap_request_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lwrap  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char request_init ();
+int
+main ()
+{
+request_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_wrap_request_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_wrap_request_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_wrap_request_init" >&5
+echo "${ECHO_T}$ac_cv_lib_wrap_request_init" >&6
+if test $ac_cv_lib_wrap_request_init = yes; then
+
+                       cat >>confdefs.h <<\_ACEOF
+#define LIBWRAP 1
+_ACEOF
+
+                       WRAPLIBS="-lwrap"
+                       cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBWRAP 1
+_ACEOF
+
+fi
+
+               echo "$as_me:$LINENO: checking for yp_get_default_domain in -lnsl" >&5
+echo $ECHO_N "checking for yp_get_default_domain in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_yp_get_default_domain+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char yp_get_default_domain ();
+int
+main ()
+{
+yp_get_default_domain ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_yp_get_default_domain=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_nsl_yp_get_default_domain=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_yp_get_default_domain" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_yp_get_default_domain" >&6
+if test $ac_cv_lib_nsl_yp_get_default_domain = yes; then
+
+                       WRAPLIBS="$WRAPLIBS -lnsl"
+fi
+
+               LIBS="$WRAPLIBS $LIBS"
+               ;;
+       *)
+               echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+               cat >>confdefs.h <<\_ACEOF
+#define LIBWRAP 1
+_ACEOF
+
+               if test -d "$withval"; then
+                       WRAPLIBS="-L$withval -lwrap"
+               else
+                       WRAPLIBS="$withval"
+               fi
+               echo "$as_me:$LINENO: checking for yp_get_default_domain in -lnsl" >&5
+echo $ECHO_N "checking for yp_get_default_domain in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_yp_get_default_domain+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char yp_get_default_domain ();
+int
+main ()
+{
+yp_get_default_domain ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_yp_get_default_domain=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_nsl_yp_get_default_domain=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_yp_get_default_domain" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_yp_get_default_domain" >&6
+if test $ac_cv_lib_nsl_yp_get_default_domain = yes; then
+
+                       WRAPLIBS="$WRAPLIBS -lnsl"
+fi
+
+               OLDLIBS="$LIBS"
+               LIBS="$WRAPLIBS $LIBS"
+               cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+ int allow_severity; int deny_severity;
+int
+main ()
+{
+ hosts_access();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { { echo "$as_me:$LINENO: error: Could not find the $withval library.  You must first install tcp_wrappers." >&5
+echo "$as_me: error: Could not find the $withval library.  You must first install tcp_wrappers." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+               ;;
+       esac
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+fi;
+
+
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+       mmap private not fixed
+       mmap private fixed at somewhere currently unmapped
+       mmap private fixed at somewhere already mapped
+       mmap shared not fixed
+       mmap shared fixed at somewhere currently unmapped
+       mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the file system buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propagated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !STDC_HEADERS && !HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#if !HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h.  */
+# if !HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  if HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192  /* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+  char *data, *data2, *data3;
+  int i, pagesize;
+  int fd;
+
+  pagesize = getpagesize ();
+
+  /* First, make a file with some known garbage in it. */
+  data = (char *) malloc (pagesize);
+  if (!data)
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    *(data + i) = rand ();
+  umask (0);
+  fd = creat ("conftest.mmap", 0600);
+  if (fd < 0)
+    exit (1);
+  if (write (fd, data, pagesize) != pagesize)
+    exit (1);
+  close (fd);
+
+  /* Next, try to mmap the file at a fixed address which already has
+     something else allocated at it.  If we can, also make sure that
+     we see the same garbage.  */
+  fd = open ("conftest.mmap", O_RDWR);
+  if (fd < 0)
+    exit (1);
+  data2 = (char *) malloc (2 * pagesize);
+  if (!data2)
+    exit (1);
+  data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
+  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+                    MAP_PRIVATE | MAP_FIXED, fd, 0L))
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data2 + i))
+      exit (1);
+
+  /* Finally, make sure that changes to the mapped area do not
+     percolate back to the file as seen by read().  (This is a bug on
+     some variants of i386 svr4.0.)  */
+  for (i = 0; i < pagesize; ++i)
+    *(data2 + i) = *(data2 + i) + 1;
+  data3 = (char *) malloc (pagesize);
+  if (!data3)
+    exit (1);
+  if (read (fd, data3, pagesize) != pagesize)
+    exit (1);
+  for (i = 0; i < pagesize; ++i)
+    if (*(data + i) != *(data3 + i))
+      exit (1);
+  close (fd);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+
+
+for ac_func in isatty
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in memcpy
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in waitpid
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in sigvec
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in setsid
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in strftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# AC_CHECK_TYPE(R_OK,4)
+
+
+mkdir -p libs/src/misc
+mkdir -p libs/src/pset
+mkdir -p libs/src/sio
+mkdir -p libs/src/str
+mkdir -p libs/src/xlog
+mkdir -p libs/include
+mkdir -p libs/lib
+mkdir -p libs/man
+
+          ac_config_headers="$ac_config_headers config.h"
+
+                                                                                ac_config_files="$ac_config_files Makefile libs/src/misc/Makefile libs/src/pset/Makefile libs/src/sio/Makefile libs/src/str/Makefile libs/src/xlog/Makefile libs/src/portable/Makefile xinetd/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[    ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[      ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "libs/src/misc/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/misc/Makefile" ;;
+  "libs/src/pset/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/pset/Makefile" ;;
+  "libs/src/sio/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/sio/Makefile" ;;
+  "libs/src/str/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/str/Makefile" ;;
+  "libs/src/xlog/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/xlog/Makefile" ;;
+  "libs/src/portable/Makefile" ) CONFIG_FILES="$CONFIG_FILES libs/src/portable/Makefile" ;;
+  "xinetd/Makefile" ) CONFIG_FILES="$CONFIG_FILES xinetd/Makefile" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@target@,$target,;t t
+s,@target_cpu@,$target_cpu,;t t
+s,@target_vendor@,$target_vendor,;t t
+s,@target_os@,$target_os,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                    sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([   ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[        ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([   ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        # Do quote $f, to prevent DOS paths from being IFS'd.
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[      ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[     ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[     ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[     ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+cp config.h libs/include
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..1e01a59
--- /dev/null
@@ -0,0 +1,316 @@
+AC_INIT(xinetd/main.c)
+
+AC_CANONICAL_SYSTEM
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+AC_CHECK_LIB(compat, main)
+AC_SEARCH_LIBS(gethostbyname, nsl socket resolv)
+AC_SEARCH_LIBS(getnameinfo, nsl socket resolv)
+AC_SEARCH_LIBS(inet_ntop, nsl socket resolv)
+AC_CHECK_FUNCS(getnameinfo inet_ntop)
+AC_CHECK_FUNCS(difftime, ,
+   AC_CHECK_LIB(m, difftime))
+AC_CHECK_FUNCS(fcvt, ,
+   AC_CHECK_LIB(m, fcvt))
+AC_CHECK_FUNCS(ecvt, ,
+   AC_CHECK_LIB(m, ecvt))
+AC_CHECK_FUNCS(gcvt, ,
+   AC_CHECK_LIB(m, gcvt))
+
+AC_CHECK_FUNC(strerror, [AC_DEFINE(HAVE_STRERROR)])
+AC_CHECK_FUNC(strcasecmp, [AC_DEFINE(HAVE_STRCASECMP)])
+AC_CHECK_FUNC(socket, ,
+   AC_CHECK_LIB(socket, socket, ,
+      AC_CHECK_LIB(nsl, socket)))
+AC_CHECK_FUNC(inet_aton, ,
+       AC_CHECK_LIB(nsl, inet_aton, ,
+               AC_CHECK_LIB(socket, inet_aton, ,
+                       AC_CHECK_LIB(resolv, inet_aton, ,[AC_DEFINE(NO_INET_ATON)]))))
+AC_CHECK_FUNC(setenv,[AC_DEFINE(HAVE_SETENV)])
+AC_CHECK_FUNC(strsignal, [AC_DEFINE(HAVE_STRSIGNAL)])
+AC_CHECK_LIB(c, sys_siglist, [AC_DEFINE(HAVE_SYS_SIGLIST)])
+AC_CHECK_FUNC(gai_strerror,[AC_DEFINE(HAVE_GAI_STRERROR)])
+AC_CHECK_FUNC(freeaddrinfo,[AC_DEFINE(HAVE_FREEADDRINFO)])
+AC_CHECK_FUNC(getaddrinfo,[AC_DEFINE(HAVE_GETADDRINFO)])
+
+AC_CHECK_HEADERS(sys/types.h sys/termios.h termios.h sys/ioctl.h sys/select.h rpc/rpc.h rpc/rpcent.h sys/file.h ftw.h machine/reg.h netdb.h)
+AC_CHECK_HEADER(sys/resource.h, [AC_DEFINE(HAVE_SYS_RESOURCE_H)])
+AC_CHECK_HEADER(arpa/inet.h, [AC_DEFINE(HAVE_ARPA_INET_H)])
+AC_CHECK_HEADER(grp.h, [AC_DEFINE(HAVE_GRP_H)])
+AC_CHECK_HEADER(rpc/pmap_clnt.h, [AC_DEFINE(HAVE_RPC_PMAP_CLNT_H)])
+AC_CHECK_HEADER(sys/socket.h, [AC_DEFINE(HAVE_SYS_SOCKET_H)])
+AC_CHECK_HEADER(sys/signal.h, [AC_DEFINE(HAVE_SYS_SIGNAL_H)])
+AC_CHECK_HEADER(crypt.h, [AC_DEFINE(HAVE_CRYPT_H)])
+AC_CHECK_HEADER(stdint.h, [AC_DEFINE(HAVE_STDINT_H)])
+AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H)])
+AC_CHECK_HEADER(sys/filio.h, [AC_DEFINE(HAVE_SYS_FILIO_H)])
+AC_CHECK_HEADER(DNSServiceDiscovery/DNSServiceDiscovery.h, [AC_DEFINE(HAVE_DNSREGISTRATION) AC_DEFINE(HAVE_MDNS)])
+
+AC_ARG_WITH(howl, [  --with-howl=PATH        Compile in howl support.  
+                          PATH is the prefix where howl is installed,
+                          and is not optional.],
+   [ OLDCFLAGS=$CFLAGS; CFLAGS="-I$withval/include/howl/ $CFLAGS"; 
+     OLDLDFLAGS=$LDFLAGS; LDFLAGS="-L$withval/lib/ $LDFLAGS"; 
+     OLDCPPFLAGS=$CPPFLAGS; CPPFLAGS="-I$withval/include/howl/ $CPPFLAGS";
+     AC_CHECK_HEADER($withval/include/howl/howl.h, 
+        [AC_DEFINE(HAVE_HOWL) AC_DEFINE(HAVE_MDNS)], 
+        [CFLAGS=$OLDCFLAGS; LDFLAGS=$OLDLDFLAGS; CPPFLAGS=$OLDCPPFLAGS;]) 
+     AC_CHECK_LIB(howl, sw_discovery_publish, [LIBS="-lhowl $LIBS"], [
+        OLDLIBS=$LIBS; LIBS="-lpthread $LIBS"; 
+        AC_CHECK_LIB(howl, main, [LIBS="-lhowl $LIBS"],
+           [LIBS=$OLDLIBS]) 
+     ])
+   ])
+
+XINETD_CHECK_TYPE(uint16_t, unsigned short)
+XINETD_CHECK_TYPE(uint32_t, unsigned int)
+XINETD_CHECK_TYPE(uint64_t, unsigned long long)
+XINETD_CHECK_TYPE(uid_t, unsigned int)
+XINETD_CHECK_TYPE(gid_t, unsigned int)
+XINETD_CHECK_TYPE(socklen_t, unsigned int)
+XINETD_CHECK_TYPE(rlim_t, long long)
+
+AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
+        AC_TRY_COMPILE(
+                [
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+                ],
+                [ struct addrinfo s; s.ai_flags = AI_PASSIVE; ],
+                [ ac_cv_have_struct_addrinfo="yes" ],
+                [ ac_cv_have_struct_addrinfo="no" ]
+        )
+])
+if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
+        AC_DEFINE(HAVE_STRUCT_ADDRINFO)
+fi
+
+AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
+        AC_TRY_COMPILE(
+                [
+#include <sys/types.h>
+#include <netinet/in.h>
+                ],
+                [ struct in6_addr s; s.s6_addr[0] = 0; ],
+                [ ac_cv_have_struct_in6_addr="yes" ],
+                [ ac_cv_have_struct_in6_addr="no" ]
+        )
+])
+if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
+        AC_DEFINE(HAVE_STRUCT_IN6_ADDR)
+fi
+
+AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
+        AC_TRY_COMPILE(
+                [
+#include <sys/types.h>
+#include <netinet/in.h>
+                ],
+                [ struct sockaddr_in6 s; s.sin6_family = 0; ],
+                [ ac_cv_have_struct_sockaddr_in6="yes" ],
+                [ ac_cv_have_struct_sockaddr_in6="no" ]
+        )
+])
+if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
+        AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)
+fi
+
+AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [
+        AC_TRY_COMPILE(
+                [
+#include <sys/types.h>
+#include <sys/socket.h>
+                ],
+                [ struct sockaddr_storage s; ],
+                [ ac_cv_have_struct_sockaddr_storage="yes" ],
+                [ ac_cv_have_struct_sockaddr_storage="no" ]
+        )
+])
+if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
+        AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE)
+fi
+
+
+case "$target_os" in
+
+solaris*)
+       AC_DEFINE(N0_SIGLIST)
+       AC_DEFINE(solaris)
+
+       AC_MSG_CHECKING(whether to compile in loadavg)
+       AC_ARG_WITH(loadavg,
+       [  --with-loadavg[=PATH]   Compile in loadavg support.],
+       [ case "$withval" in
+               no)
+                       AC_MSG_RESULT(no)
+                       ;;
+               yes)
+                       AC_MSG_RESULT(yes)
+                       AC_CHECK_LIB(kstat, main)
+                       AC_CHECK_HEADER(kstat.h, [AC_DEFINE(HAVE_KSTAT_H)])
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+               *)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+       esac ], AC_MSG_RESULT(no) )
+       ;;
+osf*)
+       LDFLAGS=-oldstyle_liblookup
+       AC_MSG_CHECKING(whether to compile in loadavg)
+       AC_ARG_WITH(loadavg,,
+       [ case "$withval" in
+               no)
+                       AC_MSG_RESULT(no)
+                       ;;
+               yes)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+               *)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+       esac ], AC_MSG_RESULT(no))
+       ;;
+linux*|freebsd*)
+       AC_CHECK_LIB(crypt, main)
+
+       AC_MSG_CHECKING(whether to compile in loadavg)
+       AC_ARG_WITH(loadavg,,
+       [ case "$withval" in
+               no)
+                       AC_MSG_RESULT(no)
+                       ;;
+               yes)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+               *)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+       esac ], AC_MSG_RESULT(no))
+       ;;
+darwin* | "Mac OS"*)
+       ac_cv_prog_RANLIB="ranlib"
+       # AC_CHECK_FUNCS doesn't look in the proper header file...
+       AC_DEFINE(HAVE_ISATTY)
+       CFLAGS="$CFLAGS -no-cpp-precomp"
+       AC_MSG_CHECKING(whether to compile in loadavg)
+       AC_ARG_WITH(loadavg,,
+       [ case "$withval" in
+               no)
+                       AC_MSG_RESULT(no)
+                       ;;
+               yes)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+               *)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+       esac ], AC_MSG_RESULT(no))
+       ;;
+*bsdi*)
+       AC_MSG_CHECKING(whether to compile in loadavg)
+       AC_ARG_WITH(loadavg,,
+       [ case "$withval" in
+               no)
+                       AC_MSG_RESULT(no)
+                       ;;
+               yes)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(bsdi)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+               *)
+                       AC_MSG_RESULT(yes)
+                       AC_DEFINE(bsdi)
+                       AC_DEFINE(HAVE_LOADAVG)
+                       ;;
+       esac ], AC_MSG_RESULT(no))
+       ;;
+esac
+
+
+AC_CHECK_LIB(c, crypt, [:], [
+ AC_CHECK_LIB(crypt, crypt, [
+  LIBS="-lcrypt $LIBS"
+  AC_DEFINE(HAVE_LIBCRYPT) ], []) ])
+
+AC_CHECK_LIB(m, log10, [ LIBS="-lm $LIBS" ], [])
+
+AC_MSG_CHECKING(whether to default to ipv6)
+AC_ARG_WITH(inet6, [  --with-inet6    Compile in ipv6 support. (obsolete)],
+AC_MSG_RESULT(ignored), AC_MSG_RESULT(ignored) )
+
+AC_MSG_CHECKING(whether to use libwrap)
+AC_ARG_WITH(libwrap,
+[  --with-libwrap[=PATH]   Compile in libwrap (tcp_wrappers) support.],
+[ case "$withval" in
+       no)
+               AC_MSG_RESULT(no)
+               ;;
+       yes)
+               AC_MSG_RESULT(yes)
+               AC_CHECK_LIB(wrap, request_init, [
+                       AC_DEFINE(LIBWRAP)
+                       WRAPLIBS="-lwrap"
+                       AC_DEFINE(HAVE_LIBWRAP) ])
+               AC_CHECK_LIB(nsl, yp_get_default_domain, [ 
+                       WRAPLIBS="$WRAPLIBS -lnsl" ])
+               LIBS="$WRAPLIBS $LIBS"
+               ;;
+       *)
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(LIBWRAP)
+               if test -d "$withval"; then
+                       WRAPLIBS="-L$withval -lwrap"
+               else
+                       WRAPLIBS="$withval"
+               fi
+               AC_CHECK_LIB(nsl, yp_get_default_domain, [ 
+                       WRAPLIBS="$WRAPLIBS -lnsl" ])
+               OLDLIBS="$LIBS"
+               LIBS="$WRAPLIBS $LIBS"
+               AC_TRY_LINK([ int allow_severity; int deny_severity; ], 
+                       [ hosts_access(); ], [], [ AC_MSG_ERROR(Could not find the $withval library.  You must first install tcp_wrappers.) ])
+               ;;
+       esac ],
+       AC_MSG_RESULT(no)
+)
+
+AC_FUNC_MMAP
+
+AC_CHECK_FUNCS(isatty)
+AC_CHECK_FUNCS(memcpy)
+AC_CHECK_FUNCS(waitpid)
+AC_CHECK_FUNCS(sigvec)
+AC_CHECK_FUNCS(setsid)
+AC_CHECK_FUNCS(strftime)
+
+# AC_CHECK_TYPE(R_OK,4)
+
+
+mkdir -p libs/src/misc
+mkdir -p libs/src/pset
+mkdir -p libs/src/sio
+mkdir -p libs/src/str
+mkdir -p libs/src/xlog
+mkdir -p libs/include
+mkdir -p libs/lib
+mkdir -p libs/man
+
+AC_CONFIG_HEADER(config.h)
+AC_OUTPUT(Makefile libs/src/misc/Makefile libs/src/pset/Makefile libs/src/sio/Makefile libs/src/str/Makefile libs/src/xlog/Makefile libs/src/portable/Makefile xinetd/Makefile)
+
+cp config.h libs/include
diff --git a/contrib/empty.conf b/contrib/empty.conf
new file mode 100644 (file)
index 0000000..19101e0
--- /dev/null
@@ -0,0 +1,71 @@
+# This is an empty xinetd service configuration. To add a service to 
+# xinetd copy this file to /etc/xinetd.d giving it a name similar to the
+# service you are adding. Next change the service name before the curly
+# brace to match the name found in /etc/services. Then modify the following
+# attributes
+
+service empty
+{
+# This is for quick on or off of the service
+       disable         = no
+
+# The next attributes are mandatory for all services
+       id              =
+       type            =
+       wait            =
+       socket_type     =
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+       user            =
+       group           =
+       server          =
+       server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+       port            =
+
+# RPC based services must fill out these
+       rpc_version     =
+       rpc_number      =
+
+# Logging options
+       log_type        =
+       log_on_success  =
+       log_on_failure  =
+
+# Networking options
+       flags           =
+       bind            =
+       redirect        =
+       v6only          = 
+
+# Access restrictions
+       only_from       =
+       no_access       =
+       access_times    =
+       cps             =
+       instances       =
+       per_source      =
+       max_load        =
+       deny_time       =
+       mdns            = 
+
+# Environmental options
+       env             =
+       passenv         =
+       nice            =
+       umask           =
+       groups          = 
+       rlimit_as       =
+       rlimit_cpu      =
+       rlimit_data     =
+       rlimit_rss      =
+       rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd b/contrib/xinetd
new file mode 100755 (executable)
index 0000000..de0e294
--- /dev/null
@@ -0,0 +1,140 @@
+#!/bin/bash
+#
+# xinetd        This starts and stops xinetd.
+#
+# chkconfig: 345 65 50
+# description: xinetd is a powerful replacement for inetd. \
+#             xinetd has access control machanisms, extensive \
+#              logging capabilities, the ability to make services \
+#              available based on time, and can place \
+#              limits on the number of servers that can be started, \
+#              among other things.
+#
+# processname: /usr/sbin/xinetd
+# config: /etc/sysconfig/network
+# config: /etc/xinetd.conf
+# pidfile: /var/run/xinetd.pid
+
+PATH=/sbin:/bin:/usr/bin:/usr/sbin
+
+# Source function library.
+. /etc/init.d/functions
+
+# Get config.
+test -f /etc/sysconfig/network && . /etc/sysconfig/network
+
+# More config
+
+test -f /etc/sysconfig/xinetd && . /etc/sysconfig/xinetd
+
+# Check that networking is up.
+[ ${NETWORKING} = "yes" ] || exit 0
+
+[ -f /usr/sbin/xinetd ] || exit 1
+[ -f /etc/xinetd.conf ] || exit 1
+
+RETVAL=0
+
+if [ "$NETWORKING_IPV6" = "yes" ] && [ -x /usr/sbin/xinetd6 ]; then
+    prog="xinetd6"
+else
+    prog="xinetd"
+fi
+
+start(){
+    echo -n $"Starting $prog: "
+    # Need to get rid of localization for external services - 
+    # it doesn't make much sense to have i18n on the server side here
+
+    LANG=en_US
+    LC_TIME=en_US
+    LC_ALL=en_US
+    LC_MESSAGES=en_US
+    LC_NUMERIC=en_US
+    LC_MONETARY=en_US
+    LC_COLLATE=en_US
+    export LANG LC_TIME LC_ALL LC_MESSAGES LC_NUMERIC LC_MONETARY LC_COLLATE
+    unset HOME MAIL USER USERNAME
+    daemon $prog -stayalive -reuse -pidfile /var/run/xinetd.pid "$EXTRAOPTIONS"
+    RETVAL=$?
+    echo
+    touch /var/lock/subsys/xinetd
+    return $RETVAL
+}
+
+stop(){
+    echo -n $"Stopping $prog: "
+    killproc $prog
+    RETVAL=$?
+    echo
+    rm -f /var/lock/subsys/xinetd
+    return $RETVAL
+
+}
+
+reload(){
+    echo -n $"Reloading configuration: "       
+    killproc $prog -HUP
+    RETVAL=$?
+    echo
+    return $RETVAL
+}
+
+restart(){
+    stop
+    start
+}
+
+condrestart(){
+    [ -e /var/lock/subsys/xinetd ] && restart
+    return 0
+}
+
+dump(){
+    echo -n $"Dumping configuration: " 
+    killproc $prog -USR1
+    RETVAL=$?
+    echo
+    return $RETVAL
+}
+
+check(){
+    echo -n $"Performing Consistency Check: "  
+    /bin/kill -s IOT $prog
+    RETVAL=$?
+    echo
+    return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+    start)
+       start
+       ;;
+    stop)
+       stop
+       ;;
+    status)
+       status $prog
+       ;;
+    restart)
+       restart
+       ;;
+    reload)
+       reload
+       ;;
+    condrestart)
+       condrestart
+       ;;
+    dump)
+        dump
+        ;;
+    check)
+        check
+        ;;
+    *)
+       echo $"Usage: $0 {start|stop|status|restart|condrestart|reload|dump|check}"
+       RETVAL=1
+esac
+
+exit $RETVAL
diff --git a/contrib/xinetd.conf b/contrib/xinetd.conf
new file mode 100644 (file)
index 0000000..41904e0
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# This is the master xinetd configuration file. Settings in the
+# default section will be inherited by all service configurations
+# unless explicitly overridden in the service configuration. See
+# xinetd.conf in the man pages for a more detailed explanation of
+# these attributes.
+
+defaults
+{
+# The next two items are intended to be a quick access place to
+# temporarily enable or disable services.
+#
+#      enabled         =
+#      disabled        =
+
+# Define general logging characteristics.
+       log_type        = SYSLOG daemon info 
+       log_on_failure  = HOST
+       log_on_success  = PID HOST DURATION EXIT
+
+# Define access restriction defaults
+#
+#      no_access       =
+#      only_from       =
+#      max_load        = 0
+       cps             = 50 10
+       instances       = 50
+       per_source      = 10
+
+# Address and networking defaults
+#
+#      bind            =
+#      mdns            = yes
+       v6only          = no
+
+# setup environmental attributes
+#
+#      passenv         =
+       groups          = yes
+       umask           = 002
+
+# Generally, banners are not used. This sets up their global defaults
+#
+#      banner          =
+#      banner_fail     =
+#      banner_success  =
+}
+
+includedir /etc/xinetd.d
diff --git a/contrib/xinetd.d/chargen-dgram b/contrib/xinetd.d/chargen-dgram
new file mode 100644 (file)
index 0000000..e3a604a
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the udp/dgram chargen service.
+
+service chargen
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = chargen-dgram
+       type            = INTERNAL
+       wait            = yes
+       socket_type     = dgram
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/chargen-stream b/contrib/xinetd.d/chargen-stream
new file mode 100644 (file)
index 0000000..545cec9
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the tcp/stream chargen service.
+
+service chargen
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = chargen-stream
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/daytime-dgram b/contrib/xinetd.d/daytime-dgram
new file mode 100644 (file)
index 0000000..a0d83b1
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the udp/dgram daytime service.
+
+service daytime
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = daytime-dgram
+       type            = INTERNAL
+       wait            = yes
+       socket_type     = dgram
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/daytime-stream b/contrib/xinetd.d/daytime-stream
new file mode 100644 (file)
index 0000000..ab3e670
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the tcp/stream daytime service.
+
+service daytime
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = daytime-stream
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/discard-dgram b/contrib/xinetd.d/discard-dgram
new file mode 100644 (file)
index 0000000..e47a812
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the udp/dgram discard service.
+
+service discard
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = discard-dgram
+       type            = INTERNAL
+       wait            = yes
+       socket_type     = dgram
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/discard-stream b/contrib/xinetd.d/discard-stream
new file mode 100644 (file)
index 0000000..8feefae
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the tcp/stream discard service.
+
+service discard
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = discard-stream
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/echo-dgram b/contrib/xinetd.d/echo-dgram
new file mode 100644 (file)
index 0000000..48802af
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the udp/dgram echo service.
+
+service echo
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = echo-dgram
+       type            = INTERNAL
+       wait            = yes
+       socket_type     = dgram
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/echo-stream b/contrib/xinetd.d/echo-stream
new file mode 100644 (file)
index 0000000..6a4f46f
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the tcp/stream echo service.
+
+service echo
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = echo-stream
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/ftp-sensor b/contrib/xinetd.d/ftp-sensor
new file mode 100644 (file)
index 0000000..8e72be5
--- /dev/null
@@ -0,0 +1,70 @@
+# This is an example sensor running on the ftp port. Xinetd sensors are
+# a form of intrusion detection aimed at locating hosts that are trying
+# to access an unadvertised service. Once tripped, they are denied 
+# access to everything until the deny_time expires.
+
+service ftp
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = ftp-sensor
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+       flags           = SENSOR
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+       deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/tcpmux-server b/contrib/xinetd.d/tcpmux-server
new file mode 100644 (file)
index 0000000..43d04b3
--- /dev/null
@@ -0,0 +1,68 @@
+# This is the configuration of the tcpmux server. It must be enabled in
+# order to add any other tcpmux services.
+
+service tcpmux
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = tcpmux-server
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            = root
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/time-dgram b/contrib/xinetd.d/time-dgram
new file mode 100644 (file)
index 0000000..eac2066
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the udp/dgram time service. 
+
+service time
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = time-dgram
+       type            = INTERNAL
+       wait            = yes
+       socket_type     = dgram
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/contrib/xinetd.d/time-stream b/contrib/xinetd.d/time-stream
new file mode 100644 (file)
index 0000000..b4b81e4
--- /dev/null
@@ -0,0 +1,67 @@
+# This is the configuration for the tcp/stream time service.
+
+service time
+{
+# This is for quick on or off of the service
+       disable         = yes
+
+# The next attributes are mandatory for all services
+       id              = time-stream
+       type            = INTERNAL
+       wait            = no
+       socket_type     = stream
+#      protocol        =  socket type is usually enough
+
+# External services must fill out the following
+#      user            =
+#      group           =
+#      server          =
+#      server_args     =
+
+# External services not listed in /etc/services must fill out the next one
+#      port            =
+
+# RPC based services must fill out these
+#      rpc_version     =
+#      rpc_number      =
+
+# Logging options
+#      log_type        =
+#      log_on_success  =
+#      log_on_failure  =
+
+# Networking options
+#      flags           =
+#      bind            =
+#      redirect        =
+#      v6only          = 
+
+# Access restrictions
+#      only_from       =
+#      no_access       =
+#      access_times    =
+#      cps             = 50 10
+#      instances       = UNLIMITED
+#      per_source      = UNLIMITED
+#      max_load        = 0
+#      deny_time       = 120
+#      mdns            = yes 
+
+# Environmental options
+#      env             =
+#      passenv         =
+#      nice            = 0
+#      umask           = 022
+#      groups          = yes
+#      rlimit_as       =
+#      rlimit_cpu      =
+#      rlimit_data     =
+#      rlimit_rss      =
+#      rlimit_stack    =
+
+# Banner options. (Banners aren't normally used)
+#      banner          =
+#      banner_success  =
+#      banner_fail     =
+}
+
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/include/.cvsignore b/libs/include/.cvsignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/lib/.cvsignore b/libs/lib/.cvsignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/man/.cvsignore b/libs/man/.cvsignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/src/misc/COPYRIGHT b/libs/src/misc/COPYRIGHT
new file mode 100644 (file)
index 0000000..7c11bad
--- /dev/null
@@ -0,0 +1,33 @@
+This software is
+
+(c) Copyright 1992 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution and that this copyright notice is also included in any 
+redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
+Modifications:
+Version: 2.1.8.7-current
+Copyright 1998-2001 by Rob Braun
diff --git a/libs/src/misc/Makefile.in b/libs/src/misc/Makefile.in
new file mode 100644 (file)
index 0000000..a84127d
--- /dev/null
@@ -0,0 +1,105 @@
+# (c) Copyright 1992 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+#
+# Based on Library makefile template: *Revision: 1.15 *
+#
+
+NAME                   = misc
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = $(SRCDIR)/misc.h $(SRCDIR)/m_env.h
+SOURCES                        = misc.c m_env.c
+OBJECTS                        = misc.o m_env.o
+
+MANFILES               = $(SRCDIR)/misc.3 $(SRCDIR)/m_env.3
+INCLUDEFILES           = $(HEADERS)
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+#
+#LIBDIR                        = $(HOME)/.links/libraries/$(ARCH)
+#MANDIR                        = $(HOME)/.links/manpages/man3
+#INCLUDEDIR            = $(HOME)/.links/includes
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+#
+# Possible flags:
+#     -DOLD_DIR         : must include <sys/dir.h> instead of <dirent.h>
+#
+
+DEBUG                  = -g                            # -g or -O
+
+CPP_DEFS               = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS) -I$(INCLUDEDIR)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O lib
+       mv $(LIBNAME) $(LIBDIR)/optimized
+
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               ${RANLIB} $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+               for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
+               echo Installed $(MANFILES) to $(MANDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+       a=`pwd` ; cd $(MANDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+spotless: clean uninstall
+
+distclean: clean
+       rm -f Makefile
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+misc.o:                misc.h
+m_env.o:       m_env.h misc.h
+
diff --git a/libs/src/misc/README b/libs/src/misc/README
new file mode 100644 (file)
index 0000000..d3740d1
--- /dev/null
@@ -0,0 +1,14 @@
+
+
+This library is made of 3 parts:
+       ftwx, misc, env
+
+env is a collection of environment processing functions.
+misc is a collection of miscellaneous functions.
+ftwx is a replacement for the standard ftw(3) function.
+
+When installing this library you may need to define the following
+flags in the Makefile:
+       OLD_DIR if your system does not have the file /usr/include/dirent.h
+       __FTWX_NO_FTW if your system does not have the ftw(3) function
+
diff --git a/libs/src/misc/install-sh b/libs/src/misc/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/src/misc/m_env.3 b/libs/src/misc/m_env.3
new file mode 100644 (file)
index 0000000..db6d1c3
--- /dev/null
@@ -0,0 +1,162 @@
+.\"(c) Copyright 1992 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: m_env.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH ENV 3L "20 October 1992"
+.SH NAME
+env_create, env_destroy, env_make, env_addvar, env_addstr, env_remvar, env_lookup, env_getvars -- environment manipulation functions
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "m_env.h"
+.LP
+.ft B
+env_h env_create( env )
+env_h env ;
+.LP
+.ft B
+void env_destroy( env )
+env_h env ;
+.LP
+.ft B
+env_h env_make( env_strings )
+char **env_strings ;
+.LP
+.ft B
+int env_addvar( env, from_env, var )
+env_h env ;
+env_h from_env ;
+char *var ;
+.LP
+.ft B
+int env_addstr( env, str )
+env_h env ;
+char *str ;
+.LP
+.ft B
+int env_remvar( env, var )
+env_h env ;
+char *var ;
+.LP
+.ft B
+char **env_getvars( env )
+env_h env ;
+.SH DESCRIPTION
+This library handles environments. An environment is a set of strings
+of the form 
+.I "name=value".
+In the following, we will use the term string as a synonym of
+NUL-terminated array of 
+.I char.
+.LP
+.B env_create()
+creates a new environment. The new environment will be empty unless
+the argument
+.I env
+is not
+.SB ENV_NULL.
+In that case, the new environment will be a duplicate of 
+.I env
+(i.e. they will contain the same strings).
+.LP
+.B env_destroy()
+destroys the specified environment.
+.LP
+.B env_make()
+creates a new environment which includes the
+.I env_strings.
+.I env_strings
+should be a NULL-terminated array of strings.
+.LP
+.B env_addvar()
+adds the specified variable
+.I var
+to
+.I env.
+The variable value is obtained from the environment
+.I from_env.
+If the variable exists already in 
+.I env
+the old value is replaced with the new value.
+.LP
+.B env_addstr()
+adds a string of the form
+.I "name=value"
+to
+.I env.
+.LP
+.B env_remvar()
+removes the specified variable
+.I var
+from the environment
+.I env.
+.LP
+.B env_lookup()
+searches
+.I env
+for variable
+.I var.
+It returns a string of the form
+.I "name=value"
+where
+.I name
+is the name of the variable
+(i.e. it is equal to
+.I var).
+.LP
+.B env_getvars
+returns a NULL-terminated array of strings of the form
+.I "name=value".
+.SH "RETURN VALUES"
+In case of error, all calls will place an error code in the global variable
+.I env_errno.
+Possible error codes:
+.TP 15
+.SB ENV_ENOMEM
+out of memory
+.TP
+.SB ENV_EBADVAR
+variable is not in environment
+.TP
+.SB ENV_EBADSTRING
+string is not well-formed (i.e. is not of the form \fIname=value\fR).
+.LP
+.B env_create()
+returns a handle or 
+.SM ENV_NULL
+if it fails.
+.LP
+.B env_make()
+returns a handle or 
+.SM ENV_NULL
+if it fails.
+.LP
+.B env_addvar()
+returns
+.SM ENV_OK
+on success or
+.SM ENV_ERR
+on failure.
+.LP
+.B env_addstr()
+returns
+.SM ENV_OK
+on success or
+.SM ENV_ERR
+on failure.
+.LP
+.B env_remvar()
+returns
+.SM ENV_OK
+on success or
+.SM ENV_ERR
+if the variable is not part of the environment.
+.LP
+.B env_loopkup()
+returns a string on success or
+.SM NULL
+on failure.
+.SH "SEE ALSO"
+environ(5)
diff --git a/libs/src/misc/m_env.c b/libs/src/misc/m_env.c
new file mode 100644 (file)
index 0000000..090811b
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "m_env.h"
+#include "str.h"
+
+
+typedef struct __env env_s ;
+
+#define INITIAL_VARS            20
+#define INCREASE                10
+
+
+int env_errno ;
+
+static char **lookup( const env_h env, const char *var, 
+       register unsigned int len );
+
+static env_s *alloc_env( unsigned max_vars )
+{
+   env_s *ep ;
+   unsigned size ;
+   char **pointers ;
+
+   ep = (env_s *) malloc( sizeof( env_s ) ) ;
+   if ( ep == ENV_NULL )
+   {
+      env_errno = ENV_ENOMEM ;
+      return( ENV_NULL ) ;
+   }
+
+   memset( ep, 0, sizeof( env_s ) );
+   size = ( max_vars + 1 ) * sizeof( char * ) ;
+   pointers = (char **) malloc( size ) ;
+   if ( pointers == NULL )
+   {
+      free( (char *)ep ) ;
+      env_errno = ENV_ENOMEM ;
+      return( ENV_NULL ) ;
+   }
+   (void) memset( (char *)pointers, 0, size ) ;
+
+   ep->vars = pointers ;
+   ep->max_vars = max_vars ;
+   ep->n_vars = 0 ;
+   return( ep ) ;
+}
+
+
+env_h env_create( const env_h init_env )
+{
+   unsigned u ;
+   env_s *ep ;
+   unsigned max_vars ;
+
+   if ( init_env == ENV_NULL )
+      max_vars = INITIAL_VARS ;
+   else
+      max_vars = init_env->n_vars + 5 ;
+   
+   ep = alloc_env( max_vars ) ;
+   if ( ep == NULL )
+   {
+      env_errno = ENV_ENOMEM ;
+      return( ENV_NULL ) ;
+   }
+
+   if ( init_env == ENV_NULL )
+      return( ep ) ;
+
+   for ( u = 0, ep->n_vars = 0 ; u < init_env->n_vars ; u++, ep->n_vars++ )
+   {
+      ep->vars[ ep->n_vars ] = new_string( init_env->vars[ u ] ) ;
+      if ( ep->vars[ ep->n_vars ] == NULL )
+      {
+         env_destroy( ep ) ;
+         env_errno = ENV_ENOMEM ;
+         return( ENV_NULL ) ;
+      }
+   }
+   return( ep ) ;
+}
+
+
+void env_destroy( env_h env )
+{
+   unsigned u ;
+
+   for ( u = 0 ; u < env->n_vars ; u++ )
+      free( env->vars[ u ] ) ;
+   free( (char *)env->vars ) ;
+   free( (char *)env ) ;
+}
+
+
+env_h env_make( char **env_strings )
+{
+   env_s *ep ;
+   char **pp ;
+
+   for ( pp = env_strings ; *pp ; pp++ ) ;
+
+   ep = alloc_env( (unsigned) (pp-env_strings) ) ;
+   if ( ep == NULL )
+   {
+      env_errno = ENV_ENOMEM ;
+      return( ENV_NULL ) ;
+   }
+
+   for ( pp = env_strings ; *pp ; pp++ )
+   {
+      char *p = new_string( *pp ) ;
+
+      if ( p == NULL )
+      {
+         env_destroy( ep ) ;
+         env_errno = ENV_ENOMEM ;
+         return( ENV_NULL ) ;
+      }
+      ep->vars[ ep->n_vars++ ] = p ;
+   }
+   return( ep ) ;
+}
+
+
+char *env_lookup( env_h env, const char *var )
+{
+   char **pp = lookup( env, var, strlen( var ) ) ;
+
+   return( ( pp == NULL ) ? NULL : *pp ) ;
+}
+
+
+static char **lookup( const env_h env, const char * var, 
+       register unsigned int len )
+{
+   char **pp ;
+
+   for ( pp = env->vars ; *pp ; pp++ )
+      if ( strncmp( *pp, var, len ) == 0 && (*pp)[ len ] == '=' )
+         return( pp ) ;
+   return( NULL ) ;
+}
+
+
+static int grow( env_s *ep )
+{
+   char **new_vars ;
+   unsigned new_max_vars ;
+   unsigned new_size ;
+   new_max_vars = ep->max_vars + INCREASE ;
+   new_size = ( new_max_vars+1 ) * sizeof( char * ) ;
+   new_vars = (char **) realloc( (char *)ep->vars, new_size ) ;
+   if ( new_vars == NULL )
+      return( ENV_ERR ) ;
+
+   ep->vars = new_vars ;
+   ep->max_vars = new_max_vars ;
+   
+   memset(&ep->vars[ep->n_vars], 0, new_size - (ep->n_vars * sizeof(char *)));
+   return( ENV_OK ) ;
+}
+
+
+/*
+ * Add the variable string to the given environment.
+ */
+static int addstring( env_s *ep, const char *var_string, unsigned int len )
+{
+   char **pp ;
+   char *p ;
+
+   p = new_string( var_string ) ;
+   if ( p == NULL )
+      return( ENV_ERR ) ;
+      
+   pp = lookup( ep, var_string, len ) ;
+   if ( pp == NULL )
+   {
+      if ( ep->n_vars >= ep->max_vars && grow( ep ) == ENV_ERR )
+      {
+         free( p ) ;
+         env_errno = ENV_ENOMEM ;
+         return( ENV_ERR ) ;
+      }
+      ep->vars[ ep->n_vars++ ] = p ;
+      ep->vars[ ep->n_vars ] = NULL;
+   }
+   else
+   {
+      free( *pp ) ;
+      *pp = p ;
+   }
+   return( ENV_OK ) ;
+}
+
+
+int env_addvar( env_h env, env_h from_env, char *var_name )
+{
+   char *var_string = env_lookup( from_env, var_name ) ;
+
+   if ( var_string == NULL )
+   {
+      env_errno = ENV_EBADVAR ;
+      return( ENV_ERR ) ;
+   }
+
+   return( addstring( env, var_string, strlen( var_name ) ) ) ;
+}
+
+
+int env_addstr( env_h env, char *var_string )
+{
+   char *p = strchr( var_string, '=' ) ;
+
+   if ( p == NULL )
+   {
+      env_errno = ENV_EBADSTRING ;
+      return( ENV_ERR ) ;
+   }
+
+   return( addstring( env, var_string, (unsigned int)(p-var_string) ) ) ;
+}
+
+
+#ifdef notdef
+static int comparator( char **p1, char **p2 )
+{
+   return( strcmp( *p1, *p2 ) ) ;
+}
+
+
+void env_sort( env_h env )
+{
+   qsort( (char *)env->vars, env->n_vars, sizeof( char * ), comparator ) ;
+}
+#endif
+
diff --git a/libs/src/misc/m_env.h b/libs/src/misc/m_env.h
new file mode 100644 (file)
index 0000000..9dada5b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef __M_ENV_H
+#define __M_ENV_H
+
+/*
+ * $Id: m_env.h,v 1.2 2003/03/09 19:27:08 steveg Exp $
+ */
+
+struct __env
+{
+   unsigned max_vars ;
+   unsigned n_vars ;
+   char **vars ;
+} ;
+
+typedef struct __env *env_h ;
+
+#define ENV_NULL                  ((env_h)0)
+
+/*
+ * Return values
+ */
+#define ENV_ERR                   (-1)
+#define ENV_OK                    0
+
+/*
+ * Error codes
+ */
+#define ENV_ENOMEM                1
+#define ENV_EBADVAR               2
+#define ENV_EBADSTRING            3
+
+
+env_h env_create ( const env_h ) ;
+void env_destroy ( env_h ) ;
+env_h env_make ( char **env_strings ) ;
+int env_addvar ( env_h, env_h from_env, char *var ) ;
+int env_addstr ( env_h, char *str ) ;
+char *env_lookup ( env_h, const char *var ) ;
+
+#define env_getvars( env )            (env)->vars
+
+extern int env_errno ;
+
+#endif   /* __M_ENV_H */
+
diff --git a/libs/src/misc/misc.3 b/libs/src/misc/misc.3
new file mode 100644 (file)
index 0000000..bba1db4
--- /dev/null
@@ -0,0 +1,94 @@
+.\"(c) Copyright 1992 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: misc.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH MISC 3X "25 January 1992"
+.SH NAME
+make_string, make_pathname, argv_copy_and_clear, basename, dirname - miscellaneous functions
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "misc.h"
+.LP
+.ft B
+char *make_string( count, ... )
+unsigned count ;
+.LP
+.ft B
+char *make_pathname( count, ... )
+unsigned count ;
+.LP
+.ft B
+char **argv_copy_and_clear( argv, start, count )
+char **argv ;
+int start, count ;
+.LP
+.ft B
+char *dirname( path )
+char *path ;
+.LP
+.ft B
+char *basename( path )
+char *path ;
+.SH DESCRIPTION
+.LP
+This library contain miscellaneous functions, hence the name.
+.LP
+.B make_string()
+creates a string by catenating the list of strings passed as arguments.
+\fIcount\fR indicates how many strings there are.
+Strings that are
+.SM NULL
+pointers are ignored.
+\fBmake_string()\fR returns malloc'ed memory.
+.LP
+.B make_pathname()
+creates a pathname by catenating the list of pathname components passed
+as arguments and inserting slashes between them.
+\fIcount\fR indicates how many components there are.
+\fBmake_pathname()\fR returns malloc'ed memory.
+.LP
+.B argv_copy_and_clear()
+creates a new argv array of size \fIcount\fR, and fills it with the
+contents of \fIargv\fR from \fIstart\fR up to \fIstart+count-1\fR.
+The original \fIargv\fR entries in that range are cleared by filling
+them with
+.SM SPACEs.
+.LP
+.B dirname()
+returns in a malloced string containing all but the last of 
+component of \fIpath\fR. There are 2 special cases:
+first when the
+\fIpath\fR is "/", \fBdirname()\fR will return "/", 
+and second, when the \fIpath\fR does not contain any '/',
+\fBdirname()\fR will return ".".
+.LP
+.B basename()
+returns a pointer to the last component of \fIpath\fR.
+.SH "RETURN VALUES"
+.LP
+\fBmake_string()\fR returns a pointer to the new string.
+It returns
+.SM NULL
+if \fIcount\fR is 0.
+.LP
+\fBmake_pathname()\fR returns a pointer to the new pathname.
+It returns
+.SM NULL
+if \fIcount\fR is 0.
+.LP
+\fBargv_copy_and_clear()\fR returns the new argv array. It returns
+.SM NULL
+if \fImalloc\fR fails to allocate more memory.
+.LP
+\fBdirname()\fR returns a new string or
+.SM NULL
+if \fImalloc\fR fails to allocate more memory.
+.LP
+\fBbasename()\fR returns a pointer to the last component of \fIpath\fR.
+.SH BUGS
+.LP
+The behavior of \fBdirname()\fR and \fBbasename()\fR is undefined if
+they are given a zero-length string.
diff --git a/libs/src/misc/misc.c b/libs/src/misc/misc.c
new file mode 100644 (file)
index 0000000..777cf14
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Portions Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * MISCELLANEOUS FUNCTIONS
+ */
+
+#include "misc.h"
+
+
+/*
+ * We always return a pointer in pathname
+ */
+#if !defined(linux)
+char *basename( char *pathname )
+{
+   char *s = strrchr( pathname, '/' ) ;
+
+   if ( s == NULL )
+      return( pathname ) ;
+   else
+      return( s+1 ) ;
+}
+#endif
+
+
diff --git a/libs/src/misc/misc.h b/libs/src/misc/misc.h
new file mode 100644 (file)
index 0000000..38e430d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#ifndef __MISC_H
+#define __MISC_H
+
+/*
+ * $Id: misc.h,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+ */
+
+#if !defined(linux)
+char *basename ( char *pathname ) ;
+#endif
+
+#endif         /* __MISC_H */
diff --git a/libs/src/portable/Makefile.in b/libs/src/portable/Makefile.in
new file mode 100644 (file)
index 0000000..f172cd7
--- /dev/null
@@ -0,0 +1,94 @@
+# (c) Copyright 2001 by Rob Braun
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+NAME                   = portable
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = $(SRCDIR)/libportable.h 
+SOURCES                        = difftime.c inet_aton.c strerror.c fake-getnameinfo.c \
+                          inet_ntop.c cvt.c
+OBJECTS                        = difftime.o inet_aton.o strerror.o fake-getnameinfo.o \
+                          inet_ntop.o cvt.o
+
+INCLUDEFILES           = $(HEADERS)
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+#
+#LIBDIR                        = $(HOME)/.links/libraries/$(ARCH)
+#MANDIR                        = $(HOME)/.links/manpages/man3
+#INCLUDEDIR            = $(HOME)/.links/includes
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+#
+# Possible flags:
+#     -DOLD_DIR         : must include <sys/dir.h> instead of <dirent.h>
+#
+
+DEBUG                  = -g                            # -g or -O
+
+CPP_DEFS               = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS) -I$(INCLUDEDIR)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O lib
+       mv $(LIBNAME) $(LIBDIR)/optimized
+
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               ${RANLIB} $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+spotless: clean uninstall
+
+distclean: clean
+       rm -f Makefile
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+# None special
diff --git a/libs/src/portable/compat.h b/libs/src/portable/compat.h
new file mode 100644 (file)
index 0000000..16f4286
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (c) Copyright 2001 by Steve Grubb
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#if !defined(HAVE_GCVT)
+int APPEND(FUNC_PREFIX,fcvt_r)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign,char *buf,size_t len);
+char *APPEND(FUNC_PREFIX,gcvt)(FLOAT_TYPE value,int ndigit,char *buf);
+char *APPEND(FUNC_PREFIX,ecvt)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign);
+char *APPEND(FUNC_PREFIX,fcvt)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign);
+weak_extern2(FLOOR)weak_extern2(LOG10)weak_extern2(FABS)weak_extern2(EXP)int APPEND(FUNC_PREFIX,ecvt_r)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign,char *buf,size_t len);
+#endif
+
+
+#endif
diff --git a/libs/src/portable/cvt.c b/libs/src/portable/cvt.c
new file mode 100644 (file)
index 0000000..4bd99fc
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#define FUNC_PREFIX
+#define FLOAT_FMT_FLAG
+#define FLOAT_NAME_EXT
+#endif
+
+#ifndef MAXDIG
+#define MAXDIG 120
+#endif
+
+#ifndef APPEND
+#define APPEND(a, b) APPEND2 (a, b)
+#endif
+
+#ifndef APPEND2
+#define APPEND2(a, b) a##b
+#endif
+
+#ifndef FLOOR
+#define FLOOR APPEND(floor, FLOAT_NAME_EXT)
+#endif
+#ifndef FABS
+#define FABS APPEND(fabs, FLOAT_NAME_EXT)
+#endif
+#ifndef LOG10
+#define LOG10 APPEND(log10, FLOAT_NAME_EXT)
+#endif
+#ifndef EXP
+#define EXP APPEND(exp, FLOAT_NAME_EXT)
+#endif
+#ifndef ISINF
+#define ISINF APPEND(isinf, FLOAT_NAME_EXT)
+#endif
+#ifndef ISNAN
+#define ISNAN APPEND(isnan, FLOAT_NAME_EXT)
+#endif
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef __set_errno
+#define __set_errno(x) errno = (x)
+#endif
+
+#ifndef HAVE_FCVT
+int
+APPEND (FUNC_PREFIX, fcvt_r) (FLOAT_TYPE value, 
+                              int ndigit, 
+                              int *decpt, 
+                              int *sign, 
+                              char *buf, 
+                              size_t len)
+{
+   int n, i;
+   int left;
+
+   if (buf == NULL) {
+      __set_errno (EINVAL);
+      return -1;
+   }
+
+   left = 0;
+   if (!ISINF (value) && !ISNAN (value)) {
+      /* OK, the following is not entirely correct.  -0.0 is not handled
+       * correctly but glibc 2.0 does not have a portable function to
+       * implement this test.  
+       */
+       *sign = value < 0.0;
+       if (*sign)
+          value = -value;
+
+       if (ndigit < 0) {
+          /* Rounding to the left of the decimal point.  */
+          while (ndigit < 0) {
+             FLOAT_TYPE new_value = value * 0.1;
+
+             if (new_value < 1.0) {
+                ndigit = 0;
+                break;
+             }
+
+             value = new_value;
+             ++left;
+             ++ndigit;
+          }
+       }
+    } else {
+       /* Value is Inf or NaN.  */
+       *sign = 0;
+    }
+
+    n = strx_nprint (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value);
+    if (n < 0)
+       return -1;
+
+    i = 0;
+    while (i < n && isdigit (buf[i]))
+       ++i;
+    *decpt = i;
+
+    if (i == 0)
+       /* Value is Inf or NaN.  */
+       return 0;
+
+    if (i < n) {
+       do
+       ++i;
+       while (i < n && !isdigit (buf[i]));
+
+       if (*decpt == 1 && buf[0] == '0' && value != 0.0) {
+          /* We must not have leading zeroes.  Strip them all out and
+           * adjust *DECPT if necessary.  */
+          --*decpt;
+          while (i < n && buf[i] == '0')
+          {
+             --*decpt;
+             ++i;
+          }
+       }
+
+       memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i);
+       buf[n - (i - MAX (*decpt, 0))] = '\0';
+    }
+
+    if (left) {
+       *decpt += left;
+       if (--len > n) {
+          while (left-- > 0 && n < len)
+             buf[n++] = '0';
+          buf[n] = '\0';
+       }
+    }
+
+    return 0;
+}
+#endif /* HAVE_FCVT */
+
+#define weak_extern2(name) 
+weak_extern2 (FLOOR) weak_extern2 (LOG10) weak_extern2 (FABS)
+weak_extern2 (EXP)
+
+#ifndef HAVE_ECVT
+int
+APPEND (FUNC_PREFIX, ecvt_r) (FLOAT_TYPE value, 
+                              int ndigit, 
+                              int *decpt, 
+                              int *sign, 
+                              char *buf, 
+                              size_t len)
+{
+  int exponent = 0;
+
+  if (!ISNAN (value) && !ISINF (value) && value != 0.0) {
+      FLOAT_TYPE (*log10_function) (FLOAT_TYPE) = &LOG10;
+
+      if (log10_function) {
+         /* Use the reasonable code if -lm is included.  */
+         FLOAT_TYPE dexponent;
+         dexponent = FLOOR (LOG10 (FABS (value)));
+         value *= EXP (dexponent * -M_LN10);
+         exponent = (int) dexponent;
+      } else {
+         /* Slow code that doesn't require -lm functions.  */
+         FLOAT_TYPE d;
+         if (value < 0.0)
+            d = -value;
+         else
+            d = value;
+         if (d < 1.0) {
+            do {
+               d *= 10.0;
+               --exponent;
+            } while (d < 1.0);
+         } else if (d >= 10.0) {
+            do {
+               d *= 0.1;
+               ++exponent;
+            } while (d >= 10.0);
+         }
+         if (value < 0.0)
+            value = -d;
+         else
+            value = d;
+       }
+    } else if (value == 0.0)
+       /* SUSv2 leaves it unspecified whether *DECPT is 0 or 1 for 0.0.
+        * This could be changed to -1 if we want to return 0.  */
+        exponent = 0;
+
+    if (ndigit <= 0 && len > 0) {
+       buf[0] = '\0';
+       *decpt = 1;
+       if (!ISINF (value) && !ISNAN (value))
+          *sign = value < 0.0;
+       else
+          *sign = 0;
+    } else
+       if (APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit - 1, decpt, sign,
+                      buf, len))
+          return -1;
+
+    *decpt += exponent;
+    return 0;
+}
+#endif /* HAVE_ECVT */
+
+#ifndef HAVE_FCVT
+char *
+APPEND (FUNC_PREFIX, fcvt) (FLOAT_TYPE value, 
+                            int ndigit, 
+                            int *decpt, 
+                            int *sign)
+{
+  static char buf[MAXDIG];
+
+  (void) APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign,
+                       buf, sizeof buf);
+
+  return buf;
+}
+#endif /* HAVE_FCVT */
+
+#ifndef HAVE_ECVT
+char *
+APPEND (FUNC_PREFIX, ecvt) (FLOAT_TYPE value, 
+                            int ndigit, 
+                            int *decpt, 
+                            int *sign)
+{
+  static char buf[MAXDIG];
+
+  (void) APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign,
+                       buf, sizeof buf);
+
+  return buf;
+}
+#endif /* HAVE_ECVT */
+
+#ifndef HAVE_GCVT
+char *
+APPEND (FUNC_PREFIX, gcvt) (FLOAT_TYPE value, 
+                            int ndigit, 
+                            char *buf)
+{
+  sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", ndigit, value);
+  return buf;
+}
+#endif /* HAVE_GCVT */
diff --git a/libs/src/portable/difftime.c b/libs/src/portable/difftime.c
new file mode 100644 (file)
index 0000000..1c572d6
--- /dev/null
@@ -0,0 +1,9 @@
+#include "config.h"
+#ifndef HAVE_DIFFTIME
+#include <sys/types.h>
+
+double difftime( time_t a, time_t b)
+{
+       return (double)a - (double)b;
+}
+#endif
diff --git a/libs/src/portable/fake-getaddrinfo.c b/libs/src/portable/fake-getaddrinfo.c
new file mode 100644 (file)
index 0000000..9b0c544
--- /dev/null
@@ -0,0 +1,117 @@
+#include "fake-getaddrinfo.h"
+/*
+ * fake library for ssh
+ *
+ * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
+ * These funtions are defined in rfc2133.
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For exapmle, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#ifndef HAVE_GAI_STRERROR
+char *gai_strerror(int ecode)
+{
+       switch (ecode) {
+               case EAI_NODATA:
+                       return "no address associated with hostname.";
+               case EAI_MEMORY:
+                       return "memory allocation failure.";
+               default:
+                       return "unknown error.";
+       }
+}    
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+void freeaddrinfo(struct addrinfo *ai)
+{
+       struct addrinfo *next;
+
+       do {
+               next = ai->ai_next;
+               free(ai);
+       } while (NULL != (ai = next));
+}
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+static struct addrinfo *malloc_ai(int port, u_long addr)
+{
+       struct addrinfo *ai;
+
+       ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
+       if (ai == NULL)
+               return(NULL);
+       
+       memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
+       
+       ai->ai_addr = (struct sockaddr *)(ai + 1);
+       /* XXX -- ssh doesn't use sa_len */
+       ai->ai_addrlen = sizeof(struct sockaddr_in);
+       ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
+       
+       return(ai);
+}
+
+int getaddrinfo(const char *hostname, const char *servname, 
+                const struct addrinfo *hints, struct addrinfo **res)
+{
+       struct addrinfo *cur, *prev = NULL;
+       struct hostent *hp;
+       struct in_addr in;
+       int i, port;
+
+       if (servname)
+               port = htons(atoi(servname));
+       else
+               port = 0;
+
+       if (hints && hints->ai_flags & AI_PASSIVE) {
+               if (NULL != (*res = malloc_ai(port, htonl(0x00000000))))
+                       return 0;
+               else
+                       return EAI_MEMORY;
+       }
+               
+       if (!hostname) {
+               if (NULL != (*res = malloc_ai(port, htonl(0x7f000001))))
+                       return 0;
+               else
+                       return EAI_MEMORY;
+       }
+       
+       if (inet_aton(hostname, &in)) {
+               if (NULL != (*res = malloc_ai(port, in.s_addr)))
+                       return 0;
+               else
+                       return EAI_MEMORY;
+       }
+       
+       hp = gethostbyname(hostname);
+       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+               for (i = 0; hp->h_addr_list[i]; i++) {
+                       cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
+                       if (cur == NULL) {
+                               if (*res)
+                                       freeaddrinfo(*res);
+                               return EAI_MEMORY;
+                       }
+                       
+                       if (prev)
+                               prev->ai_next = cur;
+                       else
+                               *res = cur;
+
+                       prev = cur;
+               }
+               return 0;
+       }
+       
+       return EAI_NODATA;
+}
+#endif /* !HAVE_GETADDRINFO */
diff --git a/libs/src/portable/fake-getaddrinfo.h b/libs/src/portable/fake-getaddrinfo.h
new file mode 100644 (file)
index 0000000..0940e37
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _FAKE_GETADDRINFO_H
+#define _FAKE_GETADDRINFO_H
+
+#include "config.h"
+
+/*
+#include "fake-gai-errnos.h"
+*/
+
+#ifndef AI_PASSIVE
+# define AI_PASSIVE        1
+# define AI_CANONNAME      2
+#endif
+
+#ifndef NI_NUMERICHOST
+# define NI_NUMERICHOST    2
+# define NI_NAMEREQD       4
+# define NI_NUMERICSERV    8
+#endif
+
+#ifndef EAI_NODATA
+#define EAI_NODATA        -5
+#endif
+
+#ifndef EAI_MEMORY
+#define EAI_MEMORY       -10
+#endif
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif /* !HAVE_STRUCT_ADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+int getaddrinfo(const char *hostname, const char *servname, 
+                const struct addrinfo *hints, struct addrinfo **res);
+#endif /* !HAVE_GETADDRINFO */
+
+#ifndef HAVE_GAI_STRERROR
+char *gai_strerror(int ecode);
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+void freeaddrinfo(struct addrinfo *ai);
+#endif /* !HAVE_FREEADDRINFO */
+
+#endif /* _FAKE_GETADDRINFO_H */
diff --git a/libs/src/portable/fake-getnameinfo.c b/libs/src/portable/fake-getnameinfo.c
new file mode 100644 (file)
index 0000000..7af6c33
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * fake library for ssh
+ *
+ * This file includes getnameinfo().
+ * These funtions are defined in rfc2133.
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For exapmle, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "fake-getaddrinfo.h"
+
+#ifndef HAVE_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 
+                size_t hostlen, char *serv, size_t servlen, int flags)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+       struct hostent *hp;
+       char tmpserv[16];
+
+       if (serv) {
+               snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
+               if (strlen(tmpserv) >= servlen)
+                       return EAI_MEMORY;
+               else
+                       strcpy(serv, tmpserv);
+       }
+
+       if (host) {
+               if (flags & NI_NUMERICHOST) {
+                       if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
+                               return EAI_MEMORY;
+
+                       strcpy(host, inet_ntoa(sin->sin_addr));
+                       return 0;
+               } else {
+                       hp = gethostbyaddr((char *)&sin->sin_addr, 
+                               sizeof(struct in_addr), AF_INET);
+                       if (hp == NULL)
+                               return EAI_NODATA;
+                       
+                       if (strlen(hp->h_name) >= hostlen)
+                               return EAI_MEMORY;
+
+                       strcpy(host, hp->h_name);
+                       return 0;
+               }
+       }
+       return 0;
+}
+#endif /* !HAVE_GETNAMEINFO */
diff --git a/libs/src/portable/inet_aton.c b/libs/src/portable/inet_aton.c
new file mode 100644 (file)
index 0000000..0a05e61
--- /dev/null
@@ -0,0 +1,193 @@
+/*     $OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $    */
+
+/*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
+ * Copyright (c) 1983, 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#include "config.h"
+
+#if defined(NO_INET_ATON)
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)inet_addr.c        8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#if 0
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+in_addr_t
+inet_addr(cp)
+       register const char *cp;
+{
+       struct in_addr val;
+
+       if (inet_aton(cp, &val))
+               return (val.s_addr);
+       return (INADDR_NONE);
+}
+#endif
+
+/* 
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+       register uint32_t val;
+       register int base, n;
+       register char c;
+       unsigned int parts[4];
+       register unsigned int *pp = parts;
+
+       c = *cp;
+       for (;;) {
+               /*
+                * Collect number up to ``.''.
+                * Values are specified as for C:
+                * 0x=hex, 0=octal, isdigit=decimal.
+                */
+               if (!isdigit(c))
+                       return (0);
+               val = 0; base = 10;
+               if (c == '0') {
+                       c = *++cp;
+                       if (c == 'x' || c == 'X')
+                               base = 16, c = *++cp;
+                       else
+                               base = 8;
+               }
+               for (;;) {
+                       if (isascii(c) && isdigit(c)) {
+                               val = (val * base) + (c - '0');
+                               c = *++cp;
+                       } else if (base == 16 && isascii(c) && isxdigit(c)) {
+                               val = (val << 4) |
+                                       (c + 10 - (islower(c) ? 'a' : 'A'));
+                               c = *++cp;
+                       } else
+                               break;
+               }
+               if (c == '.') {
+                       /*
+                        * Internet format:
+                        *      a.b.c.d
+                        *      a.b.c   (with c treated as 16 bits)
+                        *      a.b     (with b treated as 24 bits)
+                        */
+                       if (pp >= parts + 3)
+                               return (0);
+                       *pp++ = val;
+                       c = *++cp;
+               } else
+                       break;
+       }
+       /*
+        * Check for trailing characters.
+        */
+       if (c != '\0' && (!isascii(c) || !isspace(c)))
+               return (0);
+       /*
+        * Concoct the address according to
+        * the number of parts specified.
+        */
+       n = pp - parts + 1;
+       switch (n) {
+
+       case 0:
+               return (0);             /* initial nondigit */
+
+       case 1:                         /* a -- 32 bits */
+               break;
+
+       case 2:                         /* a.b -- 8.24 bits */
+               if ((val > 0xffffff) || (parts[0] > 0xff))
+                       return (0);
+               val |= parts[0] << 24;
+               break;
+
+       case 3:                         /* a.b.c -- 8.8.16 bits */
+               if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16);
+               break;
+
+       case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
+               if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+               break;
+       }
+       if (addr)
+               addr->s_addr = htonl(val);
+       return (1);
+}
+
+#endif /* defined(NO_INET_ATON) */
diff --git a/libs/src/portable/inet_ntop.c b/libs/src/portable/inet_ntop.c
new file mode 100644 (file)
index 0000000..3c57ccd
--- /dev/null
@@ -0,0 +1,216 @@
+/*     $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $    */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#ifndef HAVE_INET_NTOP
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifndef HAVE_CYGWIN
+#include <arpa/nameser.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ   16   /* IPv6 T_AAAA */                 
+#endif
+
+#ifndef INT16SZ
+#define INT16SZ     2    /* for systems without 16-bit ints */
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 (const u_char *src, char *dst, size_t size);
+#ifdef AF_INET6
+static const char *inet_ntop6 (const u_char *src, char *dst, size_t size);
+#endif /* AF_INET6 */
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *     convert a network format address to presentation format.
+ * return:
+ *     pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *     Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+       int af;
+       const void *src;
+       char *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_ntop4(src, dst, size));
+#ifdef AF_INET6
+       case AF_INET6:
+               return (inet_ntop6(src, dst, size));
+#endif /* AF_INET6 */
+       default:
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+       /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *     format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *     `dst' (as a const)
+ * notes:
+ *     (1) uses no statics
+ *     (2) takes a u_char* not an in_addr as input
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       static const char fmt[] = "%u.%u.%u.%u";
+       char tmp[sizeof "255.255.255.255"];
+
+       if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *     convert IPv6 binary address into presentation (printable) format
+ * author:
+ *     Paul Vixie, 1996.
+ */
+#ifdef AF_INET6
+static const char *
+inet_ntop6(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       /*
+        * Note that int32_t and int16_t need only be "at least" large enough
+        * to contain a value of the specified size.  On some systems, like
+        * Crays, there is no such thing as an integer variable with 16 bits.
+        * Keep this in mind if you think this function should have been coded
+        * to use pointer overlays.  All the world's not a VAX.
+        */
+       char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+       struct { int base, len; } best, cur;
+       u_int words[IN6ADDRSZ / INT16SZ];
+       int i;
+
+       /*
+        * Preprocess:
+        *      Copy the input (bytewise) array into a wordwise array.
+        *      Find the longest run of 0x00's in src[] for :: shorthanding.
+        */
+       memset(words, '\0', sizeof words);
+       for (i = 0; i < IN6ADDRSZ; i++)
+               words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+       best.base = -1;
+       cur.base = -1;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               if (words[i] == 0) {
+                       if (cur.base == -1)
+                               cur.base = i, cur.len = 1;
+                       else
+                               cur.len++;
+               } else {
+                       if (cur.base != -1) {
+                               if (best.base == -1 || cur.len > best.len)
+                                       best = cur;
+                               cur.base = -1;
+                       }
+               }
+       }
+       if (cur.base != -1) {
+               if (best.base == -1 || cur.len > best.len)
+                       best = cur;
+       }
+       if (best.base != -1 && best.len < 2)
+               best.base = -1;
+
+       /*
+        * Format the result.
+        */
+       tp = tmp;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               /* Are we inside the best run of 0x00's? */
+               if (best.base != -1 && i >= best.base &&
+                   i < (best.base + best.len)) {
+                       if (i == best.base)
+                               *tp++ = ':';
+                       continue;
+               }
+               /* Are we following an initial run of 0x00s or any real hex? */
+               if (i != 0)
+                       *tp++ = ':';
+               /* Is this address an encapsulated IPv4? */
+               if (i == 6 && best.base == 0 &&
+                   (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+                       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+                               return (NULL);
+                       tp += strlen(tp);
+                       break;
+               }
+               tp += sprintf(tp, "%x", words[i]);
+       }
+       /* Was it a trailing run of 0x00's? */
+       if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+               *tp++ = ':';
+       *tp++ = '\0';
+
+       /*
+        * Check for overflow, copy, and we're done.
+        */
+       if ((size_t)(tp - tmp) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
+#endif /* AF_INET6 */
+
+#endif /* !HAVE_INET_NTOP */
diff --git a/libs/src/portable/libportable.h b/libs/src/portable/libportable.h
new file mode 100644 (file)
index 0000000..825f3c3
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef _XINETD_LIBPORTABLE
+#define _XINETD_LIBPORTABLE 1
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#ifndef IPV6_ADDRFORM
+#define IPV6_ADDRFORM            1
+#endif
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+#ifndef HAVE_DIFFTIME
+double difftime( time_t, time_t );
+#endif
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp(const char *s1, const char *s2);
+#endif
+
+#ifndef HAVE_STRERROR
+char * strerror(int);
+#endif
+
+#ifdef NO_INET_ATON
+int inet_aton(const char *cp, struct in_addr *addr);
+#endif
+
+#ifndef HAVE_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+                size_t hostlen, char *serv, size_t servlen, int flags);
+#endif
+
+#ifndef HAVE_INET_NTOP
+const char *inet_ntop(int, const void *, char *, size_t);
+#endif
+
+#ifndef APPEND
+#define APPEND(a, b) APPEND2 (a, b)
+#endif
+
+#ifndef APPEND2
+#define APPEND2(a, b) a##b
+#endif
+
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#endif
+
+#ifndef FUNC_PREFIX
+#define FUNC_PREFIX 
+#endif
+
+#ifndef HAVE_FCVT
+int APPEND(FUNC_PREFIX,fcvt_r)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign,char *buf,size_t len);
+char *APPEND(FUNC_PREFIX,fcvt)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign);
+#endif
+#ifndef HAVE_ECVT
+char *APPEND(FUNC_PREFIX,ecvt)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign);
+int APPEND(FUNC_PREFIX,ecvt_r)(FLOAT_TYPE value,int ndigit,int *decpt,int *sign,char *buf,size_t len);
+#endif
+#ifndef HAVE_GCVT
+char *APPEND(FUNC_PREFIX,gcvt)(FLOAT_TYPE value,int ndigit,char *buf);
+#endif
+
+/* from OpenSSH's fake-socket.h */
+
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+# define       _SS_MAXSIZE     128     /* Implementation specific max size */
+# define       _SS_PADSIZE     (_SS_MAXSIZE - sizeof (struct sockaddr))
+
+struct sockaddr_storage {
+       struct  sockaddr ss_sa;
+       char            __ss_pad2[_SS_PADSIZE];
+};
+# define ss_family ss_sa.sa_family
+#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
+       (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+        ((uint32_t *) (a))[2] == 0 && ((uint32_t *) (a))[3] == htonl (1))
+#endif /* !IN6_IS_ADDR_LOOPBACK */
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+       uint8_t         s6_addr[16];
+};
+#endif /* !HAVE_STRUCT_IN6_ADDR */
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+   unsigned short sin6_family;
+       uint16_t sin6_port;
+       uint32_t sin6_flowinfo;
+       struct in6_addr sin6_addr;
+};
+#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
+
+#ifndef AF_INET6
+/* Define it to something that should never appear */
+#define AF_INET6 AF_MAX
+#endif
+
+
+#endif /* _XINETD_LIBPORTABLE */
diff --git a/libs/src/portable/strcasecmp.c b/libs/src/portable/strcasecmp.c
new file mode 100644 (file)
index 0000000..35b92c6
--- /dev/null
@@ -0,0 +1,15 @@
+typedef unsigned char u_char;
+
+int
+strcasecmp(s1, s2)
+               const char *s1, *s2;
+{
+       register const u_char
+       *us1 = (const u_char *)s1,
+       *us2 = (const u_char *)s2;
+
+       while (tolower(*us1) == tolower(*us2++))
+               if (*us1++ == '\0')
+                       return (0);
+       return (tolower(*us1) - tolower(*--us2));
+}
diff --git a/libs/src/portable/strerror.c b/libs/src/portable/strerror.c
new file mode 100644 (file)
index 0000000..2fa75f6
--- /dev/null
@@ -0,0 +1,75 @@
+#include "config.h"
+#ifndef HAVE_STRERROR
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD: src/lib/libc/string/strerror.c,v 1.3 2001/05/24 08:47:41 obrien Exp $";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+char *
+strerror(num)
+       int num;
+{
+#define        UPREFIX "Unknown error: "
+       static char ebuf[40] = UPREFIX;         /* 64-bit number + slop */
+       register unsigned int errnum;
+       register char *p, *t;
+       char tmp[40];
+
+       errnum = num;                           /* convert to unsigned */
+       if (errnum < sys_nerr)
+               return ((char *)sys_errlist[errnum]);
+
+       /* Do this by hand, so we don't link to stdio(3). */
+       t = tmp;
+       if (num < 0)
+               errnum = -errnum;
+       do {
+               *t++ = "0123456789"[errnum % 10];
+       } while (errnum /= 10);
+       if (num < 0)
+               *t++ = '-';
+       for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+               *p++ = *--t;
+               if (t <= tmp)
+                       break;
+       }
+       *p = '\0';
+       return (ebuf);
+}
+#endif /* HAVE_STRERROR */
diff --git a/libs/src/pset/COPYRIGHT b/libs/src/pset/COPYRIGHT
new file mode 100644 (file)
index 0000000..362419b
--- /dev/null
@@ -0,0 +1,30 @@
+This software is
+
+(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution and that this copyright notice is also included in any 
+redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
diff --git a/libs/src/pset/Makefile.in b/libs/src/pset/Makefile.in
new file mode 100644 (file)
index 0000000..8b6382d
--- /dev/null
@@ -0,0 +1,95 @@
+# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+#
+# Based on Library makefile template: *Revision: 1.15 *
+#
+
+
+NAME                   = pset
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = pset.h
+SOURCES                        = pset.c ops.c
+OBJECTS                        = pset.o ops.o
+
+MANFILES               = $(SRCDIR)/pset.3 $(SRCDIR)/psi.3
+INCLUDEFILES           = $(SRCDIR)/pset.h
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+DEBUG                  = -g            # -g or -O
+
+CPP_DEFS               = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS) -I$(INCLUDEDIR)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                        # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O lib
+       mv $(LIBNAME) $(LIBDIR)/optimized
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               $(RANLIB) $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+               for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
+               echo Installed $(MANFILES) to $(MANDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+       a=`pwd` ; cd $(MANDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+distclean: clean
+       rm -f Makefile
+
+spotless: clean uninstall
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+pset.o: pset.h
+
diff --git a/libs/src/pset/install-sh b/libs/src/pset/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/src/pset/ops.c b/libs/src/pset/ops.c
new file mode 100644 (file)
index 0000000..331a861
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include "pset.h"
+#include <stdlib.h>
+
+#define POINTER                                __pset_pointer
+
+
+/*
+ * Remove all NULL pointers from a pset
+ */
+void pset_compact( register pset_h pset )
+{
+       register unsigned u ;
+
+       for ( u = 0 ; u < pset_count( pset ) ; )
+       {
+               POINTER ptr = pset_pointer( pset, u );
+               if ( ptr != NULL )
+                       u++ ;
+               else
+                       pset_delete( pset, ptr ) ;
+       }
+
+       /* See if we can reclaim some memory, make sure we are 2 below for some hysteresis */
+       if ((int)( pset->max - pset->alloc_step - 2) > (int)pset_count( pset ))
+       {       /* This rounds up to the next unit of steps */
+               POINTER *new_ptrs ;
+               unsigned new_max = ((pset_count( pset ) / pset->alloc_step) + 1)*pset->alloc_step;
+
+               new_ptrs = (POINTER *) realloc(
+                                                               (char *)pset->ptrs, new_max * sizeof( POINTER ) ) ;
+               if ( new_ptrs == NULL )
+                       return;
+               pset->max = new_max ;
+               pset->ptrs = new_ptrs ;
+       }
+}
+
+
+/*
+ * Apply a function to all pointers of a pset
+ */
+void pset_apply( register pset_h pset, void (*func)(), register void *arg )
+{
+       register unsigned u ;
+
+       for ( u = 0 ; u < pset_count( pset ) ; u++ )
+               if ( arg )
+                       (*func)( arg, pset_pointer( pset, u ) ) ;
+               else
+                       (*func)( pset_pointer( pset, u ) ) ;
+}
+
diff --git a/libs/src/pset/pset.3 b/libs/src/pset/pset.3
new file mode 100644 (file)
index 0000000..7835529
--- /dev/null
@@ -0,0 +1,270 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: pset.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH PSET 3X "23 April 1993"
+.SH NAME
+pset_create, pset_destroy, pset_add, pset_insert, pset_remove, pset_delete, pset_remove_index, pset_clear, pset_count, pset_pointer, pset_compact, pset_sort, pset_apply - routines that handle pointer sets
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "pset.h"
+.LP
+.ft B
+pset_h pset_create( alloc_start, alloc_step )
+unsigned alloc_start, alloc_step ;
+.LP
+.ft B
+void pset_destroy( pset )
+pset_h pset ;
+.LP
+.ft B
+ANY_TYPE *pset_add( pset, ptr )
+pset_h pset ;
+ANY_TYPE *ptr ;
+.LP
+.ft B
+void *pset_insert( pset, ptr )
+pset_h pset ;
+void *ptr ;
+.LP
+.ft B
+void pset_remove( pset, ptr )
+pset_h pset ;
+ANY_TYPE *ptr ;
+.LP
+.ft B
+void pset_delete( pset, ptr )
+pset_h pset ;
+void *ptr ;
+.LP
+.ft B
+void pset_remove_index( pset, index )
+pset_h pset ;
+unsigned index ;
+.LP
+.ft B
+void pset_clear( pset )
+pset_h pset ;
+.LP
+.ft B
+unsigned pset_count( pset )
+pset_h pset ;
+.LP
+.ft B
+void *pset_pointer( pset, index )
+pset_h pset ;
+unsigned index ;
+.LP
+.ft B
+void pset_compact( pset )
+pset_h pset ;
+.LP
+.ft B
+void pset_sort( pset, compfunc )
+pset_h pset ;
+int (*compfunc)() ;
+.LP
+.ft B
+void pset_apply( pset, func, arg )
+pset_h pset ;
+void (*func)() ;
+void *arg ;
+.SH DESCRIPTION
+This library provides functions that handle sets of pointers. Pointers
+can be inserted and deleted from sets and the sets can be enumerated.
+Pointers are inserted in sets in no particular order. However it is 
+guaranteed
+that a sequence of insertions will result in a set which if enumerated
+will provide the pointers in the same order in which they were inserted
+(assuming no intervening deletions).
+.LP
+.B pset_create()
+creates a pointer set.
+.I alloc_start
+determines the initial table size, and
+.I alloc_step
+determines the amount by which the set size is increased in case of
+overflow. If any of these parameters is 0, a default value is used.
+.LP
+.B pset_destroy()
+destroys the specified pointer set.
+.LP
+.B pset_add()
+is a macro that adds a pointer to the specified set.
+The pointer can be of any type.
+.LP
+.B pset_insert()
+inserts a pointer to the specified set.
+This is the same operation as
+.B pset_add().
+.LP
+.B pset_remove()
+removes a pointer from the specified set.
+.LP
+.B pset_delete()
+deletes a pointer from the specified set.
+This is the same operation as
+.B pset_remove().
+.LP
+.B pset_remove_index()
+removes the pointer that is at position
+.I index
+in the set.
+.I index
+should be in the range [0, \fBpset_count(pset)\fP) (but there is no
+check to enforce this).
+After this operation, the
+.I index
+position will be occupied by another pointer.
+.LP
+.B pset_clear()
+removes all pointers from the specified set.
+.LP
+.B pset_count()
+returns the number of pointers in the specified set.
+.LP
+.B pset_pointer()
+returns the pointer at position
+.I index
+in the specified set.
+.I index
+must be between 0 and
+.B "pset_count(pset)."
+.B pset_pointer()
+is a macro and it can also be used in the left-hand side of assignments.
+.LP
+.B pset_compact()
+removes all NULL pointers from
+.I pset.
+.LP
+.B pset_sort()
+sorts the pointers in
+.I pset
+using the specified function.
+.I compfunc
+is invoked with 2 arguments that are pointers pointing to pointers stored in 
+.I pset.
+For example, if the pset holds pointers to objects of type T, then
+the function F whose address is in
+.I compfunc
+should be defined as:
+F( T **p1, T **p2 ).
+.br
+.I compfunc 
+should return a negative, zero or positive value 
+if its first argument is less than, equal to, or greater than its
+second argument.
+.LP
+.B pset_apply()
+applies
+.I func
+to all pointers in
+.I pset.
+If 
+.I arg
+is not
+.SM NULL
+the function is invoked as:
+.RS
+(*func)( arg, p )
+.RE
+where
+.I p
+is a pset pointer.  If 
+.I arg
+is
+.SM NULL
+the function is invoked as:
+.RS
+(*func)( p )
+.RE
+.SH EXAMPLE
+The following code fragment reads lines from standard input
+and places them in a pset. Then it sorts the pset, prints the
+sorted contents to standard output and then it eliminates duplicate
+lines (which it also prints to standard output).
+.RS
+.sp 1
+.ft B
+.nf
+pset_h ph ;
+char buf[ 80 ] ;
+unsigned u ;
+int compstr() ;
+void printstr() ;
+.sp 1
+ph = pset_create( 0, 0 ) ;
+while ( gets( buf ) )
+.RS
+pset_add( strcpy( malloc( strlen( buf ) + 1 ), buf ) ) ;
+.RE
+pset_sort( ph, compstr ) ;
+for ( u = 0 ; u < pset_count( ph ) ; u++ )
+.RS
+printf( "%s\\n", (char *) pset_pointer( ph, u ) ) ;
+.RE
+.RE
+.fi
+.ft R
+.LP
+The function
+.I compstr()
+follows:
+.sp 1
+.RS
+.ft B
+.nf
+int compstr( p1, p2 )
+.RS
+char **p1, **p2 ;
+.RE
+{
+.RS
+return( strcmp( *p1, *p2 ) ) ;
+.RE
+}
+.RE
+.SH "RETURN VALUES"
+.LP
+.I pset_h
+is a pointer type. Functions that return
+.I pset_h
+will return
+.SM NULL
+to indicate an error.
+.LP
+.B pset_create()
+returns a pointer set handle or
+.SM NULL
+if it fails.
+.LP
+.B pset_add()
+returns its second argument if successful or
+.SM NULL
+if it fails.
+.LP
+.B pset_insert()
+returns its second argument if successful or
+.SM NULL
+if it fails.
+.LP
+.B pset_count()
+always returns the number of pointers in the set.
+.LP
+.B pset_pointer()
+always returns a pointer. There is no check if the specified index is within
+range.
+.SH BUGS
+.LP
+.B pset_add(),
+.B pset_remove(),
+.B pset_remove_index(),
+.B pset_count(),
+.B pset_clear(),
+.B pset_pointer()
+and 
+.B pset_sort()
+are macros, therefore the \fI&\fR operator cannot be applied to them.
diff --git a/libs/src/pset/pset.c b/libs/src/pset/pset.c
new file mode 100644 (file)
index 0000000..a5f8069
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <stdlib.h>
+#include "pset.h"
+
+
+#define ALLOC_START                            20
+#define ALLOC_STEP                             10
+
+
+static __pset_pointer pset_insert( pset_h pset, const __pset_pointer p );
+
+
+/*
+ * Create a pointer set and return a handle to it.
+ * Some space is initially allocated for the set.
+ */
+pset_h pset_create( unsigned alloc_start, unsigned alloc_step )
+{
+       pset_h pset ;
+       unsigned start ;
+
+       pset = (pset_h) malloc( sizeof( struct __pset ) ) ;
+       if ( pset == NULL )
+               return( NULL ) ;
+       
+       start = ( alloc_start == 0 ) ? ALLOC_START : alloc_start ;
+       pset->ptrs = (__pset_pointer *) malloc( start * sizeof( __pset_pointer ) ) ;
+       if ( pset->ptrs == NULL )
+       {
+               free( (char *) pset ) ;
+               return( NULL ) ;
+       }
+
+       pset->max = start ;
+       pset->count = 0 ;
+       pset->alloc_step = ( alloc_step == 0 ) ? ALLOC_STEP : alloc_step ;
+       return( pset ) ;
+}
+
+
+/*
+ * Destroy a pset
+ */
+void pset_destroy( pset_h pset )
+{
+       if ( pset == NULL )
+               return;
+       free( (char *) pset->ptrs ) ;
+       free( (char *) pset ) ;
+}
+
+__pset_pointer pset_add( pset_h pset, const __pset_pointer ptr )
+{
+       return (pset->count < pset->max )
+               ? (pset->ptrs[ pset->count++ ] = ptr)
+                       : pset_insert( pset, ptr) ;
+}
+
+/*
+ * Append a pointer to a pset
+ */
+static __pset_pointer pset_insert( pset_h pset, const __pset_pointer p )
+{
+       if ( pset->count >= pset->max )
+       {
+               unsigned new_max = pset->max + pset->alloc_step ;
+               __pset_pointer *new_ptrs ;
+
+               new_ptrs = (__pset_pointer *) realloc(
+                       (char *)pset->ptrs, new_max * sizeof( __pset_pointer ) ) ;
+               if ( new_ptrs == NULL )
+                       return( NULL ) ;
+               pset->max = new_max ;
+               pset->ptrs = new_ptrs ;
+       }
+       return( pset->ptrs[ pset->count++ ] = p ) ;
+}
+
+
+/*
+ * Remove a pointer from a pset by moving every thing above it down 1 spot.
+ */
+void pset_delete( register pset_h pset, register const __pset_pointer ptr )
+{
+       register unsigned u = 0;
+       register int found_it = 0;
+
+       if ( pset->count == 0 )
+               return ;
+
+       while ( u < pset->count )
+       {
+               if ( pset->ptrs[ u ] == ptr )
+                       found_it = 1;
+               if ( found_it )
+               {       /* If not the last one, copy it */
+                       if ( (u+1) < pset->count )
+                               pset->ptrs[ u ] = pset->ptrs[ u+1 ];
+               }
+               u++;
+       }
+       pset->count--;
+}
+
+
+/*
+ * Create a pset iterator
+ */
+psi_h psi_create( pset_h pset )
+{
+       psi_h iter = (psi_h) malloc( sizeof( struct __pset_iterator ) ) ;
+
+       if ( iter == NULL )
+               return( NULL ) ;
+       iter->pset = pset ;
+       return( iter ) ;
+}
+
+/*
+ * Remove an element from a pset
+ */
+void psi_remove( psi_h iter )
+{
+       if ( iter->current < pset_count( iter->pset ) )
+       {
+               pset_remove_index( iter->pset, iter->current ) ;
+               iter->step = 0;
+       }
+}
+
diff --git a/libs/src/pset/pset.h b/libs/src/pset/pset.h
new file mode 100644 (file)
index 0000000..4a726a1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef __PSET_H
+#define __PSET_H
+
+/*
+ * $Id: pset.h,v 1.2 2003/03/09 19:27:08 steveg Exp $
+ */
+
+#include <stdlib.h>
+
+typedef void *__pset_pointer ;
+
+struct __pset
+{
+   unsigned alloc_step ;
+   __pset_pointer *ptrs ;   /* void Pointer to a Pointer */
+   unsigned max ;
+   unsigned count ;
+} ;
+
+
+/*
+ * INTERFACE
+ */
+
+typedef struct __pset *pset_h ;
+
+pset_h pset_create( unsigned alloc_start, unsigned alloc_step );
+void pset_destroy( pset_h pset );
+
+void pset_delete( pset_h pset, const __pset_pointer ptr );
+__pset_pointer pset_add( pset_h pset, const __pset_pointer ptr );
+
+/* These 2 are in ops.c   */
+void pset_compact( pset_h pset );
+void pset_apply( pset_h pset, void (*func)(), void *arg );
+
+/*
+ * Macros
+ */
+
+#define pset_remove( pset, ptr )   pset_delete( pset, (__pset_pointer)(ptr) )
+
+#define pset_remove_index( pset, i )                          \
+      {                                                       \
+         if ( ((unsigned)i) < (pset)->count )                 \
+             pset_delete(pset, (pset)->ptrs[ (unsigned)(i) ]);  \
+      }
+
+#define pset_clear( pset )           (pset)->count = 0
+#define pset_count( pset )           (pset)->count
+#define pset_pointer( pset, i )      (pset)->ptrs[ (unsigned)(i) ]
+
+#define pset_sort( pset, compfunc )                         \
+      (void) qsort( (char *) &pset_pointer( pset, 0 ),      \
+            pset_count( pset ), sizeof( __pset_pointer ), compfunc )
+
+/*
+ * PSET iterators
+ *
+ * Note that the iterators do NOT use any knowledge about the internals
+ * of pset's.
+ */
+struct __pset_iterator
+{
+   pset_h pset ;
+   unsigned current ;
+   int step ;
+} ;
+
+typedef struct __pset_iterator *psi_h ;
+void psi_remove( psi_h iter );
+
+#define __psi_current( iter )                             \
+   ( (iter)->current < pset_count( (iter)->pset )         \
+      ? pset_pointer( (iter)->pset, (iter)->current )     \
+      : NULL )
+
+#define psi_start( iter )                                 \
+      ( (iter)->current = 0, (iter)->step = 1,            \
+               __psi_current( iter ) )
+
+#define psi_next( iter )                   \
+      ( (iter)->current += (iter)->step, (iter)->step = 1,   \
+               __psi_current( iter ) )
+
+#define psi_destroy( iter )          free( (char *) iter )
+
+psi_h psi_create( pset_h pset );
+
+#endif   /* __PSET_H */
diff --git a/libs/src/pset/psi.3 b/libs/src/pset/psi.3
new file mode 100644 (file)
index 0000000..bd24184
--- /dev/null
@@ -0,0 +1,89 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: psi.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH PSET 3X "25 September 1992"
+.SH NAME
+psi_create, psi_destroy, psi_reset, psi_start, psi_next, psi_remove - pointer set iterator functions
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "pset.h"
+.LP
+.ft B
+psi_h psi_create( pset )
+pset_h pset ;
+.LP
+.ft B
+void psi_destroy( iter )
+psi_h iter ;
+.LP
+.ft B
+void psi_reset( iter, pset )
+psi_h iter ;
+pset_h pset ;
+.LP
+.ft B
+void *psi_start( iter )
+psi_h iter ;
+.LP
+.ft B
+void *psi_next( iter )
+psi_h iter ;
+.LP
+.ft B
+void psi_remove( iter )
+psi_h iter ;
+.SH DESCRIPTION
+These functions provide a means to iterate over psets (pointer sets).
+.LP
+.B psi_create()
+creates an iterator. The only operation that should be applied to
+an iterator after it is created is
+.B psi_start().
+.LP
+.B psi_destroy()
+destroys the iterator.
+.LP
+.B psi_reset()
+changes the pset that is being iterated to
+.I pset.
+.LP
+.B psi_start()
+starts an iteration and returns the first pointer
+in the pointer set.
+.LP
+.B psi_next()
+returns the next pointer in the set.
+.LP
+.B psi_remove()
+removes the current pointer from the set. The current pointer is
+the one returned most recently from either
+.B psi_start()
+or
+.B psi_next().
+.SH "RETURN VALUES"
+.LP
+.B psi_create()
+returns an iterator handle on success or
+.SM NULL
+on failure.
+.LP
+.B psi_start()
+returns the first pointer from the set or
+.SM NULL
+if the set is empty.
+.LP
+.B psi_next()
+returns a pointer or
+.SM NULL
+if the end of the set is reached.
+.SH WARNINGS
+.B psi_create()
+is the only function in this library. The rest of the interface is macros.
+.LP
+This interface may be eliminated in a future release of the
+.I pset
+library.
diff --git a/libs/src/sio/COPYRIGHT b/libs/src/sio/COPYRIGHT
new file mode 100644 (file)
index 0000000..d149511
--- /dev/null
@@ -0,0 +1,29 @@
+This software is
+
+(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that a) the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution, and b) this file is also included in any redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e. <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
diff --git a/libs/src/sio/Makefile.in b/libs/src/sio/Makefile.in
new file mode 100644 (file)
index 0000000..40ae2c5
--- /dev/null
@@ -0,0 +1,96 @@
+# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+#
+# Based on Library makefile template: *Revision: 1.15 *
+#
+
+NAME                   = sio
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = sio.h impl.h sioconf.h
+SOURCES                        = sprint.c sio.c siosup.c
+OBJECTS                        = sprint.o sio.o siosup.o
+
+MANFILES               = $(SRCDIR)/sio.3 $(SRCDIR)/Sprint.3
+INCLUDEFILES           = $(SRCDIR)/sio.h
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+DEBUG          = -g                    # -g or -O
+
+CPP_DEFS       = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS) -I$(INCLUDEDIR)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                        # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O lib
+       $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR)/optimized
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               $(RANLIB) $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+               for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
+               echo Installed $(MANFILES) to $(MANDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+       a=`pwd` ; cd $(MANDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+spotless: clean uninstall
+
+distclean: clean
+       rm -f Makefile
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+sprint.o:   sio.h impl.h sioconf.h
+sio.o:      sio.h impl.h sioconf.h 
+siosup.o:   sio.h impl.h sioconf.h 
+
diff --git a/libs/src/sio/README b/libs/src/sio/README
new file mode 100644 (file)
index 0000000..ce127e5
--- /dev/null
@@ -0,0 +1,128 @@
+======================================================================
+NOTE: I use vi with a tabstop value of 3. Using the same tabstop
+               value will make the text/code look properly indented.
+======================================================================
+
+
+1. What is SIO ?
+
+SIO is a library that provides _stream_ I/O which is what most Unix
+programs do. As such it is a competitor to stdio.
+
+
+2. Why would you care to use it ?
+
+a. SIO is a little faster than stdio
+b. SIO provides an easier-to-use interface (IMHO)
+c. SIO is capable of using memory mapping for reading files if the operating
+       system supports it.
+d. If you have a program that uses read(2)/write(2) it is trivial
+   to convert it to use SIO (just replace read with Sread and 
+   write with Swrite)
+e. You get source
+
+
+
+3. Setting up the Stream I/O (SIO) library
+
+There are 3 steps to the process:
+       1) modifying the SIO configuration file (but you can skip this
+               step if you are using one of the operating systems listed below).
+       2) testing SIO
+       3) installing the library and manpages
+
+
+3.1. How to compile the Stream I/O (SIO) library
+
+All the system-dependent stuff of SIO is placed in the sioconf.h file.
+If your system is not listed below, you will need to read that file
+to see what flags you need to set to properly compile SIO.
+
+For the following systems, here is what you need to do:
+
+       SunOS 4.x:
+               make "DEFS=-DHAVE_MMAP -DHAVE_ONEXIT -DHAVE_MEMCPY -DHAVE_ISATTY"
+
+       SunOS 5.x (aka Solaris 2.y):
+               make "DEFS=-DHAVE_MMAP -DHAVE_ATEXIT -DHAVE_MEMCPY -DHAVE_ISATTY"
+       (I don't have access to a system running Solaris 2.y so I have not
+       tested this)
+
+       Ultrix 4.x:
+               make "DEFS=-DHAVE_MEMCPY -DHAVE_ATEXIT -DHAVE_ISATTY"
+
+If your system is one of the above, then you can skip to the next subsection.
+However, I should mention that the library compiles by default with
+debugging enabled (i.e. uses the -g flag of cc). You can override this
+by appending to the invocation of 'make' the argument "DEBUG=-O"
+
+If your system is not among the above, then you will need to modify the
+sioconf.h file. You do this by uncommenting the inclusion of
+customconf.h. Then, you can override all constants/macros defined in
+sioconf.h by defining them first in customconf.h.  Please read
+sioconf.h for more information on what constants/macros can be
+defined.
+
+The Makefile has a header that explains what the Makefile can do.
+The only flag that you may want to define is -DDEBUG which enables 
+assertions in the SIO code (if an assertion fails, the program is 
+terminated with an error message that lists the SIO file and line 
+number where the error occured).
+
+
+3.2. Testing SIO
+
+After you have successfully compiled SIO, you can use the programs in
+the "suite" directory to test the SIO functions.  Testing should be
+done before installing the library.
+The script testlib does everything; just type:
+
+       testlib all
+
+The script sprint_test (invoked by testlib) tests Sprint by using a variety 
+of formats and comparing its output with that of an ANSI-compatible printf.
+At least on Ultrix 4.1 and 4.2 this test fails because printf is not 
+ANSI-compatible.
+In such a case, you can test the rest of the SIO functions by typing:
+
+       testlib all Sprint
+
+(anything after the 'all' argument is interpreted as a function that
+should not be tested).
+
+The README file in the "suite" directory describes how to do a
+few more tests that cannot be done automatically.
+
+
+3.3. Installing the library and manpages
+
+The 'make' command will create libsio.a in the current directory.
+The Makefile includes an "install" target. Doing a 'make install' will 
+cause the following:
+
+a) libsio.a will be installed in LIBDIR
+b) the necessary SIO header files will be installed in INCLUDEDIR
+c) the SIO man pages will be installed in MANDIR
+
+LIBDIR, INCLUDEDIR, and MANDIR are Makefile variables that you can edit in
+the Makefile or override when you invoke 'make'.
+Here is a sample command to install SIO:
+
+       make install LIBDIR=/usr/local/lib INCLUDEDIR=/usr/local/include MANDIR=/usr/local/man/man3
+
+
+4. Epilogue
+
+Feel free to modify SIO to suit your needs. Please let me know of
+any bugs you find.
+
+If you want to distribute your modifications, please read the COPYRIGHT
+file.  It basically says that you are free to redistribute as long as
+you retain the original copyright notice and you make sure that your
+modifications are identifiable. In order to achieve this I have
+reserved the first 3 components of the version number (for example,
+1.4.2) and you can identify your mods by appending another component to
+that version number (for example, 1.4.2.A2). Also, if you distribute a
+modified version of the library, you take full responsibility for any
+bugs in the code (not just your code; the whole thing).
+
diff --git a/libs/src/sio/Sprint.3 b/libs/src/sio/Sprint.3
new file mode 100644 (file)
index 0000000..31bc948
--- /dev/null
@@ -0,0 +1,157 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: Sprint.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH Sprint 3X "29 May 1992"
+.SH NAME
+Sprint -- formatted stream output
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+int Sprint( fd, format [ , ... ] )
+int fd ;
+char *format ;
+.SH DESCRIPTION
+\fBSprint()\fR provides formatted output conversion. The formatting is
+controlled by the \fIformat\fR argument. All characters in
+\fIformat\fR that do not specify a conversion are printed. A conversion
+is specified by a '%' followed by a string that ends with a
+conversion type character. The string may contain flags, a field width,
+a precision, and a modifier.
+.LP
+Possible flags (more that one can be specified and they can be in any order)
+include:
+.TP 10
+.B \'-'
+specifies left adjustment of the converted argument. The default
+is right adjustment. This flag is meaningful only if a field width
+is specified.
+.TP
+.B \'+'
+specifies that a number will always have a sign as a prefix (this
+forces a '+' sign to appear if the number is positive).
+.TP
+.B \' '
+prefixes a \fIspace\fR to the number if the number has not a sign
+(therefore the '+' flag overrides this flag).
+.TP
+.B \'#'
+The meaning of '#' depends on the conversion type character: for \fBo\fR 
+conversions the first digit will be 0; for \fBx\fR or \fBX\fR conversions
+\fB0x\fR or \fB0X\fR respectively will be prefixed to the number (if it
+is not zero); for \fBe\fR, \fBE\fR, \fBf\fR, \fBg\fR, and \fBG\fR conversions
+the number will always have a decimal point.
+.TP
+.B \'0'
+specifies padding with zeros instead of spaces.
+.LP
+The field width is specified by a number. This number indicates the
+\fIminimum\fR width for the field. A '*' may be used instead of the number.
+In that case the width is the value of the next argument which should
+be an \fBint\fR. 
+A negative width value specifies left adjustment with a width equal
+to the absolute width value.
+.LP
+A precision is specified by a '.' followed by a number. The meaning of
+the precision depends on the type conversion character. For a string
+conversion, precision determines how many characters are printed from
+the string. For integer conversions, precision determines the 
+number of digits used to print the number (zero padding is done if
+the precision exceeds the length of the number). For floating point
+conversions, precision determines the number of digits after the
+decimal point (\fBe\fR, \fBE\fR, \fBf\fR) or the number of
+significant digits (\fBg\fR, \fBG\fR).
+A '*' may be used instead of a number to specify the precision. In that
+case the precision is the value of the next argument which should
+be an \fBint\fR.
+The behavior of \fBSprint()\fR is undefined if the precision is negative.
+.LP
+The length modifier is \fBl\fR and indicates that the argument is
+a \fBlong\fR integer.
+.LP
+The type conversion characters are:
+\fBd, i, o, x, X, u, c, s, f, e, E, g, G, p, n, %\fR.
+For floating point conversions the argument should be of type \fIdouble\fR.
+.TP 10
+.B d,i
+specify signed decimal conversion.
+.TP
+.B u
+specifies unsigned decimal conversion.
+.TP
+.B o
+specifies octal conversion.
+.TP
+.B x,X
+specify hexadecimal conversion. For 
+.B x
+the hex digits used are 0123456789abcdef. For
+.B X
+the hex digits used are 0123456789ABCDEF.
+There is no leading
+.B 0x
+or
+.B 0X
+(use the '#' flag for that).
+.TP
+.B c
+specifies character conversion; the argument should be of type
+\fIchar\fR.
+.TP
+.B s
+specifies string conversion; the argument should be of type
+\fIchar *\fR.
+.TP
+.B f
+specifies conversion to the form [-]ddd.dddd. The number
+of digits after the decimal point depends on precision; the default is 6.
+If the precision is 0, the decimal point is not printed (this can
+be overriden with the '#' flag).
+.B e,E
+specify conversion to the form [-]ddd.dddd[eE][+-]ddd.
+The number of digits after the decimal point depends on precision;
+the default is 6. If the precision is 0, the decimal point is not printed
+(this can be overriden with the '#' flag).
+The exponent is at least 2 digit wide.
+.TP
+.B g,G
+specify a conversion using the
+.B e,E
+format respectively if the
+exponent is less than -4 or greater than or equal to the precision;
+otherwise the 
+.B f
+format is used.
+.TP
+.B p
+is used to print pointers (type \fIvoid *\fR,
+or \fIchar *\fR if the compiler does not support the former).
+.TP
+.B n
+expects a \fIint *\fR argument and puts in that integer 
+the number of characters already printed by this call.
+.TP
+.B %
+is used to print a \fI%\fR.
+.LP
+If an unknown conversion character is specified, the percent sign
+followed by that character will be printed.
+.SH RETURN VALUE
+.LP
+If no error occured, \fBSprint()\fR returns the number of characters
+printed. In case of error, it returns \fBSIO_ERR\fR.
+.SH BUGS
+.LP
+This is a list of differences between \fBSprint()\fR and the ANSI C Standard
+\fBprintf()\fR:
+.LP
+\fBSprint()\fR does not support non-removal of trailing zeroes for
+\fBg\fR and \fBG\fR conversions when the '#' flag is used.
+.LP
+\fBSprint()\fR does not support the h and L modifiers.
+.LP
+The current implementation assumes that \fIsizeof(int)==sizeof(long)\fR.
+.LP
+\fBSprint()\fR supports "%p" only if \fIsizeof(pointer)<=sizeof(int)\fR.
diff --git a/libs/src/sio/impl.h b/libs/src/sio/impl.h
new file mode 100644 (file)
index 0000000..f22cef2
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+/*
+ * $Id: impl.h,v 1.2 2003/03/09 19:29:21 steveg Exp $
+ */
+
+#ifndef SIO_BUFFER_SIZE
+
+#include "sioconf.h"
+#include "sio.h"
+
+#ifdef HAVE_MMAP
+#include <sys/types.h>
+
+
+/*
+ * A struct map_unit describes a memory mapped area of a file.
+ *
+ * addr is the address where the file is mapped. If addr is NULL
+ * the other fields are meaningless.
+ * valid_bytes indicates how many bytes are _valid_ in that unit
+ * mapped_bytes of a unit is how many bytes are mapped in that
+ * unit ( valid <= mapped ).
+ * Normally mapped_bytes will be equal to valid_bytes until
+ * we reach the end of the file. Then if the file size is not a multiple
+ * of the unit size, only the rest of the file will be mapped at the
+ * unit, leaving part of what was mapped at the unit before still
+ * visible (this happens because I chose not to unmap a unit before
+ * remapping it). In that case valid_bytes shows the size of the "new"
+ * mapping and mapped_bytes shows how many bytes are really mapped.
+ * mapped_bytes is used in Sdone() to unmap the units.
+ */
+struct map_unit
+{
+       caddr_t addr ;
+       size_t valid_bytes ;
+       size_t mapped_bytes ;
+} ;
+
+
+/*
+ * Meaning of fields used when memory mapping:
+ *
+ *    file_offset:      it is the offset in the file where the next
+ *                      mapping should be done
+ *
+ *    file_size:        size of the file (obtained from stat(2))
+ */
+struct mmap_descriptor
+{
+   off_t file_offset ;
+   off_t file_size ;
+       struct map_unit first_unit ;
+       struct map_unit second_unit ;
+} ;
+
+typedef struct mmap_descriptor mapd_s ;
+
+#endif /* HAVE_MMAP */
+
+typedef enum { FAILURE, SUCCESS } sio_status_e ;
+
+/*
+ * Descriptor management: convert a descriptor pointer to an input or
+ * output descriptor pointer
+ */
+#define IDP( dp )                                              (&(dp)->descriptor.input_descriptor)
+#define ODP( dp )                                              (&(dp)->descriptor.output_descriptor)
+
+#define DESCRIPTOR_INITIALIZED( dp )   ((dp)->initialized)
+
+/*
+ * Internal constants
+ */
+#define SIO_BUFFER_SIZE        8192
+#define SIO_NO_TIED_FD                         (-1)
+
+typedef enum { NO = 0, YES = 1 } boolean_e ;
+
+#ifndef FALSE
+#define FALSE                  0
+#define TRUE                   1
+#endif
+
+#ifndef NULL
+#define NULL                   0
+#endif
+
+#ifdef MIN
+#undef MIN
+#endif
+#define MIN( a, b )                                    ( (a) < (b) ? (a) : (b) )
+
+#define NUL                                                            '\0'
+
+#ifdef DEBUG
+
+static char *itoa( num )
+       unsigned num ;
+{
+#define NUMBUF_SIZE            15
+       static char numbuf[ NUMBUF_SIZE ] ;
+       char *p = &numbuf[ NUMBUF_SIZE ] ;
+
+       *--p = '\0' ;
+       do
+       {
+               *--p = num % 10 + '0' ;
+               num /= 10 ;
+       }
+       while ( num ) ;
+       return( p ) ;
+}
+
+#      define ASSERT( expr )                                                                                                           \
+               if ( ! (expr) )                                                                                                                 \
+               {                                                                                                                                                               \
+                       char *s1 = "SIO assertion << expr >> failed: File: " ;  \
+                       char *s2 = __FILE__ ;                                                                                           \
+                       char *s3 = ", line: " ;                                                                                         \
+                       char *s4 = itoa( __LINE__ ) ;                                                                           \
+                       char *s5 = "\n" ;                                                                                                               \
+                       (void) write( 2, s1, strlen( s1 ) ) ;                                                   \
+                       (void) write( 2, s2, strlen( s2 ) ) ;                                                   \
+                       (void) write( 2, s3, strlen( s3 ) ) ;                                                   \
+                       (void) write( 2, s4, strlen( s4 ) ) ;                                                   \
+                       (void) write( 2, s5, strlen( s5 ) ) ;                                                   \
+                       exit ( 1 ) ;                                                                                                                    \
+               }
+#else
+#      define ASSERT( expr )
+#endif
+
+
+#include <errno.h>
+
+/*
+ * Internal functions that are visible
+ */
+int __sio_writef( __sio_od_t *odp, int fd ) ;
+int __sio_extend_buffer( __sio_id_t *idp, int fd, int b_left ) ;
+int __sio_init( __sio_descriptor_t *dp, int fd, enum __sio_stream stream_type );
+int __sio_more( __sio_id_t *idp, int fd ) ;
+sio_status_e __sio_switch( __sio_id_t *idp, int fd ) ;
+
+
+#ifdef HAVE_MEMCPY
+#include <memory.h>
+#define sio_memcopy( from, to, nbytes )        (void) memcpy( to, from, nbytes )
+#define sio_memscan( from, nbytes, ch )   memchr( from, ch, nbytes )
+#else
+#define sio_memcopy( from, to, nbytes )      (void) bcopy( from, to, nbytes )
+#endif
+
+#ifndef sio_memcopy
+#define sio_memcopy            __sio_memcopy
+#define NEED_MEMCOPY
+void __sio_memcopy() ;
+#endif
+
+#ifndef sio_memscan
+char *sio_memscan() ;
+#endif
+
+#endif /* SIO_BUFFER_SIZE */
+
diff --git a/libs/src/sio/install-sh b/libs/src/sio/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/src/sio/sio.3 b/libs/src/sio/sio.3
new file mode 100644 (file)
index 0000000..6f02380
--- /dev/null
@@ -0,0 +1,416 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: sio.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH SIO 3X "29 May 1992"
+.SH NAME
+Sread, Sgetc, Srdline, Sfetch, Swrite, Sputc, Sprint, Sprintv, Sdone, Sundo, Stie, Suntie, Sflush, Sclose, Sbuftype, Smorefds, Sgetchar, Sputchar, SIOLINELEN - fast stream I/O
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "sio.h"
+#include <stdarg.h>
+.LP
+.ft B
+int Sread( fd, buf, nbytes )
+int fd ;
+char *buf ;
+int nbytes ;
+.LP
+.ft B
+int Sgetc( fd )
+int fd ;
+.LP
+.ft B
+char *Srdline( fd )
+int fd ;
+.LP
+.ft B
+char *Sfetch( fd, length )
+int fd ;
+long *length ;
+.LP
+.ft B
+int Swrite( fd, buf, nbytes )
+int fd ;
+char *buf ;
+int nbytes ;
+.LP
+.ft B
+int Sputc( fd, c )
+int fd ;
+char c ;
+.LP
+.ft B
+int Sprint( fd, format [ , ... ] )
+int fd ;
+char *format ;
+.LP
+.ft B
+int Sprintv( fd, format, ap )
+int fd ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+int Sdone( fd )
+int fd ;
+.LP
+.ft B
+int Sundo( fd, type )
+int fd ;
+int type ;
+.LP
+.ft B
+int Stie( ifd, ofd )
+int ifd, ofd ;
+.LP
+.ft B
+int Suntie( fd )
+int fd ;
+.LP
+.ft B
+int Sbuftype( fd, type )
+int fd, type ;
+.LP
+.ft B
+int Smorefds()
+.LP
+.ft B
+int Sflush( fd )
+int fd ;
+.LP
+.ft B
+int Sclose( fd )
+int fd ;
+.LP
+.ft B
+int Sgetchar( fd )
+int fd ;
+.LP
+.ft B
+int Sputchar( fd, c )
+int fd;
+char c ;
+.LP
+.ft B
+int SIOLINELEN( fd )
+int fd ;
+.SH DESCRIPTION
+The \fISIO\fR library provides support
+for \fIstream\fR I/O on file descriptors.
+The first argument of every function
+or macro is a file descriptor. The file descriptor may be used either for
+input or for output but not both. Attempting to use a descriptor for
+both input and output will cause the call to fail. When you are
+done with using a file descriptor, you should inform \fISIO\fR
+by invoking \fBSdone()\fR (unless the program is about to 
+call \fIexit(3)\fR).
+You can also use \fBSdone()\fR if
+you want to perform a different type of operation on the same
+file descriptor (e.g. first you were reading data from the file
+descriptor and then you want to write some data).
+Another possibility is to do stream I/O at different file offsets
+by using \fBSdone()\fR before doing the \fBlseek(2)\fR to the
+new file offset.
+.LP
+I/O operations on different file descriptors do not interfere
+(unless the file descriptors refer to the same file, in which case
+the results are undefined).
+.LP
+For disk files I/O always starts at the current file offset.
+If that offset is not a multiple of the preferred block size for file
+system I/O (the \fIst_blksize\fR field in \fIstruct stat\fR),
+performance will not be optimal.
+For optimal performance, it is recommended that no I/O operations
+(like \fIread(2)\fR or \fIwrite(2)\fR)
+are applied to the file descriptor if it is to be used by \fISIO\fR.
+.LP
+Read I/O is either buffered or is done using memory mapping whenever
+that is possible and appropriate.
+.LP
+The library functions that do stream I/O resemble system calls
+(for example \fBSread()\fR resembles \fIread(2)\fR) so that modifying
+a program that uses the system calls to use the \fISIO\fR functions
+is easy (e.g. just replace \fIread(2)\fR with \fBSread()\fR; the function
+signatures as well as the return values are exactly the same).
+.LP
+.B Sread()
+reads \fInbytes\fR bytes from the stream associated with file 
+descriptor \fIfd\fR into the buffer pointed to by \fIbuf\fR.
+.LP
+.B Sgetc()
+reads a character from the stream
+associated with file descriptor \fIfd\fR.
+It returns \fBSIO_EOF\fR if the end of file has been reached.
+.LP
+.B Sgetchar()
+(a macro) performs exactly the same function as \fBSgetc()\fR but
+it is much faster.
+.LP
+.B Srdline()
+reads a line from the stream
+associated with file descriptor \fIfd\fR.
+The newline at the end of the line is replaced by a 0 byte. Lines
+longer than the maximum line length supported by \fISIO\fR will
+have characters deleted.
+.LP
+.B SIOLINELEN()
+(a macro) returns the length of
+the line returned by the last call to \fBSrdline()\fR
+(the value returned by \fBSIOLINELEN()\fR is valid only after
+\fBSrdline()\fR and as long as no other 
+\fISIO\fR calls are performed on that file descriptor).
+.LP
+.B Sfetch()
+returns a pointer to data coming from the stream
+associated with file
+descriptor \fIfd\fR. The amount of data available is indicated
+by the \fIlength\fR argument. One possible use for this function
+is copying of files.
+.LP
+.B Swrite()
+writes \fInbytes\fR bytes to the stream associated with file
+descriptor \fIfd\fR from the buffer pointed to by \fIbuf\fR.
+.LP
+.B Sputc()
+writes a single character to the stream
+associated with file descriptor \fIfd\fR.
+.LP
+.B Sputchar()
+(a macro) performs exactly the same function as \fBSputc()\fR
+but it is much faster.
+.LP
+.B Sprint()
+imitates the behavior of printf(3) as defined in the
+ANSI C Standard. There are some limitations. Check the \fBSprint()\fR
+man page for more information.
+.LP
+.B Sprintv()
+is the same as \fBSprint()\fR except that it takes a
+\fIstdarg\fR argument list.
+.LP
+.B Sundo()
+returns the characters returned by the last call to
+\fBSrdline()\fR, \fBSgetc()\fR or \fBSgetchar()\fR to the stream
+so that they can be reread. The \fItype\fR argument to \fBSundo()\fR
+can be \fBSIO_UNDO_LINE\fR or \fBSIO_UNDO_CHAR\fR depending
+on whether the call whose effect needs to be undone was
+\fBSrdline()\fR or \fBSgetc()\fR/\fBSgetchar()\fR respectively.
+There is no check on
+whether the last function invoked on \fIfd\fR was one of the above
+and the results are undefined if there is no correspondence
+between the \fItype\fR and the last operation on \fIfd\fR.
+(i.e. the result is undefined if you try \fBSIO_UNDO_CHAR\fR 
+and the last operation was not \fBSgetchar()\fR or \fBSgetc()\fR).
+.LP
+.B Stie()
+ties the file descriptor \fIifd\fR to the file descriptor \fIofd\fR.
+This means that whenever a \fIread(2)\fR is done on \fIifd\fR, it is
+preceded by a \fIwrite(2)\fR on \fIofd\fR.
+For filters it is useful to do \fIStie( 0, 1 )\fR to maximize concurrency.
+It is also useful to do the same thing when you issue prompts to the
+user and you want the user reply to appear on the same line with the
+prompt.
+\fIifd\fR, \fIofd\fR  will be initialized for input, output respectively
+(if any of them is initialized, it must be for the appropriate
+stream type (input or output)).
+If \fIifd\fR was tied to another file descriptor, the old tie is broken.
+.LP
+.B Suntie()
+undoes the effect of \fBStie()\fR for the specified input file descriptor.
+.LP
+.B Sbuftype()
+determines the buffering type for the output stream associated with
+file descriptor \fIfd\fR.
+By default output directed to terminals is line buffered, output
+directed to file descriptor 2 (standard error) is unbuffered and
+everything else is fully buffered.
+Possible values for the \fItype\fR argument are
+.RS
+.TP 15
+.B SIO_FULLBUF
+for full buffering
+.TP
+.B SIO_LINEBUF
+for line buffering
+.TP
+.B SIO_NOBUF
+for no buffering
+.RE
+.LP
+.B Smorefds()
+should be used to inform \fBSIO\fR that the number of available file
+descriptors has been increased. \fBSIO\fR uses an array of internal
+stream descriptors which are indexed by the file descriptor number. Some
+operating systems (ex. SunOS 4.1[.x]) allow the number of available
+file descriptors to vary. If that number is increased beyond its initial
+value \fBSIO\fR needs to know in order to allocate more stream descriptors.
+.LP
+.B Sdone()
+flushes any buffered output for \fIfd\fR 
+and releases the \fISIO\fR resources used. \fBSdone()\fR 
+is useful in case the program needs to reprocess the
+data of a file descriptor (assuming the file descriptor corresponds
+to a file).  The program can call \fBSdone()\fR,
+\fIlseek(2)\fR to the beginning of the file
+and then proceed to reread the file.
+.LP
+.B Sflush()
+causes any buffered stream output to be written to the
+file descriptor. If its argument is the special value \fBSIO_FLUSH_ALL\fR
+then all output streams will be flushed.
+.LP
+.B Sclose()
+closes a file descriptor used for stream I/O, flushes
+any buffered output and releases the \fISIO\fR resources used.
+.SH EXAMPLES
+.LP
+The following code implements a (poor) substitute for the tee command
+(it copies standard input to a file as well as to standard output).
+.ne 10
+.RS
+.nf
+.ft B
+#include "sio.h"
+.sp .5
+main( argc, argv )
+       int argc ;
+       char *argv[] ;
+{
+       char *file = (argc > 1) ? argv[ 1 ] : "tee.file" ;
+       int fd = creat( file, 0644 ) ;
+       long length ;
+       char *s ;
+.sp .5
+       while ( s = Sfetch( 0, &length ) )
+       {
+               Swrite( 1, s, length ) ;
+               Swrite( fd, s, length ) ;
+       }
+       exit( 0 ) ;
+}
+.fi
+.ft R
+.RE
+.SH RETURN VALUES
+.LP
+.B Sread()
+returns the number of bytes read on success
+(0 means end-of-file)
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sgetc()
+returns the character read on success,
+SIO_EOF when the end-of-file is reached,
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Srdline()
+returns a pointer to the next line on success.
+On failure or when the end-of-file is reached it returns
+.SM NULL.
+If the end-of-file is reached \fIerrno\fR is set to 0, otherwise it indicates
+the error.
+.LP
+.B Sfetch()
+returns a pointer to file data on success.
+(the \fIlength\fR argument indicates how many bytes
+are available).
+On failure or when the end-of-file is reached it returns
+.SM NULL.
+If the end-of-file is reached \fIerrno\fR is set to 0, otherwise it indicates
+the error.
+.LP
+.B Swrite()
+returns the number of bytes written on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sputc()
+returns the character it was given as an argument on success
+.B Sprint()
+returns the number of characters printed on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sdone()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sundo()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Stie()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Suntie()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure
+(\fIerrno\fR is set to \fBEBADF\fR if there
+was no tied file descriptor).
+.LP
+.B Sbuftype()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure
+(\fIerrno\fR is set to \fBEBADF\fR if this is not an output stream
+or to \fBEINVAL\fR if an unknown \fItype\fR is specified).
+.LP
+.B Smorefds()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (because of lack of memory).
+.LP
+.B Sflush()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sclose()
+returns \fB0\fR on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sgetchar()
+returns the character read on success,
+SIO_EOF when the end-of-file is reached,
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B Sputchar()
+returns the character it was given as an argument on success
+or \fBSIO_ERR\fR on failure (\fIerrno\fR is set to indicate the error).
+.LP
+.B SIOLINELEN()
+returns the length of the last line read by \fBSrdline()\fR.
+.LP
+Attempting a read operation on a descriptor opened for writing or vice
+versa will cause the operation to fail with \fIerrno\fR set to \fBEBADF\fR.
+.LP
+The first \fISIO\fR operation on a descriptor must be a read or write
+operation. It cannot be a control operation (like \fBSflush()\fR). Such
+an operation will fail with \fIerrno\fR set to \fBEBADF\fR.
+.LP
+.IP "\fBNOTE 1:\fR" 15
+\fBStie()\fR is an input/output operation for the
+respective file descriptors, not a control operation. \fBSuntie()\fR
+is a control operation.
+.IP "\fBNOTE 2:\fR"
+\fBSIO_ERR\fR is defined to be \fB-1\fR.
+.SH "SEE ALSO"
+.LP
+Sprint(3)
+.SH BUGS
+.LP
+If the operating system does not provide for invocation of a
+finalization function upon exit, the program will have to
+explicitly flush all output streams.
+The following operating systems provide such a facility:
+SunOS 4.x, Ultrix 4.x.
+.LP
+Socket file descriptors can be used for input as well as output but
+\fBSIO\fR does not support this.
+.LP
+The current implementation will not try to use memory mapping to
+read a file if the file offset is not 0 (it will use buffered I/O instead).
+.LP
+Pointers returned by \fBSfetch()\fR point to read-only memory.
+Attempting to modify this memory will result in a segmentation
+violation.
diff --git a/libs/src/sio/sio.c b/libs/src/sio/sio.c
new file mode 100644 (file)
index 0000000..58f70b4
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * (c) Portions Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#ifndef linux
+#include <sys/types.h>
+#endif
+
+#ifdef _APPLE_
+#undef HAVE_MMAP
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "sio.h"
+#include "impl.h"
+
+/*
+ * SIO WRITE FUNCTIONS: Swrite, Sputc
+ */
+
+/*
+ * Stream write call: arguments same as those of write(2)
+ */
+int Swrite( int fd, const char *addr, unsigned int nbytes )
+{
+       __sio_descriptor_t *dp ;
+       __sio_od_t *odp ;
+       unsigned int b_transferred ;
+       unsigned int b_avail ;
+       int total_b_transferred ;
+       int b_written ;
+       int b_in_buffer ;
+
+       if ( nbytes > INT_MAX )
+               return( SIO_ERR );
+       if( sio_setup( fd, &dp, __SIO_OUTPUT_STREAM ) == SIO_ERR )
+               return( SIO_ERR );
+       odp = ODP( dp ) ;
+       ASSERT( odp->start <= odp->nextb && odp->nextb <= odp->buf_end ) ;
+
+       b_avail = odp->buf_end - odp->nextb ;
+       b_transferred = MIN( nbytes, b_avail ) ;
+       sio_memcopy( addr, odp->nextb, b_transferred ) ;
+       odp->nextb += b_transferred ;
+
+       /*
+        * check if we are done
+        */
+       if ( b_transferred == nbytes )
+               return( b_transferred ) ;
+
+       /*
+        * at this point we know that the buffer is full
+        */
+       b_in_buffer = odp->buf_end - odp->start ;
+       b_written = __sio_writef( odp, fd ) ;
+       if ( b_written != b_in_buffer )
+               return( (b_written >= (int)nbytes) ? (int)nbytes : b_written ) ;
+       
+       total_b_transferred = b_transferred ;
+       addr += b_transferred ;
+       nbytes -= b_transferred ;
+
+       for ( ;; )
+       {
+               b_transferred = MIN( nbytes, odp->buffer_size ) ;
+               sio_memcopy( addr, odp->nextb, b_transferred ) ;
+               odp->nextb += b_transferred ;
+               nbytes -= b_transferred ;
+               if ( nbytes == 0 )
+               {
+                       total_b_transferred += b_transferred ;
+                       break ;
+               }
+               /*
+                * the buffer is full
+                */
+               b_written = __sio_writef( odp, fd ) ;
+               if ( b_written != (int)odp->buffer_size )
+               {
+                       if ( b_written != SIO_ERR )
+                       {
+                               total_b_transferred += b_written ;
+                               odp->nextb += b_written ;
+                       }
+                       break ;
+               }
+               /*
+                * everything is ok
+                */
+               total_b_transferred += b_transferred ;
+               addr += b_transferred ;
+       }
+       return( total_b_transferred ) ;
+}
+
+
+/*
+ * Add a character to a file
+ */
+static int Sputc( int fd, char c )
+{
+       __sio_descriptor_t *dp ;
+       __sio_od_t *odp ;
+
+       if( sio_setup( fd, &dp, __SIO_OUTPUT_STREAM) == SIO_ERR )
+               return( SIO_ERR );
+       odp = ODP( dp ) ;
+       ASSERT( odp->start <= odp->nextb && odp->nextb <= odp->buf_end ) ;
+
+       /*
+        * The following is a weak check since we should really be
+        * checking that nextb == buf_end (it would be an error for
+        * nextb to exceed buf_end; btw, the assertion above, when
+        * enabled makes sure this does not occur).
+        *
+        * NOTE: __sio_writef NEVER uses data beyond the end of buffer.
+        */
+       if ( odp->nextb >= odp->buf_end )
+       {
+               int b_in_buffer = odp->buf_end - odp->start ;
+
+               /*
+                * There is nothing we can do if __sio_writef does not manage
+                * to write the whole buffer
+                */
+               if ( __sio_writef( odp, fd ) != b_in_buffer )
+                       return( SIO_ERR ) ;
+       }
+       *odp->nextb++ = c ;
+       if ( __SIO_MUST_FLUSH( *odp, c ) && __sio_writef( odp, fd ) == SIO_ERR )
+               return( SIO_ERR ) ;
+       return ( c ) ;
+}
+
+
+
+/*
+ * SIO READ FUNCTIONS
+ */
+
+
+/*
+ * Read a line from a file
+ * Returns a pointer to the beginning of the line or NULL
+ */
+char *Srdline( int fd )
+{
+       __sio_descriptor_t *dp ;
+       __sio_id_t *idp ;
+       char *cp ;
+       char *line_start ;
+       int b_left ;
+       int extension ;
+
+       if( sio_setup( fd, &dp, __SIO_INPUT_STREAM ) == SIO_ERR )
+               return( NULL );
+       idp = IDP( dp ) ;
+       ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
+
+#ifdef HAVE_MMAP
+       if ( idp->memory_mapped && __sio_switch( idp, fd ) == FAILURE )
+               return( NULL ) ;
+#endif
+
+       b_left = idp->end - idp->nextb ;
+       /*
+        * Look for a '\n'. If the search fails, extend the buffer
+        * and search again (the extension is performed by copying the
+        * bytes that were searched to the auxiliary buffer and reading 
+        * new input in the main buffer).
+        * If the new input still does not contain a '\n' and there is
+        * more space in the main buffer (this can happen with network
+        * connections), read more input until either the buffer is full
+        * or a '\n' is found.
+        * Finally, set cp to point to the '\n', and line_start to
+        * the beginning of the line
+        */
+       if ( b_left && ( cp = sio_memscan( idp->nextb, b_left, '\n' ) ) != NULL )
+       {
+               line_start = idp->nextb ;
+               idp->nextb = cp + 1 ;
+       }
+       else
+       {
+               extension = __sio_extend_buffer( idp, fd, b_left ) ;
+               if ( extension > 0 )
+               {
+                       ASSERT( idp->start <= idp->nextb && idp->nextb <= idp->end ) ;
+
+                       line_start = idp->start ;
+                       cp = sio_memscan( idp->nextb, extension, '\n' ) ;
+                       if ( cp != NULL )
+                               idp->nextb = cp + 1 ;
+                       else
+                               for ( ;; )
+                               {
+                                       idp->nextb = idp->end ;
+                                       extension = __sio_more( idp, fd ) ;
+                                       if ( extension > 0 )
+                                       {
+                                               cp = sio_memscan( idp->nextb, extension, '\n' ) ;
+                                               if ( cp == NULL )
+                                                       continue ;
+                                               idp->nextb = cp + 1 ;
+                                               break ;
+                                       }
+                                       else
+                                       {
+                                               /*
+                                                * If there is spare room in the buffer avoid trashing
+                                                * the last character
+                                                */
+                                               if ( idp->end < &idp->buf[ idp->buffer_size ] )
+                                                       cp = idp->end ;
+                                               else
+                                                       cp = &idp->buf[ idp->buffer_size - 1 ] ;
+                                               break ;
+                                       }
+                               }
+               }
+               else                                    /* buffer could not be extended */
+                       if ( b_left == 0 )
+                       {
+                               /*
+                                * Set errno to 0 if EOF has been reached
+                                */
+                               if ( extension == 0 )
+                                       errno = 0 ;
+                               return( NULL ) ;
+                       }
+                       else
+                       {
+                               line_start = idp->start ;
+                               cp = idp->end ;
+                               /*
+                                * By setting idp->nextb to be equal to idp->end,
+                                * subsequent calls to Srdline will return NULL because
+                                * __sio_extend_buffer will be invoked and it will return 0.
+                                */
+                               idp->nextb = idp->end ;
+                       }
+       }
+       *cp = NUL ;
+       idp->line_length = cp - line_start ;
+       return( line_start ) ;
+}
+
+
+
+/*
+ * SIO CONTROL FUNCTIONS
+ */
+
+
+/*
+ * Flush the buffer associated with the given file descriptor
+ * The special value, SIO_FLUSH_ALL flushes all buffers
+ *
+ * Return value:
+ *                     0 :  if fd is SIO_FLUSH_ALL or if the flush is successful
+ *             SIO_ERR: if fd is not SIO_FLUSH_ALL and
+ *                                                             the flush is unsuccessful
+ *                                                     or the descriptor is not initialized or it is not 
+ *                                                             an output descriptor
+ */
+int Sflush( int fd )
+{
+   __sio_descriptor_t *dp ;
+   int b_in_buffer ;
+
+   if ( fd == SIO_FLUSH_ALL )
+   {
+      for ( fd = 0, dp = __sio_descriptors ;
+                               fd < __sio_n_descriptors ;
+                               dp++, fd++ )
+         if ( DESCRIPTOR_INITIALIZED( dp ) &&
+                                                       dp->stream_type == __SIO_OUTPUT_STREAM )
+            (void) __sio_writef( ODP( dp ), fd ) ;
+      return( 0 ) ;
+   }
+   else
+   {
+      if ( fd >= __sio_n_descriptors ) {
+         errno = EBADF ;
+         return( SIO_ERR ) ;
+      }
+
+      dp = &__sio_descriptors[ fd ] ;
+
+      if( (! DESCRIPTOR_INITIALIZED( dp )) || 
+            (dp->stream_type != __SIO_OUTPUT_STREAM) )
+         return( SIO_ERR );
+
+      b_in_buffer = ODP( dp )->nextb - ODP( dp )->start ;
+      if ( __sio_writef( ODP( dp ), fd ) != b_in_buffer )
+         return( SIO_ERR ) ;
+      else
+         return( 0 ) ;
+   }
+}
+
+
+/*
+ * Close the file descriptor. This call is provided because
+ * a file descriptor may be closed and then reopened. There is
+ * no easy way for SIO to identify such a situation, so Sclose
+ * must be used.
+ *
+ * Sclose invokes Sdone which finalizes the buffer.
+ * There is no SIO_CLOSE_ALL value for fd because such a thing
+ * would imply that the program will exit very soon, therefore
+ * the closing of all file descriptors will be done in the kernel
+ * (and the finalization will be done by the finalization function
+ * NOTE: not true if the OS does not support a finalization function)
+ *
+ * There is no need to invoke SETUP; Sdone will do it.
+ */
+int Sclose( int fd )
+{
+       if ( __SIO_FD_INITIALIZED( fd ) ) {
+               if ( Sdone( fd ) == SIO_ERR ) {
+                       close( fd ); 
+                       return( SIO_ERR ) ;
+               }
+       }
+       return( close( fd ) ) ;
+}
+
+
+/*
+ * Changes the type of buffering on the specified descriptor.
+ * As a side-effect, it initializes the descriptor as an output stream.
+ */
+int Sbuftype( int fd, int type )
+{
+       __sio_descriptor_t *dp ;
+
+       /*
+        * Check for a valid type
+        */
+       if ( type != SIO_LINEBUF && type != SIO_FULLBUF && type != SIO_NOBUF )
+       {
+               errno = EINVAL ;
+               return( SIO_ERR ) ;
+       }
+
+       if( sio_setup( fd, &dp, __SIO_OUTPUT_STREAM ) == SIO_ERR )
+               return( SIO_ERR );
+       ODP( dp )->buftype = type ;
+       return( 0 ) ;
+}
+
+
+#ifndef sio_memscan
+
+static char *sio_memscan( const char *from, int how_many, char ch )
+{
+   char *p ;
+   char *last = from + how_many ;
+
+   for ( p = from ; p < last ; p++ )
+      if ( *p == ch )
+         return( p ) ;
+      return( 0 ) ;
+}
+
+#endif /* sio_memscan */
+
+
+#ifdef NEED_MEMCOPY
+
+void __sio_memcopy( const char *from, char *to, int nbytes )
+{
+   while ( nbytes-- )
+      *to++ = *from++ ;
+}
+
+#endif /* NEED_MEMCOPY */
+
+int sio_setup(int fd, __sio_descriptor_t **dp, unsigned int type)
+{
+   if ( fd >= __sio_n_descriptors ) {
+      if( Smorefds(fd) != 0 ) {
+         errno = EBADF;
+         return(SIO_ERR);
+      }
+   }
+
+   *dp = &__sio_descriptors[ fd ];
+
+   if( DESCRIPTOR_INITIALIZED( *dp ) ) {
+      if( (*dp)->stream_type != type ) {
+         errno = EBADF;
+         return( SIO_ERR );
+      }
+   } else if( __sio_init(*dp, fd, type) == SIO_ERR )
+      return( SIO_ERR );
+
+   return( 0 );
+}
+
+/*
+ * The Sputchar function depends on the fact that the fields
+ *                              nextb, buf_end, end
+ * are 0 if a stream descriptor is not being used or has not yet been
+ * initialized.
+ * This is true initially because of the static allocation of the
+ * descriptor array, and Sdone must make sure that it is true
+ * after I/O on a descriptor is over.
+ */
+int Sputchar( int fd, char c )
+{
+   int ret = 0;
+
+   if( __SIO_OD( fd ).nextb < __SIO_OD( fd ).buf_end ) {
+      if( __SIO_OD(fd).buftype == SIO_FULLBUF ) {
+         ret = *(__SIO_OD(fd).nextb)++ = (unsigned char) (c);
+      } else if ( __SIO_OD(fd).buftype == SIO_LINEBUF ) {
+         if( (*(__SIO_OD(fd).nextb) = (unsigned char)(c)) != '\n' ) {
+            ret = *(__SIO_OD(fd).nextb)++;
+         } else {
+            ret = Sputc( fd, *(__SIO_OD(fd).nextb) );
+         }
+      } else {
+         ret = Sputc( fd, c );
+      }
+   } else {
+      ret = Sputc( fd, c );
+   }
+
+   return ret;
+}
+
+
diff --git a/libs/src/sio/sio.h b/libs/src/sio/sio.h
new file mode 100644 (file)
index 0000000..dfc3af1
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+/*
+ * $Id: sio.h,v 1.6 2003/06/10 13:15:44 steveg Exp $
+ */
+
+#ifndef __SIO_H
+#define __SIO_H
+
+#include <errno.h>
+#include <stdarg.h>
+
+/*
+ * Naming conventions:
+ *             1) SIO functions and macros have names starting with a capital S
+ *             2) SIO constants meant to be used by user programs have 
+ *                     names starting with SIO_
+ *             3) Internal functions, struct identifiers, enum identifiers 
+ *                     etc. have names starting with __sio
+ *             4) Internal constants and macros have names starting with __SIO
+ */
+
+
+/*
+ * external constants
+ *
+ * SIO_FLUSH_ALL: flush all output streams
+ * SIO_ERR: operation failed
+ * SIO_EOF:    eof on stream
+ * #define SIO_EOF                             (-2)
+ */
+#define SIO_FLUSH_ALL                          (-1)
+#define SIO_ERR                                        (-1)
+
+/*
+ * Buffering types
+ */
+#define SIO_FULLBUF                    0
+#define SIO_LINEBUF                    1
+#define SIO_NOBUF                      2
+
+/*
+ * Descriptor for an input stream
+ */
+struct __sio_input_descriptor
+{
+       /*
+        * buf:         points to the buffer area.
+        *              When doing memory mapping, it is equal to the unit 
+        *              from which we are reading. When doing buffered I/O
+        *              it points to the primary buffer. The auxiliary
+        *              buffer is right below buf and is of the same size.
+        */
+       char *buf ;
+       unsigned buffer_size ;
+
+       char *start ;                 /* start of valid buffer contents         */
+       char *end ;                   /* end of valid buffer contents + 1       */
+       char *nextb ;                 /* pointer to next byte to read/write     */
+                                                                                       /* Always:  start <= nextb < end                        */
+
+       unsigned line_length ;
+       int max_line_length ;
+       int tied_fd ;
+
+       int memory_mapped ;                             /* flag to denote if we use                             */
+                                                                                       /* memory mapping                                                               */
+} ;
+
+typedef struct __sio_input_descriptor __sio_id_t ;
+
+
+/*
+ * Descriptor for an output stream
+ */
+struct __sio_output_descriptor
+{
+       /*
+        * buf:         points to the buffer area.
+        * buf_end: is equal to buf + buffer_size
+        */
+       char *buf ;
+       char *buf_end ;
+
+       unsigned buffer_size ;
+
+       char *start ;                 /* start of valid buffer contents         */
+                                                                                       /* (used by the R and W functions)              */
+       char *nextb ;                 /* pointer to next byte to read/write  */
+                                                                                       /* Always:  start <= nextb < buf_end    */
+       int buftype ;                                           /* type of buffering                                            */
+} ;
+
+typedef struct __sio_output_descriptor __sio_od_t ;
+
+
+
+/*
+ * Stream types
+ */
+enum __sio_stream { __SIO_INPUT_STREAM, __SIO_OUTPUT_STREAM } ;
+
+
+/*
+ * General descriptor
+ */
+struct __sio_descriptor
+{
+       union
+       {
+               __sio_id_t input_descriptor ;
+               __sio_od_t output_descriptor ;
+       } descriptor ;
+       enum __sio_stream stream_type ;
+       int initialized ;
+} ;
+
+typedef struct __sio_descriptor __sio_descriptor_t ;
+
+
+/*
+ * The array of descriptors (as many as available file descriptors)
+ */
+extern int __sio_n_descriptors ;
+extern __sio_descriptor_t *__sio_descriptors ;
+
+
+/*
+ * Internally used macros
+ */
+#define __SIO_FD_INITIALIZED( fd ) \
+   (fd >= 0 && fd < __sio_n_descriptors && __sio_descriptors[ fd ].initialized)
+#define __SIO_ID( fd ) (__sio_descriptors[ fd ].descriptor.input_descriptor)
+#define __SIO_OD( fd ) (__sio_descriptors[ fd ].descriptor.output_descriptor)
+#define __SIO_MUST_FLUSH( od, ch )                             \
+                       ( (od).buftype != SIO_FULLBUF &&        \
+                       ( (od).buftype == SIO_NOBUF || ch == '\n' ) )
+
+
+/*
+ * SIO Macros:
+ *
+ *             SIOLINELEN( fd )
+ *
+ * NOTE: The maximum line size depends on whether the descriptor
+ *     was originally memory mapped. If it was, then the maximum
+ *     line size will be the map_unit_size (a function of the system
+ *     page size and PAGES_MAPPED). Otherwise, it will be either the
+ *     optimal block size as reported by stat(2) or SIO_BUFFER_SIZE.
+ */
+
+#define SIOLINELEN( fd )      __SIO_ID( fd ).line_length 
+
+/*
+ * The Read functions
+ */
+char *Srdline ( int fd ) ;
+
+/*
+ * The Write functions
+ */
+int Swrite ( int fd, const char *buf, unsigned int nbytes );
+int Sprint ( int fd, const char *format, ... )
+#ifdef __GNUC__
+       __attribute__ ((format (printf, 2, 3)));
+#else
+       ;
+#endif
+int Sputchar( int fd, char c );
+int Sprintv ( int fd, const char *format, va_list ap )
+#ifdef __GNUC__
+       __attribute__ ((format (printf, 2, 0)));
+#else
+       ;
+#endif
+
+/*
+ * other functions
+ */
+int Sdone ( int fd ) ;
+int Sflush ( int fd ) ;
+int Sclose ( int fd ) ;
+int Sbuftype ( int fd, int type ) ;
+int Smorefds ( int ) ;
+int __sio_converter( __sio_od_t *, int , const char *, va_list );
+int sio_setup(int fd, __sio_descriptor_t **dp, unsigned int type );
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void terminate(const char *);
+
+#endif /* __SIO_H */
+
diff --git a/libs/src/sio/sioconf.h b/libs/src/sio/sioconf.h
new file mode 100644 (file)
index 0000000..5f8fd13
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+/*
+ * $Id: sioconf.h,v 1.3 2003/03/09 19:27:07 steveg Exp $
+ */
+
+/*
+ * This file has 2 sections:
+ *             1. a OS-specific section
+ *             2. a CPU/compiler-specific section
+ *
+ * You can override/redefine any of the constants/macros in this file.
+ * by uncommenting the inclusion of customconf.h and placing your own
+ * definitions in that file.
+ */
+
+/* #include "customconf.h" */
+
+
+
+/*
+ * OS-specific section.
+ *
+ * Features here use the flag HAVE_<feature>.
+ * List of flags (check the following for macros that can be overridden):
+ *
+ *                     HAVE_MMAP (overridable macros)
+ *
+ *                     HAVE_ATEXIT
+ *                     HAVE_ONEXIT
+ *                     HAVE_OTHER_FINALIZER    (must define macros)
+ *
+ *                     HAVE_MEMCPY
+ *                     HAVE_BCOPY                      (HAVE_MEMCPY will be preferred if both are defined)
+ *
+ *     At least one of the following flags must be defined. The 2nd and 3rd
+ * flags are incompatible.
+ *                     HAVE_ISATTY
+ *                     HAVE_SYSVTTY
+ *                     HAVE_BSDTTY
+ */
+
+/*
+ * Memory mapping.
+ *             The library requires 3 macros: SIO_MMAP, SIO_MUNMAP, SIO_MNEED.
+ *             You can selectively override any of them.
+ *             Notice that the SIO_MNEED macro is not required. If your system
+ *             does not have madvise, you can define the macro as:
+ *                     #define SIO_MNEED( addr, len )
+ */
+#ifdef HAVE_MMAP
+
+#if !defined( SIO_MMAP ) || !defined( SIO_MUNMAP ) || !defined( SIO_MNEED )
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+
+#ifndef SIO_MMAP
+#define SIO_MMAP( addr, len, fd, off )                                  \
+         mmap( addr, len, PROT_READ,                                    \
+            ( addr == 0 ) ? MAP_PRIVATE : MAP_PRIVATE + MAP_FIXED,      \
+               fd, off )
+#endif
+
+#ifndef SIO_MUNMAP
+#define SIO_MUNMAP( addr, len )  munmap( addr, len )
+#endif
+
+#ifndef SIO_MNEED
+#if defined(linux)
+#define SIO_MNEED( addr, len )
+#else
+#define SIO_MNEED( addr, len )      (void) madvise( addr, len, MADV_WILLNEED )
+#endif
+#endif
+
+#endif /* HAVE_MMAP */
+
+/*
+ * N_SIO_DESCRIPTORS is the maximum number of file descriptors
+ * supported by the OS
+ */
+#include <sys/param.h>
+#ifdef OPEN_MAX
+#define N_SIO_DESCRIPTORS              OPEN_MAX
+#else
+#define N_SIO_DESCRIPTORS              NOFILE
+#endif
+
+
+
+/*
+ * Finalization function. 
+ *
+ * The purpose of this function is to do work after your program has
+ * called exit(3). In the case of SIO, this means flushing the SIO
+ * output buffers.
+ *
+ * If your system does not support atexit or onexit but has some other
+ * way of installing a finalization function, you define the flag 
+ * HAVE_FINALIZER. Then you must define the macros 
+ *                     SIO_FINALIZE and SIO_DEFINE_FIN
+ *
+ * SIO_FINALIZE attempts to install a finalization function and returns TRUE 
+ * if successful, FALSE if unsuccessful.
+ * SIO_DEFINE_FIN defines the finalization function (the reason for this macro
+ * s that different systems pass different number/type of arguments to the
+ * finalization function; the SIO finalization function does not use any
+ * arguments).
+ */
+#if defined(HAVE_ONEXIT) || defined(HAVE_ATEXIT) || defined(HAVE_FINALIZER)
+
+#define HAVE_FINALIZATION_FUNCTION
+
+#if defined( HAVE_ONEXIT ) && defined( HAVE_ATEXIT )
+#undef HAVE_ONEXIT
+#endif
+
+#ifdef HAVE_ONEXIT
+#define SIO_FINALIZE( func )        ( on_exit( func, (caddr_t) 0 ) == 0 )
+#define SIO_DEFINE_FIN( func )      static void func ( exit_status, arg )  \
+                                          int exit_status ;                \
+                                          caddr_t arg ;
+#endif /* HAVE_ONEXIT */
+
+#ifdef HAVE_ATEXIT
+#define SIO_FINALIZE( func )        ( atexit( func ) == 0 )
+#define SIO_DEFINE_FIN( func )      static void func ()
+#endif /* HAVE_ATEXIT */
+
+#endif /* HAVE_ONEXIT || HAVE_ATEXIT || HAVE_FINALIZER */
+
+
+/*
+ * HAVE_MEMCPY should be defined if your OS supports the mem* functions
+ * (memcpy etc). If not, then you can define HAVE_BCOPY if your OS supports 
+ * bcopy.
+ */
+#if defined( HAVE_MEMCPY ) && defined( HAVE_BCOPY )
+#undef HAVE_BCOPY
+#endif
+
+
+/*
+ * Support for the isatty(3) function. This function identifies if a 
+ * descriptor refers to a terminal.
+ *
+ * Case 1: isatty(3) is in the C library
+ *             --> define HAVE_ISATTY
+ *     Case 2: no isatty(3), BSD 4.3 tty handling
+ *             --> define HAVE_BSDTTY
+ * Case 3: no isatty(3), System V tty handling
+ *             --> define HAVE_SYSVTTY
+ *
+ * The following code checks:
+ *             1) that at least one of the flags is defined
+ *             2) only one of the BSD, SYS V flags is defined
+ */
+#if !defined(HAVE_ISATTY) && !defined(HAVE_BSDTTY) && !defined(HAVE_SYSVTTY)
+ #error function_isatty_not_available ;
+#endif
+
+#ifdef HAVE_ISATTY
+#undef HAVE_BSDTTY
+#undef HAVE_SYSVTTY
+#endif
+
+#if defined(HAVE_BSDTTY) && defined(HAVE_SYSVTTY)
+ #error HAVE_BSDTTY_and_HAVE_SYSVTTY_both_defined ;
+#endif
+
+
+
+/*
+ * CPU/compiler-specific section.
+ *
+ * The following constant affects the behavior of Sprint.
+ *
+ * Sprint performs integer->string conversions by first converting
+ * the integer to the widest int type supported by the CPU/compiler.
+ * By default, this is the "long int" type. If your machine has
+ * a wider type, you can specify it by defining the WIDE_INT constant.
+ * For example:
+ *             #define WIDE_INT                                        long long
+ */
+
diff --git a/libs/src/sio/siosup.c b/libs/src/sio/siosup.c
new file mode 100644 (file)
index 0000000..e717941
--- /dev/null
@@ -0,0 +1,899 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#ifdef _APPLE_
+#undef HAVE_MMAP
+#endif
+
+#include "impl.h"
+#include "sio.h"
+
+int __sio_n_descriptors = 0 ;
+__sio_descriptor_t *__sio_descriptors = NULL ;
+
+static sio_status_e setup_read_buffer( __sio_id_t *idp, unsigned buf_size );
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/*
+ * Code for finalization
+ */
+#ifdef HAVE_FINALIZATION_FUNCTION
+static int finalizer_installed ;
+
+SIO_DEFINE_FIN( sio_cleanup )
+{
+   (void) Sflush( SIO_FLUSH_ALL ) ;
+}
+#endif /* HAVE_FINALIZATION_FUNCTION */
+
+
+
+#ifdef HAVE_MMAP
+
+#define CHAR_NULL            ((char *)0)
+
+/*
+ * PAGES_MAPPED gives the size of each map unit in pages
+ */
+#define PAGES_MAPPED            2
+
+static size_t map_unit_size = 0 ;         /* bytes */
+static size_t page_size = 0 ;               /* bytes */
+
+static mapd_s *mmap_descriptors = NULL ;
+
+#define MDP( fd )            ( mmap_descriptors + (fd) )
+
+
+/*
+ * NOTES ON MEMORY MAPPING:
+ *
+ *    1. Memory mapping works only for file descriptors opened for input
+ *   2. Mapping an object to a part of the address space where another
+ *   object is mapped will cause the old mapping to disappear (i.e. mmap
+ *   will not fail)
+ *
+ * Memory mapping interface:
+ *      SIO_MMAP : maps a file into a portion of the address space.
+ *      SIO_MUNMAP: unmap a portion of the address space
+ *      SIO_MNEED: indicate to the OS that we will need a portion of
+ *                   our address space.
+ *
+ * The map_unit_size variable defines how much of the file is mapped at
+ * a time. It is a multiple of the operating system page size. It is
+ * not less than SIO_BUFFER_SIZE unless SIO_BUFFER_SIZE is not a
+ * multiple of the page size (so the SIO_BUFFER_SIZE overrides
+ * PAGES_MAPPED).
+ *
+ * NOTE: All memory mapping code is in this file only
+ */
+
+
+/*
+ * Macros used by the memory mapping code
+ */
+#define FIRST_TIME( dp )      ( dp->buf == NULL )
+
+/*
+ * Functions to support memory mapping:
+ *
+ *         try_memory_mapping
+ *         buffer_setup
+ *         __sio_switch
+ *         initial_map
+ *         map_unit
+ */
+
+/*
+ * try_memory_mapping attempts to setup the specified descriptor
+ * for memory mapping. 
+ * It returns FAILURE if it fails and SUCCESS if it is successful.
+ * If HAVE_MMAP is not defined, the function is defined to be FAILURE.
+ *
+ * Sets fields:
+ *      memory_mapped:          TRUE or FALSE
+ *      
+ * Also sets the following fields if memory_mapped is TRUE:
+ *    file_offset, file_size, buffer_size
+ *
+ */
+static sio_status_e try_memory_mapping( int fd, __sio_id_t *idp, const struct stat *stp )
+{
+   int access_f ;
+
+   /*
+    * Do not try memory mapping if:
+    *      1) The file is not a regular file
+    *      2) The file is a regular file but has zero-length
+    *      3) The file pointer is not positioned at the beginning of the file
+    *      4) The fcntl to obtain the file descriptor flags fails
+    *      5) The access mode is not O_RDONLY or O_RDWR
+    *
+    * The operations are done in this order to avoid the system calls
+    * if possible.
+    */
+   if ( ( ( stp->st_mode & S_IFMT ) != S_IFREG ) ||
+        ( stp->st_size == 0 ) ||
+        ( lseek( fd, (long)0, 1 ) != 0 ) ||
+        ( ( access_f = fcntl( fd, F_GETFL, 0 ) ) == -1 ) ||
+        ( ( access_f &= 0x3 ) != O_RDONLY && access_f != O_RDWR ) )
+   {
+      idp->memory_mapped = FALSE ;
+      return( FAILURE ) ;
+   }
+
+   /*
+    * Determine page_size and map_unit_size.
+    * Note that the code works even if PAGES_MAPPED is 0.
+    */
+   if ( page_size == 0 )
+   {
+      page_size = getpagesize() ;
+      map_unit_size = page_size * PAGES_MAPPED ;
+      if ( map_unit_size < SIO_BUFFER_SIZE )
+      {
+         if ( map_unit_size != 0 && SIO_BUFFER_SIZE % map_unit_size == 0 )
+            map_unit_size = SIO_BUFFER_SIZE ;
+         else
+            map_unit_size = page_size ;
+      }
+   }
+   
+   MDP(fd)->file_offset = 0 ;
+   MDP(fd)->file_size = stp->st_size ;
+   idp->buffer_size = map_unit_size ;
+   idp->buf = CHAR_NULL ;
+   idp->memory_mapped = TRUE ;
+
+   return( SUCCESS ) ;
+}
+
+
+/*
+ * Copy the current_unit to the primary buffer
+ *
+ * Sets fields: start, end, nextb
+ * Also sets the file pointer
+ */
+static void buffer_setup( __sio_id_t *idp, int fd, const struct map_unit *mu_cur, const struct map_unit *mu_next )
+{
+   off_t new_offset ;
+
+   sio_memcopy( mu_cur->addr, idp->buf, mu_cur->valid_bytes ) ;
+   idp->start = idp->buf ;
+   idp->end = idp->buf + mu_cur->valid_bytes ;
+   idp->nextb = idp->buf + ( idp->nextb - mu_cur->addr ) ;
+
+   if ( mu_next->addr != CHAR_NULL )
+      new_offset = MDP(fd)->file_offset - mu_next->valid_bytes ;
+   else
+      new_offset = MDP(fd)->file_offset ;
+   (void) lseek( fd, new_offset, 0 ) ;
+}
+
+/*
+ * Switch from memory mapping to buffered I/O
+ * If any mapping has occurred, then the current unit is
+ * copied into the buffer that is allocated.
+ * Any data in the next unit is ignored.
+ * We rely on idp->buf to identify the current unit (so it
+ * better be equal to the address of one of the units).
+ *
+ * Sets fields:
+ *         start, end, nextb
+ */
+sio_status_e __sio_switch( __sio_id_t *idp, int fd )
+{
+   mapd_s *mdp = MDP( fd ) ;
+   struct map_unit *mu_cur, *mu_next ;
+   unsigned buffer_size = idp->buffer_size ;
+   char *buf_addr = idp->buf ;
+   int first_time = FIRST_TIME( idp ) ;
+
+   /*
+    * Initialize stream for buffering
+    */
+   if ( setup_read_buffer( idp, buffer_size ) == FAILURE )
+      return( FAILURE ) ;
+
+   if ( ! first_time )
+   {
+      /*
+       * Find current, next unit
+       */
+      if ( buf_addr == mdp->first_unit.addr )
+      {
+         mu_cur = &mdp->first_unit ;
+         mu_next = &mdp->second_unit ;
+      }
+      else
+      {
+         mu_cur = &mdp->second_unit ;
+         mu_next = &mdp->first_unit ;
+      }
+
+      buffer_setup( idp, fd, mu_cur, mu_next ) ;
+      /*
+       * Destroy all mappings
+       */
+      (void) SIO_MUNMAP( mu_cur->addr, mu_cur->mapped_bytes ) ;
+      if ( mu_next->addr != NULL )
+         (void) SIO_MUNMAP( mu_next->addr, mu_next->mapped_bytes ) ;
+   }
+   else
+      idp->start = idp->end = idp->nextb = idp->buf ;
+
+   idp->memory_mapped = FALSE ;
+   return( SUCCESS ) ;
+}
+
+
+/*
+ * initial_map does the first memory map on the file descriptor.
+ * It attempts to map both units.
+ * The mapping always starts at file offset 0.
+ *
+ * SETS FIELDS:
+ *         first_unit.*, second_unit.*
+ *         file_offset
+ *
+ * Returns: 
+ *         number of bytes mapped in first_unit
+ *    or
+ *         0 to indicate that mmap failed.
+ */
+static int initial_map( mapd_s *mdp, int fd )
+{
+   caddr_t addr ;
+   size_t requested_length = 2 * map_unit_size ;
+   size_t mapped_length = MIN( (size_t)mdp->file_size, requested_length ) ;
+   size_t bytes_left ;
+   size_t bytes_in_unit ;
+
+   addr = SIO_MMAP( CHAR_NULL, mapped_length, fd, 0 ) ;
+   if ( addr == MAP_FAILED )
+      return( 0 ) ;
+
+   SIO_MNEED( addr, mapped_length ) ;
+
+   /*
+    * Map as much as possible in the first unit
+    */
+   bytes_in_unit = MIN( mapped_length, map_unit_size ) ;
+   mdp->first_unit.addr          = addr ;
+   mdp->first_unit.mapped_bytes    = bytes_in_unit ;
+   mdp->first_unit.valid_bytes    = bytes_in_unit ;
+
+   /*
+    * If there is more, map it in the second unit.
+    */
+   bytes_left = mapped_length - bytes_in_unit ;
+   if ( bytes_left != 0 )
+   {
+      mdp->second_unit.addr          = addr + bytes_in_unit ;
+      mdp->second_unit.mapped_bytes = bytes_left ;
+      mdp->second_unit.valid_bytes    = bytes_left ;
+   }
+   else
+      mdp->second_unit.addr          = CHAR_NULL ;
+
+   mdp->file_offset = mapped_length ;
+
+   return( mdp->first_unit.valid_bytes ) ;
+}
+
+
+/*
+ * ALGORITHM:
+ *
+ *      if ( there are more bytes in the file )
+ *      {
+ *         map them at the given unit
+ *         update offset
+ *         issue SIO_MNEED()
+ *      }
+ *      else
+ *         unmap the unit
+ */
+static sio_status_e map_unit( mapd_s *mdp, int fd, struct map_unit *mup )
+{
+   size_t bytes_left = mdp->file_size - mdp->file_offset ;
+   size_t bytes_to_map = MIN( bytes_left, map_unit_size ) ;
+
+   if ( bytes_to_map != 0 )
+   {
+      if ( SIO_MMAP( mup->addr, bytes_to_map,
+                                             fd, mdp->file_offset ) == MAP_FAILED )
+         return( FAILURE ) ;         /* XXX: need to do more ? */
+      
+      mup->valid_bytes = bytes_to_map ;
+      ASSERT( mup->valid_bytes <= mup->mapped_bytes ) ;
+      mdp->file_offset += bytes_to_map ;
+      SIO_MNEED( mup->addr, mup->valid_bytes ) ;
+   }
+   else
+   {
+      (void) SIO_MUNMAP( mup->addr, mup->mapped_bytes ) ;
+      mup->addr = CHAR_NULL ;
+   }
+   return( SUCCESS ) ;
+}
+
+#else
+
+#define try_memory_mapping( x, y, z )            FAILURE
+
+#endif /* HAVE_MMAP */
+
+
+static sio_status_e setup_read_buffer( __sio_id_t *idp, unsigned buf_size )
+{
+   char *buf ;
+
+   /*
+    * First allocate space for 2 buffers: primary and auxiliary
+    */
+   buf = malloc( buf_size * 2 ) ;
+   if ( buf == NULL )
+      return( FAILURE ) ;
+
+   /*
+    * The descriptor buf field should point to the start of the main buffer
+    */
+   idp->buf = buf + buf_size ;
+   idp->buffer_size = buf_size ;
+   return( SUCCESS ) ;
+}
+
+
+static sio_status_e init_input_stream( __sio_id_t *idp, int fd, const struct stat *stp )
+{
+   /*
+    * First initialize the fields relevant to buffering: buf, buffer_size
+    */
+   if ( try_memory_mapping( fd, idp, stp ) == FAILURE )
+   {
+      /*
+       * Try to use normal buffering
+       */
+      unsigned buf_size = (unsigned)
+                     ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
+      
+      if ( setup_read_buffer( idp, buf_size ) == FAILURE )
+         return( FAILURE ) ;
+   }
+
+    /*
+    * Initialize remaining descriptor fields
+    */
+   idp->max_line_length = 2 * idp->buffer_size - 1 ;
+   idp->start = idp->end = idp->nextb = idp->buf ;
+   idp->tied_fd = SIO_NO_TIED_FD ;
+
+   return( SUCCESS ) ;
+}
+
+
+static sio_status_e init_output_stream( __sio_od_t *odp, int fd, 
+       const struct stat *stp )
+{
+   unsigned buf_size ;
+   char *buf ;
+
+   buf_size = (unsigned)
+                  ( stp->st_blksize ? stp->st_blksize : SIO_BUFFER_SIZE ) ;
+   buf = malloc( buf_size ) ;
+   if ( buf == NULL )
+      return( FAILURE ) ;
+   
+   /*
+    * Initialize buffering fields
+    */
+   odp->buf = buf ;
+   odp->buffer_size = buf_size ;
+   odp->buf_end = odp->buf + buf_size ;
+
+   /*
+    * Initialize remaining fields
+    */
+   odp->start = odp->nextb = odp->buf ;
+   if ( isatty( fd ) )
+      odp->buftype = SIO_LINEBUF ;
+
+   if ( fd == 2 )
+      odp->buftype = SIO_NOBUF ;
+
+   return( SUCCESS ) ;
+}
+
+
+#ifndef HAVE_ISATTY
+
+#ifdef HAVE_SYSVTTY
+
+#include <termio.h>
+
+static int isatty( int fd )
+{
+   struct termio t ;
+
+   if ( ioctl( fd, TCGETA, &t ) == -1 && errno == ENOTTY )
+      return( FALSE ) ;
+   else
+      return( TRUE ) ;
+}
+#endif   /* HAVE_SYSVTTY */
+
+#ifdef HAVE_BSDTTY
+
+#include <sgtty.h>
+
+static int isatty( int fd )
+{
+   struct sgttyb s ;
+
+   if ( ioctl( fd, TIOCGETP, &s ) == -1 && errno == ENOTTY )
+      return( FALSE ) ;
+   else
+      return( TRUE ) ;
+}
+#endif   /* HAVE_BSDTTY */
+
+#endif   /* ! HAVE_ISATTY */
+
+
+/*
+ * Initialize stream I/O for a file descriptor.
+ *
+ * Arguments:
+ *      fd:            file descriptor
+ *      dp:            descriptor pointer
+ *      stream_type:    either __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
+ *
+ * Returns
+ *      0          if successful
+ *     SIO_ERR   if the file descriptor is not valid (sets errno)
+ *   exits      if stream_type is not __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM
+ */
+int __sio_init( __sio_descriptor_t *dp, int fd, enum __sio_stream stream_type )
+{
+   struct stat st ;
+
+   memset(dp, 0, sizeof(__sio_descriptor_t));
+   if ( fd >= __sio_n_descriptors )
+   {
+      errno = EBADF ;
+      return( SIO_ERR ) ;
+   }
+
+   if ( fstat( fd, &st ) == -1 )
+      return( SIO_ERR ) ;
+   
+   switch ( stream_type )
+   {
+      case __SIO_INPUT_STREAM:
+         if ( init_input_stream( IDP( dp ), fd, &st ) == FAILURE )
+            return( SIO_ERR ) ;
+         break ;
+
+      case __SIO_OUTPUT_STREAM:
+         if ( init_output_stream( ODP( dp ), fd, &st ) == FAILURE )
+            return( SIO_ERR ) ;
+         break ;
+         
+      default:
+         terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ;
+         /* NOTREACHED */
+   }
+   dp->stream_type = stream_type ;
+   dp->initialized = TRUE ;
+
+#ifdef HAVE_FINALIZATION_FUNCTION
+   if ( ! finalizer_installed )
+   {
+      if ( ! SIO_FINALIZE( sio_cleanup ) )
+      {
+         char *s = "SIO __sio_init: finalizer installation failed\n" ;
+
+         (void) write( 2, s, strlen( s ) ) ;
+      }
+      else
+         finalizer_installed = TRUE ;
+   }
+#endif /* HAVE_FINALIZATION_FUNCTION */
+
+   return( 0 ) ;
+}
+
+
+/*
+ * __sio_writef writes the data in the buffer to the file descriptor.
+ *
+ * It tries to write as much data as possible until either all data
+ * are written or an error occurs. EINTR is the only error that is
+ * ignored.
+ * In case an error occurs but some data were written, that number
+ * is returned instead of SIO_ERR.
+ *
+ * Fields modified:
+ *      When successful: start, nextb
+ *      When not successful: start
+ *
+ * Return value:
+ *      Number of bytes written
+ *      SIO_ERR, if write(2) fails and no data were written
+ */ 
+int __sio_writef( __sio_od_t *odp, int fd )
+{
+   int b_in_buffer ;
+   int cc_total = 0 ;
+
+   /*
+    * Make sure we don't exceed the buffer limits
+    *   Maybe we should log this ?         XXX
+    */
+   if ( odp->nextb > odp->buf_end )
+      odp->nextb = odp->buf_end ;
+
+   b_in_buffer = odp->nextb - odp->start ;
+
+   if ( b_in_buffer == 0 )
+      return( 0 ) ;
+   
+   for ( ;; )
+   {
+      int cc ;
+
+      cc = write( fd, odp->start, b_in_buffer ) ;
+      if ( cc == b_in_buffer )
+      {
+         odp->start = odp->nextb = odp->buf ;
+         cc_total += cc ;
+         break ;
+      }
+      else if ( cc == -1 )
+      {
+         if ( errno == EINTR )
+            continue ;
+         else
+            /*
+             * If some bytes were written, return that number, otherwise
+             * return SIO_ERR
+             */
+            return( ( cc_total != 0 ) ? cc_total : SIO_ERR ) ;
+      }
+      else         /* some bytes were written */
+      {
+         odp->start += cc ;         /* advance start of buffer */
+         b_in_buffer -= cc ;         /* decrease number bytes left in buffer */
+         cc_total += cc ;            /* count the bytes that were written */
+      }
+   }
+   return( cc_total ) ;
+}
+
+
+/*
+ * __sio_readf reads data from the file descriptor into the buffer.
+ * Unlike __sio_writef it does NOT try to read as much data as will fit
+ * in the buffer. It ignores EINTR.
+ *
+ * Returns: # of bytes read or SIO_ERR
+ *
+ * Fields set:
+ *       If it does not return SIO_ERR, it sets start, nextb, end
+ *         If it returns SIO_ERR, it does not change anything
+ */
+static int __sio_readf( __sio_id_t *idp, int fd )
+{
+   int cc ;
+
+   /*
+    * First check for a tied fd and flush the stream if necessary
+    *
+    *       XXX   the return value of __sio_writef is not checked.
+    *               Is that right ?
+    */
+   if ( idp->tied_fd != SIO_NO_TIED_FD )
+      (void) __sio_writef( &__SIO_OD( idp->tied_fd ), idp->tied_fd ) ;
+
+#ifdef HAVE_MMAP
+   if ( idp->memory_mapped )
+   {
+      mapd_s *mdp = MDP( fd ) ;
+
+      /*
+       * The functions initial_map and map_unit may fail.
+       * In either case, we switch to buffered I/O.
+       * If initial_map fails, we have read no data, so we
+       * should perform a read(2).
+       * If map_unit fails (for the next unit), we still have
+       * the data in the current unit, so we can return.
+       */
+      if ( FIRST_TIME( idp ) )
+      {
+         cc = initial_map( mdp, fd ) ;
+         if ( cc > 0 )
+            idp->buf = mdp->first_unit.addr ;
+         else
+         {
+            if ( __sio_switch( idp, fd ) == FAILURE )
+               return( SIO_ERR ) ;
+            cc = -1 ;
+         }
+      }
+      else
+      {
+         struct map_unit *mu_cur, *mu_next ;
+
+         if ( idp->buf == mdp->first_unit.addr )
+         {
+            mu_cur = &mdp->first_unit ;
+            mu_next = &mdp->second_unit ;
+         }
+         else
+         {
+            mu_cur = &mdp->second_unit ;
+            mu_next = &mdp->first_unit ;
+         }
+
+         if ( mu_next->addr != NULL )
+         {
+            idp->buf = mu_next->addr ;
+            cc = mu_next->valid_bytes ;
+            /*
+             * XXX:  Here we may return SIO_ERR even though there
+             *         are data in the current unit because the switch
+             *         fails (possibly because malloc failed).
+             */
+            if ( map_unit( mdp, fd, mu_cur ) == FAILURE &&
+                              __sio_switch( idp, fd ) == FAILURE )
+               return( SIO_ERR ) ;
+         }
+         else
+            cc = 0 ;
+      }
+      if ( cc >= 0 )
+      {
+         idp->end = idp->buf + cc ;
+         idp->start = idp->nextb = idp->buf ;
+         return( cc ) ;
+      }
+   }
+#endif /* HAVE_MMAP */
+
+   for ( ;; )
+   {
+      cc = read( fd, idp->buf, (int) idp->buffer_size ) ;
+      if ( cc == -1 )
+         if ( errno == EINTR )
+            continue ;
+         else
+            return( SIO_ERR ) ;
+      else
+         break ;
+   }
+
+   idp->end = idp->buf + cc ;
+   idp->start = idp->nextb = idp->buf ;
+   return( cc ) ;
+}
+
+
+/*
+ * __sio_extend_buffer is used by Srdline to extend the buffer
+ * If successful, it returns the number of bytes that have been read.
+ * If it fails (because of end-of-file or I/O error), it returns 0 or -1.
+ *
+ * Fields modified:
+ *    idp->start points to the start of the buffer area (which is in the
+ *    auxiliary buffer)
+ *      Also, if successful, idp->nextb is set to idp->buf, idp->end is modified.
+ */
+int __sio_extend_buffer( __sio_id_t *idp, int fd, int b_left )
+{
+   int b_read ;
+
+   /*
+    * copy to auxiliary buffer
+    */
+   if ( b_left )
+      sio_memcopy( idp->nextb, idp->buf - b_left, b_left ) ;
+   b_read = __sio_readf( idp, fd ) ;
+   idp->start = idp->buf - b_left ;
+   return( b_read ) ;
+}
+
+
+/*
+ * __sio_more tries to read more data from the given file descriptor iff
+ * there is free space in the buffer.
+ * __sio_more is used only by Srdline and only AFTER __sio_extend_buffer
+ * has been called. This implies that 
+ *      a) this is not a memory mapped file
+ *      b) __sio_readf has been called (so we don't need to check for tied fd's
+ *
+ * Fields modified (only if successful):
+ *         idp->end
+ *
+ * Return value: the number of bytes read.
+ */
+int __sio_more( __sio_id_t *idp, int fd )
+{
+   int b_left = &idp->buf[ idp->buffer_size ] - idp->end ;
+   int cc ;
+
+   if ( b_left <= 0 )
+      return( 0 ) ;
+   
+   for ( ;; )
+   {
+      cc = read( fd, idp->end, b_left ) ;
+      if ( cc >= 0 )
+      {
+         idp->end += cc ;
+         return( cc ) ;
+      }
+      else
+         if ( errno == EINTR )
+            continue ;
+         else
+            return( SIO_ERR ) ;
+   }
+}
+
+
+/*
+ * Finalize a buffer by unmapping the file or freeing the malloc'ed memory.
+ * This function is only called by Sclose. We always free memory even if
+ * SIO_ERR is returned as long as the descriptor was initialized.
+ */
+int Sdone( int fd )
+{
+   __sio_descriptor_t *dp ;
+   int ret_val = 0;
+
+   if ( fd < 0 || fd >= __sio_n_descriptors )
+   {
+      errno = EBADF ;
+      return( SIO_ERR ) ;
+   }
+
+   dp = &__sio_descriptors[ fd ] ;
+   if ( ! DESCRIPTOR_INITIALIZED( dp ) )
+   {
+      errno = EBADF ;
+      return( SIO_ERR ) ;
+   }
+
+   switch ( dp->stream_type )
+   {
+      case __SIO_INPUT_STREAM:
+         {
+            __sio_id_t *idp = IDP( dp ) ;
+
+#ifdef HAVE_MMAP
+            if ( idp->memory_mapped )
+            {
+               mapd_s *mdp = MDP( fd ) ;
+
+               if ( mdp->first_unit.addr != CHAR_NULL )
+                  (void) SIO_MUNMAP( mdp->first_unit.addr,
+                                          mdp->first_unit.mapped_bytes ) ;
+               if ( mdp->second_unit.addr != CHAR_NULL )
+                  (void) SIO_MUNMAP( mdp->second_unit.addr,
+                                          mdp->second_unit.mapped_bytes ) ;
+               idp->memory_mapped = FALSE ;
+            }
+            else
+#endif   /* HAVE_MMAP */
+               free( idp->buf - idp->buffer_size ) ;
+               idp->nextb = idp->end = NULL ;
+         }
+         break ;
+      
+      case __SIO_OUTPUT_STREAM:
+         {
+            __sio_od_t *odp = ODP( dp ) ;
+
+            if ( Sflush( fd ) == SIO_ERR )
+               ret_val = SIO_ERR;
+            free( odp->buf ) ;
+            odp->nextb = odp->buf_end = NULL ;
+         }
+         break ;
+      
+      default:
+         terminate( "SIO Sdone: bad stream type\n" ) ;
+   }
+
+   memset( dp, 0, sizeof(__sio_descriptor_t) );
+   dp->initialized = FALSE ;
+   return ret_val;
+}
+
+
+static char *sioexpand( char *area, unsigned old_size, unsigned new_size, int is_static )
+{
+   char *new_area ;
+
+   if ( is_static )
+   {
+      if ( ( new_area = malloc( new_size ) ) == NULL )
+         return( NULL ) ;
+      sio_memcopy( area, new_area, old_size ) ;
+   }
+   else
+      if ( ( new_area = realloc( area, new_size ) ) == NULL )
+         return( NULL ) ;
+      
+   return( new_area ) ;
+}
+
+
+/*
+ * Expand the descriptor array (and if we use memory mapping the
+ * memory mapping descriptors). We first expand the memory mapping
+ * descriptors.
+ * There is no problem if the expansion of the SIO descriptors fails
+ * (i.e. there is no need to undo anything).
+ */
+int Smorefds(int fd)
+{
+   char *p ;
+   int is_static ;
+   unsigned new_size, old_size ;
+   int n_fds = 4; /* Let's bump 4 at a time for hysteresis */
+
+   /* If the fd is out of range of the proposed size, make n_fds big enough */
+   if (fd >= (__sio_n_descriptors+n_fds))
+      n_fds += fd - __sio_n_descriptors;
+
+#ifdef HAVE_MMAP
+   old_size = __sio_n_descriptors * sizeof( mapd_s ) ;
+   new_size = n_fds * sizeof( mapd_s ) ;
+   new_size += old_size;
+   is_static = ( mmap_descriptors == NULL ) ;
+   p = sioexpand( (char *)mmap_descriptors, old_size, new_size, is_static ) ;
+   if ( p == NULL )
+      return( SIO_ERR ) ;
+   memset(p+old_size, 0, new_size-old_size);
+   mmap_descriptors = (mapd_s *) p ;
+#endif   /* HAVE_MMAP */
+   
+   old_size = __sio_n_descriptors * sizeof( __sio_descriptor_t ) ;
+   new_size = n_fds * sizeof( __sio_descriptor_t ) ;
+   new_size += old_size;
+   is_static =  ( __sio_descriptors == NULL ) ;
+   p = sioexpand( (char *)__sio_descriptors, old_size, new_size, is_static ) ;
+   if ( p == NULL )
+      return( SIO_ERR ) ;
+   memset(p+old_size, 0, new_size-old_size);
+   __sio_descriptors = (__sio_descriptor_t *) p ;
+
+   __sio_n_descriptors += n_fds ;
+   return( 0 ) ;
+}
+
+void terminate(const char *msg)
+{
+      syslog(LOG_CRIT, "%s", msg);
+      (void) abort() ;
+      _exit( 1 ) ;      /* NOT REACHED */
+}
+
diff --git a/libs/src/sio/sprint.c b/libs/src/sio/sprint.c
new file mode 100644 (file)
index 0000000..87ecf92
--- /dev/null
@@ -0,0 +1,742 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sio.h"
+#include "impl.h"
+#include "libportable.h"
+
+typedef long long                      wide_int ;
+typedef unsigned long long             u_wide_int ;
+typedef int                            bool_int ;
+
+static char *conv_10( wide_int num, bool_int is_unsigned, bool_int *is_negative, char *buf_end, int *len );
+
+#define S_NULL_LEN                     6
+static char S_NULL[S_NULL_LEN+1] = "(null)";
+
+#define FLOAT_DIGITS                   6
+#define MAX_FLOAT_DIGITS               17
+#define EXPONENT_LENGTH                        10
+
+/*
+ * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
+ *
+ * XXX: this is a magic number; do not decrease it
+ */
+#define NUM_BUF_SIZE                   512
+
+/*
+ * The INS_CHAR macro inserts a character in the buffer and writes
+ * the buffer back to disk if necessary
+ * It uses the char pointers sp and bep:
+ *     sp points to the next available character in the buffer
+ *     bep points to the end-of-buffer+1
+ * While using this macro, note that the nextb pointer is NOT updated.
+ *
+ * No I/O is performed if fd is not positive. Negative fd values imply
+ * conversion with the output directed to a string. Excess characters
+ * are discarded if the string overflows.
+ *
+ * NOTE: Evaluation of the c argument should not have any side-effects
+ */
+#define INS_CHAR( c, sp, bep, odp, cc, fd )                    \
+{                                                              \
+       if ( sp < bep )                                         \
+       {                                                       \
+               *sp++ = c ;                                     \
+               cc++ ;                                          \
+       }                                                       \
+       else                                                    \
+       {                                                       \
+               if ( fd >= 0 )                                  \
+               {                                               \
+                       odp->nextb = sp ;                       \
+                       if ( __sio_writef( odp, fd ) != bep - odp->start ) \
+                               return( ( cc != 0 ) ? cc : SIO_ERR ) ;  \
+                       sp = odp->nextb ;                       \
+                       *sp++ = c ;                             \
+                       cc++ ;                                  \
+               }                                               \
+       }                                                       \
+       if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 )           \
+       {                                                       \
+               int b_in_buffer = sp - odp->start ;             \
+                                                               \
+               odp->nextb = sp ;                               \
+               if ( __sio_writef( odp, fd ) != b_in_buffer )   \
+                       return( cc ) ;                          \
+               sp = odp->nextb ;                               \
+       }                                                       \
+}
+
+
+
+#define NUM( c )                       ( c - '0' )
+
+#define STR_TO_DEC( str, num )                                         \
+       num = NUM( *str++ ) ;                                           \
+       while ( isdigit( *str ) )                                       \
+       {                                                               \
+               num *= 10 ;                                             \
+               num += NUM( *str++ ) ;                                  \
+       }
+
+/*
+ * This macro does zero padding so that the precision
+ * requirement is satisfied. The padding is done by
+ * adding '0's to the left of the string that is going
+ * to be printed.
+ */
+#define FIX_PRECISION( adjust, precision, s, s_len )                   \
+       if ( adjust )                                                   \
+               while ( s_len < precision && s_len < NUM_BUF_SIZE - 2 ) \
+               {                                                       \
+                       *--s = '0' ;                                    \
+                       s_len++ ;                                       \
+               }
+
+/*
+ * Macro that does padding. The padding is done by printing
+ * the character ch.
+ */
+#define PAD( width, len, ch )                                          \
+       do                                                              \
+       {                                                               \
+               INS_CHAR( ch, sp, bep, odp, cc, fd ) ;                  \
+               width-- ;                                               \
+       } while ( width > len )
+
+/*
+ * Sprint is the equivalent of printf for SIO.
+ * It returns the # of chars written
+ * Assumptions:
+ *     - all floating point arguments are passed as doubles
+ */
+/* VARARGS2 */
+int Sprint( int fd, const char *fmt, ...) 
+{
+       __sio_descriptor_t *dp ;
+       __sio_od_t *odp ;
+       int cc ;
+       va_list ap ;
+
+       if( sio_setup( fd, &dp, __SIO_OUTPUT_STREAM ) == SIO_ERR )
+               return( SIO_ERR );
+       odp = ODP( dp ) ;
+
+       va_start( ap, fmt ) ;
+       cc = __sio_converter( odp, fd, fmt, ap ) ;
+       va_end( ap ) ;
+       return( cc ) ;
+}
+
+
+/*
+ * This is the equivalent of vfprintf for SIO
+ */
+int Sprintv( int fd, const char *fmt, va_list ap)
+{
+       __sio_descriptor_t *dp ;
+       __sio_od_t *odp ;
+
+       if( sio_setup( fd, &dp, __SIO_OUTPUT_STREAM ) == SIO_ERR )
+               return( SIO_ERR );
+       odp = ODP( dp ) ;
+       return( __sio_converter( odp, fd, fmt, ap ) ) ;
+}
+
+
+/*
+ * Convert a floating point number to a string formats 'f', 'e' or 'E'.
+ * The result is placed in buf, and len denotes the length of the string
+ * The sign is returned in the is_negative argument (and is not placed
+ * in buf).
+ */
+static char *conv_fp( char format, double num, boolean_e add_dp, 
+   int precision, bool_int *is_negative, char buf[], int *len )
+       /* always add decimal point if YES */
+{
+       char *s = buf ;
+       char *p = NULL ;
+       int decimal_point ;
+               
+       if ( precision > MAX_FLOAT_DIGITS )
+               precision = MAX_FLOAT_DIGITS ;
+
+       if ( format == 'f' )
+               p = (char *)fcvt( num, precision, &decimal_point, is_negative ) ;
+       else /* either e or E format */
+               p = (char *)ecvt( num, precision+1, &decimal_point, is_negative ) ;
+
+       /*
+        * Check for Infinity and NaN
+        */
+       if ( isalpha( *p ) )
+       {
+               *len = strlen( strcpy( buf, p ) ) ;
+               *is_negative = FALSE ;
+               return( buf ) ;
+       }
+       
+       if ( format == 'f' )
+               if ( decimal_point <= 0 )
+               {
+                       *s++ = '0' ;
+                       if ( precision > 0 )
+                       {
+                               *s++ = '.' ;
+                               while ( decimal_point++ < 0 )
+                                       *s++ = '0' ;
+                       }
+                       else if ( add_dp )
+                               *s++ = '.' ;
+               }
+               else
+               {
+                       while ( decimal_point-- > 0 )
+                               *s++ = *p++ ;
+                       if ( precision > 0 || add_dp ) *s++ = '.' ;
+               }
+       else
+       {
+               *s++ = *p++ ;
+               if ( precision > 0 || add_dp ) *s++ = '.' ;
+       }
+
+       /*
+        * copy the rest of p, the NUL is NOT copied
+        */
+       while ( *p ) *s++ = *p++ ;                      
+       
+       if ( format != 'f' )
+       {
+               char temp[ EXPONENT_LENGTH ] ;          /* for exponent conversion */
+               int t_len ;
+               bool_int exponent_is_negative ;
+
+               *s++ = format ;         /* either e or E */
+               decimal_point-- ;
+               if ( decimal_point != 0 )
+               {
+                       p = conv_10( (wide_int)decimal_point, FALSE, &exponent_is_negative,
+                                       &temp[ EXPONENT_LENGTH ], &t_len ) ;
+                       *s++ = exponent_is_negative ? '-' : '+' ;
+                       
+                       /*
+                        * Make sure the exponent has at least 2 digits
+                        */
+                       if ( t_len == 1 )
+                               *s++ = '0' ;
+                       while ( t_len-- ) *s++ = *p++ ;
+               }
+               else
+               {
+                       *s++ = '+' ;
+                       *s++ = '0' ;
+                       *s++ = '0' ;
+               }
+       }
+
+       *len = s - buf ;
+       return( buf ) ;
+}
+
+
+/*
+ * Convert num to a base X number where X is a power of 2. nbits determines X.
+ * For example, if nbits is 3, we do base 8 conversion
+ * Return value:
+ *                     a pointer to a string containing the number
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ */
+static char *conv_p2( u_wide_int num, int nbits, char format, char *buf_end, int *len )
+{
+       int mask = ( 1 << nbits ) - 1 ;
+       char *p = buf_end ;
+       static const char low_digits[] = "0123456789abcdef" ;
+       static const char upper_digits[] = "0123456789ABCDEF" ;
+       const char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
+
+       do
+       {
+               *--p = digits[ num & mask ] ;
+               num >>= nbits ;
+       }
+       while( num ) ;
+
+       *len = buf_end - p ;
+       return( p ) ;
+}
+
+/*
+ * Convert num to its decimal format.
+ * Return value:
+ *      - a pointer to a string containing the number (no sign)
+ *     - len contains the length of the string
+ *     - is_negative is set to TRUE or FALSE depending on the sign
+ *               of the number (always set to FALSE if is_unsigned is TRUE)
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ */
+static char *conv_10( wide_int num, bool_int is_unsigned, bool_int *is_negative, char *buf_end, int *len )
+{
+       char *p = buf_end ;
+       u_wide_int magnitude ;
+
+       if ( is_unsigned )
+       {
+               magnitude = (u_wide_int) num ;
+               *is_negative = FALSE ;
+       }
+       else
+       {
+               *is_negative = ( num < 0 ) ;
+
+               /*
+                * On a 2's complement machine, negating the most negative integer 
+                * results in a number that cannot be represented as a signed integer.
+                * Here is what we do to obtain the number's magnitude:
+                *              a. add 1 to the number
+                *              b. negate it (becomes positive)
+                *              c. convert it to unsigned
+                *              d. add 1
+                */
+               if ( *is_negative )
+               {
+                       wide_int t = num + 1 ;
+
+                       magnitude = ( (u_wide_int) -t ) + 1 ;
+               }
+               else
+                       magnitude = (u_wide_int) num ;
+       }
+
+       /*
+        * We use a do-while loop so that we write at least 1 digit 
+        */
+       do
+       {
+               u_wide_int new_magnitude = magnitude / 10 ;
+
+               *--p = magnitude - new_magnitude*10 + '0' ;
+               magnitude = new_magnitude ;
+       }
+       while ( magnitude ) ;
+       
+       *len = buf_end - p ;
+       return( p ) ;
+}
+
+
+/*
+ * Do format conversion placing the output in odp.
+ * Note: we do not support %n for security reasons.
+ */
+int __sio_converter( __sio_od_t *odp, int fd, const char *fmt, va_list ap )
+{
+       char *sp = NULL;
+       char *bep = NULL;
+       int cc = 0 ;
+       int i ;
+
+       char *s = NULL;
+       char *q = NULL;
+       int s_len ;
+
+       int min_width = 0 ;
+       int precision = 0 ;
+       enum { LEFT, RIGHT } adjust ;
+       char pad_char ;
+       char prefix_char ;
+
+       double fp_num ;
+       wide_int i_num = 0 ;
+       u_wide_int ui_num ;
+
+       char num_buf[ NUM_BUF_SIZE ] ;
+       char char_buf[ 2 ] ;            /* for printing %% and %<unknown> */
+
+       /*
+        * Flag variables
+        */
+       boolean_e is_long = NO;
+       boolean_e is_quad = NO;
+       boolean_e alternate_form ;
+       boolean_e print_sign ;
+       boolean_e print_blank ;
+       boolean_e adjust_precision ;
+       boolean_e adjust_width ;
+       bool_int is_negative ;
+
+       sp = odp->nextb ;
+       bep = odp->buf_end ;
+
+       while ( *fmt )
+       {
+               if ( *fmt != '%' )
+               {
+                       INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
+               }
+               else
+               {
+                       /*
+                        * Default variable settings
+                        */
+                       adjust = RIGHT ;
+                       alternate_form = print_sign = print_blank = NO ;
+                       pad_char = ' ' ;
+                       prefix_char = NUL ;
+
+                       fmt++ ;
+
+                       /*
+                        * Try to avoid checking for flags, width or precision
+                        */
+                       if ( isascii( *fmt ) && ! islower( *fmt ) )
+                       {
+                               /*
+                                * Recognize flags: -, #, BLANK, +
+                                */
+                               for ( ;; fmt++ )
+                               {
+                                       if ( *fmt == '-' )
+                                               adjust = LEFT ;
+                                       else if ( *fmt == '+' )
+                                               print_sign = YES ;
+                                       else if ( *fmt == '#' )
+                                               alternate_form = YES ;
+                                       else if ( *fmt == ' ' )
+                                               print_blank = YES ;
+                                       else if ( *fmt == '0' )
+                                               pad_char = '0' ;
+                                       else
+                                               break ;
+                               }
+
+                               /*
+                                * Check if a width was specified
+                                */
+                               if ( isdigit( *fmt ) )
+                               {
+                                       STR_TO_DEC( fmt, min_width ) ;
+                                       adjust_width = YES ;
+                               }
+                               else if ( *fmt == '*' )
+                               {
+                                       min_width = va_arg( ap, int ) ;
+                                       fmt++ ;
+                                       adjust_width = YES ;
+                                       if ( min_width < 0 )
+                                       {
+                                               adjust = LEFT ;
+                                               min_width = -min_width ;
+                                       }
+                               }
+                               else
+                                       adjust_width = NO ;
+                               
+                               /*
+                                * Check if a precision was specified.
+                                */
+                               if ( *fmt == '.' )
+                               {
+                                       adjust_precision = YES ;
+                                       fmt++ ;
+                                       if ( isdigit( *fmt ) )
+                                       {
+                                               STR_TO_DEC( fmt, precision ) ;
+                                       }
+                                       else if ( *fmt == '*' )
+                                       {
+                                               precision = va_arg( ap, int ) ;
+                                               fmt++ ;
+                                               if ( precision < 0 )
+                                                       precision = 0 ;
+                                       }
+                                       else
+                                               precision = 0 ;
+                               }
+                               else
+                                       adjust_precision = NO ;
+                       }
+                       else
+                               adjust_precision = adjust_width = NO ;
+
+                       /*
+                        * Modifier check
+                        */
+                       if ( *fmt == 'l' )
+                       {
+                               if( *(fmt+1) == 'l' ) {
+                                       is_quad = YES;
+                                       fmt++;
+                               } else {
+                                       is_quad = NO;
+                                       is_long = YES;
+                               }
+                               fmt++ ;
+                       } else {
+                               is_long = NO;
+                               is_quad = NO;
+                       }
+
+                       if ( *fmt == 'q' )
+                       {
+                               is_quad = YES;
+                               fmt++;
+                       }
+
+                       /*
+                        * Argument extraction and printing.
+                        * First we determine the argument type.
+                        * Then, we convert the argument to a string.
+                        * On exit from the switch, s points to the string that
+                        * must be printed, s_len has the length of the string
+                        * The precision requirements, if any, are reflected in s_len.
+                        *
+                        * NOTE: pad_char may be set to '0' because of the 0 flag.
+                        *                      It is reset to ' ' by non-numeric formats
+                        */
+                       switch( *fmt )
+                       {
+                               case 'd':
+                               case 'i':
+                               case 'u':
+                                       if ( is_long )
+                                               i_num = va_arg( ap, long ) ;
+                                       else
+                                               i_num = (wide_int) va_arg( ap, int ) ;
+                                       s = conv_10( i_num, (*fmt) == 'u', &is_negative,
+                                                       &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
+                                       FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
+
+                                       if ( *fmt != 'u' )
+                                       {
+                                               if ( is_negative )
+                                                       prefix_char = '-' ;
+                                               else if ( print_sign )
+                                                       prefix_char = '+' ;
+                                               else if ( print_blank )
+                                                       prefix_char = ' ' ;
+                                       }
+                                       break ;
+                               
+
+                               case 'o':
+                                       if ( is_long )
+                                               ui_num = va_arg( ap, u_wide_int ) ; 
+                                       else
+                                               ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
+                                       s = conv_p2( ui_num, 3, *fmt, 
+                                               &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
+                                       FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
+                                       if ( alternate_form && *s != '0' )
+                                       {
+                                               *--s = '0' ;
+                                               s_len++ ;
+                                       }
+                                       break ;
+                               
+
+                               case 'x':
+                               case 'X':
+                                       if ( is_long )
+                                               ui_num = (u_wide_int) va_arg( ap, unsigned long ) ;
+                                       else if ( is_quad )
+                                               ui_num = (u_wide_int) va_arg( ap, u_wide_int ) ;
+                                       else
+                                               ui_num = (u_wide_int) va_arg( ap, unsigned int ) ;
+                                       s = conv_p2( ui_num, 4, *fmt,
+                                               &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
+                                       FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
+                                       if ( alternate_form && i_num != 0 )
+                                       {
+                                               *--s = *fmt ;           /* 'x' or 'X' */
+                                               *--s = '0' ;
+                                               s_len += 2 ;
+                                       }
+                                       break ;
+                               
+
+                               case 's':
+                                       s = va_arg( ap, char * ) ;
+                                       if ( s != NULL )
+                                       {
+                                               s_len = strlen( s ) ;
+                                               if ( adjust_precision && precision < s_len )
+                                                       s_len = precision ;
+                                       }
+                                       else
+                                       {
+                                               s = S_NULL ;
+                                               s_len = S_NULL_LEN ;
+                                       }
+                                       pad_char = ' ' ;
+                                       break ;
+
+
+                               case 'f':
+                               case 'e':
+                               case 'E':
+                                       fp_num = va_arg( ap, double ) ;
+
+                                       s = conv_fp( *fmt, fp_num, alternate_form,
+                                               ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
+                                               &is_negative, &num_buf[ 1 ], &s_len ) ;
+                                       if ( is_negative )
+                                               prefix_char = '-' ;
+                                       else if ( print_sign )
+                                               prefix_char = '+' ;
+                                       else if ( print_blank )
+                                               prefix_char = ' ' ;
+                                       break ;
+
+
+                               case 'g':
+                               case 'G':
+                                       if ( adjust_precision == NO )
+                                               precision = FLOAT_DIGITS ;
+                                       else if ( precision == 0 )
+                                               precision = 1 ;
+                                       if ( precision > MAX_FLOAT_DIGITS )
+                                               precision = MAX_FLOAT_DIGITS ;
+                                       /*
+                                        * We use &num_buf[ 1 ], so that we have room for the sign
+                                        */
+                                       s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
+                                       if ( *s == '-' )
+                                               prefix_char = *s++ ;
+                                       else if ( print_sign )
+                                               prefix_char = '+' ;
+                                       else if ( print_blank )
+                                               prefix_char = ' ' ;
+
+                                       s_len = strlen( s ) ;
+
+                                       if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
+                                               s[ s_len++ ] = '.' ;
+                                       if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
+                                               *q = 'E' ;
+                                       break ;
+
+
+                               case 'c':
+                                       char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
+                                       s = &char_buf[ 0 ] ;
+                                       s_len = 1 ;
+                                       pad_char = ' ' ;
+                                       break ;
+
+
+                               case '%':
+                                       char_buf[ 0 ] = '%' ;
+                                       s = &char_buf[ 0 ] ;
+                                       s_len = 1 ;
+                                       pad_char = ' ' ;
+                                       break ;
+
+                               /*
+                                * Always extract the argument as a "char *" pointer. We 
+                                * should be using "void *" but there are still machines 
+                                * that don't understand it.
+                                * If the pointer size is equal to the size of an unsigned
+                                * integer we convert the pointer to a hex number, otherwise 
+                                * we print "%p" to indicate that we don't handle "%p".
+                                */
+                               case 'p':
+                                       /* Assume that pointers are of same size as "unsigned long" */
+                                       ui_num = (u_wide_int)(unsigned long)va_arg( ap, char * ) ;
+
+                                       if ( sizeof( char * ) <= sizeof( u_wide_int ) )
+                                               s = conv_p2( ui_num, 4, 'x', 
+                                               &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
+                                       else
+                                       {
+                                               s = "%p" ;
+                                               s_len = 2 ;
+                                       }
+                                       pad_char = ' ' ;
+                                       break ;
+                                       
+
+                               case NUL:
+                                       /*
+                                        * The last character of the format string was %.
+                                        * We ignore it.
+                                        */
+                                       continue ;
+
+
+                                       /*
+                                        * The default case is for unrecognized %'s.
+                                        * We print %<char> to help the user identify what
+                                        * option is not understood.
+                                        * This is also useful in case the user wants to pass
+                                        * the output of __sio_converter to another function
+                                        * that understands some other %<char> (like syslog).
+                                        * Note that we can't point s inside fmt because the
+                                        * unknown <char> could be preceded by width etc.
+                                        */
+                               default:
+                                       char_buf[ 0 ] = '%' ;
+                                       char_buf[ 1 ] = *fmt ;
+                                       s = char_buf ;
+                                       s_len = 2 ;
+                                       pad_char = ' ' ;
+                                       break ;
+                       }
+
+                       if ( prefix_char != NUL )
+                       {
+                               *--s = prefix_char ;
+                               s_len++ ;
+                       }
+
+                       if ( adjust_width && adjust == RIGHT && min_width > s_len )
+                       {
+                               if ( pad_char == '0' && prefix_char != NUL )
+                               {
+                                       INS_CHAR( *s, sp, bep, odp, cc, fd )
+                                       s++ ;
+                                       s_len-- ;
+                                       min_width-- ;
+                               }
+                               PAD( min_width, s_len, pad_char ) ;
+                       }
+
+                       /*
+                        * Print the string s. 
+                        */
+                       for ( i = s_len ; i != 0 ; i-- )
+                       {
+                               INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
+                               s++ ;
+                       }
+
+                       /*
+                        * Ignore pad_char for right padding, as padding
+                        * with zeroes would produce a different number.
+                        */
+                       if ( adjust_width && adjust == LEFT && min_width > s_len )
+                               PAD( min_width, s_len, ' ' ) ;
+               }
+               fmt++ ;
+       }
+       odp->nextb = sp ;
+       return( cc ) ;
+}
+
diff --git a/libs/src/str/CHANGELOG b/libs/src/str/CHANGELOG
new file mode 100644 (file)
index 0000000..2fbea8d
--- /dev/null
@@ -0,0 +1,19 @@
+
+1.2.0: 
+       First release (as part of xinetd 1.3)
+
+1.3.2:
+       Added the string matching functions
+
+1.3.3: (posted to alt.sources)
+       Changed the way the library is configured
+
+1.4.0:
+       Added the shift-or string matching algorithm
+       Implemented the automatic switching to the proper search algorithm
+       Added the STRS_NOSWITCH flag to disallow switching
+       Added the STRS_PATLEN flag
+
+1.4.1:
+       Moved definition of u_wide_int from ss_rk.h to ss_impl.h
+
diff --git a/libs/src/str/COPYRIGHT b/libs/src/str/COPYRIGHT
new file mode 100644 (file)
index 0000000..dfb323c
--- /dev/null
@@ -0,0 +1,29 @@
+This software is
+
+(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution and that this file is also included in any redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
diff --git a/libs/src/str/Makefile.in b/libs/src/str/Makefile.in
new file mode 100644 (file)
index 0000000..cc74b71
--- /dev/null
@@ -0,0 +1,109 @@
+# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+#
+# Based on Library makefile template: *Revision: 1.15 *
+#
+
+NAME                   = str
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = str.h strparse.h
+SOURCES                        = strutil.c strprint.c strparse.c
+OBJECTS                        = strutil.o strprint.o strparse.o
+
+MANFILES               = $(SRCDIR)/strparse.3 $(SRCDIR)/strprint.3 \
+                       $(SRCDIR)/strutil.3
+INCLUDEFILES           = $(SRCDIR)/str.h
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+#
+# Available flags
+#      NBIC    : number of bits in a character variable (defaults to 8)
+#      WIDE_INT : widest integer supported by the CPU/compiler
+#                        (defaults to 'long')
+#      WIDE_INT_SIZE  : size of the WIDE_INT type in bits (defaults to 32);
+#                effective (and required) only when WIDE_INT is defined
+#      NO_SIO  : if the SIO library is not available (results in turning
+#                        all the string printing functions to no-ops)
+#
+DEBUG                  = -g            # -g or -O
+
+CPP_DEFS               = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS) -I$(INCLUDEDIR)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                        # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O "DEFS=$(DEFS)" lib
+       $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR)-O
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+LINT_IGNORE=possible pointer alignment|RCSid unused
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               $(RANLIB) $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+               for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
+               echo Installed $(MANFILES) to $(MANDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+       a=`pwd` ; cd $(MANDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+spotless: clean uninstall
+
+distclean: clean
+       rm -f Makefile
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+strparse.o:            strparse.h str.h
+strprint.o:            str.h
+strutil.o:             str.h
+
diff --git a/libs/src/str/README b/libs/src/str/README
new file mode 100644 (file)
index 0000000..d07936e
--- /dev/null
@@ -0,0 +1,73 @@
+======================================================================
+NOTE: I use vi with a tabstop value of 3. Using the same tabstop
+               value will make the text/code look properly indented.
+======================================================================
+
+
+1. What is this library about ?
+
+The STR library consists of string handling functions. These
+functions can be separated into 4 groups:
+
+A. String matching functions. A variety of algorithms are available
+       for string matching:
+                       brute force
+                       Rabin-Karp
+                       Knuth-Morris-Pratt
+                       Boyer-Moore
+                       Shift-or
+
+B. String printing functions (similar to sprintf). These functions offer
+       2 significant advantages over sprintf:
+               1) they include functions that will *not* overrun the string buffer 
+                       provided
+               2) they include functions returning "char *" as well as functions
+                       returning "int" so that one can pick the most appropriate one.
+
+C. String parsing functions. These functions offer an easy way of breaking
+       a string into pieces.
+
+D. String utility functions. This group includes functions that will
+       convert a string to upper/lower case etc.
+
+
+2. Setting up the STR library
+
+All you need to do is type 'make'. This will create the library in the
+current directory.  The string printing functions use (and therefore
+require) the underlying format conversion facility of my SIO (Stream
+I/O) library.  If you don't want to bother with it, you can define the
+flag NO_SIO in the Makefile (check the Makefile comments on how to do
+this) which will turn all string printing functions to no-ops.  The SIO
+library is available from mystique.cs.colorado.edu in the directory
+pub/libs (it may also be available at other places).  Make sure you get
+SIO version 1.6.2 or later; versions prior to 1.6.2 will result in
+identical behavior between the strx_*print* and the str_*print*
+functions.
+
+To install the library and the associated man pages and include files
+type 'make install'. This will install the library in LIBDIR, the man
+pages in MANDIR and the include files in INCLUDEDIR.  LIBDIR,
+INCLUDEDIR, and MANDIR are Makefile variables that you can edit in the
+Makefile or override when you invoke 'make'.
+
+
+
+3. Epilogue
+
+Please send bug-reports/comments to panos@cs.colorado.edu
+
+You can obtain the latest version of this library from
+mystique.cs.colorado.edu in the directory pub/libs.
+
+Feel free to modify the library to suit your needs.  If you want to
+distribute modifications to this library, please read the COPYRIGHT
+file.  It basically says that you are free to redistribute as long as
+you retain the original copyright notice and you make sure that your
+modifications are identifiable. In order to achieve this I have
+reserved the first 3 components of the version number (for example,
+1.4.2) and you can identify your mods by appending another component to
+that version number (for example, 1.4.2.A2). Also, if you distribute a
+modified version of the library, you take full responsibility for any
+bugs in the code (not just your code; the whole thing).
+
diff --git a/libs/src/str/install-sh b/libs/src/str/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/src/str/str.h b/libs/src/str/str.h
new file mode 100644 (file)
index 0000000..e1d234c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#ifndef __STR_H
+#define __STR_H
+
+/*
+ * $Id: str.h,v 1.4 2003/06/07 16:46:32 steveg Exp $
+ */
+
+#include <stdarg.h>
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT(n, m) \
+   __attribute__ ((format (printf, n, m)))
+#else
+#define PRINTF_FORMAT(n, m)
+#endif
+
+typedef void *str_h ;
+
+/*
+ * strprint(3) functions
+ */
+char *strx_sprint ( char *buf, int len, const char *fmt, ... ) 
+   PRINTF_FORMAT(3, 4);
+int strx_nprint ( char *buf, int len, const char *fmt, ... ) 
+   PRINTF_FORMAT(3, 4);
+void strx_print ( int *count, char *buf, int len, const char *fmt, ... )
+   PRINTF_FORMAT(4, 5);
+
+int strx_nprintv ( char *buf, int len, const char *fmt, va_list )
+   PRINTF_FORMAT(3, 0);
+void strx_printv ( int *cnt, char *buf, int len, const char *fmt, va_list ) 
+   PRINTF_FORMAT(4, 0);
+
+/*
+ * strparse(3) functions
+ */
+int str_setstr( str_h handle, char *newstr );
+   
+/*
+ * Return values
+ */
+#define STR_OK                                  0
+#define STR_ERR                                 (-1)
+   
+
+/* 
+ * Flags for the string parsing functions
+ */
+#define STR_NOFLAGS                    0x0
+#define STR_RETURN_ERROR               0x1
+#define STR_NULL_START                 0x2
+#define STR_NULL_END                   0x4
+#define STR_MALLOC                     0x8
+
+/*
+ * Error values
+ */
+#define STR_ENULLSEPAR                 1
+#define STR_ENULLSTRING                        2
+#define STR_ENOMEM                     3
+
+char *new_string(const char *) ;
+str_h str_parse ( char *str, const char *separ, int flags, int *errnop ) ;
+void str_endparse ( str_h handle ) ;
+char *str_component ( str_h handle ) ;
+
+
+/*
+ * strutil(3) functions
+ */
+char *str_casefind ( char *s1, const char *s2 ) ;
+void str_fill ( char *s, char c ) ;
+
+
+#endif         /* __STR_H */
+
diff --git a/libs/src/str/strparse.3 b/libs/src/str/strparse.3
new file mode 100644 (file)
index 0000000..ade2757
--- /dev/null
@@ -0,0 +1,161 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: strparse.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH STRPARSE 3X "30 September 1992"
+.SH NAME
+str_parse, str_endparse, str_component, str_separator, str_nextpos
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "str.h"
+.LP
+.ft B
+str_h str_parse( str, separ, flags, errnop )
+char *str ;
+char *separ ;
+int flags ;
+int *errnop ;
+.LP
+.ft B
+void str_endparse( handle )
+str_h handle ;
+.LP
+.ft B
+char *str_component( handle )
+str_h handle ;
+.LP
+.ft B
+int str_setstr( handle, newstr )
+str_h handle ;
+char *newstr ;
+.LP
+.ft B
+int str_separator( handle, separ )
+str_h handle ;
+char *separ ;
+.LP
+.ft B
+char *str_nextpos( handle )
+str_h handle ;
+.LP
+extern int str_errno ;
+.SH DESCRIPTION
+.LP
+These functions are useful for parsing strings.  In this context
+parsing means breaking the string into substrings. The substrings are
+separated by a list of possible separator characters.
+.LP
+.B str_component()
+returns successive substrings of the string.
+.B str_parse()
+creates and initializes a string parser with the string
+that will be processed, \fIstr\fR, the list of possible separator
+characters, \fIsepar\fR, and flags that control how the parser
+works. The \fIflags\fR argument is formed by ORing one or more of
+the following constants:
+.TP 20
+.SB STR_RETURN_ERROR
+If something goes wrong return a value that indicates that an error occured
+(e.g. out of memory). The default is for the program to be terminated
+with an appropriate error message.
+.TP
+.SB STR_NULL_START
+If \fIstr\fR starts with a separator then a zero-length string will be returned
+the first time \fBstr_component()\fR is called.
+.TP
+.SB STR_NULL_END
+If \fIstr\fR ends with a separator then a zero-length string will be returned
+by \fBstr_component()\fR when the substrings of \fIstr\fR are exhausted.
+.TP
+.SB STR_MALLOC
+The strings returned by \fBstr_component()\fR will be in malloc'ed memory.
+By default the substrings are part of \fIstr\fR.
+If this option is not used \fIstr\fR will be modified
+by \fBstr_component()\fR.
+.LP
+Finally, \fBSTR_NOFLAGS\fR may be used to specify no flags.
+The \fIerrnop\fR argument points to an integer where the string processing
+functions will deposit an error code if an error occurs.
+If \fIerrnop\fR
+is
+.SM NULL
+the error codes will be placed in \fIstr_errno\fR.
+This is useful only if \fBSTR_RETURN_ERROR\fR is used in \fIflags\fR.
+It is possible that \fIstr\fP is 
+.SM NULL.
+In this case, a subsequent
+.B str_setstr()
+should be used to specify the string to be processed.
+.LP
+.B str_component()
+returns successive substrings from the string associated with the
+parser specified by \fIhandle\fR.
+.LP
+.B str_endparse()
+destroys the parser specified by \fIhandle\fR.
+.LP
+.B str_setstr()
+changes the processed string to \fInewstr\fP.
+.LP
+.B str_separator()
+replaces the list of separator characters with \fIsepar\fR.
+Processing continues from the current position.
+.LP
+.B str_nextpos()
+returns a pointer to the rest of the string. The previous character
+is a separator character (if \fBSTR_MALLOC\fR is not set, then the
+previous character is
+.SM NUL
+).
+.SH "RETURN VALUES"
+.LP
+.B str_parse()
+returns a parser handle or
+.SM NULL
+if something goes wrong and \fIflags\fR & \fBSTR_RETURN_ERROR\fR is true.
+Possible \fIstr_errno\fR values:
+.RS
+.TP 20
+.SB STR_ENULLSEPAR
+\fIsepar\fR is
+.SM NULL
+.TP
+.SB STR_ENOMEM
+the program ran out of memory
+.RE
+.LP
+.B str_component()
+returns a pointer to the next substring or
+.SM NULL
+if something goes wrong and \fIflags\fR & \fBSTR_RETURN_ERROR\fR is true.
+.LP
+.B str_setstr()
+returns 
+.SB STR_OK
+on success or
+.SB STR_ERR
+on failure.
+.LP
+.B str_separator()
+returns 
+.SB STR_OK
+on success or
+.SB STR_ERR
+on failure.
+.LP
+.B str_nextpos()
+returns a pointer or
+.SM NULL
+if the end of string has been reached.
+.SH BUGS
+.B str_component()
+modifies the string unless \fBSTR_MALLOC\fR is
+set in the parser.
+.LP
+There should be only one parser active on a specific string. If there
+is more than
+one, they all must use the \fBSTR_MALLOC\fR option.
+
diff --git a/libs/src/str/strparse.c b/libs/src/str/strparse.c
new file mode 100644 (file)
index 0000000..4c0c355
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "str.h"
+#include "strparse.h"
+#include "sio.h"
+
+static int str_errno ;
+
+#define HANDLE_ERROR( flags, retval, errp, errval, msg )    \
+       if ( flags & STR_RETURN_ERROR )                 \
+       {                                               \
+               *errp = errval ;                         \
+               return( retval ) ;                       \
+        }                                               \
+        else                                            \
+               terminate( msg );
+
+
+char *new_string( const char *s )
+{
+   if ( s )
+      return strdup( s ) ;
+   else
+      return 0;
+}
+
+str_h str_parse( register char *str, const char *separ, int flags, int *errnop )
+{
+       register struct str_handle *hp ;
+       int *errp = ( errnop == NULL ) ? &str_errno : errnop ;
+
+       if ( separ == NULL ) {
+               HANDLE_ERROR( flags, NULL, errp, STR_ENULLSEPAR,
+                       "STR str_parse: NULL separator" ) ;
+       }
+
+       hp = (struct str_handle *) malloc( sizeof( struct str_handle ) ) ;
+       if ( hp == NULL ) {
+               HANDLE_ERROR( flags, NULL, errp, STR_ENOMEM,
+                       "STR str_parse: malloc failed" ) ;
+       }
+
+       hp->string = str ;
+       hp->pos = str ;
+       hp->separator = new_string( separ ) ;
+       if ( hp->separator == NULL ) {
+               if ( flags & STR_RETURN_ERROR )
+               {
+                       free( (char *) hp ) ;
+                       *errp = STR_ENOMEM ;
+                       return( NULL ) ;
+               } else {
+                       terminate( "STR str_parse: malloc failed" ) ;
+               }
+       }
+       
+       hp->flags = flags ;
+       hp->errnop = errp ;
+       hp->no_more = ( str == NULL ) ;
+       return( (str_h) hp ) ;
+}
+
+
+void str_endparse( str_h handle )
+{
+       register struct str_handle *hp = (struct str_handle *) handle ;
+
+       if( hp->separator != NULL )
+               free( hp->separator ) ;
+       free( (char *) handle ) ;
+}
+
+
+/*
+ * Change the string
+ */
+int str_setstr( str_h handle, char *newstr )
+{
+        register struct str_handle *hp = (struct str_handle *) handle ;
+               
+        if ( newstr == NULL ) {
+                HANDLE_ERROR( hp->flags, STR_ERR, hp->errnop, STR_ENULLSTRING,
+                        "STR str_setstr: NULL string" ) ;
+        }
+                               
+        hp->string = newstr ;
+        hp->pos = newstr ;
+        hp->no_more = FALSE ;
+        return( STR_OK ) ;
+}
+
+
+char *str_component( str_h handle )
+{
+       register char                   *start ;
+       register char                   *last ;
+       register unsigned int           sep_count ;
+       char                            *retval ;
+       int                             last_char ;
+       register struct str_handle      *hp     = (struct str_handle *) handle ;
+       register int                    first_call = ( hp->pos == hp->string ) ;
+
+       if ( hp->no_more )
+               return( NULL ) ;
+
+       /*
+        * Get number of separator characters.
+        * Find beginning of component.
+        */
+       sep_count = strspn( hp->pos, hp->separator ) ;
+
+       /*
+        * If this is the first call, and there are separator characters
+        * at the beginning of the string and the STR_NULL_START flag is set
+        * we return a 0-length string.
+        */
+       if ( first_call && ( sep_count > 0 ) && ( hp->flags & STR_NULL_START ))
+       {
+               start = hp->pos ;
+               last = hp->pos ;
+       }
+       else
+       {
+               start = hp->pos + sep_count ;
+
+               if ( *start == '\0' )
+               {
+                       last = start ;
+                       hp->no_more = TRUE ;
+                       if ( ! ( hp->flags & STR_NULL_END ) )
+                               return( NULL ) ;
+               }
+               else
+               {
+                       last = strpbrk( start, hp->separator ) ;
+                       if ( last == NULL )
+                               last = start + strlen( start ) ;
+               }
+       }
+
+       /*
+        * At this point, the following variables must be set:
+        *              start:  beginning of component
+        *              last:   end of component + 1
+        *
+        * If STR_MALLOC is set, allocate space for the new string.
+        *
+        * NOTE: If STR_MALLOC is not set, the processed string is trashed.
+        */
+       last_char = *last ;
+       if ( hp->flags & STR_MALLOC )
+       {
+               int len = last - start ;
+
+               retval = malloc( (unsigned)len + 1 ) ;
+               if ( retval == NULL ) {
+                       HANDLE_ERROR( hp->flags, NULL, hp->errnop, STR_ENOMEM,
+                               "STR str_component: malloc failed" ) ;
+               }
+               strncpy( retval, start, len )[ len ] = '\0' ;
+       }
+       else
+       {
+               retval = start ;
+               *last = '\0' ;
+       }
+
+       /*
+        * Check if last_char is NUL to avoid setting hp->pos past the
+        * end of the string
+        */
+       hp->pos = ( last_char == '\0' ) ? last : last+1 ;
+       return( retval ) ;
+}
+
diff --git a/libs/src/str/strparse.h b/libs/src/str/strparse.h
new file mode 100644 (file)
index 0000000..3bf7875
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef __STRPARSE_H
+#define __STRPARSE_H
+
+/*
+ * $Id: strparse.h,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+ */
+
+struct str_handle
+{
+   char *string ;
+   char *separator ;
+   char *pos ;
+   int flags ;
+   int *errnop ;
+   int no_more ;
+} ;
+
+
+#ifndef NULL
+#define NULL         0
+#endif
+
+#ifndef FALSE
+#define FALSE        0
+#define TRUE         1
+#endif
+
+#endif /* __STRPARSE_H */
+
diff --git a/libs/src/str/strprint.3 b/libs/src/str/strprint.3
new file mode 100644 (file)
index 0000000..9cd9eb0
--- /dev/null
@@ -0,0 +1,157 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: strprint.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH STRPRINT 3X "30 September 1992"
+.SH NAME
+str_sprint, tr_sprintv, str_nprint, str_nprintv, str_print, str_printv, strx_sprint, strx_sprintv, strx_nprint, strx_nprintv, strx_print, strx_printv -- formatted conversion to string
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "str.h"
+.LP
+.ft B
+char *str_sprint( buf, format, ... )
+char *buf ;
+char *format ;
+.LP
+.ft B
+char *str_sprintv( buf, format, ap )
+char *buf ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+int str_nprint( buf, format, ... )
+char *buf ;
+char *format ;
+.LP
+.ft B
+int str_nprintv( buf, format, ap )
+char *buf ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+void str_print( countp, buf, format, ... )
+int *countp ;
+char *buf ;
+char *format ;
+.LP
+.ft B
+void str_printv( countp, buf, format, ap )
+int *countp ;
+char *buf ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+char *strx_sprint( buf, len, format, ... )
+char *buf ;
+int len ;
+char *format ;
+.LP
+.ft B
+char *strx_sprintv( buf, len, format, ap )
+char *buf ;
+int len ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+int strx_nprint( buf, len, format, ... )
+char *buf ;
+int len ;
+char *format ;
+.LP
+.ft B
+int strx_nprintv( buf, len, format, ap )
+char *buf ;
+int len ;
+char *format ;
+va_list ap ;
+.LP
+.ft B
+void strx_print( countp, buf, len, format, ... )
+int *countp ;
+char *buf ;
+int len ;
+char *format ;
+.LP
+.ft B
+void strx_printv( countp, buf, len, format, ap )
+int *countp ;
+char *buf ;
+int len ;
+char *format ;
+va_list ap ;
+.SH DESCRIPTION
+.LP
+All functions are similar in functionality to \fIsprintf()\fR.
+Their only difference is in their return values. For information about their
+conversion capabilities, check \fISprint(3)\fR.
+.LP
+The difference between the \fIstr_*\fR and the \fIstrx_*\fR functions
+is that the latter take an extra argument, the size of the buffer, so
+that they will never write beyond the end of the buffer. Writing
+beyond the end of the buffer is possible with the \fIstr_*\fR functions.
+Previously, invoking any of the \fIstrx_*\fR functions with the
+.I len
+argument set to 0
+used to be the same as calling the equivalent \fIstr_*\fR function.
+This dangerous behavior has since been changed and now the \fIstrx_*\fR
+functions don't touch the buffer when
+.I len
+is 0 or negative.
+.LP
+All functions will append a
+.SM NUL
+at the end of
+.I buf
+(the \fIstrx_*\fR functions will not do this if it would cause 
+a buffer overrun).
+.LP
+.B str_print(),
+.B str_printv(),
+.B strx_print(),
+and
+.B strx_printv()
+will put in
+.I "*countp"
+the number of characters placed in 
+.I buf
+excluding the ending
+.SM NUL
+(this happens only if
+.I "*countp"
+is not
+.SM NULL
+).
+.LP
+The functions that have a name ending in 'v' are similar to those without
+the 'v' at the end of their name
+except that instead of accepting a variable number of arguments, they
+expect a \fIstdarg(3)\fR argument list.
+.SH "RETURN VALUES"
+.LP
+.B str_sprint(),
+.B str_sprintv(),
+.B strx_sprint(),
+and
+.B strx_sprintv()
+return
+.I buf.
+.LP
+.B str_nprint(),
+.B str_nprintv(),
+.B strx_nprint(),
+and
+.B strx_nprintv()
+return the number of characters placed in 
+.I buf
+excluding the ending
+.SM NUL.
+.SH "SEE ALSO"
+Sprint(3)
diff --git a/libs/src/str/strprint.c b/libs/src/str/strprint.c
new file mode 100644 (file)
index 0000000..0fd7ec8
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#ifndef NO_SIO
+#include "sio.h"
+#endif
+
+#include "str.h"
+#include "strparse.h"
+
+#define INT_NULL                       ((int *)0)
+
+/*
+ * The strx_* functions will never over-run the buffer
+ * The str_* functions may over-run the buffer
+ */
+
+/*
+ * Group 1: the strx_* functions
+ */
+
+/*
+ * This is the general purpose conversion function. It is invoked
+ * by all the other str[x]_* functions
+ */
+void strx_printv( int *ccp, char *buf, int len, const char *format, va_list ap )
+{
+#ifndef NO_SIO
+       __sio_od_t od ;
+       int cc ;
+
+   /*
+    * First initialize the descriptor
+        * Notice that if no length is given, we initialize buf_end to the
+        * highest possible address.
+    */
+   od.buf = buf ;                                                              /* NOT NEEDED        */
+   od.buf_end = len ? &buf[ len ] : (char *) ~0 ;      /* NEEDED                               */
+   od.buffer_size = 0 ;                                                        /* NOT NEEDED        */
+   od.start = buf ;                                                            /* NOT NEEDED        */
+   od.nextb = buf ;                                                            /* NEEDED            */
+   od.buftype = 0 ;                                                            /* NOT NEEDED        */
+
+   /*
+    * Do the conversion
+    */
+   cc = __sio_converter( &od, -1, format, ap ) ;
+       if ( len == 0 || od.nextb < od.buf_end )
+               *(od.nextb) = '\0' ;
+   if ( ccp )
+      *ccp = cc ;
+#endif /* ! NO_SIO */
+}
+
+
+void strx_print( int *ccp, char *buf, int len, const char *format, ... )
+{
+       va_list ap ;
+
+       if (len <= 0) {
+               if( ccp )
+                       *ccp = 0;
+               return;
+       }
+
+       va_start( ap, format ) ;
+       strx_printv( ccp, buf, len, format, ap ) ;
+       va_end( ap ) ;
+}
+
+
+char *strx_sprint( char *buf, int len, const char *format, ... )
+{
+       va_list ap ;
+
+       if (len <= 0) {
+               return buf;
+       }
+       va_start( ap, format ) ;
+       strx_printv( INT_NULL, buf, len, format, ap ) ;
+       va_end( ap ) ;
+       return( buf ) ;
+}
+
+
+int strx_nprint( char *buf, int len, const char *format, ...)
+{
+       int cc ;
+       va_list ap ;
+
+       if (len <= 0) {
+               return 0;
+       }
+       va_start( ap, format ) ;
+       strx_printv( &cc, buf, len, format, ap ) ;
+       va_end( ap ) ;
+       return( cc ) ;
+}
+
+
+int strx_nprintv( char *buf, int len, const char *format, va_list ap )
+{
+       int cc ;
+
+       if (len <= 0) {
+               return 0;
+       }
+       strx_printv( &cc, buf, len, format, ap ) ;
+       return( cc ) ;
+}
+
+
diff --git a/libs/src/str/strutil.3 b/libs/src/str/strutil.3
new file mode 100644 (file)
index 0000000..ab24e1d
--- /dev/null
@@ -0,0 +1,62 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: strutil.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH STRUTIL 3X "30 September 1992"
+.SH NAME
+str_find, str_casefind, str_fill, str_lower, str_upper -- string utility functions
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "str.h"
+.LP
+.ft B
+char *str_find( s1, s2 )
+char *s1, *s2 ;
+.LP
+.ft B
+char *str_casefind( s1, s2 )
+char *s1, *s2 ;
+.LP
+.ft B
+void str_fill( s, c )
+char *s ;
+char c ;
+.LP
+.ft B
+char *str_lower( s )
+char *s ;
+.LP
+.ft B
+char *str_upper( s )
+char *s ;
+.SH DESCRIPTION
+.B str_find()
+returns a pointer to the first instance of string \fIs2\fR in string \fIs1\fR.
+If \fIs2\fR is the empty string a pointer to \fIs1\fR is returned.
+.LP
+.B str_casefind()
+performs the same function as
+.B str_find()
+except that it performs case insensitive character comparisons.
+.LP
+.B str_fill()
+fills the string \fIs\fR with the character \fIc\fR.
+.LP
+.B str_lower()
+and
+.B str_upper()
+convert their argument in place to a lower or upper case string respectively.
+.SH "RETURN VALUES"
+.LP
+\fBstr_find()\fR 
+and
+.B str_casefind()
+return a pointer to the first occurrence of \fIs2\fR
+in \fIs1\fR or
+.SM NULL
+if \fIs2\fR does not exist in \fIs1\fR.
+.LP
+\fBstr_lower()\fR and \fBstr_upper()\fR return \fIs\fR.
diff --git a/libs/src/str/strutil.c b/libs/src/str/strutil.c
new file mode 100644 (file)
index 0000000..094da45
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <ctype.h>
+
+#ifndef NULL
+#define NULL                           0
+#endif
+
+#define TRIVIAL_STR_FIND 1
+
+#ifndef TRIVIAL_STR_FIND
+
+#define LOWER_CASE( c )                                        ( (c) + 'a' - 'A' )
+
+/*
+ * look for an instance of sstr in str
+ * Returns a pointer to the beginning of sstr in str.
+ * It ignores the case of the alphabetic characters
+ */
+char *str_casefind( register char *str, char *sstr )
+{
+       register int ssfc = *sstr++ ;           /* sub-string first char */
+
+       if ( ssfc == 0 )
+               return( str ) ;
+
+       if ( isalpha( ssfc ) && isupper( ssfc ) )
+               ssfc = LOWER_CASE( ssfc ) ;
+
+       while ( *str )
+       {
+               char *current = str ;
+               register int strc = *str++ ;
+               char *sp ;                                                      /* string pointer */
+               char *ssp ;                                                     /* sub-string pointer */
+
+               if ( isalpha( strc ) && isupper( strc ) )
+                       strc = LOWER_CASE( strc ) ;
+               if ( strc != ssfc )
+                       continue ;
+               
+               for ( sp = str, ssp = sstr ;; sp++, ssp++ )
+               {
+                       register int sc = *sp ;                         /* string char */
+                       register int ssc = *ssp ;                       /* substring char */
+
+                       /*
+                        * End-of-substring means we got a match
+                        */
+                       if ( ssc == 0 )
+                               return( current ) ;
+
+                       /*
+                        * Convert to lower case if alphanumeric
+                        */
+                       if ( isalpha( sc ) && isupper( sc ) )
+                               sc = LOWER_CASE( sc ) ;
+                       if ( isalpha( ssc ) && isupper( ssc ) )
+                               ssc = LOWER_CASE( ssc ) ;
+                       if ( sc != ssc )
+                               break ;
+               }
+       }
+
+       return( 0 ) ;
+}
+
+
+#else          /* defined( TRIVIAL_STR_FIND ) */
+
+/*
+ * look for an instance of s2 in s1
+ * Returns a pointer to the beginning of s2 in s1.
+ * It ignores the case of the alphabetic characters
+ */
+char *str_casefind( char *s1, const char *s2 )
+{
+   unsigned int i ;
+   unsigned long l1 = strlen( s1 ) ;
+   unsigned long l2 = strlen( s2 ) ;
+   
+   if ( l2 > l1 )
+      return( NULL ) ;
+
+   for ( i = 0 ; i < l1 - l2 + 1 ; i++ )
+      if ( strncasecmp( &s1[ i ], s2, l2 ) == 0 )
+         return( (char *) &s1[ i ] ) ;
+   return( NULL ) ;
+}
+
+#endif         /* TRIVIAL_STR_FIND */
+
+
+/*
+ * Fill string s with character c
+ */
+void str_fill( char *s, char c )
+{
+       while ( *s ) *s++ = c ;
+}
+
diff --git a/libs/src/xlog/CHANGELOG b/libs/src/xlog/CHANGELOG
new file mode 100644 (file)
index 0000000..e076e44
--- /dev/null
@@ -0,0 +1,12 @@
+
+1.0.8:
+       First release
+
+1.0.9:
+       Fixed bug in the syslog xlogs.
+
+1.1.2:
+       * Timestamps are now always included
+       * If NO_SYSLOG is defined, syslog xlogs become unavailable (this was
+         available in 1.0.9 but it didn't work right).
+
diff --git a/libs/src/xlog/COPYRIGHT b/libs/src/xlog/COPYRIGHT
new file mode 100644 (file)
index 0000000..362419b
--- /dev/null
@@ -0,0 +1,30 @@
+This software is
+
+(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+
+The author (Panagiotis Tsirigotis) grants permission to use, copy,
+and distribute this software and its documentation for any purpose 
+and without fee, provided that the above copyright notice extant in
+files in this distribution is not removed from files included in any
+redistribution and that this copyright notice is also included in any 
+redistribution.
+
+Modifications to this software may be distributed, either by distributing
+the modified software or by distributing patches to the original software,
+under the following additional terms:
+
+1. The version number will be modified as follows:
+      a. The first 3 components of the version number
+         (i.e <number>.<number>.<number>) will remain unchanged.
+      b. A new component will be appended to the version number to indicate
+         the modification level. The form of this component is up to the 
+         author of the modifications.
+
+2. The author of the modifications will include his/her name by appending it 
+   along with the new version number to this file and will be responsible for 
+   any wrong behavior of the modified software.
+
+The author makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without any express 
+or implied warranty.
+
diff --git a/libs/src/xlog/Makefile.in b/libs/src/xlog/Makefile.in
new file mode 100644 (file)
index 0000000..4a89870
--- /dev/null
@@ -0,0 +1,102 @@
+# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+#
+# Based on Library makefile template: *Revision: 1.15 *
+#
+
+NAME                   = xlog
+VPATH                  = @srcdir@
+SRCDIR                 = @srcdir@
+
+HEADERS                        = xlog.h impl.h slog.h filelog.h
+SOURCES                        = xlog.c filelog.c slog.c util.c
+OBJECTS                        = xlog.o filelog.o slog.o util.o
+
+MANFILES               = $(SRCDIR)/xlog.3
+INCLUDEFILES           = $(SRCDIR)/xlog.h
+
+# The following variables are used by the 'install' entry and
+# should be customized:
+#     LIBDIR:     where the library will be placed
+#     INCUDEDIR:  where the include files will be placed
+#     MANDIR:     where the man pages will be placed
+#
+LIBDIR                 = ../../lib
+MANDIR                 = ../../man
+INCLUDEDIR             = ../../include
+
+#
+# Flags:
+#     -DNO_SYSLOG
+#
+
+DEBUG                  = -g                    # -g or -O
+
+CPP_DEFS               = 
+
+#
+# The following variables shouldn't need to be changed
+#
+CPP_FLAGS              = $(CPP_DEFS) -I$(INCLUDEDIR)
+CC_FLAGS               = $(DEBUG)
+CFLAGS                 = @CFLAGS@ $(CPP_FLAGS) $(CC_FLAGS)
+
+INSTALL                        = @INSTALL@
+FMODE                  = -m 640                        # used by install
+RANLIB                 = @RANLIB@
+
+LIBNAME                        = lib$(NAME).a
+
+lib: $(LIBNAME)
+
+libopt: clean
+       make DEBUG=-O "DEFS=$(DEFS)" lib
+       $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR)/optimized
+
+$(LIBNAME): $(OBJECTS)
+       ar r $@ $?
+       $(RANLIB) $@
+
+install: $(LIBNAME)
+       @if test "$(LIBDIR)" -a "$(INCLUDEDIR)" -a "$(MANDIR)" ;\
+       then \
+               $(INSTALL) $(FMODE) $(LIBNAME) $(LIBDIR) ;\
+               $(RANLIB) $(LIBDIR)/$(LIBNAME) ;\
+               echo "Installed $(LIBNAME) to $(LIBDIR)" ;\
+               for i in $(INCLUDEFILES); do $(INSTALL) $(FMODE) $$i $(INCLUDEDIR) ; done ;\
+               echo Installed $(INCLUDEFILES) to $(INCLUDEDIR) ;\
+               for i in $(MANFILES) ; do $(INSTALL) $(FMODE) $$i $(MANDIR) ; done ;\
+               echo Installed $(MANFILES) to $(MANDIR) ;\
+       else \
+               echo "You forgot to set one of the following variables: LIBDIR,INCLUDEDIR,MANDIR" ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INCLUDEDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(INCLUDEFILES) ; fi
+       a=`pwd` ; cd $(LIBDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(LIBNAME) ; fi
+       a=`pwd` ; cd $(MANDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANFILES) ; fi
+
+clean:
+       rm -f $(OBJECTS) $(LIBNAME) core
+       rm -f *.swp
+       rm -f *.?~ 
+
+spotless: clean uninstall
+
+distclean: clean
+       rm -f Makefile
+
+#
+# PUT HERE THE RULES TO MAKE THE OBJECT FILES
+#
+xlog.o:                        xlog.h impl.h
+filelog.o:             xlog.h impl.h filelog.h
+slog.o:                        xlog.h impl.h slog.h
+
diff --git a/libs/src/xlog/filelog.c b/libs/src/xlog/filelog.c
new file mode 100644 (file)
index 0000000..ee688e5
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "config.h"
+#ifndef NO_SYSLOG
+#include <syslog.h>
+#else
+#define LOG_ALERT                              0
+#endif
+
+#include "sio.h"
+#include "str.h"
+#include "xlog.h"
+#include "filelog.h"
+
+static int filelog_init(xlog_s *, va_list) ;
+static void filelog_fini(xlog_s *) ;
+static int filelog_control(xlog_s *, xlog_cmd_e, va_list) ;
+static int filelog_write(xlog_s *, const char buf[], int, int, va_list) ;
+static int filelog_parms(xlog_e, va_list) ;
+static int limit_checks(const xlog_s *) ;
+
+struct xlog_ops __xlog_filelog_ops = 
+       {
+               filelog_init,
+               filelog_fini,
+               filelog_write,
+               filelog_control,
+               filelog_parms
+       } ;
+
+
+static int filelog_init( xlog_s *xp, va_list ap )
+{
+       int                             fd ;
+       struct filelog_s                *flp ;
+       char                            *filename;
+       int                             flags;
+
+       filename = va_arg(ap, char *);
+       flags = va_arg(ap, int);
+
+       flp = NEW( struct filelog_s ) ;
+       if ( flp == NULL )
+               return( XLOG_ENOMEM ) ;
+
+       if ( flags & O_CREAT )
+               fd = open( filename, flags, va_arg( ap, int ) ) ;
+       else
+               fd = open( filename, flags ) ;
+
+       if ( fd == -1 )
+       {
+               free( flp ) ;
+               return( XLOG_EOPEN ) ;
+       }
+       
+       FILELOG_DISABLE_SIZE_CONTROL( flp ) ;
+       (void) Sbuftype( fd, SIO_LINEBUF ) ;
+       flp->fl_fd = fd ;
+       flp->fl_state = FL_OPEN ;
+       xp->xl_data = flp ;
+       return( XLOG_ENOERROR ) ;
+}
+
+
+static void filelog_fini( xlog_s *xp )
+{
+       struct filelog_s *flp = FILELOG( xp ) ;
+
+       if ( flp->fl_state != FL_CLOSED )
+       {
+               (void) Sclose( flp->fl_fd ) ;
+               flp->fl_state = FL_CLOSED ;
+       }
+       free( flp ) ;
+       xp->xl_data = NULL ;
+}
+
+
+static int filelog_control( xlog_s *xp, xlog_cmd_e cmd, va_list ap )
+{
+       struct stat             st ;
+       struct filelog_s *flp   = FILELOG( xp ) ;
+       int             status  = XLOG_ENOERROR ;
+
+       if ( flp->fl_state == FL_ERROR )
+               return( flp->fl_error ) ;
+
+       switch ( cmd )
+       {
+               case XLOG_GETFD:
+                       if ( flp->fl_state == FL_OPEN )
+                               *va_arg( ap, int * ) = flp->fl_fd ;
+                       else
+                               status = XLOG_ENOERROR ;
+                       break ;
+
+               case XLOG_LIMITS:
+                       flp->fl_soft_limit = va_arg( ap, unsigned ) ;
+                       flp->fl_hard_limit = va_arg( ap, unsigned ) ;
+                       flp->fl_issued_warning = FALSE ;
+                       FILELOG_ENABLE_SIZE_CONTROL( flp ) ;
+                       flp->fl_state = FL_OPEN ;
+                       /* FALL THROUGH */
+
+               case XLOG_SIZECHECK:
+                       if ( ! FILELOG_SIZE_CONTROL( flp ) )
+                               break ;
+                       if ( fstat( flp->fl_fd, &st ) == -1 )
+                       {
+                               FILELOG_DISABLE_SIZE_CONTROL( flp ) ;
+                               flp->fl_state = FL_ERROR ;
+                               flp->fl_error = status = XLOG_EFSTAT ;
+                       }
+                       else
+                       {
+                               flp->fl_size = st.st_size ;
+                               if ( flp->fl_size > flp->fl_soft_limit )
+                                       status = limit_checks( xp ) ;
+                       }
+                       break ;
+               case XLOG_LINK:
+               case XLOG_CALLBACK:
+               case XLOG_GETFLAG:
+               case XLOG_SETFLAG:
+               case XLOG_LEVEL:
+               case XLOG_FACILITY:
+               case XLOG_PREEXEC:
+               case XLOG_POSTEXEC:
+                       break;
+       }
+       return( status ) ;
+}
+
+
+static int limit_checks( const xlog_s *xp )
+{
+       struct filelog_s *flp = FILELOG( xp ) ;
+       char buf[ 100 ] ;
+
+       if ( ! flp->fl_issued_warning )
+       {
+               if ( xp->xl_use != NULL )
+                       xlog_write( (xlog_h) xp->xl_use, buf,
+                               strx_nprint( buf, sizeof( buf ),
+                               "soft limit exceeded on '%s'", xp->xl_id ),
+                                       XLOG_NOFLAGS, LOG_ALERT ) ;
+               flp->fl_issued_warning = TRUE ;
+       }
+
+       if ( flp->fl_size <= flp->fl_hard_limit )
+               return( XLOG_ENOERROR ) ;
+       
+       if ( xp->xl_use != NULL )
+               xlog_write( (xlog_h) xp->xl_use, buf,
+                       strx_nprint( buf, sizeof( buf ),
+                       "hard limit exceeded on '%s'; log closed", xp->xl_id ),
+                               XLOG_NOFLAGS, LOG_ALERT ) ;
+       flp->fl_state = FL_ERROR ;
+       return( XLOG_ESIZE ) ;
+}
+
+
+static int filelog_write( xlog_s *xp, const char buf[], int len, int flags, 
+       va_list ap )
+{
+       struct filelog_s *flp   = FILELOG( xp ) ;
+       int     action_flags    = ( xp->xl_flags | flags ) ;
+       int     msglen          = 0 ;
+       int     percent_m_pos   = 0 ;
+       int     cc ;
+       int     status ;
+       time_t          current_time ;
+       struct tm       *tmp ;
+
+       if ( flp->fl_state != FL_OPEN )
+               return( flp->fl_error ) ;
+
+       (void) time( &current_time ) ;
+       tmp = localtime( &current_time ) ;
+       cc = Sprint( flp->fl_fd, "%02d/%d/%d@%02d:%02d:%02d",
+               tmp->tm_year%100, tmp->tm_mon+1, tmp->tm_mday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
+       if ( cc == SIO_ERR ) 
+               return XLOG_EWRITE;
+       
+       msglen += cc ;
+
+       if ( action_flags & XLOG_PRINT_ID )
+       {
+               cc = Sprint( flp->fl_fd, " %s", xp->xl_id ) ;
+               if ( cc == SIO_ERR ) {
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+       }
+
+       if ( action_flags & XLOG_PRINT_PID )
+       {
+               cc = Sprint( flp->fl_fd, "[%d]", getpid() ) ;
+               if ( cc == SIO_ERR ) { 
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+       }
+
+       cc = Sprint( flp->fl_fd, ": " ) ;
+       if ( cc == SIO_ERR ) { 
+               flp->fl_size += msglen ;
+               return XLOG_EWRITE;
+       }
+       msglen += cc ;
+
+       if ( ( action_flags & XLOG_NO_ERRNO ) ||
+               ( percent_m_pos = __xlog_add_errno( buf, len ) ) == -1 )
+       {
+               cc = Swrite( flp->fl_fd, buf, len ) ;
+               if ( cc == SIO_ERR ) { 
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+       }
+       else
+       {
+               char errno_buf[ 100 ] ;
+               unsigned size = sizeof( errno_buf ) ;
+               char *ep ;
+
+               /*
+                * The reason for the repetition of "msglen += cc ;" is that 
+                * in the future we may want to check cc for SIO_ERR
+                */
+               ep = __xlog_explain_errno( errno_buf, &size ) ;
+               cc = Swrite( flp->fl_fd, buf, percent_m_pos ) ;
+               if ( cc == SIO_ERR ) { 
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+               cc = Swrite( flp->fl_fd, ep, size ) ;
+               if ( cc == SIO_ERR ) { 
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+               cc = Swrite( flp->fl_fd, buf+percent_m_pos+2, 
+                               len-percent_m_pos-2 ) ;
+               if ( cc == SIO_ERR ) { 
+                       flp->fl_size += msglen ;
+                       return XLOG_EWRITE;
+               }
+               msglen += cc ;
+       }
+       /*
+        * Writing a newline will cause a buffer flush since we asked for
+        * line-buffered output
+        */
+       if ( Sputchar( flp->fl_fd, '\n' ) != SIO_ERR )
+               msglen++ ;
+
+       /*
+        * NOTE: we don't check if XLOG_NO_SIZECHECK is set in xp->xl_flags
+        *      because size control is off by default and in order to
+        *      be enabled XLOG_LIMITS must be used which overrides xp->xl_flags
+        */
+       if ( ! FILELOG_SIZE_CONTROL( flp ) || ( flags & XLOG_NO_SIZECHECK ) )
+               return( XLOG_ENOERROR ) ;
+
+       flp->fl_size += msglen ;
+       if ( flp->fl_size <= flp->fl_soft_limit || 
+               ( status = limit_checks( xp ) ) == XLOG_ENOERROR )
+               return( XLOG_ENOERROR ) ;
+       
+       flp->fl_state = FL_SIZE ;
+       return( status ) ;
+}
+
+
+static int filelog_parms( xlog_e type, va_list ap)
+{
+       return( XLOG_ENOERROR ) ;
+}
+
diff --git a/libs/src/xlog/filelog.h b/libs/src/xlog/filelog.h
new file mode 100644 (file)
index 0000000..bc5877a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+/*
+ * $Id: filelog.h,v 1.2 2003/03/09 19:29:21 steveg Exp $
+ */
+
+#ifndef __FILELOG_H
+#define __FILELOG_H
+
+#include "impl.h"
+
+/*
+ * The file can be either open or closed.
+ * When the file is closed, the state is always FL_CLOSED.
+ * When the file is open, the state is:
+ *             FL_OPEN:                        if everything is ok
+ *             FL_SIZE:                        if the hard limit was exceeded
+ *             FL_ERROR:               if an error occured
+ */
+typedef enum { FL_CLOSED = 0, FL_OPEN, FL_SIZE, FL_ERROR } filelog_state_e ;
+
+struct filelog_s
+{
+       int                                     fl_fd ;
+       filelog_state_e fl_state ;
+       int                                     fl_error ;                              /* error code when in FL_ERROR          */
+       bool_int                                fl_size_control ;               /* enabled or not                                                       */
+       bool_int                                fl_issued_warning ;     /* when the soft limit was exceeded     */
+       unsigned                        fl_size ;            /* current size                    */
+       unsigned                                fl_soft_limit ;
+       unsigned                                fl_hard_limit ;
+} ;
+
+#define FILELOG_ENABLE_SIZE_CONTROL( flp )     (flp)->fl_size_control = TRUE
+#define FILELOG_DISABLE_SIZE_CONTROL( flp )    (flp)->fl_size_control = FALSE
+#define FILELOG_SIZE_CONTROL( flp )                    ( (flp)->fl_size_control )
+
+#define FILELOG( xp )                  ((struct filelog_s *)xp->xl_data)
+
+#endif
+
diff --git a/libs/src/xlog/impl.h b/libs/src/xlog/impl.h
new file mode 100644 (file)
index 0000000..3760e58
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+/*
+ * $Id: impl.h,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+ */
+
+#ifndef __XLOG_IMPL_H
+#define __XLOG_IMPL_H
+
+#include <stdlib.h>    /* For malloc() & free() prototypes */
+#include <stdarg.h>
+#define DEFINE_LINK_TYPE( type, name )         struct { type *next, *prev ; } name
+
+
+#define NEXT( obj, field )             (obj)->field.next
+#define PREV( obj, field )             (obj)->field.prev
+
+#define INIT_LINKS( obj, field )                       \
+       {                                               \
+               NEXT( obj, field ) = obj ;              \
+               PREV( obj, field ) = obj ;              \
+       }
+
+/*
+ * Link new object after object using the specified field
+ */
+#define LINK( obj, new_obj, field )                    \
+       {                                               \
+               NEXT( new_obj, field ) = NEXT( obj, field ) ;   \
+               PREV( new_obj, field ) = obj ;                  \
+               NEXT( obj, field ) = new_obj ;                  \
+               PREV( NEXT( obj, field ), field ) = new_obj ;   \
+       }
+
+#define UNLINK( obj, field )                           \
+       {                                               \
+               NEXT( PREV( obj, field ), field ) = NEXT( obj, field ) ;        \
+               PREV( NEXT( obj, field ), field ) = PREV( obj, field ) ;        \
+       }
+
+
+/*
+ * xlog linking:
+ *     When xlog1 is linked to xlog2 (i.e. errors on xlog1 are reported to 
+ *             xlog2) we use the xl_clients field on xlog2 and the xl_other_users 
+ *             field on xlog1
+ */
+struct xlog
+{
+       xlog_e                  xl_type ;
+       char                            *xl_id ;
+       int                             xl_flags ;
+       void                            (*xl_callback)() ;
+       void                            *xl_callback_arg ;
+       struct xlog     *xl_use ;       /* xlog we report errors to             */
+       struct xlog     *xl_clients ;   /* linked list of xlogs that use */
+                                                                                                       /* this xlog to report errors   */
+       DEFINE_LINK_TYPE( struct xlog, xl_other_users ) ;
+       struct xlog_ops
+       {
+               int     (*init)         ( struct xlog *, va_list ) ;
+               void    (*fini)         ( struct xlog * ) ;
+               int     (*write)        ( struct xlog *, const char *, int, int, va_list ) ;
+               int     (*control)      ( struct xlog *, xlog_cmd_e, va_list ) ;
+               int     (*parms)        ( xlog_e, va_list ) ;
+       }       *xl_ops ;
+       void    *xl_data ;
+} ;
+
+#define XL_INIT( xp, ap )              (*(xp)->xl_ops->init)( (xp), (ap) )
+#define XL_FINI( xp )                  (*(xp)->xl_ops->fini)( xp )
+#define XL_WRITE( xp, buf, size, flags, ap ) \
+               (*(xp)->xl_ops->write)( (xp), (buf), (size), (flags), (ap ) )
+#define XL_CONTROL( xp, cmd, ap ) \
+               (*(xp)->xl_ops->control)( (xp), (cmd), (ap) )
+
+typedef struct xlog xlog_s ;
+
+typedef void (*voidfunc)() ;
+typedef int bool_int ;
+
+#define XP( p )                        ((struct xlog *)(p))
+
+#define XLOG_NULL              XP( NULL )
+
+#ifndef FALSE
+#define FALSE          0
+#define TRUE           1
+#endif
+
+#ifndef NULL
+#define NULL           0
+#endif
+
+#define NEW( type )            (type *) malloc( sizeof( type ) )
+
+int __xlog_add_errno(const char *, int) ;
+char *__xlog_explain_errno(char *, unsigned *) ;
+char *__xlog_new_string(const char *) ;
+
+#endif
+
diff --git a/libs/src/xlog/install-sh b/libs/src/xlog/install-sh
new file mode 100755 (executable)
index 0000000..ebc6691
--- /dev/null
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libs/src/xlog/slog.c b/libs/src/xlog/slog.c
new file mode 100644 (file)
index 0000000..7aefa42
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#ifndef NO_SYSLOG
+#include <syslog.h>
+#endif
+
+#include "xlog.h"
+#include "impl.h"
+#include "slog.h"
+#include "str.h"
+#include <stdarg.h>
+
+#define MSGBUFSIZE         2048
+
+
+static int syslog_init(xlog_s *, va_list) ;
+static void syslog_fini(xlog_s *) ;
+static int syslog_control(xlog_s *, xlog_cmd_e, va_list ) ;
+static int syslog_write(xlog_s *, const char buf[], int , int , va_list ) ;
+static int syslog_parms(xlog_e, va_list) ;
+
+static struct syslog_parms parms =
+{
+      0,
+#ifndef NO_SYSLOG
+      LOG_PID + LOG_NOWAIT,
+      LOG_USER,
+#else
+      0,
+      0,
+#endif
+      "XLOG",
+} ;
+
+
+struct xlog_ops __xlog_syslog_ops =
+   {
+      syslog_init,
+      syslog_fini,
+      syslog_write,
+      syslog_control,
+      syslog_parms
+   } ;
+
+#ifdef NO_SYSLOG
+
+/*
+ * Notice that the following functions will never be invoked since
+ * the xlog_* functions will not call them. However, we need to define
+ * them so that we don't have any unresolved references; and we define 
+ * them without any arguments.
+ */
+static void syslog()
+{
+}
+
+static void openlog()
+{
+}
+
+static void closelog()
+{
+}
+
+#endif   /* NO_SYSLOG */
+
+
+/*
+ * Expected arguments:
+ *      facility, level
+ */
+static int syslog_init( xlog_s *xp, va_list ap )
+{
+   struct syslog_parms   *slp = &parms ;
+   struct syslog_s                 *sp ;
+
+   sp = NEW( struct syslog_s ) ;
+   if ( sp == NULL )
+      return( XLOG_ENOMEM ) ;
+   sp->sl_facility = va_arg( ap, int ) ;
+   sp->sl_default_level = va_arg( ap, int ) ;
+   if ( slp->slp_n_xlogs++ == 0 )
+      openlog( slp->slp_ident, slp->slp_logopts, slp->slp_facility ) ;
+   xp->xl_data = sp ;
+   return( XLOG_ENOERROR ) ;
+}
+
+
+static void syslog_fini( xlog_s *xp )
+{
+   if ( --parms.slp_n_xlogs == 0 )
+      closelog() ;
+   free( SYSLOG( xp ) ) ;
+   xp->xl_data = NULL ;
+}
+
+
+static int syslog_control( xlog_s *xp, xlog_cmd_e cmd, va_list ap )
+{
+   switch ( cmd )
+   {
+      case XLOG_LEVEL:
+         SYSLOG( xp )->sl_default_level = va_arg( ap, int ) ;
+         break ;
+
+      case XLOG_FACILITY:
+         SYSLOG( xp )->sl_facility = va_arg( ap, int ) ;
+         break ;
+      
+      case XLOG_PREEXEC:
+         closelog() ;
+         break ;
+
+      case XLOG_POSTEXEC:
+         if ( parms.slp_n_xlogs )
+            openlog( parms.slp_ident, parms.slp_logopts, parms.slp_facility ) ;
+         break ;
+
+      /* These fall through ? */
+      case XLOG_LINK:
+      case XLOG_CALLBACK:
+      case XLOG_GETFLAG:
+      case XLOG_SETFLAG: 
+      case XLOG_SIZECHECK:
+      case XLOG_GETFD:
+      case XLOG_LIMITS:
+         break ;
+   }
+   return( XLOG_ENOERROR ) ;
+}
+
+
+static int syslog_write( xlog_s *xp, const char buf[], int len, int flags, va_list ap )
+{
+   int   level ;
+   int   syslog_arg ;
+   char   prefix[ MSGBUFSIZE ] ;
+   int   prefix_size = sizeof( prefix ) ;
+   int   prefix_len = 0 ;
+   int   cc ;
+   int   percent_m_pos ;
+   int   action_flags = ( flags | xp->xl_flags ) ;
+
+   if ( flags & XLOG_SET_LEVEL )
+      level = va_arg( ap, int ) ;
+   else
+      level = SYSLOG( xp )->sl_default_level ;
+   syslog_arg = SYSLOG( xp )->sl_facility + level ;
+
+   if ( action_flags & XLOG_PRINT_ID )
+   {
+      cc = strx_nprint( &prefix[ prefix_len ], prefix_size, "%s: ",
+                     xp->xl_id ) ;
+      prefix_len += cc ;
+      prefix_size -= cc ;
+   }
+
+   if ( ( action_flags & XLOG_NO_ERRNO ) ||
+                  ( percent_m_pos = __xlog_add_errno( buf, len ) ) == -1 )
+      syslog( syslog_arg, "%.*s%.*s", prefix_len, prefix, len, buf ) ;
+   else
+   {
+      char *ep ;
+      char errno_buf[ 100 ] ;
+      unsigned size = sizeof( errno_buf ) ;
+      
+      ep = __xlog_explain_errno( errno_buf, &size ) ;
+      syslog( syslog_arg, "%.*s%.*s%.*s%.*s",
+            prefix_len, prefix,
+               percent_m_pos, buf,
+                  (int)size, ep,
+                     len - percent_m_pos - 2, buf + percent_m_pos + 2 ) ;
+   }
+   return( XLOG_ENOERROR ) ;
+}
+
+
+static int syslog_parms( xlog_e type, va_list ap )
+{
+   char *id = NULL;
+
+   id = __xlog_new_string( va_arg( ap, char * ) );
+   if ( id == NULL )
+      return( XLOG_ENOMEM ) ;
+   parms.slp_ident = id ;
+   parms.slp_logopts = va_arg( ap, int ) ;
+   parms.slp_facility = va_arg( ap, int ) ;
+   return( XLOG_ENOERROR ) ;
+}
+
diff --git a/libs/src/xlog/slog.h b/libs/src/xlog/slog.h
new file mode 100644 (file)
index 0000000..763badd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+/*
+ * $Id: slog.h,v 1.3 2003/05/31 21:58:58 steveg Exp $
+ */
+#ifndef __SLOG_H
+#define __SLOG_H
+
+struct syslog_s
+{
+       int sl_facility ;
+       int sl_default_level ;
+} ;
+
+
+struct syslog_parms
+{
+   int                 slp_n_xlogs ;           /* # of xlogs using syslog */
+   int                 slp_logopts ;           /* used at openlog */
+   int                 slp_facility ;
+   const char  *slp_ident ;            /* used at openlog */
+   /* bool_int slp_ident_is_malloced ; */
+} ;
+
+#define SYSLOG( xp )         ((struct syslog_s *)xp->xl_data)
+
+#endif
+
diff --git a/libs/src/xlog/util.c b/libs/src/xlog/util.c
new file mode 100644 (file)
index 0000000..2b34e32
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "str.h"
+#include "libportable.h"
+
+/*
+ * Search the given buffer for an occurrence of "%m"
+ */
+int __xlog_add_errno( const char *buf, int len )
+{
+       int i;
+
+       for ( i = 0 ; i < len-1 ; i++ )
+               if ( (buf[i] == '%') && (buf[i+1] == 'm') )
+                       return( i ) ;
+       return( -1 ) ;
+}
+
+/* __xlog_explain_errno:
+ * Description: generates a string to explain the value of errno.
+ * On entry: buf must point to space already allocated by the caller,
+ * and size points to the amount of memory buf is allocated.
+ * On exit: buf contains the NULL terminated string, size now points
+ * to the length of the string, and the return value is buf.
+ */
+char *__xlog_explain_errno( char *buf, unsigned *size )
+{
+   strx_print((int *)size, buf, *size, "%s (errno = %d)", 
+      strerror(errno), errno);
+   return( buf ) ;
+}
+
+
+char *__xlog_new_string( const char *s )
+{
+   if ( s )
+      return strdup( s ) ;
+   else
+      return 0;
+}
+
+
diff --git a/libs/src/xlog/xlog.3 b/libs/src/xlog/xlog.3
new file mode 100644 (file)
index 0000000..c89fb5c
--- /dev/null
@@ -0,0 +1,297 @@
+.\"(c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: xlog.3,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+.TH XLOG 3X "15 June 1993"
+xlog_parms, xlog_create, xlog_destroy, xlog_write, xlog_control -- general purpose logging facility
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include "xlog.h"
+.LP
+.ft B
+xlog_h xlog_create( type, id, flags, ... )
+xlog_e type ;
+char *id ;
+int flags ;
+.LP
+.ft B
+int xlog_parms( type, ... )
+xlog_e type ;
+.LP
+.ft B
+void xlog_destroy( xlog )
+xlog_h xlog ;
+.LP
+.ft B
+void xlog_write( xlog, buf, len, flags, ... )
+xlog_h xlog ;
+char buf[] ;
+int len ;
+int flags ;
+.LP
+.ft B
+int xlog_control( xlog, cmd, ... )
+xlog_h xlog ;
+xlog_cmd_e cmd ;
+.SH DESCRIPTION
+The purpose of this library is to provide a general purpose logging facility
+by providing
+.I xlogs,
+logging objects that may be connected to various existent logging facilities.
+Currently, the only logging facilities supported are
+.I "syslog(3)"
+and logging to files.
+Log entries are timestamped lines which may contain arbitrary information.
+.\" ********************* xlog_create ***********************
+.LP
+.B xlog_create()
+creates a new xlog of the specified
+.I type.
+Possible type values are:
+.RS
+.TP 20
+.SB XLOG_SYSLOG
+Varargs: \fIint facility, int priority\fP.
+The xlog will be connected to 
+.I "syslog(3)." 
+.I facility
+determines the syslog facility to use for logged messages and 
+.I priority
+is the default message priority.
+.TP
+.SB XLOG_FILELOG
+Varargs: \fIchar *pathname, int flags [, int flags]\fP.
+The xlog will be connected to the file identified by
+.I pathname.
+The variable part of the argument list has the same semantics as the
+argument list of the
+.I "open(2)"
+system call.
+.RE
+.LP
+All xlogs have an id, specified by the 
+.I id 
+argument. The
+.I flags
+argument is formed by ORing one or more of the following constants:
+.RS
+.TP 20
+.SB XLOG_NO_ERRNO
+do not replace 
+.I "%m" 
+with an explanation of the current value of errno.
+.TP
+.SB XLOG_NO_SIZECHECK
+.I "(XLOG_FILELOG only)"
+do not perform size checks on the file.
+.TP
+.SB XLOG_PRINT_ID
+precede each log entry with the xlog id
+.TP
+.SB XLOG_PRINT_PID
+precede each log entry with the process id
+(the process id will follow the xlog id)
+.RE
+.LP
+Flags that do not apply to the xlog are ignored.
+The contant
+.SM XLOG_NOFLAGS
+can be used if you don't want to specify any flags.
+.\" ********************* xlog_parms ***********************
+.LP
+.B xlog_parms()
+sets default parameters for the specified xlog
+.I type:
+.RS
+.TP 20
+.SB XLOG_SYSLOG
+3 arguments are expected which correspond one-to-one to the arguments of 
+.I "openlog(3)."
+The defaults, in case this function is not used, are:
+"XLOG", LOG_PID + LOG_NOWAIT, LOG_USER
+.TP
+.SB XLOG_FILELOG
+No action.
+.RE
+.LP
+.B xlog_parms()
+should be invoked before any xlogs of the specified type
+are created.
+.\" ********************* xlog_destroy ***********************
+.LP
+.B xlog_destroy()
+destroys an xlog. The action taken depends on the type of the xlog:
+.RS
+.TP 20
+.SB XLOG_SYSLOG
+if this is the last xlog using syslog, then
+.I "closelog(3)"
+is invoked.
+.TP
+.SB XLOG_FILELOG
+The file is closed.
+.RE
+.\" ********************* xlog_control ***********************
+.LP
+.B xlog_control()
+applies control operations to an xlog. Certain operations are common to
+all xlogs while others are type-specific. The common ones are:
+.RS
+.TP 15
+.SB XLOG_LINK
+Argument list: \fIxlog_h link_to\fP.
+Link the specified xlog to the one provided as argument.
+(if the argument is
+.SM NULL
+any existent link is severed).
+Linking xlogs has the effect that if one finds an error it uses the
+other to report it.
+.TP
+.SB XLOG_CALLBACK
+Argument list: \fIvoid (*callback)(), void *arg\fP.
+This function will be invoked in case of error while writing a log
+entry. It will be given
+3 arguments: the xlog handle, an integer that indicates the type
+of error and the
+.I arg 
+specified in this call. Possible errors include:
+.RS
+.TP 15
+.SB XLOG_ENOMEM
+lack of memory
+.TP
+.SB XLOG_EOPEN
+.I "open(2)"
+failed
+.TP
+.SB XLOG_EFSTAT
+.I "fstat(2)"
+failed
+.TP
+.SB XLOG_ESIZE
+hard limit exceeded
+.RE
+.TP
+.SB XLOG_SETFLAG
+Argument list: \fIint flag, int *value\fP.
+The value of
+.I flag
+(one of those listed before) is set according to
+.I "*value"
+which should be either 0 or 1.
+The old flag value is placed in 
+.I "*value."
+.TP
+.SB XLOG_GETFLAG
+Argument list: \fIint flag, int *value\fP.
+The value of 
+.I flag
+(one of those listed before) is placed in
+.I "*value."
+.RE
+.LP
+Xlogs of type
+.B XLOG_SYSLOG
+also support the following operations:
+.RS
+.TP 15
+.SB XLOG_FACILITY
+Argument list: \fIint facility\fP.
+Sets the syslog facility to the specified value.
+.TP
+.SB XLOG_LEVEL
+Argument list: \fIint level\fP.
+Sets the default syslog level for this xlog to the specified value.
+.TP
+.SB XLOG_PREEXEC
+Argument list: \fIvoid\fP.
+Prepares the xlog for an impending exec operation
+.TP
+.SB XLOG_POSTEXEC
+Argument list: \fIvoid\fP.
+Informs the xlog that the exec failed
+.RE
+.LP
+Xlogs of type
+.B XLOG_FILELOG
+also support the following operations:
+.RS
+.TP 15
+.SB XLOG_LIMITS
+Argument list: \fIunsigned soft_limit, unsigned hard_limit\fP.
+Sets soft and hard limits on the size of the file.
+When any of the limits is exceeded a message is sent to the linked xlog.
+(if there is no linked xlog, no message is sent)
+When the soft limit is exceeded a warning message is sent to the linked xlog
+(if the linked xlog is of the
+.SB XLOG_SYSLOG
+type, the message will be sent at the
+.I LOG_ALERT
+level).
+If the exceeded limit is the hard limit, logging is terminated.
+The actual file size is checked every time this operation is applied to
+the file.
+If logging was terminated because the hard limit was exceeded and
+this operation increases the hard limit beyond the actual file size,
+logging will be resumed.
+.TP
+.SB XLOG_SIZECHECK
+Argument list: \fIvoid\fP.
+Checks the actual file size.
+.TP
+.SB XLOG_GETFD
+Argument list: \fIint *value\fP.
+Places in
+.I "*value"
+the file descriptor of the log file.
+.RE
+.\" ********************* xlog_write ***********************
+.LP
+.B xlog_write()
+writes a message to the specified xlog. A
+.SM NEWLINE
+is always appended to the message.
+The first occurrence of "%m" in
+.I buf
+is replaced by a string explaining the current value of
+.I errno.
+The
+.I flags
+argument is formed in the same way as in 
+.B xlog_create().
+One additional constant is available:
+.RS
+.TP 20
+.SB XLOG_SET_LEVEL
+.I "(XLOG_SYSLOG only)"
+the next argument is an integer that should be used as the syslog level
+for this message instead of the default level of the xlog.
+.RE
+.SH "RETURN VALUES"
+.B xlog_create()
+returns an xlog handle or
+.SM NULL
+if it fails.
+.LP
+.B xlog_control()
+returns an error code (it returns
+.SM XLOG_ENOERROR
+if it is successful).
+.LP
+.B xlog_parms()
+returns an error code (it returns
+.SM XLOG_ENOERROR
+if it is successful).
+.SH "SEE ALSO"
+openlog(3), syslog(3), closelog(3)
+.SH BUGS
+.LP
+Only the first occurrence of
+.I "%m"
+is replaced by an errno explanation.
+.LP
+There is no check for cycles when linking xlogs. In particular it is
+possible to link a xlog to itself.
diff --git a/libs/src/xlog/xlog.c b/libs/src/xlog/xlog.c
new file mode 100644 (file)
index 0000000..f0c992f
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "xlog.h"
+#include "impl.h"
+
+extern struct xlog_ops __xlog_filelog_ops ;
+#ifndef NO_SYSLOG
+extern struct xlog_ops __xlog_syslog_ops ;
+#endif
+
+struct lookup_table
+{
+       struct xlog_ops *ops ;
+       xlog_e          type ;
+} ;
+
+static struct lookup_table ops_lookup_table[] =
+{
+       { &__xlog_filelog_ops,  XLOG_FILELOG },
+#ifndef NO_SYSLOG
+       { &__xlog_syslog_ops,   XLOG_SYSLOG },
+#endif
+       { NULL,                 0           }
+} ;
+
+
+#define CALLBACK( xp, status )                                 \
+       if ( (xp)->xl_callback )                        \
+               (*(xp)->xl_callback)( (xlog_h)(xp), status, (xp)->xl_callback_arg )
+
+
+static void xlog_link( xlog_s *client, xlog_s *server ) ;
+static void xlog_unlink( xlog_s *xp ) ;
+
+
+static struct xlog_ops *xlog_ops_lookup( xlog_e type )
+{
+       struct lookup_table *ltp ;
+
+       for ( ltp = &ops_lookup_table[ 0 ] ; ltp->ops ; ltp++ )
+               if ( ltp->type == type )
+                       break ;
+       return( ltp->ops ) ;
+}
+
+
+/* VARARGS3 */
+xlog_h xlog_create( xlog_e type, const char *id, int flags, ... )
+{
+       xlog_s                          *xp ;
+       va_list                         ap ;
+       struct xlog_ops *xops ;
+       int                             status ;
+
+       if ( ( xp = NEW( xlog_s ) ) == NULL )
+               return( NULL ) ;
+       
+       if ( id == NULL || ( xp->xl_id = __xlog_new_string( id ) ) == NULL )
+       {
+               free( xp ) ;
+               return( NULL ) ;
+       }
+
+       xops = xlog_ops_lookup( type ) ;
+       
+       if ( xops != NULL )
+       {
+               va_start( ap, flags ) ;
+               xp->xl_ops = xops ;
+               status = XL_INIT( xp, ap ) ;
+               va_end( ap ) ;
+
+               if ( status == XLOG_ENOERROR )
+               {
+                       xp->xl_flags = flags ;
+                       xp->xl_type = type ;
+                       xp->xl_clients = XLOG_NULL ;
+                       xp->xl_use = XLOG_NULL ;
+                       return( (xlog_h) xp ) ;
+               }
+       }
+
+       free( xp->xl_id ) ;
+       free( xp ) ;
+       return( NULL ) ;
+}
+
+
+
+static void xlog_link( xlog_s *client, xlog_s *server )
+{
+       client->xl_use = server ;
+       if ( server == NULL )
+               return ;
+
+       if ( server->xl_clients == XLOG_NULL )
+       {
+               INIT_LINKS( client, xl_other_users ) ;
+               server->xl_clients = client ;
+       }
+       else
+               LINK( server, client, xl_other_users ) ;
+}
+
+
+static void xlog_unlink( xlog_s *xp )
+{
+       xlog_s *server = xp->xl_use ;
+
+       /*
+        * Step 1: remove from server chain
+        */
+       if ( server != XLOG_NULL )
+       {
+               if ( server->xl_clients == xp )
+                       if ( NEXT( xp, xl_other_users ) == xp )
+                               server->xl_clients = XLOG_NULL ;
+                       else
+                               server->xl_clients = NEXT( xp, xl_other_users ) ;
+               else
+                       UNLINK( xp, xl_other_users ) ;
+       }
+
+       /*
+        * Step 2: If we have users, clear their link to us.
+        */
+       if ( xp->xl_clients != NULL )
+       {
+               xlog_s *xp2 = xp->xl_clients ;
+
+               do
+               {
+                       xp2->xl_use = XLOG_NULL ;
+                       xp2 = NEXT( xp2, xl_other_users ) ;
+               }
+               while ( xp2 != xp->xl_clients ) ;
+       }
+}
+
+
+static void xlog_flags( xlog_s *xp, xlog_cmd_e cmd, ... )
+{
+       va_list ap;
+       int     flag;
+       int     old_value;
+       int     *valp;
+
+       va_start(ap, cmd);
+       flag = va_arg( ap, int );
+       old_value = ((xp->xl_flags & flag) != 0);
+       valp = va_arg( ap, int * );
+       va_end(ap);
+       if ( cmd == XLOG_SETFLAG ) {
+               if ( *valp )
+                       xp->xl_flags |= flag ;
+               else
+                       xp->xl_flags &= ~flag ;
+       }
+       *valp = old_value ;
+}
+
+
+void xlog_destroy( xlog_h pxlog )
+{
+       xlog_s *xp = XP( pxlog ) ;
+
+       xlog_unlink( xp ) ;
+       XL_FINI( xp ) ;
+       free( xp->xl_id ) ;
+       free( xp ) ;
+}
+
+
+/* VARARGS4 */
+void xlog_write( xlog_h pxlog, const char buf[], int len, int flags, ... )
+{
+       xlog_s  *xp = XP( pxlog ) ;
+       va_list ap ;
+       int             status ;
+
+       va_start( ap, flags ) ;
+       status = XL_WRITE( xp, buf, len, flags, ap ) ;
+       va_end( ap ) ;
+
+       if ( status != XLOG_ENOERROR )
+       {
+               CALLBACK( xp, status ) ;
+       }
+}
+
+
+/* VARARGS2 */
+int xlog_control( xlog_h pxlog, xlog_cmd_e cmd, ... )
+{
+       va_list ap ;
+       xlog_s  *xp             = XP( pxlog ) ;
+       int             status  = XLOG_ENOERROR ;
+
+       va_start( ap, cmd ) ;
+
+       switch ( cmd )
+       {
+               case XLOG_LINK:
+                       xlog_unlink( xp ) ;
+                       xlog_link( xp, va_arg( ap, xlog_s * ) ) ;
+                       xp->xl_callback_arg = va_arg( ap, void * ) ;
+                       break ;
+               
+               case XLOG_CALLBACK:
+                       xp->xl_callback = va_arg( ap, voidfunc ) ;
+                       break ;
+                       
+               case XLOG_GETFLAG:
+               case XLOG_SETFLAG:
+                       xlog_flags( xp, cmd, ap ) ;
+                       break ;
+
+               default:
+                       status = XL_CONTROL( xp, cmd, ap ) ;
+       }
+
+       va_end( ap ) ;
+
+       return( status ) ;
+}
+
+
+int xlog_parms( xlog_e type, ... )
+{
+       va_list ap ;
+       int             status ;
+
+       va_start( ap, type ) ;
+       switch ( type )
+       {
+#ifndef NO_SYSLOG
+               case XLOG_SYSLOG:
+                       status = (*__xlog_syslog_ops.parms)( type, ap ) ;
+                       break ;
+#endif
+               case XLOG_FILELOG:
+                       status = (*__xlog_filelog_ops.parms)( type, ap ) ;
+                       break ;
+               
+               default:
+                       status = XLOG_ENOERROR ;
+       }
+       va_end( ap ) ;
+       return( status ) ;
+}
+
diff --git a/libs/src/xlog/xlog.h b/libs/src/xlog/xlog.h
new file mode 100644 (file)
index 0000000..14b26d0
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef __XLOG_H
+#define __XLOG_H
+
+/*
+ * $Id: xlog.h,v 1.2 2003/03/09 19:30:08 steveg Exp $
+ */
+
+/*
+ * Flags
+ */
+#define XLOG_NOFLAGS                                   0x0
+#define XLOG_SET_LEVEL                         0x1
+#define XLOG_NO_SIZECHECK                      0x2
+#define XLOG_NO_ERRNO                          0x4
+/* #define XLOG_PRINT_TIMESTAMP                0x8 */
+#define XLOG_PRINT_ID                          0x10
+#define XLOG_PRINT_PID                         0x20
+
+/*
+ * Errors
+ */
+#define XLOG_ENOERROR                          0
+#define XLOG_ESIZE                                     1
+#define XLOG_EOPEN                                     2
+#define XLOG_EFSTAT                                    3
+#define XLOG_ENOMEM                                    4
+#define XLOG_EWRITE                                    5
+
+/*
+ * Interface
+ */
+
+typedef enum { XLOG_SYSLOG, XLOG_FILELOG } xlog_e ;
+
+typedef enum
+       {
+               XLOG_LINK,                              /* generic: link this log to another log                        */
+               XLOG_CALLBACK,                  /* generic: call this function in case of error */
+               XLOG_GETFLAG,                   /* generic:     get value of specified flag                     */
+               XLOG_SETFLAG,                   /* generic:     set value of specified flag                     */
+               XLOG_LEVEL,                             /* syslog:  set the default syslog level                        */
+               XLOG_FACILITY,                  /* syslog:  set the default syslog facility             */
+               XLOG_PREEXEC,                   /* syslog:      prepare the log for an exec(2)          */
+               XLOG_POSTEXEC,                  /* syslog:      exec(2) failed                                                          */
+               XLOG_SIZECHECK,         /* filelog: check file size                                                     */
+               XLOG_GETFD,                             /* filelog: get file descriptor of log file             */
+               XLOG_LIMITS                     /* filelog: set (new) soft/hard limits                          */
+       } xlog_cmd_e ;
+
+typedef void *xlog_h ;
+
+xlog_h xlog_create     ( xlog_e type, const char *id, int flags, ... ) ;
+void xlog_destroy              ( xlog_h ) ;
+void xlog_write                ( xlog_h, const char *buf, int len, int flags, ... ) ;
+int xlog_control               ( xlog_h, xlog_cmd_e, ... ) ;
+int xlog_parms                 ( xlog_e type, ... ) ;
+
+#endif /* __XLOG_H */
diff --git a/xinetd.spec b/xinetd.spec
new file mode 100644 (file)
index 0000000..19ed13f
--- /dev/null
@@ -0,0 +1,88 @@
+
+Summary:       xinetd -- A better inetd.
+Name:          xinetd
+Version:       2.3.14
+Release:       1
+License:       BSD
+Vendor:                xinetd.org (Rob Braun)
+Group:         System Environment/Daemons
+Packager:      Steve Grubb <linux_4ever@yahoo.com>
+URL:           http://www.xinetd.org/
+Source:                %{name}-%{version}.tar.gz
+BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+Provides:      inetd
+Prereq:                /sbin/chkconfig, /sbin/service 
+BuildRequires:  tcp_wrappers >= 7.6
+Obsoletes:     inetd
+
+%description
+Xinetd is a powerful inetd replacement. Xinetd has access control 
+mechanisms, extensive logging capabilities, the ability to make 
+services available based on time, can place limits on the number 
+of servers that can be started, and has a configurable defence 
+mechanism to protect against port scanners, among other things.
+%prep
+%setup -q
+
+%build
+  ./configure                          \
+       --sbindir=%{_sbindir}           \
+       --mandir=%{_datadir}/man        \
+       --with-libwrap                  \
+       --with-inet6
+  make
+  strip xinetd/xinetd
+  cp xinetd/xinetd xinetd6
+  make distclean
+  ./configure \
+       --sbindir=$RPM_BUILD_ROOT/%{_sbindir}           \
+       --mandir=$RPM_BUILD_ROOT/%{_datadir}/man        \
+       --with-libwrap 
+  make
+  strip xinetd/xinetd
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
+
+%makeinstall  
+install -m 0755 xinetd6 $RPM_BUILD_ROOT/%{_sbindir}
+install -m 0755 contrib/xinetd $RPM_BUILD_ROOT/etc/rc.d/init.d/xinetd
+install -m 0600 contrib/xinetd.conf $RPM_BUILD_ROOT/etc/
+cp contrib/xinetd.d/* $RPM_BUILD_ROOT/etc/xinetd.d
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if [ $1 = 1 ]; then
+   /sbin/chkconfig --add xinetd
+fi
+
+%preun
+if [ $1 = 0 ]; then
+   /sbin/service xinetd stop > /dev/null 2>&1
+   /sbin/chkconfig --del xinetd
+fi
+
+%postun
+if [ $1 -ge 1 ]; then
+   /sbin/service xinetd condrestart > /dev/null 2>&1
+fi
+
+%files
+%defattr(-, root, root)
+%doc CHANGELOG COPYRIGHT README xinetd/sample.conf contrib/empty.conf 
+%{_sbindir}/*
+%{_datadir}/man/*/*
+%attr(0750, root, root) %config(noreplace) /etc/rc.d/init.d/xinetd
+%attr(0750, root, root) %config(noreplace) /etc/xinetd.conf
+%attr(0750, root, root) %config(noreplace) /etc/xinetd.d/*
+
+%changelog
+* Sun Sep 07 2003 Steve Grubb <linux_4ever@yahoo.com>
+- Refined installation and added services.
diff --git a/xinetd.spec.in b/xinetd.spec.in
new file mode 100644 (file)
index 0000000..7647877
--- /dev/null
@@ -0,0 +1,88 @@
+
+Summary:       xinetd -- A better inetd.
+Name:           @PACKAGE@
+Version:        @VERSION@
+Release:       1
+License:       BSD
+Vendor:                xinetd.org (Rob Braun)
+Group:         System Environment/Daemons
+Packager:      Steve Grubb <linux_4ever@yahoo.com>
+URL:           http://www.xinetd.org/
+Source:                %{name}-%{version}.tar.gz
+BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+Provides:      inetd
+Prereq:                /sbin/chkconfig, /sbin/service 
+BuildRequires:  tcp_wrappers >= 7.6
+Obsoletes:     inetd
+
+%description
+Xinetd is a powerful inetd replacement. Xinetd has access control 
+mechanisms, extensive logging capabilities, the ability to make 
+services available based on time, can place limits on the number 
+of servers that can be started, and has a configurable defence 
+mechanism to protect against port scanners, among other things.
+%prep
+%setup -q
+
+%build
+  ./configure                          \
+       --sbindir=%{_sbindir}           \
+       --mandir=%{_datadir}/man        \
+       --with-libwrap                  \
+       --with-inet6
+  make
+  strip xinetd/xinetd
+  cp xinetd/xinetd xinetd6
+  make distclean
+  ./configure \
+       --sbindir=$RPM_BUILD_ROOT/%{_sbindir}           \
+       --mandir=$RPM_BUILD_ROOT/%{_datadir}/man        \
+       --with-libwrap 
+  make
+  strip xinetd/xinetd
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
+
+%makeinstall  
+install -m 0755 xinetd6 $RPM_BUILD_ROOT/%{_sbindir}
+install -m 0755 contrib/xinetd $RPM_BUILD_ROOT/etc/rc.d/init.d/xinetd
+install -m 0600 contrib/xinetd.conf $RPM_BUILD_ROOT/etc/
+cp contrib/xinetd.d/* $RPM_BUILD_ROOT/etc/xinetd.d
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if [ $1 = 1 ]; then
+   /sbin/chkconfig --add xinetd
+fi
+
+%preun
+if [ $1 = 0 ]; then
+   /sbin/service xinetd stop > /dev/null 2>&1
+   /sbin/chkconfig --del xinetd
+fi
+
+%postun
+if [ $1 -ge 1 ]; then
+   /sbin/service xinetd condrestart > /dev/null 2>&1
+fi
+
+%files
+%defattr(-, root, root)
+%doc CHANGELOG COPYRIGHT README xinetd/sample.conf contrib/empty.conf 
+%{_sbindir}/*
+%{_datadir}/man/*/*
+%config(noreplace) /etc/rc.d/init.d/xinetd
+%config(noreplace) /etc/xinetd.conf
+%config(noreplace) /etc/xinetd.d/*
+
+%changelog
+* Sun Sep 07 2003 Steve Grubb <linux_4ever@yahoo.com>
+- Refined installation and added services.
diff --git a/xinetd/Makefile.in b/xinetd/Makefile.in
new file mode 100644 (file)
index 0000000..f8957cd
--- /dev/null
@@ -0,0 +1,237 @@
+# (c) Copyright 1992 by Panagiotis Tsirigotis
+# All rights reserved.  The file named COPYRIGHT specifies the terms 
+# and conditions for redistribution.
+
+#
+# $Id: Makefile.in,v 1.6 2005/03/30 23:15:28 bbraun Exp $
+#
+# Based on Program makefile template: *Revision: 1.14 *
+#
+
+#
+# Available entries:
+#      $(NAME)         --> create the program (this is the default target)
+#      install         --> install the program (and man page)
+#      uninstall       --> uninstall the program (and man page)
+#      clean                   --> cleanup
+#
+
+NAME           = xinetd
+VPATH          = @srcdir@
+SRCDIR         = @srcdir@
+TOPSRC         = @top_srcdir@
+
+# Available debug flags:
+#     DEBUG                      code is being debugged
+#     DEBUG_SERVER               forked server will do a sleep
+#     DEBUG_INTERCEPTOR          forked interceptor will do a sleep
+#     DEBUG_SIGNALS              code that handles SIGSEGV and SIGBUS
+#     DEBUG_LOGGING              forked logging server will do a sleep
+#     DEBUG_SHUTDOWN             forked shutdown server will do a sleep
+#     DEBUG_TPCINT               enable debugging code in the tcp interceptor
+#     DEBUG_UDPINT               enable debugging code in the udp interceptor
+#     DEBUG_DAEMON               debug xinetd when not invoked with -d option
+#     DEBUG_RETRY                debug the server retry code
+#
+
+DEFS        = @DEFS@
+
+PREFIX      = @prefix@
+
+INSTALL_CMD = @INSTALL@
+
+LIBS        = -lsio -lmisc -lxlog -lportable -lstr -lpset @LIBS@
+
+INCLUDEDIR  = -I../libs/include
+LIBDIR      = -L../libs/lib
+
+LDFLAGS     = @LDFLAGS@ $(LIBDIR) 
+CFLAGS      = $(INCLUDEDIR) @CFLAGS@ @DEFS@ -Wall
+
+HDRS     = \
+               access.h \
+               addr.h \
+               attr.h \
+               builtins.h \
+               conf.h \
+               xconfig.h \
+               connection.h \
+               defs.h \
+               inet.h \
+               int.h \
+               log.h \
+               mask.h \
+               parse.h \
+               sconst.h \
+               sconf.h \
+               sensor.h \
+               server.h \
+               service.h \
+               state.h \
+               xtimer.h
+
+SRCS     = \
+               access.c addr.c \
+               builtins.c \
+               child.c conf.c confparse.c connection.c \
+               env.c \
+               ident.c init.c int.c intcommon.c internals.c \
+               log.c logctl.c \
+               main.c msg.c \
+               nvlists.c \
+               parse.c parsesup.c parsers.c \
+               reconfig.c retry.c \
+               sconf.c sensor.c server.c service.c \
+               signals.c special.c \
+               tcpint.c time.c \
+               udpint.c util.c redirect.c \
+               xgetloadavg.c includedir.c xtimer.c inet.c xmdns.c
+
+OBJS     = \
+               access.o addr.o \
+               builtins.o \
+               child.o conf.o confparse.o connection.o \
+               env.o \
+               ident.o init.o int.o intcommon.o internals.o \
+               log.o logctl.o \
+               main.o msg.o \
+               nvlists.o \
+               parse.o parsesup.o parsers.o \
+               reconfig.o retry.o \
+               sconf.o sensor.o server.o service.o \
+               signals.o special.o \
+               tcpint.o time.o \
+               udpint.o util.o redirect.o \
+               xgetloadavg.o options.o includedir.o xtimer.o inet.o xmdns.o
+
+XMODE          = -m 700        # mode for executables
+FMODE          = -m 640        # mode for anything but executables
+INSTALL                = @INSTALL@
+
+#
+# The following variables do not need to be changed
+#
+
+
+all: xinetd itox
+
+itox: itox.c
+       $(CC) $(CFLAGS) $(DEBUG) $(SRCDIR)/itox.c -o $@ $(LDFLAGS) $(LIBS)
+
+xinetd: $(OBJS)
+       $(CC) $(CFLAGS) $(DEBUG) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) || rm -f $@
+
+clean:
+       rm -f $(OBJS) $(NAME) core itox
+       rm -f *.swp 
+       rm -f *.?~ 
+
+distclean: clean
+       rm -f Makefile
+
+install: $(NAME)
+       $(INSTALL) $(XMODE) $(NAME) $(INSTALLDIR)
+
+install.man:
+       if test "$(MANPROGDIR)" ; then \
+               $(INSTALL) $(FMODE) $(MANPROGFILE) $(MANPROGDIR)/$(MANPROGPAGE) ;\
+       fi
+       if test "$(MANDATADIR)" ; then \
+               for i in $(MANDATANAMES) ; do \
+                       name=$(NAME).$$i ; \
+                       $(INSTALL) $(FMODE) $$name.man $(MANDATADIR)/$$name.$(MANDATASECTION);\
+               done ;\
+       fi
+
+uninstall:
+       a=`pwd` ; cd $(INSTALLDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(NAME) ; fi
+       a=`pwd` ; cd $(MANPROGDIR) ;\
+       if test $$a != `pwd` ; then rm -f $(MANPROGPAGE) ; fi
+       a=`pwd` ; cd $(MANDATADIR) ;\
+       if test $$a != `pwd` ; then \
+               for i in $(MANDATANAMES) ; do \
+                       rm -f $(NAME).$$i.$(MANDATASECTION) ;\
+               done ;\
+       fi
+
+#
+# Header file dependencies
+#
+$(SRCDIR)/addr.h: defs.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/builtins.h: defs.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/conf.h: service.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/int.h: server.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/parse.h: defs.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/sconf.h: defs.h log.h mask.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/sensor.h: defs.h service.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/server.h: defs.h service.h connection.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/service.h: defs.h sconf.h builtins.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/state.h: mask.h sconf.h conf.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+$(SRCDIR)/connection.h: mask.h service.h
+       @if test -f $@ ; then touch $@ ; else echo $@ is missing ; exit 1 ; fi
+
+#
+# Object file dependencies
+#
+access.o:      access.h addr.h connection.h sensor.h service.h state.h msg.h
+addr.o:        addr.h defs.h msg.h
+builtins.o:    builtins.h xconfig.h defs.h sconf.h server.h msg.h
+child.o:       attr.h xconfig.h sconst.h server.h state.h msg.h $(OPT_HEADER)
+conf.o:        attr.h conf.h xconfig.h defs.h service.h state.h msg.h
+confparse.o:   attr.h xconfig.h conf.h defs.h parse.h sconst.h \
+               sconf.h sensor.h state.h msg.h
+connection.o:  connection.h service.h state.h msg.h
+sconf.o:       addr.h attr.h defs.h sconf.h state.h
+env.o:         attr.h defs.h sconf.h msg.h
+ident.o:       defs.h sconst.h server.h msg.h
+includedir.o:  parse.h msg.h
+inet.o:                parse.h parsesup.h msg.h
+init.o:                defs.h conf.h xconfig.h state.h msg.h $(OPT_HEADER)
+int.o:         xconfig.h connection.h defs.h int.h server.h service.h msg.h
+intcommon.o:   xconfig.h defs.h int.h server.h service.h state.h msg.h
+internals.o:   xconfig.h server.h service.h state.h msg.h
+log.o:         access.h defs.h connection.h sconst.h server.h service.h msg.h
+logctl.o:      xconfig.h defs.h log.h service.h state.h msg.h
+main.o:                service.h state.h msg.h $(OPT_HEADER)
+msg.o:         xconfig.h defs.h state.h $(OPT_HEADER)
+nvlists.o:     defs.h sconf.h
+parse.o:       addr.h attr.h conf.h defs.h parse.h service.h msg.h
+parsers.o:     addr.h xconfig.h defs.h parse.h sconf.h msg.h
+parsesup.o:    defs.h parse.h msg.h
+reconfig.o:    access.h conf.h xconfig.h defs.h server.h service.h state.h \
+               msg.h
+redirect.o:    service.h log.h sconf.h msg.h
+retry.o:       access.h xconfig.h connection.h server.h state.h msg.h
+sensor.o:      addr.h msg.h sconf.h server.h xconfig.h xtimer.h
+server.o:      access.h xconfig.h connection.h server.h state.h msg.h
+service.o:     access.h attr.h xconfig.h connection.h defs.h \
+                       server.h service.h state.h msg.h $(OPT_HEADER)
+signals.o:     xconfig.h defs.h state.h msg.h
+special.o:     builtins.h conf.h xconfig.h connection.h server.h sconst.h \
+               state.h msg.h $(OPT_HEADER)
+tcpint.o:      access.h xconfig.h defs.h int.h msg.h
+time.o:                defs.h msg.h
+udpint.o:      access.h defs.h int.h msg.h
+util.o:                xconfig.h defs.h msg.h
+xtimer.o:      msg.h
diff --git a/xinetd/access.c b/xinetd/access.c
new file mode 100644 (file)
index 0000000..2af9dfe
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <time.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "str.h"
+#include "access.h"
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int deny_severity = LOG_INFO;
+int allow_severity = LOG_INFO;
+#endif
+
+#ifdef HAVE_LOADAVG
+#include "xgetloadavg.h"
+#endif
+
+#include "msg.h"
+#include "addr.h"
+#include "sconf.h"
+#include "log.h"       
+#include "main.h"      /* for ps */
+#include "sconst.h"
+#include "sensor.h"
+#include "state.h"
+#include "timex.h"
+#include "xconfig.h"
+#include "xtimer.h"
+
+#if !defined(NAME_MAX)
+      #ifdef FILENAME_MAX
+      #define NAME_MAX FILENAME_MAX
+      #else
+      #define NAME_MAX 256
+      #endif
+#endif
+
+const struct name_value access_code_names[] =
+{
+   { "address",                  (int) AC_ADDRESS         },
+   { "time",                     (int) AC_TIME            },
+   { "fork",                     (int) AC_FORK            },
+   { "service_limit",            (int) AC_SERVICE_LIMIT   },
+   { "per_source_limit",         (int) AC_PER_SOURCE_LIMIT},
+   { "process_limit",            (int) AC_PROCESS_LIMIT   },
+   { "libwrap",                  (int) AC_LIBWRAP         },
+   { "load",                     (int) AC_LOAD            },
+   { "connections per second",   (int) AC_CPS             },
+   { CHAR_NULL,                  1                        },
+   { "UNKNOWN",                  0                        }
+} ;
+
+
+/* This is called by the flags processor */
+static void cps_service_restart(void)
+{
+   unsigned int i;
+   time_t nowtime;
+   const char *func = "cps_service_restart";
+
+   nowtime = time(NULL);
+   for( i=0; i < pset_count( SERVICES(ps) ); i++ ) {
+      struct service *sp;
+      struct service_config *scp;
+
+      sp = pset_pointer( SERVICES(ps), i);
+
+      if( SVC_STATE(sp) == SVC_DISABLED ) {
+         scp = SVC_CONF( sp );
+         if ( SC_TIME_REENABLE(scp) <= nowtime ) {
+            /* re-enable the service */
+            if( svc_activate(sp) == OK ) {
+               msg(LOG_ERR, func,
+               "Activating service %s", SC_NAME(scp));
+            } else {
+               msg(LOG_ERR, func,
+               "Error activating service %s", 
+               SC_NAME(scp)) ;
+            } /* else */
+         }
+      }
+   } /* for */
+}
+
+
+void cps_service_stop(struct service *sp, const char *reason)
+{
+   struct service_config   *scp = SVC_CONF( sp ) ; 
+   time_t nowtime;
+
+   svc_deactivate( sp );
+   msg(LOG_ERR, "service_stop", 
+       "Deactivating service %s due to %s.  Restarting in %d seconds.", 
+       SC_NAME(scp), reason, (int)SC_TIME_WAIT(scp));
+   nowtime = time(NULL);
+   SC_TIME_REENABLE(scp) = nowtime + SC_TIME_WAIT(scp);
+   xtimer_add(cps_service_restart, SC_TIME_WAIT(scp));
+}
+
+
+/*
+ * Returns OK if the IP address in sinp is acceptable to the access control
+ * lists of the specified service.
+ */
+static status_e remote_address_check(const struct service *sp, 
+                                    const union xsockaddr *sinp)
+{
+   /*
+    * of means only_from, na means no_access
+    */
+   const char *func = "remote_addr_chk";
+   bool_int   of_matched  = FALSE;
+   bool_int   na_matched  = FALSE;
+
+   if (sinp == NULL )
+      return FAILED;
+
+   if ( SC_SENSOR( SVC_CONF(sp) ))
+   {   /* They hit a sensor...return FAILED since this isn't a real service */
+      process_sensor( sp, sinp ) ; 
+      return FAILED ;
+   } 
+   /* They hit a real server...note, this is likely to be a child process. */
+   else if ( check_sensor( sinp ) == FAILED )
+      return FAILED ;
+
+   /*
+    * The addrlist_match function returns an offset+1 to a matching
+    * entry in the supplied list. It is not a true/false answer.
+    */
+   if ( SC_NO_ACCESS( SVC_CONF(sp) ) != NULL )
+      na_matched = addrlist_match( SC_NO_ACCESS( SVC_CONF(sp) ), SA(sinp));
+
+   if ( SC_ONLY_FROM( SVC_CONF(sp) ) != NULL )
+      of_matched = addrlist_match( SC_ONLY_FROM( SVC_CONF(sp) ), SA(sinp));
+
+   /*
+    * Check if the specified address is in both lists
+    */
+   if ( na_matched && of_matched )
+   {
+      /*
+       * If there is a match in both lists, this is an error in the 
+       * service entry and we cannot allow a server to start.
+       * We do not disable the service entry (not our job).
+       */
+      msg( LOG_ERR, func,
+"Service=%s: only_from list and no_access list match equally the address %s",
+            SVC_ID( sp ), 
+            xaddrname( sinp ) ) ;
+      return FAILED ;
+   }
+
+   /* A no_access list was specified and the socket is on it, fail */
+   if ( SC_NO_ACCESS( SVC_CONF(sp) ) != NULL && (na_matched != 0) )
+      return FAILED ;
+
+   /* A only_from list was specified and the socket wasn't on the list, fail */
+   if ( SC_ONLY_FROM( SVC_CONF(sp) ) != NULL && (of_matched == 0) )
+      return FAILED ;
+
+   /* If no lists were specified, the default is to allow starting a server */
+   return OK ;
+}
+
+/*
+ * mp is the mask pointer, t is the check type
+ */
+#define CHECK( mp, t )      ( ( (mp) == NULL ) || M_IS_SET( *(mp), t ) )
+
+/*
+ * Perform the access controls specified by check_mask.
+ * If check_mask is NULL, perform all access controls
+ */
+access_e access_control( struct service *sp, 
+                         const connection_s *cp, 
+                         const mask_t *check_mask )
+{
+   struct service_config   *scp = SVC_CONF( sp ) ;
+#ifdef LIBWRAP
+   const char *func = "access_control";
+#endif
+
+   /* make sure it's not one of the special pseudo services */
+   if( (strncmp(SC_NAME( scp ), INTERCEPT_SERVICE_NAME, sizeof(INTERCEPT_SERVICE_NAME)) == 0) || (strncmp(SC_NAME( scp ), LOG_SERVICE_NAME, sizeof(LOG_SERVICE_NAME)) == 0) ) {
+      return (AC_OK);
+   }
+
+   /* This has to be before the TCP_WRAPPERS stuff to make sure that
+      the sensor gets a chance to see the address */
+   if ( CHECK( check_mask, CF_ADDRESS ) &&
+         remote_address_check( sp, CONN_XADDRESS( cp ) ) == FAILED )
+      return( AC_ADDRESS ) ;
+
+   if( ! SC_NOLIBWRAP( scp ) ) 
+   { /* LIBWRAP code block */
+#ifdef LIBWRAP
+      struct request_info req;
+      char *server = NULL;
+
+      /* get the server name to pass to libwrap */
+      if( SC_NAMEINARGS( scp ) )
+      {
+         if ( SC_SERVER_ARGV(scp) )
+            server = strrchr( SC_SERVER_ARGV(scp)[0], '/' );
+      }
+      else {
+         if( SC_SERVER(scp) == NULL ) {
+            /* probably an internal server, use the service id instead */
+            server = SC_ID(scp);
+            server--;  /* nasty.  we increment it later... */
+         } else {
+            server = strrchr( SC_SERVER(scp), '/' );
+         }
+      }
+
+      /* If this is a redirection or internal , go by the service name,
+       * since the server name will be bogus.
+       */
+      if( (SC_REDIR_ADDR(scp) != NULL) || (SC_IS_INTERNAL(scp) )) {
+         server = SC_NAME(scp);
+         server--; /* nasty but ok. */
+      }
+
+      if( server == NULL )
+      {
+         if ( SC_SERVER_ARGV(scp))
+            server = SC_SERVER_ARGV(scp)[0];
+      }
+      else
+         server++;
+
+      if ( scp->sc_libwrap != NULL )
+      {
+         server = SC_LIBWRAP(scp);
+      }
+
+      if ( server == NULL )
+      {
+         msg(deny_severity, func, 
+            "server param not provided to libwrap refusing connection to %s from %s", 
+            SC_ID(scp), conn_addrstr(cp));
+         return(AC_LIBWRAP);
+      }
+      request_init(&req, RQ_DAEMON, server, RQ_FILE, cp->co_descriptor, 0);
+      fromhost(&req);
+      if (!hosts_access(&req)) {
+         msg(deny_severity, func, 
+            "libwrap refused connection to %s (libwrap=%s) from %s",
+            SC_ID(scp), server, conn_addrstr(cp));
+         return(AC_LIBWRAP);
+      }
+#endif
+   } /* LIBWRAP code block */
+
+   return( AC_OK ) ;
+}
+
+
+/* Do the "light weight" access control here */
+access_e parent_access_control( struct service *sp, const connection_s *cp )
+{
+   struct service_config *scp = SVC_CONF( sp ) ;
+   int n;
+   time_t nowtime;
+
+   /* make sure it's not one of the special pseudo services */
+   if( (strncmp(SC_NAME( scp ), INTERCEPT_SERVICE_NAME, sizeof(INTERCEPT_SERVICE_NAME)) == 0) || (strncmp(SC_NAME( scp ), LOG_SERVICE_NAME, sizeof(LOG_SERVICE_NAME)) == 0) ) 
+      return (AC_OK);
+
+   /* CPS handler */
+   if( SC_TIME_CONN_MAX(scp) != 0 ) {
+      int time_diff;
+      nowtime = time(NULL);
+      time_diff = nowtime - SC_TIME_LIMIT(scp) ;
+
+      if( SC_TIME_CONN(scp) == 0 ) {
+         SC_TIME_CONN(scp)++;
+         SC_TIME_LIMIT(scp) = nowtime;
+      } else if( time_diff < SC_TIME_CONN_MAX(scp) ) {
+         SC_TIME_CONN(scp)++;
+         if( time_diff == 0 ) time_diff = 1;
+         if( SC_TIME_CONN(scp)/time_diff > SC_TIME_CONN_MAX(scp) ) {
+            cps_service_stop(sp, "excessive incoming connections");
+            return(AC_CPS);
+         }
+      } else {
+         SC_TIME_LIMIT(scp) = nowtime;
+         SC_TIME_CONN(scp) = 1;
+      }
+   }
+
+#ifdef HAVE_LOADAVG
+   if ( SC_MAX_LOAD(scp) != 0 ) {
+      if ( xgetloadavg() >= SC_MAX_LOAD(scp) ) {
+         msg(LOG_ERR, "xinetd", 
+            "refused connect from %s due to excessive load", 
+            conn_addrstr(cp));
+         return( AC_LOAD );
+      }
+   }
+#endif
+
+   if ( SC_ACCESS_TIMES( scp ) != NULL && 
+         ! ti_current_time_check( SC_ACCESS_TIMES( scp ) ) )
+      return( AC_TIME ) ;
+
+   if ( SC_INSTANCES( scp ) != UNLIMITED &&
+        SVC_RUNNING_SERVERS( sp ) >= (unsigned)SC_INSTANCES( scp ) )
+      return( AC_SERVICE_LIMIT ) ;
+
+   if( SC_PER_SOURCE(scp) != UNLIMITED ) {
+      if ( CONN_XADDRESS(cp) != NULL ) {
+         unsigned int u ; 
+         n = 0 ;
+         for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ ) {
+            struct server *serp = NULL;
+            connection_s *cop = NULL;
+            serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
+            if ( (SERVER_SERVICE( serp ) == sp) &&
+               ( cop = SERVER_CONNECTION( serp ) ) ) {
+
+               if ( SC_IPV6( scp ) && 
+                IN6_ARE_ADDR_EQUAL( &(cop->co_remote_address.sa_in6.sin6_addr),
+                  &((CONN_XADDRESS(cp))->sa_in6.sin6_addr)) )
+                  n++;
+               if ( SC_IPV4( scp ) && 
+                     (cop->co_remote_address.sa_in.sin_addr.s_addr == 
+                    (CONN_XADDRESS(cp))->sa_in.sin_addr.s_addr) )
+                  n++;
+            }
+         }
+
+         if ( n >= SC_PER_SOURCE(scp) )
+            return( AC_PER_SOURCE_LIMIT ) ;
+      }
+   }
+
+   if ( ps.ros.process_limit ) {
+      unsigned processes_to_create = SC_IS_INTERCEPTED( scp ) ? 2 : 1 ;
+
+      if ( pset_count( SERVERS( ps ) ) + processes_to_create > 
+         ps.ros.process_limit ) {
+         return( AC_PROCESS_LIMIT ) ;
+      }
+   }
+
+   return (AC_OK);
+}
+
diff --git a/xinetd/access.h b/xinetd/access.h
new file mode 100644 (file)
index 0000000..d3a5959
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef ACCESS_H
+#define ACCESS_H
+
+/*
+ * $Id: access.h,v 1.2 2004/01/02 21:07:42 steveg Exp $
+ */
+
+
+#include "util.h"      /* for nv_get_name() */
+#include "defs.h"      /* bool_int */
+#include "connection.h"
+
+
+/*
+ * These flags are used to form a mask for access_control.
+ * The mask determines which checks will be performed.
+ */
+#define CF_ADDRESS            1
+#define CF_TIME               2
+#define CF_SERVICE_LIMIT      3
+
+typedef enum 
+   {
+      AC_OK,               /* ok to start a server                         */
+      AC_FORK,             /* tried to start a server but fork failed      */
+      AC_ADDRESS,          /* we do not accept requests from that address  */
+      AC_TIME,             /* we do not accept requests at this time       */
+      AC_SERVICE_LIMIT,    /* server limit would be exceeded for this      */
+                           /* service                                      */
+      AC_PER_SOURCE_LIMIT, /* server limit would be exceeded for this      */
+                           /* service and source address                   */
+      AC_PROCESS_LIMIT,    /* total process limit would be exceeded        */
+      AC_LIBWRAP,
+      AC_LOAD,
+      AC_CPS
+   } access_e ;
+
+
+#define ACCESS_EXPLAIN( code )   nv_get_name( access_code_names, (int) (code) )
+
+
+extern const struct name_value access_code_names[];
+void cps_service_stop(struct service *sp, const char *reason);
+access_e access_control(struct service *sp,
+       const connection_s *cp,const mask_t *check_mask);
+access_e parent_access_control(struct service *sp,const connection_s *cp);
+
+
+#endif   /* ACCESS_H */
+
diff --git a/xinetd/addr.c b/xinetd/addr.c
new file mode 100644 (file)
index 0000000..cd26be9
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <memory.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <string.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#endif
+#include <netinet/in.h>
+
+#include "sio.h"
+#include "str.h"
+#include "addr.h"
+#include "msg.h"
+#include "util.h"
+#include "xtimer.h"
+#include "libportable.h"
+
+#define OPEN_CURLY_BRACKET      '{'
+#define CLOSED_CURLY_BRACKET    '}'
+#define COMMA                   ','
+#define DOT                     '.'
+
+typedef enum { CANT_PARSE, PARSED, ERROR } result_e ;
+typedef enum {   NUMERIC_ADDR, NET_ADDR, HOST_ADDR } address_e ;
+
+/*
+ * address types denote how the actual numeric address was obtained.
+ * Currently they are only useful for debugging.
+ * Note that NUMERIC_ADDR includes both simple (e.g. 128.138.91.1) and
+ * factorized symbolic addresses (e.g. 128.138.91.{1,2,3}).
+ */
+struct comp_addr
+{
+   address_e       addr_type ;
+   char            name[MAXHOSTNAMELEN+1] ;
+   char            version;   /* v4 vs. v6 addresses/masks */
+   union {
+      struct in6_addr addr6 ;
+      uint32_t        addr ;  /* host byte order */
+   } a;
+   union {
+      struct in6_addr mask6 ;
+      uint32_t        mask ;
+   } m;
+} ;
+
+#define CAP( p )                ( (struct comp_addr *) (p) )
+#define NEW_CAP()               NEW( struct comp_addr )
+#define FREE_CAP( cap )         FREE( cap )
+
+
+/* The addrlist_match function sets the mask for IPv6 addresses.
+ * mask is a pointer to the in6_addr structure, bits is the
+ * number of bits to set in the mask, and len is the length of mask.
+ */
+static void xsetmask(char *mask, unsigned int bits, unsigned int len)
+{
+   int i;
+   int bytes = bits/8;
+   int remain = bits - (bytes * 8);
+   
+   memset(mask, 0, len);
+
+   /* This may be wrong for bigendian... */
+   for(i=0; i < bytes; i++ ) {
+      mask[i] = 0xFF;
+   }
+
+   if( remain > 0 )
+      mask[i] = ( 0xFF << (8-remain) );
+
+   return;
+}
+
+
+/* This is a helper function to make address matching with mask
+ * work ok w/ipv6. The len parameter is in bytes, not bits. 
+ * Returns TRUE if addr1&mask1 == addr2
+ */
+static bool_int xmatch(const char *addr1, const char *mask1, 
+                       const char *addr2, int len)
+{
+   int i;
+
+   for(i=0; i < len; i++ ) {
+      if( (addr1[i] & mask1[i]) != ( addr2[i] & mask1[i] ) ) 
+         return( FALSE );
+   }
+   return TRUE;
+} 
+
+
+/*
+*   This function returns 0 if no match and the offset+1
+*   to list which element in the list matched. The elements
+*   in the addr_list are expected to be comp_addr structs.
+*/
+int addrlist_match( const pset_h addr_list, 
+                    const struct sockaddr *addr )
+{
+   unsigned u, addr_count, length;
+   char hname[NI_MAXHOST] ;
+
+   if ( addr == NULL )
+          return 0;
+
+   length = (addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : 
+          sizeof(struct sockaddr_in6);
+
+   addr_count = pset_count( addr_list );
+   if (addr_count == 0)
+      return 0;
+   
+   hname[0] = 0;
+      
+   for ( u = 0 ; u < addr_count ; u++ ) 
+   {
+      struct comp_addr *cap = CAP( pset_pointer( addr_list, u ) ) ;
+      if ( cap == NULL )
+         continue ;
+      if( (cap->addr_type == HOST_ADDR) ) 
+      {
+         char *tmpname = NULL;
+         if ( hname[0] == 0 ) 
+        {
+            memset(hname, 0, NI_MAXHOST);
+            if ( getnameinfo(addr, length, hname, NI_MAXHOST, 
+                NULL, 0, NI_NAMEREQD) )
+            {  /* 
+               * Name cannot be looked up if here. We should continue 
+               * searching the list in case a IP address or net mask agrees 
+               */
+                hname[0] = 0;
+                continue ;
+            }
+        }
+
+         /* Parse the address as a domain portion */
+         if( cap->name[0] == '.' )
+         {
+            tmpname = str_casefind( hname, cap->name );
+            if( tmpname != NULL ) 
+           {
+               if( strlen(cap->name) == strlen(tmpname) )
+                  return( u+1 );
+            }
+         } 
+        else 
+        {
+            if( (strlen(hname) == strlen(cap->name)) && 
+               (str_casefind( hname, cap->name ) == (char *)hname) )
+               return( u+1 );
+         }
+      } /* End HOST_ADDR */ 
+      else 
+      { /* NUMERIC or NET addresses */ 
+         if( (addr->sa_family == AF_INET) && (cap->version == 4) ) 
+        {
+            const struct sockaddr_in *inp = SAIN(addr);
+            if( ( ntohl(inp->sin_addr.s_addr) & cap->m.mask ) == 
+                           ( cap->a.addr & cap->m.mask ) ) 
+               return (u+1) ;
+         } 
+        else if( (addr->sa_family == AF_INET6) && (cap->version == 6)) 
+        {
+            if (cap->addr_type == NUMERIC_ADDR) {
+              if (IN6_ARE_ADDR_EQUAL(&SAIN6(addr)->sin6_addr, &cap->a.addr6))
+                  return( u+1 );
+            }
+            else {  /* NET_ADDR */ 
+               if ( xmatch( (const char *)SAIN6(addr)->sin6_addr.s6_addr, 
+                       (const char *)&(cap->m.mask6), 
+                       (const char *)&(cap->a.addr6), 16) == TRUE )
+                  return( u+1 );
+            }
+         } 
+        else if (((addr->sa_family) == AF_INET6) && (cap->version == 4))
+        {  /* 
+            * If it's a mapped address, and a v4 address is specified, see
+             * if the mapped address matches the v4 equivalent.
+             */
+            if( IN6_IS_ADDR_V4MAPPED( &SAIN6(addr)->sin6_addr ) ) 
+           {
+               uint32_t *tmp_addr = 
+                          (uint32_t *)&SAIN6(addr)->sin6_addr.s6_addr[12];
+               if( (ntohl(*tmp_addr) & cap->m.mask)
+                              == ( cap->a.addr & cap->m.mask ) )
+                  return (u+1);
+            }
+         }
+      } /* End NUMERIC or NET address check */
+   } /* End for loop */
+   return ( 0 );
+}
+
+
+void addrlist_dump( const pset_h addr_list, int fd )
+{
+   unsigned u, num ;
+   char addrstring[1025];
+   char maskstring[1025];
+
+   num = pset_count( addr_list );
+   for ( u = 0 ; u < num ; u++ )
+   {
+      struct comp_addr *cap = CAP( pset_pointer( addr_list, u ) ) ;
+      const char *type ;
+
+      if ( cap->addr_type == NUMERIC_ADDR )
+         type = "NUMERIC" ;
+      else if ( cap->addr_type == NET_ADDR )
+         type = "NET" ;
+      else if ( cap->addr_type == HOST_ADDR )
+         type = "HOST" ;
+      else
+         type = "BAD" ;
+      
+      memset(addrstring, 0, sizeof(addrstring));
+      memset(maskstring, 0, sizeof(maskstring));
+      if( cap->version == 4 ) {
+         uint32_t addr = htonl(cap->a.addr);
+         uint32_t mask = htonl(cap->m.mask);
+         inet_ntop(AF_INET, &addr, addrstring, sizeof(addrstring));
+         inet_ntop(AF_INET, &mask, maskstring, sizeof(maskstring));
+      }
+      else if( cap->version == 6 ) {
+         inet_ntop(AF_INET6, &cap->a.addr6, addrstring, sizeof(addrstring));
+         inet_ntop(AF_INET6, &cap->m.mask6, maskstring, sizeof(maskstring));
+      }
+
+      if ( cap->addr_type == NET_ADDR )
+         Sprint(fd, " %s/%s(%s)", addrstring, maskstring, type);
+      else if ( cap->addr_type == HOST_ADDR )
+         Sprint( fd, " %s(%s)",  cap->name, type ) ;
+      else
+         Sprint( fd, " %s(%s)", addrstring, type ) ;
+   }
+}
+
+
+void addrlist_free( pset_h addr_list )
+{
+   pset_apply( addr_list, free, NULL ) ;
+}
+
+
+/*
+ * Verify's an address has more than numbers & dots. 
+ * Returns 0 if numbers & dots, 1 otherwise.
+ */
+int check_hostname( const char *addr )
+{
+   int i;
+
+   for (i = 0; addr[i]; ++i)
+   {
+      if ( !isdigit(addr[i]) && (addr[i] != '.') )
+         return 1;
+   }
+   return 0;
+}
+
+
+/*
+ * Add an address to the address list
+ */
+static status_e add( pset_h addr_list, const struct comp_addr *cap )
+{
+   struct comp_addr *new_cap = NULL;
+   const char *func = "add" ;
+
+   new_cap = NEW_CAP() ;
+   if ( new_cap == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+
+   *new_cap = *cap ;
+   if ( pset_add( addr_list, new_cap ) == NULL )
+   {
+      out_of_memory( func ) ;
+      FREE_CAP( new_cap ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+/*
+ * Find the address and remove it from the list
+ * Since there is no check when we add entries that an
+ * address is not entered twice, in this function we remove all
+ * addresses that match.
+ *
+ * XXX: we need to work on the way two cap's are considered equal
+ */
+static status_e xremove( pset_h addr_list, const struct comp_addr *cap )
+{
+   unsigned u = 0 ;
+   struct comp_addr *old_cap ;
+
+   for ( u = 0 ; u < pset_count( addr_list ) ; u++ )
+   {
+      old_cap = CAP( pset_pointer( addr_list, u ) ) ;
+
+      if ( (cap->addr_type == HOST_ADDR) && ( old_cap->addr_type == HOST_ADDR ))
+      {
+         if ( EQ(cap->name, old_cap->name) )
+        {
+            pset_pointer( addr_list, u ) = NULL ;
+            FREE_CAP( old_cap ) ;
+        }
+      }
+      /* If the versions are the same, and the v6 addresses are the same,
+       * or the v4 addresses are the same, then one's a dup. 
+       */
+      else if ( (old_cap->version == cap->version) && 
+       (((old_cap->version == 6) && 
+         (IN6_ARE_ADDR_EQUAL( &(old_cap->a.addr6), &(cap->a.addr6))) && 
+         (IN6_ARE_ADDR_EQUAL( &(old_cap->m.mask6), &(cap->m.mask6))) ) ||
+         ((old_cap->version == cap->version) && (old_cap->version == 4) && 
+         old_cap->a.addr == cap->a.addr && old_cap->m.mask == cap->m.mask)) )
+      {
+         pset_pointer( addr_list, u ) = NULL ;
+         FREE_CAP( old_cap ) ;
+      }
+   }
+   pset_compact( addr_list ) ;
+   return( OK ) ;
+}
+
+/*
+ * Function allows the use of 0.0.0.0/24 style address ranges for access cntl.
+ *   --bbraun 10/26/98
+ *
+ * Updated to handle ::/46 style address ranges for access cntl.
+ */
+static result_e explicit_mask( const char *str_addr, statfunc op, 
+                               pset_h addr_list)
+{
+   struct comp_addr         ca ;
+   int val;
+   unsigned mask;
+   struct addrinfo hints, *res;
+   char saddr[INET6_ADDRSTRLEN];
+
+   memset(saddr, 0, INET6_ADDRSTRLEN);
+
+   if (strchr(str_addr, OPEN_CURLY_BRACKET))  /* Don't even try factorized */
+      return CANT_PARSE ;
+
+   if (sizeof(saddr) < 46)
+      return CANT_PARSE ;
+   val = sscanf(str_addr, "%45[^/]/%u", saddr, &mask);
+   if( val < 2 ) 
+      return CANT_PARSE ;
+
+   memset(&hints, 0, sizeof(hints));
+   hints.ai_family = PF_UNSPEC;
+   hints.ai_flags = AI_NUMERICHOST;
+   if( getaddrinfo(saddr, NULL, &hints, &res) ) {
+      return CANT_PARSE;
+   }
+
+   if( res->ai_family == AF_INET ) {
+      ca.version = 4;
+      ca.a.addr = ntohl( SAIN(res->ai_addr)->sin_addr.s_addr );
+      if(mask == 32) {
+         ca.addr_type = NUMERIC_ADDR;
+         ca.m.mask      = 0xFFFFFFFF;
+      } else {
+         uint32_t i;
+         unsigned n;
+   
+         ca.addr_type = NET_ADDR ;
+      
+         i = 0x80000000U;
+         ca.m.mask = 0;
+         /* Go through and set each bit to 1 */
+         for( n=mask; n != 0 ; n--)
+         {
+            ca.m.mask |= i;
+            i /= 2;
+         }
+      }
+   } /* PF_INET */
+
+   else if( res->ai_family == AF_INET6 ) {
+      ca.version = 6;
+      if( mask >= 128 ) {
+         ca.addr_type = HOST_ADDR;
+      } else {
+         ca.addr_type = NET_ADDR;
+      }
+      memcpy( &ca.a.addr6, &(SAIN6(res->ai_addr)->sin6_addr), 
+           sizeof(struct in6_addr) );
+      xsetmask((char *)&ca.m.mask6, mask, sizeof(ca.m.mask6));
+   } /* PF_INET6 */
+
+   freeaddrinfo(res);
+
+   return( ( (*op)( addr_list, &ca ) == OK ) ? PARSED : ERROR ) ;
+}
+
+/*
+ * Try to parse 'str_addr' as a symbolic net name
+ * 
+ * NOTE: This doesn't work with IPv6 addresses.
+ */
+static result_e net_addr( const char *str_addr, statfunc op, pset_h addr_list )
+{
+   /*
+    *
+    *  The following table demonstrates how the mask is determined
+    *  given a net number N and following the relation:
+    *     net #1 <= N <= #2
+    *
+    *     net #1      net #2      mask
+    *        0           0        FFFFFFFF    (this should be rejected)
+    *        1           FF       FF000000
+    *        100         FFFF     FFFF0000
+    *        10000       FFFFFF   FFFFFF00
+    *        1000000     FFFFFFFF FFFFFFFF
+    */
+   static struct { uint32_t lim, mask, shift ; } net_to_mask[] =
+   {
+      { 0,            0xFF000000,   24  },
+      { 0xFF,         0xFFFF0000,   16  },
+      { 0xFFFF,       0xFFFFFF00,   8   },
+      { 0xFFFFFF,     0xFFFFFFFF,   0   },
+      { 0xFFFFFFFF,   0,            0   }
+   } ;
+   struct comp_addr         ca ;
+   struct netent            *nep ;
+   uint32_t                 net_num ;
+   int                      i ;
+   const char              *func = "net_addr" ;
+
+   nep = getnetbyname( str_addr ) ;
+   if ( nep == NULL || nep->n_addrtype != AF_INET || nep->n_net == 0 )
+      return( CANT_PARSE ) ;
+
+   for ( i = 0, net_num = (uint32_t) nep->n_net ;; i++ )
+   {
+      if ( net_to_mask[ i ].mask == 0 )
+      {
+         msg( LOG_CRIT, func,
+            "INTERNAL ERROR: Cannot process net number %u", net_num ) ;
+         return( ERROR ) ;
+      }
+      if ( net_to_mask[i].lim < net_num && net_num <= net_to_mask[i+1].lim )
+      {
+         ca.addr_type = NET_ADDR ;
+         ca.a.addr = net_num << net_to_mask[ i ].shift ;
+         ca.m.mask = net_to_mask[ i ].mask ;
+         ca.version = 4;
+         return( ( (*op)( addr_list, &ca ) == OK ) ? PARSED : ERROR ) ;
+      }
+   }
+}
+
+
+/*
+ * Try to parse 'str_addr' as a numeric address
+ */
+static result_e numeric_addr( const char *str_addr, 
+                               status_e (*op)(), 
+                               pset_h addr_list )
+{
+   struct comp_addr ca ;
+   struct addrinfo hints, *res = NULL;
+   struct in6_addr zero;
+   uint32_t mask, addr;
+
+   if (strchr(str_addr, '/')) /* Don't even try explicit masks */
+      return CANT_PARSE;
+   if(strchr(str_addr, OPEN_CURLY_BRACKET))  /* Don't even try factorized */
+      return CANT_PARSE;
+   
+   memset(&zero, 0, sizeof(zero));
+   memset(&hints, 0, sizeof(hints));
+
+   hints.ai_flags = AI_NUMERICHOST;
+   if (strchr(str_addr, ':'))
+      hints.ai_family = PF_INET6;
+   else
+      hints.ai_family = PF_INET;
+
+   if( getaddrinfo(str_addr, NULL, &hints, &res) != 0 ) 
+      return CANT_PARSE;
+
+   if ( res == NULL )
+      return CANT_PARSE;
+
+   if ( res->ai_addr == NULL ) {
+      freeaddrinfo(res);
+      return CANT_PARSE;
+   }
+
+   if( res->ai_family == AF_INET6 ) {
+      ca.version = 6;
+      ca.addr_type = NUMERIC_ADDR;
+      if( memcmp( &(SAIN6(res->ai_addr)->sin6_addr), &zero, 
+           sizeof(struct in6_addr) ) == 0 ) {
+         memset( &ca.a.addr6, 0, sizeof(struct in6_addr) );
+         memset( &ca.m.mask6, 0, sizeof(struct in6_addr) );
+      } else {
+         memcpy( &ca.a.addr6, &(SAIN6(res->ai_addr)->sin6_addr), 
+           sizeof(struct in6_addr) );
+         memset(&ca.m.mask6, 0xFF, sizeof(struct in6_addr));
+      }
+   } else if( res->ai_family == AF_INET ) {
+      ca.version = 4;
+      ca.addr_type = NUMERIC_ADDR;
+      if( SAIN(res->ai_addr)->sin_addr.s_addr == 0 ) {
+         ca.a.addr = 0;
+         ca.m.mask = 0;
+      } else {
+         addr = (uint32_t) ntohl( SAIN(res->ai_addr)->sin_addr.s_addr );
+         for ( mask = 0xFF ;; )
+         {
+            if ( addr & mask )
+               break ;
+            mask <<= 8 ;
+            mask |= 0xFF ;
+         }
+         mask = ~( mask >> 8 ) ;
+
+         ca.a.addr = addr;
+         ca.m.mask = mask;
+      }
+   
+   }
+
+   freeaddrinfo(res);
+   return( ( (*op)( addr_list, &ca ) == OK ) ? PARSED : ERROR ) ;
+}
+
+
+/*
+ * Try to parse 'str_addr' as a symbolic host name
+ * Apply 'op' to the 'addrlist' for *all* IP addresses of the host
+ */
+static result_e host_addr( const char *str_addr, status_e (*op)(), pset_h addr_list )
+{
+   struct comp_addr ca;
+   struct addrinfo hints, *res = NULL;
+   char addr[46];
+
+   if (strchr(str_addr, '/')) /* Don't even try explicit masks */
+      return CANT_PARSE;
+   if(strchr(str_addr, OPEN_CURLY_BRACKET))  /* Don't even try factorized */
+      return CANT_PARSE;
+
+   if( str_addr[0] == '.' ) 
+   {
+      if ( check_hostname(str_addr) )
+      {
+         ca.version = 0xFF;
+         ca.addr_type = HOST_ADDR;
+         /* XXX: does this really need to be NUL-padded? */
+         strncpy(ca.name, str_addr, sizeof(ca.name)-1) ;
+         ca.name[sizeof(ca.name)-1] = '\0';
+         if ( (*op)( addr_list, &ca ) == FAILED )
+            return ERROR ;
+         return PARSED ;
+      }
+      else
+        return CANT_PARSE;
+   }
+
+   memset(&hints, 0, sizeof(hints));
+   memset(addr, 0, sizeof(addr));
+
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_family = PF_UNSPEC;
+
+   if ( getaddrinfo(str_addr, NULL, &hints, &res) != 0 ) 
+      return CANT_PARSE;
+
+   if ( res == NULL )
+      return CANT_PARSE;
+
+   strncpy(ca.name, str_addr, sizeof(ca.name)-1) ;
+   ca.name[sizeof(ca.name)-1] = '\0';
+   ca.addr_type = HOST_ADDR ;
+   ca.version = 0xFF;
+   freeaddrinfo(res);
+
+   if ( (*op)( addr_list, &ca ) == FAILED ) 
+      return ERROR ;
+   else
+      return PARSED ;
+}
+
+
+/*
+ * Try to parse 'str_addr' as a factorized address
+ * (for example, 128.138.{200,201})
+ *
+ * XXX: It is unclear whether this function should exist. It is really doing
+ *      the job of a preprocessor.
+ *
+ * This does not work for IPv6 Addresses.
+ */
+static result_e factorized_addr( const char *str_addr, 
+                                  status_e (*op)(), 
+                                  pset_h addr_list )
+{
+   int                pass ;
+   char               last   = DOT ;
+   unsigned           num   = 0 ;
+   int                shift = 24 ;   /* because we assume a 32-bit IP address */
+   uint32_t           addr = 0 ;
+   struct comp_addr   ca ;
+   const char        *func = "factorized_addr" ;
+   int                i, j;
+
+   for ( i = 0 ; str_addr[i] != OPEN_CURLY_BRACKET ; last = str_addr[i++] )
+   {
+      if ( isdigit( str_addr[i] ) )
+      {
+         num = num * 10 + str_addr[i] - '0' ;
+         continue ;
+      }
+      switch ( str_addr[i] )
+      {
+         case DOT:
+            if ( last == DOT )
+            {
+               parsemsg( LOG_ERR, func,
+                  "Bad address: %s. Consecutive dots", str_addr ) ;
+               return( ERROR ) ;
+            }
+            addr = addr * 256 + num ;
+            num = 0 ;
+            shift -= 8 ;
+            break ;
+         
+         default:
+            return( CANT_PARSE ) ;
+      }
+   }
+
+   ca.addr_type = NUMERIC_ADDR ;
+   ca.version = 4;
+   if ( addr != 0 )
+      addr <<= ( shift+8 ) ;
+
+   /*
+    * First pass is for syntax checking
+    */
+   j = i;
+   for ( pass = 0 ; pass < 2 ; pass++ )
+   {
+      i = j;
+      num = 0 ;
+      for ( i = i+1, last = COMMA ;; last = str_addr[i++] )
+      {
+         if ( isdigit( str_addr[i] ) )
+         {
+            num = num * 10 + str_addr[i] - '0' ;
+            continue ;
+         }
+         switch ( str_addr[i] )
+         {
+            case COMMA:
+            case CLOSED_CURLY_BRACKET:
+               if ( last == COMMA )
+               {
+                  parsemsg( LOG_ERR, func,
+                     "Bad address: %s. Consecutive commas", str_addr ) ;
+                  return( ERROR ) ;
+               }
+
+               if ( pass == 1 )
+               {
+                  ca.a.addr = addr + ( num << shift ) ;
+                  ca.m.mask = ~( ( 1 << shift ) - 1 ) ;
+                  if ( (*op)( addr_list, &ca ) == FAILED )
+                     return( ERROR ) ;
+                  num = 0 ;
+               }
+               break ;
+            
+            default:
+               parsemsg( LOG_ERR, func, "Bad address: %s", str_addr ) ;
+               return( ERROR ) ;
+         }
+         if ( str_addr[i] == CLOSED_CURLY_BRACKET )
+         {
+            if ( str_addr[i+1] != NUL )
+            {
+               parsemsg( LOG_ERR, func, "Bad address: %s", str_addr ) ;
+               return( ERROR ) ;
+            }
+
+            if ( pass == 0 )
+               break ;
+            else
+               return( PARSED ) ;
+         }
+      }
+   }
+   /* NOTREACHED */
+
+   return( ERROR );
+}
+
+
+/*
+ * Try to parse 'str_addr' using all known methods.
+ * Try until one of the methods succeeds.
+ * A successful method will apply 'op' with the parsed address to the 
+ * 'addr_list'. The 'op' can be either 'add' or 'remove'
+ * This means that the parsed address will be either added or removed
+ * from the addr_list.
+ */
+static status_e addrlist_op( pset_h addr_list, 
+                              status_e (*op)(), 
+                              const char *str_addr )
+{
+   int i ;
+   static result_e (*addr_parser[])() =
+      {
+         numeric_addr,
+         host_addr,
+         explicit_mask,
+         factorized_addr,
+         net_addr,
+         NULL
+      } ;
+   const char *func = "addrlist_op" ;
+
+   if (str_addr == NULL)
+      return FAILED;
+   
+   if (str_addr[0] == NUL )
+      return OK;
+   
+   for ( i = 0 ; addr_parser[ i ] != NULL ; i++ )
+      switch ( (*addr_parser[ i ])( str_addr, op, addr_list ) )
+      {
+         case PARSED:
+            return OK;
+         case ERROR:
+            return FAILED;
+         case CANT_PARSE:
+            break;
+      }
+
+   parsemsg( LOG_ERR, func, "failed to parse %s", str_addr ) ;
+   return OK;
+}
+
+
+status_e addrlist_add( pset_h addr_list, const char *str_addr ) 
+{
+   return( addrlist_op( addr_list, add, str_addr ) ) ;
+}
+
+
+status_e addrlist_remove( pset_h addr_list, const char *str_addr ) 
+{
+   return( addrlist_op( addr_list, xremove, str_addr ) ) ;
+}
+
+
+status_e addrlist_copy( const pset_h from, pset_h *to )
+{
+   return( copy_pset( from, to, sizeof( struct comp_addr ) ) ) ;
+}
+
diff --git a/xinetd/addr.h b/xinetd/addr.h
new file mode 100644 (file)
index 0000000..3711212
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef ADDR_H
+#define ADDR_H
+
+/*
+ * $Id: addr.h,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+ */
+
+
+#include "pset.h"
+#include "defs.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+int addrlist_match(const pset_h addr_list, const struct sockaddr *addr);
+void addrlist_dump(const pset_h addr_list, int fd);
+void addrlist_free(pset_h addr_list);
+status_e addrlist_add(pset_h addr_list, const char *str_addr);
+status_e addrlist_remove(pset_h addr_list, const char *str_addr);
+status_e addrlist_copy(const pset_h from, pset_h *to);
+int check_hostname(const char *addr);
+
+#endif   /* ADDR_H */
+
diff --git a/xinetd/attr.h b/xinetd/attr.h
new file mode 100644 (file)
index 0000000..fa2e209
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef ATTR_H
+#define ATTR_H
+
+/*
+ * $Id: attr.h,v 1.3 2005/10/05 17:15:33 bbraun Exp $
+ */
+
+/*
+ * Attribute IDs
+ */
+#define A_NONE              0
+#define A_WAIT              1
+#define A_SOCKET_TYPE       2
+#define A_PROTOCOL          3
+#define A_USER              4
+#define A_GROUP             5
+#define A_SERVER            6
+#define A_SERVER_ARGS       7
+#define A_INSTANCES         8
+#define A_ID                9
+#define A_ONLY_FROM        10
+#define A_ACCESS_TIMES     11
+#define A_RPC_VERSION      12
+#define A_LOG_TYPE         13
+#define A_NO_ACCESS        14
+#define A_TYPE             15
+#define A_LOG_ON_FAILURE   16
+#define A_LOG_ON_SUCCESS   17
+#define A_ENV              18
+#define A_PORT             19
+#define A_PASSENV          20
+#define A_FLAGS            21
+#define A_RPC_NUMBER       22
+#define A_NICE             23
+#define A_REDIR            24
+#define A_BIND             25
+#define A_BANNER           26
+#define A_PER_SOURCE       27
+#define A_GROUPS           28
+#define A_BANNER_SUCCESS   29
+#define A_BANNER_FAIL      30
+#define A_MAX_LOAD         31
+#define A_CPS              32
+#define A_SVCDISABLE       33
+#define A_RLIMIT_AS        34
+#define A_RLIMIT_CPU       35
+#define A_RLIMIT_DATA      36
+#define A_RLIMIT_RSS       37
+#define A_RLIMIT_STACK     38
+#define A_V6ONLY           39
+#define A_DENY_TIME        40
+#define A_UMASK            41
+#define A_ENABLED          42
+#define A_DISABLED         43
+#define A_MDNS             44
+#define A_LIBWRAP          45
+
+/*
+ * SERVICE_ATTRIBUTES is the number of service attributes and also
+ * the number from which defaults-only attributes start.
+ */
+#define SERVICE_ATTRIBUTES      ( A_MDNS + 1 )
+
+/*
+ * Mask of attributes that must be specified.
+ */
+#define NECESSARY_ATTRS         ( XMASK( A_SOCKET_TYPE ) + XMASK( A_WAIT ) )
+#define NECESSARY_ATTRS_EXTERNAL     ( XMASK( A_SERVER ) + XMASK( A_USER ) )
+#define NECESSARY_ATTRS_UNLISTED     ( XMASK( A_PROTOCOL ) + XMASK( A_PORT ) )
+#define NECESSARY_ATTRS_UNLISTED_MUX ( XMASK( A_PROTOCOL ) )
+#define NECESSARY_ATTRS_RPC          ( XMASK( A_PROTOCOL ) + \
+                                       XMASK( A_RPC_VERSION ) )
+#define NECESSARY_ATTRS_RPC_UNLISTED XMASK( A_RPC_NUMBER )
+
+#endif   /* ATTR_H */
diff --git a/xinetd/builtins.c b/xinetd/builtins.c
new file mode 100644 (file)
index 0000000..aac5dfe
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <time.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "str.h"
+#include "pset.h"
+#include "sio.h"
+#include "builtins.h"
+#include "msg.h"
+#include "connection.h"
+#include "server.h"
+#include "service.h"
+#include "sconf.h"
+#include "main.h"
+#include "util.h"
+#include "xconfig.h"
+#include "state.h"
+#include "libportable.h"
+#include "signals.h"
+#include "nvlists.h"
+#include "child.h"
+#include "access.h"
+
+#define BUFFER_SIZE               1024
+
+static void stream_echo(const struct server *) ;
+static void dgram_echo(const struct server *) ;
+static void stream_discard(const struct server *) ;
+static void dgram_discard(const struct server *) ;
+static void stream_time(const struct server *) ;
+static void dgram_time(const struct server *) ;
+static void stream_daytime(const struct server *) ;
+static void dgram_daytime(const struct server *) ;
+static void stream_chargen(const struct server *) ;
+static void dgram_chargen(const struct server *) ;
+static void tcpmux_handler(const struct server *) ;
+
+/*
+ * SG - This is the call sequence to get to a built-in service
+ *
+ *   main_loop                  main.c
+ *    svc_request                  service.c
+ *     svc_handle -- aka svc_handler_func -- aka svc_generic_handler   service.c
+ *      server_run                      server.c
+ *       server_internal               server.c
+ *      SC_INTERNAL               service.h
+ *       BUILTIN_INVOKE               sc_conf.h
+ *        sc_builtin -- index into builtin_services   builtins.c
+ */
+
+static const struct builtin_service builtin_services[] =
+   {
+      { "echo",      SOCK_STREAM,   { stream_echo,     FORK    } },
+      { "echo",      SOCK_DGRAM,    { dgram_echo,      NO_FORK } },
+      { "discard",   SOCK_STREAM,   { stream_discard,  FORK    } },
+      { "discard",   SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
+      { "time",      SOCK_STREAM,   { stream_time,     NO_FORK } },
+      { "time",      SOCK_DGRAM,    { dgram_time,      NO_FORK } },
+      { "daytime",   SOCK_STREAM,   { stream_daytime,  NO_FORK } },
+      { "daytime",   SOCK_DGRAM,    { dgram_daytime,   NO_FORK } },
+      { "chargen",   SOCK_STREAM,   { stream_chargen,  FORK    } },
+      { "chargen",   SOCK_DGRAM,    { dgram_chargen,   NO_FORK } },
+      { "sensor",    SOCK_STREAM,   { stream_discard,  NO_FORK } },
+      { "sensor",    SOCK_DGRAM,    { dgram_discard,   NO_FORK } },
+      { "tcpmux",    SOCK_STREAM,   { tcpmux_handler,  FORK    } },
+      { NULL,        0,             { NULL,            0       } }
+   } ;
+
+
+const builtin_s *builtin_find( const char *service_name, int type )
+{
+   const builtin_s   *bsp ;
+   const char        *func = "builtin_find" ;
+   
+   if ( (bsp = builtin_lookup( builtin_services, service_name, type )) )
+      return( bsp ) ;
+   else
+   {
+       const char *type_name;
+       const struct name_value *sock_type = nv_find_name( socket_types, type );
+       if (sock_type == NULL)
+               type_name = "Unknown socket type";
+       else
+               type_name = sock_type->name;
+       msg( LOG_ERR, func, "No such internal service: %s/%s - DISABLING", 
+                       service_name, type_name ) ;
+       return( NULL ) ;
+   }
+}
+
+
+const builtin_s *builtin_lookup( const struct builtin_service services[], 
+                           const char *service_name, 
+                           int type )
+{
+   const struct builtin_service *bsp ;
+   
+   for ( bsp = services ; bsp->bs_name != NULL ; bsp++ )
+      if ( EQ( bsp->bs_name, service_name ) && bsp->bs_socket_type == type )
+         return( &bsp->bs_handle ) ;
+   return( NULL ) ;
+}
+
+
+/*
+ * The rest of this file contains the functions that implement the 
+ * builtin services
+ */
+
+
+static void stream_echo( const struct server *serp )
+{
+   char   buf[ BUFFER_SIZE ] ;
+   int    cc ;
+   int    descriptor = SERVER_FD( serp ) ;
+   struct service *svc = SERVER_SERVICE( serp ) ;;
+
+   if( SVC_WAITS( svc ) ) {
+      descriptor = accept(descriptor, NULL, NULL);
+      if ( descriptor == -1 ) {
+         if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(svc, "no available descriptors");
+         return;
+      }
+   }
+
+   close_all_svc_descriptors();
+
+   for ( ;; )
+   {
+      cc = read( descriptor, buf, sizeof( buf ) ) ;
+      if ( cc == 0 )
+         break ;
+      if ( cc == -1 ) {
+         if ( errno == EINTR )
+            continue ;
+         else
+            break ;
+      }
+
+      if ( write_buf( descriptor, buf, cc ) == FAILED )
+         break ;
+   }
+   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
+      Sclose(descriptor);
+}
+
+static void dgram_echo( const struct server *serp )
+{
+   char            buf[ DATAGRAM_SIZE ] ;
+   union xsockaddr lsin;
+   int             cc ;
+   socklen_t       sin_len = 0;
+   int             descriptor = SERVER_FD( serp ) ;
+   const char     *func = "dgram_echo";
+
+   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
+      sin_len = sizeof( struct sockaddr_in );
+   else if( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) )
+      sin_len = sizeof( struct sockaddr_in6 );
+
+   cc = recvfrom( descriptor, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) ;
+   if ( cc != -1 ) {
+      (void) sendto( descriptor, buf, cc, 0, SA( &lsin ), sizeof( lsin ) ) ;
+   }
+}
+
+static void stream_discard( const struct server *serp )
+{
+   char  buf[ BUFFER_SIZE ] ;
+   int   cc ;
+   int    descriptor = SERVER_FD( serp ) ;
+   struct service *svc = SERVER_SERVICE( serp ) ;;
+
+   if( SVC_WAITS( svc ) ) {
+      descriptor = accept(descriptor, NULL, NULL);
+      if ( descriptor == -1 ) {
+         if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(svc, "no available descriptors");
+         return;
+      }
+   }
+
+   close_all_svc_descriptors();
+
+   for ( ;; )
+   {
+      cc = read( descriptor, buf, sizeof( buf ) ) ;
+      if ( (cc == 0) || ((cc == -1) && (errno != EINTR)) )
+         break ;
+   }
+   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
+      Sclose(descriptor);
+}
+
+
+static void dgram_discard( const struct server *serp )
+{
+   char buf[ 1 ] ;
+
+   (void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
+}
+
+
+/*
+ * Generate the current time using the SMTP format:
+ *      02 FEB 1991 12:31:42 MST
+ *
+ * The result is placed in buf.
+ * buflen is a value-result parameter. It indicates the size of
+ * buf and on exit it has the length of the string placed in buf.
+ */
+static void daytime_protocol( char *buf, unsigned int *buflen )
+{
+   static const char *month_name[] =
+      {
+         "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
+      } ;
+   time_t      now ;
+   struct tm   *tmp ;
+   int         size = *buflen ;
+#ifdef HAVE_STRFTIME
+   int      cc ;
+#endif
+
+   (void) time( &now ) ;
+   tmp = localtime( &now ) ;
+#ifndef HAVE_STRFTIME
+   strx_print( buflen, buf, size,
+      "%02d %s %d %02d:%02d:%02d %s\r\n",
+         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
+            tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
+#else
+   cc = strx_nprint( buf, size,
+      "%02d %s %d %02d:%02d:%02d",
+         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
+            tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
+   if ( cc >= 0 ) { 
+      *buflen = cc ;
+      size -= cc ;
+      cc = strftime( &buf[ *buflen ], size, " %Z\r\n", tmp ) ;
+      *buflen += cc ;
+   }
+#endif
+}
+
+
+static void stream_daytime( const struct server *serp )
+{
+   char  time_buf[ BUFFER_SIZE ] ;
+   unsigned int buflen = sizeof( time_buf ) ;
+   int    descriptor = SERVER_FD( serp ) ;
+   struct service *svc = SERVER_SERVICE( serp ) ;;
+
+   if( SVC_WAITS( svc ) ) {
+      descriptor = accept(descriptor, NULL, NULL);
+      if ( descriptor == -1 ) {
+         if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(svc, "no available descriptors");
+         return;
+      }
+   }
+   daytime_protocol( time_buf, &buflen ) ;
+   (void) write_buf( descriptor, time_buf, buflen ) ;
+   Sclose(descriptor);
+}
+
+
+static void dgram_daytime( const struct server *serp )
+{
+   char            time_buf[ BUFFER_SIZE ] ;
+   union xsockaddr lsin ;
+   socklen_t       sin_len     = 0 ;
+   unsigned int    buflen      = sizeof( time_buf ) ;
+   int             descriptor  = SERVER_FD( serp ) ;
+   const char     *func       = "dgram_daytime";
+
+   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in );
+   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in6 );
+
+   if ( recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
+            SA( &lsin ), &sin_len ) == -1 )
+      return ;
+
+   daytime_protocol( time_buf, &buflen ) ;
+   
+   (void) sendto( descriptor, time_buf, buflen, 0, SA(&lsin), sizeof( lsin ) ) ;
+}
+
+
+#define TIME_OFFSET         2208988800UL
+
+/*
+ * We always report the time as 32 bits in network-byte-order
+ */
+static void time_protocol( unsigned char *timep )
+{
+   time_t now ;
+   unsigned long base1900;
+
+   (void) time( &now ) ;
+   base1900 = (unsigned long)now + TIME_OFFSET ;
+   timep[0] = base1900 >> 24;
+   timep[1] = base1900 >> 16;
+   timep[2] = base1900 >> 8;
+   timep[3] = base1900;
+
+}
+
+
+static void stream_time( const struct server *serp )
+{
+   unsigned char time_buf[4];
+   int descriptor = SERVER_FD( serp );
+   struct service *svc = SERVER_SERVICE( serp );
+
+   if( SVC_WAITS( svc ) ) {
+      descriptor = accept(descriptor, NULL, NULL);
+      if ( descriptor == -1 ) {
+         if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(svc, "no available descriptors");
+         return;
+      }
+   }
+
+   time_protocol( time_buf ) ;
+   (void) write_buf( descriptor, (char *) time_buf, 4 ) ;
+
+   Sclose(descriptor);
+}
+
+
+static void dgram_time( const struct server *serp )
+{
+   char     buf[ 1 ] ;
+   unsigned char time_buf[4];
+   union xsockaddr lsin ;
+   socklen_t       sin_len = 0 ;
+   int             fd      = SERVER_FD( serp ) ;
+   const char     *func    = "dgram_daytime";
+
+   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in );
+   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in6 );
+
+   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
+      return ;
+
+   time_protocol( time_buf ) ;
+   (void) sendto( fd, (char *) time_buf, 4, 0, SA( &lsin ), sin_len ) ;
+}
+
+
+#define ASCII_PRINTABLE_CHARS     94
+#define LINE_LENGTH               72
+
+#define RING_BUF_SIZE             ASCII_PRINTABLE_CHARS + LINE_LENGTH
+
+static char *ring_buf = NULL ;
+static char *ring ;
+
+
+#define ASCII_START          ( ' ' + 1 )
+#define ASCII_END            126
+
+#define min( a, b )          ((a)<(b) ? (a) : (b))
+
+static char *generate_line( char *buf, unsigned int len )
+{
+   unsigned int line_len = min( LINE_LENGTH, len-2 ) ;
+
+   if ( len < 2 )       /* If len < 2, min will be wrong */
+      return( NULL ) ;
+
+   /* This never gets freed.  That's ok, because the reference to it is
+    * always kept for future reference.
+    */
+   if ( (ring_buf == NULL) && ((ring_buf = malloc(RING_BUF_SIZE)) == NULL) ) 
+      return(NULL);
+
+   if ( ring == NULL )
+   {
+      char ch ;
+      char *p ;
+
+      for ( p = ring_buf, ch = ASCII_START ;
+            p <= &ring_buf[ RING_BUF_SIZE - 1 ] ; p++ )
+      {
+         *p = ch++ ;
+         if ( ch == ASCII_END )
+            ch = ASCII_START ;
+      }
+      ring = ring_buf ;
+   }
+   (void) memcpy( buf, ring, line_len ) ;
+   buf[ line_len   ] = '\r' ;
+   buf[ line_len+1 ] = '\n' ;
+
+   ring++ ;
+   if ( &ring_buf[ RING_BUF_SIZE - 1 ] - ring + 1 < LINE_LENGTH )
+      ring = ring_buf ;
+   return( buf ) ;
+}
+
+
+static void stream_chargen( const struct server *serp )
+{
+   char   line_buf[ LINE_LENGTH+2 ] ;
+   int    descriptor = SERVER_FD( serp ) ;
+   struct service *svc = SERVER_SERVICE( serp );
+
+   if( SVC_WAITS( svc ) ) {
+      descriptor = accept(descriptor, NULL, NULL);
+      if ( descriptor == -1 ) {
+         if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(svc, "no available descriptors");
+         return;
+      }
+   }
+
+   (void) shutdown( descriptor, 0 ) ;
+   close_all_svc_descriptors();
+
+   for ( ;; )
+   {
+      if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
+         break ;
+      if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
+         break ;
+   }
+   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
+      Sclose(descriptor);
+}
+
+
+static void dgram_chargen( const struct server *serp )
+{
+   char            buf[ BUFFER_SIZE ] ;
+   char            *p ;
+   unsigned int    len ;
+   union xsockaddr lsin ;
+   socklen_t       sin_len = 0 ;
+   int             fd      = SERVER_FD( serp ) ;
+   unsigned int    left    = sizeof( buf ) ;
+   const char     *func    = "dgram_chargen";
+
+   if ( SC_IPV4( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in );
+   else if ( SC_IPV6( SVC_CONF( SERVER_SERVICE( serp ) ) ) ) 
+      sin_len = sizeof( struct sockaddr_in6 );
+
+   if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &lsin ), &sin_len ) == -1 )
+      return ;
+
+#if BUFFER_SIZE < LINE_LENGTH+2
+   bad_variable = 1 ;      /* this will cause a compilation error */
+#endif
+
+   for ( p = buf ; left > 2 ; left -= len, p += len )
+   {
+      len = min( LINE_LENGTH+2, left ) ;
+      if ( generate_line( p, len ) == NULL )
+         break ;
+   }
+   (void) sendto( fd, buf, p-buf, 0, SA( &lsin ), sin_len ) ;
+}
+
+
+/*  Handle a request for a tcpmux service. 
+ *  It's helpful to remember here that we are now a child of the original
+ *  xinetd process. We were forked to keep the parent from blocking
+ *  when we try to read the service name off'n the socket connection.
+ *  Serp still points to an actual tcpmux 'server', or at least the
+ *  service pointer of serp is valid.
+ */
+
+static void tcpmux_handler( const struct server *serp )
+{
+   char      svc_name[ BUFFER_SIZE ] ;
+   int       cc ;
+   int       descriptor = SERVER_FD( serp ) ;
+   const     struct service *svc = SERVER_SERVICE( serp ) ;
+   unsigned  u;
+   struct    service *sp = NULL;
+   struct    server server, *nserp;
+   struct    service_config *scp = NULL;
+
+   close_all_svc_descriptors();
+
+   /*  Read in the name of the service in the format "svc_name\r\n".
+    *
+    *  XXX: should loop on partial reads (could probably use Sread() if
+    *  it wasn't thrown out of xinetd source code a few revisions back).
+    */
+   do
+   {
+      cc = read( descriptor, svc_name, sizeof( svc_name ) ) ;
+   } while (cc == -1 && errno == EINTR);
+
+   if ( cc <= 0 )
+   {
+      msg(LOG_ERR, "tcpmux_handler", "read failed");
+      exit(0);
+   }
+
+   if ( ( cc <= 2 ) ||
+        ( ( svc_name[cc - 1] != '\n' ) || ( svc_name[cc - 2] != '\r' ) ) )
+   {
+      if ( debug.on )
+         msg(LOG_DEBUG, "tcpmux_handler", "Invalid service name format.");
+      
+      exit(0);
+   }
+
+   svc_name[cc - 2] = '\0';  /*  Remove \r\n for compare */
+
+   if ( debug.on )
+   {
+      msg(LOG_DEBUG, "tcpmux_handler", "Input (%d bytes) %s as service name.",
+          cc, svc_name);
+   }
+
+   /*  Search the services for the a match on name.
+    */
+
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+   {
+      sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+
+      if ( strcasecmp( svc_name, SC_NAME( SVC_CONF( sp ) ) ) == 0 )
+      {
+         /*  Found the pointer. Validate its type.
+          */
+         scp = SVC_CONF( sp );
+/*
+         if ( ! SVC_IS_MUXCLIENT( sp ) )
+         {
+            if ( debug.on )
+            {
+               msg(LOG_DEBUG, "tcpmux_handler", "Non-tcpmux service name: %s.",
+                   svc_name);
+            }
+            exit(0);
+         }
+*/
+
+         /*  Send the accept string if we're a PLUS (+) client.
+          */
+
+         if ( SVC_IS_MUXPLUSCLIENT( sp ) )
+         {
+            if ( Swrite( descriptor, TCPMUX_ACK, sizeof( TCPMUX_ACK ) ) !=
+                 sizeof( TCPMUX_ACK ) )
+            {
+                msg(LOG_ERR, "tcpmux_handler", "Ack write failed for %s.",
+                   svc_name);
+                exit(0);
+            }
+         }
+         break;  /*  Time to get on with the service */
+      }
+      continue;  /*  Keep looking */
+   }
+
+   if ( u >= pset_count( SERVICES( ps ) ) )
+   {
+      if ( debug.on )
+      {
+         msg(LOG_DEBUG, "tcpmux_handler", "Service name %s not found.",
+             svc_name);
+      }
+      exit(0);
+   }
+
+   if( SVC_WAITS( svc ) ) /* Service forks, so close it */
+      Sclose(descriptor);
+
+   server.svr_sp = sp;
+   server.svr_conn = SERVER_CONNECTION(serp);
+   nserp = server_alloc(&server);
+   if( SC_IS_INTERNAL( scp ) ) {
+      SC_INTERNAL(scp, nserp);
+   } else {
+      exec_server(nserp);
+   }
+}
+
diff --git a/xinetd/builtins.h b/xinetd/builtins.h
new file mode 100644 (file)
index 0000000..4b828e2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef BUILTINS_H
+#define BUILTINS_H
+
+/*
+ * $Id: builtins.h,v 1.2 2003/05/08 14:52:24 steveg Exp $
+ */
+
+#include "defs.h"
+
+
+#define FORK            YES
+#define NO_FORK         NO
+
+struct builtin
+{
+   voidfunc    b_handler ;             /* builtin service handler           */
+   boolean_e   b_fork_server ;         /* whether a server must be forked   */
+} ;
+
+typedef struct builtin builtin_s ;
+
+/*
+ * All builtins are invoked with a struct server argument
+ */
+#define BUILTIN_HANDLER( bp )          ( (bp)->b_handler ) 
+#define BUILTIN_INVOKE( bp, serp )     (*(bp)->b_handler)( serp )
+#define BUILTIN_FORKS( bp )            ( (bp)->b_fork_server == YES )
+
+
+struct builtin_service
+{
+   const char  *bs_name ;               /* for identification purposes      */
+   int         bs_socket_type ;         /* for identification purposes      */
+   builtin_s   bs_handle ;
+} ;
+
+const builtin_s *builtin_find(const char *service_name,int type);
+const builtin_s *builtin_lookup(const struct builtin_service services[],const char *service_name,int type);
+
+#endif   /* BUILTIN_H */
diff --git a/xinetd/child.c b/xinetd/child.c
new file mode 100644 (file)
index 0000000..89ee54c
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <errno.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#if defined (HAVE_GRP_H)
+#include <grp.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "str.h"
+#include "child.h"
+#include "sconf.h"
+#include "msg.h"
+#include "main.h"
+#include "xconfig.h"
+#include "ident.h"
+#include "sconst.h"
+#include "signals.h"
+#include "options.h"
+#include "redirect.h"
+
+/*
+ * This function is running in the new process
+ */
+void exec_server( const struct server *serp )
+{
+   const struct service_config *scp = SVC_CONF( SERVER_SERVICE( serp ) ) ;
+   struct rlimit rl ;
+   int fd ;
+   int descriptor = SERVER_FD( serp ) ;
+   const char *server = SC_SERVER( scp ) ;
+   const char *func = "exec_server" ;
+
+   /*
+    * The following code solves a problem with post-version-4.3
+    * Ultrix systems (the bug was reported, and a fix was provided by
+    * doug@seas.smu.edu; a slightly modified version of this
+    * fix is included here).
+    *
+    * If this is a 'nowait' service, we pass the service descriptor
+    * to the server. Note that we have set the close-on-exec flag
+    * on all service descriptors. It is unclear whether the dup2()
+    * will create a descriptor with the close-on-exec flag set,
+    * so we explicitly clear the flag (since we are doing this
+    * after the fork, it does not affect the descriptor of the
+    * parent process).
+    */
+   if ( fcntl( descriptor, F_SETFD, 0 ) == -1 )
+      msg( LOG_WARNING, func,
+         "fcntl( %d, clear close-on-exec ) failed: %m", descriptor ) ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "duping %d", descriptor ) ;
+
+   /*
+    * If server_loguser flag is on, then syslog may have opened fd 0, 1, or
+    * 2. We call msg_suspend() now so that the logging system doesn't use 
+    * the dup'ed descriptor.
+    */
+
+   msg_suspend() ;
+
+   for ( fd = 0 ; fd <= MAX_PASS_FD ; fd++ )
+   {
+      if ( dup2( descriptor, fd ) == -1 )
+      {
+        msg_resume();
+         msg( LOG_ERR, func,
+               "dup2( %d, %d ) failed: %m", descriptor, fd ) ;
+         _exit( 1 ) ;
+      }
+   }
+
+
+#ifdef RLIMIT_NOFILE
+   rl.rlim_max = ps.ros.orig_max_descriptors ;
+   rl.rlim_cur = ps.ros.max_descriptors ;
+   (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
+#endif
+#ifdef RLIMIT_AS
+   if (SC_RLIM_AS (scp))
+   {
+      rl.rlim_cur = SC_RLIM_AS( scp );
+      rl.rlim_max = SC_RLIM_AS( scp );
+      (void) setrlimit( RLIMIT_AS, &rl );
+   }
+#endif
+#ifdef RLIMIT_CPU
+   if (SC_RLIM_CPU (scp))
+   {
+      rl.rlim_cur = SC_RLIM_CPU( scp );
+      rl.rlim_max = SC_RLIM_CPU( scp );
+      (void) setrlimit( RLIMIT_CPU, &rl );
+   }
+#endif
+#ifdef RLIMIT_DATA
+   if (SC_RLIM_DATA (scp))
+   {
+      rl.rlim_cur = SC_RLIM_DATA( scp );
+      rl.rlim_max = SC_RLIM_DATA( scp );
+      (void) setrlimit( RLIMIT_DATA, &rl );
+   }
+#endif
+#ifdef RLIMIT_RSS
+   if (SC_RLIM_RSS (scp))
+   {
+      rl.rlim_cur = SC_RLIM_RSS( scp );
+      rl.rlim_max = SC_RLIM_RSS( scp );
+      (void) setrlimit( RLIMIT_RSS, &rl );
+   }
+#endif
+#ifdef RLIMIT_STACK
+   if (SC_RLIM_STACK (scp))
+   {
+      rl.rlim_cur = SC_RLIM_STACK( scp );
+      rl.rlim_max = SC_RLIM_STACK( scp );
+      (void) setrlimit( RLIMIT_STACK, &rl );
+   }
+#endif
+
+   (void) Sclose( descriptor ) ;
+
+#ifndef solaris
+#if !defined(HAVE_SETSID)
+   msg_resume();
+#endif
+   no_control_tty() ;
+#if !defined(HAVE_SETSID)
+   msg_suspend();
+#endif
+#endif
+
+   (void) execve( server, SC_SERVER_ARGV( scp ),
+             env_getvars( SC_ENV( scp )->env_handle ) ) ;
+
+   /*
+    * The exec failed. Log the error and exit.
+    */
+   msg_resume() ;
+   msg( LOG_ERR, func, "execv( %s ) failed: %m", server ) ;
+   _exit( 0 ) ;
+}
+
+
+/*
+ * Rename this process by changing the ps.ros.Argv vector
+ * Try to put the name of the service in ps.ros.Argv[0], Argv[1]
+ * until either the service name is exhausted or we run out
+ * of ps.ros.Argv's. 
+ * The rest of ps.ros.Argv is cleared to spaces
+ */
+static void rename_process( const char *name )
+{
+   const char *from = name ;
+   char *to = ps.ros.Argv[ 0 ] ;
+   int tmp_index = 1 ;
+
+   while ( *from != NUL )
+   {
+      if ( *to != NUL )
+         *to++ = *from++ ;
+      else
+         if ( tmp_index < ps.ros.Argc )
+            to = ps.ros.Argv[ tmp_index++ ] ;
+         else
+            break ;
+   }
+   str_fill( to, ' ' ) ;
+   while ( tmp_index < ps.ros.Argc )
+      str_fill( ps.ros.Argv[ tmp_index++ ], ' ' ) ;
+}
+
+
+static void set_credentials( const struct service_config *scp )
+{
+   const char *func = "set_credentials" ;
+
+   if ( SC_SPECIFIED( scp, A_GROUP ) || SC_SPECIFIED( scp, A_USER ) ) {
+      if ( ps.ros.is_superuser )
+      {
+         gid_t gid = SC_GETGID( scp ) ;
+
+         if ( setgid( gid ) == -1 )
+         {
+            msg( LOG_ERR, func, "setgid failed: %m" ) ;
+            _exit( 1 ) ;
+         }
+
+#ifndef NO_INITGROUPS
+         /*
+          * Bug discovered by maf+@osu.edu (a bug fix was also provided;
+          * a slightly modified version is included here):
+          *      initgroups was not being invoked to set the remaining
+          *      groups appropriately
+          */
+         /* Solar Designer's groups fix */
+         if ( SC_SPECIFIED( scp, A_USER ) && SC_SPECIFIED( scp, A_GROUPS ) &&
+            SC_GROUPS(scp) == YES )
+         {
+            struct passwd *pwd ;
+
+            /*
+             * Invoke getpwuid() to get the user's name.
+             *
+             * XXX:   we should not need to invoke getpwuid(); we should
+             *         remember the user name in the configuration file.
+             */
+            if ( ( pwd = getpwuid( SC_UID( scp ) ) ) == NULL )
+            {
+               msg( LOG_ERR, func, "getpwuid( %d ) (service=%s) failed: %m",
+                  SC_UID( scp ), SC_ID( scp ) ) ;
+               _exit( 1 ) ;
+            }
+            str_fill( pwd->pw_passwd, ' ' );
+
+            if ( initgroups( pwd->pw_name, pwd->pw_gid ) == -1 )
+            {
+               msg( LOG_ERR, func, "initgroups( %s, %d ) failed: %m",
+                  pwd->pw_name, pwd->pw_gid ) ;
+               _exit( 1 ) ;
+            }
+         }
+         else
+         {
+            if ( setgroups( 0, NULL ) )
+            {
+               msg( LOG_ERR, func, "setgroups( 0, NULL ) failed: %m" ) ;
+               msg( LOG_ERR, func, "Your system may require that 'groups = yes' be defined for this service: %s", SC_NAME(scp));
+               _exit( 1 ) ;
+            }
+         }
+#endif   /* ! NO_INITGROUPS */
+      }
+   }
+
+   if ( SC_SPECIFIED( scp, A_USER ) ) {
+         if ( setuid( SC_UID( scp ) ) == -1 )
+         {
+            msg( LOG_ERR, func, "setuid failed: %m" ) ;
+            _exit( 1 ) ;
+         }
+      }
+
+   if ( SC_SPECIFIED( scp, A_UMASK ) ) 
+      umask(SC_UMASK(scp));
+}
+
+
+
+/*
+ * This function is invoked in a forked process to run a server. 
+ * If the service is internal the appropriate function is invoked
+ * otherwise the server program is exec'ed.
+ * This function also logs the remote user id if appropriate
+ */
+void child_process( struct server *serp )
+{
+   struct service          *sp  = SERVER_SERVICE( serp ) ;
+   connection_s            *cp  = SERVER_CONNECTION( serp ) ;
+   struct service_config   *scp = SVC_CONF( sp ) ;
+   const char              *func = "child_process" ;
+
+   signal_default_state();
+
+   if ((signals_pending[0] >= 0 && Sclose(signals_pending[0])) ||
+       (signals_pending[1] >= 0 && Sclose(signals_pending[1])))
+   {
+      msg(LOG_ERR, func, "Failed to close the signal pipe: %m");
+      _exit(1);
+   }
+   signals_pending[0] = -1;
+   signals_pending[1] = -1;
+
+   Sclose(0);
+   Sclose(1);
+   Sclose(2);
+
+
+#ifdef DEBUG_SERVER
+   if ( debug.on )
+   {
+      msg( LOG_DEBUG, func, "Process %d is sleeping", getpid() ) ;
+      sleep( 10 ) ;
+   }
+#endif
+
+   if ( ! SC_IS_INTERCEPTED( scp ) )
+   {
+      set_credentials( scp ) ;
+      if ( SC_SPECIFIED( scp, A_NICE ) )
+         (void) nice( SC_NICE( scp ) ) ;
+   }
+
+   if ( svc_child_access_control(sp, cp) != OK )
+      exit(0);
+
+   if ( SERVER_LOGUSER( serp ) )
+   {
+      unsigned   timeout ;
+      idresult_e result ;
+      
+      /*
+       * We use LOGUSER_SUCCESS_TIMEOUT unless the service requires
+       * identification, in which case we use an infinite timeout
+       */
+      timeout = SC_MUST_IDENTIFY( scp ) ? 0 : LOGUSER_SUCCESS_TIMEOUT ;
+      result = log_remote_user( serp, timeout ) ;
+
+      if ( result != IDR_OK && SC_MUST_IDENTIFY( scp ) )
+      {
+         svc_logprint( sp, NOID_ENTRY, "%s %s",
+                  conn_addrstr( SERVER_CONNECTION( serp ) ),
+                     idresult_explain( result ) ) ;
+         _exit( 0 ) ;
+      }
+   }
+
+
+   /* this is where the server gets executed  -bbraun */
+   if ( ! SC_IS_INTERNAL( scp ) )
+   {
+      if( SC_REDIR_ADDR(scp) != NULL )
+      {
+         redir_handler( serp );
+      }
+      else
+      {
+#if defined(HAVE_SETENV)
+         char buff[1024];
+
+         strx_sprint(buff, sizeof(buff)-1, "REMOTE_HOST=%s", conn_addrstr(cp));
+         if( env_addstr(SC_ENV(scp)->env_handle, buff) != ENV_OK ) {
+            msg( LOG_ERR, func, "Error adding REMOTE_HOST variable for %s: %m", SC_NAME(scp) );
+            _exit( 1 ) ;
+         }
+#endif
+         exec_server( serp ) ;
+      }
+   }
+   else
+   {
+      char name[ 180 ] ;
+      /*
+       * We don't bother to disassociate from the controlling terminal
+       *   (we have a controlling terminal only if debug.on is TRUE)
+       *
+       * Also, for interceptor processes, we give them the name:
+       *            <program_name> <service-id> interceptor
+       */
+      if ( SC_IS_INTERCEPTED( scp ) )
+         strx_print( INT_NULL, name, sizeof( name ) - 1,
+                           "%s %s interceptor", program_name, SC_ID( scp ) ) ;
+      else
+      {
+         int namelen = sizeof( name ) - 1 ;      /* leave space for the NUL */
+         char host[NI_MAXHOST];
+         size_t hostlen = NI_MAXHOST;
+         socklen_t addrlen = 0;
+         union xsockaddr *sinp = CONN_XADDRESS(SERVER_CONNECTION(serp));
+         int len;
+
+         if( sinp == NULL )
+            exit(0);
+
+         if( SC_IPV6(scp) ) addrlen = sizeof(struct sockaddr_in6);
+         else if( SC_IPV4(scp) ) addrlen = sizeof(struct sockaddr_in);
+
+         len = strx_nprint(name, namelen, "(%s service) %s", program_name,
+            SC_ID( scp ) ) ;
+
+         if( getnameinfo( SA(sinp), addrlen, host, hostlen, NULL, 0, 0) != 0 )
+               strcpy(host, "unknown");
+
+         if ( SC_IPV6(scp) && SC_ACCEPTS_CONNECTIONS( scp ) && 
+               !IN6_IS_ADDR_UNSPECIFIED(&sinp->sa_in6.sin6_addr) )
+            strx_print( INT_NULL, &name[ len ], namelen - len, " %s" , host ) ;
+         if ( SC_IPV4(scp) && SC_ACCEPTS_CONNECTIONS( scp ) )
+            strx_print( INT_NULL, &name[ len ], namelen - len, " %s", host ) ;
+      }
+      rename_process( name ) ;
+      SVC_INTERNAL( sp, serp ) ;
+   }
+   _exit( 0 ) ;
+   /* NOTREACHED */
+}
+
+
+/*
+ * This function is invoked when a SIGCLD is received
+ */
+void child_exit(void)
+{
+   const char *func = "child_exit" ;
+
+   for ( ;; )         /* Find all children that exited */
+   {
+      int status ;
+      pid_t pid ;
+      struct server *serp ;
+      
+#ifdef HAVE_WAITPID
+      pid = waitpid( -1, &status, WNOHANG ) ;
+#else
+#if defined( sun ) && defined( lint )
+      pid = wait3( (union wait *)&status, WNOHANG, RUSAGE_NULL ) ;
+#else
+      pid = wait3( &status, WNOHANG, RUSAGE_NULL ) ;
+#endif
+#endif
+
+      if ( debug.on )
+#ifdef HAVE_WAITPID
+         msg( LOG_DEBUG, func, "waitpid returned = %d", pid ) ;
+#else
+         msg( LOG_DEBUG, func, "wait3 returned = %d", pid ) ;
+#endif
+      
+      if ( pid == -1 ) {
+         if ( errno == EINTR )
+            continue ;
+         else
+            break ;
+      }
+
+      if ( pid == 0 )
+         break ;
+      
+      if ( ( serp = server_lookup( pid ) ) != NULL )
+      {
+         SERVER_EXITSTATUS(serp) = status ;
+         server_end( serp ) ;
+      }
+      else
+         msg( LOG_NOTICE, func, "unknown child process %d %s", pid,
+            PROC_STOPPED( status ) ? "stopped" : "died" ) ;
+   }
+}
+
diff --git a/xinetd/child.h b/xinetd/child.h
new file mode 100644 (file)
index 0000000..70bdceb
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#ifndef _X_CHILD
+#define _X_CHILD
+
+#include "defs.h"
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void child_process(struct server *serp);
+void child_exit(void);
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void exec_server( const struct server *serp );
+
+#endif
diff --git a/xinetd/conf.c b/xinetd/conf.c
new file mode 100644 (file)
index 0000000..7ec7d1e
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "sio.h"
+#include "conf.h"
+#include "msg.h"
+#include "main.h"
+
+
+void cnf_free( struct configuration *confp )
+{
+   unsigned u ;
+   pset_h sconfs = confp->cnf_service_confs ;
+
+   for ( u = 0 ; u < pset_count( sconfs ) ; u++ )
+      sc_free( SCP( pset_pointer( sconfs, u ) ) ) ;
+   pset_destroy( sconfs ) ;
+   if ( confp->cnf_defaults )
+      sc_free( confp->cnf_defaults ) ;
+
+   CLEAR(*confp);
+}
+
+
+/*
+ * Extract from 'confp' the service that matches 'scp'
+ */
+struct service_config *cnf_extract( struct configuration *confp, 
+                                    struct service_config *scp )
+{
+   pset_h stab = confp->cnf_service_confs ;
+   unsigned u ;
+
+   for ( u = 0 ; u < pset_count( stab ) ; u++ )
+   {
+      struct service_config *iscp = SCP( pset_pointer( stab, u ) ) ;
+
+      if ( ! EQ( SC_ID(scp), SC_ID(iscp) ) || sc_different_confs( scp, iscp ) )
+         continue ;
+
+      pset_remove_index( stab, u ) ;
+      return( iscp ) ;
+   }
+   return( NULL ) ;
+}
+
+
+void cnf_dump( struct configuration *confp, int fd )
+{
+   pset_h stab; 
+   unsigned u ;
+
+   stab = confp->cnf_service_confs;
+
+   sc_dump( confp->cnf_defaults, fd, 0, TRUE ) ;
+   tabprint( fd, 0, "\n" ) ;
+
+   for ( u = 0 ; u < pset_count( stab ) ; u++ )
+   {
+      sc_dump( SCP( pset_pointer( stab, u ) ), fd, 0, FALSE ) ;
+      Sputchar( fd, '\n' ) ;
+   }
+}
+
+
+status_e cnf_init( struct configuration *confp, int *fdp, psi_h *iterp )
+{
+   int fd ;
+   pset_h pset ;
+   psi_h pset_iter ;
+   struct service_config *scp ;
+   const char *func = "cnf_init" ;
+
+   /*
+    * Open configuration file
+    */
+   fd = open( ps.ros.config_file, O_RDONLY ) ;
+
+   if ( fd == -1 ) {
+      msg( LOG_ERR, func, "open( %s ) failed: %m", ps.ros.config_file ) ;
+      return( FAILED ) ;
+   }
+
+   if ( ( pset = pset_create( 0, 0 ) ) == NULL )
+   {
+      msg( LOG_CRIT, func, "can't create service table" ) ;
+      (void) Sclose( fd ) ;
+      return( FAILED ) ;
+   }
+
+   if ( ( scp = sc_alloc( CHAR_NULL ) ) == NULL )
+   {
+      msg( LOG_ERR, func, "can't allocate defaults service" ) ;
+      pset_destroy( pset ) ;
+      (void) Sclose( fd ) ;
+      return( FAILED ) ;
+   }
+
+   if ( ( pset_iter = psi_create( pset ) ) == NULL )
+   {
+      msg( LOG_ERR, func, "can't create service table iterator" ) ;
+      sc_free( scp ) ;
+      pset_destroy( pset ) ;
+      (void) Sclose( fd ) ;
+      return( FAILED ) ;
+   }
+
+   *fdp = fd ;
+   confp->cnf_service_confs = pset ;
+   confp->cnf_defaults = scp ;
+   *iterp = pset_iter ;
+   return( OK ) ;
+}
+
+
+static void destroy_service( struct service *sp )
+{
+   svc_deactivate( sp ) ;
+   svc_free( sp ) ;
+   sp = NULL;
+}
+
+
+/*
+ * Try to start all services.
+ * Return the # of services started.
+ */
+unsigned cnf_start_services( struct configuration *confp )
+{
+   pset_h sconfs = confp->cnf_service_confs ;
+   unsigned services_started = 0 ;
+   unsigned u ;
+   const char *func = "cnf_start_services" ;
+
+   for ( u = 0 ; u < pset_count( sconfs ) ; u++ )
+   {
+      struct service_config *scp = SCP( pset_pointer( sconfs, u ) ) ;
+      struct service *sp ;
+
+      if ( ( sp = svc_new( scp ) ) == NULL )
+      {
+         sc_free( scp ) ;
+         scp = NULL;
+         continue ;
+      }
+
+      if ( svc_activate( sp ) == FAILED )
+      {
+         msg( LOG_ERR, func,
+            "Service %s failed to start and is deactivated.",
+               SVC_ID( sp ) ) ;
+         svc_free( sp ) ;
+         scp = NULL;
+         continue ;
+      }
+
+      /*
+       * descriptors_free can be negative without a descriptor-allocating
+       * system call failing because some of the descriptors we reserve
+       * are transient
+       */
+      if ( ps.rws.descriptors_free < 0 )
+      {
+         msg( LOG_ERR, func,
+            "Service %s disabled because of lack of file descriptors",
+               SVC_ID( sp ) ) ;
+         destroy_service( sp ) ;
+         continue ;
+      }
+
+      /*
+       * Activation successful; add service to service table
+       */
+      if ( pset_add( SERVICES( ps ), sp ) == NULL )
+      {
+         out_of_memory( func ) ;
+         destroy_service( sp ) ;
+         break ;
+      }
+
+      SVC_HOLD( sp ) ;
+
+      services_started++ ;
+
+      if ( debug.on )
+         msg( LOG_DEBUG, func, "Started service: %s", SVC_ID( sp ) ) ;
+   }
+
+   /*
+    * All the configurations have been linked to their services
+    * so we don't need to hold references to them in the pset.
+    * We need to clear the pset so that the cnf_free will not free the memory.
+    */
+   pset_clear( sconfs ) ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "mask_max = %d, services_started = %d",
+            ps.rws.mask_max, services_started ) ;
+         
+   return( services_started ) ;
+}
diff --git a/xinetd/conf.h b/xinetd/conf.h
new file mode 100644 (file)
index 0000000..0330e30
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef CONF_H
+#define CONF_H
+
+/*
+ * $Id: conf.h,v 1.1.1.1 2003/02/19 17:29:27 bbraun Exp $
+ */
+
+
+#include "pset.h"
+#include "sconf.h"
+
+
+struct configuration
+{
+   pset_h cnf_service_confs ;
+   struct service_config *cnf_defaults ;
+} ;
+
+#define CNF_DEFAULTS( confp )        (confp)->cnf_defaults
+#define CNF_SERVICE_CONFS( confp )   (confp)->cnf_service_confs
+
+void cnf_free(struct configuration *confp);
+struct service_config *cnf_extract(struct configuration *confp,struct service_config *scp);
+void cnf_dump(struct configuration *confp,int fd);
+status_e cnf_init(struct configuration *confp,int *fdp,psi_h *iterp);
+unsigned cnf_start_services(struct configuration *confp);
+
+
+#endif    /* CONF_H */
+
diff --git a/xinetd/confparse.c b/xinetd/confparse.c
new file mode 100644 (file)
index 0000000..db9f431
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <syslog.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
+
+#ifdef HAVE_RPC_RPCENT_H
+#include <rpc/rpcent.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "str.h"
+#include "sio.h"
+#include "confparse.h"
+#include "msg.h"
+#include "xconfig.h"
+#include "parse.h"
+#include "special.h"
+#include "sconst.h"
+#include "env.h"
+#include "sconf.h"
+#include "sensor.h"
+#include "inet.h"
+#include "main.h"
+
+extern int inetd_compat;
+
+/*
+ * Pset iterator used by functions in this file.
+ * It lives only when get_configuration is called (i.e. it is created and
+ * destroyed each time). This is because the pset it is iterating on
+ * changes.
+ */
+static psi_h iter ;
+
+static status_e fix_server_argv( struct service_config *scp )
+{
+   char *server_name ;
+   const char *func = "fix_server_argv" ;
+
+   if( SC_SERVER(scp) == NULL )
+   {
+      msg( LOG_ERR, func, 
+           "Must specify a server in %s", SC_NAME(scp));
+      return( FAILED );
+   }
+   
+   if( SC_NAMEINARGS( scp ) ) {
+      if( !SC_SPECIFIED(scp, A_SERVER_ARGS ) ){
+         msg( LOG_ERR, func, 
+              "Must specify server args if using NAMEINARGS flag");
+         return( FAILED );
+      }
+
+      return ( OK );
+   }
+
+   /*
+    * Check if the user specified any server arguments.
+    * If not, then the server_argv has not been allocated yet,
+    * so malloc it (size 2)
+    * Put in argv[ 0 ] the last component of the server pathname
+    */
+   if ( ! SC_SPECIFIED( scp, A_SERVER_ARGS ) )
+   {
+      SC_SERVER_ARGV(scp) = (char **) malloc( 2 * sizeof( char * ) ) ;
+      if ( SC_SERVER_ARGV(scp) == NULL )
+      {
+         out_of_memory( func ) ;
+         return( FAILED ) ;
+      }
+      SC_SERVER_ARGV(scp)[ 0 ] = NULL ;
+      SC_SERVER_ARGV(scp)[ 1 ] = NULL ;
+      SC_PRESENT( scp, A_SERVER_ARGS ) ;
+   }
+
+   /*
+    * Determine server name
+    */
+   server_name = strrchr( SC_SERVER(scp), '/' ) ;
+   if ( server_name == NULL )
+      server_name = SC_SERVER(scp) ;
+   else
+      server_name++ ;      /* skip the '/' */
+
+   /*
+    * Place it in argv[ 0 ]
+    */
+   SC_SERVER_ARGV(scp)[ 0 ] = new_string( server_name ) ;
+   if ( SC_SERVER_ARGV(scp)[ 0 ] == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+
+#define USE_DEFAULT( scp, def, attr_id )   \
+         ( ! SC_SPECIFIED( scp, attr_id ) && SC_SPECIFIED( def, attr_id ) )
+
+/*
+ * Fill the service configuration with attributes that were not
+ * explicitly specified. These can be:
+ *      1) implied attributes (like the server name in argv[0])
+ *      2) attributes from 'defaults' so that we won't need to check
+ *         'defaults' anymore.
+ *      3) default values (like the service instance limit)
+ */
+static status_e service_fill( struct service_config *scp, 
+                            struct service_config *def )
+{
+   const char *func = "service_fill" ;
+
+   /* Note: if the service was specified, it won't be honored. */
+   if( (SC_REDIR_ADDR(scp) != NULL) ) {
+       if ( SC_SPECIFIED( scp, A_SERVER ) && SC_SERVER(scp))
+          free(SC_SERVER(scp));
+       SC_SERVER(scp) = new_string( "/bin/true" );
+       SC_SPECIFY(scp, A_SERVER);
+   }
+
+   if ( ! SC_IS_INTERNAL( scp ) && fix_server_argv( scp ) == FAILED )
+      return( FAILED ) ;
+
+   /* 
+    * FIXME: Should all these set SPECIFY or PRESENT ?
+    * PRESENT means that either a default or specified value.
+    * SPECIFIED means that the user specified a value. 
+    * PRESENT makes more sense for default values. -SG
+    */
+   if ( ! SC_SPECIFIED( scp, A_INSTANCES ) )
+   {
+      SC_INSTANCES(scp) = SC_SPECIFIED( def, A_INSTANCES ) ? SC_INSTANCES(def)
+                                                     : DEFAULT_INSTANCE_LIMIT ;
+      SC_PRESENT( scp, A_INSTANCES ) ;
+   }
+
+   if ( (! SC_SPECIFIED( scp, A_UMASK )) && SC_SPECIFIED( def, A_UMASK ) ) 
+   {
+      SC_UMASK(scp) = SC_UMASK(def);
+      SC_SPECIFY( scp, A_UMASK );
+   }
+
+   if ( ! SC_SPECIFIED( scp, A_PER_SOURCE ) )
+   {
+      SC_PER_SOURCE(scp) = SC_SPECIFIED( def, A_PER_SOURCE ) ? 
+         SC_PER_SOURCE(def) : DEFAULT_INSTANCE_LIMIT ;
+      SC_SPECIFY( scp, A_PER_SOURCE ) ;
+   }
+
+#ifdef HAVE_MDNS
+   if ( ! SC_SPECIFIED( scp, A_MDNS ) )
+   {
+      SC_MDNS(scp) = SC_SPECIFIED( def, A_MDNS ) ? SC_MDNS(def) : YES;
+      SC_SPECIFY( scp, A_MDNS );
+   }
+#endif
+
+   if ( ! SC_SPECIFIED( scp, A_GROUPS ) )
+   {
+      SC_GROUPS(scp) = SC_SPECIFIED( def, A_GROUPS ) ? SC_GROUPS(def) : NO;
+      SC_SPECIFY( scp, A_GROUPS );
+   }
+
+   if ( ! SC_SPECIFIED( scp, A_CPS ) ) 
+   {
+      SC_TIME_CONN_MAX(scp) = SC_SPECIFIED( def, A_CPS ) ? 
+         SC_TIME_CONN_MAX(def) : DEFAULT_LOOP_RATE;
+      SC_TIME_WAIT(scp) = SC_SPECIFIED( def, A_CPS ) ? 
+         SC_TIME_WAIT(def) : DEFAULT_LOOP_TIME;
+      SC_TIME_REENABLE(scp) = 0;
+   }
+
+#ifdef HAVE_LOADAVG
+   if ( ! SC_SPECIFIED( scp, A_MAX_LOAD ) ) {
+      SC_MAX_LOAD(scp) = SC_SPECIFIED( def, A_MAX_LOAD ) ? SC_MAX_LOAD(def) : 0;
+      SC_SPECIFY( scp, A_MAX_LOAD ) ;
+   }
+#endif
+
+   /* 
+    * we need to check a few things. A_BIND can be specified & sc_bind_addr
+    * is NULL. This means the address couldn't be determined in bind_parser
+    * and it was stored into sc_orig_bind_addr. We unset the attribute
+    * so that its processed correctly.
+    */
+   if (SC_SPECIFIED( scp, A_BIND ) && SC_BIND_ADDR(scp) == NULL)
+      M_CLEAR( scp->sc_specified_attributes, A_BIND ) ;
+   
+   if ( (! SC_SPECIFIED( scp, A_BIND )) && (SC_ORIG_BIND_ADDR(scp) == 0) ) {
+      if ( SC_SPECIFIED( def, A_BIND ) ) {
+         SC_BIND_ADDR(scp) = (union xsockaddr *)malloc(sizeof(union xsockaddr));
+         if( SC_BIND_ADDR(scp) == NULL ) {
+            msg(LOG_ERR, func, "can't allocate space for bind addr");
+            return( FAILED );
+         }
+         memcpy(SC_BIND_ADDR(scp), SC_BIND_ADDR(def), sizeof(union xsockaddr));
+         SC_SPECIFY( scp, A_BIND ) ;
+      }
+      else if ( SC_ORIG_BIND_ADDR(def) )
+         SC_ORIG_BIND_ADDR(scp) = new_string( SC_ORIG_BIND_ADDR(def) );
+   }
+   
+   if ( ! SC_SPECIFIED( scp, A_V6ONLY ) ) {
+      SC_V6ONLY(scp) = SC_SPECIFIED( def, A_V6ONLY ) ? SC_V6ONLY(def) : NO;
+   }
+
+   if ( ! SC_SPECIFIED( scp, A_DENY_TIME ) )
+   {
+      SC_DENY_TIME(scp) = SC_SPECIFIED( def, A_DENY_TIME ) ? 
+         SC_DENY_TIME(def)  : 0 ;
+      SC_SPECIFY( scp, A_DENY_TIME ) ;
+   }
+
+   if ( (!SC_IPV4( scp )) && (!SC_IPV6( scp )) )
+   {
+      /*
+       * If bind is specified, check the address and see what family is
+       * available. If not, then use default.
+       */
+      if ( SC_SPECIFIED( scp, A_BIND ) && !SC_ORIG_BIND_ADDR(scp) ) 
+      {
+         if ( SAIN(SC_BIND_ADDR(scp))->sin_family == AF_INET )
+             M_SET(SC_XFLAGS(scp), SF_IPV4);
+         else
+             M_SET(SC_XFLAGS(scp), SF_IPV6);
+      }
+      else
+         M_SET(SC_XFLAGS(scp), SF_IPV4);
+   }
+
+   if (SC_ORIG_BIND_ADDR(scp))
+   {
+      /*
+       * If we are here, we have a dual stack machine with multiple
+       * entries for a domain name. We can finally use the flags for
+       * a hint to see which one to use.
+       */
+      struct addrinfo hints, *res;
+
+      memset(&hints, 0, sizeof(hints));
+      hints.ai_flags = AI_CANONNAME;
+      if (SC_IPV6(scp))
+         hints.ai_family = AF_INET6;
+      else
+         hints.ai_family = AF_INET;
+
+      if( getaddrinfo(SC_ORIG_BIND_ADDR(scp), NULL, &hints, &res) < 0 ) 
+      {
+         msg(LOG_ERR, func, "bad address given for: %s", SC_NAME(scp));
+         return( FAILED );
+      }
+
+      if( (res == NULL) || (res->ai_addr == NULL) ) 
+      {
+         msg(LOG_ERR, func, "no addresses returned for: %s", SC_NAME(scp));
+        return( FAILED );
+      }
+
+      if( (res->ai_family == AF_INET) || (res->ai_family == AF_INET6) )
+      {
+         SC_BIND_ADDR(scp) = (union xsockaddr *)
+            malloc(sizeof(union xsockaddr));
+         if( SC_BIND_ADDR(scp) == NULL )
+         {
+            msg(LOG_ERR, func, "can't allocate space for bind addr of: %s",
+                SC_NAME(scp));
+            return( FAILED );
+         }
+         memset(SC_BIND_ADDR(scp), 0, sizeof(union xsockaddr));
+         memcpy(SC_BIND_ADDR(scp), res->ai_addr, res->ai_addrlen);
+         free(SC_ORIG_BIND_ADDR(scp));
+         SC_ORIG_BIND_ADDR(scp) = 0;
+        SC_SPECIFY( scp, A_BIND );
+      }
+      freeaddrinfo(res);
+   }
+
+   /* This should be removed if sock_stream is ever something other than TCP,
+    * or sock_dgram is ever something other than UDP.
+    */
+   if ( (! SC_SPECIFIED( scp, A_PROTOCOL )) && 
+       ( SC_SPECIFIED( scp, A_SOCKET_TYPE ) ) )
+   {
+      struct protoent *pep ;
+
+      if( SC_SOCKET_TYPE(scp) == SOCK_STREAM ) {
+         if( (pep = getprotobyname( "tcp" )) != NULL ) {
+            SC_PROTONAME(scp) = new_string ( "tcp" );
+            if( SC_PROTONAME(scp) == NULL )
+               return( FAILED );
+            SC_PROTOVAL(scp) = pep->p_proto ;
+            SC_SPECIFY(scp, A_PROTOCOL);
+         }
+      }
+
+      if( SC_SOCKET_TYPE(scp) == SOCK_DGRAM ) {
+         if( (pep = getprotobyname( "udp" )) != NULL ) {
+            SC_PROTONAME(scp) = new_string ( "udp" );
+            if( SC_PROTONAME(scp) == NULL )
+               return( FAILED );
+            SC_PROTOVAL(scp) = pep->p_proto ;
+            SC_SPECIFY(scp, A_PROTOCOL);
+         }
+      }
+   }
+   if ( ( SC_SPECIFIED( scp, A_PROTOCOL )) && 
+        (! SC_SPECIFIED( scp, A_SOCKET_TYPE ) ) )
+   {
+      if( (SC_PROTONAME(scp) != NULL) && EQ("tcp", SC_PROTONAME(scp)) )
+      {
+            SC_SOCKET_TYPE(scp) = SOCK_STREAM;
+            SC_SPECIFY(scp, A_SOCKET_TYPE);
+      }
+
+      if( (SC_PROTONAME(scp) != NULL) && EQ("udp", SC_PROTONAME(scp)) )
+      {
+            SC_SOCKET_TYPE(scp) = SOCK_DGRAM;
+            SC_SPECIFY(scp, A_SOCKET_TYPE);
+      }
+   }
+
+   /*
+    * Next assign a port based on service name if not specified. Based
+    * on the code immediately before this, if either a socket_type or a
+    * protocol is specied, the other gets set appropriately. We will only
+    * use protocol for this code.
+    */
+   if (! SC_SPECIFIED( scp, A_PORT ) && ! SC_IS_MUXCLIENT( scp ) && 
+                                        ! SC_IS_RPC( scp )) {
+       if ( SC_IS_UNLISTED( scp ) ) {
+          msg(LOG_ERR, func, "Unlisted service: %s must have a port entry",
+              SC_NAME(scp));
+          return(FAILED);
+       }
+       if ( SC_SPECIFIED( scp, A_PROTOCOL ) ) {
+          /*
+           * Look up the service based on the protocol and service name.
+          * If not found, don't worry. Message will be emitted in
+          * check_entry().
+           */
+         struct servent *sep = getservbyname( SC_NAME(scp), 
+                                           SC_PROTONAME(scp) ) ;
+         if ( sep != NULL ) {
+            /* s_port is in network-byte-order */
+            SC_PORT(scp) = ntohs(sep->s_port);
+            SC_SPECIFY(scp, A_PORT);
+         }
+         else {
+            msg(LOG_ERR, func, 
+             "Port not specified and can't find service: %s with getservbyname",
+               SC_NAME(scp));
+            return(FAILED);
+         }
+      }
+      else {
+         msg(LOG_ERR, func, 
+             "Port not specified for service: %s and no protocol given", 
+             SC_NAME(scp));
+         return(FAILED);
+      }
+   }
+   
+   if ( USE_DEFAULT( scp, def, A_LOG_ON_SUCCESS ) )
+   {
+      SC_LOG_ON_SUCCESS(scp) = SC_LOG_ON_SUCCESS(def) ;
+      SC_SPECIFY( scp, A_LOG_ON_SUCCESS ) ;
+   }
+
+   if ( USE_DEFAULT( scp, def, A_LOG_ON_FAILURE ) )
+   {
+      SC_LOG_ON_FAILURE(scp) = SC_LOG_ON_FAILURE(def) ;
+      SC_SPECIFY( scp, A_LOG_ON_FAILURE ) ;
+   }
+
+   if ( USE_DEFAULT( scp, def, A_LOG_TYPE ) )
+   {
+      struct log *dlp = SC_LOG( def ) ;
+      struct log *slp = SC_LOG( scp ) ;
+
+      switch ( LOG_GET_TYPE( dlp ) )
+      {
+         case L_NONE:
+            LOG_SET_TYPE( slp, L_NONE ) ;
+            break ;
+         
+         case L_SYSLOG:
+            *slp = *dlp ;
+            break ;
+         
+         case L_FILE:
+            LOG_SET_TYPE( slp, L_COMMON_FILE ) ;
+            break ;
+
+         default:
+            msg( LOG_ERR, func,
+                        "bad log type: %d", (int) LOG_GET_TYPE( dlp ) ) ;
+            return( FAILED ) ;
+      }
+      SC_SPECIFY( scp, A_LOG_TYPE ) ;
+   }
+   if ( setup_environ( scp, def ) == FAILED )
+      return( FAILED ) ;
+   return( OK ) ;
+}
+
+
+static void remove_disabled_services( struct configuration *confp )
+{
+   pset_h disabled_services ;
+   pset_h enabled_services ;
+   struct service_config *scp ;
+   struct service_config *defaults = confp->cnf_defaults ;
+
+   if( SC_SPECIFIED( defaults, A_ENABLED ) ) {
+      enabled_services = SC_ENABLED(defaults) ;
+      
+
+      /* Mark all the services disabled */
+      for ( scp = SCP( psi_start( iter ) ) ; scp ; scp = SCP( psi_next(iter) ) )
+         SC_DISABLE( scp );
+
+      /* Enable the selected services */
+      for ( scp = SCP( psi_start( iter ) ) ; scp ; scp = SCP( psi_next(iter) ) )
+      {
+         register char *sid = SC_ID( scp ) ;
+         register unsigned u ;
+
+         for ( u = 0 ; u < pset_count( enabled_services ) ; u++ ) {
+            if ( EQ( sid, (char *) pset_pointer( enabled_services, u ) ) ) {
+               SC_ENABLE( scp );
+               break;
+            }
+         }
+      }
+   }
+
+   /* Remove any services that are left marked disabled */
+   for ( scp = SCP( psi_start( iter ) ) ; scp ; scp = SCP( psi_next(iter)) ){
+      if( SC_IS_DISABLED( scp ) ) {
+         msg(LOG_DEBUG, "remove_disabled_services", "removing %s", SC_NAME(scp));
+         SC_DISABLE( scp );
+         sc_free(scp);
+         psi_remove(iter);
+      }
+   }
+
+   if ( ! SC_SPECIFIED( defaults, A_DISABLED ) )
+      return ;
+   
+   disabled_services = SC_DISABLED(defaults) ;
+
+   for ( scp = SCP( psi_start( iter ) ) ; scp ; scp = SCP( psi_next( iter ) ) )
+   {
+      register char *sid = SC_ID( scp ) ;
+      register unsigned u ;
+
+      for ( u = 0 ; u < pset_count( disabled_services ) ; u++ )
+         if ( EQ( sid, (char *) pset_pointer( disabled_services, u ) ) )
+         {
+            sc_free( scp ) ;
+            psi_remove( iter ) ;
+            break ;
+         }
+   }
+}
+
+
+/*
+ * Check if all required attributes have been specified
+ */
+static status_e service_attr_check( struct service_config *scp )
+{
+   mask_t         necessary_and_specified ;
+   mask_t         necessary_and_missing ;
+   mask_t         must_specify = NECESSARY_ATTRS ; /* socket_type & wait */
+   unsigned int   attr_id ;
+   const char    *attr_name ;
+   const char    *func = "service_attr_check" ;
+
+   /*
+    * Determine what attributes must be specified
+    */
+   if ( ! SC_IS_INTERNAL( scp ) ) 
+   {  /* user & server */
+      M_OR( must_specify, must_specify, NECESSARY_ATTRS_EXTERNAL ) ;
+      if ( SC_IS_UNLISTED( scp ) ) 
+      {
+         if ( ! SC_IS_MUXCLIENT( scp ) ) /* protocol, & port */
+         {
+            M_OR( must_specify, must_specify, NECESSARY_ATTRS_UNLISTED ) ;
+         }
+         else  /* Don't need port for TCPMUX CLIENT */
+         {
+           M_OR( must_specify, must_specify, NECESSARY_ATTRS_UNLISTED_MUX ) ;
+         }
+      }
+   }
+
+   if ( SC_IS_RPC( scp ) ) 
+   {
+      M_CLEAR( must_specify, A_PORT ); /* port is already known for RPC */
+      /* protocol & rpc_version */
+      M_OR( must_specify, must_specify, NECESSARY_ATTRS_RPC ) ;
+      if ( SC_IS_UNLISTED( scp ) ) /* rpc_number */
+         M_OR( must_specify, must_specify, NECESSARY_ATTRS_RPC_UNLISTED ) ;
+   }
+   else
+   {
+      if ( SC_SPECIFIED( scp, A_REDIR ) )
+         M_CLEAR( must_specify, A_SERVER ); /* server isn't used */
+   }
+
+   if( SC_IPV4( scp ) && SC_IPV6( scp ) ) {
+      msg( LOG_ERR, func, 
+         "Service %s specified as both IPv4 and IPv6 - DISABLING", 
+        SC_NAME(scp));
+      return FAILED ;
+   }
+   
+   /*
+    * Check if all necessary attributes have been specified
+    *
+    * NOTE: None of the necessary attributes can belong to "defaults"
+    *         This is why we use the sc_attributes_specified mask instead
+    *         of the sc_attributes_present mask.
+    */
+
+   M_AND( necessary_and_specified,
+                  scp->sc_specified_attributes, must_specify ) ;
+   M_XOR( necessary_and_missing, necessary_and_specified, must_specify ) ;
+
+   if ( M_ARE_ALL_CLEAR( necessary_and_missing) )
+      return OK ;
+
+   /*
+    * Print names of missing attributes
+    */
+   for ( attr_id = 0 ; attr_id < SERVICE_ATTRIBUTES ; attr_id++ )
+      if ( M_IS_SET( necessary_and_missing, attr_id ) && 
+                  ( attr_name = attr_name_lookup( attr_id ) ) != NULL )
+      {
+         msg( LOG_ERR, func,
+            "Service %s missing attribute %s - DISABLING", 
+           SC_ID(scp), attr_name ) ;
+      }
+   return FAILED ;
+}
+
+
+/*
+ * Perform validity checks on the whole entry. At this point, all
+ * attributes have been read and we can do an integrated check that
+ * all parameters make sense.
+ *
+ * Also does the following:
+ *      1. If this is an internal service, it finds the function that
+ *         implements it
+ *      2. For RPC services, it finds the program number
+ *      3. For non-RPC services, it finds the port number.
+ */
+static status_e check_entry( struct service_config *scp, 
+                             const struct configuration *confp )
+{
+   const char *func = "check_entry" ;
+   unsigned int u;
+   const pset_h sconfs = CNF_SERVICE_CONFS( confp ) ;
+
+   /*
+    * Make sure the service id is unique
+    */
+   for ( u = 0 ; u < pset_count( sconfs ) ; u++ ) 
+   {
+      int diff = 1;
+      const struct service_config *tmp_scp = SCP( pset_pointer( sconfs, u ) );
+      if (tmp_scp == scp)
+         break; /* Don't check ourselves, or anything after us */
+      if ( EQ( SC_ID(tmp_scp), SC_ID(scp) ) )
+      { 
+         diff = 0;
+      }
+      if( SC_BIND_ADDR(tmp_scp) == NULL)
+         continue; /* problem entry, skip it */
+      if ( (SC_PORT(scp) != SC_PORT(tmp_scp)) || 
+           (SC_PROTOVAL(scp) != SC_PROTOVAL(tmp_scp)) )
+         continue; /* if port or protocol are different, its OK */
+      if (SC_BIND_ADDR(scp) != NULL)
+      {
+         if (SC_BIND_ADDR(scp)->sa.sa_family != 
+             SC_BIND_ADDR(tmp_scp)->sa.sa_family)
+            continue;
+         if (SC_BIND_ADDR(scp)->sa.sa_family == AF_INET)
+         {
+            if (memcmp(&SC_BIND_ADDR(scp)->sa_in.sin_addr, 
+                       &SC_BIND_ADDR(tmp_scp)->sa_in.sin_addr, 
+                       sizeof(struct in_addr) ) )
+               continue;
+         }
+         else /* We assume that all bad address families are weeded out */
+         {
+            if (memcmp(&SC_BIND_ADDR(scp)->sa_in6.sin6_addr, 
+                       &SC_BIND_ADDR(tmp_scp)->sa_in6.sin6_addr, 
+                       sizeof(struct in6_addr) ) )
+               continue;
+         }
+      } 
+      if( SC_IS_DISABLED( tmp_scp ) ||
+               SC_IS_DISABLED(scp) ) 
+      {
+         /* 
+          * Allow multiple configs, as long as all but one are
+          * disabled.
+          */
+         continue;
+      }
+#if defined(HAVE_RPC_RPCENT_H) || defined(HAVE_NETDB_H)
+      if ( SC_IS_RPC( scp ) && SC_IS_RPC ( tmp_scp ) )
+      {
+         const struct rpc_data *rdp1 = SC_RPCDATA( scp ) ;
+         const struct rpc_data *rdp2 = SC_RPCDATA( tmp_scp ) ;
+         if ( rdp1->rd_program_number != rdp2->rd_program_number )
+           continue;
+        if ( rdp1->rd_min_version > rdp2->rd_max_version ||
+             rdp1->rd_max_version < rdp2->rd_min_version )
+          continue;
+      }
+#endif
+      if (diff) 
+         msg( LOG_ERR, func, 
+         "service: %s id: %s is unique but its identical to "
+               "service: %s id: %s - DISABLING",
+           SC_NAME(scp), SC_ID(scp), SC_NAME(tmp_scp), SC_ID(tmp_scp) ) ;
+      else
+         msg( LOG_ERR, func, 
+           "service: %s id: %s not unique or is a duplicate - DISABLING",
+           SC_NAME(scp), SC_ID(scp) ) ;
+      return FAILED ;
+   } /* for */
+   
+   /*
+    * Currently, we cannot intercept:
+    *      1) internal services
+    *      2) multi-threaded services
+    * We clear the INTERCEPT flag without disabling the service.
+    */
+   if ( SC_IS_INTERCEPTED( scp ) )
+   {
+      if ( SC_IS_INTERNAL( scp ) )
+      {
+         msg( LOG_ERR, func,
+            "Internal services cannot be intercepted: %s ", SC_ID(scp) ) ;
+         M_CLEAR( SC_XFLAGS(scp), SF_INTERCEPT ) ;
+      }
+      if ( SC_WAIT(scp) == NO )
+      {
+         msg( LOG_ERR, func,
+            "Multi-threaded services cannot be intercepted: %s", SC_ID(scp) ) ;
+         M_CLEAR( SC_XFLAGS(scp), SF_INTERCEPT ) ;
+      }
+   }
+   
+   /* Steer the lost sheep home */
+   if ( SC_SENSOR( scp ) )
+      M_SET( SC_TYPE(scp), ST_INTERNAL );
+
+   if ( SC_IS_INTERNAL( scp ) )
+   {   /* If SENSOR flagged redirect to internal builtin function. */ 
+      if ( SC_SENSOR( scp ) )
+      {
+        init_sensor();
+         SC_BUILTIN(scp) =
+            builtin_find( "sensor", SC_SOCKET_TYPE(scp) );
+      }
+      else
+         SC_BUILTIN(scp) =
+            builtin_find( SC_NAME(scp), SC_SOCKET_TYPE(scp) );
+      if (SC_BUILTIN(scp) == NULL )
+         return( FAILED ) ;
+   }
+
+   if ( SC_IS_MUXCLIENT( scp ) ) 
+   {
+          if ( !SC_IS_UNLISTED( scp ) )
+          {
+               msg(LOG_ERR, func, 
+                   "Service: %s (tcpmux) should have UNLISTED in type.",
+                  SC_NAME(scp));
+              return( FAILED );
+          }
+          
+          if (!EQ("tcp", SC_PROTONAME(scp)))
+          {
+               msg(LOG_ERR, func, 
+                   "Service: %s (tcpmux) should have tcp in protocol.",
+                  SC_NAME(scp));
+              return( FAILED );
+          }
+   }
+
+/* #ifndef NO_RPC */
+#if defined(HAVE_RPC_RPCENT_H) || defined(HAVE_NETDB_H)
+   if ( SC_IS_RPC( scp ) && !SC_IS_UNLISTED( scp ) )
+   {
+      struct rpcent *rep = (struct rpcent *)getrpcbyname( SC_NAME(scp) ) ;
+
+      if ( rep == NULL )
+      {
+         msg( LOG_ERR, func, "unknown RPC service: %s", SC_NAME(scp) ) ;
+         return( FAILED ) ;
+      }
+      SC_RPCDATA( scp )->rd_program_number = rep->r_number ;
+   }
+   else
+#endif   /* ! NO_RPC */
+   {
+       if ( !SC_IS_UNLISTED( scp ) ) 
+       { 
+          uint16_t service_port ;
+          struct servent *sep ;
+  
+          /*
+           * Check if a protocol was specified. Based on the code in 
+          * service_fill, if either socket_type or protocol is specified,
+          * the other one is filled in. Protocol should therefore always
+          * be filled in unless they made a mistake. Then verify it is the
+          * proper protocol for the given service. 
+           * We don't need to check MUXCLIENTs - they aren't in /etc/services.
+           */
+          if ( SC_SPECIFIED( scp, A_PROTOCOL ) )
+          {
+             sep = getservbyname( SC_NAME(scp), SC_PROTONAME(scp) ) ;
+             if ( (sep == NULL) )
+             {
+                msg( LOG_ERR, func, 
+                   "service/protocol combination not in /etc/services: %s/%s",
+                   SC_NAME(scp), SC_PROTONAME(scp) ) ;
+                return( FAILED ) ;
+             }
+          }
+          else
+          {
+             msg( LOG_ERR, func,
+               "A protocol or a socket_type must be specified for service: %s.",
+                SC_NAME(scp) ) ;
+             return( FAILED ) ;
+          }
+          /* s_port is in network-byte-order */
+          service_port = ntohs(sep->s_port);
+          /*
+           * If a port was specified, it must be the right one
+           */
+          if ( SC_SPECIFIED( scp, A_PORT ) && 
+               SC_PORT(scp) != service_port )
+          {
+             msg( LOG_ERR, func, "Service %s expects port %d, not %d",
+                  SC_NAME(scp), service_port, SC_PORT(scp) ) ;
+             return( FAILED ) ;
+          }
+      } /* if not unlisted */
+    }
+    if ( SC_SPECIFIED( scp, A_REDIR ))
+    {
+       if ( SC_SOCKET_TYPE( scp ) != SOCK_STREAM )
+       {
+          msg( LOG_ERR, func, 
+             "Only tcp sockets are supported for redirected service %s",
+             SC_NAME(scp));
+          return FAILED;
+       }
+       if ( SC_WAITS( scp ) )
+       {
+          msg( LOG_ERR, func, 
+             "Redirected service %s must not wait", SC_NAME(scp));
+          return FAILED;
+       }
+       if ( SC_NAMEINARGS( scp ) )
+       {
+          msg( LOG_ERR, func, 
+             "Redirected service %s should not have NAMEINARGS flag set", 
+             SC_NAME(scp));
+          return FAILED;
+       }
+    }
+    else /* Not a redirected service */
+    {
+       if( M_IS_SET( SC_LOG_ON_SUCCESS(scp), LO_TRAFFIC ) )
+       {
+          msg( LOG_ERR, func,
+             "Service %s should not have TRAFFIC flag set since its"
+             " not redirected", SC_NAME(scp));
+          return FAILED;
+       }
+    }
+    
+   if ( SC_NAMEINARGS(scp) )
+   {
+      if (SC_IS_INTERNAL( scp ) )
+      {
+         msg( LOG_ERR, func, 
+              "Service %s is INTERNAL and has NAMEINARGS flag set", 
+             SC_NAME(scp) );
+         return FAILED;
+      }
+      else if (!SC_SPECIFIED( scp, A_SERVER_ARGS) )
+      {
+         msg( LOG_ERR, func, 
+              "Service %s has NAMEINARGS flag set and no server_args", 
+             SC_NAME(scp) );
+         return FAILED;
+      }
+   }
+
+   if ( service_attr_check( scp ) == FAILED )
+      return( FAILED ) ;
+
+   return( OK ) ;
+}
+
+/*
+ * Get a configuration from the specified file.
+ */
+static status_e get_conf( int fd, struct configuration *confp )
+{
+   parse_conf_file( fd, confp, ps.ros.config_file ) ;
+   parse_end() ;
+   return( OK ) ;
+}
+
+
+#define CHECK_AND_CLEAR( scp, mask, mask_name )                               \
+   if ( M_IS_SET( mask, LO_USERID ) )                                         \
+   {                                                                          \
+      msg( LOG_WARNING, func,                                                 \
+      "%s service: clearing USERID option from %s", SC_ID(scp), mask_name ) ; \
+      M_CLEAR( mask, LO_USERID ) ;                                            \
+   }
+
+/*
+ * Get a configuration by reading the configuration file.
+ */
+status_e cnf_get( struct configuration *confp )
+{
+   int config_fd ;
+   struct service_config *scp ;
+   const char *func = "get_configuration" ;
+
+   if ( cnf_init( confp, &config_fd, &iter ) == FAILED )
+      return( FAILED ) ;
+
+   else if ( get_conf( config_fd, confp ) == FAILED )
+   {
+      Sclose( config_fd ) ;
+      cnf_free( confp ) ;
+      psi_destroy( iter ) ;
+      return( FAILED ) ;
+   }
+
+   /* get_conf eventually calls Srdline, try Sclosing to unmmap memory. */
+   Sclose( config_fd );
+   if( inetd_compat ) {
+      current_file = "/etc/inetd.conf";
+      config_fd = open(current_file, O_RDONLY);
+      if( config_fd >= 0 ) {
+         parse_inet_conf_file( config_fd, confp );
+         parse_end() ;
+         /*
+         * parse_inet_conf eventually calls Srdline, try Sclosing to 
+         * unmmap memory. 
+         */
+         Sclose(config_fd);
+      }
+   }
+
+   remove_disabled_services( confp ) ;
+
+   for ( scp = SCP( psi_start( iter ) ) ; scp ; scp = SCP( psi_next( iter ) ) )
+   {
+      /*
+       * Fill the service configuration from the defaults.
+       * We do this so that we don't have to look at the defaults any more.
+       */
+      if ( service_fill( scp, confp->cnf_defaults ) == FAILED )
+      {
+         sc_free( scp ) ;
+         psi_remove( iter ) ;
+         continue ;
+      }
+
+      if ( check_entry( scp, confp ) == FAILED )
+      {
+         sc_free( scp ) ;
+         psi_remove( iter ) ;
+         continue ;
+      }
+
+      /*
+       * If the INTERCEPT flag is set, change this service to an internal 
+       * service using the special INTERCEPT builtin.
+       */
+      if ( SC_IS_INTERCEPTED( scp ) )
+      {
+         const builtin_s *bp ;
+
+         bp = spec_find( INTERCEPT_SERVICE_NAME, SC_SOCKET_TYPE(scp) ) ;
+         if ( bp == NULL )
+         {
+            msg( LOG_ERR, func, "removing service %s", SC_ID( scp ) ) ;
+            sc_free( scp ) ;
+            psi_remove( iter ) ;
+            continue ;
+         }
+
+         SC_BUILTIN(scp) = bp ;
+         M_SET( SC_TYPE(scp), ST_INTERNAL ) ;
+      }
+
+      /*
+       * Clear the USERID flag for the identity service because
+       * it may lead to loops (for example, remote xinetd issues request,
+       * local xinetd issues request to remote xinetd etc.)
+       * We identify the identity service by its (protocol,port) combination.
+       */
+      if ( SC_PORT(scp) == IDENTITY_SERVICE_PORT && 
+                                       SC_PROTOVAL(scp) == IPPROTO_TCP )
+      {
+         CHECK_AND_CLEAR( scp, SC_LOG_ON_SUCCESS(scp), "log_on_success" ) ;
+         CHECK_AND_CLEAR( scp, SC_LOG_ON_FAILURE(scp), "log_on_failure" ) ;
+      }
+   }
+
+   psi_destroy( iter ) ;
+
+   if ( debug.on && debug.fd != -1 )
+      cnf_dump( confp, debug.fd ) ;
+
+   endservent() ;
+   endprotoent() ;
+#ifndef NO_RPC
+   endrpcent() ;
+#endif
+   return( OK ) ;
+}
+
diff --git a/xinetd/confparse.h b/xinetd/confparse.h
new file mode 100644 (file)
index 0000000..677c30f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef CONFPARSE_H
+#define CONFPARSE_H
+
+#include "defs.h"
+#include "conf.h"
+#include "xconfig.h"
+
+status_e cnf_get(struct configuration *confp);
+
+#endif
+
diff --git a/xinetd/connection.c b/xinetd/connection.c
new file mode 100644 (file)
index 0000000..fae7f77
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <netinet/tcp.h>
+
+#include "sio.h"
+#include "connection.h"
+#include "sconf.h"
+#include "msg.h"
+#include "main.h"
+#include "state.h"
+#include "special.h"
+#include "access.h"
+
+#define NEW_CONN()            NEW( connection_s )
+#define FREE_CONN( cop )      FREE( cop )
+
+/*
+ * Get a new connection request and initialize 'cp' appropriately
+ */
+static status_e get_connection( struct service *sp, connection_s *cp )
+{
+   struct service_config *scp = SVC_CONF( sp );
+   socklen_t sin_len;
+   const char *func = "get_connection" ;
+   int on = 1;
+
+   if( SC_IPV4(scp) ) sin_len = sizeof(struct sockaddr_in);
+   if( SC_IPV6(scp) ) sin_len = sizeof(struct sockaddr_in6);
+
+   if ( SVC_SOCKET_TYPE( sp ) == SOCK_STREAM ) {
+      /* If it's a TCP socket, and we're set to wait, the accept is
+       * done by the child process.  Don't set NEW_DESCRIPTOR, since
+       * there isn't one.  The descriptor will be/was removed from
+       * the descriptor set in svc_suspend and re-enabled in svc_resume.
+       */
+      if( SC_WAITS( scp ) ) {
+         cp->co_descriptor = SVC_FD( sp );
+      } else {
+         cp->co_descriptor = accept( SVC_FD( sp ), &(cp->co_remote_address.sa),
+                                     &sin_len ) ;
+        if (cp->co_descriptor != -1)
+             M_SET( cp->co_flags, COF_NEW_DESCRIPTOR ) ;
+      }
+
+      if ( cp->co_descriptor == -1 )
+      {
+        if ((errno == EMFILE) || (errno == ENFILE))
+            cps_service_stop(sp, "no available descriptors");
+        else
+             msg( LOG_ERR, func, "service %s, accept: %m", SVC_ID( sp ) ) ;
+         return( FAILED ) ;
+      }
+
+      if( SC_NODELAY( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) )
+         if( setsockopt(SVC_FD(sp), IPPROTO_TCP, TCP_NODELAY, 
+                        (char *)&on, sizeof( on ) ) < 0 )
+            msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp));
+
+      if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL( scp ) == IPPROTO_TCP) )
+      {
+         if( setsockopt(SVC_FD(sp), SOL_SOCKET, SO_KEEPALIVE, 
+                        (char *)&on, sizeof( on ) ) < 0 )
+            msg( LOG_WARNING, func, "service %s, setsockopt: %m", SVC_ID(sp));
+      }
+      
+      if( SC_IPV6(scp) && !(SC_V6ONLY( scp ))  && 
+         (IN6_IS_ADDR_V4MAPPED(&cp->co_remote_address.sa_in6.sin6_addr) || 
+         IN6_IS_ADDR_V4COMPAT(&cp->co_remote_address.sa_in6.sin6_addr)) ) 
+      {
+         int af = AF_INET;
+         if( setsockopt(cp->co_descriptor, IPPROTO_IPV6,
+               IPV6_ADDRFORM, &af, sizeof( af ) ) ) {
+            if( debug.on ) msg( LOG_WARNING, func, "service %s, IPV6_ADDRFORM setsockopt() failed: %m", SVC_ID( sp) );
+         }
+      }
+
+      M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ;
+   }
+   else
+   {
+      if ( SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM )
+      {
+         char t_ch ;
+
+         /*
+          * This trick is done to get the remote address.
+          * select(2) guaranteed that we won't block on the recvfrom
+          */
+         if ( recvfrom( SVC_FD( sp ), &t_ch, 1, MSG_PEEK,
+                              &cp->co_remote_address.sa, &sin_len ) == -1 )
+         {
+            msg( LOG_ERR, func, "service %s, recvfrom: %m", SVC_ID( sp ) ) ;
+            return( FAILED ) ;
+         }
+         M_SET( cp->co_flags, COF_HAVE_ADDRESS ) ;
+      }
+
+      cp->co_descriptor = SVC_FD( sp ) ;
+   }
+
+   return( OK ) ;
+}
+
+
+
+/*
+ * Get a connection for the specified service and return a pointer
+ * to a new connection_s
+ */
+connection_s *conn_new( struct service *sp )
+{
+   connection_s    new_conn ;
+   connection_s   *cp ;
+   const char     *func = "conn_new" ;
+
+   CLEAR( new_conn ) ;
+
+   /*
+    * The reason we first get the connection and then allocate a
+    * 'connection_s' is because we want to always consume some input.
+    */
+   if ( get_connection( sp, &new_conn ) == FAILED )
+      return( NULL ) ;
+
+   new_conn.co_sp = sp ;
+   SVC_HOLD( sp ) ;
+   
+   if ( SVC_WAITS( sp ) )
+      svc_suspend( sp ) ;
+
+   cp = NEW_CONN() ;
+   if ( cp == CONN_NULL )
+   {
+      out_of_memory( func ) ;
+      conn_free( &new_conn, 0 ) ;
+      CLEAR( new_conn ) ;
+      return( CONN_NULL ) ;
+   }
+   memcpy(cp, &new_conn, sizeof(connection_s));
+   return( cp ) ;
+}
+
+
+/*
+ * Release the specified connection.
+ * Certain actions may be performed before doing this:
+ *      - drain of a single UDP packet if the socket type is SOCK_DGRAM
+ */
+void conn_free( connection_s *cp, int release_mem )
+{
+   struct service *sp = cp->co_sp ;
+
+   if( cp == NULL )
+      return;
+      if( debug.on )
+         msg( LOG_INFO, "conn_free", "freeing connection") ;
+
+   if( (SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM) && (SVC_IS_ACTIVE( sp )) )
+      drain( cp->co_descriptor ) ;
+
+   if ( SVC_RELE( sp ) == 0 ) {
+      pset_remove( SERVICES( ps ), sp ) ;
+      svc_release( sp );
+   }
+   cp->co_sp = NULL;
+
+   CONN_CLOSE( cp ) ;
+
+   CLEAR( *cp ) ;
+   if (release_mem) {
+      FREE_CONN( cp ) ;
+   }
+}
+
+/* This returns a pointer to a local static stack variable.
+ * The behavior is a remnant of inet_ntoa() behavior.
+ */ 
+const char *conn_addrstr( const connection_s *cp )
+{
+   static char name[NI_MAXHOST];
+   unsigned int len = 0;
+
+   if( !M_IS_SET( (cp)->co_flags, COF_HAVE_ADDRESS ) )
+      return "<no address>";
+
+   if( cp->co_remote_address.sa.sa_family == AF_INET ) 
+      len = sizeof(struct sockaddr_in);
+   else if( cp->co_remote_address.sa.sa_family == AF_INET6 )
+      len = sizeof(struct sockaddr_in6);
+
+   if( getnameinfo( &cp->co_remote_address.sa, len,
+         name, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ) ) {
+      return "<no address>";
+   }
+   return name;
+}
+
+void conn_dump( const connection_s *cp, int fd )
+{
+   const char *name = conn_addrstr( cp );
+
+   tabprint( fd, 1, "service = %s\n", SVC_ID( cp->co_sp ) ) ;
+   tabprint( fd, 1, "descriptor = %d\n", cp->co_descriptor ) ;
+#if defined(__GNUC__) && !defined(__arch64__) && !defined(__alpha__)
+   tabprint( fd, 1, "flags = %#llx\n", cp->co_flags ) ;
+#else
+   tabprint( fd, 1, "flags = %#lx\n", cp->co_flags ) ;
+#endif
+   tabprint( fd, 1, "remote_address = %s,%d\n", name,
+                              ntohs( cp->co_remote_address.sa_in.sin_port ) ) ;
+}
+
diff --git a/xinetd/connection.h b/xinetd/connection.h
new file mode 100644 (file)
index 0000000..dda823f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+/*
+ * $Id: connection.h,v 1.4 2003/06/23 13:46:37 steveg Exp $
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+#if defined( HAVE_ARPA_INET_H )
+#include <arpa/inet.h>
+#endif
+#include <string.h>
+
+#include "mask.h"
+#include "service.h"
+#include "defs.h"
+#include "msg.h"
+#include "sio.h"
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a) \
+   ((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+   (((uint32_t *) (a))[2] == htonl (0xffff)))
+#endif
+#ifndef IN6_IS_ADDR_V4COMPAT
+#define IN6_IS_ADDR_V4COMPAT(a) \
+   ((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+   (((uint32_t *) (a))[2] == 0) && (ntohl (((uint32_t *) (a))[3]) > 1))
+#endif
+
+#define MAX_ALTERNATIVES            3
+
+/* Connection flags */
+#define COF_HAVE_ADDRESS            1
+#define COF_NEW_DESCRIPTOR          2
+
+struct connection
+{
+   struct service        *co_sp ;
+   int                   co_descriptor ;
+   mask_t                co_flags ;
+   union xsockaddr       co_remote_address ;
+} ;
+
+#define CONN_CLOSE( cp ) { Sclose( (cp)->co_descriptor ); (cp)->co_descriptor = -1; }
+
+#define COP( p )       ((connection_s *)(p))
+#define CONN_NULL      COP( NULL )
+
+/*
+ * Field access macros
+ */
+#define CONN_DESCRIPTOR( cp )       (cp)->co_descriptor
+#define CONN_SERVICE( cp )          (cp)->co_sp
+#define CONN_SET_FLAG( cp, flag )   M_SET( (cp)->co_flags, flag )
+#define CONN_SET_DESCRIPTOR( cp, fd )   (cp)->co_descriptor = (fd)
+
+#define CONN_SETADDR( cp, sinp )               \
+   {                        \
+      CONN_SET_FLAG( cp, COF_HAVE_ADDRESS ) ;         \
+      memcpy(((cp)->co_remote_address.pad), sinp, sizeof(*sinp) ); \
+   }
+
+#define CONN_ADDRESS( cp )                     \
+   (                           \
+      M_IS_SET( (cp)->co_flags, COF_HAVE_ADDRESS )         \
+         ? &((cp)->co_remote_address.sa)    \
+         : SA(NULL)               \
+   )
+#define CONN_XADDRESS( cp )                     \
+   (                           \
+      M_IS_SET( (cp)->co_flags, COF_HAVE_ADDRESS )         \
+         ? &((cp)->co_remote_address)    \
+         : NULL               \
+   )
+
+connection_s *conn_new(struct service *sp);
+void conn_free(connection_s *cp, int);
+void conn_dump(const connection_s *cp,int fd);
+const char *conn_addrstr( const connection_s *cp );
+
+#endif   /* CONNECTION_H */
+
diff --git a/xinetd/defs.h b/xinetd/defs.h
new file mode 100644 (file)
index 0000000..d19699c
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef DEFS_H
+#define DEFS_H
+
+/*
+ * $Id: defs.h,v 1.3 2005/03/29 15:50:34 bbraun Exp $
+ */
+
+
+#include "config.h"
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+union xsockaddr {
+   struct sockaddr     sa;
+   struct sockaddr_in  sa_in;
+   struct sockaddr_in6 sa_in6;
+   char                pad[128];
+};
+
+#ifndef FALSE
+#define FALSE                           0
+#define TRUE                            1
+#endif
+
+#define NUL                             '\0'
+
+#define ES_NOMEM                        "out of memory"
+
+#define INT_NULL                        ((int *)0)
+#define CHAR_NULL                       ((char *)0)
+#define VOID_NULL                       ((void *)0)
+#define FD_SET_NULL                     ((fd_set *)0)
+#define RUSAGE_NULL                     ((struct rusage *)0)
+#define TIMEVAL_NULL                    ((struct timeval *)0)
+
+#define EQ( s1, s2 )          ( strcasecmp( s1, s2 ) == 0 )
+#define CLEAR( x )            (void) memset( (char *)&(x), 0, sizeof( x ) )
+/* Apparently, some tcp wrapper header files export an SA definition.
+ * make sure we use ours instead of some other one.
+ */
+#undef SA
+
+#define SA( p )               ( (struct sockaddr *) (p) )
+#define SAIN( p )             ( (struct sockaddr_in *) (p) )
+#define SAIN6( p )            ( (struct sockaddr_in6 *) (p) )
+#define NEW( type )           (type *) malloc( sizeof( type ) )
+#define FREE( p )             (void) free( (char *)(p) )
+
+/*
+ * Value for unlimited server instances
+ */
+#define UNLIMITED                  (-1)
+
+/*
+ * We pass to the child the descriptors 0..MAX_PASS_FD
+ */
+#define MAX_PASS_FD                2
+
+/*
+ * Service port for the identification service
+ */
+#define IDENTITY_SERVICE_PORT      113
+
+/*
+ * This is the signal sent to interceptor processes to tell them
+ * to stop intercepting
+ */
+#define INTERCEPT_SIG              SIGUSR1
+
+/*
+ * This is how many descriptors we reserve for ourselves:
+ *
+ *      3    for stdin, stdout, stderr
+ *      1    for syslog/debug
+ *
+ * For the rest we just need to reserve the maximum of each category.
+ *
+ *   1    for doing accepts
+ *   1    for registering rpc services (initialization phase)
+ *   4    for reading the configuration file during reconfiguration
+ *      1 for the configuration file
+ *      1 for /etc/passwd
+ *      1 for /etc/group
+ *      1 for /etc/services, /etc/protocols, /etc/rpc
+ *      NOTE: We need only 1 descriptor for the last 3 files because
+ *         the functions get{serv,proto,rpc}byname close the
+ *         respective files after accessing them.
+ *      1    for dumping the internal state
+ *      1   for talking to the portmapper (reconfiguration phase)
+ *      1   for doing identification
+ *
+ * NOTE: we assume that the socket used for pmap_{set,unset} is closed
+ *      after the operation is completed. If it stays open, then we
+ *      need to increase DESCRIPTORS_RESERVED.
+ */
+#define DESCRIPTORS_RESERVED         8
+
+/*
+ * Used for listen(2)
+ */
+#define LISTEN_BACKLOG               64
+
+/*
+ * When explicit values are given for enum's, that is because the structures 
+ * that the enum's are in may be initialized by a memory clear operation.
+ */
+
+typedef enum { FAILED = 0, OK } status_e ;
+typedef enum { NO = 0, YES } boolean_e ;
+
+/*
+ * Possible outcomes of an identification attempt
+ */
+typedef enum
+   {
+      IDR_OK,
+      IDR_NOSERVER,
+      IDR_TIMEDOUT,
+      IDR_RESPERR,
+      IDR_BADRESP,
+      IDR_ERROR
+   } idresult_e ;
+
+typedef int bool_int ;
+
+typedef void (*voidfunc)() ;
+typedef status_e (*statfunc)() ;
+
+
+/*
+ * A name-value list is exactly what its name says.
+ * The functions nv_get_name() and nv_get_value() return a pointer to
+ * the entry with the specified value or name respectively.
+ * The list ends when an antry with a NULL name is encountered.
+ * The value field of that entry is treated in a special manner: if it
+ * is non-zero, it is assumed that there exists one more entry whose
+ * name field will be returned by the nv_get_name function if it can't
+ * find an entry whose value field is equal to its 2nd parameter.
+ * If the value field of the NULL entry is 0, then nv_get_name() will
+ * return NULL.
+ */
+struct name_value
+{
+   const char   *name ;
+   int          value ;
+} ;
+
+struct protocol_name_value
+{
+   char   *name ;
+   int    value ;
+} ;
+
+struct debug
+{
+   bool_int on ;
+   int fd ;
+} ;
+
+/* This is some forward prototypes to work out a couple
+ * circular dependencies in the data structures */
+struct service;
+struct server;
+struct connection;
+typedef struct connection connection_s ;
+
+
+extern struct debug debug ;
+
+#endif   /* DEFS_H */
diff --git a/xinetd/env.c b/xinetd/env.c
new file mode 100644 (file)
index 0000000..89a06c0
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <syslog.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "pset.h"
+#include "env.h"
+#include "msg.h"
+
+extern char **environ ;
+env_h std_env ;            /* created from environ */
+
+status_e initenv(void)
+{
+   std_env = env_make( environ ) ;
+   return( ( std_env == NULL ) ? FAILED : OK ) ;
+}
+
+static status_e make_env_with_strings(struct environment *, env_h, pset_h);
+static status_e make_env_from_vars(struct environment *, env_h, pset_h) ;
+static status_e update_env_with_strings(env_h, pset_h) ;
+
+
+status_e setup_environ( struct service_config *scp, struct service_config *def )
+{
+   struct environment   *ep = SC_ENV( scp ) ;
+
+   if ( ! SC_SPECIFIED( scp, A_PASSENV ) )
+   {
+      if ( ! SC_SPECIFIED( def, A_PASSENV ) )
+      {
+         if ( ! SC_SPECIFIED( scp, A_ENV ) )
+         {
+            ep->env_type = STD_ENV ;
+            ep->env_handle = std_env ;
+            return( OK ) ;
+         }
+         else
+            return( 
+               make_env_with_strings( ep, std_env, SC_ENV_VAR_DEFS(scp) ) ) ;
+      }
+      else   /* SC_SPECIFIED( def, A_PASSENV ) */
+      {
+         struct environment *dep = SC_ENV( def ) ;
+
+         if ( dep->env_type == NO_ENV &&
+                  make_env_from_vars( dep, std_env,
+                                 SC_PASS_ENV_VARS(def) ) == FAILED )
+            return( FAILED ) ;
+
+         if ( ! SC_SPECIFIED( scp, A_ENV ) )
+         {
+            ep->env_type = DEF_ENV ;
+            ep->env_handle = dep->env_handle ;
+            return( OK ) ;
+         }
+         else
+            return( make_env_with_strings( ep, 
+                           dep->env_handle, SC_ENV_VAR_DEFS(scp) ) ) ;
+      }
+   }
+   else   /* SC_SPECIFIED( scp, A_PASSENV ) */
+   {
+      if ( make_env_from_vars( ep, std_env, SC_PASS_ENV_VARS(scp) ) == FAILED )
+         return( FAILED ) ;
+
+      if ( ! SC_SPECIFIED( scp, A_ENV ) )
+         return( OK ) ;
+      else
+      {
+         if ( update_env_with_strings( 
+                     ep->env_handle, SC_ENV_VAR_DEFS(scp) ) == FAILED )
+         {
+            env_destroy( ep->env_handle ) ;
+            return( FAILED ) ;
+         }
+         return( OK ) ;
+      }
+   }
+}
+
+
+/*
+ * Create a new environment from environ and env_strings
+ * env_strings contains strings of the form "var=value"
+ */
+static status_e make_env_with_strings( struct environment *ep, 
+                                        env_h env, 
+                                        pset_h env_strings )
+{
+   env_h      new_env ;
+   const char *func = "make_env_with_strings" ;
+
+   if ( ( new_env = env_create( env ) ) == ENV_NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+
+   if ( update_env_with_strings( new_env, env_strings ) == FAILED )
+   {
+      env_destroy( new_env ) ;
+      return( FAILED ) ;
+   }
+
+   ep->env_type = CUSTOM_ENV ;
+   ep->env_handle = new_env ;
+   return( OK ) ;
+}
+
+
+static status_e make_env_from_vars( struct environment *ep, 
+                                     env_h env, 
+                                     pset_h vars )
+{
+   env_h               new_env ;
+   char               *varname ;
+   unsigned            u ;
+   const char         *func = "make_env_from_vars" ;
+
+   if ( ( new_env = env_create( ENV_NULL ) ) == ENV_NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   
+   for ( u = 0 ; u < pset_count( vars ) ; u++ )
+   {
+      varname = (char *) pset_pointer( vars, u ) ;
+      if ( env_addvar( new_env, env, varname ) == ENV_ERR )
+         switch ( env_errno )
+         {
+            case ENV_EBADVAR:
+               msg( LOG_ERR, func, "Unknown variable %s", varname ) ;
+               break ;
+            
+            case ENV_ENOMEM:
+               out_of_memory( func ) ;
+               env_destroy( new_env ) ;
+               return( FAILED ) ;
+         }
+   }
+
+   ep->env_type = CUSTOM_ENV ;
+   ep->env_handle = new_env ;
+   return( OK ) ;
+}
+
+
+static status_e update_env_with_strings( env_h env, pset_h strings )
+{
+   unsigned u ;
+   const char *func = "update_env_with_strings" ;
+
+   for ( u = 0 ; u < pset_count( strings ) ; u++ )
+   {
+      char *p = (char *) pset_pointer( strings, u ) ;
+
+      if ( env_addstr( env, p ) == ENV_ERR )
+         switch ( env_errno )
+         {
+            case ENV_ENOMEM:
+               out_of_memory( func ) ;
+               return( FAILED ) ;
+            
+            case ENV_EBADSTRING:
+               msg( LOG_ERR, func, "Bad environment string: %s", p ) ;
+               break ;
+         }
+   }
+   return( OK ) ;
+}
+
diff --git a/xinetd/env.h b/xinetd/env.h
new file mode 100644 (file)
index 0000000..541a6b4
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef X_ENV_H
+#define X_ENV_H
+
+#include "m_env.h"
+#include "defs.h"
+#include "sconf.h"
+
+extern env_h std_env;
+status_e initenv(void);
+status_e setup_environ(struct service_config *scp,struct service_config *def);
+
+#endif
diff --git a/xinetd/ident.c b/xinetd/ident.c
new file mode 100644 (file)
index 0000000..c526fcc
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <syslog.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#include "str.h"
+#include "ident.h"
+#include "msg.h"
+#include "server.h"
+#include "connection.h"
+#include "util.h"
+#include "log.h"
+#include "sconst.h"
+
+
+static char *get_line( int sd, register char *buf, unsigned bufsize );
+static char *verify_line( char *line, unsigned local_port, unsigned remote_port );
+
+
+#define IBUFSIZE      1024      /* RFC-1413 suggests 1000 */
+
+#define START_TIMER( t )   (void) alarm( t )
+#define STOP_TIMER()      (void) alarm( 0 )
+
+
+
+static sigjmp_buf env ;
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+static void sigalrm_handler(int signum)
+{
+   siglongjmp( env, 1 ) ;
+}
+
+
+/*
+ * This function always runs in a forked process.
+ */
+idresult_e log_remote_user( const struct server *serp, unsigned timeout )
+{
+   static char         buf[ IBUFSIZE ] ;
+   int                 cc ;
+   union xsockaddr     sin_local, sin_remote, sin_contact, sin_bind;
+   volatile unsigned   local_port;
+   volatile unsigned   remote_port;
+   int                 sd ;
+   socklen_t           sin_len ;
+   char               *p ;
+   const char         *func = "log_remote_user" ;
+
+   if ( timeout && signal( SIGALRM, sigalrm_handler ) == SIG_ERR )
+   {
+      msg( LOG_ERR, func, "signal: %m" ) ;
+      return( IDR_ERROR ) ;
+   }
+
+   /*
+    * Determine local and remote addresses
+    */
+   sin_len = sizeof( sin_local ) ;
+   if ( getsockname( SERVER_FD( serp ), &sin_local.sa, &sin_len ) == -1 )
+   {
+      msg( LOG_ERR, func, "(%d) getsockname: %m", getpid() ) ;
+      return( IDR_ERROR ) ;
+   }
+
+   if ( CONN_XADDRESS( SERVER_CONNECTION( serp ) ) == NULL )
+   {
+      /*
+       * This shouldn't happen since identification only works for
+       * connection-based services.
+       */
+      msg( LOG_ERR, func, "connection has no address" ) ;
+      return( IDR_ERROR ) ;
+   }
+
+   CLEAR( sin_contact );
+   sin_remote = *CONN_XADDRESS( SERVER_CONNECTION( serp ) ) ;
+   sin_contact = sin_remote;
+   memcpy( &sin_bind, &sin_local, sizeof(sin_bind) ) ;
+   local_port = 0;
+   remote_port = 0;
+   if( sin_remote.sa.sa_family == AF_INET ) {
+      local_port = ntohs( sin_local.sa_in6.sin6_port ) ;
+      remote_port = ntohs( sin_remote.sa_in6.sin6_port ) ;
+      sin_contact.sa_in6.sin6_port = htons( IDENTITY_SERVICE_PORT ) ;
+      sin_bind.sa_in.sin_port = 0 ;
+   } else if( sin_remote.sa.sa_family == AF_INET6 ) {
+      local_port = ntohs( sin_local.sa_in.sin_port ) ;
+      remote_port = ntohs( sin_remote.sa_in.sin_port ) ;
+      sin_contact.sa_in.sin_port = htons( IDENTITY_SERVICE_PORT ) ;
+      sin_bind.sa_in6.sin6_port = 0 ;
+   }
+
+   /*
+    * Create a socket, bind it, and set the close-on-exec flag on the
+    * descriptor. We set the flag in case we are called as part of a 
+    * successful attempt to start a server (i.e. execve will follow). 
+    * The socket must be bound to the receiving address or ident might 
+    * fail for multi-homed hosts.
+    */
+   sd = socket( sin_remote.sa.sa_family, SOCK_STREAM, 0 ) ;
+   if ( sd == -1 )
+   {
+      msg( LOG_ERR, func, "socket creation: %m" ) ;
+      return( IDR_ERROR ) ;
+   }
+   if ( bind(sd, &sin_bind.sa, sizeof(sin_bind.sa)) == -1 )
+   { 
+      msg( LOG_ERR, func, "socket bind: %m" ) ;
+      (void) Sclose( sd ) ;
+      return( IDR_ERROR ) ;
+   }
+   if ( fcntl( sd, F_SETFD, FD_CLOEXEC ) == -1 )
+   {
+      msg( LOG_ERR, func, "fcntl F_SETFD: %m" ) ;
+      (void) Sclose( sd ) ;
+      return( IDR_ERROR ) ;
+   }
+
+   if ( timeout ) {
+      if ( sigsetjmp( env, 1 ) == 0 )
+         START_TIMER( timeout ) ;
+      else {
+         Sclose( sd ) ;
+         return( IDR_TIMEDOUT ) ;
+      }
+   }
+
+   if ( connect( sd, &sin_contact.sa, sizeof( sin_contact ) ) == -1 )
+   {
+      if ( timeout ) {
+         STOP_TIMER() ;
+         signal ( SIGALRM, SIG_DFL ) ;
+      }
+      Sclose( sd );
+      return( IDR_NOSERVER ) ;
+   }
+
+   cc = strx_nprint( buf, sizeof( buf ), 
+      "%d,%d\r\n", remote_port, local_port ) ;
+   if ( write_buf( sd, buf, cc ) == FAILED )
+   {
+      if ( timeout ) {
+         STOP_TIMER() ;
+         signal ( SIGALRM, SIG_DFL ) ;
+      }
+      Sclose( sd );
+      return( IDR_ERROR ) ;
+   }
+
+   p = get_line( sd, buf, sizeof( buf ) ) ;
+
+   if ( timeout ) {
+      STOP_TIMER() ;
+      signal ( SIGALRM, SIG_DFL ) ;
+   }
+
+   if ( p == NULL ) {
+      Sclose( sd );
+      return( IDR_RESPERR ) ;
+   }
+   
+   /*
+    * Verify that the received line is OK
+    */
+   if ( ( p = verify_line( buf, local_port, remote_port ) ) == NULL )
+   {
+      msg(LOG_ERR, func, "Bad line received from identity server at %s: %s",
+         xaddrname( &sin_remote ), buf ) ;
+      Sclose( sd );
+      return( IDR_BADRESP ) ;
+   }
+
+   svc_logprint( SERVER_CONNSERVICE( serp ), USERID_ENTRY, "%s", p ) ;
+   return( IDR_OK ) ;
+}
+
+
+static char *verify_line( char *line, 
+                           unsigned local_port, 
+                           unsigned remote_port )
+{
+   char   *p ;
+   char   *start = line ;
+   int     port;
+
+   /*
+    * Verify port numbers
+    */
+   p = strchr( start, ',' ) ;
+   if ( p == NULL )
+      return( NULL ) ;
+   *p = NUL ;
+   if ( parse_base10( start, &port ) ||
+        port < 0 || (unsigned)port != remote_port ) {
+      *p = ',';
+      return( NULL ) ;
+   }
+   *p = ',' ;
+   
+   start = p+1 ;
+   p = strchr( start, ':' ) ;
+   if ( p == NULL )
+      return( NULL ) ;
+   *p = NUL ;
+   if ( parse_base10( start, &port ) ||
+        port < 0 || (unsigned)port != local_port ) {
+      *p = ':';
+      return( NULL ) ;
+   }
+   *p = ':';
+   
+   /*
+    * Look for the 'USERID' string
+    */
+   {
+      const char *line_id = "USERID" ;
+      unsigned int line_id_len = strlen( line_id ) ;
+
+      start = p+1 ;
+      for ( p = start ; isspace( *p ) ; p++ ) ;
+      if ( *p == NUL )
+         return( NULL ) ;
+      start = p ;
+      if ( strncmp( start, line_id, line_id_len ) != 0 )
+         return( NULL ) ;
+      start += line_id_len ;      /* skip it */
+   }
+
+   for ( p = start ; isspace( *p ) ; p++ ) ;      /* skip any white-space */
+   if ( *p != ':' )
+      return( NULL ) ;
+   for ( p++ ; isspace( *p ) ; p++ ) ;
+   if ( *p == NUL )
+      return( NULL ) ;
+   return( p ) ;
+}
+   
+
+/*
+ * Get a line terminated by CR-LF.
+ * Replace the CR-LF with NUL.
+ */
+static char *get_line( int sd, char *buf, unsigned bufsize )
+{
+   int     size ;
+   int     cc ;
+   char   *p ;
+   char   *s ;
+   const char *func = "get_line" ;
+
+   for ( p = buf, size = bufsize ; size > 0 ; p += cc, size -= cc )
+   {
+      cc = read( sd, p, size ) ;
+      if ( cc == -1 ) {
+         if ( errno == EINTR )
+         {
+            cc = 0 ;
+            continue ;
+         }
+         else
+         {
+            msg( LOG_ERR, func, "read: %m" ) ;
+            return( CHAR_NULL ) ;
+         }
+      }
+
+      if ( cc == 0 )
+      {
+         msg( LOG_ERR, func, "identd server reply missing ending CR-LF" ) ;
+         return( CHAR_NULL ) ;
+      }
+      for ( s = p ; s < p + cc ; s++ )
+      {
+         if ( (*s == '\n') && (s != buf) && (*(s-1) == '\r') )
+         {
+            *(s-1) = NUL ;
+            return( buf ) ;
+         }
+      }
+   }
+   msg( LOG_ERR, func, "Too much input from identity server" ) ;
+   return( CHAR_NULL ) ;
+}
+
+
+const char *idresult_explain( idresult_e result )
+{
+   const char *reason = "UNKNOWN" ;
+
+   switch ( result )
+   {
+      case IDR_OK:
+         reason = "no error" ;
+         break ;
+
+      case IDR_NOSERVER:
+         reason = "no server" ;
+         break ;
+
+      case IDR_TIMEDOUT:
+         reason = "timeout" ;
+         break ;
+      
+      case IDR_ERROR:
+         reason = "system error" ;
+         break ;
+      
+      case IDR_RESPERR:
+         reason = "error while receiving response" ;
+         break ;
+      
+      case IDR_BADRESP:
+         reason = "bad response" ;
+         break ;
+   }
+   return( reason ) ;
+}
+
diff --git a/xinetd/ident.h b/xinetd/ident.h
new file mode 100644 (file)
index 0000000..aba1719
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef IDENT_H
+#define IDENT_H
+
+#include "defs.h"
+
+idresult_e log_remote_user(const struct server *serp,unsigned timeout);
+const char *idresult_explain(idresult_e result);
+
+#endif
+
diff --git a/xinetd/includedir.c b/xinetd/includedir.c
new file mode 100644 (file)
index 0000000..0f3be61
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#include "config.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pset.h"
+#include "str.h"
+#include "includedir.h"
+#include "msg.h"
+#include "parse.h"
+#include "sio.h"
+
+#if !defined(NAME_MAX)
+   #ifdef FILENAME_MAX
+   #define NAME_MAX FILENAME_MAX
+   #else
+   #define NAME_MAX 256
+   #endif
+#endif
+
+static int compfunc( const void *_a, const void *_b )
+{
+   char **a = (char **)_a;
+   char **b = (char **)_b;
+
+   if( a == NULL || a[0] == NULL )
+      return -1;
+   if( b == NULL || b[0] == NULL )
+      return 1;
+   return strcmp(a[0], b[0]);
+}
+
+void handle_includedir(const char *service_name, struct configuration *confp)
+{
+   char *filename;
+   pset_h dir_list;
+   DIR *dirfp;
+   struct dirent *direntry;
+   char *storename;
+   struct stat sb;
+   int u, incfd, len_sn;
+   const char *func = "handle_includedir";
+
+   if( service_name == NULL )
+      return;
+
+   dir_list = pset_create(0, 0);
+   if( dir_list == NULL )
+      return;
+
+   len_sn = strlen(service_name);
+   filename = (char *)malloc(len_sn + NAME_MAX + 2);
+   if (! filename) {
+      parsemsg( LOG_ERR, func, ES_NOMEM );
+      return;
+   }
+   errno = 0;
+   dirfp = opendir(service_name);
+   if (! dirfp) {
+      parsemsg( LOG_ERR, func, "Unable to read included directory: %s", service_name);
+      free(filename);
+      return;
+   }
+   /* Get the list of files in the directory */
+   while ((direntry = readdir(dirfp)) != 0) {
+      storename = new_string(direntry->d_name);
+      if( storename == NULL ) {
+         parsemsg( LOG_ERR, func, ES_NOMEM );
+         free( filename );
+         return;
+      }
+      pset_add(dir_list, storename);
+   }
+   closedir(dirfp);
+
+   /* Sort the list using "compfunc" */
+   pset_sort(dir_list, compfunc);
+
+   /* Now, traverse the list in alphabetic order 
+    * (as determined by strcmp).
+    */
+   for( u = 0; (unsigned)u < pset_count(dir_list); u++ ) {
+      storename = pset_pointer(dir_list, u);
+
+      /* Don't try to parse any files containing a dot ('.')
+      * or ending with a tilde ('~'). This catches the case of 
+      * '.' and '..', as well as preventing the parsing of 
+      * many editor files, temporary files and those saved by RPM
+      * package upgrades.
+      */
+      if ( !storename[0] /* Shouldn't happen */ || 
+                      strchr(storename, '.') ||
+                      storename[strlen(storename)-1] == '~') {
+         pset_remove(dir_list, storename);
+         free(storename);
+         u--;
+         continue;
+      }
+
+      strx_sprint(filename, len_sn+NAME_MAX+1, "%s/%s",
+         service_name, storename);
+
+      if( stat(filename, &sb) < 0 ) {
+         parsemsg( LOG_ERR, func, "Unable to stat includedir file %s", filename);
+         pset_remove(dir_list, storename);
+         free(storename);
+         u--;
+         continue;
+      }
+
+      /* Only open it if it's a regular file. */
+      if( !S_ISREG(sb.st_mode) ) {
+          msg( LOG_ERR, func,
+         "%s is not a regular file. It is being skipped.",
+         filename );
+          pset_remove(dir_list, storename);
+          free(storename);
+          u--;
+          continue;
+      }
+      incfd = open(filename, O_RDONLY);
+      if( incfd < 0 ) {
+         parsemsg( LOG_ERR, func, "Unable to open included configuration file: %s", filename);
+         pset_remove(dir_list, storename);
+         free(storename);
+         u--;
+         continue;
+      }
+      parsemsg( LOG_DEBUG,func,"Reading included configuration file: %s",filename);
+      parse_conf_file(incfd, confp, filename);
+
+      /* 
+       * parse_conf_file eventually calls Srdline, try Sclosing to 
+       * unmmap memory. 
+       */
+      Sclose(incfd);
+      pset_remove(dir_list, storename);
+      free(storename);
+      u--;
+   }
+   if ( errno != 0) {
+      parsemsg( LOG_ERR, func, "Error reading included directory: %s", service_name);
+   }
+   pset_destroy(dir_list);
+   free(filename);
+}
diff --git a/xinetd/includedir.h b/xinetd/includedir.h
new file mode 100644 (file)
index 0000000..b79a830
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef INCLUDEDIR_H
+#define INCLUDEDIR_H
+
+#include "conf.h"
+
+void handle_includedir(const char *service_name,struct configuration *confp);
+
+#endif
diff --git a/xinetd/inet.c b/xinetd/inet.c
new file mode 100644 (file)
index 0000000..1cb2ba2
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#include "config.h"
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <syslog.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#include <limits.h>
+
+#include "str.h"
+#include "inet.h"
+#include "msg.h"
+#include "parse.h"
+#include "parsesup.h"
+#include "nvlists.h"
+
+static int get_next_inet_entry( int fd, pset_h sconfs, 
+                          struct service_config *defaults);
+
+void parse_inet_conf_file( int fd, struct configuration *confp )
+{
+   pset_h sconfs                         = CNF_SERVICE_CONFS( confp );
+   struct service_config *default_config = CNF_DEFAULTS( confp );
+   
+   line_count = 0;
+
+   for( ;; )
+   {   
+      if (get_next_inet_entry(fd, sconfs, default_config) == -2)
+         break;
+   }
+}
+
+static int get_next_inet_entry( int fd, pset_h sconfs, 
+                          struct service_config *defaults)
+{
+   char *p;
+   str_h strp;
+   char *line = next_line(fd);
+   struct service_config *scp;
+   unsigned u, i;
+   const char *func = "get_next_inet_entry";
+   char *name = NULL, *rpcvers = NULL, *rpcproto = NULL;
+   char *group, *proto, *stype;
+   const struct name_value *nvp;
+   struct protoent *pep ;
+   struct passwd *pw ;
+   struct group *grp ;
+   const char *dot = ".";
+   const char *slash = "/";
+   pset_h args;
+   
+   if( line == CHAR_NULL )
+      return -2;
+
+   strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
+   if( strp == NULL )
+   {
+      parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ;
+      return( -1 ) ;
+   }
+
+   if( (args = pset_create(10,10)) == NULL )
+   {
+      out_of_memory(func);
+      return -1;
+   }
+
+   /* Break the line into components, based on spaces */
+   while( (p = str_component( strp )) )
+   {
+      if( pset_add(args, p) == NULL )
+      {
+         parsemsg( LOG_CRIT, func, ES_NOMEM );
+         pset_destroy(args);
+         return -1;
+      }
+   }
+   str_endparse( strp );
+
+   /* get the service name */
+   name = new_string((char *)pset_pointer( args, 0 ));
+   if( name == NULL ) {
+      parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" );
+      pset_destroy(args);
+      return -1;
+   }
+
+   /* Check to find the '/' for specifying RPC version numbers */
+   if( (rpcvers = strstr(name, slash)) != NULL ) {
+      *rpcvers = '\0';
+      rpcvers++;
+   }
+
+   scp = sc_alloc( name );
+   if( scp == NULL )
+   {
+      pset_destroy(args);
+      free( name );
+      return -1;
+   }
+   /*
+    * sc_alloc makes its own copy of name. At this point, sc_alloc worked
+    * so we will free our copy to avoid leaks.
+    */
+   free( name );
+
+   /* Replicate inetd behavior in this regard.  Also makes sure the
+    * service actually works on system where setgroups(0,NULL) doesn't
+    * work.
+    */
+   SC_GROUPS(scp) = YES;
+   SC_SPECIFY( scp, A_GROUPS );
+
+   /* Get the socket type (stream dgram) */
+   stype = (char *)pset_pointer(args, 1);
+   if( stype == NULL ) {
+      parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" );
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+   nvp = nv_find_value( socket_types, stype );
+   if( nvp == NULL )
+   {
+      parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p);
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+
+   SC_SOCKET_TYPE(scp) = nvp->value;
+
+   /* Get the protocol type */
+   proto = (char *)pset_pointer(args,2);
+   if( strstr(proto, "rpc") != NULL )
+   {
+      int rpcmin, rpcmax;
+      struct rpc_data *rdp = SC_RPCDATA( scp ) ;
+
+      if( rpcvers == NULL ) {
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+         /* uh oh */
+      }
+
+      p = strchr(rpcvers, '-');
+      if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) {
+         if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) {
+            pset_destroy(args);
+            sc_free(scp);
+            return -1;
+         }
+      } else {
+         if( parse_base10(rpcvers, &rpcmin) ) {
+            pset_destroy(args);
+            sc_free(scp);
+            return -1;
+         }
+
+         rpcmax = rpcmin;
+      }
+
+      /* now have min and max rpc versions */
+      rdp->rd_min_version = rpcmin;      
+      rdp->rd_max_version = rpcmax;      
+
+      rpcproto = strstr(proto, slash);
+      if( rpcproto == NULL ) {
+         parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" );
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+      *rpcproto = '\0';
+      rpcproto++;
+      proto = rpcproto;
+
+      /* Set the RPC type field */
+      nvp = nv_find_value( service_types, "RPC" );
+      if ( nvp == NULL )
+      {
+         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+
+      M_SET(SC_TYPE(scp), nvp->value);
+   }
+   if ( ( pep = getprotobyname( proto ) ) == NULL )
+   {
+      parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols",
+               proto ) ;
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+
+   SC_PROTONAME(scp) = new_string( proto ) ;
+   if ( SC_PROTONAME(scp) == NULL )
+   {
+      out_of_memory( func ) ;
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+   SC_PROTOVAL(scp) = pep->p_proto;
+   SC_SPECIFY(scp, A_PROTOCOL);
+
+   /* Get the wait attribute */
+   p = (char *)pset_pointer(args, 3);
+   if ( p == NULL ) {
+      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" );
+      sc_free(scp);
+      return -1;
+   }
+   if ( EQ( p, "wait" ) )
+      SC_WAIT(scp) = YES ;
+   else if ( EQ( p, "nowait" ) )
+      SC_WAIT(scp) = NO ;
+   else
+      parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ;
+
+   /* Get the user to run as */
+   p = (char *)pset_pointer(args, 4);
+   if ( p == NULL ) {
+      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
+      sc_free(scp);
+      return -1;
+   }
+   if( (group = strstr(p, dot)) )
+   {
+      *group = '\0';
+      group++;
+   
+      grp = (struct group *)getgrnam( (char *)group ) ;
+      if ( grp == NULL )
+      {
+         parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }   
+
+      SC_GID(scp) = ((struct group *)grp)->gr_gid;
+      SC_SPECIFY( scp, A_GROUP );
+   }
+
+   pw = getpwnam( p );
+   if ( pw == NULL )
+   {
+      parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ;
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+   str_fill( pw->pw_passwd, ' ' );
+   SC_UID(scp) = pw->pw_uid;
+   SC_USER_GID(scp) = pw->pw_gid;
+
+   /* Get server name, or flag as internal */
+   p = (char *)pset_pointer(args, 5);
+   if ( p == NULL ) {
+      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
+      sc_free(scp);
+      return -1;
+   }
+   if( EQ( p, "internal" ) ) 
+   {
+      nvp = nv_find_value( service_types, "INTERNAL" );
+      if ( nvp == NULL )
+      {
+         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+
+      M_SET(SC_TYPE(scp), nvp->value);
+
+      if( EQ( SC_NAME(scp), "time" ) ) {
+         if( EQ( proto, "stream" ) )
+            SC_ID(scp) = new_string("time-stream");
+         else
+            SC_ID(scp) = new_string("time-dgram");
+      }
+
+      if( EQ( SC_NAME(scp), "daytime" ) ) {
+         if( EQ( proto, "stream" ) )
+            SC_ID(scp) = new_string("daytime-stream");
+         else
+            SC_ID(scp) = new_string("daytime-dgram");
+      }
+
+      if( EQ( SC_NAME(scp), "chargen" ) ) {
+         if( EQ( proto, "stream" ) )
+            SC_ID(scp) = new_string("chargen-stream");
+         else
+            SC_ID(scp) = new_string("chargen-dgram");
+      }
+
+      if( EQ( SC_NAME(scp), "echo" ) ) {
+         if( EQ( proto, "stream" ) )
+            SC_ID(scp) = new_string("echo-stream");
+         else
+            SC_ID(scp) = new_string("echo-dgram");
+      }
+
+      if( EQ( SC_NAME(scp), "discard" ) ) 
+      {
+         parsemsg(LOG_WARNING, func, 
+                 "inetd.conf - service discard not supported");
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+   }
+   else
+   {
+      SC_SERVER(scp) = new_string( p );
+      if ( SC_SERVER(scp) == NULL )
+      {
+         out_of_memory( func ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+      SC_SPECIFY( scp, A_SERVER);
+
+      /* Get argv */ 
+      SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1);
+
+      for( u = 0; u < pset_count(args)-6 ; u++ )
+      {
+         p = new_string((char *)pset_pointer(args, u+6));
+         if( p == NULL )
+         {
+            for ( i = 1 ; i < u ; i++ )
+               free( SC_SERVER_ARGV(scp)[i] );
+            free( SC_SERVER_ARGV(scp) );
+            pset_destroy(args);
+            sc_free(scp);
+            return -1;
+         }
+         SC_SERVER_ARGV(scp)[u] = p;
+      }
+      /* Set the reuse flag, as this is the default for inetd */
+      nvp = nv_find_value( service_flags, "REUSE" );
+      if ( nvp == NULL )
+      {
+         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+      M_SET(SC_XFLAGS(scp), nvp->value);
+
+      /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */
+      nvp = nv_find_value( service_flags, "NOLIBWRAP" );
+      if ( nvp == NULL )
+      {
+         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+      M_SET(SC_XFLAGS(scp), nvp->value);
+   
+      /* Set the NAMEINARGS flag, as that's the default for inetd */
+      nvp = nv_find_value( service_flags, "NAMEINARGS" );
+      if ( nvp == NULL )
+      {
+         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return (-1);
+      }
+      M_SET(SC_XFLAGS(scp), nvp->value);
+      SC_SPECIFY( scp, A_SERVER_ARGS );
+
+      if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
+         SC_PRESENT( scp, A_ID ) ;
+      else
+      {
+         out_of_memory( func ) ;
+         pset_destroy(args);
+         sc_free(scp);
+         return -1;
+      }
+   }
+   
+   SC_SPECIFY( scp, A_PROTOCOL );
+   SC_SPECIFY( scp, A_USER );
+   SC_SPECIFY( scp, A_SOCKET_TYPE );
+   SC_SPECIFY( scp, A_WAIT );
+
+   if( ! pset_add(sconfs, scp) )
+   {
+      out_of_memory( func );
+      pset_destroy(args);
+      sc_free(scp);
+      return -1;
+   }
+
+   pset_destroy(args);
+   parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp));
+   return 0;
+}
+
diff --git a/xinetd/inet.h b/xinetd/inet.h
new file mode 100644 (file)
index 0000000..3d87059
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef X_INET_H
+#define X_INET_H
+
+#include "pset.h"
+#include "sconf.h"
+#include "conf.h"
+
+void parse_inet_conf_file(int fd,struct configuration *confp);
+
+#endif
diff --git a/xinetd/init.c b/xinetd/init.c
new file mode 100644 (file)
index 0000000..f93cece
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <syslog.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "sio.h"
+#include "init.h"
+#include "defs.h"
+#include "msg.h"
+#include "signals.h"
+#include "env.h"
+#include "confparse.h"
+#include "options.h"
+#include "main.h"
+#include "xconfig.h"
+#include "special.h"
+#include "retry.h"
+#include "internals.h"
+#include "libportable.h"
+
+struct module
+{
+   const char *name ;
+   status_e (*initializer)() ;
+} ;
+
+
+
+static const struct module program_modules[] = 
+   {
+      { "signal",                       signal_init       },
+      { "environment",                  initenv           },
+      { CHAR_NULL,                      NULL              }
+   } ;
+
+
+static bool_int have_stderr ;
+
+#define STDERR_FD                  2
+
+static void set_fd_limit(void);
+
+/*
+ * This function is invoked when a system call fails during initialization.
+ * A message is printed to stderr, and the program is terminated
+ */
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+static void syscall_failed( const char *call )
+{
+   char *err ;
+
+   if ( have_stderr )
+   {
+      err = strerror(errno);
+      Sprint( STDERR_FD, "%s: %s failed: %s\n", program_name, call, err ) ;
+   }
+   exit( 1 ) ;
+}
+
+
+
+/*
+ * Close all descriptors except STDERR_FD. We need this to report
+ * errors and the process pid of the daemon.
+ * Open all descriptors in the range 0..MAX_PASS_FD (except STDERR_FD)
+ * to /dev/null.
+ * STDERR_FD should not be 0.
+ *
+ * msg() cannot be used from this function, as it has not been initialized yet.
+ */
+static void setup_file_descriptors(void)
+{
+   int   fd ;
+   int   new_fd ;
+   int   null_fd ;
+
+   if ( Smorefds(3) == SIO_ERR )
+   {
+      syscall_failed("Smorefds");
+      exit( 1 ) ;
+   }
+
+   set_fd_limit() ;
+
+   /*
+    * Close all unneeded descriptors
+    */
+   for ( fd = STDERR_FD + 1 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
+      if ( Sclose( fd ) && errno != EBADF )
+      {
+         syscall_failed("Sclose");
+         exit( 1 ) ;
+      }
+   
+   /*
+    * Check if the STDERR_FD descriptor is open.
+    */
+   new_fd = dup( STDERR_FD ) ;
+   if ( new_fd != -1 )
+   {
+      have_stderr = TRUE ;
+      (void) Sclose( new_fd ) ;
+   }
+
+   if ( ( null_fd = open( "/dev/null", O_RDONLY ) ) == -1 )
+      syscall_failed( "open of '/dev/null'" ) ;
+
+   for ( fd = 0 ; fd <= MAX_PASS_FD ; fd++ )
+   {
+      if ( have_stderr && fd == STDERR_FD )
+         continue ;
+      if ( fd != null_fd && dup2( null_fd, fd ) == -1 )
+         syscall_failed( "dup2" ) ;
+   }
+
+   if ( null_fd > MAX_PASS_FD )
+      (void) Sclose( null_fd ) ;
+}
+
+
+/* msg() cannot be used in this function, as it has not been initialized yet. */
+static void set_fd_limit(void)
+{
+#ifdef RLIMIT_NOFILE
+   struct rlimit rl ;
+   rlim_t maxfd ;
+    
+   /*
+    * Set the soft file descriptor limit to the hard limit.
+    */
+   if ( getrlimit( RLIMIT_NOFILE, &rl ) == -1 )
+   {
+      syscall_failed("getrlimit(RLIMIT_NOFILE)");
+      exit( 1 ) ;
+   }
+
+   maxfd = rl.rlim_max;
+   if ( rl.rlim_max == RLIM_INFINITY ) 
+      rl.rlim_max = FD_SETSIZE;
+
+   /* XXX: a dumb way to prevent fd_set overflow possibilities; the rest
+    * of xinetd should be changed to use an OpenBSD inetd-like fd_grow(). */
+   if ( rl.rlim_max > FD_SETSIZE )
+      rl.rlim_max = FD_SETSIZE;
+     
+   rl.rlim_cur = rl.rlim_max ;
+   if ( setrlimit( RLIMIT_NOFILE, &rl ) == -1 )
+   {
+      syscall_failed("setrlimit(RLIMIT_NOFILE)");
+      ps.ros.max_descriptors = FD_SETSIZE;
+      ps.ros.orig_max_descriptors = FD_SETSIZE;
+      return ;
+   }
+
+   ps.ros.orig_max_descriptors = maxfd ;
+   ps.ros.max_descriptors = rl.rlim_max ;
+#else      /* ! RLIMIT_NOFILE */
+   ps.ros.max_descriptors = getdtablesize() ;
+#endif   /* RLIMIT_NOFILE */
+}
+
+
+static void init_common( int argc, char *argv[] )
+{
+   const struct module *mp = NULL;
+   const char *func = "init_common" ;
+
+   /*
+    * Initialize the program state
+    */
+
+   ps.ros.Argv = argv ;
+   ps.ros.Argc = argc ;
+   ps.ros.is_superuser = ( geteuid() == 0 ) ;
+
+   /*
+    * Initialize the program modules
+    */
+   for ( mp = program_modules ; mp->name ; mp++ )
+      if ( (*mp->initializer)() == FAILED )
+      {
+         msg( LOG_CRIT, func,
+            "Initialization of %s facility failed. Exiting...", mp->name ) ;
+         exit( 1 ) ;
+      }
+   (void) umask( umask( 077 ) | 022 ) ;
+}
+
+/* Create the pidfile. 
+ * This is called after msg_init(), and potentially after 
+ * we've become_daemon() (depending on if we're in debug or not-forking)
+ */
+static void create_pidfile(void)
+{
+   int    pidfd;
+   FILE  *pidfile;
+
+   if ( ps.ros.pid_file ) {
+      unlink(ps.ros.pid_file);
+      pidfd = open(ps.ros.pid_file, O_EXCL|O_CREAT|O_WRONLY,
+         S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+      if (pidfd >= 0) { /* successfully created file */
+         pidfile = fdopen(pidfd, "w");
+         if (pidfile) {
+            fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+            fprintf(pidfile, "%d\n", getpid());
+            fclose(pidfile);
+         } else {
+            msg(LOG_DEBUG, "create_pidfile", "fdopen failed: %m");
+            Sclose(pidfd);
+         }
+      } else
+         msg(LOG_DEBUG, "create_pidfile", "open failed: %m");
+   }
+}
+
+/*
+ * Become a daemon by forking a new process. The parent process exits.
+ */
+static void become_daemon(void)
+{
+   int   tries ;
+   int   pid ;
+   const char  *func = "become_daemon" ;
+
+   /*
+    * First fork so that the parent will think we have exited
+    */
+   for ( tries = 0 ;; tries++ )
+   {
+      if ( tries == 5 )
+      {
+         msg( LOG_CRIT, func, "fork: %m. Exiting..." ) ;
+         exit( 0 ) ;
+      }
+
+      pid = fork() ;
+
+      if ( pid == -1 )
+      {
+         sleep( 1 ) ;   /* wait for a second */
+         continue ;      /* and then retry      */
+      }
+      else if ( pid == 0 )
+         break ;
+      else
+         exit( 0 ) ;
+   }
+
+   (void) dup2( 0, STDERR_FD ) ;
+   no_control_tty() ;
+
+#ifdef DEBUG_DAEMON
+   sleep( 20 ) ;       /* XXX: timers will probably not work after this */
+#endif
+}
+
+
+static pset_h new_table( unsigned size )
+{
+   const char *func = "new_table" ;
+   pset_h tab = pset_create( size, 0 ) ;
+
+   if ( tab == NULL )
+   {
+      msg( LOG_CRIT, func, "Failed to create table" ) ;
+      exit( 1 ) ;
+   }
+   return( tab ) ;
+}
+
+
+/*
+ * Create tables
+ */
+static void init_rw_state( void )
+{
+   SERVERS( ps ) = new_table( 0 ) ;
+   RETRIES( ps ) = new_table( 0 ) ;
+   SERVICES( ps ) = new_table( 0 ) ;
+
+   ps.rws.descriptors_free = ps.ros.max_descriptors - DESCRIPTORS_RESERVED ;
+
+   FD_ZERO( &ps.rws.socket_mask ) ;
+   ps.rws.mask_max = 0 ;
+
+}
+
+
+/*
+ * Perform all necessary initializations
+ */
+void init_daemon( int argc, char *argv[] )
+{
+   const char *fail = NULL;
+
+   debug.on = 0;
+   memset(&ps, 0, sizeof(ps));
+
+   setup_file_descriptors() ;
+   ps.ros.config_file = DEFAULT_CONFIG_FILE ;
+   (void) opt_recognize( argc, argv ) ;
+
+   /*
+    * XXX: we only use xlog_parms on XLOG_SYSLOG-type logs but in general
+    *        we should do it for all types of xlog's we may use. We can get
+    *        away with this now, because xlog_parms for XLOG_FILELOG is a noop.
+    */
+   (void) xlog_parms( XLOG_SYSLOG,
+               program_name, LOG_PID + LOG_NOWAIT, LOG_DAEMON ) ;
+
+   /*
+    * Initialize the message facility; after this everything can use the
+    * msg() interface
+    */
+   if ( (fail = msg_init()) )
+   {
+      if ( have_stderr )
+         Sprint( STDERR_FD, "%s: msg_init failed: %s\n", program_name, fail ) ;
+      exit( 1 ) ;
+   }
+
+   init_common( argc, argv ) ;
+
+   if ( ! debug.on && !dont_fork )
+      become_daemon() ;
+   create_pidfile();
+   
+   init_rw_state() ;
+}
+
+
+/*
+ * Initialize all services
+ *
+ * This function is either successful in starting some services 
+ * or it terminates the program.
+ */
+void init_services( void )
+{
+   struct configuration conf ;
+   const char *func = "init_services" ;
+
+   if ( cnf_get( &conf ) == FAILED )
+   {
+      msg( LOG_CRIT, func, "couldn't get configuration. Exiting..." ) ;
+      exit( 1 ) ;
+   }
+
+   DEFAULTS( ps ) = CNF_DEFAULTS( &conf ) ;
+   (void) cnf_start_services( &conf ) ;
+   CNF_DEFAULTS( &conf ) = NULL ;      /* to avoid the free by cnf_free */
+   cnf_free( &conf ) ;
+
+   /*
+    * The number of available/active services is kept by the service functions
+    */
+   if ( stayalive_option == 0 ) {
+      if ( ps.rws.available_services == 0 )
+      {
+         msg( LOG_CRIT, func, "no services. Exiting..." ) ;
+         if ( ps.ros.pid_file ) {
+            unlink(ps.ros.pid_file);
+         }
+         exit( 1 ) ;
+      }
+   }
+
+   spec_include() ;      /* include special services */
+}
+
diff --git a/xinetd/init.h b/xinetd/init.h
new file mode 100644 (file)
index 0000000..88ddbfa
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef INIT_H
+#define INIT_H
+
+
+void init_daemon(int argc,char *argv[]);
+void init_services(void);
+
+
+#endif
diff --git a/xinetd/int.c b/xinetd/int.c
new file mode 100644 (file)
index 0000000..b9dabbd
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "int.h"
+#include "msg.h"
+#include "log.h"
+#include "tcpint.h"
+#include "udpint.h"
+#include "sconf.h"
+#include "intcommon.h"
+#include "child.h"
+#include "state.h"
+#include "main.h"
+#include "signals.h"
+#include "xconfig.h"
+#include <netdb.h>
+
+static void start_server( struct intercept_s *ip );
+static void terminate_server( struct intercept_s *ip );
+
+typedef struct intercept_s *(*initfunc)() ;
+
+struct lookup_table
+{
+   initfunc   initializer ;
+   int        socket_type ;
+} ;
+
+
+static struct lookup_table intercept_lookup_table[] =
+   {
+      { di_init,         SOCK_DGRAM  },
+      { si_init,         SOCK_STREAM },
+      { NULL,            0           }
+   } ;
+
+         
+/*
+ * This variable has file scope for the benefit of the signal handler
+ */
+static struct intercept_s *intp = NULL;
+
+
+
+static initfunc find_initializer( int type )
+{
+   struct lookup_table *ltp ;
+
+   for ( ltp = intercept_lookup_table ; ltp->initializer ; ltp++ )
+      if ( ltp->socket_type == type )
+         return( ltp->initializer ) ;
+   msg( LOG_ERR, "find_initializer", "No initializer for type %d", type ) ;
+   _exit( 0 ) ;
+   /* NOTREACHED */
+   return (initfunc)0;
+}
+
+
+/*
+ * This function is the interface of the intercept code with the rest of 
+ * the program. 
+ */
+void intercept( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE( serp ) ;
+   initfunc initializer ;
+
+#ifdef DEBUG_INTERCEPTOR
+   if ( debug.on )
+   {
+      msg( LOG_DEBUG, "intercept", "%d is sleeping", getpid() ) ;
+      sleep( 10 ) ;
+   }
+#endif
+
+   initializer = find_initializer( SVC_SOCKET_TYPE( sp ) ) ;
+   intp = (*initializer)( serp ) ;
+   start_server( intp ) ;
+   (*intp->int_ops->mux)() ;
+   terminate_server( intp ) ;
+   /*
+    * the terminate_server function should not return but even if it
+    * does, child_process will do the _exit.
+    */ 
+}
+
+
+/*
+ * Create a socket and bind it to (INADDR_LOOPBACK,0)
+ */
+static int get_server_socket( struct intercept_s *ip )
+{
+   struct service *sp = SERVER_SERVICE( INT_SERVER( ip ) ) ;
+   union xsockaddr *sinp = INT_LOCALADDR( ip ) ;
+   int sd ;
+   socklen_t size ;
+   const char *func = "get_server_socket" ;
+
+   if( SC_IPV6(SVC_CONF(sp)) ) {
+      struct addrinfo hint, *res = NULL;
+      memset(&hint, 0, sizeof(struct addrinfo));
+      hint.ai_family = AF_INET6;
+      hint.ai_flags = AI_NUMERICHOST;
+      sinp->sa_in6.sin6_family = AF_INET6;
+      sinp->sa_in6.sin6_port = 0;
+      if( getaddrinfo("::1", NULL, &hint, &res) != 0  )
+         int_fail( ip, "can't find ::1" );
+      if( res == NULL )
+         int_fail( ip, "no results for ::1" );
+      if( res->ai_family != AF_INET6 )
+         int_fail( ip, "non IPv6 result for ::1" );
+      memcpy(sinp, res->ai_addr, sizeof( struct sockaddr_in6 ));
+      freeaddrinfo(res);
+      size = sizeof(struct sockaddr_in6);
+   } else if( SC_IPV4(SVC_CONF(sp)) ) {
+      sinp->sa_in.sin_family = AF_INET;
+      sinp->sa_in.sin_port = 0;
+      sinp->sa_in.sin_addr.s_addr = inet_addr( "127.0.0.1" );
+      size = sizeof(struct sockaddr_in);
+   } else
+      int_fail( ip, "unknown socket family" );
+
+   if ( ( sd = socket( sinp->sa.sa_family, SVC_SOCKET_TYPE( sp ), SC_PROTOVAL(SVC_CONF(sp)) ) ) == -1 )
+      int_fail( ip, "socket creation" ) ;
+
+   if ( bind( sd, SA( sinp ), size ) == -1 )
+      int_fail( ip, "bind" ) ;
+   
+   size = sizeof( *sinp ) ;
+   if ( getsockname( sd, SA( sinp ), &size ) == -1 )
+      int_fail( ip, "getsockname" ) ;
+   
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "address = %s, port = %d",
+         xaddrname( sinp ), ntohs( xaddrport( sinp ) ) ) ;
+      
+   if ( ip->int_socket_type == SOCK_STREAM )
+      (void) listen( sd, LISTEN_BACKLOG ) ;
+   
+   return( sd ) ;
+}
+
+
+static void start_server( struct intercept_s *ip )
+{
+   struct server      *serp = INT_SERVER( ip ) ;
+   struct service     *sp = SERVER_SERVICE( serp ) ;
+   int                server_socket ;
+   pid_t              pid ;
+
+   server_socket = get_server_socket( ip ) ;
+   
+   pid = fork() ;
+
+   switch ( pid )
+   {
+      case -1:
+         int_fail( ip, "fork" ) ;
+         /* NOTREACHED */
+      
+      case 0:
+         CONN_SET_DESCRIPTOR( SERVER_CONNECTION( serp ), server_socket ) ;
+         SVC_MAKE_EXTERNAL( sp ) ;            /* avoid looping */
+         child_process( serp ) ;
+         /* NOTREACHED */
+      
+      default:
+         SERVER_SET_PID( serp, pid ) ;
+         (void) Sclose( server_socket ) ;
+   }
+}
+
+
+
+/*
+ * Return value:
+ *         OK          if the server died
+ *         FAILED       otherwise
+ */
+static status_e wait_child( struct intercept_s *ip )
+{
+   const char *func = "wait_child" ;
+   int status ;
+   status_e ret = FAILED;
+   pid_t pid ;
+
+   while( (pid = waitpid( -1, &status, WNOHANG )) != 0 )
+   {
+
+      if ( pid == -1 )
+      {
+         if ( errno != EINTR )
+         {
+            msg( LOG_ERR, func, "wait: %m" ) ;
+            return( ret ) ;
+         }
+      }
+      else if ( pid == SERVER_PID( INT_SERVER( ip ) ) )
+      {
+         if ( PROC_STOPPED( status ) )
+            ret = FAILED;
+         SERVER_SET_EXIT_STATUS( INT_SERVER( ip ), status ) ;
+         ret = OK;
+      }
+      else
+      {
+         unsigned u;
+
+         /* Ideally, this will never be executed */
+         msg( LOG_ERR, func,
+            "wait returned pid of unknown process: %d", pid ) ;
+
+         /* Since we don't have the intercept pointer to this service,
+          * do our best to shut it down safely...
+          */
+         for( u = 0; u < pset_count( SERVERS(ps) ); u++ ) {
+            struct server *p = SERP( pset_pointer( SERVERS(ps), u) );
+
+            if( (p != NULL) && (SERVER_PID(p) == pid) ) {
+               struct service *sp = SERVER_SERVICE(p);
+               struct service_config *scp = SVC_CONF(sp);
+
+               if( SC_PROTOVAL(scp) == IPPROTO_TCP ) {
+                  SERVER_SET_EXIT_STATUS( p, status );
+                  si_exit();
+               } else if( SC_PROTOVAL(scp) == IPPROTO_UDP ) {
+                  SERVER_SET_EXIT_STATUS( p, status );
+                  di_exit();
+               } else {
+                  msg( LOG_ERR, func, "Don't know how to exit %d", pid);
+               }
+               break;
+            }
+         }
+      }
+   }
+
+   return ret;
+}
+
+
+static void terminate_server( struct intercept_s *ip )
+{
+   pid_t pid = SERVER_PID( INT_SERVER( intp ) ) ;
+
+   if ( pid > 0 )
+      (void) kill( pid, SIGKILL ) ;
+
+   /*
+    * Normally, wait_child should never return since a SIGCHLD will 
+    * invoke the signal handler which will then call the exit function.
+    */
+   if ( wait_child( ip ) == OK )
+      (*intp->int_ops->exit)() ;
+}
+
+
+void int_sighandler( int sig )
+{
+   const char *func = "int_sighandler" ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Received signal %s", sig_name( sig ) ) ;
+
+   if ( sig == SERVER_EXIT_SIG )
+   {
+      if ( wait_child( intp ) == OK )
+         (*intp->int_ops->exit)() ;
+   }
+   else if ( sig == INTERCEPT_SIG )
+      INTERCEPT( intp ) = FALSE ;
+   else if ( sig == SIGTERM )
+      terminate_server( intp ) ;
+}
diff --git a/xinetd/int.h b/xinetd/int.h
new file mode 100644 (file)
index 0000000..4653ef3
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef INT_H
+#define INT_H
+
+/*
+ * $Id: int.h,v 1.1.1.1 2003/02/19 17:29:28 bbraun Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "pset.h"
+#include "defs.h"
+#include "server.h"
+
+typedef enum { GOOD_CHANNEL, BAD_CHANNEL } channel_state_e ;
+
+struct channel
+{
+   channel_state_e      ch_state ;
+   union xsockaddr      ch_from ;
+   int                  ch_local_socket ;
+   int                  ch_remote_socket ;
+} ;
+
+typedef struct channel channel_s ;
+
+#define CHP( p )                 ((struct channel *)(p))
+
+#define CHANNEL_NULL             CHP( NULL )
+
+#define NEW_CHANNEL()            NEW( channel_s )
+#define FREE_CHANNEL( chp )      FREE( chp )
+
+
+struct intercept_common
+{
+   bool_int             ic_intercept ;
+   int                  ic_remote_socket ;
+   union xsockaddr      ic_local_addr ;
+   pset_h               ic_connections ;
+   struct server        ic_server ;
+} ;
+
+
+struct intercept_ops
+{
+   void (*mux)() ;
+   void (*exit)() ;
+} ;
+
+
+struct intercept_s
+{
+   int                        int_socket_type ;
+   struct intercept_common    int_common ;
+   void                      *int_priv ;
+   const struct intercept_ops *int_ops ;
+} ;
+
+#define INT_SERVER( p )              (&(p)->int_common.ic_server)
+#define INT_LOCALADDR( p )           (&(p)->int_common.ic_local_addr)
+#define INT_REMOTE( p )              ((p)->int_common.ic_remote_socket)
+#define INT_CONNECTIONS( p )         ((p)->int_common.ic_connections)
+#define INTERCEPT( p )               ((p)->int_common.ic_intercept)
+
+void intercept(struct server *serp);
+void int_sighandler(int sig);
+
+#endif   /* INT_H */
diff --git a/xinetd/intcommon.c b/xinetd/intcommon.c
new file mode 100644 (file)
index 0000000..730c27e
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "intcommon.h"
+#include "msg.h"
+#include "signals.h"
+#include "connection.h"
+#include "sconf.h"
+#include "state.h"
+#include "main.h"
+#include "xconfig.h"
+
+
+void int_fail( const struct intercept_s *ip, const char *lsyscall )
+{
+   msg( LOG_ERR, "fail", "%s failed: %m", lsyscall ) ;
+   (*ip->int_ops->exit)() ;
+   /* NOTREACHED */
+}
+
+
+/*
+ * Returns either a positive number or -1
+ */
+int int_select( int max, fd_set *read_mask )
+{
+   const char *func = "int_select" ;
+
+   for ( ;; )
+   {
+      int n_ready ;
+
+      n_ready = select( max+1, read_mask,
+                                 FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ;
+      if ( n_ready > 0 )
+         return( n_ready ) ;
+      else if ( n_ready == -1 ) {
+         if ( errno == EINTR )
+            continue ;
+         else
+         {
+            msg( LOG_ERR, func, "select: %m" ) ;
+            return( -1 ) ;
+         }
+      }
+   }
+}
+
+
+void int_exit( struct intercept_s *ip )
+{
+   int status = SERVER_EXITSTATUS( INT_SERVER( ip ) ) ;
+   const char *func = "int_exit" ;
+
+   if ( debug.on )
+   {
+      if ( PROC_EXITED( status ) )
+         msg( LOG_DEBUG, func, "intercepted server died" ) ;
+      else if ( PROC_SIGNALED( status ) )
+         msg( LOG_DEBUG, func, "intercepted server received signal %s",
+               sig_name( (int) PROC_TERMSIG( status ) ) ) ;
+   }
+   _exit( (int) PROC_EXITSTATUS( status ) ) ;
+}
+
+
+/*
+ * The ops vector must be installed before invoking this function
+ */
+void int_init( struct intercept_s *ip, struct server *serp )
+{
+   unsigned u ;
+   const char *func = "int_init" ;
+
+   /*
+    * Sanity test
+    */
+   if ( SERVER_SERVICE( serp ) != SERVER_CONNSERVICE( serp ) )
+   {
+      msg( LOG_ERR, func, "server service (%s) != connection service (%s)",
+                           SVC_ID( SERVER_SERVICE( serp ) ),
+                              SVC_ID( SERVER_CONNSERVICE( serp ) ) ) ;
+      exit( 1 ) ;
+   }
+
+   /*
+    * Close all unneeded descriptors
+    */
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+   {
+      struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+
+      if ( sp == SERVER_SERVICE( serp ) )
+         continue ;
+      if ( LOG_GET_TYPE( SC_LOG( SVC_CONF( sp ) ) ) == L_FILE )
+         xlog_destroy( SVC_LOG( sp ) ) ;
+      (void) Sclose( SVC_FD( sp ) ) ;
+   }
+
+   /*
+    * Setup signal handling
+    */
+   if ( signal( SERVER_EXIT_SIG, int_sighandler ) == SIG_ERR )
+      int_fail( ip, "signal" ) ;
+   if ( signal( INTERCEPT_SIG, int_sighandler ) == SIG_ERR )
+      int_fail( ip, "signal" ) ;
+   if ( signal( SIGTERM, int_sighandler ) == SIG_ERR )
+      int_fail( ip, "signal" ) ;
+   
+   /*
+    * Initialize state
+    */
+   INTERCEPT( ip ) = TRUE ;
+   *INT_SERVER( ip ) = *serp ;
+   INT_REMOTE( ip ) = SERVER_FD( serp ) ;
+
+   INT_CONNECTIONS( ip ) = pset_create( 0, 0 ) ;
+   if ( INT_CONNECTIONS( ip ) == NULL )
+   {
+      msg( LOG_ERR, func, ES_NOMEM ) ;
+      (*ip->int_ops->exit)() ;
+   }
+}
+
+
+/*
+ * Make a new connection to the local server
+ */
+channel_s *int_newconn( struct intercept_s *ip, 
+                        union xsockaddr *sinp,
+                        int remote_socket )
+{
+   struct service       *sp          = SERVER_SERVICE( INT_SERVER( ip ) ) ;
+   int                   socket_type = SVC_SOCKET_TYPE( sp ) ;
+   union xsockaddr      *local       = INT_LOCALADDR( ip ) ;
+   char                 *sid         = SVC_ID( sp ) ;
+   channel_s            *chp ;
+   int                   sd ;
+   const char           *func = "int_newconn" ;
+
+   /*
+    * Get a socket and connect it to the local address
+    *
+    */
+   if ( ( sd = socket( local->sa.sa_family, socket_type, SC_PROTOVAL(SVC_CONF(sp)) ) ) == -1 )
+   {
+      msg( LOG_ERR, func,"(intercepting %s) socket creation failed: %m", sid ) ;
+      return( CHANNEL_NULL ) ;
+   }
+
+   if ( connect( sd, SA( local ), sizeof( *local ) ) == -1 )
+   {
+      msg( LOG_ERR, func, "(intercepting %s) connect failed: %m", sid ) ;
+      (void) Sclose( sd ) ;
+      return( CHANNEL_NULL ) ;
+   }
+
+   chp = NEW_CHANNEL() ;
+   if ( chp == CHANNEL_NULL )
+   {
+      msg( LOG_ERR, func, ES_NOMEM ) ;
+      (void) Sclose( sd ) ;
+      return( CHANNEL_NULL ) ;
+   }
+
+   if ( pset_add( INT_CONNECTIONS( ip ), chp ) == NULL )
+   {
+      msg( LOG_ERR, func, ES_NOMEM ) ;
+      FREE_CHANNEL( chp ) ;
+      (void) Sclose( sd ) ;
+      return( CHANNEL_NULL ) ;
+   }
+
+   chp->ch_state = GOOD_CHANNEL ;
+   chp->ch_from = *sinp ;
+   chp->ch_local_socket = sd ;
+   chp->ch_remote_socket = remote_socket ;
+   return( chp ) ;
+}
+
+
+
+/*
+ * Check if the (address,port) in sinp is already in the connection table.
+ * Return value:
+ *    a connection pointer if the address is found
+ *    NULL if the address if not found
+ *
+ * *addr_checked is set to TRUE of FALSE depending on whether there
+ * is already a connection from the same IP address in the table.
+ */
+channel_s *int_lookupconn( struct intercept_s *ip, 
+                           union xsockaddr *sinp,
+                           bool_int *addr_checked )
+{
+   unsigned      u ;
+   pset_h      conntab = INT_CONNECTIONS( ip ) ;
+
+   *addr_checked = FALSE ;
+
+   for ( u = 0 ; u < pset_count( conntab ) ; u++ )
+   {
+      register channel_s *chp = CHP( pset_pointer( conntab, u ) ) ;
+
+      if ( memcmp( &chp->ch_from, sinp, sizeof( *sinp ) ) == 0 )
+      {
+         *addr_checked = TRUE ;
+         if ( xaddrport(&chp->ch_from) == xaddrport(sinp) )
+            return( chp ) ;
+      }
+   }
+   return( CHANNEL_NULL ) ;
+}
diff --git a/xinetd/intcommon.h b/xinetd/intcommon.h
new file mode 100644 (file)
index 0000000..3a4019f
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef INTCOMMON_H
+#define INTCOMMON_H
+
+#include "config.h"
+#include <sys/types.h>
+#include "int.h"
+
+void int_fail(const struct intercept_s *ip,const char *lsyscall);
+int int_select(int max,fd_set *read_mask);
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void int_exit(struct intercept_s *ip);
+void int_init(struct intercept_s *ip,struct server *serp);
+
+channel_s *int_newconn( struct intercept_s *ip, union xsockaddr *sinp, 
+                        int remote_socket );
+channel_s *int_lookupconn( struct intercept_s *ip, union xsockaddr *sinp, 
+                           bool_int *addr_checked );
+#endif
+
diff --git a/xinetd/internals.c b/xinetd/internals.c
new file mode 100644 (file)
index 0000000..ec67bfc
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "sio.h"
+#include "internals.h"
+#include "msg.h"
+#include "sconf.h"
+#include "state.h"
+#include "main.h"
+#include "xconfig.h"
+#include "xtimer.h"
+#include "options.h"
+
+static unsigned thread_check( register struct service *sp,unsigned running_servers, unsigned retry_servers );
+static unsigned refcount_check( struct service *sp, unsigned *running_servers, unsigned *retry_servers );
+static unsigned service_count_check( register struct service *sp, unsigned running_servers, unsigned retry_servers );
+static void periodic_check(void);
+
+
+static void dump_services( int fd )
+{
+   unsigned u ;
+
+   /*
+    * Dump the current configuration (services + defaults)
+    */
+   Sprint( fd, "Services + defaults:\n" ) ;
+   sc_dump( DEFAULTS( ps ), fd, 0, TRUE ) ;
+
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+      svc_dump( SP( pset_pointer( SERVICES( ps ), u ) ), fd ) ;
+}
+
+void dump_internal_state(void)
+{
+   int dump_fd ;
+   const char *dump_file = DUMP_FILE ;
+   time_t current_time ;
+   int fd ;
+   unsigned u ;
+   const char *func = "dump_internal_state" ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Dumping State" ) ;
+
+   dump_fd = open( dump_file, O_WRONLY | O_CREAT | O_APPEND, DUMP_FILE_MODE);
+   if ( dump_fd == -1 )
+   {
+      msg( LOG_ERR, func, "failed to open %s: %m", dump_file ) ;
+      return ;
+   }
+   
+   if (Sbuftype( dump_fd, SIO_LINEBUF ) == SIO_ERR )
+   {
+       /*
+       * If the above function failed, Sprint will most likely
+       * fail, too. Output a message for troubleshooting and quit.
+       */
+       msg( LOG_ERR, func, 
+            "failed setting up sio buffering: %m fd:%d", dump_fd ) ;
+       Sclose(dump_fd);
+       return;
+   }
+
+   /*
+    * Print the program name, version, and timestamp.
+    * Note that the program_version variable contains the program name.
+    */
+   (void) time( &current_time ) ;
+   Sprint( dump_fd, "INTERNAL STATE DUMP: %s\n", program_version ) ;
+   Sprint( dump_fd, "Current time: %s\n", ctime( &current_time ) ) ;
+
+   dump_services( dump_fd ) ;
+
+   /*
+    * Dump the server table
+    */
+   Sprint( dump_fd, "Server table dump:\n" ) ;
+   for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
+      server_dump( SERP( pset_pointer( SERVERS( ps ), u ) ), dump_fd ) ;
+   Sputchar( dump_fd, '\n' ) ;
+
+   /*
+    * Dump the retry_table
+    */
+   Sprint( dump_fd, "Retry table dump:\n" ) ;
+   for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
+      server_dump( SERP( pset_pointer( RETRIES( ps ), u ) ), dump_fd ) ;
+   Sputchar( dump_fd, '\n' ) ;
+
+   /*
+    * Dump the socket mask
+    */
+   Sprint( dump_fd, "Socket mask:" ) ;
+   for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
+      if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
+         Sprint( dump_fd, " %d", fd ) ;
+   Sputchar( dump_fd, '\n' ) ;
+   Sprint( dump_fd, "mask_max = %d\n", ps.rws.mask_max ) ;
+
+   /*
+    * Dump the descriptors that are open and are *not* in the socket mask
+    */
+   Sprint( dump_fd, "Open descriptors (not in socket mask):" ) ;
+   for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
+   {
+      struct stat st ;
+
+      if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
+         continue ;
+      if ( fstat( fd, &st ) == -1 )
+         continue ;
+      Sprint( dump_fd, " %d", fd ) ;
+   }
+   Sputchar( dump_fd, '\n' ) ;
+   Sputchar( dump_fd, '\n' ) ;
+
+   Sprint( dump_fd, "active_services = %d\n", ps.rws.active_services ) ;
+   Sprint( dump_fd, "available_services = %d\n", ps.rws.available_services ) ;
+   Sprint( dump_fd, "descriptors_free = %d\n", ps.rws.descriptors_free ) ;
+   Sprint( dump_fd, "running_servers = %d\n", pset_count( SERVERS( ps ) ) ) ;
+   Sprint( dump_fd, "Logging service = %s\n",
+            LOG_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
+   Sputchar( dump_fd, '\n' ) ;
+
+   Sprint( dump_fd, "max_descriptors = %d\n", (int)ps.ros.max_descriptors ) ;
+   Sprint( dump_fd, "process_limit = %d\n", (int)ps.ros.process_limit ) ;
+   Sprint( dump_fd, "config_file = %s\n", ps.ros.config_file ) ;
+   if ( debug.on )
+      Sprint( dump_fd, "debug_fd = %d\n", debug.fd ) ;
+   Sputchar( dump_fd, '\n' ) ;
+
+   Sprint( dump_fd, "END OF DUMP\n\n" ) ;
+   Sclose( dump_fd );
+
+   msg( LOG_INFO, func, "generated state dump in file %s", dump_file ) ;
+}
+
+
+/*
+ * Types of consistency checks
+ */
+enum check_type { PERIODIC, USER_REQUESTED } ;
+
+
+static void consistency_check( enum check_type type )
+{
+   int         fd ;
+   fd_set      socket_mask_copy ;
+   unsigned    u ;
+   int         errors ;
+   unsigned    total_running_servers        = 0 ;
+   unsigned    total_retry_servers          = 0 ;
+   unsigned    error_count                  = 0 ;
+   bool_int    service_count_check_failed   = FALSE ;
+   const char  *func                        = "consistency_check" ;
+
+   socket_mask_copy = ps.rws.socket_mask ;
+
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+   {
+      register struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+      char *sid = SVC_ID( sp ) ;
+      unsigned   running_servers ;
+      unsigned   retry_servers ;
+
+      error_count += refcount_check( sp, &running_servers, &retry_servers ) ;
+
+      if ( SVC_IS_AVAILABLE( sp ) || SVC_IS_DISABLED ( sp ) )
+      {
+         /*
+          * In this case, there may be some servers running
+          */
+         if ( FD_ISSET( SVC_FD( sp ), &socket_mask_copy ) )
+         {
+            if ( SVC_IS_DISABLED( sp ) )
+            {
+               msg( LOG_ERR, func,
+                  "fd of disabled service %s still in socket mask", sid ) ;
+               error_count++ ;
+            }
+            FD_CLR( SVC_FD( sp ), &socket_mask_copy ) ;
+         }
+         error_count += thread_check( sp, running_servers, retry_servers ) ;
+
+         errors = service_count_check( sp, running_servers, retry_servers ) ;
+         if ( ! errors && ! service_count_check_failed )
+         {
+            total_retry_servers += retry_servers ;
+            total_running_servers += running_servers ;
+         }
+         if ( errors )
+         {
+            service_count_check_failed = TRUE ;
+            error_count += errors ;
+         }
+
+         if ( SVC_IS_DISABLED( sp ) && SVC_RUNNING_SERVERS( sp ) == 0 )
+         {
+            msg( LOG_ERR, func,
+               "disabled service %s has 0 running servers\n", sid ) ;
+            error_count++ ;
+            continue ;
+         }
+      }
+      /* TCPMUX client programs are always stopped until they run. */
+      else if ( ! SVC_IS_MUXCLIENT( sp ) )
+      {
+         msg( LOG_ERR, func, "service %s not started", SVC_ID( sp ) ) ;
+         error_count++ ;
+      }
+   }
+
+   if ( ! service_count_check_failed )
+   {
+      if ( total_running_servers != pset_count( SERVERS( ps ) ) )
+      {
+         msg( LOG_ERR, func,
+            "total running servers (%d) != number of running servers (%d)",
+               total_running_servers, pset_count( SERVERS( ps ) ) ) ;
+         error_count++ ;
+      }
+      if ( total_retry_servers != pset_count( RETRIES( ps ) ) )
+      {
+         msg( LOG_ERR, func,
+            "total retry servers (%d) != number of retry servers (%d)",
+               total_retry_servers, pset_count( RETRIES( ps ) ) ) ;
+         error_count++ ;
+      }
+   }
+
+   /*
+    * Check if there are any descriptors set in socket_mask_copy
+    */
+   for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
+      if ( FD_ISSET( fd, &socket_mask_copy ) && ((fd != signals_pending[0]) && fd != signals_pending[1]))
+      {
+         msg( LOG_ERR, func,
+            "descriptor %d set in socket mask but there is no service for it",
+               fd ) ;
+         error_count++ ;
+      }
+
+   if ( error_count != 0 )
+      msg( LOG_WARNING, func,
+            "Consistency check detected %d errors", error_count ) ;
+   else
+      if ( type == USER_REQUESTED || debug.on )
+         msg( LOG_INFO, func, "Consistency check passed" ) ;
+
+   if( type == PERIODIC ) 
+      if ( xtimer_add( periodic_check, ps.ros.cc_interval ) == -1 )
+         msg( LOG_ERR, func, "Failed to start consistency timer" ) ;
+}
+
+
+/*
+ * Check that the counts of running and retry servers stored in struct service
+ * are accurate
+ */
+static unsigned service_count_check( struct service *sp, 
+                                      unsigned running_servers, 
+                                      unsigned retry_servers )
+{
+   char *sid = SVC_ID( sp ) ;
+   int error_count = 0 ;
+   const char *func = "service_count_check" ;
+
+   if ( SVC_RUNNING_SERVERS( sp ) != running_servers )
+   {
+      msg( LOG_ERR, func,
+         "service %s: actual running servers = %d, known running servers = %d",
+            sid, running_servers, SVC_RUNNING_SERVERS( sp ) ) ;
+      error_count++ ;
+   }
+   if ( SVC_RETRIES( sp ) != retry_servers )
+   {
+      msg( LOG_ERR, func,
+         "service %s: actual retry servers = %d, known retry servers = %d",
+            sid, retry_servers, SVC_RETRIES( sp ) ) ;
+      error_count++ ;
+   }
+
+   if ( error_count && debug.on )
+      msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
+
+   return( error_count ) ;
+}
+
+
+
+/*
+ * If the service is single-threaded:
+ *         if the descriptor is set in the socket mask, there must
+ *         be a server running (or to be retried)
+ *   If the service is multi-threaded:
+ *         the descriptor must be always set
+ */
+static unsigned thread_check( struct service *sp, 
+                               unsigned running_servers, 
+                               unsigned retry_servers )
+{
+   unsigned error_count = 0 ;
+   int sd = SVC_FD( sp ) ;
+   char *sid = SVC_ID( sp ) ;
+   const char *func = "thread_check" ;
+
+   if ( SVC_WAITS( sp ) )
+   {
+      bool_int has_servers = ( running_servers + retry_servers != 0 ) ;
+
+      if ( has_servers && FD_ISSET( sd, &ps.rws.socket_mask ) )
+      {
+         msg( LOG_ERR, func,
+"Active single-threaded service %s: server running, descriptor set", sid ) ;
+         error_count++ ;
+      }
+      if ( !has_servers && !FD_ISSET( sd, &ps.rws.socket_mask ) )
+      {
+         msg( LOG_ERR, func,
+"Active single-threaded service %s: no server running, descriptor not set",
+            sid ) ;
+         error_count++ ;
+      }
+   }
+   else
+      if ( ! FD_ISSET( sd, &ps.rws.socket_mask ) )
+      {
+         msg( LOG_ERR, func,
+            "Active multi-threaded service %s: descriptor not set", sid ) ;
+         error_count++ ;
+      }
+
+   if ( error_count && debug.on )
+      msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
+
+   return( error_count ) ;
+}
+
+
+
+/*
+ * Count the number of references to the specified service contained
+ * in the specified table of servers; put the number of servers
+ * in *countp
+ */
+static int count_refs( struct service *sp, pset_h servers, unsigned *countp )
+{
+   unsigned u ;
+   struct server *serp ;
+   int refs = 0 ;
+   unsigned count = 0 ;
+
+   for ( u = 0 ; u < pset_count( servers ) ; u++ )
+   {
+      serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
+      if ( SERVER_SERVICE( serp ) == sp )
+      {
+         refs++ ;
+         count++ ;
+      }
+      if ( SERVER_CONNSERVICE( serp ) == sp )
+         refs++ ;
+      /*
+       * XXX:   in the future we may want to check if the given service
+       *         is any of the alternative services (currently only SPECIAL
+       *         services can be alternative services and SPECIAL services
+       *         are not included in the service table)
+       */
+   }
+   *countp = count ;
+   return( refs ) ;
+}
+
+
+/*
+ * Check for reference counting errors.
+ * Returns number of errors found.
+ * Always set the number of running and retry servers.
+ */
+static unsigned refcount_check( struct service *sp, 
+                                 unsigned *running_servers, 
+                                 unsigned *retry_servers )
+{
+   char *sid = SVC_ID( sp ) ;
+   unsigned errors = 0 ;
+   int refs ;
+   int refcount = SVC_REFCOUNT( sp ) ;
+   const char *func = "refcount_check" ;
+
+   if ( refcount <= 0 )
+   {
+      msg( LOG_ERR, func, "%s service has bad refcount: %d",
+               sid, refcount ) ;
+      errors++ ;
+   }
+
+   /*
+    * The service table holds a reference to the service. The remaining
+    * references must be from servers and connections.
+    */
+   refcount-- ;
+
+   refs = count_refs( sp, SERVERS( ps ), running_servers ) ;
+   if ( ! errors && refs > refcount )
+   {
+      msg( LOG_ERR, func,
+         "running servers: too many references for %s (%d with max=%d)",
+            sid, refs, refcount ) ;
+      errors++ ;
+   }
+
+   refs = count_refs( sp, RETRIES( ps ), retry_servers ) ;
+   if ( ! errors && refs > refcount )
+   {
+      msg( LOG_ERR, func,
+         "retry servers: too many references for %s (%d with max=%d)",
+            sid, refs, refcount ) ;
+      errors++ ;
+   }
+
+   if ( errors && debug.on )
+      msg( LOG_DEBUG, func, "%s: %d errors detected", sid, errors ) ;
+
+   return( errors ) ;
+}
+
+
+void user_requested_check(void)
+{
+   consistency_check( USER_REQUESTED ) ;
+} 
+
+
+static void periodic_check(void)
+{
+   consistency_check( PERIODIC ) ;
+}
+
+/* This actually gets called during initialization, so be careful what
+ * gets put in here.
+ */
+void enable_periodic_check( unsigned interval )
+{
+   const char *func = "enable_periodic_check" ;
+
+   if ( xtimer_add( periodic_check, interval ) == -1 )
+   {
+      msg( LOG_ERR, func, "Failed to start consistency timer" ) ;
+      return ;
+   }
+}
diff --git a/xinetd/internals.h b/xinetd/internals.h
new file mode 100644 (file)
index 0000000..4d2c59e
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef INTERNALS_H
+#define INTERNALS_H
+
+#include "config.h"
+#include "defs.h"
+
+void dump_internal_state(void);
+void user_requested_check(void);
+void enable_periodic_check( unsigned );
+#endif
diff --git a/xinetd/itox.8 b/xinetd/itox.8
new file mode 100644 (file)
index 0000000..de109db
--- /dev/null
@@ -0,0 +1,19 @@
+.TH ITOX 8 "October 1999" "xinetd"
+.SH NAME
+itox \- converts inetd.conf style configuration files to xinetd.conf
+.SH SYNOPSIS
+itox [-daemon_dir <dir_path>]
+.SH DESCRIPTION
+.B itox
+takes on its standard input inetd.conf style entries and dumps to
+standard output the corresponding xinetd.conf style entries.
+.SH OPTIONS
+.TP
+.I -daemon_dir <dir_path>
+Specifies the file name of the TCP daemon used in the inetd.conf file.
+.SH EXAMPLES
+itox -daemon_dir /usr/sbin/tcpd < inetd.conf > xinetd.conf
+.SH AUTHOR
+xinetd and itox were written by Panagiotis Tsirigotis.
+.sp
+This man page was written by Norbert Veber <nveber@debian.org>.
diff --git a/xinetd/itox.c b/xinetd/itox.c
new file mode 100644 (file)
index 0000000..dd37e8f
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+static char RCSid[] = "$Id: itox.c,v 1.3 2003/06/23 21:13:36 steveg Exp $" ;
+
+#include "config.h"
+#define EQ( s1, s2 )                           ( strcmp( s1, s2 ) == 0 )
+
+#define NUL                                    '\0'
+#define static                                 static
+
+#define FIELD_WIDTH                            15
+#define DAEMON_DIR_OPTION                      "-daemon_dir"
+#define TCPD_NAME                              "tcpd"
+
+#include <stdlib.h>
+#include <string.h>
+#include "sio.h"
+#include "str.h"
+#if !defined(linux)
+#include "misc.h"
+#else
+#include <libgen.h>
+#endif
+
+str_h strp ;
+int line_count ;
+static void print_line( const char *name, const char *value );
+static char *next_word( const char *description );
+static char *make_string_cat( register unsigned count, ... );
+static char *make_pathname( register unsigned count, ... );
+
+
+/*
+ * This program works only as a filter.
+ * Options:
+ *    -daemon_dir <dir_name> : if you use tcpd, this option specifies the
+ *             directory where all the daemons are.
+ *             You must specify this option if you use tcpd
+ *
+ * Note that we don't bother to free the memory we malloc.
+ */
+int main(int argc, char *argv[] )
+{
+       char *s ;
+       int uses_tcpd ;
+       char *daemon_dirpath = "" ;
+
+       if ( argc != 1 && argc != 3 )
+       {
+               Sprint( 2, "Usage: %s [%s dir_path]\n",
+                               basename( argv[ 0 ] ), DAEMON_DIR_OPTION ) ;
+               exit( 1 ) ;
+       }
+
+       uses_tcpd = ( argc == 3 ) ;
+
+       if ( uses_tcpd )
+       {
+               int len ;
+
+               daemon_dirpath = argv[ 2 ] ;
+               len = strlen( daemon_dirpath ) ;
+               if ( daemon_dirpath[ len-1 ] == '/' )
+                       daemon_dirpath[ --len ] = NUL ;
+       }
+
+       strp = str_parse( (char *)0, " \t", STR_NOFLAGS, (int *)0 ) ;
+
+       while ( (s = Srdline( 0 )) )
+       {
+               char *word ;
+               char *p ;
+               char *socket_type, *protocol ;
+               char *service ;
+               int is_rpc ;
+
+               line_count++ ;
+
+               if ( SIOLINELEN( 0 ) == 0 || s[ 0 ] == '#' )
+                       continue ;
+
+               str_setstr( strp, s ) ;
+
+               service = word = next_word( "service name" ) ;
+
+               /*
+                * Check if it is an RPC service
+                */
+               p = strchr( word, '/' ) ;
+               if ( p != NULL )
+                       *p = 0 ;
+               Sprint( 1, "service %s\n{\n", word ) ;
+               if ( (is_rpc = ( p != NULL )) )
+               {
+                       print_line( "type", "RPC" ) ;
+                       print_line( "rpc_version", p+1 ) ;
+               }
+
+               socket_type = word = next_word( "socket type" ) ;
+               print_line( "socket_type", socket_type ) ;
+
+               word = next_word( "protocol" ) ;
+               p = strchr( word, '/' ) ;
+               protocol = ( p == NULL ) ? word : p+1 ;
+
+               print_line( "protocol", protocol ) ;
+
+               word = next_word( "wait/nowait" ) ;
+               p = strchr(word, '.');
+               if (p != NULL)
+               {
+                       Sprint( 2, 
+                       "The entry for service %s/%s may be wrong, because\n", 
+                               service, protocol);
+                       Sprint( 2, 
+                       "we can't convert .max option for wait/nowait field\n");
+                       *p = '\0';
+                       print_line( "wait", EQ( word, "wait" ) ? "yes" : "no" );
+               }
+               else
+                       print_line( "wait", EQ( word, "wait" ) ? "yes" : "no" );
+
+               word = next_word( "user[.group]" ) ;
+               p = strchr(word, '.');
+               if (p != NULL)
+               {
+                       *p = '\0';
+                       print_line( "user", word ) ;
+                       word = ++p;
+                       print_line( "group", word );
+               }
+               else
+                       print_line( "user", word ) ;
+
+               word = next_word( "server" ) ;
+               if ( EQ( word, "internal" ) )
+               {
+                       /*
+                        * We are in trouble if this is an RPC service
+                        */
+                       if ( is_rpc )
+                       {
+                               Sprint( 2,
+                                       "The entry for service %s will be wrong because\n", service ) ;
+                               Sprint( 2, "we can't handle internal RPC services\n" ) ;
+                       }
+                       else
+                       {
+                               print_line( "type", "INTERNAL" ) ;
+                               print_line( "id", 
+                                       make_string_cat( 3, service, 
+                                               "-", socket_type ) ) ;
+                       }
+               }
+               else
+               {
+                       char *server_path = word ;      /* from inetd.conf */
+                       char *server_of_server_path = basename( server_path ) ;
+                       char *server_name = next_word( "server name" ) ;
+                       char *server ;          /* for xinetd config file */
+
+                       if ( EQ( server_of_server_path, TCPD_NAME ) )
+                       {
+                               if ( ! uses_tcpd )
+                               {
+                                       Sprint( 2, "You must use option %s if you use %s\n",
+                                               DAEMON_DIR_OPTION, TCPD_NAME ) ;
+                                       exit( 1 ) ;
+                               }
+                               if ( server_name[ 0 ] == '/' )
+                                       server = server_name ;
+                               else
+                                       server = make_pathname( 2, 
+                                               daemon_dirpath, server_name ) ;
+                       }
+                       else
+                               server = server_path ;
+
+                       print_line( "server", server ) ;
+
+                       word = str_component( strp ) ;  /* 1st arg */
+                       if ( word != NULL )
+                       {
+                               Sprint( 1, "\t%-*s = %s", FIELD_WIDTH, 
+                                       "server_args", word ) ;
+                               while ( (word = str_component( strp )) )
+                                       Sprint( 1, " %s", word ) ;
+                               Sputchar( 1, '\n' ) ;
+                       }
+               }
+
+               Sprint( 1, "}\n\n" ) ;
+       }
+       Sflush( 1 ) ;
+       exit( 0 ) ;
+}
+
+
+static void print_line( const char *name, const char *value )
+{
+       Sprint( 1, "\t%-*s = %s\n", FIELD_WIDTH, name, value ) ;
+}
+
+
+static char *next_word( const char *description )
+{
+       char *word = str_component( strp ) ;
+
+       if ( word == NULL )
+       {
+               Sprint( 2, "Line %d: %s missing \n", line_count, description ) ;
+               exit( 1 ) ;
+       }
+       return( word ) ;
+}
+
+static char *make_string_cat( register unsigned count, ... )
+{
+   va_list ap ;
+   register unsigned i ;
+   register unsigned len = 0 ;
+   register char *s, *p ;
+   char *newstring ;
+
+   if ( count == 0 )
+      return( NULL ) ;
+
+   va_start( ap, count ) ;
+   if (count == 1)
+   {  /* 9 out of 10 have just 1, so this optimizes it */
+      s = va_arg( ap, char * ) ;
+      va_end( ap );
+      if ( s == NULL )
+         return strdup("");
+      else
+         return strdup(s);
+   }
+   for ( i = 0 ; i < count ; i++ )
+   {
+      s = va_arg( ap, char * ) ;
+      if ( s == NULL )
+         continue ;
+      len += strlen( s ) ;
+   }
+   va_end( ap ) ;
+
+   newstring = (char *)malloc( len + 1 ) ;
+   if ( newstring == NULL )
+      return( NULL ) ;
+
+   p = newstring ;
+   va_start( ap, count ) ;
+   for ( i = 0 ; i < count ; i++ )
+   {
+      s = va_arg( ap, char * ) ;
+      if ( s == NULL )
+         continue ;
+      while ( (*p++ = *s++) ) ;
+      p-- ;
+   }
+   va_end( ap ) ;
+   newstring[len] = 0; /* if len == 0, must terminate or boom! */
+   return newstring ;
+}
+
+static char *make_pathname( register unsigned count, ... )
+{
+   va_list ap ;
+   register unsigned i ;
+   register unsigned len = 0 ;
+   register char *s, *p ;
+   char *pathname ;
+
+   if ( count == 0 )
+      return( NULL ) ;
+
+   va_start( ap, count ) ;
+   for ( i = 0 ; i < count ; i++ )
+   {
+      s = va_arg( ap, char * ) ;
+      len += strlen( s ) ;
+   }
+   va_end( ap ) ;
+
+   pathname = (char *)malloc( len + count ) ;
+   if ( pathname == NULL )
+      return( NULL ) ;
+
+   p = pathname ;
+   va_start( ap, count ) ;
+   for ( i = 0 ; i < count ; i++ )
+   {
+      s = va_arg( ap, char * ) ;
+      while ( (*p++ = *s++) ) ;
+      *(p-1) = '/' ;         /* change '\0' to '/' */
+   }
+   *(p-1) = '\0' ;
+   va_end( ap ) ;
+   return( pathname ) ;
+} 
+
diff --git a/xinetd/log.c b/xinetd/log.c
new file mode 100644 (file)
index 0000000..f1351c4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <syslog.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "str.h"
+#include "log.h"
+#include "sconf.h"
+#include "sconst.h"
+#include "msg.h"
+
+
+#define LOGBUF_SIZE                  1024
+
+static char ipv6_ret[NI_MAXHOST];
+
+const char *xaddrname(const union xsockaddr *inaddr)
+{
+   unsigned int len = 0;
+   if( inaddr->sa.sa_family == AF_INET )  len = sizeof(struct sockaddr_in);
+   if( inaddr->sa.sa_family == AF_INET6 ) len = sizeof(struct sockaddr_in6);
+   memset(ipv6_ret, 0, sizeof(ipv6_ret));
+   if( getnameinfo(&inaddr->sa, len, ipv6_ret, sizeof(ipv6_ret), NULL, 
+         0, NI_NUMERICHOST) )
+      strncpy(ipv6_ret, "<unknown>", NI_MAXHOST);
+   return ipv6_ret;
+}
+
+uint16_t xaddrport(const union xsockaddr *inaddr)
+{
+   if( inaddr->sa.sa_family == AF_INET )  return inaddr->sa_in.sin_port;
+   if( inaddr->sa.sa_family == AF_INET6 ) return inaddr->sa_in6.sin6_port;
+   return 0;
+}
+
+static int log_common(mask_t *, char *, int, const connection_s *) ;
+
+/*
+ * This function writes log records of the form:
+ *
+ *      START: service [pid] [from_address]
+ */
+void svc_log_success( struct service *sp, const connection_s *cp, pid_t pid )
+{
+   char                    buf[ LOGBUF_SIZE ] ;
+   int                     bufsize ;
+   struct service_config   *scp = SVC_CONF( sp ) ;
+   int                     len ;
+   int                     cc ;
+
+   if ( ! SVC_LOGS_ON_SUCCESS( sp ) )
+      return ;
+   
+   bufsize = sizeof( buf ) ;
+   len = 0 ;
+   
+   cc = strx_nprint( buf, bufsize, "%s: %s", START_ENTRY, SC_ID( scp ) ) ;
+   len += cc ;
+   bufsize -= cc ;
+
+   if ( SC_LOGS_PID( scp ) )
+   {
+      cc = strx_nprint( &buf[ len ], bufsize, " pid=%d", pid ) ;
+      len += cc ;
+      bufsize -= cc ;
+   }
+
+   cc = log_common( &SC_LOG_ON_SUCCESS( scp ), &buf[len], bufsize, cp ) ;
+   len += cc ;
+   bufsize -= cc ;
+
+   xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
+}
+
+
+/*
+ * This function writes log records of the form:
+ *
+ *      FAIL: service failure-type [from_address]
+ *
+ */
+void svc_log_failure( struct service *sp, 
+                      const connection_s *cp, 
+                      access_e access_failure )
+{
+   char                    buf[ LOGBUF_SIZE ] ;
+   int                     bufsize ;
+   struct service_config   *scp = SVC_CONF( sp ) ;
+   int                     len = 0 ;
+   int                     cc ;
+   
+   if ( ! SVC_LOGS_ON_FAILURE( sp ) )
+      return ;
+   
+   bufsize = sizeof( buf ) ;
+   cc = strx_nprint( buf, bufsize, "%s: %s", FAIL_ENTRY, SC_ID( scp ) ) ;
+   len += cc ;
+   bufsize -= cc ;
+
+   cc = strx_nprint( &buf[ len ], bufsize,
+                        " %s", ACCESS_EXPLAIN( access_failure ) ) ;
+   len += cc ;
+   bufsize -= cc ;
+
+   cc = log_common( &SC_LOG_ON_FAILURE( scp ), &buf[ len ], bufsize, cp ) ;
+   len += cc ;
+   bufsize -= cc ;
+
+   xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
+}
+
+
+
+static int log_common( mask_t *logmask, 
+                        char *buf, 
+                        int bufsize, 
+                        const connection_s *cp )
+{
+   int len = 0 ;
+
+   if ( M_IS_SET( *logmask, LO_HOST ) )
+      len = strx_nprint( buf, bufsize, " from=%s", conn_addrstr( cp ) ) ;
+   return( len ) ;
+}
+
+
+void svc_log_exit( struct service *sp, const struct server *serp )
+{
+   char                    buf[ LOGBUF_SIZE ] ;
+   int                     bufsize ;
+   int                     cc ;
+   int                     len ;
+   int                     exit_status = SERVER_EXITSTATUS( serp ) ;
+   struct service_config   *scp = SVC_CONF( sp ) ;
+   const char                    *func = "log_exit" ;
+
+   if ( ! SVC_LOGS_ON_EXIT( sp ) )
+      return ;
+
+   bufsize = sizeof( buf ) ;
+   len = 0 ;
+
+   cc = strx_nprint( buf, bufsize, "%s: %s", EXIT_ENTRY, SC_ID( scp ) ) ;
+   bufsize -= cc ;
+   len += cc ;
+
+   /*
+    * If the EXIT flag was used, log the exit status or the signal that
+    * killed the process. We assume that these are the only reasons
+    * for process termination.
+    */
+   if ( SC_LOGS_EXITS( scp ) )
+   {
+      int num  = 0;
+      const char *s ;
+
+      if ( PROC_EXITED( exit_status ) )
+      {
+         s = "status" ;
+         num = PROC_EXITSTATUS( exit_status ) ;
+      }
+      else if ( PROC_SIGNALED( exit_status ) )
+      {
+         s = "signal" ;
+         num = PROC_TERMSIG( exit_status ) ;
+      }
+      else
+      {
+         msg( LOG_ERR, func, "Bad exit status" ) ;
+         s = NULL ;
+      }
+
+      if ( s )
+      {
+         cc = strx_nprint( &buf[ len ], bufsize, " %s=%d", s, num ) ;
+         len += cc ;
+         bufsize -= cc ;
+      }
+   }
+
+   if ( SC_LOGS_PID( scp ) )
+   {
+      cc = strx_nprint( &buf[ len ], bufsize, " pid=%d", SERVER_PID( serp ) ) ;
+      len += cc ;
+      bufsize -= cc ;
+   }
+
+   if ( SC_LOGS_DURATION( scp ) )
+   {
+      time_t current_time ;
+
+      (void) time( &current_time ) ;
+      cc = strx_nprint( &buf[ len ], bufsize, " duration=%ld(sec)",
+         (long)(current_time - SERVER_STARTTIME( serp )) ) ;
+      len += cc ;
+      bufsize -= cc ;
+   }
+   xlog_write( SVC_LOG(sp), buf, len, XLOG_NO_ERRNO ) ;
+}
+
+
+
+/*
+ * Used by other parts of xinetd that want to log something without
+ * going through the proper channels (i.e. log_{success,failure} and log_exit)
+ */
+/* VARARGS3 */
+void svc_logprint( struct service *sp, const char *line_id, 
+                   const char *fmt, ...)
+{
+   char     buf[ LOGBUF_SIZE ] ;
+   int      bufsize = sizeof( buf ) ;
+   int      len ;
+   int      cc ;
+   va_list  ap ;
+
+   if ( ! SVC_IS_LOGGING( sp ) )
+      return ;
+
+   len = strx_nprint( buf, bufsize, "%s: %s ", line_id, SVC_ID( sp ) ) ;
+   va_start( ap, fmt ) ;
+   cc = strx_nprintv( &buf[ len ], bufsize-len, fmt, ap ) ;
+   va_end( ap ) ;
+   xlog_write( SVC_LOG(sp), buf, len+cc, XLOG_NO_ERRNO | XLOG_NO_SIZECHECK ) ;
+}
+
diff --git a/xinetd/log.h b/xinetd/log.h
new file mode 100644 (file)
index 0000000..1b9ff95
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+#include <sys/socket.h>
+
+#include "defs.h"
+#include "access.h"
+
+/*
+ * $Id: log.h,v 1.2 2003/05/08 14:52:24 steveg Exp $
+ */
+
+/*
+ * Meaning of logtype flags:
+ *
+ *    L_NONE:           no logging
+ *    L_FILE:           log output goes to a file
+ *    L_SYSLOG:         log output goes to syslog(3)
+ *    L_COMMON_FILE:    log output goes to the file specified in defaults
+ */
+typedef enum { L_NONE = 0, L_FILE, L_SYSLOG, L_COMMON_FILE } logtype_e ;
+
+struct filelog
+{
+   char     *fl_filename ;                  /* always malloc'ed      */
+   unsigned fl_soft_limit ;
+   unsigned fl_hard_limit ;
+} ;
+
+#define FILELOG_SIZE_CONTROL( flp )      ( flp->fl_soft_limit != 0 )   
+
+
+struct syslog
+{
+   int sl_facility ;
+   int sl_level ;
+} ;
+
+struct log
+{
+   logtype_e      l_type ;
+   struct filelog l_fl ;
+   struct syslog  l_sl ;
+} ;
+
+#define LOG_GET_TYPE( lp )           (lp)->l_type
+#define LOG_SET_TYPE( lp, type )     (lp)->l_type = (type)
+
+#define LOG_GET_FILELOG( lp )        (&(lp)->l_fl)
+#define LOG_GET_SYSLOG( lp )         (&(lp)->l_sl)
+
+const char *xaddrname(const union xsockaddr *inaddr);
+uint16_t xaddrport(const union xsockaddr *inaddr);
+void svc_log_success(struct service *sp, const connection_s *cp,pid_t pid);
+void svc_log_failure(struct service *sp, const connection_s *cp,access_e access_failure);
+void svc_log_exit(struct service *sp,const struct server *serp);
+void svc_logprint(struct service *sp,const char *line_id,const char *fmt,...)
+#ifdef __GNUC__
+       __attribute__ ((format (printf, 3, 4)));
+#else
+       ;
+#endif
+#endif   /* LOG_H */
+
diff --git a/xinetd/logctl.c b/xinetd/logctl.c
new file mode 100644 (file)
index 0000000..c92f656
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <fcntl.h>
+
+#include "logctl.h"
+#include "msg.h"
+#include "xconfig.h"
+#include "main.h"
+#include "sconf.h"
+
+
+static xlog_h start_filelog( const char *id, struct filelog *flp )
+{
+   xlog_h   xh ;
+   int      fd ;
+   int      log_file_mode = ( debug.on ) ? 0644 : LOG_FILE_MODE ;
+   const char *func = "start_filelog" ;
+
+   xh = xlog_create( XLOG_FILELOG, id, XLOG_NOFLAGS,
+                     flp->fl_filename, LOG_OPEN_FLAGS, log_file_mode ) ;
+   if ( xh == NULL )
+   {
+      msg( LOG_ERR, func, "creation of %s log failed", id ) ;
+      return( NULL ) ;
+   }
+
+   if ( xlog_control( xh, XLOG_GETFD, &fd ) != XLOG_ENOERROR ||
+       fcntl( fd,  F_SETFD, FD_CLOEXEC ) == -1 )
+   {
+      msg( LOG_ERR, func, "Failed to set close-on-exec flag for log file" ) ;
+      xlog_destroy( xh ) ;
+      return( NULL ) ;
+   }
+
+   ps.rws.descriptors_free-- ;
+
+   if ( FILELOG_SIZE_CONTROL( flp ) )
+      (void) xlog_control( xh,
+                     XLOG_LIMITS, flp->fl_soft_limit, flp->fl_hard_limit ) ;
+
+   return( xh ) ;
+}
+
+
+/*
+ * This function is invoked when a xlog detects an error (for example,
+ * exceeding the file size limit).
+ * The function just enters a log message.
+ * 
+ * NOTE: We could destroy the xlog at this point but we choose not to.
+ */
+static void log_in_error( xlog_h xh, int error_code, void *arg )
+{
+   struct service     *sp       = SP( arg ) ;
+   const char         *log_id   = ( sp == NULL ) ? "common" : SVC_ID( sp ) ;
+   const char         *func     = "log_in_error" ;
+
+#ifdef lint
+   xh = xh ;
+#endif
+   if ( error_code == XLOG_ESIZE )
+      msg( LOG_ERR, func, "Size of %s log exceeded hard limit", log_id ) ;
+   else
+      msg( LOG_ERR, func, "Error in %s log: %d", log_id, error_code ) ;
+}
+
+/*
+ * Start logging for the specified service.
+ * The current configuration is used to determine the common log file.
+ */
+status_e log_start( struct service *sp, xlog_h *xhp )
+{
+   xlog_h        xh ;
+   const char   *sid   = SVC_ID( sp ) ;
+   struct log   *lp    = SC_LOG( SVC_CONF( sp ) ) ;
+   const char   *func  = "log_start" ;
+
+   switch ( lp->l_type )
+   {
+      case L_NONE:
+         xh = NULL ;
+         break ;
+
+      case L_SYSLOG:
+         xh = xlog_create( XLOG_SYSLOG, sid, XLOG_NOFLAGS, 
+                  LOG_GET_SYSLOG( lp )->sl_facility,
+                  LOG_GET_SYSLOG( lp )->sl_level ) ;
+         if ( xh == NULL )
+         {
+            msg( LOG_ERR, func, "failed to create a log for service %s", sid ) ;
+            return( FAILED ) ;
+         }
+         xlog_control( xh, XLOG_CALLBACK, log_in_error, (void *)sp ) ;
+         break ;
+      
+      case L_FILE:
+         /*
+          * NOTE: if the same file is specified for more than one service,
+          *         it will be opened as many times.
+          *         Furthermore, size control will not be accurate.
+          */
+         xh = start_filelog( sid, LOG_GET_FILELOG( lp ) ) ;
+         if ( xh == NULL )
+            return( FAILED ) ;
+         (void) xlog_control( xh, XLOG_CALLBACK, log_in_error, (void *)sp ) ;
+         break ;
+      
+      case L_COMMON_FILE:
+         if ( DEFAULT_LOG( ps ) == NULL )
+            if ( DEFAULT_LOG_ERROR( ps ) )
+               return( FAILED ) ;
+            else
+            {
+               xh = start_filelog( "default", 
+                              LOG_GET_FILELOG( SC_LOG( DEFAULTS( ps ) ) ) ) ;
+               if ( xh == NULL )
+               {
+                  DEFAULT_LOG_ERROR( ps ) = TRUE ;
+                  return( FAILED ) ;
+               }
+               DEFAULT_LOG( ps ) = xh ;
+               (void) xlog_control( xh,
+                           XLOG_CALLBACK, log_in_error, VOID_NULL ) ;
+            }
+         else
+            xh = DEFAULT_LOG( ps ) ;
+         break ;
+
+      default:         /* SHOULDN'T HAPPEN */
+         msg( LOG_ERR, func, "bad log type (%d) for service %s",
+            (int) LOG_GET_TYPE( lp ), sid ) ;
+         return( FAILED ) ;
+   }
+   *xhp = xh ;
+   return( OK ) ;
+}
+
+
+void log_end( struct log *lp, xlog_h xh )
+{
+   const char *func = "log_end" ;
+
+   if ( xh == NULL )      /* shouldn't be NULL but just in case */
+   {
+      msg( LOG_NOTICE, func, "called with NULL handle" ) ;
+      return ;
+   }
+
+   switch ( LOG_GET_TYPE( lp ) )
+   {
+      case L_FILE:
+         ps.rws.descriptors_free++ ;
+         /* FALL THROUGH */
+      
+      case L_SYSLOG:
+         xlog_destroy( xh ) ;
+      case L_NONE:
+      case L_COMMON_FILE:
+         ;
+   }
+}
+
diff --git a/xinetd/logctl.h b/xinetd/logctl.h
new file mode 100644 (file)
index 0000000..0b303e4
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef LOGCTL_H
+#define LOGCTL_H
+
+#include "defs.h"
+#include "xlog.h"
+#include "log.h"
+
+status_e log_start(struct service *sp,xlog_h *xhp);
+void log_end(struct log *lp,xlog_h xh);
+
+#endif
+
diff --git a/xinetd/main.c b/xinetd/main.c
new file mode 100644 (file)
index 0000000..4ca383a
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "main.h"
+#include "init.h"
+#include "msg.h"
+#include "internals.h"
+#include "signals.h"
+#include "service.h"
+#include "sconf.h"
+#include "xtimer.h"
+#include "sensor.h"
+#include "xmdns.h"
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+static void main_loop(void);
+static void find_bad_fd(void) ;
+
+/*
+ * The following are the only global variables of this program
+ */
+struct program_state ps ;
+struct debug debug ;
+char program_version[] = XINETD_VERSION ;
+int signals_pending[2] = {-1, -1} ;
+
+/*
+ * This is where the story starts...
+ */
+int main( int argc, char *argv[] )
+{
+   const char            *func = "main" ;
+
+   init_daemon( argc, argv ) ;
+#ifdef HAVE_MDNS
+   xinetd_mdns_init();
+#endif
+   init_services() ;
+
+   /* Do the chdir after reading the config file.  Relative path names
+    * will work better.  
+    */
+   if (chdir("/") < 0) {
+      msg(LOG_ERR, func, "Can't chdir to /: %m");
+   }
+
+   /* Print out all the options we're compiled with.  Makes support 
+    * a tad easier.
+    * Also, try to get them all into one syslog message for atomicity
+    */
+   msg( LOG_NOTICE, func, "%s started with "
+#ifdef LIBWRAP
+   "libwrap "
+#endif
+#ifdef HAVE_LOADAVG
+   "loadavg "
+#endif
+#ifdef HAVE_MDNS
+   "mdns "
+#endif
+#ifdef HAVE_HOWL
+   "howl "
+#endif
+#ifdef HAVE_DNSREGISTRATION
+   "rendezvous "
+#endif
+#if !defined(LIBWRAP) && !defined(HAVE_LOADAVG) && !defined(HAVE_MDNS) && !defined(HAVE_HOWL) && !defined(HAVE_DNSREGISTRATION)
+   "no "
+#endif
+   "options compiled in."
+   , XINETD_VERSION );
+
+   msg( LOG_NOTICE, func, "Started working: %d available service%s",
+      ps.rws.available_services,
+         ( ps.rws.available_services != 1 ) ? "s" : "" ) ;
+
+   /*
+    * The reason for doing the setjmp here instead of in main_loop is
+    * that setjmp is not guaranteed to restore register values which
+    * can cause a problem for register variables
+    */
+   if ( sigsetjmp( ps.rws.env, 1 ) == 0 )
+      ps.rws.env_is_valid = TRUE ;
+
+   main_loop() ;
+
+   /* NOTREACHED */
+   exit(1);
+}
+
+
+/*
+ * What main_loop does:
+ *
+ *      select on all active services
+ *      for each socket where a request is pending
+ *         try to start a server
+ */
+static void main_loop(void)
+{
+   const char      *func = "main_loop" ;
+   struct timeval   tv, *tvptr = NULL;
+
+   FD_SET(signals_pending[0], &ps.rws.socket_mask);
+   if ( signals_pending[0] > ps.rws.mask_max )
+      ps.rws.mask_max = signals_pending[0] ;
+   if ( signals_pending[1] > ps.rws.mask_max )
+      ps.rws.mask_max = signals_pending[1] ;
+
+   for ( ;; )
+   {
+      fd_set read_mask ;
+      int n_active ;
+      unsigned u ;
+
+      if ( debug.on ) 
+         msg( LOG_DEBUG, func,
+               "active_services = %d", ps.rws.active_services ) ;
+
+      /* get the next timer value, if there is one, and select for that time */
+      if( (tv.tv_sec = xtimer_nexttime()) >= 0 ) {
+         tv.tv_usec = 0;
+         tvptr = &tv;
+      } else {
+         tvptr = NULL;
+      }
+
+      read_mask = ps.rws.socket_mask ;
+      n_active = select( ps.rws.mask_max+1, &read_mask,
+                        FD_SET_NULL, FD_SET_NULL, tvptr ) ;
+      if ( n_active == -1 )
+      {
+         if ( errno == EINTR ) {
+            continue ;
+         } else if ( errno == EBADF )
+            find_bad_fd() ;
+         continue ;
+      }
+      else if ( n_active == 0 ) {
+         xtimer_poll();
+         continue ;
+      }
+
+      if ( debug.on )
+         msg( LOG_DEBUG, func, "select returned %d", n_active ) ;
+
+      xtimer_poll();
+
+      if( FD_ISSET(signals_pending[0], &read_mask) ) {
+         check_pipe();
+            if ( --n_active == 0 )
+               continue ;
+      }
+
+#ifdef HAVE_MDNS
+      if( xinetd_mdns_poll() == 0 )
+         if ( --n_active == 0 )
+            continue ;
+#endif
+
+      for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+      {
+         struct service *sp ;
+
+         sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+
+         if ( ! SVC_IS_ACTIVE( sp ) )
+            continue ;
+
+         if ( FD_ISSET( SVC_FD( sp ), &read_mask ) )
+         {
+            svc_request( sp ) ;
+            if ( --n_active == 0 )
+               break ;
+         }
+      }
+      if ( n_active > 0 )
+         msg( LOG_ERR, func, "%d descriptors still set", n_active ) ;
+   }
+}
+
+
+/*
+ * This function identifies if any of the fd's in the socket mask
+ * is bad. We use it in case select(2) returns EBADF
+ * When we identify such a bad fd, we remove it from the mask
+ * and deactivate the service.
+ */
+static void find_bad_fd(void)
+{
+   int fd ;
+   struct stat st ;
+   unsigned bad_fd_count = 0 ;
+   const char *func = "find_bad_fd" ;
+
+   for ( fd = 0 ; (unsigned)fd < ps.ros.max_descriptors ; fd++ )
+      if ( FD_ISSET( fd, &ps.rws.socket_mask ) && fstat( fd, &st ) == -1 )
+      {
+         int found = FALSE ;
+         unsigned u ;
+
+         for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
+         {
+            register struct service *sp ;
+
+            sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+
+            if ( ! SVC_IS_AVAILABLE( sp ) )
+               continue ;
+
+            if ( SVC_FD( sp ) == fd )
+            {
+               msg( LOG_ERR, func,
+                  "file descriptor of service %s has been closed",
+                              SVC_ID( sp ) ) ;
+               svc_deactivate( sp ) ;
+               found = TRUE ;
+               break ;
+            }
+         }
+         if ( ! found )
+         {
+            FD_CLR( fd, &ps.rws.socket_mask ) ;
+            msg( LOG_ERR, func,
+               "No active service for file descriptor %d\n", fd ) ;
+            bad_fd_count++ ;
+         }
+      }
+   if ( bad_fd_count == 0 )
+      msg( LOG_NOTICE, func,
+         "select reported EBADF but no bad file descriptors were found" ) ;
+}
+
+
+/*
+ * Deactivates all active processes.
+ * The real reason for doing this instead of just exiting is
+ * to deregister the RPC services
+ */
+void quit_program(void)
+{
+   unsigned u ;
+   struct service_config *scp = NULL;
+   const char *func = "quit_program" ;
+
+   destroy_global_access_list() ;
+   
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
+      scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
+      
+      /* This is essentially the same as the following function, 
+       * Except we forcibly deactivate them, rather than just 
+       * send signals.
+       */
+      if( SC_IS_INTERNAL( scp ) )
+         svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+      if( SC_REDIR_ADDR(scp) != NULL )
+         svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+      if( SC_IS_RPC( scp ) )
+         svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+   }
+
+   if ( ps.ros.pid_file ) {
+      unlink(ps.ros.pid_file);
+   }
+
+   msg( LOG_WARNING, func, "Exiting..." ) ;
+   exit( 0 ) ;
+}
+
+
+void terminate_program(void)
+{
+   unsigned u ;
+   struct service_config *scp = NULL;
+   void terminate_servers(struct service *);
+
+   for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
+      scp = SVC_CONF( SP(pset_pointer(SERVICES(ps), u)) );
+
+      /* Terminate the service if it is:
+       * 1) internal (if we don't, it'll zombie)
+       * 2) a redirector (again, if we don't it'll zombie)
+       * 3) It's RPC (we must deregister it.
+       */
+      if( SC_IS_INTERNAL( scp ) )
+         terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+      if( SC_REDIR_ADDR( scp ) != NULL )
+         terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+      if( SC_IS_RPC( scp ) )
+         terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
+   }
+   quit_program() ;
+}
+
diff --git a/xinetd/main.h b/xinetd/main.h
new file mode 100644 (file)
index 0000000..8ca1d87
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "state.h"
+#include "defs.h"
+
+extern char program_version[];
+extern struct program_state ps;
+extern int signals_pending[2];
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void quit_program(void);
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void terminate_program(void);
+
+#endif
diff --git a/xinetd/mask.h b/xinetd/mask.h
new file mode 100644 (file)
index 0000000..f511557
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef MASK_H
+#define MASK_H
+
+/*
+ * $Id: mask.h,v 1.1.1.1 2003/02/19 17:29:28 bbraun Exp $
+ */
+
+#include "config.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/*
+ * Macros about masks - Note: 64 bits is needed because of attr.h
+ */
+
+typedef uint64_t mask_t;
+
+#define MASK_NULL                   ((mask_t *)0)
+
+#define XMASK( v )                  ( (mask_t)1 << ( (v)-1 ) )
+
+#define M_CLEAR_ALL( mask )         (mask) = 0
+#define M_ASSIGN( mask1, mask2 )    (mask1) = (mask2)
+#define M_ARE_ALL_CLEAR( mask )     ( (mask) == 0 )
+#define M_SET( mask, v )            (mask) |= XMASK(v)
+#define M_CLEAR( mask, v )          (mask) &= ~XMASK(v)
+#define M_IS_SET( mask, v )         ( (mask) & XMASK(v) )
+#define M_IS_CLEAR( mask, v )       ( ! M_IS_SET( mask, v ) )
+
+#define M_AND( mres, m1, m2 )       ( (mres) = (m1) & (m2) )
+#define M_OR( mres, m1, m2 )        ( (mres) = (m1) | (m2) )
+#define M_XOR( mres, m1, m2 )       ( (mres) = (m1) ^ (m2) )
+
+#endif   /* MASK_H */
diff --git a/xinetd/msg.c b/xinetd/msg.c
new file mode 100644 (file)
index 0000000..4acdec9
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <syslog.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "xlog.h"
+#include "str.h"
+#include "msg.h"
+#include "defs.h"
+#include "options.h"
+#include "xconfig.h"
+#include "util.h"
+#include "nvlists.h"
+#include "main.h"
+#include "parse.h"
+
+static const struct name_value priorities[] =
+   {
+      { "WARNING",   LOG_WARNING  },
+      { "ERROR",     LOG_ERR      },
+      { "CRITICAL",  LOG_CRIT     },
+      { "NOTICE",    LOG_NOTICE   },
+      { "DEBUG",     LOG_DEBUG    },
+      { "INFO",      LOG_INFO     },
+      { NULL,        1            },
+      { "UNKNOWN",   0            }
+   } ;
+
+#define BUFSIZE                     2048
+
+#define DEFAULT_SYSLOG_LEVEL         LOG_INFO
+
+const char *msg_init(void)
+{
+   xlog_h      xh ;
+   int         fd ;
+   xlog_e      type_of_xlog ;
+   bool_int    facility_error = FALSE ;
+   const char *func            = "msg_init" ;
+
+   if ( debug.on )
+   {
+      type_of_xlog = XLOG_FILELOG ;
+      xh = xlog_create( type_of_xlog, program_name, XLOG_NOFLAGS,
+                                 "/dev/tty", O_APPEND + O_WRONLY, 0 ) ;
+      debug.fd = -1 ;
+   }
+   else
+   {
+      if ( filelog_option )
+      {
+         type_of_xlog = XLOG_FILELOG ;
+         xh = xlog_create( type_of_xlog, program_name,
+                  XLOG_PRINT_ID + XLOG_PRINT_PID,
+                     filelog_option_arg, LOG_OPEN_FLAGS, LOG_FILE_MODE ) ;
+      }
+      else
+      {
+         int facility = DEFAULT_SYSLOG_FACILITY ;
+         
+         if ( syslog_option )
+         {
+            const struct name_value *nvp ;
+
+            nvp = nv_find_value( syslog_facilities, syslog_option_arg ) ;
+            if ( nvp != NULL )
+               facility = nvp->value ;
+            else
+               facility_error = TRUE ;
+         }
+
+         type_of_xlog = XLOG_SYSLOG ;
+         xh = xlog_create( type_of_xlog, program_name, XLOG_NOFLAGS,
+                                       facility, DEFAULT_SYSLOG_LEVEL ) ;
+      }
+   }
+
+   if ( xh == NULL )
+   {
+      /*
+       * This simply returns the most likely reason for failure.
+       * We can't do any better since xlog_create does not return an
+       * error code.
+       */
+      if ( type_of_xlog == XLOG_SYSLOG )
+         return( "can't connect to syslog" ) ;
+      else if ( type_of_xlog == XLOG_FILELOG )
+         return( "can't open log file" ) ;
+      else
+         return( "unknown reason" ) ;
+   }
+   
+   /*
+    * XXX:   we shouldn't have to check the xlog type.
+    *         xlog_control should not succeed if the undelying logging
+    *         object does not support the XLOG_GETFD operation.
+    */
+   if ( type_of_xlog == XLOG_FILELOG &&
+            xlog_control( xh, XLOG_GETFD, &fd ) == XLOG_ENOERROR )
+   {
+      if ( fcntl( fd, F_SETFD, FD_CLOEXEC ) == -1 )
+      {
+         xlog_destroy( xh ) ;
+         return( "can't set close-on-exec flag of log file" ) ;
+      }
+      if ( debug.on )
+         debug.fd = fd ;
+   }
+   
+   ps.rws.program_log = xh ;
+
+   if ( facility_error )
+      msg( LOG_ERR, func, "Bad syslog facility: %s", syslog_option_arg ) ;
+   return( CHAR_NULL ) ;
+}
+
+
+void msg_suspend(void)
+{
+   (void) xlog_control( ps.rws.program_log, XLOG_PREEXEC ) ;
+}
+
+
+void msg_resume(void)
+{
+   (void) xlog_control( ps.rws.program_log, XLOG_POSTEXEC ) ;
+}
+
+
+/*
+ * The size argument is a value-result argument
+ */
+static int
+#ifdef __GNUC__
+__attribute__ ((format (printf, 5, 0)))
+#endif
+prepare_buffer( int level, 
+                const char *func, 
+                char *buf, 
+                unsigned size, 
+                const char *fmt, 
+                va_list ap )
+{
+   int         cc ;
+   char        *bufstart   = buf ;
+   unsigned    bytes_left  = size ;
+
+   /*
+    * Check if we need to print the level name
+    */
+   if ( debug.on || filelog_option )
+   {
+      cc = strx_nprint( bufstart, bytes_left,
+                                 "%s: ", nv_get_name( priorities, level ) ) ;
+      bufstart += cc ;
+      bytes_left -= cc ;
+   }
+
+   /*
+    * Check if we need to print the function name
+    */
+   if ( debug.on || level == LOG_CRIT )
+   {
+      cc = strx_nprint( bufstart, bytes_left, "%d {%s} ", getpid(), func ) ;
+      bufstart += cc ;
+      bytes_left -= cc ;
+   }
+
+   cc = strx_nprintv( bufstart, bytes_left, fmt, ap ) ;
+
+   bytes_left -= cc ;
+
+   return( size - bytes_left ) ;
+}
+
+
+/* VARARGS3 */
+void msg( int level, const char *func, const char *fmt, ...)
+{
+   va_list   ap ;
+   char      buf[ BUFSIZE ] ;
+   int      len ;
+
+   va_start( ap, fmt ) ;
+   len = prepare_buffer( level, func, buf, sizeof( buf ), fmt, ap ) ;
+   va_end( ap ) ;
+
+   xlog_write( ps.rws.program_log, buf, len, XLOG_SET_LEVEL, level ) ;
+}
+
+
+/*
+ * Parser message.
+ * There are 2 differences from msg():
+ *      1) parsemsg() prints the line #
+ *      2) parsemsg() does not interpret %m
+ */
+/* VARARGS3 */
+void parsemsg( int msg_level, const char *func, const char *fmt, ...)
+{
+   va_list   ap ;
+   char      buf[ BUFSIZE ] ;
+   int       cc ;
+   int       len ;
+
+   va_start( ap, fmt ) ;
+   len = prepare_buffer( msg_level, func, buf, sizeof( buf ), fmt, ap ) ;
+   va_end( ap ) ;
+
+   cc = strx_nprint( &buf[ len ], sizeof(buf)-len, 
+                     " [file=%s] [line=%d]", current_file, line_count ) ;
+   len += cc ;
+
+   xlog_write( ps.rws.program_log, buf, len, 
+         XLOG_NO_ERRNO + XLOG_SET_LEVEL, msg_level ) ;
+}
+
diff --git a/xinetd/msg.h b/xinetd/msg.h
new file mode 100644 (file)
index 0000000..736bba3
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef MSG_H
+#define MSG_H
+
+#include <syslog.h>
+
+const char *msg_init(void);
+void msg_suspend(void);
+void msg_resume(void);
+void msg(int level,const char *func,const char *fmt,...)
+#ifdef __GNUC__ 
+        __attribute__ ((format (printf, 3, 4)));
+#else
+        ;
+#endif
+void parsemsg(int msg_level,const char *func,const char *fmt,...)
+#ifdef __GNUC__ 
+        __attribute__ ((format (printf, 3, 4)));
+#else
+        ;
+#endif
+#endif
diff --git a/xinetd/nvlists.c b/xinetd/nvlists.c
new file mode 100644 (file)
index 0000000..b66eda6
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <syslog.h>
+
+#include "nvlists.h"
+#include "sconf.h"
+
+
+/*
+ * A NULL value for the name field marks the end of the table
+ */
+
+const struct name_value service_types[] =
+   {
+#ifndef NO_RPC
+      { "RPC",                        ST_RPC                  },
+#endif
+      { "INTERNAL",                   ST_INTERNAL             },
+      { "UNLISTED",                   ST_UNLISTED             },
+      { "SPECIAL",                    ST_SPECIAL              },
+      { "TCPMUX",                     ST_TCPMUX               },
+      { "TCPMUXPLUS",                 ST_TCPMUXPLUS           },
+      { CHAR_NULL,                    0                       }
+   } ;
+
+
+/* REUSE is only used for backward compatibility.  All services are now reuse */
+const struct name_value service_flags[] =
+   {
+      { "REUSE",                      SF_REUSE               },
+      { "INTERCEPT",                  SF_INTERCEPT           },
+      { "NORETRY",                    SF_NORETRY             },
+      { "IDONLY",                     SF_IDONLY              },
+      { "NAMEINARGS",                 SF_NAMEINARGS          },
+      { "NODELAY",                    SF_NODELAY             },
+      { "KEEPALIVE",                  SF_KEEPALIVE           },
+      { "NOLIBWRAP",                  SF_NOLIBWRAP           },
+      { "SENSOR",                     SF_SENSOR              },
+      { "IPv4",                       SF_IPV4                },
+      { "IPv6",                       SF_IPV6                },
+      { CHAR_NULL,                    0                      }
+   } ;
+
+
+const struct name_value socket_types[] =
+   {
+      { "stream",                     SOCK_STREAM           },
+      { "dgram",                      SOCK_DGRAM            },
+      { "raw",                        SOCK_RAW              },
+      { "seqpacket",                  SOCK_SEQPACKET        },
+      { CHAR_NULL,                    1                     },
+      { "BAD SOCKET TYPE",            0                     }
+   } ;
+
+
+const struct name_value success_log_options[] =
+   {
+      { "HOST",        LO_HOST     },
+      { "DURATION",    LO_DURATION },
+      { "EXIT",        LO_EXIT     },
+      { "PID",         LO_PID      },
+      { "USERID",      LO_USERID   },
+      { "TRAFFIC",     LO_TRAFFIC  },
+      { CHAR_NULL,     0           }
+   } ;
+
+
+const struct name_value failure_log_options[] = 
+   {
+      { "HOST",        LO_HOST     },
+      { "ATTEMPT",     LO_ATTEMPT  },
+      { "USERID",      LO_USERID   },
+      { CHAR_NULL,     0           }
+   } ;
+
+
+
+const struct name_value syslog_facilities[] =
+   {
+      { "daemon",         LOG_DAEMON      },
+      { "auth",           LOG_AUTH        },
+#ifdef linux
+      { "authpriv",       LOG_AUTHPRIV    },
+#endif
+      { "user",           LOG_USER        },
+#ifdef LOG_MAIL
+      { "mail",           LOG_MAIL        },
+#endif
+#ifdef LOG_LPR
+      { "lpr",            LOG_LPR         },
+#endif
+#ifdef LOG_NEWS
+      { "news",           LOG_NEWS        },
+#endif
+#ifdef LOG_UUCP
+      { "uucp",           LOG_UUCP        },
+#endif
+#ifdef LOG_FTP
+      { "ftp",            LOG_FTP         },
+#endif
+      { "local0",         LOG_LOCAL0      },
+      { "local1",         LOG_LOCAL1      },
+      { "local2",         LOG_LOCAL2      },
+      { "local3",         LOG_LOCAL3      },
+      { "local4",         LOG_LOCAL4      },
+      { "local5",         LOG_LOCAL5      },
+      { "local6",         LOG_LOCAL6      },
+      { "local7",         LOG_LOCAL7      },
+      { CHAR_NULL,        1               },
+      { "BAD FACILITY",   0               }
+   } ;
+
+
+const struct name_value syslog_levels[] = 
+   {
+      { "emerg",         LOG_EMERG      },
+      { "alert",         LOG_ALERT      },
+      { "crit",          LOG_CRIT       },
+      { "err",           LOG_ERR        },
+      { "warning",       LOG_WARNING    },
+      { "notice",        LOG_NOTICE     },
+      { "info",          LOG_INFO       },
+      { "debug",         LOG_DEBUG      },
+      { CHAR_NULL,       1              },
+      { "BAD LEVEL",     0              }
+   } ;
+
diff --git a/xinetd/nvlists.h b/xinetd/nvlists.h
new file mode 100644 (file)
index 0000000..432f4d4
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef NVLISTS_H
+#define NVLISTS_H
+
+#include "defs.h"
+
+extern const struct name_value service_types[];
+extern const struct name_value service_flags[];
+extern const struct name_value socket_types[];
+extern const struct name_value success_log_options[];
+extern const struct name_value failure_log_options[];
+extern const struct name_value syslog_facilities[];
+extern const struct name_value syslog_levels[];
+
+#endif
diff --git a/xinetd/options.c b/xinetd/options.c
new file mode 100644 (file)
index 0000000..b058b6a
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "str.h"
+#include "sio.h"
+#include "options.h"
+#include "main.h"
+#include "util.h"
+#include "internals.h" /* for enable_periodic_check() */
+
+/*
+ * $Id: options.c,v 1.7 2005/10/05 21:45:41 bbraun Exp $
+ */
+
+
+int filelog_option ;
+char * filelog_option_arg ;
+int syslog_option ;
+char * syslog_option_arg ;
+int logprocs_option ;
+unsigned logprocs_option_arg ;
+int stayalive_option=0;
+char *program_name ;
+int inetd_compat = 0 ;
+int dont_fork = 0;
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+static void usage(void);
+
+int opt_recognize( int argc, char *argv[] )
+{
+   int arg, arg_1 ;
+   unsigned int uarg_1;
+   unsigned long long ullarg_1;
+
+   program_name = strrchr( argv[ 0 ], '/' ) ;
+   program_name = ( program_name == NULL ) ? argv[ 0 ] : program_name + 1 ;
+
+   for ( arg = 1 ; arg < argc ; arg++ )
+      if ( argv[ arg ][ 0 ] == '-' && argv[ arg ][ 1 ] != 0 )
+      {
+         if ( strcmp( &argv[ arg ][ 1 ], "d" ) == 0 ) 
+            debug.on = 1 ;
+         else if ( strcmp( &argv[ arg ][ 1 ], "f" ) == 0 ) 
+         {
+            if ( ++arg == argc )
+               usage() ;
+            ps.ros.config_file = argv[ arg ];
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "filelog" ) == 0 ) 
+         {
+            if ( ++arg == argc )
+               usage() ;
+            filelog_option_arg = ( argv[ arg ] ) ;
+            filelog_option = 1 ;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "syslog" ) == 0 ) 
+         {
+            if ( ++arg == argc )
+               usage() ;
+            syslog_option_arg = ( argv[ arg ] ) ;
+            syslog_option = 1 ;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "reuse" ) == 0 ) 
+            ; /* This is now a null option, kept for compatibility */
+         else if ( strcmp( &argv[ arg ][ 1 ], "limit" ) == 0 ) 
+         {
+            if ( ++arg == argc )
+               usage() ;
+            if ( parse_ull( argv[ arg ], 10, NUL, &ullarg_1 ) || ullarg_1 < 0 )
+               usage() ;
+            ps.ros.process_limit = (rlim_t)ullarg_1 ;
+            if( ps.ros.process_limit != ullarg_1 )
+               usage() ;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "pidfile" ) == 0 ) {
+            if( ++arg ==argc )
+               usage () ;
+            ps.ros.pid_file = (char *)new_string( argv[arg] );
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "stayalive" )==0)
+            stayalive_option = 1;
+         else if ( strcmp( &argv[ arg ][ 1 ], "dontfork" )==0) {
+            dont_fork = 1;
+            stayalive_option = 1;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "logprocs" ) == 0 ) {
+            if ( ++arg == argc )
+               usage() ;
+            if ( parse_uint( argv[ arg ], 10, NUL, &uarg_1 ) || uarg_1 < 0 )
+               usage() ;
+            logprocs_option_arg = uarg_1 ;
+            logprocs_option = 1 ;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "shutdownprocs" ) == 0 ) 
+         {
+            if ( ++arg == argc )
+               usage() ;
+            Sprint(2, "The shutdownprocs option has been deprecated.\n");
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "cc" ) == 0 ) {
+            if ( ++arg == argc )
+               usage() ;
+            if ( parse_int( argv[ arg ], 10, NUL, &arg_1 ) || arg_1 < 0 )
+               usage() ;
+            ps.ros.cc_interval = arg_1;
+            enable_periodic_check( arg_1 ) ;
+         }
+         else if ( strcmp( &argv[ arg ][ 1 ], "version" ) == 0 ) {
+            fprintf(stderr, "%s", program_version);
+#ifdef LIBWRAP       
+            fprintf(stderr, " libwrap");
+#endif            
+#ifdef HAVE_LOADAVG
+            fprintf(stderr, " loadavg");
+#endif          
+            fprintf(stderr, "\n");
+            exit(0);
+         }
+         else if ( strcmp ( &argv[ arg ][ 1 ], "inetd_compat" ) == 0 )
+            inetd_compat = 1;
+      }
+      else
+         break ;
+
+   if ( filelog_option + syslog_option > 1 )
+      usage() ;
+
+   if ( argc - arg != 0 )
+      usage() ;
+   return( arg ) ;
+}
+
+static void usage(void)
+{
+   Sprint( 2, "Usage: %s [-d] [-f config_file] [-filelog filename] [-syslog facility] [-reuse] [-limit proc_limit] [-pidfile filename] [-logprocs limit] [-shutdownprocs limit] [-cc interval]\n", program_name ) ;
+   exit( 1 ) ;
+}
+
diff --git a/xinetd/options.h b/xinetd/options.h
new file mode 100644 (file)
index 0000000..5b78cba
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+
+
+extern int filelog_option;
+extern char *filelog_option_arg;
+extern int syslog_option;
+extern char *syslog_option_arg;
+extern int logprocs_option;
+extern unsigned logprocs_option_arg;
+extern int stayalive_option;
+extern char *program_name;
+extern int dont_fork;
+
+int opt_recognize(int argc,char *argv[]);
+
+#endif
diff --git a/xinetd/parse.c b/xinetd/parse.c
new file mode 100644 (file)
index 0000000..563940b
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include "str.h"
+#include "parse.h"
+#include "parsers.h"
+#include "msg.h"
+#include "parsesup.h"
+#include "addr.h"
+#include "includedir.h"
+#include "main.h"
+#include "sio.h"
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+
+/*
+ * A NULL value for the name field marks the end of the table
+ *
+ * The 3rd value is the number of attribute values.
+ * If the number is positive, exactly that many values must be specified.
+ * If the number is -1, 0 or more values may be specified.
+ * If the number is -2, 0 or more values may be specified and the operators
+ * '+=' and '-=' may be used.
+ */
+static const struct attribute service_attributes[] =
+{
+   { "socket_type",    A_SOCKET_TYPE,    1,  socket_type_parser     },
+   { "protocol",       A_PROTOCOL,       1,  protocol_parser        },
+   { "wait",           A_WAIT,           1,  wait_parser            },
+   { "user",           A_USER,           1,  user_parser            },
+   { "group",          A_GROUP,          1,  group_parser           },
+   { "server",         A_SERVER,         1,  server_parser          },
+   { "server_args",    A_SERVER_ARGS,   -1,  server_args_parser     },
+   { "instances",      A_INSTANCES,      1,  instances_parser       },
+   { "log_on_success", A_LOG_ON_SUCCESS,-2,  log_on_success_parser  },
+   { "log_on_failure", A_LOG_ON_FAILURE,-2,  log_on_failure_parser  },
+   { "log_type",       A_LOG_TYPE,      -1,  log_type_parser        },
+   { "only_from",      A_ONLY_FROM,     -2,  only_from_parser       },
+   { "no_access",      A_NO_ACCESS,     -2,  no_access_parser       },
+   { "access_times",   A_ACCESS_TIMES,  -1,  access_times_parser    },
+   { "type",           A_TYPE,          -1,  type_parser            },
+#ifndef NO_RPC
+   { "rpc_version",    A_RPC_VERSION,    1,  rpc_version_parser     },
+   { "rpc_number",     A_RPC_NUMBER,     1,  rpc_number_parser      },
+#endif
+   { "id",             A_ID,             1,  id_parser              },
+   { "env",            A_ENV,           -2,  env_parser             },
+   { "port",           A_PORT,           1,  port_parser            },
+   { "passenv",        A_PASSENV,       -2,  passenv_parser         },
+   { "flags",          A_FLAGS,         -1,  flags_parser           },
+   { "nice",           A_NICE,           1,  nice_parser            },
+   { "redirect",       A_REDIR,          2,  redir_parser           },
+   { "banner",         A_BANNER,         1,  banner_parser          },
+   { "bind",           A_BIND,           1,  bind_parser            },
+   { "interface",      A_BIND,           1,  bind_parser            },
+   { "per_source",     A_PER_SOURCE,     1,  per_source_parser      },
+   { "groups",         A_GROUPS,         1,  groups_parser          },
+   { "banner_success", A_BANNER_SUCCESS, 1,  banner_success_parser  },
+   { "banner_fail",    A_BANNER_FAIL,    1,  banner_fail_parser     },
+   { "cps",            A_CPS,            2,  cps_parser             },
+   { "disable",        A_SVCDISABLE,     1,  svcdisable_parser      },
+#ifdef HAVE_LOADAVG
+   { "max_load",       A_MAX_LOAD,       1,  max_load_parser        },
+#endif
+#ifdef RLIMIT_AS
+   { "rlimit_as",      A_RLIMIT_AS,      1,  rlim_as_parser         },
+#endif
+#ifdef RLIMIT_CPU
+   { "rlimit_cpu",     A_RLIMIT_CPU,     1,  rlim_cpu_parser        },
+#endif
+#ifdef RLIMIT_DATA
+   { "rlimit_data",    A_RLIMIT_DATA,    1,  rlim_data_parser       },
+#endif
+#ifdef RLIMIT_RSS
+   { "rlimit_rss",     A_RLIMIT_RSS,     1,  rlim_rss_parser        },
+#endif
+#ifdef RLIMIT_STACK
+   { "rlimit_stack",   A_RLIMIT_STACK,   1,  rlim_stack_parser      },
+#endif
+   { "v6only",         A_V6ONLY,         1,  v6only_parser          },
+   { "deny_time",      A_DENY_TIME,      1,  deny_time_parser       },
+   { "umask",          A_UMASK,          1,  umask_parser           },
+#ifdef HAVE_MDNS
+   { "mdns",           A_MDNS,           1,  mdns_parser            },
+#endif
+#ifdef LIBWRAP
+   { "libwrap",        A_LIBWRAP,        1, libwrap_parser          },
+#endif
+   { NULL,             A_NONE,          -1,  NULL                   }
+} ;
+
+static const struct attribute default_attributes[] =
+{
+   { "log_type",        A_LOG_TYPE,       -2,   log_type_parser       },
+   { "log_on_success",  A_LOG_ON_SUCCESS, -2,   log_on_success_parser },
+   { "log_on_failure",  A_LOG_ON_FAILURE, -2,   log_on_failure_parser },
+   { "disabled",        A_DISABLED,       -2,   disabled_parser       },
+   { "no_access",       A_NO_ACCESS,      -2,   no_access_parser      },
+   { "only_from",       A_ONLY_FROM,      -2,   only_from_parser      },
+   { "instances",       A_INSTANCES,       1,   instances_parser      },
+   { "passenv",         A_PASSENV,        -2,   passenv_parser        },
+   { "banner",          A_BANNER,          1,   banner_parser         },
+   { "bind",            A_BIND,            1,   bind_parser           },
+   { "interface",       A_BIND,            1,   bind_parser           },
+   { "per_source",      A_PER_SOURCE,      1,   per_source_parser     },
+   { "groups",          A_GROUPS,          1,   groups_parser         },
+   { "banner_success",  A_BANNER_SUCCESS,  1,   banner_success_parser },
+   { "banner_fail",     A_BANNER_FAIL,     1,   banner_fail_parser    },
+   { "cps",             A_CPS,             2,   cps_parser            },
+   { "enabled",         A_ENABLED,        -2,   enabled_parser        },
+#ifdef HAVE_LOADAVG
+   { "max_load",        A_MAX_LOAD,        1,   max_load_parser       },
+#endif
+   { "v6only",          A_V6ONLY,         1,    v6only_parser         },
+   { "umask",           A_UMASK,          1,    umask_parser          },
+#ifdef HAVE_MDNS
+   { "mdns",            A_MDNS,           1,    mdns_parser           },
+#endif
+   { NULL,              A_NONE,           0,    NULL                  }
+} ;
+
+
+#define MODIFIABLE( ap )       ( (ap)->a_nvalues == -2 )
+#define FIXED_VALUES( ap )         ( (ap)->a_nvalues > 0 )
+
+int line_count ;
+const char *current_file = NULL;
+
+static void get_service_entry( int fd, pset_h, const char *, 
+       struct service_config * );
+static void fill_attribute( unsigned attr_id, struct service_config *scp, 
+        struct service_config *def );
+static entry_e  find_next_entry(int , char **) ;
+static status_e parse_entry(entry_e, int, struct service_config *) ;
+
+/*
+ * Given the id, return the name (only the service attributes are searched)
+ */
+const char *attr_name_lookup( unsigned int id )
+{
+   const struct attribute *ap ;
+
+   for ( ap = &service_attributes[ 0 ] ; ap->a_name ; ap++ )
+      if ( id == ap->a_id )
+         return( ap->a_name ) ;
+   return( CHAR_NULL ) ;
+}
+
+
+void parse_end(void)
+{
+   endprotoent() ;
+   endpwent() ;
+   endgrent() ;
+   endnetent() ;
+   endhostent() ;
+}
+
+
+/*
+ * Parsing rules and rationale
+ *
+ * The parse_conf_file function parses a configuration file identified
+ * by a file descriptor and fills the service table and defaults of
+ * the configuration argument.
+ *
+ * The configuration information for a service comes from 2 sources: the
+ * service entry and, possibly, the defaults entry.
+ * Attributes specified in the defaults entry can be overriden or
+ * modified by the service entry. Modifiable attributes can be identified
+ * by the value -2 for the 'a_nvalues' field of the struct attribute. Those
+ * attributes with a different value for 'a_nvalues' are overridable ones.
+ * The modifiable attributes are filled in only if the entry tries to modify
+ * them.
+ */
+
+/*
+ * Read the configuration file (descriptor fd) and place all
+ * services found there in the configuration.
+ */
+void parse_conf_file( int fd, struct configuration *confp, const char *filename)
+{
+   pset_h                   sconfs       = CNF_SERVICE_CONFS( confp ) ;
+   struct service_config   *default_config   = CNF_DEFAULTS( confp ) ;
+   boolean_e                found_defaults   = NO ;
+   struct service_config    default_default_config ;
+   const char              *func      = "parse_conf_file" ;
+   int                      incfd;
+
+   line_count = 0 ;
+   current_file = filename;
+   CLEAR( default_default_config ) ;
+
+   for ( ;; )
+   {
+      entry_e   entry_type ;
+      char      *service_name  = NULL;
+
+      /*
+       * if find_next_entry is successful, service_name
+       * will point to malloc'ed memory
+       */
+      entry_type = find_next_entry( fd, &service_name ) ;
+      switch ( entry_type )
+      {
+      case INCLUDE_ENTRY:
+         {
+            int saved_line_count = line_count;
+            incfd = open(service_name, O_RDONLY);
+            if( incfd < 0 ) {
+               parsemsg( LOG_ERR, func, 
+                  "Unable to open included configuration file: %s", 
+                  service_name);
+               break;
+            }
+            parsemsg( LOG_DEBUG,func,
+               "Reading included configuration file: %s",service_name);
+            parse_conf_file(incfd, confp, service_name);
+           /*
+            * parse_conf_file eventually calls Srdline, try Sclosing it
+            * to unmmap memory.
+            */
+            Sclose(incfd);
+            /* Restore since we've returned from included file */
+            current_file = filename;
+            line_count = saved_line_count;
+         }
+         break;
+      case INCLUDEDIR_ENTRY:
+         {
+            int saved_line_count = line_count;
+            handle_includedir(service_name, confp);
+            current_file = filename;
+            line_count = saved_line_count;
+         }
+         break;
+      case SERVICE_ENTRY:
+         get_service_entry( fd, sconfs, service_name, default_config ) ; 
+         break ;
+      case DEFAULTS_ENTRY:
+         if ( found_defaults == YES )
+         {
+            parsemsg( LOG_ERR, func,
+            "only 1 defaults entry is allowed. This entry will be ignored" ) ;
+            skip_entry( fd ) ;
+         }
+         else if ( parse_entry( DEFAULTS_ENTRY, fd,
+                           default_config ) == OK ) {
+            found_defaults = YES ;
+           /*
+            * We must check bind_address to see if it was deferred. 
+            */
+            if (SC_SPECIFIED( default_config, A_BIND) && 
+                  SC_BIND_ADDR(default_config) == NULL)
+               M_CLEAR( default_config->sc_specified_attributes, A_BIND ) ;
+        }
+         break ;
+         
+      case BAD_ENTRY:
+         skip_entry( fd ) ;
+         break ;
+
+      case NO_ENTRY:
+         return ;
+      }
+      if (service_name)
+         free(service_name);
+   }
+}
+
+
+/*
+ * Find the next service entry.
+ * Look for a line of the form:
+ *
+ *      <white-space> service <white-space> <service_name>
+ *
+ * followed by a line containing only the ENTRY_BEGIN character
+ */
+static entry_e find_next_entry( int fd, char **snamep )
+{
+   char           *p ;
+   str_h           strp ;
+   char           *sname = NULL;
+   entry_e         entry_type=0;
+   char           *line = next_line( fd ) ;
+   const char     *func = "find_next_entry" ;
+
+   if ( line == CHAR_NULL )
+      return( NO_ENTRY ) ;
+
+   strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
+   if ( strp == NULL )
+   {
+      parsemsg( LOG_CRIT, func, "str_parse failed" ) ;
+      return( BAD_ENTRY ) ;
+   }
+
+   if ( ( p = str_component( strp ) ) == CHAR_NULL )
+   {
+      /*
+       * This shouldn't happen since it implies that there is a bug
+       * in next_line
+       */
+      parsemsg( LOG_WARNING, func, "empty line" ) ;
+      str_endparse( strp ) ;
+      return( BAD_ENTRY ) ;
+   }
+
+   /*
+    * Look for a keyword
+    */
+   if ( EQ( p, KW_SERVICE ) || EQ( p, KW_INCLUDE ) || EQ(p, KW_INCLUDEDIR))
+   {
+      if ( EQ( p, KW_INCLUDE ))
+         entry_type = INCLUDE_ENTRY;
+      else if ( EQ( p, KW_INCLUDEDIR ))
+         entry_type = INCLUDEDIR_ENTRY;
+
+      /*
+       * Now get the service name
+       */
+      if ( ( p = str_component( strp ) ) == CHAR_NULL )
+      {
+         parsemsg( LOG_ERR, func, "service name missing" ) ;
+         str_endparse( strp ) ;
+         return( BAD_ENTRY ) ;
+      }
+   
+      sname = new_string( p ) ;
+      if ( sname == CHAR_NULL )
+      {
+         out_of_memory( func ) ;
+         str_endparse( strp ) ;
+         return( BAD_ENTRY ) ;
+      }
+      str_endparse( strp ) ;
+
+      if( (entry_type == INCLUDE_ENTRY) || 
+          (entry_type == INCLUDEDIR_ENTRY))
+      {
+         *snamep = sname ;
+         return( entry_type ) ;
+      }
+      else
+         entry_type = SERVICE_ENTRY ;
+   }
+   else if ( EQ( p, KW_DEFAULTS ) )
+   {
+      str_endparse( strp ) ;
+      entry_type = DEFAULTS_ENTRY ;
+   }
+   else
+   {
+      parsemsg( LOG_ERR, func, "missing service keyword" ) ;
+      str_endparse( strp ) ;
+      return( BAD_ENTRY ) ;
+   }
+
+   /*
+    * Now look for ENTRY_BEGIN
+    */
+   line = next_line( fd ) ;
+   if ( line == NULL || ! line_has_only_1_char( line, ENTRY_BEGIN ) )
+   {
+      parsemsg( LOG_ERR, func,
+         "Service %s: missing '%c'", sname, ENTRY_BEGIN ) ;
+      if ( entry_type == SERVICE_ENTRY )
+         free( sname ) ;
+      return( BAD_ENTRY ) ;
+   }
+   *snamep = sname ;
+   return( entry_type ) ;
+}
+
+
+/*
+ * Get a service entry. Steps:
+ *
+ *      1. Parse entry attributes
+ *      2. Determine service id
+ *      3. Insert entry in table
+ */
+static void get_service_entry( int fd, 
+                                pset_h sconfs,
+                                const char *name,
+                                struct service_config *defaults )
+{
+   struct service_config   *scp ;
+   const char              *func = "get_service_entry" ;
+
+   scp = sc_alloc( name ) ;
+   if ( scp == NULL )
+   {
+      skip_entry( fd ) ;
+      return ;
+   }
+
+   /* Now fill in default attributes if given. */
+   if ( SC_SPECIFIED( defaults, A_LOG_ON_SUCCESS ) &&
+      ! SC_IS_PRESENT( scp, A_LOG_ON_SUCCESS) )
+      fill_attribute( A_LOG_ON_SUCCESS, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_LOG_ON_FAILURE ) &&
+      ! SC_IS_PRESENT( scp, A_LOG_ON_FAILURE ) )
+      fill_attribute( A_LOG_ON_FAILURE, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_ONLY_FROM ) &&
+      ! SC_IS_PRESENT( scp, A_ONLY_FROM ) )
+      fill_attribute( A_ONLY_FROM, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_NO_ACCESS ) &&
+      ! SC_IS_PRESENT( scp, A_NO_ACCESS ) )
+      fill_attribute( A_NO_ACCESS, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_PASSENV ) &&
+      ! SC_IS_PRESENT( scp, A_PASSENV ) )
+      fill_attribute( A_PASSENV, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_ACCESS_TIMES ) &&
+      ! SC_IS_PRESENT( scp, A_ACCESS_TIMES ) )
+      fill_attribute( A_ACCESS_TIMES, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_BANNER ) &&
+      ! SC_IS_PRESENT( scp, A_BANNER ) )
+      fill_attribute( A_BANNER, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_BANNER_SUCCESS ) &&
+      ! SC_IS_PRESENT( scp, A_BANNER_SUCCESS ) )
+      fill_attribute( A_BANNER_SUCCESS, scp, defaults ) ;
+   if ( SC_SPECIFIED( defaults, A_BANNER_FAIL ) &&
+      ! SC_IS_PRESENT( scp, A_BANNER_FAIL ) )
+      fill_attribute( A_BANNER_FAIL, scp, defaults ) ;
+  
+   if ( parse_entry( SERVICE_ENTRY, fd, scp ) == FAILED )
+   {
+      sc_free( scp ) ;
+      skip_entry( fd ) ;
+      return ;
+   }
+
+   /*
+    * If no service id was specified, set it equal to the service name
+    */
+   if ( ! SC_SPECIFIED( scp, A_ID ) ) {
+      if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
+         SC_PRESENT( scp, A_ID ) ;
+      else
+      {
+         out_of_memory( func ) ;
+         sc_free( scp ) ;
+         return ;
+      }
+   }
+
+   if ( ! (pset_add( sconfs, scp )) )
+   {
+      out_of_memory( func ) ;
+      sc_free( scp ) ;
+      return ;
+   }
+
+}
+
+
+/*
+ * Fill in scp the value of the modifiable attribute attr from def.
+ * These modifiable attributes are:
+ *      log_on_{success,failure}
+ *      only_from
+ *      no_access
+ *      passenv
+ */
+static void fill_attribute( unsigned attr_id, 
+                             struct service_config *scp, 
+                             struct service_config *def )
+{
+   switch ( attr_id )
+   {
+      case A_LOG_ON_SUCCESS:
+         M_ASSIGN( SC_LOG_ON_SUCCESS(scp), SC_LOG_ON_SUCCESS(def) ) ;
+         SC_PRESENT( scp, A_LOG_ON_SUCCESS ) ;
+         break ;
+
+      case A_LOG_ON_FAILURE:
+         M_ASSIGN( SC_LOG_ON_FAILURE(scp), SC_LOG_ON_FAILURE(def) ) ;
+         SC_PRESENT( scp, A_LOG_ON_FAILURE ) ;
+         break ;
+
+      case A_ONLY_FROM:
+         if ( addrlist_copy( SC_ONLY_FROM(def), &SC_ONLY_FROM(scp) ) == OK )
+            SC_PRESENT( scp, A_ONLY_FROM ) ;
+         break ;
+
+      case A_NO_ACCESS:
+         if ( addrlist_copy( SC_NO_ACCESS(def), &SC_NO_ACCESS(scp) ) == OK )
+            SC_PRESENT( scp, A_NO_ACCESS ) ;
+         break ;
+      
+      case A_PASSENV:
+         if ( copy_pset( SC_PASS_ENV_VARS(def),
+                           &SC_PASS_ENV_VARS(scp), 0 ) == OK )
+            SC_PRESENT( scp, A_PASSENV ) ;
+         break ;
+      
+      case A_ACCESS_TIMES:
+         if ( copy_pset( SC_ACCESS_TIMES(def),
+                           &SC_ACCESS_TIMES(scp), 0 ) == OK )
+            SC_PRESENT( scp, A_ACCESS_TIMES ) ;
+         break ;
+
+      case A_BANNER:
+           if ((SC_BANNER(scp) = new_string(SC_BANNER(def))) != NULL)
+               SC_PRESENT( scp, A_BANNER );
+         break ;
+
+      case A_BANNER_SUCCESS:
+           if ((SC_BANNER_SUCCESS(scp) = new_string(SC_BANNER_SUCCESS(def)))
+                  != NULL)
+               SC_PRESENT( scp, A_BANNER_SUCCESS );
+         break ;
+
+      case A_BANNER_FAIL:
+           if ((SC_BANNER_FAIL(scp) = new_string(SC_BANNER_FAIL(def))) != NULL)
+               SC_PRESENT( scp, A_BANNER_FAIL );
+         break ;
+   }
+}
+
+
+/*
+ * Find the attribute with the specified name
+ */
+static const struct attribute *attr_lookup( 
+       const struct attribute attr_array[], const char *attr_name )
+{
+   const struct attribute *ap ;
+   const char *func = "attr_lookup" ;
+
+   for ( ap = &attr_array[ 0 ] ; ap->a_name ; ap++ )
+      if ( EQ( attr_name, ap->a_name ) )
+         return ap;
+   if ( attr_array == service_attributes )
+      parsemsg( LOG_WARNING, func, "bad service attribute: %s", attr_name ) ;
+   else 
+      parsemsg( LOG_WARNING, func, 
+         "attribute: %s should not be in default section", attr_name ) ;
+   return NULL; 
+}
+
+
+/*
+ * Identify the attribute in <attr_name>.
+ *
+ * Check if
+ *      1) the attribute has been defined already
+ *      2) the value count is correct
+ *      3) the assign op is appropriate
+ *
+ * Invoke appropriate parser.
+ *
+ * This function will return FAILED only if its in the default section
+ * and an attribute cannot be ID'd. Otherwise, it returns OK.
+ */
+static status_e identify_attribute( entry_e entry_type, 
+                                 struct service_config *scp, 
+                                 const char *attr_name, 
+                                 enum assign_op op, 
+                                 pset_h attr_values )
+{
+   const struct attribute   *ap ;
+   const char         *func = "identify_attribute" ;
+
+   if ( entry_type == SERVICE_ENTRY )
+      ap = attr_lookup( service_attributes, attr_name ) ;
+   else
+      ap = attr_lookup( default_attributes, attr_name ) ;
+  
+   if ( ap == NULL )
+      return OK;   /* We simply ignore keywords not on the list */
+
+   if ( ! MODIFIABLE( ap ) )
+   {
+      if ( SC_SPECIFIED( scp, ap->a_id ) )
+      {
+         parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s",
+                  SC_NAME(scp), attr_name ) ;
+         return OK;
+      }
+
+      if ( op != SET_EQ )
+      {
+         parsemsg( LOG_WARNING, func,
+            "Service %s: operator '%s' cannot be used for attribute '%s'",
+               SC_NAME(scp), ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ;
+         return OK;
+      }
+   }
+   else      /* modifiable attribute */
+   {
+      /*
+       * For the defaults entry, '=' and '+=' have the same meaning
+       */
+      if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ )
+         op = PLUS_EQ ;
+   }
+
+   if ( FIXED_VALUES( ap ) &&
+        (unsigned)ap->a_nvalues != pset_count( attr_values ) )
+   {
+      parsemsg( LOG_WARNING, func,
+         "attribute %s expects %d values and %d values were specified",
+         attr_name, ap->a_nvalues, pset_count( attr_values ) ) ;
+      return OK;
+   }
+
+   if ( (*ap->a_parser)( attr_values, scp, op ) == OK )
+   {    /* This is the normal path. */
+       SC_SPECIFY( scp, ap->a_id ) ;
+   }
+   else if ( entry_type == SERVICE_ENTRY )
+   {
+      parsemsg( LOG_ERR, func,
+         "Error parsing attribute %s - DISABLING SERVICE", attr_name ) ;
+      SC_DISABLE( scp );
+   }
+   /*
+    * We are in the default section and an error was detected. At
+    * this point, we should terminate since whatever attribute 
+    * was trying to be specified cannot be propagated.
+    */
+   else if ( !debug.on )
+      return FAILED;
+   
+   return OK;
+}
+
+
+/*
+ * Read the entry line-by-line and add the information in scp
+ * Use defaults to initialize modifiable entry fields.
+ */
+static status_e parse_entry( entry_e entry_type, 
+                              int fd, 
+                              struct service_config *scp )
+{
+   static pset_h      attr_values = NULL;
+   char               *line ;
+   char               *attr_name ;
+   enum assign_op      op ;
+   const char         *func = "get_attributes" ;
+
+   if ( ! attr_values && ( attr_values = pset_create( 10, 10 ) ) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+
+   for ( ;; )
+   {
+      line = next_line( fd ) ;
+      if ( line == CHAR_NULL )
+      {
+         parsemsg( LOG_ERR, func, "incomplete entry" ) ;
+         return( FAILED ) ;
+      }
+
+      if ( line_has_only_1_char( line, ENTRY_END ) )
+         return( OK ) ;
+
+      if ( parse_line( line, &attr_name, &op, attr_values ) == FAILED )
+      {
+         pset_clear( attr_values ) ;
+         return( FAILED ) ;
+      }
+
+      if (identify_attribute( entry_type,
+               scp, attr_name, op, attr_values ) == FAILED )
+      {  
+        /*
+         * An error was detected in the default section. We will terminate
+         * since whatever attribute being specified cannot be propagated.
+         */
+         msg(LOG_ERR, func, 
+            "A fatal error was encountered while parsing the default section."
+           " xinetd will exit.");
+         Sclose( fd );
+         terminate_program();
+      }
+      pset_clear( attr_values ) ;
+   }
+}
+
diff --git a/xinetd/parse.h b/xinetd/parse.h
new file mode 100644 (file)
index 0000000..6aafb6d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef PARSE_H
+#define PARSE_H
+
+#include "defs.h"
+#include "conf.h"
+
+
+/*
+ * $Id: parse.h,v 1.4 2003/07/12 19:17:53 steveg Exp $
+ */
+
+typedef enum { NO_ENTRY, 
+               BAD_ENTRY, 
+               SERVICE_ENTRY, 
+               DEFAULTS_ENTRY, 
+               INCLUDE_ENTRY,
+               INCLUDEDIR_ENTRY
+} entry_e ;
+
+enum assign_op { SET_EQ, PLUS_EQ, MINUS_EQ } ;
+
+struct attribute
+{
+   const char  *a_name ;        /* name of attribute   */
+   unsigned     a_id ;          /* attribute id               */
+   int         a_nvalues ;     /* number of values    */
+   status_e    (*a_parser)() ; /* function that parses the attribute   */
+} ;
+
+
+#define ENTRY_BEGIN              '{'
+#define ENTRY_END                '}'
+#define COMMENT_BEGIN            '#'
+#define KW_SERVICE             "service"
+#define KW_DEFAULTS            "defaults"
+#define KW_INCLUDE             "include"
+#define KW_INCLUDEDIR          "includedir"
+
+extern int line_count;
+extern const char *current_file;
+
+const char *attr_name_lookup(unsigned int id);
+void parse_end(void);
+void parse_conf_file(int fd,struct configuration *confp, const char *filename);
+
+#endif /* PARSE_H */
diff --git a/xinetd/parsers.c b/xinetd/parsers.c
new file mode 100644 (file)
index 0000000..84297c5
--- /dev/null
@@ -0,0 +1,1515 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <ctype.h>
+#include <sys/file.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h> /* For LONG_MIN and LONG_MAX */
+#include <errno.h>
+#ifdef HAVE_LOADAVG
+#include <stdio.h>
+#endif
+
+#if defined(hpux) && !defined(X_OK)
+#define X_OK 1
+#endif
+
+#include "str.h"
+#include "parsers.h"
+#include "msg.h"
+#include "nvlists.h"
+#include "env.h"
+#include "xconfig.h"
+#include "addr.h"
+#include "libportable.h"
+#include "timex.h"
+#include "addr.h"      /* check_hostname() */
+
+#define NEW_SET( set, v1, v2 )                 \
+   if ( (set) == NULL && \
+   ( (set) = pset_create( (v1), (v2) ) ) == NULL )   \
+   {   \
+      out_of_memory( func ) ;   \
+      return( FAILED ) ;   \
+   }
+
+static void missing_attr_msg(const char *par, const char *item)
+{
+       parsemsg( LOG_WARNING, par, 
+          "attribute %s expects at least 1 value and none were given.",
+          item );
+}
+
+
+/*
+ * Find the flags corresponding to strings in "values" and apply
+ * them to "*maskp" (apply means add or remove depending on "op")
+ * "description" describes the type of flags.
+ */
+static status_e parse_value_list( pset_h values, 
+                                   mask_t *maskp, 
+                                   const struct name_value list[], 
+                                   enum assign_op op, 
+                                   const char *description )
+{
+   unsigned            u ;
+   const struct name_value  *nvp ;
+   const char               *func = "parse_value_list" ;
+
+   for ( u=0; u<pset_count( values ); u++ )
+   {
+      const char *name = (char *) pset_pointer( values, u ) ;
+
+      nvp = nv_find_value( list, name ) ;
+      if ( nvp != NULL )
+      {
+         if ( op == PLUS_EQ )
+            M_SET( *maskp, nvp->value ) ;
+         else
+            M_CLEAR( *maskp, nvp->value ) ;
+      }
+      else
+      {
+         parsemsg( LOG_WARNING, func, "Bad %s: %s", description, name ) ;
+        return( FAILED );
+      }
+   }
+   return( OK ) ;
+}
+
+
+status_e type_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   if ( pset_count( values ) >= 1 )
+   {
+      return( parse_value_list( values,
+                  &SC_TYPE(scp), service_types, PLUS_EQ, "service type" ) ) ;
+    }
+    else
+    {
+       missing_attr_msg("type_parser", "type");
+       return FAILED ;
+    }
+}
+
+
+status_e flags_parser( pset_h values, 
+                       struct service_config *scp, 
+                       enum assign_op op )
+{
+   if ( pset_count( values ) >= 1 )
+   {
+      return( parse_value_list( values,
+                  &SC_XFLAGS(scp), service_flags, PLUS_EQ, "service flag" ) ) ;
+    }
+    else
+    {
+       missing_attr_msg("flags_parser", "flags");
+       return FAILED ;
+    }
+}
+
+
+status_e socket_type_parser( const pset_h values, 
+                             struct service_config *scp, 
+                             enum assign_op op )
+{
+   const struct name_value *nvp ;
+   const char *type = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "socket_type_parser" ;
+
+   nvp = nv_find_value( socket_types, type ) ;
+   if ( nvp != NULL )
+   {
+      SC_SOCKET_TYPE(scp) = nvp->value ;
+      return( OK ) ;
+   }
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad socket type: %s", type ) ;
+      return( FAILED ) ;
+   }
+}
+
+
+status_e rpc_version_parser( pset_h values, 
+                             struct service_config *scp, 
+                             enum assign_op op )
+{
+   struct rpc_data *rdp = SC_RPCDATA( scp ) ;
+   char *version = (char *) pset_pointer( values, 0 ) ;
+   int min_version=0, max_version=0;
+   char *p = strchr( version, '-' ) ;
+   const char *func = "rpc_version_parser" ;
+
+   if ( p == NULL )
+   {
+      if ( parse_base10(version, &min_version) )
+         max_version = min_version - 1;
+      else
+         max_version = min_version;
+   }
+   else
+   {
+      *p = NUL ;
+      if ( parse_base10(version, &min_version) ||
+           parse_base10(p+1, &max_version) )
+         max_version = min_version - 1;
+   }
+   if ( min_version > max_version )
+   {
+      parsemsg( LOG_ERR, func, "bad version range: %s", version ) ;
+      return( FAILED ) ;
+   }
+   rdp->rd_min_version = min_version;
+   rdp->rd_max_version = max_version;
+   return( OK ) ;
+}
+
+
+status_e rpc_number_parser( pset_h values, 
+                            struct service_config *scp, 
+                            enum assign_op op )
+{
+   int num;
+
+   if ( parse_base10((char *) pset_pointer( values, 0 ), &num) ) {
+      parsemsg(LOG_ERR, "rpc_number_parser", "Error parsing: %s", 
+         (char *)pset_pointer( values, 0 ));
+      return( FAILED );
+   }
+   SC_RPCDATA( scp )->rd_program_number = num;
+   return( OK ) ;
+}
+
+
+status_e protocol_parser( pset_h values, 
+                          struct service_config *scp, 
+                           enum assign_op op )
+{
+   char *proto_name = (char *) pset_pointer( values, 0 ) ;
+   struct protoent *pep ;
+   const char *func = "protocol_parser" ;
+
+   if( proto_name == NULL ) {
+      parsemsg( LOG_ERR, func, "Protocol name is null in %s", SC_NAME(scp) );
+      return( FAILED );
+   }
+
+   if ( ( pep = getprotobyname( proto_name ) ) == NULL )
+   {
+      parsemsg( LOG_ERR, func, 
+               "Protocol %s not in /etc/protocols", proto_name ) ;
+      return( FAILED ) ;
+   }
+
+   SC_PROTONAME(scp) = new_string( proto_name ) ;
+   if ( SC_PROTONAME(scp) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   SC_PROTOVAL(scp) = pep->p_proto ;
+   return( OK ) ;
+}
+
+
+status_e wait_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   char *val = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "wait_parser" ;
+
+   if ( EQ( val, "yes" ) )
+      SC_WAIT(scp) = YES ;
+   else if ( EQ( val, "no" ) )
+      SC_WAIT(scp) = NO ;
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad value for wait: %s", val ) ;
+      return( FAILED );
+   }
+   return( OK ) ;
+}
+
+#ifdef HAVE_MDNS
+status_e mdns_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   char *val = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "mdns_parser" ;
+
+   if ( EQ( val, "yes" ) )
+      SC_MDNS(scp) = YES ;
+   else if ( EQ( val, "no" ) )
+      SC_MDNS(scp) = NO ;
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad value for mdns: %s", val ) ;
+      return( FAILED );
+   }
+   return( OK ) ;
+}
+#endif
+
+status_e user_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   char *user = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "user_parser" ;
+
+   if (parse_all_digits(user) == TRUE)
+   {   /* We will assume the number is a valid user. This is a workaround
+          for some Solaris systems that have problems doing getgr*. */
+      if (parse_ubase10(user, (unsigned int *)&SC_UID(scp)))
+      {
+         parsemsg( LOG_ERR, func, "Error parsing user as a number: %s", user ) ;
+         return( FAILED ) ;
+      }
+      SC_USER_GID(scp) = SC_UID(scp) ;
+   }
+   else
+   {
+      struct passwd *pw ;
+
+      pw = getpwnam( user ) ;
+      if ( pw == NULL )
+      {
+         parsemsg( LOG_ERR, func, "Unknown user: %s", user ) ;
+         return( FAILED ) ;
+      }
+      str_fill( pw->pw_passwd, ' ' );
+      SC_UID(scp) = pw->pw_uid ;
+      SC_USER_GID(scp) = pw->pw_gid ;
+   }
+   return( OK ) ;
+}
+
+
+status_e group_parser( pset_h values, 
+                       struct service_config *scp, 
+                       enum assign_op op )
+{
+   const char *func = "group_parser" ;
+   char *group_ptr = (char *) pset_pointer( values, 0 ) ;
+
+   if (parse_all_digits(group_ptr) == TRUE)
+   {   /* We will assume the number is a valid group. This is a workaround
+          for some Solaris systems that have problems doing getgr*. */
+      if (parse_ubase10(group_ptr, (unsigned int *)&SC_GID(scp)))
+      {
+         parsemsg( LOG_ERR, func, "Error parsing group as a number: %s", group_ptr ) ;
+         return( FAILED ) ;
+      }
+   }
+   else
+   {
+      struct group *grp = getgrnam( group_ptr ) ;
+      if ( grp == NULL )
+      {
+         parsemsg( LOG_ERR, func, "Unknown group: %s", group_ptr ) ;
+         return( FAILED ) ;
+      }
+   
+      SC_GID(scp) = grp->gr_gid ;
+   }
+   return( OK ) ;
+}
+
+
+status_e svcdisable_parser( pset_h values, 
+                            struct service_config *scp, 
+                            enum assign_op op )
+{
+   const char *func = "svcdisable_parser" ;
+   char *val = (char *) pset_pointer( values, 0 ) ;
+   
+   if( EQ( val, "yes" ) )
+      SC_DISABLE( scp );
+   else if( EQ( val, "no" ) ) 
+      SC_ENABLE( scp );
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad value: %s", val ) ;
+      return( FAILED );
+   }
+
+   return( OK );
+}
+
+
+status_e groups_parser( pset_h values, 
+                        struct service_config *scp, 
+                        enum assign_op op )
+{
+   char *val = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "groups_parser" ;
+
+   if ( EQ( val, "yes" ) )
+      SC_GROUPS(scp) = YES ;
+   else if ( EQ( val, "no" ) )
+      SC_GROUPS(scp) = NO ;
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad value for groups: %s", val ) ;
+      return( FAILED );
+   }
+
+   return( OK );
+}
+
+
+status_e v6only_parser( pset_h values, 
+                        struct service_config *scp, 
+                        enum assign_op op )
+{
+   char *val = (char *) pset_pointer( values, 0 );
+   const char *func = "v6only_parser" ;
+
+   if ( EQ( val, "yes" ) )
+      SC_V6ONLY(scp) = YES;
+   else if ( EQ( val, "no" ) )
+      SC_V6ONLY(scp) = NO;
+   else
+   {
+      parsemsg( LOG_ERR, func, "Bad value for v6only: %s", val );
+      return( FAILED );
+   }
+   return( OK );
+}
+
+
+status_e server_parser( pset_h values, 
+                        struct service_config *scp, 
+                        enum assign_op op )
+{
+   char *server = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "server_parser" ;
+   struct stat sb;
+
+   /* 
+    * Access is used so that the real user ID permissions
+    * are checked.
+    */
+   if ( access( server, X_OK ) == -1 )
+   {
+      parsemsg( LOG_ERR, func, "Server %s is not executable", server ) ;
+      return( FAILED ) ;
+   }
+   if (stat(server, &sb) == -1)
+   {
+      parsemsg( LOG_ERR, func, "Unable to stat: %s.", server ) ;
+      return( FAILED ) ;
+   }
+
+   SC_SERVER(scp) = new_string( server ) ;
+   if ( SC_SERVER(scp) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+status_e server_args_parser( pset_h values, 
+                             struct service_config *scp, 
+                             enum assign_op op )
+{
+   char **argv ;
+   unsigned u ;
+   unsigned i ;
+   unsigned count;
+   unsigned argv_index ;
+   unsigned n_args = pset_count( values ) ;
+   const char *func = "server_args_parser" ;
+
+   /*
+    * Create the argv for a future exec call
+    * Reserve space for the server. We cannot use scp->sc_server
+    * since it may not have a value yet.
+    */
+   argv = argv_alloc( n_args+1 ) ;
+   count = pset_count( values );
+   if ( count == 0 )
+   {
+       missing_attr_msg("server_args_parser", "server_args");
+       free( (char *) argv ) ;
+       return FAILED;
+   }
+   
+   if( SC_NAMEINARGS( scp ) )
+   {
+      for (u = 0; u < count; u++)
+      {
+         register char *s = new_string( (char *) pset_pointer( values, u )) ;
+
+         if ( s == NULL )
+         {
+             for ( i = 1 ; i < u ; i++ )
+               free( argv[ i ] ) ;
+             free( (char *) argv ) ;
+             out_of_memory( func ) ;
+             return( FAILED ) ;
+         }
+         argv[ u ] = s ;
+      }
+   }
+   else
+   {
+      for (u = 0, argv_index = 1 ; u < count; u++, argv_index++)
+      {
+         register char *s = new_string((char *) pset_pointer( values, u )) ;
+
+         if ( s == NULL )
+         {
+             for ( i = 1 ; i < argv_index ; i++ )
+               free( argv[ i ] ) ;
+             free( (char *) argv ) ;
+             out_of_memory( func ) ;
+             return( FAILED ) ;
+         }
+         argv[ argv_index ] = s ;
+      }
+      argv[ argv_index ] = argv[ 0 ] = NULL ;
+   }
+   SC_SERVER_ARGV(scp) = argv ;
+   return( OK ) ;
+}
+
+
+status_e instances_parser( pset_h values, 
+                           struct service_config *scp, 
+                           enum assign_op op )
+{
+   char *instances = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "instances_parser" ;
+
+   if ( EQ( instances, "UNLIMITED" ) )
+      SC_INSTANCES(scp) = UNLIMITED ;
+   else
+   {
+      if ( parse_base10(instances, &SC_INSTANCES(scp)) ||
+           SC_INSTANCES(scp) < 0 )
+      {
+         parsemsg( LOG_ERR, func,
+            "Number of instances is invalid: %s", instances ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+
+
+status_e per_source_parser( pset_h values, 
+                            struct service_config *scp, 
+                            enum assign_op op )
+{
+   char *per_source = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "per_source_parser" ;
+
+   if ( EQ( per_source, "UNLIMITED" ) )
+      SC_PER_SOURCE(scp) = UNLIMITED;
+   else
+   {
+      if ( parse_base10(per_source, &SC_PER_SOURCE(scp)) ||
+           SC_PER_SOURCE(scp) < 0 )
+      {
+         parsemsg( LOG_ERR, func, "Number of per source instances is invalid: %s", per_source ) ;
+         return( FAILED );
+      }
+   }
+   return(OK);
+}
+
+
+status_e cps_parser( pset_h values, 
+                     struct service_config *scp, 
+                     enum assign_op op )
+{
+   char *cps = (char *) pset_pointer(values, 0);
+   char *waittime = (char *) pset_pointer(values, 1);
+   unsigned int waittime_int, conn_max;
+
+   if( cps == NULL || waittime == NULL ) {
+      parsemsg(LOG_ERR, "cps_parser", "NULL options specified in cps");
+      return( FAILED );
+   }
+   if( parse_ubase10(cps, &conn_max) ) {
+      parsemsg(LOG_ERR, "cps_parser", "cps argument not a number");
+      SC_TIME_CONN_MAX(scp) = 0;
+      SC_TIME_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   if( parse_ubase10(waittime, &waittime_int) ) {
+      parsemsg(LOG_ERR, "cps_parser", "cps time argument not a number");
+      SC_TIME_CONN_MAX(scp) = 0;
+      SC_TIME_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   SC_TIME_WAIT(scp) = waittime_int;
+   SC_TIME_CONN_MAX(scp) = conn_max;
+
+   if( SC_TIME_CONN_MAX(scp) < 0 || SC_TIME_WAIT(scp) < 0 ) {
+      parsemsg(LOG_ERR, "cps_parser", "cps arguments invalid");
+      SC_TIME_CONN_MAX(scp) = 0;
+      SC_TIME_WAIT(scp) = 0;
+      return( FAILED );
+   }
+
+   return(OK);
+}
+
+status_e id_parser( pset_h values, 
+                    struct service_config *scp, 
+                    enum assign_op op )
+{
+   const char *func = "id_parser" ;
+
+   SC_ID(scp) = new_string( (char *) pset_pointer( values, 0 ) ) ;
+   if ( SC_ID(scp) != NULL )
+      return( OK ) ;
+   out_of_memory( func ) ;
+   return( FAILED ) ;
+}
+
+
+
+#define PORT_BITS            16
+#define PORT_MAX            ( 1 << PORT_BITS )
+
+status_e port_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   int port;
+   const char *func = "port_parser" ;
+
+   if ( parse_base10((char *) pset_pointer( values, 0 ), &port) ||
+        port < 0 || port >= PORT_MAX )
+   {
+      parsemsg( LOG_ERR, func, "port number is invalid" ) ;
+      return( FAILED ) ;
+   }
+   SC_PORT(scp) = (uint16_t)port ;
+   return( OK ) ;
+}
+
+
+static status_e add_new_string( pset_h set, char *str )
+{
+   char *p = new_string( str ) ;
+   const char *func = "add_new_string" ;
+
+   if ( p == NULL )
+   {
+      parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
+      return( FAILED ) ;
+   }
+   if ( pset_add( set, p ) == NULL )
+   {
+      free( p ) ;
+      parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+status_e env_parser( pset_h values, 
+                     struct service_config *scp, 
+                     enum assign_op op )
+{
+   unsigned u ;
+   const char *func = "env_parser" ;
+
+   if ( op == MINUS_EQ )
+   {
+      parsemsg( LOG_WARNING, func,
+         "operator '-=' not supported for env attribute" ) ;
+      return( FAILED ) ;
+   }
+
+   NEW_SET( SC_ENV_VAR_DEFS(scp), 5, 5 ) ;
+
+   if ( op == SET_EQ && pset_count( SC_ENV_VAR_DEFS(scp) ) != 0 )
+   {
+      pset_apply( SC_ENV_VAR_DEFS(scp), free, NULL ) ;
+      pset_clear( SC_ENV_VAR_DEFS(scp) ) ;
+   }
+
+   for ( u = 0 ; u < pset_count( values ) ; u++ )
+   {
+      char *str = (char *) pset_pointer( values, u ) ;
+
+      /*
+       * Check if the string contains an '='
+       */
+      if ( strchr( str, '=' ) == NULL )
+      {
+         parsemsg( LOG_ERR, func, "%s has no '='", str ) ;
+         return( FAILED ) ;
+      }
+
+      if ( add_new_string( SC_ENV_VAR_DEFS(scp), str ) == FAILED )
+         return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+status_e passenv_parser( pset_h values, 
+                         struct service_config *scp, 
+                         enum assign_op op )
+{
+   pset_h var_set ;
+   unsigned u ;
+   const char *func = "passenv_parser" ;
+
+   NEW_SET( SC_PASS_ENV_VARS(scp), 0, 0 ) ;
+
+   var_set = SC_PASS_ENV_VARS(scp) ;
+
+   if ( op == SET_EQ )
+   {
+      pset_apply( var_set, free, NULL ) ;
+      pset_clear( var_set ) ;
+      op = PLUS_EQ ;
+   }
+
+   for ( u = 0 ; u < pset_count( values ) ; u++ )
+   {
+      char *env_var = (char *) pset_pointer( values, u ) ;
+      unsigned v ;
+      boolean_e found ;
+
+      /*
+       * Check if it is already there
+       */
+      for ( found = NO, v = 0 ; v < pset_count( var_set ) ; v++ )
+         if ( EQ( env_var, (char *) pset_pointer( var_set, v ) ) )
+         {
+            found = YES ;
+            break ;
+         }
+      
+      if ( ((op == MINUS_EQ) && (found == NO)) || ((op != MINUS_EQ) && (found == YES)) )
+         continue ;
+      
+      if ( op == MINUS_EQ )
+      {
+         free( (char *) pset_pointer( var_set, v ) ) ;
+         pset_remove_index( var_set, v ) ;
+      }
+      else
+      {
+         if ( env_lookup( std_env, env_var ) == CHAR_NULL )
+         {
+            parsemsg( LOG_WARNING, func,
+               "undefined environment variable: %s", env_var ) ;
+            continue ;
+         }
+
+         if ( add_new_string( var_set, env_var ) == FAILED )
+            return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+
+
+status_e disabled_parser( pset_h values, 
+                          struct service_config *scp, 
+                          enum assign_op op )
+{
+   unsigned u ;
+   const char *func = "disabled_parser" ;
+
+   NEW_SET( SC_DISABLED(scp), pset_count( values ), 0 ) ;
+   
+   for ( u = 0 ; u < pset_count( values ) ; u++ )
+   {
+      char *name = (char *) pset_pointer( values, u ) ;
+
+      if ( add_new_string( SC_DISABLED(scp), name ) == FAILED )
+         return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+status_e enabled_parser( pset_h values, 
+                         struct service_config *scp, 
+                         enum assign_op op )
+{
+   unsigned u ;
+   const char *func = "enabled_parser" ;
+
+   NEW_SET( SC_ENABLED(scp), pset_count( values ), 0 ) ;
+   
+   for ( u = 0 ; u < pset_count( values ) ; u++ )
+   {
+      char *name = (char *) pset_pointer( values, u ) ;
+
+      if ( add_new_string( SC_ENABLED(scp), name ) == FAILED )
+         return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+/*
+ * Interpret a number of the form: <num>[m|M|k|K]
+ * m and M mean megabytes, k and K mean kilobytes, nothing means bytes
+ */
+static int get_limit( char *limit_str, rlim_t *res )
+{
+   unsigned long long limit_int;
+   int multiplier;
+   char *p;
+
+   if (*limit_str == NUL) {
+      *res = 0;
+      return -1;
+   }
+
+   p = limit_str + strlen( limit_str ) - 1;
+   while ( p > limit_str && isspace( *p ) )
+      p--;
+
+   if (*p == 'k' || *p == 'K') {
+      *p = NUL;
+      multiplier = 1024;
+   } else if (*p == 'm' || *p == 'M') {
+      *p = NUL;
+      multiplier = 1024 * 1024;
+   } else
+      multiplier = 1;
+
+   if (parse_ull(limit_str, 10, -1, &limit_int)) {
+      *res = 0;
+      return -1;
+   }
+
+   *res = (rlim_t)limit_int;
+   if (*res != limit_int) {
+      *res = 0;
+      return -1;
+   }
+
+   *res = (rlim_t)limit_int * multiplier;
+   if (*res / multiplier != (rlim_t)limit_int) {
+      *res = 0;
+      return -1;
+   }
+
+   return 0;
+}
+
+
+static status_e parse_filelog( struct filelog *flp, pset_h values )
+{
+   rlim_t      soft_limit ;
+   rlim_t      hard_limit ;
+   char         *file ;
+   unsigned      count = pset_count( values ) ;
+   const char    *func = "parse_filelog" ;
+
+   if ( count < 2 || count > 4 )
+   {
+      parsemsg( LOG_ERR, func, "wrong number of arguments" ) ;
+      return( FAILED ) ;
+   }
+
+   file = new_string( (char *) pset_pointer( values, 1 ) ) ;
+   if ( file == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+
+   /*
+    * Get the limits, if any
+    */
+   if ( count > 2 )
+   {
+      if ( get_limit( (char *) pset_pointer( values, 2 ), &soft_limit ) )
+      {
+         parsemsg( LOG_ERR, func, "soft limit is invalid" ) ;
+         free( file ) ;
+         return( FAILED ) ;
+      }
+
+      /*
+       * If a hard limit was specified check that it is at least equal 
+       * to the soft limit. If no hard limit was specified, determine
+       * it from the formula:
+       *      hard = soft + x
+       * where 
+       *      min( 1%soft,LOG_EXTRA_MIN ) <= x <= max( 1%soft,LOG_EXTRA_MAX )
+       */
+      if ( count == 4 )
+      {
+         if ( get_limit( (char *) pset_pointer( values, 3 ), &hard_limit) )
+         {
+            parsemsg( LOG_ERR, func, "hard limit is invalid" ) ;
+            free( file ) ;
+            return( FAILED ) ;
+         }
+         if ( hard_limit < soft_limit )
+         {
+            parsemsg( LOG_ERR, func,
+               "hard limit (%lu) is less than soft limit (%lu)",
+                     (unsigned long)hard_limit, (unsigned long)soft_limit ) ;
+            free( file ) ;
+            return( FAILED ) ;
+         }
+      }
+      else
+      {
+         unsigned extra = soft_limit / 100 ;      /* 1% of soft limit */
+
+         if ( extra < LOG_EXTRA_MIN )
+            extra = LOG_EXTRA_MIN ;
+         else if ( extra > LOG_EXTRA_MAX )
+            extra = LOG_EXTRA_MAX ;
+         hard_limit = soft_limit + extra ;
+      }
+      flp->fl_soft_limit = soft_limit ;
+      flp->fl_hard_limit = hard_limit ;
+   }
+   flp->fl_filename = file ;
+   return( OK ) ;
+}
+
+
+static status_e parse_syslog( struct syslog *slp, pset_h values )
+{
+   const char               *facility ;
+   const char               *level ;
+   const struct name_value  *nvp ;
+   unsigned                  count = pset_count( values ) ;
+   const char               *func  = "parse_syslog" ;
+
+   if ( count < 2 || count > 3 )
+   {
+      parsemsg( LOG_ERR, func, "wrong number of arguments" ) ;
+      return( FAILED ) ;
+   }
+
+   facility = (char *) pset_pointer( values, 1 ) ;
+   if ( ( nvp = nv_find_value( syslog_facilities, facility ) ) == NULL )
+   {
+      parsemsg( LOG_ERR, func, "Unknown syslog facility: %s", facility ) ;
+      return( FAILED ) ;
+   }
+   slp->sl_facility = nvp->value ;
+
+   if ( count == 3 )
+   {
+      level = (char *) pset_pointer( values, 2 ) ;
+      if ( ( nvp = nv_find_value( syslog_levels, level ) ) == NULL )
+      {
+         parsemsg( LOG_ERR, func, "Unknown syslog level: %s", level ) ;
+         return( FAILED ) ;
+      }
+      slp->sl_level = nvp->value ;
+   }
+   else
+      slp->sl_level = DEFAULT_SERVICE_SYSLOG_LEVEL ;
+
+   return( OK ) ;
+}
+
+
+status_e log_type_parser( pset_h values, 
+                          struct service_config *scp, 
+                          enum assign_op op )
+{
+   struct log *lp = SC_LOG( scp ) ;
+   char *type ;
+   const char *func = "parse_log_type" ;
+   int count = pset_count( values);
+
+   if ( count == 0 )
+   {
+      missing_attr_msg(func, "log_type");
+      return( FAILED );
+   }
+   
+   type = (char *) pset_pointer( values, 0 ) ;
+
+   if ( EQ( type, "FILE" ) )
+   {
+      if ( parse_filelog( LOG_GET_FILELOG( lp ), values ) == FAILED )
+         return( FAILED ) ;
+      lp->l_type = L_FILE ;
+   }
+   else if ( EQ( type, "SYSLOG" ) )
+   {
+      if ( parse_syslog( LOG_GET_SYSLOG( lp ), values ) == FAILED )
+         return( FAILED ) ;
+      lp->l_type = L_SYSLOG ;
+   }
+   else
+   {
+      parsemsg( LOG_ERR, func, "Unknown log type: %s", type ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+static status_e parse_log_flags( pset_h values, 
+                                  enum assign_op op, 
+                                  mask_t *maskp, 
+                                  const struct name_value options[], 
+                                  const char *name )
+{
+   if ( op == SET_EQ )
+   {
+      M_CLEAR_ALL( *maskp ) ;
+      op = PLUS_EQ ;
+   }
+
+   return( parse_value_list( values, maskp, options, op, name ) ) ;
+}
+
+
+status_e log_on_success_parser( pset_h values, 
+                                struct service_config *scp, 
+                                enum assign_op op )
+{
+   return( parse_log_flags( values, op,
+      &SC_LOG_ON_SUCCESS(scp), success_log_options, "log_on_success flag" ) ) ;
+}
+
+
+status_e log_on_failure_parser( pset_h values, 
+                                struct service_config *scp, 
+                                enum assign_op op )
+{
+   return( parse_log_flags( values, op,
+      &SC_LOG_ON_FAILURE(scp), failure_log_options, "log_on_failure flag" ) ) ;
+}
+
+
+static status_e parse_inet_addresses( pset_h values, 
+                                       enum assign_op op, 
+                                       pset_h *addr_list )
+{
+   unsigned             u ;
+   pset_h               addr_set ;
+   statfunc             addrlist_func ;
+   const char          *func = "parse_inet_addresses" ;
+
+   NEW_SET( *addr_list, 0, 0 );
+
+   addr_set = *addr_list;
+
+   /*
+    * If the op was '=' clear the existing list of addresses
+    */
+   if ( op == SET_EQ )
+   {
+      op = PLUS_EQ ;
+      addrlist_free( addr_set ) ;
+      pset_clear( addr_set ) ;
+   }
+
+   addrlist_func = ( op == PLUS_EQ ) ? addrlist_add : addrlist_remove ;
+
+   for ( u = 0 ; u < pset_count( values ) ; u++ )
+   {
+      register char *str_addr = (char *) pset_pointer( values, u ) ;
+
+      /* If it is factorized, allow a comma. Otherwise complain */
+      if (strchr(str_addr, ',') && !strchr(str_addr, '{'))
+      {
+         parsemsg( LOG_ERR, func, 
+             "Address: %s has a comma in it - remove the comma", 
+             str_addr ) ;
+         return( FAILED );
+      }
+
+      if ( (*addrlist_func)( addr_set, str_addr ) == FAILED )
+      {
+         parsemsg( LOG_ERR, func, "Failed adding: %s", str_addr ) ;
+         return( FAILED );
+      }
+   }
+   return( OK ) ;
+}
+
+
+status_e only_from_parser( pset_h values, 
+                           struct service_config *scp, 
+                           enum assign_op op )
+{
+   return( parse_inet_addresses( values, op, &SC_ONLY_FROM(scp) ) ) ;
+}
+
+
+status_e no_access_parser( pset_h values, 
+                           struct service_config *scp, 
+                           enum assign_op op )
+{
+   return( parse_inet_addresses( values, op, &SC_NO_ACCESS(scp) ) ) ;
+}
+
+
+status_e banner_parser(pset_h values, 
+                       struct service_config *scp, 
+                       enum assign_op op)
+{
+   const char *func = "banner_parser";
+
+   if( pset_pointer(values, 0) == NULL )
+   {
+      msg(LOG_ERR, func, "pset_pointer returned NULL");
+      return( FAILED );
+   }
+
+   SC_BANNER(scp) = new_string( pset_pointer(values,0) );
+   if( SC_BANNER(scp) == NULL ) {
+      msg(LOG_ERR, func, ES_NOMEM);
+      return( FAILED );
+   }
+
+   return OK;
+}
+
+status_e banner_success_parser(pset_h values, 
+                               struct service_config *scp, 
+                               enum assign_op op)
+{
+   const char *func = "banner_success_parser";
+
+   if( pset_pointer(values, 0) == NULL ) {
+      msg(LOG_ERR, func, "pset_pointer returned NULL" );
+      return( FAILED );
+   }
+
+   SC_BANNER_SUCCESS(scp) = new_string(pset_pointer(values,0) );
+   if( SC_BANNER_SUCCESS(scp) == NULL ) {
+      msg(LOG_ERR, func, ES_NOMEM);
+      return( FAILED );
+   }
+
+   return OK;
+}
+
+status_e banner_fail_parser(pset_h values, 
+                            struct service_config *scp, 
+                            enum assign_op op)
+{
+   const char *func = "banner_fail_parser";
+
+   if( pset_pointer(values, 0) == NULL ) {
+      msg(LOG_ERR, func, "pset_pointer returned NULL");
+      return( FAILED );
+   }
+
+   SC_BANNER_FAIL(scp) = new_string(pset_pointer(values,0) );
+   if( SC_BANNER_FAIL(scp) == NULL ) {
+      msg(LOG_ERR, func, ES_NOMEM);
+      return( FAILED );
+   }
+
+   return OK;
+}
+
+#ifdef HAVE_LOADAVG
+status_e max_load_parser(pset_h values, 
+                         struct service_config *scp, 
+                         enum assign_op op)
+{
+   const char *func = "max_load_parser" ;
+   char *adr = (char *)pset_pointer(values, 0);
+
+   if( sscanf(adr, "%lf", &SC_MAX_LOAD(scp)) < 1 ) {
+      parsemsg(LOG_ERR, func, "error reading max_load argument");
+      return( FAILED );
+   }
+
+   if( SC_MAX_LOAD(scp) == 0 ) {
+      parsemsg(LOG_ERR, func, "error parsing max_load argument");
+      return( FAILED );
+   }
+
+   return OK;
+}
+#endif
+
+status_e redir_parser(pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op)
+{
+   char *adr = (char *)pset_pointer(values, 0);
+   const char *func = "redir_parser";
+   char *port_char;
+   int port_int;
+   struct addrinfo hints, *res;
+
+   port_char = pset_pointer(values, 1);
+   if (parse_base10(port_char, &port_int) || port_int <= 0)
+   {  /* OK, maybe its a service name... */
+      struct servent *entry;
+      entry = getservbyname(port_char, "tcp");
+      if (entry == 0)
+      {
+         parsemsg(LOG_ERR, func, "port number invalid");
+         return FAILED;
+      }
+      port_int = ntohs(entry->s_port);
+   }
+   if (port_int >= PORT_MAX)
+   {
+      parsemsg(LOG_ERR, func, "port number too large");
+      return FAILED;
+   }
+   
+   SC_REDIR_ADDR(scp) = (union xsockaddr *)malloc(sizeof(union xsockaddr));
+   if( SC_REDIR_ADDR(scp) == NULL )
+   {
+      parsemsg(LOG_ERR, func, "can't allocate space for redir addr");
+      return FAILED;
+   }
+
+   memset(&hints, 0, sizeof(hints));
+   hints.ai_flags = AI_CANONNAME;
+   hints.ai_socktype = SOCK_STREAM;
+   if (strchr(adr, ':'))
+      hints.ai_family = AF_INET6;
+   else
+      hints.ai_family = AF_INET;
+
+   if( getaddrinfo(adr, NULL, &hints, &res) < 0 ) {
+      parsemsg(LOG_ERR, func, "bad address");
+      free( SC_REDIR_ADDR(scp) );
+      SC_REDIR_ADDR(scp) = NULL;
+      return FAILED;
+   }
+
+   if( (res == NULL) || (res->ai_addr == NULL) ) {
+      parsemsg(LOG_ERR, func, "no addresses returned");
+      free( SC_REDIR_ADDR(scp) );
+      SC_REDIR_ADDR(scp) = NULL;
+      return FAILED;
+   }
+      
+   if( (res->ai_family == AF_INET) || (res->ai_family == AF_INET6) )
+      memcpy(SC_REDIR_ADDR(scp), res->ai_addr, res->ai_addrlen);
+   if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET ) 
+      SC_REDIR_ADDR(scp)->sa_in.sin_port = port_int;
+   if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET6 ) 
+      SC_REDIR_ADDR(scp)->sa_in6.sin6_port = port_int;
+
+   freeaddrinfo(res);
+   return OK;
+}
+
+status_e bind_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op)
+{
+   char *adr = (char *)pset_pointer(values, 0);
+   const char *func = "bind_parser";
+   struct addrinfo hints, *res, *ressave;
+   int addr_cnt = 0;
+
+   memset(&hints, 0, sizeof(hints));
+   hints.ai_flags = AI_CANONNAME;
+
+   /*
+    * Use tcp to cut down returned address records. Get addrinfo normally
+    * returns 2 address records, one for each socket type.
+    */
+   hints.ai_socktype = SOCK_STREAM;
+   
+   if (check_hostname(adr) == 0)
+   {
+      hints.ai_family = AF_INET;
+      hints.ai_flags |= AI_NUMERICHOST;
+   }
+   else if (strchr(adr, ':'))
+   {
+      hints.ai_family = AF_INET6;
+      hints.ai_flags |= AI_NUMERICHOST;
+   }
+   else
+   {
+      hints.ai_family = AF_UNSPEC;
+   }
+   
+   if( getaddrinfo(adr, NULL, &hints, &res) < 0 ) {
+      parsemsg(LOG_ERR, func, "bad address");
+      return( FAILED );
+   }
+
+   if( (res == NULL) || (res->ai_addr == NULL) ) {
+      parsemsg(LOG_ERR, func, "no addresses returned");
+      return( FAILED );
+   }
+
+   /*
+    * If more than 1 record comes back, we need to defer selection
+    * until we are finished reading all attributes of the service.
+    * Hopefully, they will have specified IPv4 or IPv6.
+    */
+   ressave = res;
+   while (res)
+   {
+      addr_cnt++;
+      res = res->ai_next;
+   }
+   res = ressave;
+
+   if (addr_cnt == 1)
+   {
+      SC_BIND_ADDR(scp) = (union xsockaddr *)malloc(sizeof(union xsockaddr));
+      if( SC_BIND_ADDR(scp) == NULL )
+      {
+         parsemsg(LOG_ERR, func, "can't allocate space for bind addr");
+         return( FAILED );
+      } 
+      memcpy(SC_BIND_ADDR(scp), res->ai_addr, res->ai_addrlen);
+   }      
+   else
+      SC_ORIG_BIND_ADDR(scp) = new_string(adr);
+
+   freeaddrinfo(res);
+   return( OK );
+}
+
+status_e access_times_parser( pset_h values, 
+                              struct service_config *scp, 
+                              enum assign_op op )
+{
+   unsigned u, count ;
+   const char *func = "access_times_parser" ;
+
+   NEW_SET( SC_ACCESS_TIMES(scp), 0, 0 ) ;
+   count = pset_count( values) ;
+
+   if ( count == 0 )
+   {
+       missing_attr_msg("access_times_parser", "access_times");
+       return FAILED;
+   }
+
+   for ( u = 0 ; u < count ; u++ )
+   {
+      register char *interval = (char *) pset_pointer( values, u ) ;
+
+      if ( ti_add( SC_ACCESS_TIMES(scp), interval ) == FAILED )
+         return FAILED ;
+   }
+   return OK ;
+}
+
+
+status_e nice_parser( pset_h values, 
+                      struct service_config *scp, 
+                      enum assign_op op )
+{
+   if ( parse_base10((char *) pset_pointer( values, 0 ), &SC_NICE(scp)) ) {
+      parsemsg(LOG_ERR, "nice_parser", "Error parsing: %s", (char *)pset_pointer( values, 0 ));
+      return( FAILED );
+   }
+   return( OK ) ;
+}
+
+#ifdef RLIMIT_AS
+status_e rlim_as_parser( pset_h values, 
+                         struct service_config *scp, 
+                         enum assign_op op )
+{
+   char *mem = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "rlim_as_parser" ;
+
+   if ( EQ( mem, "UNLIMITED" ) )
+      SC_RLIM_AS(scp) = (rlim_t)RLIM_INFINITY ;
+   else
+   {
+      if ( get_limit ( mem, &SC_RLIM_AS(scp)) )
+      {
+         parsemsg( LOG_ERR, func,
+            "Address space limit is invalid: %s", mem ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+#endif
+
+#ifdef RLIMIT_CPU
+status_e rlim_cpu_parser( pset_h values, 
+                          struct service_config *scp, 
+                          enum assign_op op )
+{
+   char *cpu_str = (char *) pset_pointer( values, 0 ) ;
+   unsigned long long cpu_int;
+   const char *func = "rlim_cpu_parser" ;
+
+   if ( EQ( cpu_str, "UNLIMITED" ) )
+      SC_RLIM_CPU(scp) = (rlim_t)RLIM_INFINITY ;
+   else
+   {
+      if ( parse_ull(cpu_str, 10, -1, &cpu_int) || cpu_int < 0 )
+      {
+         parsemsg( LOG_ERR, func,
+            "CPU limit is invalid: %s", cpu_str ) ;
+         return( FAILED ) ;
+      }
+      SC_RLIM_CPU(scp) = (rlim_t) cpu_int ;
+      if ( SC_RLIM_CPU(scp) != cpu_int )
+      {
+         parsemsg( LOG_ERR, func, "CPU limit is invalid: %s", cpu_str );
+         return( FAILED );
+      }
+   }
+   return( OK ) ;
+}
+#endif
+
+#ifdef RLIMIT_DATA
+status_e rlim_data_parser( pset_h values, 
+                           struct service_config *scp, 
+                           enum assign_op op )
+{
+   char *mem = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "rlim_data_parser" ;
+
+   if ( EQ( mem, "UNLIMITED" ) )
+      SC_RLIM_DATA(scp) = (rlim_t)RLIM_INFINITY ;
+   else
+   {
+      if ( get_limit ( mem, &SC_RLIM_DATA(scp) ) )
+      {
+         parsemsg( LOG_ERR, func,
+            "Data limit is invalid: %s", mem ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+#endif
+
+#ifdef RLIMIT_RSS
+status_e rlim_rss_parser( pset_h values, 
+                          struct service_config *scp, 
+                          enum assign_op op )
+{
+   char *mem = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "rlim_rss_parser" ;
+
+   if ( EQ( mem, "UNLIMITED" ) )
+      SC_RLIM_RSS(scp) = (rlim_t)RLIM_INFINITY ;
+   else
+   {
+      if ( get_limit ( mem, &SC_RLIM_RSS(scp) ) )
+      {
+         parsemsg( LOG_ERR, func,
+            "RSS limit is invalid: %s", mem ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+#endif
+
+#ifdef RLIMIT_STACK
+status_e rlim_stack_parser( pset_h values, 
+                            struct service_config *scp, 
+                            enum assign_op op )
+{
+   char *mem = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "rlim_stack_parser" ;
+
+   if ( EQ( mem, "UNLIMITED" ) )
+      SC_RLIM_STACK(scp) = (rlim_t)RLIM_INFINITY ;
+   else
+   {
+      if ( get_limit ( mem, &SC_RLIM_STACK(scp) ) )
+      {
+         parsemsg( LOG_ERR, func,
+            "Stack limit is invalid: %s", mem ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+#endif
+
+status_e deny_time_parser( pset_h values, 
+                           struct service_config *scp, 
+                           enum assign_op op )
+{
+   char *deny_time = (char *) pset_pointer( values, 0 ) ;
+
+   if ( EQ( deny_time, "FOREVER" ) )
+      SC_DENY_TIME(scp) = -1 ;
+   else if ( EQ( deny_time, "NEVER" ) )
+      SC_DENY_TIME(scp) = 0 ;
+   else if ( parse_base10( deny_time, &SC_DENY_TIME(scp) ) ) {
+      parsemsg(LOG_ERR, "deny_time_parser", "Error parsing: %s", deny_time);
+      return( FAILED );
+   }
+   return( OK ) ;
+}
+
+status_e umask_parser( pset_h values, 
+                       struct service_config *scp, 
+                       enum assign_op op )
+{
+   char *umask_str = (char *)pset_pointer(values, 0);
+   int umask_int;
+
+   if( parse_int(umask_str, 8, -1, &umask_int) ||
+       umask_int < 0 || umask_int > 0777)
+   {
+      parsemsg(LOG_ERR, "umask_parser", "umask argument is invalid.\n");
+      return( FAILED );
+   }
+   SC_UMASK(scp) = umask_int;
+   return( OK );
+}
+
+#ifdef LIBWRAP
+status_e libwrap_parser( pset_h values,
+                         struct service_config *scp,
+                         enum assign_op op )
+{
+   char *libwrap = (char *) pset_pointer( values, 0 ) ;
+   const char *func = "libwrap_parser" ;
+
+   SC_LIBWRAP(scp) = new_string( libwrap ) ;
+   if ( SC_LIBWRAP(scp) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+#endif
+
diff --git a/xinetd/parsers.h b/xinetd/parsers.h
new file mode 100644 (file)
index 0000000..50a5688
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#ifndef _X_PARSERS
+#define _X_PARSERS
+
+#include "config.h"
+#include "pset.h"
+#include "defs.h"
+#include "parse.h"
+
+status_e socket_type_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e protocol_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e wait_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e user_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e group_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e server_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e server_args_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e instances_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e log_on_success_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e log_on_failure_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e log_type_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e only_from_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e no_access_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e access_times_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e type_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e id_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e env_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e port_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e rpc_version_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e passenv_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e flags_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e disabled_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e rpc_number_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e nice_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e redir_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e bind_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e banner_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e per_source_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e groups_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e banner_success_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e banner_fail_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e cps_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e enabled_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e svcdisable_parser(pset_h, struct service_config *, enum assign_op);
+#ifdef HAVE_LOADAVG
+status_e max_load_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+#ifdef RLIMIT_AS
+status_e rlim_as_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+#ifdef RLIMIT_CPU
+status_e rlim_cpu_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+#ifdef RLIMIT_DATA
+status_e rlim_data_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+#ifdef RLIMIT_RSS
+status_e rlim_rss_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+#ifdef RLIMIT_STACK
+status_e rlim_stack_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+status_e v6only_parser(pset_h, struct service_config *, enum assign_op);
+status_e deny_time_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e umask_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e mdns_parser(pset_h, struct service_config *, enum assign_op) ;
+#ifdef LIBWRAP
+status_e libwrap_parser(pset_h, struct service_config *, enum assign_op) ;
+#endif
+
+#endif
diff --git a/xinetd/parsesup.c b/xinetd/parsesup.c
new file mode 100644 (file)
index 0000000..5846fcc
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <ctype.h>
+#include <syslog.h>
+
+#include "sio.h"
+#include "str.h"
+#include "parsesup.h"
+#include "msg.h"
+
+
+/*
+ * next_line returns the next line of the file or NULL if the end of file
+ * is reached.
+ * Comment lines and empty lines are skipped.
+ */
+char *next_line( int fd )
+{
+   for ( ;; )
+   {
+      char *p ;
+      char *line = Srdline( fd ) ;
+
+      if ( line == NULL )
+         return( NULL ) ;
+
+      line_count++ ;
+
+      for ( p = line ;; p++ )
+         if ( *p == NUL || *p == COMMENT_BEGIN )
+            break ;                                /* skip this line */
+         else if ( isspace( *p ) )
+            continue ;                             /* skip white space */
+         else
+            return( line ) ;
+   }
+}
+
+
+/*
+ * Input:
+ *      a line of the form
+ *            name [SPACE] OP [SPACE] value [SPACE] value ...
+ *
+ * Recognize the attribute name and operator and place them in *attrp, *opp
+ *
+ * Currently, we allow any non-space character to be used in the
+ * attribute name.
+ *
+ * Return value: a pointer to the character after OP.
+ */
+static char *get_attr_op( char *line, char **attrp, enum assign_op *opp )
+{
+   char            *p ;
+   char            *attr ;
+   enum assign_op   op ;
+   const char      *func = "get_attr_op" ;
+
+   /*
+    * First get the attribute name
+    */
+   for ( p = line ; isspace( *p ) ; p++ ) ;      /* skip spaces */
+   if ( *p == NUL )
+   {
+      parsemsg( LOG_ERR, func, "Empty line" ) ;
+      return( NULL ) ;
+   }
+
+   attr = p ;
+   for ( ; ! isspace( *p ) && (*p != '='); p++ ) ;            /* skip attribute name */
+   if ( *p == NUL )
+   {
+      parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
+      return( NULL ) ;
+   }
+   if( *p == '=' ) {
+      *p = NUL ;         /* now attribute name is NUL terminated */
+      parsemsg( LOG_ERR, func, "Attribute %s needs a space before operator", attr);
+      return( NULL ) ;
+   }
+   *p++ = NUL ;         /* now attribute name is NUL terminated */
+
+   while ( isspace( *p ) ) p++ ;      /* skip spaces */
+
+   switch ( *p )
+   {
+      case NUL:
+         parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
+         return( NULL ) ;
+   
+      case '=':
+         op = SET_EQ ;
+         break ;
+      
+      case '+':
+      case '-':
+         op = ( *p++ == '+' ) ? PLUS_EQ : MINUS_EQ ;
+         if ( *p == '=' )
+            break ;
+         
+         /* FALL THROUGH if there is no '=' after the '+' or '-' */
+      
+      default:
+         parsemsg( LOG_ERR, func, "Bad operator for attribute: %s", attr ) ;
+         return( NULL ) ;
+   }
+   *attrp = attr ;
+   *opp = op ;
+   return( ++p ) ;      /* skip the '=' */
+}
+
+
+/*
+ * Parse a line of the form:
+ *         name OP value value value ...
+ * where each value is a string and OP can be '=', '+=', '-='
+ *
+ * NOTE: We do not allocate space for the name and values. Instead we keep
+ *         pointers to the line.
+ */
+status_e parse_line( char *line, 
+                     char **namep, 
+                     enum assign_op *opp, 
+                     pset_h values )
+{
+   char      *value ;
+   char      *values_string ;
+   char      *attribute ;
+   str_h    strp ;
+   const char *func = "parse_line" ;
+
+   if ( ( values_string = get_attr_op( line, &attribute, opp ) ) == NULL )
+      return( FAILED ) ;
+
+   /*
+    * Now grab the values
+    */
+   strp = str_parse( values_string, " \t", STR_RETURN_ERROR, (int *)0 ) ;
+   if ( strp == NULL )
+   {
+      parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
+      return( FAILED ) ;
+   }
+
+   while ( (value = str_component( strp )) )
+   {
+      if ( pset_add( values, value ) == NULL )
+      {
+         parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
+         str_endparse( strp ) ;
+         return( FAILED ) ;
+      }
+   }
+
+   str_endparse( strp ) ;
+   *namep = attribute ;
+   return( OK ) ;
+}
+
+
+void skip_entry( int fd )
+{
+   for ( ;; )
+   {
+      char *line = next_line( fd ) ;
+
+      if ( line == NULL )         /* reached EOF ? */
+      {
+         parsemsg( LOG_WARNING, "skip_entry",
+            "missing %c in last service entry", ENTRY_END ) ;
+         break ;
+      }
+
+      if ( line_has_only_1_char( line, ENTRY_END ) )
+         break ;
+   }
+}
+
+
+
+/*
+ * Returns TRUE if the given line contains a single instance of the
+ * specified character and no other non-space characters
+ */
+int line_has_only_1_char( const char *line, char ch )
+{
+   const char *p ;
+   char target_char = ch ;
+
+   for ( p = line ; *p ; p++ )
+      if ( *p == target_char )
+         target_char = NUL ;
+      else if ( ! isspace( *p ) )
+         return( FALSE ) ;
+   return( target_char != ch ) ;
+}
+
diff --git a/xinetd/parsesup.h b/xinetd/parsesup.h
new file mode 100644 (file)
index 0000000..0c1ac86
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PARSESUP_H
+#define PARSESUP_H
+
+#include "parse.h"
+
+char *next_line(int fd);
+status_e parse_line( char *line, char **namep, enum assign_op *opp,
+       pset_h values);
+void skip_entry(int fd);
+int line_has_only_1_char(const char *line, char ch);
+
+#endif
diff --git a/xinetd/reconfig.c b/xinetd/reconfig.c
new file mode 100644 (file)
index 0000000..cc065a3
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <signal.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#ifndef NO_RPC
+ #ifdef HAVE_RPC_PMAP_CLNT_H
+  #ifdef __sun
+   #include <rpc/types.h>
+   #include <rpc/auth.h>
+  #endif
+  #include <rpc/types.h>
+  #include <rpc/xdr.h>
+  #include <rpc/auth.h>
+  #include <rpc/clnt.h>
+  #include <rpc/pmap_clnt.h>
+ #endif
+ #include <rpc/rpc.h>
+#endif
+
+#include "reconfig.h"
+#include "msg.h"
+#include "sconf.h"
+#include "conf.h"
+#include "confparse.h"
+#include "state.h"
+#include "main.h"
+#include "retry.h"
+#include "logctl.h"
+#include "options.h"
+
+
+static status_e readjust(struct service *sp, 
+               struct service_config **new_conf_ptr) ;
+static void swap_defaults(struct configuration *new_conf) ;
+static void close_default_log(struct configuration *confp, xlog_h def_log);
+
+#define SWAP( x, y, temp )         (temp) = (x), (x) = (y), (y) = (temp)
+
+
+/*
+ * Reconfigure the server by rereading the configuration file.
+ * Services may be added, deleted or have their attributes changed.
+ * All syslog output uses the LOG_NOTICE priority level (except for
+ * errors).
+ */
+void hard_reconfig( void )
+{
+   struct service            *osp ;
+   struct service_config     *nscp ;
+   struct configuration      new_conf ;
+   psi_h                     iter ;
+   unsigned                  new_services ;
+   unsigned                  old_services      = 0 ;
+   unsigned                  dropped_services   = 0 ;
+   xlog_h                   def_log = DEFAULT_LOG( ps );
+   const char               *func               = "hard_reconfig" ;
+
+
+   msg( LOG_NOTICE, func, "Starting reconfiguration" ) ;
+
+   if ( cnf_get( &new_conf ) == FAILED )
+   {
+      msg( LOG_WARNING, func, "reconfiguration failed" ) ;
+      return ;
+   }
+
+   iter = psi_create( SERVICES( ps ) ) ;
+   if ( iter == NULL )
+   {
+      out_of_memory( func ) ;
+      cnf_free( &new_conf ) ;
+      return ;
+   }
+
+   /* After this call, new_conf's defaults point to the old one's defaults */
+   msg( LOG_NOTICE, func, "Swapping defaults" ) ;
+   swap_defaults( &new_conf ) ;
+
+   /*
+    * Glossary:
+    *      Sconf: service configuration
+    *      Lconf: list of service configurations
+    *
+    * Iterate over all existing services. If the service is included in the 
+    * new Lconf, readjust its attributes (as a side-effect, the new service 
+    * Sconf is removed from the new Lconf).
+    *   Services not in the new Lconf are deactivated.
+    */
+   for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
+   {
+      char *sid = SVC_ID( osp ) ;
+      boolean_e drop_service ;
+
+      /*
+       * Check if this service is in the new Lconf
+       * Notice that the service Sconf is removed from the new Lconf
+       * if it is found there.
+       */
+      if (  (nscp = cnf_extract( &new_conf, SVC_CONF( osp ) )) )
+      {
+         /*
+          * The first action of readjust is to swap the service configuration
+          * with nscp. This is the reason for passing the address of nscp
+          * (so that on return nscp will *always* point to the old service
+          * configuration).
+          */
+         if ( readjust( osp, &nscp ) == OK )
+         {
+            old_services++ ;
+            drop_service = NO ;
+         }
+         else   /* the readjustment failed */
+            drop_service = YES ;
+         sc_free( nscp ) ;
+      }
+      else
+         drop_service = YES ;
+
+      if ( drop_service == YES )
+      {
+         /*
+          * Procedure for disabling a service:
+          *
+          *      a. Deactivate the service to prevent new connections
+          *      b. Terminate running servers and cancel retry attempts, in case
+          *         of reconfiguration
+          */
+         svc_deactivate( osp ) ;
+         terminate_servers( osp ) ;
+         cancel_service_retries( osp ) ;
+
+         /*
+          * Deactivate the service; the service will be deleted only
+          * if its reference count drops to 0.
+          */
+         /* Always remove the service, even if not all the children
+          * have been killed, or there are other references.
+          */
+         psi_remove( iter ) ;
+         msg( LOG_NOTICE, func, "service %s deactivated", sid ) ;
+         if ( SVC_RELE( osp ) == 0 ) {
+            svc_release( osp );
+         } else
+            msg( LOG_ERR, func, "Errors deactivating service %s", sid ) ;
+         dropped_services++ ;
+      }
+   }
+
+   psi_destroy( iter ) ;
+
+   /*
+    * All services have terminated by now, so close the old common logfile.
+    * remember that swap_defaults put the old defaults section in new_conf.
+    */
+   close_default_log( &new_conf, def_log ) ;
+
+   /*
+    * At this point the new Lconf only contains services that were not
+    * in the old Lconf.
+    */
+   new_services = cnf_start_services( &new_conf ) ;
+   msg( LOG_NOTICE, func,
+      "Reconfigured: new=%d old=%d dropped=%d (services)",
+         new_services, old_services, dropped_services ) ;
+
+   if ( stayalive_option == 0 ) {
+      if ( ps.rws.available_services == 0 )
+      {
+         msg( LOG_CRIT, func, "No available services. Exiting" );
+         if ( ps.ros.pid_file ) {
+            unlink(ps.ros.pid_file);
+         }
+         exit( 1 ) ;
+      }
+   }
+
+   cnf_free( &new_conf ) ; 
+}
+
+
+static void swap_defaults( struct configuration *new_conf )
+{
+   struct service_config *temp ;
+
+   DEFAULT_LOG_ERROR( ps ) = FALSE ;
+   DEFAULT_LOG( ps ) = NULL ;
+   SWAP( DEFAULTS( ps ), CNF_DEFAULTS( new_conf ), temp ) ;
+}
+
+
+static void close_default_log(struct configuration *confp, xlog_h def_log)
+{
+   /* Close the common log file, if one was specified */
+   if ( def_log != NULL )
+      log_end( SC_LOG( CNF_DEFAULTS( confp ) ), def_log) ;
+}
+
+
+static void sendsig( struct server *serp, int sig )
+{
+   char      *sid   = SVC_ID( SERVER_SERVICE( serp ) ) ;
+   pid_t      pid   = SERVER_PID( serp ) ;
+   const char *func = "sendsig" ;
+
+   /*
+    * Always use a positive pid, because of the semantics of kill(2)
+    */
+   if ( pid > 0 )
+   {
+      msg( LOG_WARNING, func, "Sending signal %d to %s server %d",
+                                    sig, sid, pid ) ;
+      kill( pid, sig ) ;
+      if ((sig == SIGTERM) || (sig == SIGKILL))
+      {
+         int i, killed = 0;
+         struct timeval tv;
+
+         /*
+          * We will try 4 seconds to TERM or KILL it. If it hasn't
+          * responded by 2.5 seconds, we will send a KILL to hasten
+          * its demise.
+          */
+
+         tv.tv_sec = 0;
+         tv.tv_usec = 500000; /* half a second */
+         for (i=0; i<8; i++)
+         {
+            if( server_lookup(pid) == NULL )
+           {
+              killed = 1;
+              break;
+           } else {
+               int wret = waitpid(pid, NULL, WNOHANG);
+              if (wret == pid) {
+                 killed = 1;
+                 break;
+               }
+               server_end(serp);
+            }
+        
+           /* May not have responded to TERM, send a KILL */
+           if ( i == 5)
+               kill( pid, SIGKILL ) ;
+                
+            /* Not dead yet, give some time. */
+            select(0, NULL, NULL, NULL, &tv);
+         }
+
+        /*
+         * If it didn't die, expect problems rebinding to this port if
+         * a hard_reconfig is in process.
+         */
+         if (!killed)
+            msg( LOG_ERR, func, "Server %d did not exit after SIGKILL", 
+                 pid ) ;
+         /* no need to server_end() here.  The killed process will generate
+          * a sigchld, which will invoke the signal handler, and clean things
+          * up there.
+          */
+      }
+   } 
+   else if ( pid != 0 )
+      msg( LOG_ERR, func, "Negative server pid = %d. Service %s", pid, sid ) ;
+}
+
+
+/*
+ * Send signal sig to all running servers of service sp
+ */
+static void deliver_signal( struct service *sp, int sig )
+{
+   unsigned u ;
+
+   for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
+   {
+      struct server *serp ;
+
+      serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
+      if ( SERVER_SERVICE( serp ) == sp ) {
+         sendsig( serp, sig ) ;
+         if ( (sig == SIGTERM) || (sig == SIGKILL) )
+            u--;
+      }
+   }
+}
+
+
+/*
+ * Terminate all servers of the specified service
+ */
+void terminate_servers( struct service *sp )
+{
+   int sig = SC_IS_INTERNAL( SVC_CONF( sp ) ) ? SIGTERM : SIGKILL ;
+
+   deliver_signal( sp, sig ) ;
+}
+
+
+static void stop_interception( struct service *sp )
+{
+   deliver_signal( sp, INTERCEPT_SIG ) ;
+}
+
+/*
+ * Stop logging. svc_activate starts logging and will leak a file
+ * descriptor and memory if this is not called prior.
+ */
+static void stop_log( struct service *sp, 
+                              struct service_config *old_conf )
+{
+   struct log *lp = SC_LOG( old_conf ) ;
+
+   if ( LOG_GET_TYPE( lp ) != L_NONE && SVC_IS_LOGGING( sp ) )
+      log_end( lp, SVC_LOG( sp ) ) ;
+   SVC_LOG( sp ) = NULL ;
+}
+
+/*
+ * Stop any logging and restart if necessary.
+ * Note that this has the side-effect of using the new common log
+ * handle as it should.
+ */
+static status_e restart_log( struct service *sp, 
+                              struct service_config *old_conf )
+{
+   stop_log( sp, old_conf ); 
+   return( log_start( sp, &SVC_LOG( sp ) ) ) ;
+}
+
+
+/*
+ * Unregister past versions, register new ones
+ * We do it the dumb way: first unregister; then register
+ * We try to be a little smart by checking if there has
+ * been any change in version numbers (if not, we do nothing).
+ * Also, we save the port number
+ */
+static status_e readjust_rpc_service( struct service_config *old_scp, 
+                                       struct service_config *new_scp )
+{
+   unsigned long      vers ;
+   uint16_t           port                  = SC_PORT( old_scp ) ;
+   struct rpc_data   *new_rdp               = SC_RPCDATA( new_scp ) ;
+   struct rpc_data   *old_rdp               = SC_RPCDATA( old_scp ) ;
+   unsigned           registered_versions   = 0 ;
+   const char        *func                  = "readjust_rpc_service" ;
+
+#ifndef NO_RPC
+   SC_PORT( new_scp ) = SC_PORT( old_scp ) ;
+
+   if ( RD_MINVERS( old_rdp ) == RD_MINVERS( new_rdp ) &&
+            RD_MAXVERS( old_rdp ) == RD_MAXVERS( new_rdp ) )
+      return( OK ) ;
+
+   for ( vers = RD_MINVERS( old_rdp ) ; vers <= RD_MAXVERS( old_rdp ) ; vers++ )
+       (void) pmap_unset( RD_PROGNUM( old_rdp ), vers ) ;
+
+   for ( vers = RD_MINVERS( new_rdp ) ; vers <= RD_MAXVERS( new_rdp ) ; vers++ )
+      if ( pmap_set( RD_PROGNUM( new_rdp ),
+                              vers, SC_PROTOVAL( new_scp ), port ) )
+         registered_versions++ ;
+      else
+         msg( LOG_ERR, func, 
+            "pmap_set failed. service=%s, program=%ld, version = %ld",
+               SC_ID( new_scp ), RD_PROGNUM( new_rdp ), vers ) ;
+
+   if ( registered_versions == 0 )
+   {
+      msg( LOG_ERR, func,
+            "No versions registered for RPC service %s", SC_ID( new_scp ) ) ;
+      /*
+       * Avoid the pmap_unset
+       */
+      RD_MINVERS( new_rdp ) = RD_MAXVERS( new_rdp ) + 1 ;
+      return( FAILED ) ;
+   }
+#endif   /* ! NO_RPC */
+   return( OK ) ;
+}
+
+
+/*
+ * Readjust service attributes. 
+ *
+ * We assume that the following attributes are the same:
+ *         wait
+ *         socket_type
+ *         type
+ *         protocol
+ *
+ * Readjustment happens in 3 steps:
+ *      1) We swap the svc_conf fields
+ *            This has the side-effect of free'ing the memory associated
+ *            with the old service configuration when the new configuration
+ *            is destroyed.
+ *      2) We readjust the fields that require some action to be taken:
+ *            RPC mapping
+ *            log file open
+ *      3) We update the address control fields.
+ */
+static status_e readjust( struct service *sp, 
+                           struct service_config **new_conf_ptr )
+{
+   struct service_config   *temp_conf ;
+   struct service_config   *old_conf   = SVC_CONF( sp ) ;
+   struct service_config   *new_conf   = *new_conf_ptr ;
+   char                    *sid        = SVC_ID( sp ) ;
+   const char              *func       = "readjust" ;
+
+   msg( LOG_NOTICE, func, "readjusting service %s", sid ) ;
+
+   SWAP( SVC_CONF( sp ), *new_conf_ptr, temp_conf ) ;
+
+   if ( SC_IS_RPC( old_conf ) &&
+                  readjust_rpc_service( old_conf, new_conf ) == FAILED )
+      return( FAILED ) ;
+   
+   /*
+    * This is what happens if the INTERCEPT flag is toggled and an
+    * interceptor is running:
+    *
+    * Case 1: clear->set
+    *      Wait until the server dies (soft reconfig) or
+    *      terminate the server (hard reconfig)
+    *
+    * Case 2: set->clear
+    *    Send a signal to the interceptor to tell it to stop intercepting
+    */
+   if ( SC_IS_INTERCEPTED( old_conf ) != SC_IS_INTERCEPTED( new_conf ) )
+   {
+      if ( SC_IS_INTERCEPTED( new_conf ) )         /* case 1 */
+         terminate_servers( sp ) ;
+      else                                       /* case 2 */
+      {
+         stop_interception( sp ) ;
+         msg( LOG_NOTICE, func, "Stopping interception for %s", sid ) ;
+      }
+   }
+
+   /* 
+    * See if the bind address was specified in both the old and new config,
+    * then if it changed, readjust the service. The algorithm is check to 
+    * see if they are in the same address family, if so start a simple 
+    * comparison based on the address family. If IPv4, the addresses can be 
+    * compared directly, otherwise use the IPv6 macro. If they are not the 
+    * same, terminate & restart the service. 
+    */
+   if( (SC_BIND_ADDR(old_conf) != NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
+      int same = 0;
+
+      if ( SA(SC_BIND_ADDR(old_conf))->sa_family == 
+           SA(SC_BIND_ADDR(new_conf))->sa_family ) {
+         if ( SA(SC_BIND_ADDR(old_conf))->sa_family == AF_INET ) {
+            if ( SAIN(SC_BIND_ADDR(old_conf))->sin_addr.s_addr == 
+                 SAIN(SC_BIND_ADDR(new_conf))->sin_addr.s_addr)
+               same = 1;
+         }
+         else if ( IN6_ARE_ADDR_EQUAL(
+                  &SAIN6(SC_BIND_ADDR(old_conf))->sin6_addr, 
+                  &SAIN6(SC_BIND_ADDR(new_conf))->sin6_addr) )
+            same = 1;
+      }
+      
+      if ( !same ) {
+         terminate_servers( sp );
+         svc_deactivate( sp );
+         stop_log( sp, old_conf ); /* svc_activate re-starts logging */
+         svc_activate( sp );
+         return OK;
+      }
+   }
+
+   /* If the service didn't have a bind address before, but does now,
+    * make sure the new bind directive takes effect.
+    */
+   if( (SC_BIND_ADDR(old_conf) == NULL) && (SC_BIND_ADDR(new_conf) != NULL) ) {
+      terminate_servers( sp );
+      svc_deactivate(sp);
+      stop_log( sp, old_conf ); /* svc_activate re-starts logging */
+      svc_activate(sp);
+      return OK;
+   }
+
+   if( (SC_IPV4(old_conf) && SC_IPV6(new_conf)) || 
+         (SC_IPV6(old_conf) && SC_IPV4(new_conf)) ) {
+      terminate_servers( sp );
+      svc_deactivate(sp);
+      stop_log( sp, old_conf ); /* svc_activate re-starts logging */
+      svc_activate(sp);
+      return OK;
+   }
+
+   return( restart_log( sp, old_conf ) ) ;
+}
+
diff --git a/xinetd/reconfig.h b/xinetd/reconfig.h
new file mode 100644 (file)
index 0000000..de2ea5d
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef RECONFIG_H
+#define RECONFIG_H
+
+#include "defs.h"
+
+void hard_reconfig(void);
+void terminate_servers(struct service *sp);
+
+#endif
diff --git a/xinetd/redirect.c b/xinetd/redirect.c
new file mode 100644 (file)
index 0000000..cf93b73
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/tcp.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_SYS_SIGNAL_H
+#include <sys/signal.h>
+#endif
+
+#include "redirect.h"
+#include "service.h"
+#include "log.h"
+#include "sconf.h"
+#include "msg.h"
+
+#define NET_BUFFER 1500
+
+static int RedirServerFd = -1;
+
+/* Theoretically, this gets invoked when the remote side is no
+ * longer available for reading or writing.
+ * So, we send a HUP to the child process, wait(), then exit.
+ */
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+static void redir_sigpipe( int signum ) 
+{
+   Sclose(RedirServerFd);
+   _exit(0);
+}
+
+/* Do the redirection of a service */
+/* This function gets called from child.c after we have been forked */
+void redir_handler( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE( serp );
+   struct service_config *scp = SVC_CONF( sp );
+   int RedirDescrip = SERVER_FD( serp );
+   int maxfd, num_read, num_wrote=0, ret=0;
+   unsigned int sin_len = 0;
+   unsigned long bytes_in = 0, bytes_out = 0;
+   int no_to_nagle = 1;
+   int on = 1, v6on;
+   char buff[NET_BUFFER];
+   fd_set rdfd, msfd;
+   struct timeval *timep = NULL;
+   const char *func = "redir_handler";
+   union xsockaddr serveraddr ;
+
+   if( signal(SIGPIPE, redir_sigpipe) == SIG_ERR ) 
+      msg(LOG_ERR, func, "unable to setup signal handler");
+
+   close_all_svc_descriptors();
+
+   /* If it's a tcp service we are redirecting */
+   if( SC_PROTOVAL(scp) == IPPROTO_TCP )
+   {
+      memcpy(&serveraddr, SC_REDIR_ADDR(scp), sizeof(serveraddr));
+      if( serveraddr.sa_in.sin_family == AF_INET ) {
+         sin_len = sizeof( struct sockaddr_in );
+         RedirServerFd = socket(AF_INET, SOCK_STREAM, 0);
+       } else if( serveraddr.sa_in.sin_family == AF_INET6 ) {
+         sin_len = sizeof( struct sockaddr_in6 );
+         RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0);
+      } else {
+         msg(LOG_ERR, func, "not a valid protocol. Use IPv4 or IPv6.");
+         exit(0);
+      }
+
+      if( RedirServerFd < 0 )
+      {
+         msg(LOG_ERR, func, "cannot create socket: %m");
+         exit(0);
+      }
+
+      if( SC_IPV6( scp ) ) {
+         if( SC_V6ONLY( scp ) ) {
+            v6on = 1;
+         } else {
+            v6on = 0;
+         }
+#ifdef IPV6_V6ONLY
+         if( setsockopt(RedirServerFd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) { 
+            msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" );
+         }
+#endif
+
+      }
+      if( SC_KEEPALIVE( scp ) )
+         if (setsockopt(RedirServerFd, SOL_SOCKET, SO_KEEPALIVE, 
+                        (char *)&on, sizeof( on ) ) < 0 )
+            msg(LOG_ERR, func, 
+                "setsockopt SO_KEEPALIVE RedirServerFd failed: %m");
+      
+      if( serveraddr.sa_in.sin_family == AF_INET )
+         serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port);
+      if( serveraddr.sa_in.sin_family == AF_INET6 )
+         serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port);
+
+      if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 )
+      {
+         msg(LOG_ERR, func, "can't connect to remote host %s: %m",
+            xaddrname( &serveraddr ) );
+         exit(0);
+      }
+
+      /* connection now established */
+
+      if (setsockopt(RedirServerFd, IPPROTO_TCP, TCP_NODELAY, 
+         (char *) &no_to_nagle, sizeof( on ) ) < 0) {
+
+         msg(LOG_ERR, func, "setsockopt RedirServerFd failed: %m");
+      }
+
+      if (setsockopt(RedirDescrip, IPPROTO_TCP, TCP_NODELAY, 
+         (char *) &no_to_nagle, sizeof( on ) ) < 0) {
+
+         msg(LOG_ERR, func, "setsockopt RedirDescrip failed: %m");
+      }
+
+      maxfd = (RedirServerFd > RedirDescrip)?RedirServerFd:RedirDescrip;
+      FD_ZERO(&msfd);
+      FD_SET(RedirDescrip, &msfd);
+      FD_SET(RedirServerFd, &msfd);
+
+      while(1) {
+         memcpy(&rdfd, &msfd, sizeof(rdfd));
+         if (select(maxfd + 1, &rdfd, (fd_set *)0, (fd_set *)0, timep) <= 0) {
+            /* place for timeout code, currently does not time out */
+            break;
+         }
+
+         if (FD_ISSET(RedirDescrip, &rdfd)) {
+            do {
+               num_read = read(RedirDescrip,
+                  buff, sizeof(buff));
+               if (num_read == -1 && errno == EINTR)
+                  continue;
+               if (num_read <= 0)
+                  goto REDIROUT;
+               bytes_in += num_read;
+            } while (num_read < 0);
+
+            /* Loop until we have written everything
+             * that was read */
+            num_wrote = 0;
+            while( num_wrote < num_read ) {
+               ret = write(RedirServerFd,
+                  buff + num_wrote,
+                  num_read - num_wrote);
+               if (ret == -1 && errno == EINTR)
+                  continue;
+               if (ret <= 0)
+                  goto REDIROUT;
+               num_wrote += ret;
+            }
+         }
+
+         if (FD_ISSET(RedirServerFd, &rdfd)) {
+            do {
+               num_read = read(RedirServerFd,
+                  buff, sizeof(buff));
+               if (num_read == -1 && errno == EINTR)
+                  continue;
+               if (num_read <= 0)
+                  goto REDIROUT;
+               bytes_out += num_read;
+            } while (num_read < 0);
+
+            /* Loop until we have written everything
+             * that was read */
+            num_wrote = 0;
+            while( num_wrote < num_read ) {
+               ret = write(RedirDescrip,
+                  buff + num_wrote,
+                  num_read - num_wrote);
+               if (ret == -1 && errno == EINTR)
+                  continue;
+               if (ret <= 0)
+                  goto REDIROUT;
+               num_wrote += ret;
+            }
+         }
+      }
+REDIROUT:
+      if( M_IS_SET( SC_LOG_ON_SUCCESS(scp), LO_TRAFFIC ) ) {
+         svc_logprint( SERVER_CONNSERVICE( serp ), "TRAFFIC",
+                       "in=%lu(bytes) out=%lu(bytes)", bytes_in, bytes_out );
+      }
+
+      exit(0);
+   }
+
+   msg(LOG_ERR, func, 
+   "redirect with any protocol other than tcp is not supported at this time.");
+   exit(0);
+}
diff --git a/xinetd/redirect.h b/xinetd/redirect.h
new file mode 100644 (file)
index 0000000..fadedc0
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef REDIRECT_H
+#define REDIRECT_H
+
+#include "server.h"
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void redir_handler(struct server *serp);
+
+#endif
diff --git a/xinetd/retry.c b/xinetd/retry.c
new file mode 100644 (file)
index 0000000..505797f
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/time.h>
+#include <syslog.h>
+
+#include "pset.h"
+#include "retry.h"
+#include "state.h"
+#include "main.h"
+#include "server.h"
+#include "service.h"
+#include "connection.h"
+#include "xconfig.h"
+#include "msg.h"
+#include "sconf.h"
+#include "xtimer.h"
+
+static int retry_timer_running ;
+static void cancel_retry(struct server * serp );
+static void stop_retry_timer(void) ;
+static void start_retry_timer(void) ;
+
+
+/*
+ * Attempt to start all servers in the retry table
+ */
+static void server_retry(void)
+{
+   unsigned          servers_started = 0 ;
+   unsigned          u ;
+   const char       *func = "server_retry" ;
+
+   for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
+   {
+      struct server *retry = SERP( pset_pointer( RETRIES( ps ), u ) ) ;
+      struct service *sp = SERVER_SERVICE( retry ) ;
+      connection_s *cp = SERVER_CONNECTION( retry ) ;
+
+      /*
+       * Drop the retry if access control fails or we have
+       * a memory allocation problem
+       */
+      if ( svc_parent_access_control( sp, cp ) == FAILED ||
+         svc_child_access_control (sp, cp) == FAILED ||
+         pset_add( SERVERS( ps ), retry ) == NULL )
+      {
+         cancel_retry( retry ) ;
+         pset_pointer( RETRIES( ps ), u ) = NULL ;
+         continue ;
+      }
+
+      if ( server_start( retry ) == OK )
+      {
+         servers_started++ ;
+         SVC_DEC_RETRIES( sp ) ;
+         if ( !SVC_WAITS( sp ) )
+            CONN_CLOSE( cp ) ;
+         pset_pointer( RETRIES( ps ), u ) = NULL ;
+         continue ;
+      }
+      else
+      {
+         pset_remove( SERVERS( ps ), retry ) ;
+         if ( SERVER_FORKLIMIT( retry ) )
+         {
+            /*
+             * give up retrying
+             */
+            msg( LOG_ERR, func,
+               "service %s: too many consecutive fork failures", SVC_ID(sp) ) ;
+            svc_log_failure( sp, cp, AC_FORK ) ;
+            cancel_retry( retry ) ;
+            pset_pointer( RETRIES( ps ), u ) = NULL ;
+            continue ;
+         }
+         else
+         {
+            if ( debug.on )
+               msg( LOG_DEBUG, func,
+                  "fork failed for service %s. Retrying...", SVC_ID( sp ) ) ;
+         }
+      }
+   }
+
+   pset_compact( RETRIES( ps ) ) ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func,
+         "%d servers started, %d left to retry",
+            servers_started, pset_count( RETRIES( ps ) ) ) ;
+
+   /* If there's more, start another callback */
+   if ( pset_count( RETRIES( ps ) ) > 0 ) {
+      if ((retry_timer_running=xtimer_add(server_retry, RETRY_INTERVAL)) == -1)
+      {
+         msg( LOG_ERR, func, "xtimer_add: %m" ) ;
+         retry_timer_running = 0;
+      }
+   }
+   else
+      retry_timer_running = 0;
+}
+
+
+/*
+ * Schedule a retry by inserting the struct server in the retry table
+ * and starting the timer if necessary
+ */
+status_e schedule_retry( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE( serp ) ;
+   const char *func = "schedule_retry" ;
+
+   if ( pset_add( RETRIES( ps ), serp ) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   SVC_INC_RETRIES( sp ) ;
+   start_retry_timer() ;
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Scheduled retry attempt for %s", SVC_ID( sp ) ) ;
+   return( OK ) ;
+}
+
+
+/*
+ * This function should not be called for servers that correspond to
+ * services not in the service table because server_release will result
+ * in releasing all memory associated with the service (since the ref
+ * count will drop to 0).
+ */
+static void cancel_retry( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE( serp ) ;
+
+   conn_free( SERVER_CONNECTION( serp ), 1 ) ;
+   SVC_DEC_RETRIES( sp ) ;
+   server_release( serp ) ;
+}
+
+
+
+/*
+ * Cancel all retry attempts for the specified service
+ */
+void cancel_service_retries( struct service *sp )
+{
+   unsigned u ;
+   const char *func = "cancel_service_retries" ;
+
+   if ( SVC_RETRIES( sp ) == 0 )
+      return ;
+
+   u = 0 ;
+   while ( u < pset_count( RETRIES( ps ) ) )
+   {
+      struct server *serp ;
+
+      serp = SERP( pset_pointer( RETRIES( ps ), u ) ) ;
+      if ( SERVER_SERVICE( serp ) == sp )
+      {
+         msg( LOG_NOTICE, func,
+            "dropping retry attempt for service %s", SVC_ID( sp ) ) ;
+         cancel_retry( serp ) ;
+         pset_remove_index( RETRIES( ps ), u ) ;
+         continue ;
+      }
+      u++ ;
+   }
+
+   if ( pset_count( RETRIES( ps ) ) == 0 )
+      stop_retry_timer() ;
+}
+
+
+static void start_retry_timer(void)
+{
+   const char *func = "start_retry_timer" ;
+
+   /*
+    * Enable timer if necessary.
+    */
+
+   if ( retry_timer_running == 0 )
+      if((retry_timer_running=xtimer_add(server_retry, RETRY_INTERVAL)) == -1 ){
+         msg( LOG_ERR, func, "xtimer_add: %m" ) ;
+         retry_timer_running = 0;
+      }
+}
+
+
+static void stop_retry_timer(void)
+{
+   if ( retry_timer_running != 0)
+   {
+      xtimer_remove(retry_timer_running);
+      retry_timer_running = 0 ;
+   }
+}
+
diff --git a/xinetd/retry.h b/xinetd/retry.h
new file mode 100644 (file)
index 0000000..74fa440
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef RETRY_H
+#define RETRY_H
+
+#include "config.h"
+#include "defs.h"
+
+status_e schedule_retry(struct server *serp);
+void cancel_service_retries(struct service *sp);
+
+#endif
diff --git a/xinetd/sample.conf b/xinetd/sample.conf
new file mode 100644 (file)
index 0000000..178cba8
--- /dev/null
@@ -0,0 +1,347 @@
+#
+# Sample configuration file for xinetd
+#
+
+defaults
+{
+       instances               = 25
+       log_type                = FILE /var/log/servicelog
+       log_on_success  = HOST PID
+       log_on_failure = HOST 
+       only_from               = 128.138.193.0 128.138.204.0 128.138.209.0 128.138.243.0
+       only_from               = localhost 192.231.139.0/24
+       disabled                = tftp
+}
+
+
+#
+# Group 1: BSD services
+#
+# Shell, login, exec, comsat, talk, ntalk 
+#
+
+service login
+{
+       socket_type             = stream
+       protocol                = tcp
+       wait                    = no
+       user                    = root
+       server                  = /usr/etc/in.rlogind
+       log_type                = SYSLOG local4 info
+}
+
+
+service shell
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = root
+       instances               = UNLIMITED
+       flags                   = IDONLY
+       log_on_success += USERID
+       server                  = /usr/etc/in.rshd
+}
+
+
+service exec
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = root
+       server                  = /usr/etc/in.rexecd
+}
+
+service comsat
+{
+       socket_type             = dgram
+       wait                    = yes
+       user                    = nobody
+       group                   = tty
+       server                  = /usr/etc/in.comsat
+}
+
+service talk
+{
+       socket_type             = dgram
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/in.talkd
+}
+
+service ntalk
+{
+       socket_type             = dgram
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/in.ntalkd
+}
+
+#
+# Group 2: standard Internet services
+#
+# Telnet, ftp 
+#
+service telnet
+{
+       socket_type             = stream        
+       wait                    = no
+       user                    = root
+       server                  = /usr/etc/in.telnetd
+       bind                    = 127.0.0.1
+       log_on_failure += USERID
+}
+
+service telnet
+{
+       socket_type             = stream        
+       wait                    = no
+       user                    = root
+#      server                  = /usr/etc/in.telnetd
+       bind                    = 192.231.139.175
+       redirect                = 128.138.202.20 23
+       log_on_failure += USERID
+}
+
+service ftp
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = root
+       server                  = /usr/etc/in.ftpd
+       server_args             = -l
+       instances               = 4
+       log_on_success  += DURATION USERID
+       log_on_failure += USERID
+       access_times    = 2:00-8:59 12:00-23:59
+       nice                    = 10
+}
+
+#
+# Group 3: other services
+#
+
+#
+# Tnamed serves the obsolete IEN-116 name server protocol.
+#
+service name
+{
+       socket_type             = dgram
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/in.tnamed
+}
+
+#service uucp
+#{
+#      socket_type             = stream
+#      wait                    = no
+#      user                    = root
+#      server                  = /usr/etc/in.uucpd
+#}
+
+service tftp
+{
+       socket_type             = dgram
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/in.tftpd
+       server_args             = -s /tftpboot
+}
+
+
+#
+# Group 4: information services
+#
+service finger
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = nobody
+       server                  = /usr/etc/in.fingerd
+}
+
+service systat
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = nobody
+       server                  = /usr/bin/ps
+       server_args             = -auwwx
+       only_from               = 128.138.209.0
+       log_on_success          = HOST
+}
+
+service netstat
+{
+       socket_type             = stream
+       wait                    = no
+       user                    = nobody
+       server                  = /usr/ucb/netstat
+       server_args             = -f inet
+       only_from               = 128.138.209.0
+       log_on_success          = HOST
+}
+
+
+#
+# Group 5: internal services
+#
+# echo, time, daytime, chargen, servers, services
+#
+service echo
+{
+       type                    = INTERNAL
+       id                      = echo-stream
+       socket_type             = stream
+       protocol                = tcp
+       user                    = root
+       wait                    = no
+}
+
+service echo
+{
+       type                    = INTERNAL
+       id                      = echo-dgram
+       socket_type             = dgram
+       protocol                = udp
+       user                    = root
+       wait                    = yes
+}
+
+service chargen
+{
+       type                    = INTERNAL
+       id                      = chargen-stream
+       socket_type             = stream
+       protocol                = tcp
+       user                    = root
+       wait                    = no
+}
+
+service chargen
+{
+       type                    = INTERNAL
+       id                      = chargen-dgram
+       socket_type             = dgram
+       protocol                = udp
+       user                    = root
+       wait                    = yes
+}
+
+service daytime
+{
+       type                    = INTERNAL
+       id                      = daytime-stream
+       socket_type             = stream
+       protocol                = tcp
+       user                    = root
+       wait                    = no
+}
+
+service daytime
+{
+       type                    = INTERNAL
+       id                      = daytime-dgram
+       socket_type             = dgram
+       protocol                = udp
+       user                    = root
+       wait                    = yes
+}
+
+service time
+{
+       type                    = INTERNAL
+       id                      = time-stream
+       socket_type             = stream
+       protocol                = tcp
+       user                    = root
+       wait                    = no
+}
+
+
+service time
+{
+       type                    = INTERNAL
+       id                      = time-dgram
+       socket_type             = dgram
+       protocol                = udp
+       user                    = root
+       wait                    = yes
+}
+
+
+#
+# Group 6: RPC services
+#
+service rstatd
+{
+       type                    = RPC
+       flags                   = INTERCEPT
+       rpc_version             = 2-4
+       socket_type             = dgram
+       protocol                = udp
+       server                  = /usr/etc/rpc.rstatd
+       wait                    = yes
+       user                    = root
+}
+
+service rquotad
+{
+       type                    = RPC
+       rpc_version             = 1
+       socket_type             = dgram
+       protocol                = udp
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/rpc.rstatd
+}
+
+service rusersd
+{
+       type                    = RPC
+       rpc_version             = 1-2
+       socket_type             = dgram
+       protocol                = udp
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/rpc.rusersd
+}
+
+service sprayd
+{
+       type                    = RPC
+       rpc_version             = 1
+       socket_type             = dgram
+       protocol                = udp
+       wait                    = yes
+       user                    = root
+       server                  = /usr/etc/rpc.sprayd
+}
+
+service walld
+{
+       type                    = RPC
+       rpc_version             = 1
+       socket_type             = dgram
+       protocol                = udp
+       wait                    = yes
+       user                    = nobody
+       group                   = tty
+       server                  = /usr/etc/rpc.rwalld
+}
+
+
+#
+# Group 7: Security Sensors
+#
+service irc
+{
+         socket_type              = stream
+         wait                     = no
+         user                     = root
+         flags                    = SENSOR
+         type                     = INTERNAL
+         bind                     = 192.168.1.30
+         deny_time                = 60
+}
+
diff --git a/xinetd/sconf.c b/xinetd/sconf.c
new file mode 100644 (file)
index 0000000..71b6a30
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "str.h"
+#include "sio.h"
+#include "sconf.h"
+#include "timex.h"
+#include "addr.h"
+#include "nvlists.h"
+#include "xmdns.h"
+
+
+#define NEW_SCONF()               NEW( struct service_config )
+#define FREE_SCONF( scp )         FREE( scp )
+
+/*
+ * Conditional free; checks if the pointer is NULL
+ */
+#define COND_FREE( x )           if ( x )                   \
+                                 {                          \
+                                    *x = NUL ;              \
+                                    free( (char *) x ) ;    \
+                                 }
+
+
+/*
+ * Allocate a new service_config and initialize the service name field
+ * with 'name'; the rest of the fields are set to 0 which gives them
+ * their default values.
+ */
+struct service_config *sc_alloc( const char *name )
+{
+   struct service_config *scp ;
+   const char *func = "sc_alloc" ;
+
+   scp = NEW_SCONF() ;
+   if ( scp == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+   CLEAR( *scp ) ;
+   SC_NAME(scp) = new_string( name ) ;
+#ifdef HAVE_MDNS
+   xinetd_mdns_svc_init(scp);
+#endif
+   return( scp ) ;
+}
+
+
+static void release_string_pset( pset_h pset )
+{
+   pset_apply( pset, free, NULL ) ;
+   pset_destroy( pset ) ;
+}
+
+
+/*
+ * Free all malloc'ed memory for the specified service
+ */
+void sc_free( struct service_config *scp )
+{
+#ifdef HAVE_MDNS
+   COND_FREE( SC_MDNS_NAME(scp) );
+   xinetd_mdns_svc_free(scp);
+#endif
+#ifdef LIBWRAP
+   COND_FREE( SC_LIBWRAP(scp) );
+#endif
+   COND_FREE( SC_NAME(scp) ) ;
+   COND_FREE( SC_ID(scp) ) ;
+   COND_FREE( SC_PROTONAME(scp) ) ;
+   COND_FREE( SC_SERVER(scp) ) ;
+   COND_FREE( (char *)SC_REDIR_ADDR(scp) ) ;
+   COND_FREE( (char *)SC_BIND_ADDR(scp) ) ;
+   COND_FREE( (char *)SC_ORIG_BIND_ADDR(scp) ) ;
+   COND_FREE( (char *)SC_BANNER(scp) ) ;
+   COND_FREE( (char *)SC_BANNER_SUCCESS(scp) ) ;
+   COND_FREE( (char *)SC_BANNER_FAIL(scp) ) ;
+   if ( SC_SERVER_ARGV(scp) )
+   {
+      char **pp ;
+
+      /*
+       * argv[ 0 ] is a special case because it may not have been allocated yet
+       */
+      if ( SC_SERVER_ARGV(scp)[ 0 ] != NULL)
+         free( SC_SERVER_ARGV(scp)[ 0 ] ) ;
+      for ( pp = &SC_SERVER_ARGV(scp)[ 1 ] ; *pp != NULL ; pp++ )
+         free( *pp ) ;
+      free( (char *) SC_SERVER_ARGV(scp) ) ;
+   }
+   COND_FREE( LOG_GET_FILELOG( SC_LOG( scp ) )->fl_filename ) ;
+
+   if ( SC_ACCESS_TIMES(scp) != NULL )
+   {
+      ti_free( SC_ACCESS_TIMES(scp) ) ;
+      pset_destroy( SC_ACCESS_TIMES(scp) ) ;
+   }
+
+   if ( SC_ONLY_FROM(scp) != NULL )
+   {
+      addrlist_free( SC_ONLY_FROM(scp) ) ;
+      pset_destroy( SC_ONLY_FROM(scp) ) ;
+   }
+
+   if ( SC_NO_ACCESS(scp) != NULL )
+   {
+      addrlist_free( SC_NO_ACCESS(scp) ) ;
+      pset_destroy( SC_NO_ACCESS(scp) ) ;
+   }
+
+   if ( SC_ENV_VAR_DEFS(scp) != NULL )
+      release_string_pset( SC_ENV_VAR_DEFS(scp) ) ;
+   if ( SC_PASS_ENV_VARS(scp) != NULL )
+      release_string_pset( SC_PASS_ENV_VARS(scp) ) ;
+   if ( SC_ENV( scp )->env_type == CUSTOM_ENV && 
+                                    SC_ENV( scp )->env_handle != ENV_NULL )
+      env_destroy( SC_ENV( scp )->env_handle ) ;
+   if (SC_DISABLED(scp) ) 
+      release_string_pset( SC_DISABLED(scp) ) ;
+   if (SC_ENABLED(scp) ) 
+      release_string_pset( SC_ENABLED(scp) ) ;
+   
+   CLEAR( *scp ) ;
+   FREE_SCONF( scp ) ;
+}
+
+
+/*
+ * Create a configuration for one of the special services
+ */
+struct service_config *sc_make_special( const char *service_name, 
+                                        const builtin_s *bp, 
+                                        int instances )
+{
+   struct service_config *scp ;
+   const char *func = "sc_make" ;
+
+   if ( ( scp = sc_alloc( service_name ) ) == NULL )
+      return( NULL ) ;
+
+   SC_ID(scp) = new_string( SC_NAME(scp) ) ;
+   if ( SC_ID(scp) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+   SC_SPECIFY( scp, A_ID ) ;
+
+   /*
+    * All special services are internal
+    */
+   M_SET( SC_TYPE(scp), ST_SPECIAL ) ;
+   M_SET( SC_TYPE(scp), ST_INTERNAL ) ;
+   SC_BUILTIN(scp) = bp ;
+   SC_SPECIFY( scp, A_TYPE ) ;
+
+   M_SET( SC_XFLAGS(scp), SF_NORETRY ) ;
+   SC_SPECIFY( scp, A_FLAGS ) ;
+
+   SC_INSTANCES(scp) = instances ;
+   SC_SPECIFY( scp, A_INSTANCES ) ;
+
+   SC_WAIT(scp) = NO ;
+   SC_SPECIFY( scp, A_WAIT ) ;
+
+   return( scp ) ;
+}
+
+
+static void dump_log_data( int fd, struct service_config *scp, int tab_level )
+{
+   struct log *lp = SC_LOG( scp ) ;
+   struct filelog *flp ;
+   int i ;
+
+   switch ( LOG_GET_TYPE( lp ) )
+   {
+      case L_NONE:
+         tabprint( fd, tab_level, "No logging\n" ) ;
+         return ;
+
+      case L_COMMON_FILE:
+         tabprint( fd, tab_level, "Logging to common log file\n" ) ;
+         break ;
+
+      case L_FILE:
+         flp = LOG_GET_FILELOG( lp ) ;
+         tabprint( fd, tab_level, "Logging to file: %s", flp->fl_filename ) ;
+
+         if ( FILELOG_SIZE_CONTROL( flp ) )
+            Sprint( fd, " (soft=%d hard=%d)\n",
+                        flp->fl_soft_limit, flp->fl_hard_limit ) ;
+         else
+            Sprint( fd, " (no limits)\n" ) ;
+         break ;
+      
+      case L_SYSLOG:
+         tabprint( fd, tab_level,
+            "Logging to syslog. Facility = %s, level = %s\n",
+               nv_get_name( syslog_facilities, lp->l_sl.sl_facility ),
+               nv_get_name( syslog_levels, lp->l_sl.sl_level ) ) ;
+         break ;
+   }
+
+   tabprint( fd, tab_level, "Log_on_success flags =" ) ;
+   for ( i = 0 ; success_log_options[ i ].name != NULL ; i++ )
+      if ( M_IS_SET( SC_LOG_ON_SUCCESS(scp), success_log_options[ i ].value ) )
+         Sprint( fd, " %s", success_log_options[ i ].name ) ;
+   Sputchar( fd, '\n' ) ;
+
+   tabprint( fd, tab_level, "Log_on_failure flags =" ) ;
+   for ( i = 0 ; failure_log_options[ i ].name != NULL ; i++ )
+      if ( M_IS_SET( SC_LOG_ON_FAILURE(scp), failure_log_options[ i ].value ) )
+         Sprint( fd, " %s", failure_log_options[ i ].name ) ;
+   Sputchar( fd, '\n' ) ;
+}
+
+
+/*
+ * Print info about service scp to file descriptor fd
+ */
+void sc_dump( struct service_config *scp, 
+              int fd, 
+              int tab_level, 
+              bool_int is_defaults )
+{
+   const struct name_value    *nvp ;
+   unsigned             u ;
+   char                 **pp ;
+
+   if ( is_defaults )
+      tabprint( fd, tab_level, "Service defaults\n" ) ;
+   else
+      tabprint( fd, tab_level, "Service configuration: %s\n", SC_NAME(scp) ) ;
+
+   if ( ! is_defaults )
+   {
+      tabprint( fd, tab_level+1, "id = %s\n", SC_ID(scp) ) ;
+
+      if ( ! M_ARE_ALL_CLEAR( SC_XFLAGS(scp) ) )
+      {
+         tabprint( fd, tab_level+1, "flags =" ) ;
+         for ( nvp = &service_flags[ 0 ] ; nvp->name != NULL ; nvp++ )
+            if ( M_IS_SET( SC_XFLAGS(scp), nvp->value ) )
+               Sprint( fd, " %s", nvp->name ) ;
+         Sputchar( fd, '\n' ) ;
+      }
+
+      if ( ! M_ARE_ALL_CLEAR( SC_TYPE(scp) ) )
+      {
+         tabprint( fd, tab_level+1, "type =" ) ;
+         for ( nvp = &service_types[ 0 ] ; nvp->name != NULL ; nvp++ )
+            if ( M_IS_SET( SC_TYPE(scp), nvp->value ) )
+               Sprint( fd, " %s", nvp->name ) ;
+         Sputchar( fd, '\n' ) ;
+      }
+
+      tabprint( fd, tab_level+1, "socket_type = %s\n",
+         nv_get_name( socket_types, SC_SOCKET_TYPE(scp) ) ) ;
+
+      tabprint( fd, tab_level+1, "Protocol (name,number) = (%s,%d)\n",
+            SC_PROTONAME(scp), SC_PROTOVAL(scp) ) ;
+      
+      if ( SC_SPECIFIED( scp, A_PORT ) )
+         tabprint( fd, tab_level+1, "port = %d\n", SC_PORT(scp) ) ;
+   }
+
+   if ( SC_SPECIFIED( scp, A_INSTANCES ) ) {
+      if ( SC_INSTANCES(scp) == UNLIMITED )
+         tabprint( fd, tab_level+1, "Instances = UNLIMITED\n" ) ;
+      else
+         tabprint( fd, tab_level+1, "Instances = %d\n", SC_INSTANCES(scp) ) ;
+   }
+
+   if ( SC_SPECIFIED( scp, A_WAIT ) ) {
+      if ( SC_WAIT(scp) )
+         tabprint( fd, tab_level+1, "wait = yes\n" ) ;
+      else
+         tabprint( fd, tab_level+1, "wait = no\n" ) ;
+   }
+      
+   if ( SC_SPECIFIED( scp, A_USER ) )
+      tabprint( fd, tab_level+1, "user = %d\n", SC_UID(scp) ) ;
+      
+   if ( SC_SPECIFIED( scp, A_GROUP ) )
+      tabprint( fd, tab_level+1, "group = %d\n", SC_GID(scp) ) ;
+      
+   if ( SC_SPECIFIED( scp, A_GROUPS ) )
+   {
+      if (SC_GROUPS(scp) == 1)
+         tabprint( fd, tab_level+1, "Groups = yes\n" );
+      else
+         tabprint( fd, tab_level+1, "Groups = no\n" );
+   }
+
+   if ( SC_SPECIFIED( scp, A_UMASK ) )
+      tabprint( fd, tab_level+1, "umask = %o\n", SC_UMASK(scp) ) ;
+      
+   if ( SC_SPECIFIED( scp, A_NICE ) )
+      tabprint( fd, tab_level+1, "Nice = %d\n", SC_NICE(scp) ) ;
+
+   if ( SC_SPECIFIED( scp, A_CPS ) )
+      tabprint( fd, tab_level+1, "CPS = max conn:%lu wait:%lu\n", 
+         SC_TIME_CONN_MAX(scp), SC_TIME_WAIT(scp) );
+
+   if ( SC_SPECIFIED( scp, A_PER_SOURCE ) )
+      tabprint( fd, tab_level+1, "PER_SOURCE = %d\n", 
+         SC_PER_SOURCE(scp) );
+
+   if ( SC_SPECIFIED( scp, A_BIND ) ) {
+          if (  SC_BIND_ADDR(scp) ) {
+                 char bindname[NI_MAXHOST];
+                 unsigned int len = 0;
+                 if( SC_BIND_ADDR(scp)->sa.sa_family == AF_INET ) 
+                        len = sizeof(struct sockaddr_in);
+                 else  
+                        len = sizeof(struct sockaddr_in6);
+                 memset(bindname, 0, sizeof(bindname));
+                 if( getnameinfo(&SC_BIND_ADDR(scp)->sa, len, bindname, 
+                                  NI_MAXHOST, NULL, 0, 0) != 0 ) 
+                        strcpy(bindname, "unknown");
+                 tabprint( fd, tab_level+1, "Bind = %s\n", bindname );
+          }
+          else if ( SC_ORIG_BIND_ADDR(scp) ) {
+                 tabprint( fd, tab_level+1, "Bind = %s\n", 
+                            SC_ORIG_BIND_ADDR(scp) );
+          }
+          else { /* This should NEVER happen */
+               msg(LOG_ERR, "sc_dump", "bad configuration for %s:", 
+                    SC_NAME(scp));
+          }
+   }
+   else
+      tabprint( fd, tab_level+1, "Bind = All addresses.\n" );
+
+   if ( ! is_defaults )
+   {
+      if ( (! SC_IS_INTERNAL( scp )) && (SC_REDIR_ADDR(scp) == NULL) )
+      {
+         tabprint( fd, tab_level+1, "Server = %s\n", SC_SERVER(scp) ) ;
+         tabprint( fd, tab_level+1, "Server argv =" ) ;
+        if ( SC_SERVER_ARGV(scp) )
+        {
+            for ( pp = SC_SERVER_ARGV(scp) ; *pp ; pp++ )
+               Sprint( fd, " %s", *pp ) ;
+        }
+        else
+           Sprint( fd, " (NULL)");
+         Sputchar( fd, '\n' ) ;
+      } 
+
+#ifdef LIBWRAP
+      if ( SC_LIBWRAP(scp) != NULL )
+      {
+         tabprint( fd, tab_level + 1, "Libwrap = %s\n", SC_LIBWRAP(scp) );
+      }
+#endif
+
+      if ( SC_REDIR_ADDR(scp) != NULL ) 
+      {
+         char redirname[NI_MAXHOST];
+         unsigned int len = 0;
+         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET ) 
+            len = sizeof(struct sockaddr_in);
+         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET6 ) 
+            len = sizeof(struct sockaddr_in6);
+         memset(redirname, 0, sizeof(redirname));
+         if( getnameinfo(&SC_REDIR_ADDR(scp)->sa, len,  redirname, NI_MAXHOST, 
+               NULL, 0, 0) != 0 ) 
+            strcpy(redirname, "unknown");
+         tabprint( fd, tab_level+1, "Redirect = %s:%d\n", redirname, 
+           SC_REDIR_ADDR(scp)->sa_in.sin_port );
+      }
+
+      if ( SC_IS_RPC( scp ) )
+      {
+         struct rpc_data *rdp = SC_RPCDATA( scp ) ;
+
+         tabprint( fd, tab_level+1, "RPC data\n" ) ;
+         tabprint( fd, tab_level+2,
+                           "program number = %ld\n", rdp->rd_program_number ) ;
+         tabprint( fd, tab_level+2, "rpc_version = " ) ;
+         if ( rdp->rd_min_version == rdp->rd_max_version )
+            Sprint( fd, "%ld\n", rdp->rd_min_version ) ;
+         else
+            Sprint( fd, "%ld-%ld\n",
+                           rdp->rd_min_version, rdp->rd_max_version ) ;
+      }
+
+      if ( SC_SPECIFIED( scp, A_ACCESS_TIMES ) )
+      {
+         tabprint( fd, tab_level+1, "Access times =" ) ;
+         ti_dump( SC_ACCESS_TIMES(scp), fd ) ;
+         Sputchar ( fd, '\n' ) ;
+      }
+   }
+
+   /* This is important enough that each service should list it. */
+   tabprint( fd, tab_level+1, "Only from: " ) ;
+   if ( SC_ONLY_FROM(scp) )
+   {  /* Next check is done since -= doesn't zero out lists. */
+      if ( pset_count(SC_ONLY_FROM(scp)) == 0)
+         Sprint( fd, "All sites" );
+      else
+         addrlist_dump( SC_ONLY_FROM(scp), fd ) ;
+   }
+   else
+      Sprint( fd, "All sites" );
+   Sputchar( fd, '\n' ) ;
+
+   /* This is important enough that each service should list it. */
+   tabprint( fd, tab_level+1, "No access: " ) ;
+   if ( SC_NO_ACCESS(scp) )
+   {  /* Next check is done since -= doesn't zero out lists. */
+      if ( pset_count(SC_NO_ACCESS(scp)) == 0)
+         Sprint( fd, "No blocked sites" );
+      else
+         addrlist_dump( SC_NO_ACCESS(scp), fd ) ;
+   }
+   else
+      Sprint( fd, "No blocked sites" );
+   Sputchar( fd, '\n' ) ;
+
+   if ( SC_SENSOR(scp) )
+   {
+      tabprint( fd, tab_level+1, "Deny Time: " ) ;
+      Sprint( fd, "%d\n", SC_DENY_TIME(scp));
+   }
+   
+   dump_log_data( fd, scp, tab_level+1 ) ;
+
+   if ( SC_IS_PRESENT( scp, A_PASSENV ) )
+   {
+      tabprint( fd, tab_level+1, "Passenv =" ) ;
+      for ( u = 0 ; u < pset_count( SC_PASS_ENV_VARS(scp) ) ; u++ )
+         Sprint( fd, " %s",
+                  (char *) pset_pointer( SC_PASS_ENV_VARS(scp), u ) ) ;
+      Sputchar ( fd, '\n' ) ;
+   }
+
+   if ( ! is_defaults )
+      if ( SC_SPECIFIED( scp, A_ENV ) )
+      {
+         tabprint( fd, tab_level+1, "Environment additions:\n" ) ;
+         for ( u = 0 ; u < pset_count( SC_ENV_VAR_DEFS(scp) ) ; u++ )
+            tabprint( fd, tab_level+2,
+                  "%s\n", (char *) pset_pointer( SC_ENV_VAR_DEFS(scp), u ) ) ;
+      }
+   
+   if ( SC_ENV( scp )->env_type == CUSTOM_ENV )
+   {
+      tabprint( fd, tab_level+1, "Environment strings:\n" ) ;
+      for ( pp = env_getvars( SC_ENV( scp )->env_handle ) ; *pp ; pp++ )
+         tabprint( fd, tab_level+2, "%s\n", *pp ) ;
+   }
+   Sflush( fd ) ;
+}
+
+
+#define SC_RPCPROGNUM( s )    RD_PROGNUM( SC_RPCDATA( s ) )
+#define SAME_RPC( s1, s2 )    ( SC_RPCPROGNUM( s1 ) == SC_RPCPROGNUM( s2 ) )
+#define SAME_NONRPC( s1, s2 ) ( SC_SOCKET_TYPE((s1)) == SC_SOCKET_TYPE((s2)) \
+                                 && SC_PORT((s1)) == SC_PORT((s2)) )
+
+/*
+ * Two service configurations are considered different if any of the
+ * following is TRUE:
+ *      1) only one is unlisted
+ *      2) only one is internal
+ *      3) only one is RPC
+ *      4) they have different values for the 'wait' attribute
+ *      5) they use different protocols
+ *      6) they are both RPC services but have different program numbers
+ *      7) neither is an RPC service and they have different socket_types or
+ *         use diffent ports
+ *
+ * This function returns TRUE if the specified configurations are different.
+ *
+ * Note that this function is closely related to the 'readjust' function
+ * that is invoked on reconfiguration; that function will not change 
+ * attributes that this function checks to determine if two configurations
+ * are different.
+ */
+bool_int sc_different_confs( struct service_config *scp1, 
+                             struct service_config *scp2 )
+{
+   if ( SC_IS_UNLISTED( scp1 ) != SC_IS_UNLISTED( scp2 ) ||
+            SC_IS_INTERNAL( scp1 ) != SC_IS_INTERNAL( scp2 ) ||
+               SC_IS_RPC( scp1 ) != SC_IS_RPC( scp2 ) )
+      return( TRUE ) ;
+
+   if ( SC_WAIT(scp1) != SC_WAIT(scp2) )
+      return( TRUE ) ;
+  
+   if ( SC_PROTOVAL(scp1) != SC_PROTOVAL(scp2) )
+      return( TRUE ) ;
+
+   if ( SC_IS_RPC( scp1 ) )
+   {
+      if ( ! SAME_RPC( scp1, scp2 ) )
+         return( TRUE ) ;
+   }
+   else
+   {
+      if ( ! SAME_NONRPC( scp1, scp2 ) )
+         return( TRUE ) ;
+   }
+   return( FALSE ) ;
+}
+
diff --git a/xinetd/sconf.h b/xinetd/sconf.h
new file mode 100644 (file)
index 0000000..08dc804
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef SCONF_H
+#define SCONF_H
+
+/*
+ * $Id: sconf.h,v 1.10 2005/10/05 17:15:33 bbraun Exp $
+ */
+#include "config.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include "libportable.h"
+
+#include "pset.h"
+#include "m_env.h"
+#include "mask.h"
+#include "defs.h"
+#include "log.h"
+#include "builtins.h"
+#include "attr.h"
+
+/*
+ * Service types
+ */
+#define ST_RPC          1
+#define ST_INTERNAL     2
+#define ST_UNLISTED     3
+#define ST_SPECIAL      4
+#define ST_DISABLED     5 
+#define ST_TCPMUX      6
+#define ST_TCPMUXPLUS  7
+
+/*
+ * Service flags
+ */
+#define SF_INTERCEPT    1
+#define SF_REUSE        2
+#define SF_NORETRY      3
+#define SF_IDONLY       4
+#define SF_NAMEINARGS   5
+#define SF_NODELAY      6
+#define SF_KEEPALIVE    7
+#define SF_NOLIBWRAP    8
+#define SF_SENSOR       9
+#define SF_IPV4         10
+#define SF_IPV6         11
+
+/*
+ * Values for log options
+ */
+#define LO_HOST      1
+#define LO_DURATION  3
+#define LO_ATTEMPT   4
+#define LO_EXIT      5
+#define LO_PID       6
+#define LO_USERID    7
+#define LO_TRAFFIC   8
+
+struct rpc_data
+{
+   unsigned long rd_min_version ;
+   unsigned long rd_max_version ;
+   unsigned long rd_program_number ;
+} ;
+
+#define RD_MINVERS( rdp )      (rdp)->rd_min_version
+#define RD_MAXVERS( rdp )      (rdp)->rd_max_version
+#define RD_PROGNUM( rdp )      (rdp)->rd_program_number
+
+typedef enum { NO_ENV = 0, STD_ENV, DEF_ENV, CUSTOM_ENV } environ_e ;
+
+struct environment
+{
+   environ_e  env_type ;
+   env_h      env_handle ;
+} ;
+
+/*
+ * NOTE: Clearing the structure will give all its fields their default values
+ */
+struct service_config
+{
+   mask_t               sc_specified_attributes; /* specified attributes */
+   mask_t               sc_attributes_present; /* includes those from defaults*/
+   mask_t               sc_type;               /* RPC, UNLISTED etc           */
+   mask_t               sc_xflags ;            /* INTERCEPT etc               */
+   char                *sc_name;               /* e g  "echo"                 */
+   char                *sc_id ;                /* e.g. "echo-stream"          */
+   uint16_t             sc_port ;              /* in host byte order          */
+   int                  sc_socket_type ;       /* e.g. SOCK_DGRAM             */
+   struct protocol_name_value sc_protocol ;    /* e.g. "TCP", IPPROTO_TCP     */
+   boolean_e            sc_wait ;
+   uid_t                sc_uid ;
+   gid_t                sc_user_gid ;          /* gid corresponding to uid    */
+   gid_t                sc_gid ;               /* gid corresponding to group  */
+   char                *sc_server ;
+   char               **sc_server_argv ;
+   int                  sc_instances ;
+   int                  sc_nice ;              /* argument for nice(3) */
+   pset_h               sc_env_var_defs ;      /* list of env strings         */
+   pset_h               sc_pass_env_vars ;     /* env vars to pass to server  */
+   pset_h               sc_access_times ;
+   pset_h               sc_only_from ;
+   pset_h               sc_no_access ;
+   mask_t               sc_log_on_success ;
+   mask_t               sc_log_on_failure ;
+   struct log           sc_log ;
+   struct rpc_data      sc_rd ;
+   pset_h               sc_disabled ;     /* used only by the default entry */
+   pset_h               sc_enabled ;      /* used only by the default entry */
+   struct environment   sc_environment ;
+   const builtin_s     *sc_builtin ;
+   union xsockaddr     *sc_redir_addr ;
+   char                *sc_orig_bind_addr ; /* used only when dual stack */
+   union xsockaddr     *sc_bind_addr ;
+   boolean_e            sc_v6only;
+   char                *sc_banner ;
+   int                  sc_per_source ;
+   boolean_e            sc_groups ;
+   char                *sc_banner_success ;
+   char                *sc_banner_fail ;
+   double               sc_max_load ;
+   time_t               sc_time_limit ;
+   time_t               sc_time_conn ;
+   time_t               sc_time_conn_max ;
+   time_t               sc_time_wait ;
+   time_t               sc_time_reenable ;
+   rlim_t               sc_rlim_as;
+   rlim_t               sc_rlim_cpu;
+   rlim_t               sc_rlim_data;
+   rlim_t               sc_rlim_rss;
+   rlim_t               sc_rlim_stack;
+   mode_t               sc_umask;
+   int                  sc_deny_time;         /* Sensor deny access time:
+                                                 -1: forever
+                                                  0: never
+                                                  X: X minutes          */
+#ifdef HAVE_MDNS
+   char                *sc_mdns_name;
+   boolean_e            sc_mdns;
+   void                *mdns_state;
+#endif
+#ifdef LIBWRAP
+   char                *sc_libwrap;
+#endif
+} ;
+
+#define SCP( p ) ((struct service_config *)(p))
+
+/*
+ * Field access macros
+ */
+#define SC_LOG( scp )            (&(scp)->sc_log)
+#define SC_RPCDATA( scp )        (&(scp)->sc_rd)
+#define SC_ENV( scp )            (&(scp)->sc_environment)
+#define SC_ENV_VAR_DEFS( scp )   (scp)->sc_env_var_defs
+#define SC_PORT( scp )           (scp)->sc_port
+#define SC_NICE( scp )           (scp)->sc_nice
+#define SC_SOCKET_TYPE( scp )    (scp)->sc_socket_type
+#define SC_ID( scp )             (scp)->sc_id
+#define SC_NAME( scp )           (scp)->sc_name
+#define SC_PROTOVAL( scp )       (scp)->sc_protocol.value
+#define SC_PROTONAME( scp )      (scp)->sc_protocol.name
+#define SC_INSTANCES( scp )      (scp)->sc_instances
+#define SC_UID( scp )            (scp)->sc_uid
+#define SC_GID( scp )            (scp)->sc_gid
+#define SC_USER_GID( scp )       (scp)->sc_user_gid
+#define SC_SERVER( scp )         (scp)->sc_server
+#define SC_SERVER_ARGV( scp )    (scp)->sc_server_argv
+#define SC_ONLY_FROM( scp )      (scp)->sc_only_from
+#define SC_NO_ACCESS( scp )      (scp)->sc_no_access
+#define SC_ACCESS_TIMES( scp )   (scp)->sc_access_times
+#define SC_LOG_ON_SUCCESS( scp ) (scp)->sc_log_on_success
+#define SC_LOG_ON_FAILURE( scp ) (scp)->sc_log_on_failure
+#define SC_PASS_ENV_VARS( scp )  (scp)->sc_pass_env_vars
+#define SC_RLIM_AS( scp )        (scp)->sc_rlim_as
+#define SC_RLIM_CPU( scp )       (scp)->sc_rlim_cpu
+#define SC_RLIM_DATA( scp )      (scp)->sc_rlim_data
+#define SC_RLIM_RSS( scp )       (scp)->sc_rlim_rss
+#define SC_RLIM_STACK( scp )     (scp)->sc_rlim_stack
+#define SC_TYPE( scp )           (scp)->sc_type
+#define SC_WAIT( scp )           (scp)->sc_wait
+#define SC_XFLAGS( scp )         (scp)->sc_xflags
+#define SC_V6ONLY( scp )         (scp)->sc_v6only
+#define SC_ENABLED( scp )        (scp)->sc_enabled
+#define SC_DISABLED( scp )       (scp)->sc_disabled
+#define SC_BUILTIN( scp )        (scp)->sc_builtin
+#define SC_REDIR_ADDR( scp )     (scp)->sc_redir_addr
+#define SC_ORIG_BIND_ADDR( scp ) (scp)->sc_orig_bind_addr
+#define SC_BIND_ADDR( scp )      (scp)->sc_bind_addr
+#define SC_BANNER( scp )         (scp)->sc_banner
+#define SC_BANNER_SUCCESS( scp ) (scp)->sc_banner_success
+#define SC_BANNER_FAIL( scp )    (scp)->sc_banner_fail
+#define SC_GROUPS( scp )         (scp)->sc_groups
+#define SC_MAX_LOAD( scp )       (scp)->sc_max_load
+#define SC_TIME_LIMIT( scp )     (scp)->sc_time_limit
+#define SC_TIME_CONN( scp )      (scp)->sc_time_conn
+#define SC_TIME_CONN_MAX( scp )  (scp)->sc_time_conn_max
+#define SC_TIME_WAIT( scp )      (scp)->sc_time_wait
+#define SC_TIME_REENABLE( scp )  (scp)->sc_time_reenable
+#define SC_UMASK( scp )          (scp)->sc_umask
+#define SC_DENY_TIME( scp )      (scp)->sc_deny_time
+#define SC_MDNS_NAME( scp )      (scp)->sc_mdns_name
+#define SC_MDNS( scp )           (scp)->sc_mdns
+#define SC_PER_SOURCE( scp )     (scp)->sc_per_source
+#define SC_LIBWRAP( scp )        (scp)->sc_libwrap
+/*
+ * Field set macros
+ */
+#define SC_SET_PORT( scp, port ) (scp)->sc_port = (port)
+
+/*
+ * Predicate checking macros
+ */
+#define SC_FORKS( scp )           ( ! SC_IS_INTERNAL( scp ) ||   \
+    BUILTIN_FORKS( (scp)->sc_builtin ) )
+#define SC_WAITS( scp )           ( (scp)->sc_wait == YES )
+#define SC_RETRY( scp )           ( M_IS_CLEAR( (scp)->sc_xflags, SF_NORETRY ) )
+#define SC_MUST_IDENTIFY( scp )   M_IS_SET( (scp)->sc_xflags, SF_IDONLY )
+#define SC_NAMEINARGS( scp )      M_IS_SET( (scp)->sc_xflags, SF_NAMEINARGS )
+#define SC_NODELAY( scp )         M_IS_SET( (scp)->sc_xflags, SF_NODELAY )
+#define SC_KEEPALIVE( scp )       M_IS_SET( (scp)->sc_xflags, SF_KEEPALIVE )
+#define SC_NOLIBWRAP( scp )       M_IS_SET( (scp)->sc_xflags, SF_NOLIBWRAP )
+#define SC_IS_INTERCEPTED( scp ) ( M_IS_SET( (scp)->sc_xflags, SF_INTERCEPT ) )
+#define SC_SENSOR( scp )          M_IS_SET( (scp)->sc_xflags, SF_SENSOR )
+#define SC_IPV4( scp )            M_IS_SET( (scp)->sc_xflags, SF_IPV4 )
+#define SC_IPV6( scp )            M_IS_SET( (scp)->sc_xflags, SF_IPV6 )
+
+#define SC_IS_RPC( scp )         ( M_IS_SET( (scp)->sc_type, ST_RPC ) )
+#define SC_IS_INTERNAL( scp )    ( M_IS_SET( (scp)->sc_type, ST_INTERNAL ) )
+#define SC_IS_SPECIAL( scp )     ( M_IS_SET( (scp)->sc_type, ST_SPECIAL ) )
+#define SC_IS_UNLISTED( scp )    ( M_IS_SET( (scp)->sc_type, ST_UNLISTED ) )
+#define SC_IS_DISABLED( scp )    ( M_IS_SET( (scp)->sc_type, ST_DISABLED ) )
+#define SC_DISABLE(scp)          ( M_SET( (scp)->sc_type, ST_DISABLED ) )
+#define SC_ENABLE(scp)           ( M_CLEAR( (scp)->sc_type, ST_DISABLED ) )
+#define SC_IS_MUXCLIENT( scp )   ( M_IS_SET( (scp)->sc_type, ST_TCPMUX ) || \
+                                  M_IS_SET( (scp)->sc_type, ST_TCPMUXPLUS ) )
+#define SC_IS_MUXPLUSCLIENT(scp) ( M_IS_SET( (scp)->sc_type, ST_TCPMUXPLUS ) )
+#define SC_IS_TCPMUX( scp )     ( (scp)->sc_builtin &&                     \
+                                   (BUILTIN_HANDLER( (scp)->sc_builtin ) == \
+                                  (void *)tcpmux_handler ) )
+
+#define LOGS_USERID( scp, flags ) \
+   ( M_IS_SET( (scp)->flags, LO_USERID ) && SC_ACCEPTS_CONNECTIONS( scp ) )
+
+#define LOGS_ANY( scp, flags )   ( ! M_ARE_ALL_CLEAR( (scp)->flags ) )
+
+#define SC_LOGS_ON_SUCCESS( scp )        LOGS_ANY( scp, sc_log_on_success )
+#define SC_LOGS_ON_FAILURE( scp )        LOGS_ANY( scp, sc_log_on_failure )
+#define SC_LOGS_USERID_ON_FAILURE( scp ) LOGS_USERID( scp, sc_log_on_failure )
+#define SC_LOGS_USERID_ON_SUCCESS( scp ) LOGS_USERID( scp, sc_log_on_success )
+#define SC_LOGS_ON_EXIT( scp )  \
+   ( M_IS_SET( (scp)->sc_log_on_success, LO_DURATION ) || \
+      M_IS_SET( (scp)->sc_log_on_success, LO_EXIT ) )
+#define SC_LOGS_PID( scp )   M_IS_SET( (scp)->sc_log_on_success, LO_PID )
+#define SC_LOGS_EXITS( scp ) M_IS_SET( (scp)->sc_log_on_success, LO_EXIT )
+#define SC_LOGS_DURATION( scp ) \
+   M_IS_SET( (scp)->sc_log_on_success, LO_DURATION )
+
+
+#define SC_MUST_LISTEN( scp )   ( (scp)->sc_socket_type == SOCK_STREAM )
+
+#define SC_ACCEPTS_CONNECTIONS( scp )     \
+      ( (scp)->sc_wait == NO && (scp)->sc_socket_type == SOCK_STREAM )
+
+#define SC_SPECIFIED( scp, attr )   \
+               M_IS_SET( (scp)->sc_specified_attributes, (attr) )
+#define SC_SPECIFY( scp, attr )     \
+               {                                                     \
+                  M_SET( (scp)->sc_specified_attributes, (attr) ) ;  \
+                  SC_PRESENT( (scp), (attr) ) ;                      \
+               }
+
+#define SC_IS_PRESENT( scp, attr )  \
+               M_IS_SET( (scp)->sc_attributes_present, (attr) )
+#define SC_PRESENT( scp, attr )     \
+               M_SET( (scp)->sc_attributes_present, (attr) )
+
+#define SC_GETGID( scp ) ( SC_SPECIFIED( scp, A_GROUP ) \
+   ? (scp)->sc_gid : (scp)->sc_user_gid )
+#define SC_INTERNAL( scp, serp )  BUILTIN_INVOKE( (scp)->sc_builtin, serp )
+#define SC_MAKE_EXTERNAL( scp )   M_CLEAR( (scp)->sc_type, ST_INTERNAL )
+
+struct service_config *sc_alloc(const char *name);
+void sc_free(struct service_config *scp);
+struct service_config *sc_make_special(const char *service_name,const builtin_s *bp,int instances);
+void sc_dump(struct service_config *scp,int fd,int tab_level,bool_int is_defaults);
+bool_int sc_different_confs(struct service_config *scp1,struct service_config *scp2);
+
+
+#endif   /* SCONF_H */
diff --git a/xinetd/sconst.h b/xinetd/sconst.h
new file mode 100644 (file)
index 0000000..8dd2047
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef SCONST_H
+#define SCONST_H
+
+/*
+ * $Id: sconst.h,v 1.1.1.1 2003/02/19 17:29:28 bbraun Exp $
+ */
+
+/*
+ * Names of internal non-visible services
+ */
+#define INTERCEPT_SERVICE_NAME         "intercept"
+#define LOG_SERVICE_NAME               "logging"
+
+
+/*
+ * Log entry ids
+ */
+#define START_ENTRY                    "START"
+#define FAIL_ENTRY                     "FAIL"
+#define EXIT_ENTRY                     "EXIT"
+#define USERID_ENTRY                   "USERID"
+#define NOID_ENTRY                     "NOID"
+
+#endif    /* SCONST_H */
+
diff --git a/xinetd/sensor.c b/xinetd/sensor.c
new file mode 100644 (file)
index 0000000..09d0877
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * (c) Copyright 2001-2002 by Steve Grubb
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <time.h>
+
+#include "config.h"
+#include "pset.h"
+#include "str.h"
+#include "addr.h"
+#include "msg.h"
+#include "sconf.h"
+#include "sensor.h"
+#include "xconfig.h"
+#include "xtimer.h"
+
+/*
+ * This is the globals for the Sensor. The Sensor will add the incoming IP
+ * address to the global_no_access table for whatever the configured time is.
+ */
+static pset_h global_no_access = NULL;        /* global no_access list   */
+static pset_h global_no_access_time = NULL;   /* time of the infraction   */
+static int timer_id = 0;                     /* Timer ID */
+
+/* This function is called via a timer callback every 60 seconds */
+static void scrub_global_access_list( void );
+
+
+void init_sensor( void )
+{
+   if ( global_no_access == NULL )
+      global_no_access = pset_create(10, 10);
+   if ( global_no_access_time == NULL )
+      global_no_access_time = pset_create(10, 10);
+}
+
+/*
+ * This function runs in the parent context and updates the global_no_access
+ * list. 
+ */
+void process_sensor( const struct service *sp, const union xsockaddr *addr)
+{
+   const char *func = "process_sensor";
+
+   if (SC_DENY_TIME(SVC_CONF(sp)) != 0)   /* 0 simply logs it   */
+   {
+      if ( pset_count( global_no_access ) < MAX_GLOBAL_NO_ACCESS)
+      {
+         int item_matched = addrlist_match( global_no_access, SA(addr) );
+
+        if ( item_matched == 0)
+        {   /* no match...adding to the list   */
+            char *dup_addr = new_string(xaddrname( addr ) );
+
+           if (dup_addr == NULL )
+               return ;
+
+           if (addrlist_add(global_no_access, dup_addr) == FAILED)
+               msg(LOG_ERR, func,
+                  "Failed adding %s to the global_no_access list", dup_addr);
+            else
+            {
+               time_t nowtime;
+               char time_buf[40], *tmp;
+
+              nowtime = time(NULL);
+              msg(LOG_CRIT, func,
+                  "Adding %s to the global_no_access list for %d minutes",
+                   dup_addr, SC_DENY_TIME(SVC_CONF(sp)));
+
+              if (SC_DENY_TIME(SVC_CONF(sp)) == -1)
+                    strcpy(time_buf, "-1");
+               else
+                    strx_nprint(time_buf, 38, "%ld",
+                       (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp))));
+
+              tmp = new_string(time_buf);
+               if (tmp != NULL)
+               {
+                  if (pset_add(global_no_access_time, tmp) == NULL)
+                  {
+                     msg(LOG_ERR, func,
+                         "Failed adding %s to the global_no_access_time list. "
+                         "global_no_access list is broken, xinetd needs "
+                        "restarting.", dup_addr);
+                 /* ideally, we should rollback the previous addr addition.   */
+                  }
+               }
+              if (pset_count(global_no_access) && (timer_id == 0) )
+                  timer_id = xtimer_add( scrub_global_access_list, 60 );
+            }
+            free(dup_addr);
+         }
+         else
+        {
+           /* Here again, eh?...update time stamp. */
+            char *exp_time;
+           time_t stored_time;
+
+           item_matched--; /* Is # plus 1, to even get here must be >= 1 */
+            exp_time = pset_pointer( global_no_access_time, item_matched ) ;
+            if (exp_time == NULL)
+               return ;
+
+            if ( parse_base10(exp_time, (int *)&stored_time) )
+            {  /* if never let them off, bypass */
+               if (stored_time != -1)
+               {
+                  time_t nowtime, new_time;
+
+                  nowtime = time(NULL);
+                  new_time = (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp)));                     if (difftime(new_time, (time_t)stored_time) > 0.0)
+                 {   /* new_time is longer save it   */
+                    char time_buf[40], *new_exp_time;
+
+                    strx_nprint(time_buf, 38, "%ld", (long)new_time);
+                    new_exp_time = new_string(time_buf);
+                    if ( new_exp_time )
+                    {
+                       free(exp_time);
+                       global_no_access_time->ptrs[ 
+                        (unsigned)item_matched ] = new_exp_time;
+                     }
+                  }
+               }
+            }
+         }
+      }
+      else
+         msg(LOG_ERR, func, "Maximum global_no_access count reached.");
+   }
+}
+
+/* They hit a real server...note, this is likely to be a child process. */
+status_e check_sensor( const union xsockaddr *addr)
+{
+
+   if ( (global_no_access) && pset_count( global_no_access ) )
+   {
+      if (addrlist_match( global_no_access, SA(addr)))
+         return FAILED;
+   }
+   return OK;
+}
+   
+
+static void scrub_global_access_list( void )
+{
+   unsigned count;
+   const char *func = "scrub_global_no_access_list";
+
+   if ( global_no_access == NULL )
+      count = 0;
+   else
+      count = pset_count( global_no_access );
+
+   if ( count )
+   {
+      int found_one = 0;
+      unsigned u;
+      time_t nowtime = time(NULL);
+
+      for (u=0; u < count; u++)
+      {
+         char *exp_time;
+         time_t stored_time;
+        
+        exp_time = pset_pointer( global_no_access_time, u ) ;
+         stored_time = atol(exp_time);
+
+        if (stored_time == -1)   /* never let them off   */
+           continue;
+
+        if (difftime(nowtime, (time_t)stored_time) >= 0.0)
+        {
+           __pset_pointer ptr;
+
+            pset_pointer(global_no_access, u) = NULL;
+            ptr = global_no_access_time->ptrs[ u ];
+            free(ptr);
+            pset_pointer(global_no_access_time, u ) = NULL;
+            found_one = 1;
+         }
+      }
+      if (found_one)
+      {
+         pset_compact( global_no_access );
+         pset_compact( global_no_access_time );
+        msg(LOG_INFO, func, 
+           "At least 1 DENY_TIME has expired, global_no_access list updated");
+      }
+
+      /* If there's still more on the list, start another callback. */
+      count = pset_count( global_no_access );
+      if ( count )
+         timer_id = xtimer_add( scrub_global_access_list, 60 );
+      else
+      {
+         timer_id = 0;
+        msg(LOG_INFO, func, 
+                 "global_no_access list is empty.");
+      }
+   }
+}
+
+void destroy_global_access_list( void )
+{
+   if ( global_no_access ) {
+      pset_apply( global_no_access, free, NULL ) ;
+      pset_destroy( global_no_access ) ;
+   }
+
+   if ( global_no_access_time ) {
+      pset_apply( global_no_access_time, free, NULL ) ;
+      pset_destroy( global_no_access_time ) ;
+   }
+}
diff --git a/xinetd/sensor.h b/xinetd/sensor.h
new file mode 100644 (file)
index 0000000..b3c5591
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (c) Copyright 2001-2002 by Steve Grubb
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+
+#ifndef SENSOR_H
+#define SENSOR_H
+
+#include "defs.h"
+#include "service.h"
+
+void init_sensor( void );
+void process_sensor( const struct service *, const union xsockaddr *);
+status_e check_sensor( const union xsockaddr * );
+void destroy_global_access_list( void );
+
+#endif
diff --git a/xinetd/server.c b/xinetd/server.c
new file mode 100644 (file)
index 0000000..4999d01
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#include "pset.h"
+#include "sio.h"
+#include "server.h"
+#include "util.h"
+#include "msg.h"
+#include "service.h"
+#include "sconf.h"
+#include "state.h"
+#include "main.h"
+#include "xconfig.h"
+#include "retry.h"
+#include "child.h"
+#include "signals.h"
+
+
+#define NEW_SERVER()                NEW( struct server )
+#define FREE_SERVER( serp )         FREE( serp )
+
+
+#ifndef DEBUG_RETRY
+#define do_fork()         fork()
+#else
+#include <errno.h>
+extern int errno ;
+
+/*
+ * 3 out of 4 times the do_fork() will fail
+ */
+#define do_fork()         ( random() & 0x11 ) ? ( errno = EAGAIN, -1 ) : fork()
+#endif    /* DEBUG_RETRY */
+
+
+/*
+ * Allocate a server, initialize it from init_serp, and insert it in the server
+ * table.
+ */
+struct server *server_alloc( const struct server *init_serp )
+{
+   struct server   *serp ;
+   const char      *func = "server_alloc" ;
+
+   serp = NEW_SERVER() ;
+   if ( serp == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+
+   if ( pset_add( SERVERS(ps), serp ) == NULL )
+   {
+      msg( LOG_CRIT, func, "couldn't insert server in server table" ) ;
+      CLEAR( *serp ) ;
+      FREE_SERVER( serp ) ;
+      return( NULL ) ;
+   }
+
+   *serp = *init_serp ;         /* initialize it */
+   SVC_HOLD( SERVER_SERVICE(serp) ) ;
+
+   return( serp ) ;
+}
+
+
+void server_release( struct server *serp )
+{
+   struct service   *sp   = SERVER_SERVICE( serp ) ;
+   int              count = SVC_RELE( sp ) ;
+
+   pset_remove(SERVERS(ps), serp);
+   if ( count == 0 ) {
+      if( ! SC_IS_SPECIAL( SVC_CONF( sp ) )  )
+         pset_remove( SERVICES( ps ), sp ) ;
+      svc_release( sp );
+   }
+   
+   CLEAR( *serp ) ;
+   FREE_SERVER( serp ) ;
+}
+
+
+/*
+ * If a service is internal and does not require forking a process:
+ *      -    if it accepts connections, we put the accepted connection
+ *       in non-blocking mode to avoid a possible block on 
+ *       the write(2).
+ *      -   the log flags that have to do with the server exiting are 
+ *         ignored (i.e. nothing is logged).
+ *      -   it can be identified in the log because the server pid is 0.
+ */
+static void server_internal( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE(serp) ;
+   const char *func = "server_internal" ;
+
+   SERVER_PID(serp) = 0 ;
+   if ( SVC_ACCEPTS_CONNECTIONS( sp ) &&
+            fcntl( SERVER_FD( serp ), F_SETFL, FNDELAY ) == -1 )
+   {
+      msg( LOG_ERR, func, "%s: fcntl F_SETFL failed: %m", SVC_ID( sp ) ) ;
+      return ;
+   }
+   svc_log_success( sp, SERVER_CONNECTION(serp), SERVER_PID(serp) ) ;
+   SVC_INTERNAL( sp, serp ) ;
+}
+
+/*
+ * Attempt to start a server for service 'sp' to handle
+ * connection 'cp'.
+ * Return value:
+ *   OK:   if a server is started or a retry attempt is scheduled
+ *   FAILED:   otherwise (a log entry is also made)
+ */
+status_e server_run( struct service *sp, connection_s *cp )
+{
+   struct server    server ;
+   struct server   *serp = NULL;
+   const char      *func = "server_run" ;
+
+   CLEAR( server ) ;
+   server.svr_sp = sp ;
+   server.svr_conn = cp ;
+
+   if ( ! SVC_FORKS( sp ) )
+   {  /*
+       * SG - Added this check so that internal services get the
+       * same protection that external services get. This is
+       * mandatory for the sensor patch to work.
+       */
+
+      if (svc_child_access_control( sp, cp ) == OK)
+         server_internal( &server ) ;
+      else {
+         if ( SVC_WAITS( sp ) )
+            svc_resume( sp );
+         return( FAILED );
+      }
+      if ( SVC_WAITS( sp ) )
+         svc_resume( sp );
+      return( OK ) ;
+   }
+
+   /*
+    * Insert new struct server in server table first, to avoid the
+    * possibility of running out of memory *after* the fork.
+    */
+   serp = server_alloc( &server ) ;
+   if ( serp == NULL )
+      return( FAILED ) ;
+
+   if ( server_start( serp ) == OK )
+   {
+      if( !SVC_WAITS(sp) )
+         CONN_CLOSE( cp ) ;
+      return( OK ) ;
+   }
+
+   /* server will be removed in server_release() */
+
+   /*
+    * Currently, fork failures are the only reason for retrying.
+    * There is no retry if we exceed the max allowed number of fork failures
+    */
+   if ( ! SERVER_FORKLIMIT( serp ) && SVC_RETRY( sp ) )
+   {
+      if ( schedule_retry( serp ) == OK )
+         return( OK ) ;
+      else
+         msg( LOG_ERR, func, "Retry failure for %s service", SVC_ID( sp ) ) ;
+   }
+   else
+      svc_log_failure( sp, cp, AC_FORK ) ;
+
+   server_release( serp ) ;
+   return( FAILED ) ;
+}
+
+
+/*
+ *  Try to fork a server process.
+ *  Actually, we won't fork if tcpmux_child is set, becuase we have
+ *  already forked to keep the xinetd parent from blocking on the
+ *  read of the service name.
+ */
+status_e server_start( struct server *serp )
+{
+   struct service   *sp = SERVER_SERVICE(serp) ;
+   const char       *func = "server_start" ;
+
+   if( debug.on )
+      msg( LOG_DEBUG, func, "Starting service %s", SC_NAME( SVC_CONF( sp ) ) );
+   SERVER_LOGUSER(serp) = SVC_LOGS_USERID_ON_SUCCESS( sp ) ;
+   
+   SERVER_PID(serp) = do_fork() ;
+
+   switch ( SERVER_PID(serp) )
+   {
+      case 0:
+         ps.rws.env_is_valid = FALSE ;
+         child_process( serp ) ;
+
+         msg( LOG_ERR, func, "INTERNAL ERROR: child_process returned" ) ;
+         _exit( 0 ) ;
+         /* NOTREACHED */
+      
+      case -1:
+         msg( LOG_ERR, func, "%s: fork failed: %m", SVC_ID( sp ) ) ;
+         SERVER_FORK_FAILURES(serp)++ ;
+         return( FAILED ) ;
+
+      default:
+         (void) time( &SERVER_STARTTIME(serp) ) ;
+         SVC_INC_RUNNING_SERVERS( sp ) ;
+
+         /*
+          * Log the start of another server (if it is not an interceptor).
+          * Determine if the server writes to the log (because in that case
+          * we will have to check the log size).
+          */
+         if ( ! SVC_IS_INTERCEPTED( sp ) )
+            svc_log_success( sp, SERVER_CONNECTION(serp), SERVER_PID(serp) ) ;
+         else
+            SERVER_WRITES_TO_LOG(serp) = SVC_IS_LOGGING( sp ) ;
+         SERVER_WRITES_TO_LOG(serp) |= SERVER_LOGUSER(serp) ;
+         return( OK ) ;
+   }
+}
+
+
+void server_dump( const struct server *serp, int fd )
+{
+   const struct service *sp = SERVER_SERVICE(serp) ;
+
+   Sprint( fd, "%s server\n", SVC_ID( sp ) ) ;
+   Sprint( fd, "pid = %d\n", SERVER_PID(serp) ) ;
+   Sprint( fd, "start_time = %s", ctime( &SERVER_STARTTIME(serp) ) ) ;
+   Sprint( fd, "Connection info:\n" ) ;
+   conn_dump( SERVER_CONNECTION(serp), fd ) ;
+   if ( SERVER_FORK_FAILURES(serp) )
+      Sprint( fd, "fork_failures = %d\n", SERVER_FORK_FAILURES(serp) ) ;
+   Sprint( fd,
+         "log_remote_user = %s\n", SERVER_LOGUSER(serp) ? "YES" : "NO" ) ;
+   Sprint( fd,
+         "writes_to_log = %s\n", SERVER_WRITES_TO_LOG(serp) ? "YES" : "NO" ) ;
+   Sputchar( fd, '\n' ) ;
+   Sflush( fd ) ;
+}
+
+
+/*
+ * Invoked when a server dies, either because of a signal or in case of
+ * a normal exit.
+ */
+void server_end( struct server *serp )
+{
+   struct service *sp = SERVER_SERVICE(serp) ;
+   const char *func = "server_end" ;
+
+   if ( PROC_EXITED( SERVER_EXITSTATUS(serp) ) || 
+         PROC_SIGNALED( SERVER_EXITSTATUS(serp) ) )
+   {
+      const char *death_type = PROC_EXITED( SERVER_EXITSTATUS(serp) ) ? "exited"
+           : "died" ;
+      if ( debug.on )
+      {
+         struct service *conn_sp = CONN_SERVICE( SERVER_CONNECTION(serp) ) ;
+
+         if ( conn_sp == sp )
+            msg( LOG_DEBUG, func,
+               "%s server %d %s", SVC_ID( sp ) , SERVER_PID(serp), death_type ) ;
+         else
+            msg( LOG_DEBUG, func,
+               "%s server %d running on behalf of service %s %s",
+                  SVC_ID( sp ), SERVER_PID(serp), SVC_ID( conn_sp ), death_type ) ;
+      }
+      
+      /* Added this for when accepting wait=yes services */
+      if( SVC_WAITS( sp ) )
+         FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ;
+
+      svc_postmortem( sp, serp ) ;
+      server_release( serp ) ;
+   }
+   else if ( PROC_STOPPED( SERVER_EXITSTATUS(serp) ) )
+      msg( LOG_WARNING, func, "service %s: server with pid %d stopped",
+         SVC_ID( sp ), SERVER_PID(serp) ) ;
+}
+
+
+/*
+ * Find the running server with the specified pid
+ */
+struct server *server_lookup( pid_t pid )
+{
+   unsigned u ;
+
+   for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
+   {
+      register struct server *serp ;
+
+      serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
+      if ( SERVER_PID(serp) == pid )
+         return( serp ) ;
+   }
+   return( NULL ) ;
+}
+
diff --git a/xinetd/server.h b/xinetd/server.h
new file mode 100644 (file)
index 0000000..b4f1947
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef SERVER_H
+#define SERVER_H
+
+/*
+ * $Id: server.h,v 1.2 2003/08/06 06:12:10 bbraun Exp $
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <time.h>
+
+#include "defs.h"
+#include "pset.h"
+
+#ifdef NO_POSIX_TYPES
+typedef int pid_t ;
+#endif
+
+
+/*
+ * This struct describes running servers
+ */
+struct server
+{
+   pid_t           svr_pid ;
+   time_t          svr_start_time ;
+   connection_s   *svr_conn ;
+   struct service *svr_sp ;              /* service that owns this server    */
+   int             svr_fork_failures ;   /* number of fork(2) failures       */
+   int             svr_exit_status ;
+   bool_int        svr_log_remote_user ;
+   bool_int        svr_writes_to_log ;   /* needed because a service may be   */
+                                         /* reconfigured between server       */
+                                         /*   forking and exit                */
+} ;
+
+#define SERP( p )                       ((struct server *)(p))
+
+#define SERVER_SERVICE( serp )         (serp)->svr_sp
+#define SERVER_CONNECTION( serp)       (connection_s *)(serp)->svr_conn
+#define SERVER_CONNSERVICE( serp )     CONN_SERVICE( SERVER_CONNECTION( serp ) )
+#define SERVER_FD( serp )              CONN_DESCRIPTOR( (serp)->svr_conn )
+#define SERVER_PID( serp )             (serp)->svr_pid
+#define SERVER_EXITSTATUS( serp )      (serp)->svr_exit_status
+#define SERVER_STARTTIME( serp )       (serp)->svr_start_time
+#define SERVER_LOGUSER( serp )         (serp)->svr_log_remote_user
+#define SERVER_FORK_FAILURES( serp )   (serp)->svr_fork_failures
+#define SERVER_WRITES_TO_LOG( serp )   (serp)->svr_writes_to_log
+
+#define SERVER_FORKLIMIT( serp )         \
+                  ( (serp)->svr_fork_failures >= MAX_FORK_FAILURES )
+
+#define SERVER_SET_PID( serp, pid )      (serp)->svr_pid = (pid)
+#define SERVER_SET_EXIT_STATUS( serp, status )   \
+                  (serp)->svr_exit_status = (status)
+
+
+/*
+ * Macros for compatibility
+ */
+#ifndef OLD_WAIT
+#define PROC_EXITED( s )         WIFEXITED( s )
+#define PROC_SIGNALED( s )       WIFSIGNALED( s )
+#define PROC_STOPPED( s )        WIFSTOPPED( s )
+#define PROC_EXITSTATUS( s )     WEXITSTATUS( s )
+#define PROC_TERMSIG( s )        WTERMSIG( s )
+#else
+#define PROC_EXITED( s )         WIFEXITED( *(union wait *)&(s) )
+#define PROC_SIGNALED( s )       WIFSIGNALED( *(union wait *)&(s) )
+#define PROC_STOPPED( s )        WIFSTOPPED( *(union wait *)&(s) )
+#define PROC_EXITSTATUS( s )     (((union wait *)&(s))->w_T.w_Retcode)
+#define PROC_TERMSIG( s )        (((union wait *)&(s))->w_T.w_Termsig)
+#endif   /* OLD_WAIT */
+
+void server_release(struct server *serp);
+status_e server_run(struct service *sp,connection_s *cp);
+status_e server_start(struct server *serp);
+void server_dump(const struct server *serp,int fd);
+void server_end(struct server *serp);
+struct server *server_lookup(pid_t pid);
+struct server *server_alloc( const struct server *init_serp );
+
+#endif   /* SERVER_H */
+
diff --git a/xinetd/service.c b/xinetd/service.c
new file mode 100644 (file)
index 0000000..3d68d78
--- /dev/null
@@ -0,0 +1,904 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <netinet/tcp.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#ifdef HAVE_MDNS
+#include "xmdns.h"
+#endif
+#ifndef NO_RPC
+ #ifdef HAVE_RPC_PMAP_CLNT_H
+  #ifdef __sun
+   #include <rpc/types.h>
+   #include <rpc/auth.h>
+  #endif
+  #include <rpc/types.h>
+  #include <rpc/xdr.h>
+  #include <rpc/auth.h>
+  #include <rpc/clnt.h>
+  #include <rpc/pmap_clnt.h>
+ #endif
+ #include <rpc/rpc.h>
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#include "sio.h"
+#include "service.h"
+#include "util.h"
+#include "main.h"
+#include "sconf.h"
+#include "msg.h"
+#include "logctl.h"
+#include "xconfig.h"
+#include "special.h"
+
+
+#define NEW_SVC()              NEW( struct service )
+#define FREE_SVC( sp )         FREE( sp )
+
+#define DISABLE( sp )          SVC_STATE((sp)) = SVC_DISABLED
+
+static void deactivate( const struct service *sp );
+static int banner_always( const struct service *sp, const connection_s *cp );
+
+static const struct name_value service_states[] =
+   {
+      { "Not started",        (int) SVC_NOT_STARTED    },
+      { "Active",             (int) SVC_ACTIVE         },
+      { "Disabled",           (int) SVC_DISABLED       },
+      { "Suspended",          (int) SVC_SUSPENDED      },
+      { NULL,                 1                        },
+      { "BAD STATE",          0                        }
+   } ;
+
+
+
+/*
+ * Allocate a new struct service and initialize it from scp 
+ */
+struct service *svc_new( struct service_config *scp )
+{
+   struct service *sp ;
+   const char *func = "svc_new" ;
+
+   sp = NEW_SVC() ;
+   if ( sp == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+   CLEAR( *sp ) ;
+
+   SVC_CONF(sp) = scp ;
+   return( sp ) ;
+}
+
+
+struct service *svc_make_special( struct service_config *scp )
+{
+   struct service      *sp ;
+   const char          *func = "svc_make_special" ;
+
+   if ( ( sp = svc_new( scp ) ) == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+
+   SVC_NOT_GENERIC(sp) = 1 ;
+   SVC_LOG(sp) = ps.rws.program_log ;
+   SVC_REFCOUNT(sp) = 1 ;
+   SVC_STATE(sp) = SVC_ACTIVE ;
+   return( sp ) ;
+}
+
+
+void svc_free( struct service *sp )
+{
+   sc_free( SVC_CONF(sp) ) ;
+   CLEAR( *sp ) ;
+   FREE_SVC( sp ) ;
+}
+
+
+static status_e set_fd_modes( struct service *sp )
+{
+   int sd = SVC_FD( sp ) ;
+   const char *func = "set_fd_modes" ;
+
+   /*
+    * There is a possibility of blocking on a send/write if
+    *
+    * the service does not require forking (==> is internal) AND
+    * it does not accept connections
+    *
+    * To avoid this, we put the descriptor in FNDELAY mode.
+    * (if the service accepts connections, we still need to put the
+    * 'accepted' connection in FNDELAY mode but this is done elsewhere)
+    */
+   if ( ! SVC_FORKS( sp ) && ! SVC_ACCEPTS_CONNECTIONS( sp ) &&
+                              fcntl( sd, F_SETFL, FNDELAY ) == -1 )
+   {
+      msg( LOG_ERR, func,
+         "fcntl failed (%m) for FNDELAY. service = %s", SVC_ID( sp ) ) ;
+      return( FAILED ) ;
+   }
+
+   /*
+    * Always set the close-on-exec flag
+    */
+   if ( fcntl( sd, F_SETFD, FD_CLOEXEC ) == -1 )
+   {
+      msg( LOG_ERR, func,
+         "fcntl failed (%m) for close-on-exec. service = %s", SVC_ID( sp ) ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+#ifndef NO_RPC
+
+static status_e activate_rpc( struct service *sp )
+{
+   union xsockaddr        tsin;
+   socklen_t              sin_len = sizeof(tsin);
+   unsigned long          vers ;
+   struct service_config *scp = SVC_CONF( sp ) ;
+   struct rpc_data       *rdp = SC_RPCDATA( scp ) ;
+   char                  *sid = SC_ID( scp ) ;
+   unsigned               registered_versions = 0 ;
+   int                    sd = SVC_FD( sp ) ;
+   const char            *func = "activate_rpc" ;
+
+   if( SC_BIND_ADDR(scp) != 0 )
+      memcpy( &tsin, SC_BIND_ADDR(scp), sizeof(tsin) );
+   else
+      memset( &tsin, 0, sizeof(tsin));
+
+   if( SC_IPV4( scp ) ) {
+      tsin.sa_in.sin_family = AF_INET ;
+      sin_len = sizeof(struct sockaddr_in);
+   } else if( SC_IPV6( scp ) ) {
+      tsin.sa_in6.sin6_family = AF_INET6 ;
+      sin_len = sizeof(struct sockaddr_in6);
+   }
+
+   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
+   {
+      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
+      return( FAILED ) ;
+   }
+
+   /*
+    * Find the port number that was assigned to the socket
+    */
+   if ( getsockname( sd, &tsin.sa, &sin_len ) == -1 )
+   {
+      msg( LOG_ERR, func,
+            "getsockname failed (%m). service = %s", sid ) ;
+      return( FAILED ) ;
+   }
+   
+   if( tsin.sa.sa_family == AF_INET ) 
+      SC_SET_PORT( scp, ntohs( tsin.sa_in.sin_port ) ) ;
+   else if( tsin.sa.sa_family == AF_INET6 )
+      SC_SET_PORT( scp, ntohs( tsin.sa_in6.sin6_port ) ) ;
+
+   /*
+    * Try to register as many versions as possible
+    */
+   for ( vers = RD_MINVERS( rdp ) ; vers <= RD_MAXVERS( rdp ) ; vers++ ) {
+/*      Is this right?  For instance, if we have both tcp and udp services,
+ *      this will unregister the previously registered protocol.
+ *      pmap_unset(RD_PROGNUM(rdp), vers);
+ */
+      if ( pmap_set( RD_PROGNUM( rdp ), vers, SC_PROTOVAL( scp ), 
+                             SC_PORT( scp ) ) )
+         registered_versions++ ;
+      else
+         msg( LOG_ERR, func,
+            "pmap_set failed. service=%s program=%ld version=%ld",
+               sid, RD_PROGNUM( rdp ), vers ) ;
+      sleep(1);
+   }
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func,
+            "Registered %d versions of %s", registered_versions, sid ) ;
+
+   return( ( registered_versions == 0 ) ? FAILED : OK ) ;
+}
+
+#endif   /* ! NO_RPC */
+
+static status_e activate_normal( struct service *sp )
+{
+   union xsockaddr         tsin;
+   int                     sd             = SVC_FD( sp ) ;
+   struct service_config  *scp            = SVC_CONF( sp ) ;
+   uint16_t                service_port   = SC_PORT( scp ) ;
+   char                   *sid            = SC_ID( scp ) ;
+   const char             *func           = "activate_normal" ;
+   unsigned int            sin_len        = sizeof(tsin);
+   int                     on             = 1;
+#ifdef IPV6_V6ONLY
+   int                     v6on           = 0;
+#endif
+
+   if( SC_BIND_ADDR(scp) != NULL )
+      memcpy(&tsin, SC_BIND_ADDR(scp), sin_len);
+   else
+      memset(&tsin, 0, sin_len);
+   
+   if( SC_IPV4( scp ) ) {
+      tsin.sa_in.sin_family = AF_INET ;
+      tsin.sa_in.sin_port = htons( service_port ) ;
+      sin_len = sizeof(struct sockaddr_in);
+   } else if( SC_IPV6( scp ) ) {
+      tsin.sa_in6.sin6_family = AF_INET6;
+      tsin.sa_in6.sin6_port = htons( service_port );
+      sin_len = sizeof(struct sockaddr_in6);
+   }
+
+#ifdef IPV6_V6ONLY
+   if( SC_IPV6(scp) ) {
+      if( SC_SPECIFIED(scp, A_V6ONLY) ) {
+         v6on = 1;
+      } else {
+         v6on = 0;
+      }
+      if( setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) {
+         msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" );
+      }
+   }
+#endif
+
+   if ( setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, 
+                    (char *) &on, sizeof( on ) ) == -1 )
+      msg( LOG_WARNING, func, 
+           "setsockopt SO_REUSEADDR failed (%m). service = %s", sid ) ;
+
+   if( SC_NODELAY( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) )
+   {
+      if ( setsockopt( sd, IPPROTO_TCP, TCP_NODELAY, 
+                       (char *) &on, sizeof( on ) ) == -1 )
+         msg( LOG_WARNING, func, 
+              "setsockopt TCP_NODELAY failed (%m). service = %s", sid ) ;
+   }
+
+   if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) ) 
+   {
+      if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, 
+                     (char *)&on, sizeof( on ) ) < 0 )
+         msg( LOG_WARNING, func, 
+              "setsockopt SO_KEEPALIVE failed (%m). service = %s", sid ) ;
+   }
+
+   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
+   {
+      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
+      return( FAILED ) ;
+   }
+
+   return( OK ) ;
+}
+
+
+/*
+ * Activate a service. 
+ */
+status_e svc_activate( struct service *sp )
+{
+   struct service_config    *scp = SVC_CONF( sp ) ;
+   status_e                  status ;
+   const char                     *func = "svc_activate" ;
+
+   /*  No activation for MUXCLIENTS.
+    */
+
+   if (SC_IS_MUXCLIENT( scp ))
+   {
+      return( OK );
+   }
+
+   if( SC_IPV4( scp ) ) {
+      SVC_FD(sp) = socket( AF_INET, 
+                           SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
+   } else if( SC_IPV6( scp ) ) {
+      SVC_FD(sp) = socket( AF_INET6, 
+                           SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
+   }
+
+   if ( SVC_FD(sp) == -1 )
+   {
+      msg( LOG_ERR, func,
+                  "socket creation failed (%m). service = %s", SC_ID( scp ) ) ;
+      return( FAILED ) ;
+   }
+
+   if ( set_fd_modes( sp ) == FAILED )
+   {
+      (void) Sclose( SVC_FD(sp) ) ;
+      return( FAILED ) ;
+   }
+
+#ifndef NO_RPC
+   if ( SC_IS_RPC( scp ) )
+      status = activate_rpc( sp ) ;
+   else
+#endif   /* ! NO_RPC */
+      status = activate_normal( sp ) ;
+   
+   if ( status == FAILED )
+   {
+      (void) Sclose( SVC_FD(sp) ) ;
+      return( FAILED ) ;
+   }
+
+#ifdef HAVE_MDNS
+   xinetd_mdns_register(scp);
+#endif
+
+   if ( log_start( sp, &SVC_LOG(sp) ) == FAILED )
+   {
+      deactivate( sp ) ;
+      return( FAILED ) ;
+   }
+
+   /*
+    * Initialize the service data
+    */
+   SVC_RUNNING_SERVERS(sp)   = SVC_RETRIES(sp) = 0 ;
+
+   if ( SC_MUST_LISTEN( scp ) )
+      (void) listen( SVC_FD(sp), LISTEN_BACKLOG ) ;
+
+   ps.rws.descriptors_free-- ;
+
+   SVC_STATE(sp) = SVC_ACTIVE ;
+
+   FD_SET( SVC_FD(sp), &ps.rws.socket_mask ) ;
+   if ( SVC_FD(sp) > ps.rws.mask_max )
+      ps.rws.mask_max = SVC_FD(sp) ;
+
+   ps.rws.active_services++ ;
+   ps.rws.available_services++ ;
+
+   return( OK ) ;
+}
+
+
+static void deactivate( const struct service *sp )
+{
+   (void) Sclose( SVC_FD( sp ) ) ;
+
+#ifdef HAVE_MDNS
+   xinetd_mdns_deregister(SVC_CONF(sp));
+#endif
+
+   if (debug.on)
+      msg(LOG_DEBUG, "deactivate", "%d Service %s deactivated", 
+          getpid(), SC_NAME( SVC_CONF(sp) ) );
+
+#ifndef NO_RPC
+   if ( SC_IS_RPC( SVC_CONF( sp ) ) )
+   {
+      unsigned long vers ;
+      const struct rpc_data *rdp = SC_RPCDATA( SVC_CONF( sp ) ) ;
+
+      for ( vers = RD_MINVERS( rdp ) ; vers <= RD_MAXVERS( rdp ) ; vers++ ) {
+         (void) pmap_unset( RD_PROGNUM( rdp ), vers ) ;
+      }
+   }
+#endif   /* ! NO_RPC */
+}
+
+
+/*
+ * Close the service descriptor.
+ * If this is an RPC service, deregister it.
+ * Close the log.
+ */
+void svc_deactivate( struct service *sp )
+{
+   if ( ! SVC_IS_AVAILABLE( sp ) )
+      return ;
+
+   deactivate( sp ) ;
+   ps.rws.descriptors_free++ ;
+
+   if ( SVC_IS_ACTIVE( sp ) )
+   {
+      FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
+      ps.rws.active_services-- ;
+   }
+
+   ps.rws.available_services-- ;
+
+   DISABLE( sp ) ;
+}
+
+
+/*
+ * Suspend a service
+ */
+void svc_suspend( struct service *sp )
+{
+   const char *func = "svc_suspend" ;
+
+   if ( ! SVC_IS_ACTIVE( sp ) )
+   {
+      msg( LOG_ERR, func, "service %s is not active", SVC_ID( sp ) ) ;
+      return ;
+   }
+
+   FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
+   ps.rws.active_services-- ;
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Suspended service %s", SVC_ID( sp ) ) ;
+   
+   SUSPEND( sp ) ;
+}
+
+
+/*
+ * Resume a suspended service.
+ */
+void svc_resume( struct service *sp )
+{
+   const char *func = "svc_resume" ;
+
+   FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ;
+   ps.rws.active_services++ ;
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Resumed service %s", SVC_ID( sp ) ) ;
+   RESUME( sp ) ;
+}
+
+
+/*
+ * Steps:
+ *      1. Deactivate the service
+ *      2. Free all memory used by the service and free the service itself
+ *
+ * Since this function may free all memory associated with the service as
+ * well as the memory pointed by sp, only the value of sp should be used
+ * after this call if the return value is 0 (i.e. no dereferencing of sp).
+ *
+ * Special services are never deactivated.
+ */
+int svc_release( struct service *sp )
+{
+   char *sid = SVC_ID( sp ) ;
+   const char *func = "svc_release" ;
+
+   if ( SVC_REFCOUNT(sp) == 0 )
+   {
+      msg( LOG_ERR, func, "%s: svc_release with 0 count", sid ) ;
+      return( 0 ) ;
+   }
+   
+   SVC_REFCOUNT(sp)-- ;
+   if ( SVC_REFCOUNT(sp) == 0 )
+   {
+      if ( debug.on )
+         msg( LOG_DEBUG, func, "ref count of service %s dropped to 0", sid ) ;
+      if ( ! SC_IS_SPECIAL( SVC_CONF( sp ) ) )
+      {
+         if ( SVC_LOG(sp) )
+            log_end( SC_LOG( SVC_CONF( sp ) ), SVC_LOG(sp) ) ;
+         svc_deactivate( sp ) ;
+         svc_free( sp ) ;
+         sp = NULL;
+      }
+      else      /* this shouldn't happen */
+         msg( LOG_WARNING, func,
+            "ref count of special service %s dropped to 0", sid ) ;
+      return( 0 ) ;
+   }
+   else
+      return( SVC_REFCOUNT(sp) ) ;
+}
+
+
+void svc_dump( const struct service *sp, int fd )
+{
+   tabprint( fd, 0, "Service = %s\n", SC_NAME( SVC_CONF( sp ) ) ) ;
+   tabprint( fd, 1, "State = %s\n",
+                        nv_get_name( service_states, (int) SVC_STATE(sp) ) ) ;
+
+   sc_dump( SVC_CONF( sp ), fd, 1, FALSE ) ;
+
+   if ( SVC_IS_ACTIVE(sp) )
+   {
+      tabprint( fd, 1, "running servers = %d\n", SVC_RUNNING_SERVERS(sp) ) ;
+      tabprint( fd, 1, "retry servers = %d\n", SVC_RETRIES(sp) ) ;
+      tabprint( fd, 1, "attempts = %d\n", SVC_ATTEMPTS(sp) ) ;
+      tabprint( fd, 1, "service fd = %d\n", SVC_FD(sp) ) ;
+   }
+   Sputchar( fd, '\n' ) ;
+}
+
+
+void svc_request( struct service *sp )
+{
+   connection_s *cp ;
+   status_e ret_code;
+
+   cp = conn_new( sp ) ;
+   if ( cp == CONN_NULL )
+      return ;
+
+   /*
+    * Output the banner now that the connection is established. The
+    * other banners come later.
+    */
+   banner_always(sp, cp);
+
+   if (SVC_NOT_GENERIC(sp))
+      ret_code = spec_service_handler(sp, cp);
+   else 
+      ret_code = svc_generic_handler(sp, cp);
+
+   if( (SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM) && (SVC_IS_ACTIVE( sp )) ) 
+      drain( cp->co_descriptor ) ; /* Prevents looping next time */
+   
+   if ( ret_code != OK ) 
+   {
+      if ( SVC_LOGS_USERID_ON_FAILURE( sp ) ) {
+         if( spec_service_handler( LOG_SERVICE( ps ), cp ) == FAILED ) 
+           conn_free( cp, 1 ) ;
+         else if (!SC_WAITS( SVC_CONF( sp ) ) ) {
+        /* The logging service will gen SIGCHLD thus freeing connection */
+           CONN_CLOSE(cp) ; 
+        }
+        return;
+      }
+      if (!SC_WAITS( SVC_CONF( sp ) )) 
+        conn_free( cp, 1 );
+      else { 
+         if( (SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM) && (SVC_IS_ACTIVE( sp )) ) 
+            drain( cp->co_descriptor ) ; /* Prevents looping next time */
+        free( cp );
+      }
+   }
+   else if ((SVC_NOT_GENERIC(sp)) || (!SC_FORKS( SVC_CONF( sp ) ) ) )
+     free( cp );
+}
+
+
+status_e svc_generic_handler( struct service *sp, connection_s *cp )
+{
+   if ( svc_parent_access_control( sp, cp ) == OK ) {
+      return( server_run( sp, cp ) ) ;
+   }
+
+   return( FAILED ) ;
+}
+
+#define TMPSIZE 1024
+/* Print the banner that is supposed to always be printed */
+static int banner_always( const struct service *sp, const connection_s *cp )
+{
+   const char *func = "banner_always";
+   const struct service_config *scp = SVC_CONF( sp ) ;
+
+   /* print the banner regardless of access control */
+   if ( SC_BANNER(scp) != NULL ) {
+      char tmpbuf[TMPSIZE];
+      int retval;
+      int bannerfd = open(SC_BANNER(scp), O_RDONLY);
+
+      if( bannerfd < 0 ) {
+         msg( LOG_ERR, func, "service = %s, open of banner %s failed", 
+                        SVC_ID( sp ), SC_BANNER(scp));
+         return(-1);
+      }
+
+      while( (retval = read(bannerfd, tmpbuf, sizeof(tmpbuf))) ) {
+         if (retval == -1)
+         {
+            if (errno == EINTR)
+               continue;
+            else
+            {
+               msg(LOG_ERR, func, "service %s, Error %m reading banner %s", 
+                              SVC_ID( sp ), SC_BANNER(scp));
+               break;
+            }
+         }
+         Swrite(cp->co_descriptor, tmpbuf, retval);
+      }
+
+      Sclose(bannerfd);
+      Sflush ( cp->co_descriptor );
+   }
+
+   return(0);
+}
+
+static int banner_fail( const struct service *sp, const connection_s *cp )
+{
+   const char *func = "banner_fail";
+   const struct service_config *scp = SVC_CONF( sp ) ;
+
+
+   if ( SC_BANNER_FAIL(scp) != NULL )
+   {
+      char tmpbuf[TMPSIZE];
+      int retval;
+      int bannerfd = open(SC_BANNER_FAIL(scp), O_RDONLY);
+
+      if( bannerfd < 0 )
+      {
+         msg( LOG_ERR, func, "service = %s, open of banner %s failed", 
+            SVC_ID( sp ), SC_BANNER_FAIL(scp));
+         return(-1);
+      }
+
+      while( (retval = read(bannerfd, tmpbuf, sizeof(tmpbuf))) ) {
+         if (retval == -1)
+         {
+            if (errno == EINTR)
+               continue;
+            else
+            {
+               msg(LOG_ERR, func, "service %s, Error %m reading banner %s", 
+                              SVC_ID( sp ), SC_BANNER(scp));
+               break;
+            }
+         }
+         Swrite(cp->co_descriptor, tmpbuf, retval);
+      }
+
+      Sclose(bannerfd);
+      Sflush ( cp->co_descriptor );
+   }
+
+   return(0);
+}
+
+static int banner_success( const struct service *sp, const connection_s *cp )
+{
+   const char *func = "banner_success";
+   const struct service_config *scp = SVC_CONF( sp ) ;
+
+   /* print the access granted banner */
+   if ( SC_BANNER_SUCCESS(scp) != NULL ) {
+      char tmpbuf[TMPSIZE];
+      int retval;
+      int bannerfd = open(SC_BANNER_SUCCESS(scp), O_RDONLY);
+
+      if( bannerfd < 0 ) {
+         msg( LOG_ERR, func, "service = %s, open of banner %s failed", 
+                        SVC_ID( sp ), SC_BANNER_SUCCESS(scp));
+         return(-1);
+      }
+
+      while( (retval = read(bannerfd, tmpbuf, sizeof(tmpbuf))) ) {
+         if (retval == -1)
+         {
+            if (errno == EINTR)
+               continue;
+            else
+            {
+               msg(LOG_ERR, func, "service %s, Error %m reading banner %s", 
+                              SVC_ID( sp ), SC_BANNER(scp));
+               break;
+            }
+         }
+         Swrite(cp->co_descriptor, tmpbuf, retval);
+      }
+
+      Sclose(bannerfd);
+      Sflush ( cp->co_descriptor );
+   }
+   return(0);
+}
+
+static status_e failed_service(struct service *sp, 
+                                connection_s *cp, 
+                                access_e result)
+{
+   struct service_config *scp = SVC_CONF( sp ) ;
+
+   if ( result != AC_OK )
+   {
+      bool_int report_failure = TRUE ;
+
+      /*
+       * Try to avoid reporting multiple times a failed attempt to access
+       * a datagram-based service from a bad address. We do this because
+       * the clients of such services usually send multiple datagrams 
+       * before reporting a timeout (we have no way of telling them that
+       * their request has been denied).
+       */
+      if ( result == AC_ADDRESS && SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM )
+      {
+         if( SC_IPV4( scp ) ) {
+            struct sockaddr_in *sinp = SAIN(CONN_ADDRESS( cp )) ;
+            struct sockaddr_in *last = SAIN(SVC_LAST_DGRAM_ADDR(sp)) ;
+            time_t current_time ;
+
+            if (sinp == NULL )
+               return FAILED;
+
+            if ( last == NULL ) {
+               last = SAIN( calloc( 1, sizeof(union xsockaddr) ) );
+              SVC_LAST_DGRAM_ADDR(sp) = (union xsockaddr *)last;
+            }
+
+            (void) time( &current_time ) ;
+            if ( sinp->sin_addr.s_addr == last->sin_addr.s_addr &&
+                                          sinp->sin_port == last->sin_port )
+            {
+               if( current_time - SVC_LAST_DGRAM_TIME(sp) <= DGRAM_IGNORE_TIME )
+                  report_failure = FALSE ;
+               else
+                  SVC_LAST_DGRAM_TIME(sp) = current_time ;
+            }
+            else
+            {
+               memcpy(SVC_LAST_DGRAM_ADDR(sp), sinp,sizeof(struct sockaddr_in));
+               SVC_LAST_DGRAM_TIME(sp) = current_time ;
+            }
+         } else if( SC_IPV6( scp ) ) {
+            struct sockaddr_in6 *sinp = SAIN6(CONN_ADDRESS( cp )) ;
+            struct sockaddr_in6 *last = SAIN6(SVC_LAST_DGRAM_ADDR(sp)) ;
+            time_t current_time ;
+
+           if (sinp == NULL )
+               return FAILED;
+
+           if( last == NULL ) {
+               last = SAIN6(calloc( 1, sizeof(union xsockaddr) ) );
+              SVC_LAST_DGRAM_ADDR( sp ) = (union xsockaddr *)last;
+            }
+
+            (void) time( &current_time ) ;
+            if ( IN6_ARE_ADDR_EQUAL(&(sinp->sin6_addr), &(last->sin6_addr)) && 
+                 sinp->sin6_port == last->sin6_port )
+            {
+               if((current_time - SVC_LAST_DGRAM_TIME(sp)) <= DGRAM_IGNORE_TIME)
+                  report_failure = FALSE ;
+               else
+                  SVC_LAST_DGRAM_TIME(sp) = current_time ;
+            }
+            else
+            {
+               memcpy(SVC_LAST_DGRAM_ADDR(sp),sinp,sizeof(struct sockaddr_in6));
+               SVC_LAST_DGRAM_TIME(sp) = current_time ;
+            }
+         }
+      }
+
+      if ( report_failure )
+         svc_log_failure( sp, cp, result ) ;
+
+      banner_fail(sp, cp);
+
+      return( FAILED ) ;
+   }
+
+   return( OK );
+}
+
+/* Do the "light weight" access control here */
+status_e svc_parent_access_control( struct service *sp, connection_s *cp )
+{
+   access_e result;
+
+   result = parent_access_control( sp, cp );
+   if( failed_service(sp, cp, result) == FAILED )
+      return(FAILED);
+
+   return (OK);
+}
+
+status_e svc_child_access_control( struct service *sp, connection_s *cp )
+{
+   access_e result ;
+
+   result = access_control( sp, cp, MASK_NULL ) ;
+   if( failed_service(sp, cp, result) == FAILED )
+      return(FAILED);
+
+   banner_success(sp, cp);
+
+   return( OK ) ;
+}
+
+/*
+ * Invoked when a server of the specified service dies
+ */
+void svc_postmortem( struct service *sp, struct server *serp )
+{
+   struct service  *co_sp   = SERVER_CONNSERVICE( serp ) ;
+   connection_s    *cp      = SERVER_CONNECTION( serp ) ;
+   const char      *func    = "svc_postmortem" ;
+
+   SVC_DEC_RUNNING_SERVERS( sp ) ;
+
+   /*
+    * Log information about the server that died
+    */
+   if ( SVC_IS_LOGGING( sp ) )
+   {
+      if ( SERVER_WRITES_TO_LOG(serp) )
+      {
+         if ( debug.on )
+            msg( LOG_DEBUG, func,
+                        "Checking log size of %s service", SVC_ID( sp ) ) ;
+         xlog_control( SVC_LOG( sp ), XLOG_SIZECHECK ) ;
+      }
+      svc_log_exit( sp, serp ) ;
+   }
+
+   /*
+    * Now check if we have to check the log size of the service that owns
+    * the connection
+    */
+   if ( co_sp != sp && SVC_IS_LOGGING( co_sp ) )
+      xlog_control( SVC_LOG( co_sp ), XLOG_SIZECHECK ) ;
+
+   if (!SVC_WAITS(sp)) {
+      conn_free( cp, 1 ) ;
+      cp = NULL;
+   } else {
+      if (cp) {
+         if ( SVC_SOCKET_TYPE( sp ) == SOCK_DGRAM )
+            drain( cp->co_descriptor ) ;
+         free(cp);
+         cp = NULL;
+         if( SVC_RELE( sp ) == 0 )
+            svc_release( sp ); /* shouldn't be 0, but should remove from
+                                * pset if it is... */
+      }
+      svc_resume(sp);
+   }
+}
+
+/*
+ * This function closes all service descriptors. This should be called 
+ * for all child processes that fork, but do not exec. This includes
+ * redirect, builtins, and tcpmux. The close on exec flag takes care of
+ * child processes that call exec. Without calling this, the listening 
+ * fd's are not closed and reconfig will fail.
+ */
+void close_all_svc_descriptors(void)
+{
+   psi_h                     iter ;
+   struct service            *osp ;
+
+   /* Have to close all other descriptors here */
+   iter = psi_create( SERVICES( ps ) ) ;
+   if ( iter == NULL )
+        out_of_memory( "close_all_svc_descriptors" ) ;
+
+   for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
+        (void) Sclose( SVC_FD( osp ) ) ;
+  
+   psi_destroy( iter ) ;
+}
+
diff --git a/xinetd/service.h b/xinetd/service.h
new file mode 100644 (file)
index 0000000..2777667
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#include "config.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <time.h>
+
+#include "defs.h"
+#include "pset.h"
+#include "xlog.h"
+#include "server.h"
+
+/*
+ * $Id: service.h,v 1.5 2005/03/29 15:50:34 bbraun Exp $
+ */
+
+
+
+/*
+ * NOTE: A service can be disabled but not deleted if it has any servers
+ *       running
+ */
+typedef enum                     /* service states */
+   {
+      SVC_NOT_STARTED = 0,       /* no attempt to start it yet       */
+      SVC_ACTIVE,                /* service is available             */
+      SVC_SUSPENDED,             /* service is suspended             */
+      SVC_DISABLED               /* service disabled                 */
+   } state_e ;
+
+
+/*
+ * NOTE: Clearing the structure will give all its fields their default values
+ */
+struct service
+{
+   state_e                svc_state ;
+   int                    svc_ref_count ;   /* # of pters to this struct */
+   struct service_config *svc_conf ;    /* service configuration */
+   int                    svc_fd ;     /* The Listening FD for the service */
+   unsigned               svc_running_servers ;
+   unsigned               svc_retry_servers ;
+   unsigned               svc_attempts ; /* # of attempts to start server */
+   int                    svc_not_generic ; /* 1 spec_service, 0 generic */
+
+   /*
+    * These fields are used to avoid generating too many messages when
+    * receiving datagrams from a bad address.
+    */
+   union xsockaddr                        *svc_last_dgram_addr ;
+   time_t                                  svc_last_dgram_time ;
+   xlog_h                                  svc_log ;
+} ;
+
+
+#define SP( p )                  ( (struct service *) (p) )
+#define SUSPEND( sp )          (sp)->svc_state = SVC_SUSPENDED
+#define RESUME( sp )           (sp)->svc_state = SVC_ACTIVE
+
+
+/*
+ * Field access macros
+ */
+#define SVC_CONF( sp )             ( (sp)->svc_conf )
+#define SVC_FD( sp )               ( (sp)->svc_fd )
+#define SVC_RUNNING_SERVERS( sp )  (sp)->svc_running_servers
+#define SVC_RETRIES( sp )          (sp)->svc_retry_servers
+#define SVC_LOG( sp )              (sp)->svc_log
+#define SVC_REFCOUNT( sp )         (sp)->svc_ref_count
+#define SVC_ID( sp )               SC_ID( SVC_CONF( sp ) )
+#define SVC_SOCKET_TYPE( sp )      SC_SOCKET_TYPE( SVC_CONF( sp ) )
+#define SVC_STATE( sp )            (sp)->svc_state
+#define SVC_ATTEMPTS( sp )         (sp)->svc_attempts
+#define SVC_LAST_DGRAM_ADDR( sp )  (sp)->svc_last_dgram_addr
+#define SVC_LAST_DGRAM_TIME( sp )  (sp)->svc_last_dgram_time
+#define SVC_NOT_GENERIC( sp )      (sp)->svc_not_generic
+
+#define SVC_IS_ACTIVE( sp )      ( (sp)->svc_state == SVC_ACTIVE )
+#define SVC_IS_SUSPENDED( sp )   ( (sp)->svc_state == SVC_SUSPENDED )
+#define SVC_IS_AVAILABLE( sp )   ( SVC_IS_ACTIVE(sp) || SVC_IS_SUSPENDED(sp) )
+#define SVC_IS_DISABLED( sp )    ( (sp)->svc_state == SVC_DISABLED )
+#define SVC_IS_MUXCLIENT( sp )   ( SC_IS_MUXCLIENT( SVC_CONF ( sp ) ) )
+#define SVC_IS_MUXPLUSCLIENT(sp) ( SC_IS_MUXPLUSCLIENT( SVC_CONF ( sp ) ) )
+#define SVC_IS_TCPMUX( sp )      ( SC_IS_TCPMUX( SVC_CONF ( sp ) ) )
+
+#define TCPMUX_ACK "+Go\r\n"
+/*
+ * Predicate checking macros
+ */
+#define SVC_FORKS( sp )            SC_FORKS( SVC_CONF( sp ) )
+#define SVC_RETRY( sp )            SC_RETRY( SVC_CONF( sp ) )
+#define SVC_WAITS( sp )            SC_WAITS( SVC_CONF( sp ) )
+#define SVC_IS_INTERCEPTED( sp )   SC_IS_INTERCEPTED( SVC_CONF( sp ) )
+#define SVC_ACCEPTS_CONNECTIONS( sp )   \
+                                   SC_ACCEPTS_CONNECTIONS( SVC_CONF( sp ) )
+
+#define SVC_IS_LOGGING( sp )       ( (sp)->svc_log != NULL )
+#define SVC_LOGS_ON_SUCCESS( sp )         \
+      ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_SUCCESS( SVC_CONF( sp ) ) )
+#define SVC_LOGS_ON_FAILURE( sp )         \
+      ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_FAILURE( SVC_CONF( sp ) ) )
+#define SVC_LOGS_ON_EXIT( sp )            \
+      ( SVC_IS_LOGGING( sp ) && SC_LOGS_ON_EXIT( SVC_CONF( sp ) ) )
+#define SVC_LOGS_USERID_ON_SUCCESS( sp )   \
+      ( SVC_IS_LOGGING( sp ) && SC_LOGS_USERID_ON_SUCCESS( SVC_CONF( sp ) ) )
+#define SVC_LOGS_USERID_ON_FAILURE( sp )   \
+      ( SVC_IS_LOGGING( sp ) && SC_LOGS_USERID_ON_FAILURE( SVC_CONF( sp ) ) )
+
+/*
+ * Reference counting macros
+ */
+#define SVC_HOLD( sp )            (sp)->svc_ref_count++
+#define SVC_RELE( sp )            ( --(sp)->svc_ref_count )
+
+
+#define SVC_INTERNAL( sp, serp )     SC_INTERNAL( SVC_CONF( sp ), serp )
+#define SVC_MAKE_EXTERNAL( sp )      SC_MAKE_EXTERNAL( SVC_CONF( sp ) )
+
+#define SVC_DEC_RUNNING_SERVERS( sp )                                         \
+   {                                                                          \
+      if ( SVC_RUNNING_SERVERS( sp ) != 0 )                                   \
+         (sp)->svc_running_servers-- ;                                        \
+      else                                                                    \
+         msg( LOG_ERR, func,                                                  \
+            "Service %s: server exit with 0 running servers", SVC_ID( sp ) ) ;\
+   }
+
+#define SVC_INC_RUNNING_SERVERS( sp )       (sp)->svc_running_servers++
+
+#define SVC_INC_RETRIES( sp )               (sp)->svc_retry_servers++
+#define SVC_DEC_RETRIES( sp )               (sp)->svc_retry_servers--
+
+struct service *svc_new(struct service_config *scp);
+struct service *svc_make_special(struct service_config *scp);
+void svc_free(struct service *sp);
+status_e svc_activate(struct service *sp);
+void svc_deactivate(struct service *sp);
+void svc_suspend(struct service *sp);
+void svc_resume(struct service *sp);
+int svc_release(struct service *sp);
+void svc_dump(const struct service *sp,int fd);
+void svc_request(struct service *sp);
+status_e svc_generic_handler( struct service *sp, connection_s *cp );
+status_e svc_parent_access_control(struct service *sp,connection_s *cp);
+status_e svc_child_access_control(struct service *sp,connection_s *cp);
+void svc_postmortem(struct service *sp,struct server *serp);
+void close_all_svc_descriptors(void);
+
+#endif   /* SERVICE_H */
diff --git a/xinetd/signals.c b/xinetd/signals.c
new file mode 100644 (file)
index 0000000..4a61dd4
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#if defined(HAVE_STRSIGNAL)
+#define _GNU_SOURCE
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#include "str.h"
+#include "signals.h"
+#include "xconfig.h"
+#include "msg.h"
+#include "main.h"
+#include "xtimer.h"
+#include "child.h"
+#include "retry.h"
+#include "reconfig.h"
+#include "internals.h"
+
+#ifdef NO_POSIX_TYPES
+/*
+ * XXX:   here we assume that in the case that NO_POSIX_TYPES is not defined
+ *   (i.e. the system has posix types) the sigset_t is also typedef'd
+ *   to 'int'. Our goal is to work with systems that have defined
+ *   sigset_t but do not yet support the posix signal interface.
+ */
+typedef int sigset_t ;
+
+struct sigaction
+{
+   void         (*sa_handler)(int) ;
+   sigset_t     sa_mask ;
+   int          sa_flags ;
+} ;
+#endif   /* NO_POSIX_TYPES */
+
+static void my_handler( int sig );
+static void general_handler( int sig );
+
+typedef void sigfunc( int );
+
+#define SIGSET_NULL            ((sigset_t *)0)
+#define SIGVEC_NULL            ((struct sigvec *)0)
+#define SIGACTION_NULL         ((struct sigaction *)0)
+
+
+#ifdef NO_POSIX_SIGS
+#ifdef NO_SIGVEC
+#define sigmask( sig )                  ( 1 << ( (sig) -1 ) )
+typedef int (*sighandler_type)() ;
+#define sigpause( x )
+#define sigsetmask( x )
+#endif   /* NO_SIGVEC */
+
+#define sigsuspend( set )               sigpause( *set )
+#define sigemptyset( set )              (*set) = 0
+#define sigaddset( set, sig )           ( ( (*set) |= sigmask( sig ) ), 0 )
+#define sigismember( set, sig )         ( ( (*set) & sigmask( sig ) ) != 0 )
+
+/*
+ * Only works for SIG_SETMASK and SIG_UNBLOCK. Also oset must be NULL.
+ */
+int sigprocmask( int how, sigset_t *set, sigset_t *oset )
+{
+   if ( how == SIG_BLOCK || oset != NULL )
+   {
+      msg( LOG_ERR, "sigprocmask",
+                           "Bad args: how = %d, oset = %p", how, oset ) ;
+      return( -1 ) ;
+   }
+
+   if ( how == SIG_SETMASK )
+   {
+      (void) sigsetmask( *set ) ;
+      return( 0 ) ;
+   }
+
+   if ( how == SIG_UNBLOCK )
+   {
+      int current_mask = sigblock( 0 ) ;
+
+      (void) sigsetmask( current_mask & ~*set ) ;
+      return( 0 ) ;
+   }
+   /* NOTREACHED */
+}
+
+
+/*
+ * NOTE: This is not a complete imitation of sigaction; in particular it
+ *   expects that sap is never NULL and that osap is always NULL.
+ */
+int sigaction( int sig, struct sigaction *sap, struct sigaction *osap )
+{
+   if ( sap == NULL || osap != NULL )
+   {
+      msg( LOG_ERR, "sigaction", "Bad args: sap = %p, osap = %p", sap, osap ) ;
+      return( -1 ) ;
+   }
+
+#ifndef NO_SIGVEC
+   {
+      struct sigvec sv ;
+
+      sv.sv_handler = sap->sa_handler ;
+      sv.sv_mask = sap->sa_mask ;
+      sv.sv_flags = sap->sa_flags ;
+
+      return( sigvec( sig, &sv, SIGVEC_NULL ) ) ;
+   }
+#else      /* NO_SIGVEC */
+   {
+      sighandler_type new_handler ;
+
+      new_handler = sa.sa_handler ;
+      return( signal( sig, new_handler ) ? 0 : -1 ) ;
+   }
+#endif   /* ! NO_SIGVEC */
+}
+
+#endif   /* NO_POSIX_SIGS */
+
+
+/*
+ * reset_sigs is the list of signals that we need to reset to SIG_DFL.
+ * Currently, these are the signals whose actions we set to SIG_IGN.
+ * In general, we should also include any signals that have a handler
+ * that does anything other than setting a flag. We need to do this
+ * in case such a signal occurs while a forked process is providing
+ * an internal service.
+ */
+static sigset_t reset_sigs ;
+
+/*
+ * nsig is equal to the greatest signal number supported plus 1
+ */
+static int nsig ;
+
+
+/*
+ * When this function returns FAILED, we check the errno to determine
+ * if it failed because the signal number specified was invalid.
+ * This allows us to determine the number of supported signals.
+ */
+static status_e handle_signal( int sig )
+{
+   struct sigaction      sa ;
+   sigfunc              *sig_handler ;
+
+   sa.sa_flags = 0 ;
+
+   switch ( sig )
+   {
+      case RECONFIG_HARD_SIG:
+      case OLD_RECONFIG_HARD_SIG:
+      case TERMINATION_SIG:
+      case STATE_DUMP_SIG:
+      case CONSISTENCY_CHECK_SIG:
+      case SERVER_EXIT_SIG:
+      case QUIT_SIG:
+         sig_handler = my_handler ;
+         break ;
+
+      case SIGTTIN:
+      case SIGTTOU:
+      case SIGTSTP:
+         if ( debug.on )
+            return( OK ) ;
+         /* FALL THROUGH */
+          
+      /*
+       * We may receive a SIGPIPE when handling an internal stream 
+       * service and the other end closes the connection.
+       * We only care about internal services that don't require forking.
+       */
+      case SIGPIPE:
+         sig_handler = SIG_IGN ;
+         sigaddset( &reset_sigs, sig ) ;
+         break ;
+
+      case SIGKILL:
+      case SIGSTOP:
+         return( OK ) ;         /* we can't catch these two */
+      
+      /*
+       * If the following two cases are included, SIGSEGV and SIGBUS will
+       * cause core dumps. We want that to happen when we are debugging
+       * xinetd (i.e. DEBUG is defined) and we are not debugging the
+       * signal recovery code (i.e. DEBUG_SIGNALS is not defined).
+       */
+      case SIGSEGV:
+      case SIGBUS:
+#if defined( DEBUG ) && !defined( DEBUG_SIGNALS )
+         return( OK ) ;
+#else
+         sig_handler = general_handler ;
+         break;
+#endif
+      case SIGTRAP:
+         if ( debug.on )
+            return( OK ) ;
+      
+      default:
+         sig_handler = general_handler ;
+   }
+
+   sigemptyset( &sa.sa_mask ) ;
+   sa.sa_handler = sig_handler ;
+   return( ( sigaction( sig, &sa, SIGACTION_NULL ) == -1 ) ? FAILED : OK ) ;
+}
+
+
+/*
+ * Install signal handlers for all signals that can be caught.
+ * This implies that no core dumps are generated by default.
+ */
+status_e signal_init(void)
+{
+   int      sig ;
+   const char    *func = "install_signal_handlers" ;
+
+   sigemptyset( &reset_sigs ) ;
+
+   if ( pipe(signals_pending) ||
+        fcntl(signals_pending[0], F_SETFD, FD_CLOEXEC) ||
+        fcntl(signals_pending[1], F_SETFD, FD_CLOEXEC) ) {
+      msg( LOG_CRIT, func, "Failed to create signal pipe: %m" );
+      return( FAILED );
+   }
+
+   for ( sig = 1 ;; sig++ )
+      if ( handle_signal( sig ) == FAILED ) {
+         if ( errno == EINVAL )
+         {
+            nsig = sig ;
+            break ;
+         }
+         else
+         {
+            msg( LOG_CRIT, func,
+               "Failed to install signal handler for signal %s: %m",
+                  sig_name( sig ) ) ;
+            return( FAILED ) ;
+         }
+      }
+   return( OK ) ;
+}
+
+#define MAX_SIGNAL_COUNT               50
+#define MAX_INTERVAL_SIGNAL_COUNT      10
+#define SIGNAL_INTERVAL                 1      /* second */
+/*
+ * This function handles SIGSEGV and SIGBUS.
+ * Emergency action is taken if a certain number (MAX_SIGNAL_COUNT) of 
+ * these signals is received over the lifetime of the program OR 
+ * if a certain number (MAX_INTERVAL_SIGNAL_COUNT) of these signals 
+ * is received within a certain time interval (SIGNAL_INTERVAL).
+ *
+ * The action depends on the type of the emergency:
+ *      Case 1: MAX_INTERVAL_SIGNAL_COUNT is exceeded
+ *         If a setjmp environment is available, do a longjmp, otherwise exit
+ *      Case 2: MAX_SIGNAL_COUNT is exceeded
+ *         Exit
+ *
+ * NOTE: We try to send a message to the log only once to avoid
+ *         looping in this function (in case there is a bug in msg())
+ */
+static void bad_signal(void)
+{
+   static time_t   interval_start ;
+   static volatile int interval_signal_count ;
+   static volatile int total_signal_count ;
+   time_t          current_time ;
+   const char     *func = "bad_signal" ;
+
+   total_signal_count++ ;
+   if ( total_signal_count == MAX_SIGNAL_COUNT )
+   {
+      msg( LOG_CRIT, func,
+            "Received %d bad signals. Exiting...", total_signal_count ) ;
+      exit( 1 ) ;
+   }
+   else if ( total_signal_count > MAX_SIGNAL_COUNT )
+      _exit( 1 ) ;      /* in case of a problem in exit(3) */
+   
+   (void) time( &current_time ) ;
+
+   if ( interval_signal_count > 0 &&
+            current_time - interval_start <= SIGNAL_INTERVAL )
+   {
+      interval_signal_count++ ;
+      if ( interval_signal_count == MAX_INTERVAL_SIGNAL_COUNT )
+      {
+         if ( ps.rws.env_is_valid )
+         {
+            interval_start = current_time ;
+            interval_signal_count = 1 ;
+            msg( LOG_ERR, func, "Resetting..." ) ;
+            siglongjmp( ps.rws.env, 1 ) ;
+            /* NOTREACHED */
+         }
+         msg( LOG_CRIT, func,
+            "Received %d signals in %d seconds. Exiting...",
+               interval_signal_count, SIGNAL_INTERVAL ) ;
+         exit( 1 ) ;
+      }
+      else if ( interval_signal_count > MAX_INTERVAL_SIGNAL_COUNT )
+         _exit( 1 ) ;         /* shouldn't happen */
+   }
+   else
+   {
+      interval_start = current_time ;
+      interval_signal_count = 1 ;
+   }
+}
+
+char *sig_name( int sig )
+{
+   static char signame_buf[ 30 ] ;
+
+#if defined(HAVE_STRSIGNAL)
+   /* Use strsignal and remove the old sys_siglist stuff */
+   if ( sig < NSIG )
+      return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1,
+               "%d (%s)", sig, strsignal(sig) ) ) ;
+#else
+#if defined(HAVE_SYS_SIGLIST)
+   if ( sig < NSIG )
+      return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1,
+               "%d (%s)", sig, sys_siglist[sig] ) ) ;
+#endif
+#endif
+   return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1, "%d", sig ) ) ;
+}
+
+
+/*
+ * For SIGSEGV and SIGBUS we invoke the bad_signal() function
+ *
+ * For other signals, we just log the fact that they occured.
+ * SIGINT is a special case since in debug.on mode, it will 
+ * cause termination.
+ */
+
+static void general_handler( int sig )
+{
+   sigset_t badsigs ;
+   const char *func = "general_handler" ;
+
+   /*
+    * Do this here to catch problems like SIGSEGV in msg()
+    */
+   sigemptyset( &badsigs ) ;
+   sigaddset( &badsigs, sig ) ;
+   (void) sigprocmask( SIG_UNBLOCK, &badsigs, SIGSET_NULL ) ;
+
+   switch ( sig )
+   {
+      case SIGBUS:
+      case SIGSEGV:
+         msg( LOG_CRIT, func, "(%d) Unexpected signal: %s", 
+                        getpid(), sig_name( sig ) ) ;
+         if ( debug.on )
+        {
+           /* Generate a core dump */
+           signal(SIGABRT, SIG_DFL);
+           abort();
+        }
+        else
+            bad_signal() ;
+         break ;
+      
+      default:
+         msg( LOG_NOTICE, func, "Unexpected signal %s", sig_name( sig ) ) ;
+         if ( debug.on && sig == SIGINT )
+            exit( 1 ) ;
+   }
+}
+
+
+/*
+ * The job of this function is to write the signal received to the
+ * pipe of pending signals, which is in the main select loop.
+ */
+static void my_handler( int sig )
+{
+   int ret_val;
+   int saved_errno = errno;
+#if NSIG < 256
+   unsigned char sig_byte;
+   if (signals_pending[1] < 0) return;
+   if (sig >= 256) return;
+   sig_byte = sig;
+   do
+   {
+      ret_val = write(signals_pending[1], &sig_byte, 1);
+   } while (ret_val == -1 && errno == EINTR);
+#else
+   if (signals_pending[1] < 0) return;
+   do
+   {
+      ret_val = write(signals_pending[1], &sig, sizeof(int));
+   } while (ret_val == -1 && errno == EINTR);
+#endif
+   errno = saved_errno;
+}
+
+
+/*
+ * Reset all signals to default action. Reset the signal mask
+ *
+ * This function is invoked from a forked process. That is why we
+ * invoke _exit instead of exit (to avoid the possible stdio buffer flushes)
+ */
+void signal_default_state(void)
+{
+   int sig ;
+   sigset_t empty ;
+
+   for ( sig = 1 ; sig < nsig ; sig++ )
+      if ( sigismember( &reset_sigs, sig ) == 1 )
+         if ( signal( sig, SIG_DFL ) == SIG_ERR )
+         {
+            msg( LOG_ERR, "reset_signals",
+               "signal failed for signal %s: %m", sig_name( sig ) ) ;
+            if ( debug.on )
+               _exit( 1 ) ;
+         }
+      
+   sigemptyset( &empty ) ;
+   (void) sigprocmask( SIG_SETMASK, &empty, SIGSET_NULL ) ;
+}
+
+void check_pipe(void)
+{
+   int i;
+#if NSIG < 256
+   unsigned char sig;
+#else
+   int sig;
+#endif
+   const char *func = "check_pipe";
+
+   if (signals_pending[0] < 0) return;
+
+   if( ioctl(signals_pending[0], FIONREAD, &i) != 0 ) {
+      msg(LOG_ERR, func, "Can't get the number of pending signals: %m");
+      return;
+   }
+#if NSIG >= 256
+   i /= sizeof(int);
+#endif
+
+   while( --i >= 0 ) {
+      int ret_val;
+      do
+      {
+         ret_val = read(signals_pending[0], &sig, sizeof(sig));
+      } while (ret_val == -1 && errno == EINTR);
+      if (ret_val != sizeof(sig) ) {
+         msg(LOG_ERR, func, "Error retrieving pending signal: %m");
+         return;
+      }
+
+      if( debug.on ) {
+         msg(LOG_DEBUG, func, "Got signal %s", sig_name(sig));
+      }
+
+      switch(sig) {
+         case SERVER_EXIT_SIG:       child_exit();           break;
+         case RECONFIG_HARD_SIG:     hard_reconfig();        break;
+         case OLD_RECONFIG_HARD_SIG: hard_reconfig();        break;
+         case TERMINATION_SIG:       terminate_program();    break;
+         case STATE_DUMP_SIG:        dump_internal_state();  break;
+         case CONSISTENCY_CHECK_SIG: user_requested_check(); break;
+         case QUIT_SIG:              quit_program();         break;
+         default:
+            msg(LOG_ERR, func, "unexpected signal: %s in signal pipe", 
+               sig_name(sig));
+      }
+   }
+}
diff --git a/xinetd/signals.h b/xinetd/signals.h
new file mode 100644 (file)
index 0000000..6acf97c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#ifndef _X_SIGNALS
+#define _X_SIGNALS
+
+#include "defs.h"
+
+#if defined(NO_POSIX_SIGS)
+int sigprocmask(int how,sigset_t *set,sigset_t *oset);
+int sigaction(int sig,struct sigaction *sap,struct sigaction *osap);
+#endif
+status_e signal_init(void);
+char *sig_name(int sig);
+void signal_default_state(void);
+void check_pipe(void);
+
+#endif
diff --git a/xinetd/special.c b/xinetd/special.c
new file mode 100644 (file)
index 0000000..22b2fd5
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "special.h"
+#include "server.h"
+#include "msg.h"
+#include "sconst.h"
+#include "int.h"
+#include "util.h"
+#include "nvlists.h"
+#include "service.h"
+#include "state.h"
+#include "main.h"
+#include "connection.h"
+#include "sconf.h"
+#include "options.h"
+#include "xconfig.h"
+#include "ident.h"
+
+
+static void stream_logging( struct server *) ;
+
+static const struct builtin_service special_services[] =
+   {
+      { LOG_SERVICE_NAME,        SOCK_STREAM,   { stream_logging,    FORK   } },
+      { INTERCEPT_SERVICE_NAME,  SOCK_STREAM,   { intercept,         FORK   } },
+      { INTERCEPT_SERVICE_NAME,  SOCK_DGRAM,    { intercept,         FORK   } },
+      { NULL,                    0,             { NULL,              0      } }
+   } ;
+
+
+const builtin_s *spec_find( const char *service_name, int type )
+{
+   const builtin_s *bp ;
+   const struct name_value *nvp ;
+   const char *func = "spec_find" ;
+
+   if ( (bp = builtin_lookup( special_services, service_name, type )) )
+      return( bp ) ;
+
+   nvp = nv_find_name( socket_types, type ) ;
+   if ( nvp == NULL )
+   {
+      msg( LOG_ERR, func, "unknown socket type: %d", type ) ;
+      return( NULL ) ;
+   }
+
+   msg( LOG_ERR, func,
+            "special service %s,%s not supported", service_name, nvp->name ) ;
+   return( NULL ) ;
+}
+
+
+status_e spec_service_handler( struct service *sp, connection_s *cp )
+{
+   return(server_run( sp, cp ));
+}
+
+
+static struct service *spec_setup( const char *name, int socket_type, 
+                                   int instances )
+{
+   const builtin_s *bp ;
+   struct service_config *scp ;
+
+   bp = spec_find( name, socket_type ) ;
+   if ( bp == NULL )
+      return( NULL ) ;
+
+   if ( ( scp = sc_make_special( name, bp, instances ) ) == NULL )
+      return( NULL ) ;
+
+   return( svc_make_special( scp ) ) ;
+}
+
+
+/*
+ * Initialize the special services and the corresponding entries in
+ * the program state structure.
+ */
+void spec_include(void)
+{
+   int instances ;
+
+   instances = logprocs_option ? logprocs_option_arg : DEFAULT_LOGPROCS ;
+   LOG_SERVICE( ps ) = spec_setup( LOG_SERVICE_NAME, SOCK_STREAM, instances ) ;
+}
+
+
+static void stream_logging( struct server *serp )
+{
+   const char *func = "stream_logging" ;
+   idresult_e result ;
+
+#ifdef DEBUG_LOGGING
+   if ( debug.on )
+   {
+      msg( LOG_DEBUG, func, "%d is sleeping", getpid() ) ;
+      sleep( 10 ) ;
+   }
+#endif
+
+   result = log_remote_user( serp, LOGUSER_FAILURE_TIMEOUT ) ;
+   if ( (result != IDR_OK) && (result != IDR_NOSERVER) )
+      msg( LOG_ERR, func, "Failed to contact identity server at %s: %s", conn_addrstr( SERVER_CONNECTION( serp ) ), idresult_explain( result ) ) ;
+}
+
diff --git a/xinetd/special.h b/xinetd/special.h
new file mode 100644 (file)
index 0000000..ffc16b5
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef SPECIAL_H
+#define SPECIAL_H
+
+#include "defs.h"
+#include "builtins.h"
+
+const builtin_s *spec_find(const char *service_name,int type);
+status_e spec_service_handler( struct service *sp, connection_s *cp );
+void spec_include(void);
+       
+#endif
+
diff --git a/xinetd/state.h b/xinetd/state.h
new file mode 100644 (file)
index 0000000..6c9ada8
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef STATE_H
+#define STATE_H
+
+/*
+ * $Id: state.h,v 1.3 2005/03/30 23:15:28 bbraun Exp $
+ */
+
+#include "config.h"
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include "libportable.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "xlog.h"
+#include "pset.h"
+#include "defs.h"
+#include "mask.h"
+
+struct read_only_state
+{
+   rlim_t      orig_max_descriptors ; /* original soft rlimit                */
+   rlim_t      max_descriptors ;      /* original hard rlimit or OPEN_MAX    */
+   rlim_t      process_limit ;        /* if 0, there is no limit             */
+   int         cc_interval ;          /* # of seconds the cc gets invoked.   */
+   const char *pid_file ;             /* where the pidfile is located        */
+   const char *config_file ;
+   int         is_superuser ;
+   char      **Argv ;
+   int         Argc ;
+} ;
+
+
+struct defaults
+{
+   struct service_config  *def_settings ;
+   xlog_h                  def_log ;
+   bool_int                def_log_creation_failed ;
+} ;
+
+
+struct read_write_state
+{
+   int              descriptors_free ;     /* may be negative (reserved)    */
+   int              available_services ;   /* # of available services       */
+   int              active_services ;      /* services with descriptors set */
+                                           /* in socket mask                */
+   fd_set           socket_mask ;
+   int              mask_max ;
+   pset_h           servers ;              /* table of running servers      */
+   pset_h           retries ;              /* table of servers to retry     */
+   pset_h           services ;             /* table of services             */
+   struct service  *logging ;
+   struct defaults  defs ;
+   xlog_h           program_log ;
+   sigjmp_buf       env ;
+   bool_int         env_is_valid ;
+#ifdef HAVE_MDNS
+   void            *mdns_state ;
+#endif
+} ;
+
+struct program_state
+{
+   struct read_only_state   ros ;
+   struct read_write_state  rws ;
+} ;
+
+#define DEFAULTS( ps )                  (ps).rws.defs.def_settings
+#define DEFAULT_LOG( ps )               (ps).rws.defs.def_log
+#define DEFAULT_LOG_ERROR( ps )         (ps).rws.defs.def_log_creation_failed
+#define LOG_SERVICE( ps )               (ps).rws.logging
+#define SERVICES( ps )                  (ps).rws.services
+#define SERVERS( ps )                   (ps).rws.servers
+#define RETRIES( ps )                   (ps).rws.retries
+
+
+#endif   /* STATE_H */
diff --git a/xinetd/tcpint.c b/xinetd/tcpint.c
new file mode 100644 (file)
index 0000000..f0bf040
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "tcpint.h"
+#include "intcommon.h"
+#include "msg.h"
+#include "log.h"
+#include "xconfig.h"
+#include "sconf.h"
+
+typedef enum { S_OK, S_SERVER_ERR, S_CLIENT_ERR } stream_status_e ;
+
+struct istream_private
+{
+   unsigned accepted_connections ;
+} ;
+
+#define SIP( p )                  ((struct istream_private *)(p))
+
+static struct istream_private istream ;
+static struct intercept_s stream_intercept_state ;
+static void si_mux(void) ;
+
+
+static struct intercept_ops istream_ops =
+{
+      si_mux,
+      si_exit
+} ;
+
+
+
+struct intercept_s *si_init( struct server *serp )
+{
+   struct intercept_s *ip = &stream_intercept_state ;
+
+   ip->int_socket_type = SOCK_STREAM ;
+   ip->int_priv = (void *) &istream ;
+   ip->int_ops = &istream_ops ;
+   int_init( ip, serp ) ;
+   if ( signal( SIGPIPE, SIG_IGN ) == SIG_ERR )
+      int_fail( ip, "signal" ) ;
+   return( ip ) ;
+}
+
+static status_e handle_io( psi_h iter, channel_s *chp, fd_set *maskp, stream_status_e (*iofunc)() );
+static stream_status_e tcp_local_to_remote( channel_s *chp );
+static stream_status_e tcp_remote_to_local( channel_s *chp );
+static void connection_request( struct intercept_s *ip, channel_s **chpp );
+
+/* Unfortunatly, this can't be private... */
+void si_exit(void)
+{
+   struct intercept_s *ip = &stream_intercept_state ;
+   
+   if ( SIP( ip->int_priv )->accepted_connections == 0 )
+      (void) accept( INT_REMOTE( ip ), SA( NULL ), NULL ) ;
+   int_exit( ip ) ;
+}
+
+
+static void si_mux(void)
+{
+   struct intercept_s   *ip = &stream_intercept_state ;
+   fd_set                     socket_mask ;
+   int                        mask_max ;
+   psi_h                      iter ;
+   const char                *func = "si_mux" ;
+
+   FD_ZERO( &socket_mask ) ;
+   FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
+   mask_max = INT_REMOTE( ip ) ;
+
+   iter = psi_create( INT_CONNECTIONS( ip ) ) ;
+   if ( iter == NULL )
+   {
+      msg( LOG_ERR, func, ES_NOMEM ) ;
+      return ;
+   }
+
+   for ( ;; )
+   {
+      channel_s *chp ;
+      fd_set read_mask ;
+      int n_ready ;
+
+      read_mask = socket_mask ;
+      n_ready = int_select( mask_max+1, &read_mask ) ;
+
+      if ( n_ready == -1 )
+         return ;
+      
+      if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
+      {
+         connection_request( ip, &chp ) ;
+         if ( chp != NULL )
+         {
+            FD_SET( chp->ch_local_socket, &socket_mask ) ;
+            if ( chp->ch_local_socket > mask_max )
+               mask_max = chp->ch_local_socket ;
+            FD_SET( chp->ch_remote_socket, &socket_mask ) ;
+            if ( chp->ch_remote_socket > mask_max )
+               mask_max = chp->ch_remote_socket ;
+         }
+         if ( --n_ready == 0 )
+            continue ;
+      }
+
+      for ( chp = CHP( psi_start(iter) ) ; chp ; chp = CHP( psi_next(iter) ) )
+      {
+         if ( FD_ISSET( chp->ch_local_socket, &read_mask ) )
+         {
+#ifdef DEBUG_TCPINT
+            if ( debug.on )
+               msg( LOG_DEBUG, func, "Input available on local socket %d", 
+                                                         chp->ch_local_socket ) ;
+#endif
+            if ( handle_io( iter, chp, &socket_mask, tcp_local_to_remote ) == FAILED )
+               return ;
+            if ( --n_ready == 0 )
+               break ;
+         }
+
+         if ( FD_ISSET( chp->ch_remote_socket, &read_mask ) )
+         {
+#ifdef DEBUG_TCPINT
+            msg( LOG_DEBUG, func, "Input available on remote socket %d", 
+                                                      chp->ch_remote_socket ) ;
+#endif
+            if ( handle_io( iter, chp,
+                        &socket_mask, tcp_remote_to_local ) == FAILED )
+               return ;
+            if ( --n_ready == 0 )
+               break ;
+         }
+      }
+   }
+}
+
+
+static status_e handle_io( psi_h iter, 
+                            channel_s *chp, 
+                            fd_set *maskp, 
+                            stream_status_e (*iofunc)() )
+{
+   const char *func = "handle_io" ;
+
+   switch ( (*iofunc)( chp ) )
+   {
+      case S_SERVER_ERR:
+         return( FAILED ) ;
+      
+      case S_CLIENT_ERR:
+
+         if ( debug.on )
+            msg( LOG_DEBUG, func,
+               "Closing channel to %s,%d using sockets %d(l),%d(r)",
+                  xaddrname( &chp->ch_from ), ntohs(xaddrport( &chp->ch_from )),
+                        chp->ch_local_socket, chp->ch_remote_socket ) ;
+
+         FD_CLR( chp->ch_local_socket, maskp ) ;
+         FD_CLR( chp->ch_remote_socket, maskp ) ;
+         (void) Sclose( chp->ch_remote_socket ) ;
+         (void) Sclose( chp->ch_local_socket ) ;
+         psi_remove( iter ) ;
+         FREE_CHANNEL( chp ) ;
+         break ;
+      case S_OK:
+         break ;
+   }
+   return( OK ) ;
+}
+
+
+static void connection_request( struct intercept_s *ip, channel_s **chpp )
+{
+   union xsockaddr      csin ;
+   socklen_t            sin_len = 0;
+   channel_s           *chp ;
+   int                  sd ;
+   bool_int             addr_checked ;
+   const char          *func = "connection_request" ;
+
+   *chpp = NULL ;
+   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
+      sin_len = sizeof(struct sockaddr_in);
+   if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
+      sin_len = sizeof(struct sockaddr_in6);
+
+   if ( ( sd = accept( INT_REMOTE( ip ), SA( &csin ), &sin_len ) ) == -1 ) 
+      return ;
+   
+   SIP( ip->int_priv )->accepted_connections++ ;
+
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "connection request from %s,%d",
+         xaddrname( &csin ), ntohs( xaddrport( &csin ) ) ) ;
+
+   chp = int_lookupconn( ip, &csin, &addr_checked ) ;
+   if ( chp == NULL )
+   {
+      struct server  *serp  = INT_SERVER( ip ) ;
+      struct service *sp    = SERVER_SERVICE( serp ) ;
+      connection_s   *cop   = SERVER_CONNECTION( serp ) ;
+
+      CONN_SETADDR( cop, &csin ) ;
+
+      if ( INTERCEPT( ip ) )
+      {
+         mask_t check_mask ;
+         access_e result ;
+         
+         M_OR( check_mask, XMASK( CF_ADDRESS ), XMASK( CF_TIME ) ) ;
+         result = access_control( sp, cop, &check_mask ) ;
+
+         if ( result != AC_OK )
+         {
+            svc_log_failure( sp, cop, result ) ;
+            (void) Sclose( sd ) ;
+            return ;
+         }
+      }
+
+      if ( ( chp = int_newconn( ip, &csin, sd ) ) == NULL )
+      {
+         (void) Sclose( sd ) ;
+         return ;
+      }
+      
+      if ( ! addr_checked )
+         svc_log_success( sp, cop, SERVER_PID( serp ) ) ;
+
+#if defined( TCP_NODELAY )
+      {
+         int on = 1 ;
+
+         (void) setsockopt( chp->ch_local_socket, IPPROTO_TCP,
+                              TCP_NODELAY, (char *) &on, sizeof( on ) ) ;
+         (void) setsockopt( chp->ch_remote_socket, IPPROTO_TCP,
+                              TCP_NODELAY, (char *) &on, sizeof( on ) ) ;
+      }
+#endif   /* TCP_NODELAY */
+      
+      *chpp = chp ;
+   }
+   else
+      msg( LOG_ERR, func,
+         "Received another connection request from %s,%d",
+            xaddrname( &csin ), ntohs( xaddrport( &csin ) ) ) ;
+}
+
+
+static stream_status_e tcp_local_to_remote( channel_s *chp )
+{
+   char  buf[ DATAGRAM_SIZE ] ;
+   int   rcc, wcc ;
+   char *p ;
+   int   left ;
+   const char *func = "tcp_local_to_remote" ;
+
+   for ( ;; )
+   {
+      rcc = recv( chp->ch_local_socket, buf, sizeof( buf ), 0 ) ;
+      if ( rcc == 0 )
+         return( S_SERVER_ERR ) ;
+      else if ( rcc == -1 )
+      {
+         if ( errno != EINTR )
+         {
+            msg( LOG_ERR, func, "recv: %m" ) ;
+            return( S_SERVER_ERR ) ;
+         }
+      }
+      else
+         break ;
+   }
+
+   for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
+   {
+      wcc = send( chp->ch_remote_socket, p, left, 0 ) ;
+      if ( wcc == 0 )
+         return( S_CLIENT_ERR ) ;
+      else if ( wcc == -1 )
+      {
+         if ( errno == EINTR )
+            wcc = 0 ;
+         else
+         {
+            msg( LOG_ERR, func, "send: %m" ) ;
+            return( S_CLIENT_ERR ) ;
+         }
+      }
+   }
+
+#ifdef DEBUG_TCPINT
+   if ( debug.on )
+      msg( LOG_DEBUG, func,
+         "Transferred %d bytes from local socket %d to remote socket %d",
+            rcc, chp->ch_local_socket, chp->ch_remote_socket ) ;
+#endif
+
+   return( S_OK ) ;
+}
+
+
+static stream_status_e tcp_remote_to_local( channel_s *chp )
+{
+   char  buf[ DATAGRAM_SIZE ] ;
+   int   rcc, wcc ;
+   int   left ;
+   char *p ;
+   const char *func = "tcp_remote_to_local" ;
+
+   for ( ;; )
+   {
+      rcc = recv( chp->ch_remote_socket, buf, sizeof( buf ), 0 ) ;
+      if ( rcc == 0 )
+         return( S_CLIENT_ERR ) ;
+      else if ( rcc == -1 )
+      {
+         if ( errno != EINTR )
+         {
+            msg( LOG_ERR, func, "recv: %m" ) ;
+            return( S_CLIENT_ERR ) ;
+         }
+      }
+      else
+         break ;
+   }
+
+   for ( p = buf, left = rcc ; left ; p += wcc, left -= wcc )
+   {
+      wcc = send( chp->ch_local_socket, p, left, 0 ) ;
+      if ( wcc == 0 ) {
+         return( S_SERVER_ERR ) ;
+      } else if ( wcc == -1 ) {
+         if ( errno == EINTR ) {
+            rcc = 0 ;
+         } else {
+            msg( LOG_ERR, func, "send: %m" ) ;
+            return( S_SERVER_ERR ) ;
+         }
+      }
+   }
+
+#ifdef DEBUG_TCPINT
+   if ( debug.on )
+      msg( LOG_DEBUG, func,
+         "Transferred %d bytes from remote socket %d to local socket %d",
+            rcc, chp->ch_remote_socket, chp->ch_local_socket ) ;
+#endif
+
+   return( S_OK ) ;
+}
+
diff --git a/xinetd/tcpint.h b/xinetd/tcpint.h
new file mode 100644 (file)
index 0000000..309ed29
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef TCPINT_H
+#define TCPINT_H
+
+#include "defs.h"
+#include "int.h"
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void si_exit(void);
+struct intercept_s *si_init(struct server *serp);
+
+#endif
diff --git a/xinetd/time.c b/xinetd/time.c
new file mode 100644 (file)
index 0000000..a4d63fb
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "sio.h"
+#include "timex.h"
+#include "msg.h"
+#include "util.h"
+
+
+#define IN_RANGE( val, low, high )     ( (low) <= (val) && (val) <= (high) )
+
+struct time_interval
+{
+   int16_t min_start ;
+   int16_t min_end ;
+} ;
+
+#define TIP( p )               ( (struct time_interval *) (p) )
+#define NEW_TI()               NEW( struct time_interval )
+#define FREE_TI( tip )         FREE( tip )
+
+
+/*
+ * Returns TRUE if the current time is within at least one of the intervals
+ */
+bool_int ti_current_time_check( const pset_h intervals )
+{
+   time_t      current_time ;
+   unsigned    u ;
+   int16_t     min_current ;
+   struct tm   *tmp ;
+
+   (void) time( &current_time ) ;
+   tmp = localtime( &current_time ) ;
+   min_current = tmp->tm_hour * 60 + tmp->tm_min ;
+
+   for ( u = 0 ; u < pset_count( intervals ) ; u++ )
+   {
+      struct time_interval *tip ;
+      
+      tip = TIP( pset_pointer( intervals, u ) ) ;
+      if ( IN_RANGE( min_current, tip->min_start, tip->min_end ) )
+         return( TRUE ) ;
+   }
+   return( FALSE ) ;
+}
+
+
+static int get_num( int *nump, 
+                       int min_val, 
+                       int max_val, 
+                       const char *s, 
+                       char stop_char )
+{
+   const char *func = "get_num" ;
+   int i = 0;
+
+   for ( *nump = 0 ; isdigit( s[i] ) ; i++ )
+   {
+      *nump *= 10 ;
+      *nump += s[i] - '0' ;
+   }
+
+   if ( s[i] != stop_char )
+   {
+      parsemsg( LOG_ERR, func, "incorrect time interval" ) ;
+      return( -1 );
+   }
+
+   if ( ! IN_RANGE( *nump, min_val, max_val ) )
+   {
+      parsemsg( LOG_ERR, func, "invalid time interval" ) ;
+      return( -1 ) ;
+   }
+   return( i ) ;
+}
+
+
+/*
+ * Each interval should have the form:
+ *    hour:min-hour:min
+ * Example: 2:30-4:15
+ */
+status_e ti_add( pset_h iset, const char *interval_str )
+{
+   struct time_interval   *tip ;
+   int                  hours ;
+   int                  minutes ;
+   int                  min_start ;
+   int                  min_end ;
+   int                  p, r = 0 ;
+   const char          *func = "add_interval" ;
+
+   while (interval_str[r] == ' ')
+          r++;         /* Eat white space */
+   if ( ( p = get_num( &hours, 0, 23, interval_str+r, ':' ) ) == -1 )
+      return( FAILED ) ;
+   r += p;
+   r++;                        /* Get past : */
+   if ( ( p = get_num( &minutes, 0, 59, interval_str+r, '-' ) ) == -1 )
+      return( FAILED ) ;
+   min_start = hours * 60 + minutes ;
+
+   r += p;
+   r++;                        /* Get past - */
+   if ( ( p = get_num( &hours, 0, 23, interval_str+r, ':' ) ) == -1 )
+      return( FAILED ) ;
+   r += p;
+   r++;                        /* Get past : */
+   if ( get_num( &minutes, 0, 59, interval_str+r, NUL ) == -1 )
+      return( FAILED ) ;
+   min_end = hours * 60 + minutes ;
+   if ( min_start >= min_end )
+   {
+      parsemsg( LOG_ERR, func, "invalid time interval: %s", interval_str ) ;
+      return( FAILED ) ;
+   }
+
+   tip = NEW_TI() ;
+   if ( tip == NULL )
+   {
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   tip->min_start = min_start ;
+   tip->min_end = min_end ;
+   if ( pset_add( iset, tip ) == NULL )
+   {
+      FREE_TI( tip ) ;
+      out_of_memory( func ) ;
+      return( FAILED ) ;
+   }
+   return( OK ) ;
+}
+
+
+void ti_dump( pset_h iset, int fd )
+{
+   unsigned u ;
+
+   for ( u = 0 ; u < pset_count( iset ) ; u++ )
+   {
+      struct time_interval *tip = TIP( pset_pointer( iset, u ) ) ;
+
+      Sprint( fd, " %02d:%02d-%02d:%02d",
+         tip->min_start / 60, tip->min_start % 60,
+         tip->min_end / 60, tip->min_end % 60 ) ;
+   }
+}
+
+
+void ti_free( pset_h iset )
+{
+   pset_apply( iset, free, NULL ) ;
+}
+
diff --git a/xinetd/timex.h b/xinetd/timex.h
new file mode 100644 (file)
index 0000000..f4d1b8e
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+#ifndef _X_TIME
+#define _X_TIME
+
+#include "pset.h"
+#include "defs.h"
+
+bool_int ti_current_time_check(const pset_h intervals);
+status_e ti_add(pset_h iset,const char *interval_str);
+void ti_dump(pset_h iset,int fd);
+void ti_free(pset_h iset);
+
+#endif
diff --git a/xinetd/udpint.c b/xinetd/udpint.c
new file mode 100644 (file)
index 0000000..6f65951
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <syslog.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "udpint.h"
+#include "intcommon.h"
+#include "util.h"
+#include "connection.h"
+#include "access.h"
+#include "log.h"
+#include "msg.h"
+#include "sconf.h"
+
+/*
+ * Datagrams greater than this will be truncated
+ */
+#define MAX_DATAGRAM_SIZE         ( 32 * 1024 )
+
+struct packet
+{
+   union xsockaddr from ;
+   char                  *data ;
+   int                  size ;
+} ;
+
+typedef struct packet packet_s ;
+
+
+struct idgram_private
+{
+   unsigned received_packets ;
+} ;
+
+#define IDP( p )               ((struct idgram_private *)(p))
+
+
+static struct idgram_private idgram ;
+
+static void di_mux(void) ;
+static void udp_remote_to_local( struct intercept_s *ip, channel_s **chpp );
+static status_e udp_local_to_remote( channel_s *chp );
+static void send_data( int sd, char *buf, int len, union xsockaddr *addr );
+static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp );
+
+static const struct intercept_ops idgram_ops =
+   {
+      di_mux,
+      di_exit
+   } ;
+
+
+static struct intercept_s dgram_intercept_state ;
+
+
+struct intercept_s *di_init( struct server *serp )
+{
+   struct intercept_s *ip = &dgram_intercept_state ;
+   
+   ip->int_socket_type = SOCK_DGRAM ;
+   ip->int_priv = (void *) &idgram ;
+   ip->int_ops = &idgram_ops ;
+   int_init( ip, serp ) ;
+   return( ip ) ;
+}
+
+
+void di_exit(void)
+{
+   struct intercept_s *ip = &dgram_intercept_state ;
+
+   if ( IDP( ip->int_priv )->received_packets == 0 )
+      drain( INT_REMOTE( ip ) ) ;
+   int_exit( ip ) ;
+}
+
+
+/*
+ * Returns only if there is an I/O error while communicating with the server
+ */
+static void di_mux(void)
+{
+   struct intercept_s   *ip = &dgram_intercept_state ;
+   fd_set                     socket_mask ;
+   int                        mask_max ;
+
+   FD_ZERO( &socket_mask ) ;
+   FD_SET( INT_REMOTE( ip ), &socket_mask ) ;
+   mask_max = INT_REMOTE( ip ) ;
+
+   for ( ;; )
+   {
+      unsigned u ;
+      channel_s *chp ;
+      fd_set read_mask ;
+      int n_ready ;
+
+      read_mask = socket_mask ;
+      n_ready = int_select( mask_max+1, &read_mask ) ;
+
+      if ( n_ready == -1 )
+         return ;
+      
+      if ( FD_ISSET( INT_REMOTE( ip ), &read_mask ) )
+      {
+         udp_remote_to_local( ip, &chp ) ;
+         if ( chp != NULL )
+         {
+            FD_SET( chp->ch_local_socket, &socket_mask ) ;
+            if ( chp->ch_local_socket > mask_max )
+               mask_max = chp->ch_local_socket ;
+         }
+         if ( --n_ready == 0 )
+            continue ;
+      }
+
+      for ( u = 0 ; u < pset_count( INT_CONNECTIONS( ip ) ) ; u++ )
+      {
+         chp = CHP( pset_pointer( INT_CONNECTIONS( ip ), u ) ) ;
+
+         if ( FD_ISSET( chp->ch_local_socket, &read_mask ) )
+         {
+            if ( udp_local_to_remote( chp ) == FAILED )
+               return ;
+            if ( --n_ready == 0 )
+               break ;
+         }
+      }
+   }
+}
+
+
+/*
+ * Read data from the remote socket and send it to the appropriate local 
+ * socket.
+ * If this is a new connection, insert it in the connection table and
+ * place its handle in *chpp.
+ */
+static void udp_remote_to_local( struct intercept_s *ip, channel_s **chpp )
+{
+   char               buf[ MAX_DATAGRAM_SIZE ] ;
+   packet_s           packet ;
+   channel_s          *chp ;
+   bool_int           addr_checked ;
+
+   *chpp = CHANNEL_NULL ;
+
+   packet.data = buf ;
+   packet.size = sizeof( buf ) ;
+   if ( get_incoming_packet( ip, &packet ) == FAILED )
+      return ;
+
+   chp = int_lookupconn( ip, &packet.from, &addr_checked ) ;
+   if ( chp == CHANNEL_NULL )
+   {
+      struct server      *serp = INT_SERVER( ip ) ;
+      struct service    *sp = SERVER_SERVICE( serp ) ;
+      connection_s      *cop = SERVER_CONNECTION( serp ) ;
+
+      if ( ( chp = int_newconn( ip, &packet.from, INT_REMOTE( ip ) ) ) == NULL )
+         return ;
+
+      CONN_SETADDR( cop, &packet.from ) ;      /* for logging */
+
+      if ( INTERCEPT( ip ) )
+      {
+         mask_t check_mask ;
+         access_e result ;
+
+         M_OR( check_mask, XMASK( CF_ADDRESS ), XMASK( CF_TIME ) ) ;
+         result = access_control( sp, cop, &check_mask ) ;
+
+         if ( result != AC_OK )
+         {
+            svc_log_failure( sp, cop, result ) ;
+            chp->ch_state = BAD_CHANNEL ;
+            return ;
+         }
+      }
+      
+      /*
+       * Since we don't distinguish ports, there is no point to log
+       * another successful attempt from the same address
+       */
+      if ( ! addr_checked )
+         svc_log_success( sp, cop, SERVER_PID( serp ) ) ;
+         
+      *chpp = chp ;
+   }
+   else if ( chp->ch_state == BAD_CHANNEL )
+      return ;
+   
+#ifdef DEBUG_UDPINT
+   if ( debug.on )
+      msg( LOG_DEBUG, "udp_remote_to_local",
+               "sending %d bytes to server on port %d",
+                     packet.size, ntohs( INT_LOCALADDR( ip )->sin_port ) ) ;
+#endif
+
+   send_data( chp->ch_local_socket,
+         packet.data, packet.size, NULL ) ;
+}
+
+
+/*
+ * Send the data in buf to destination addr using the socket sd.
+ * If addr is NULL, use the default socket destination
+ */
+static void send_data( int sd, char *buf, int len, union xsockaddr *addr )
+{
+   char   *p ;
+   int   left ;
+   int   cc ;
+   const char   *func = "send_data" ;
+
+   for ( p = buf, left = len ; left > 0 ; left -= cc, p+= cc )
+   {
+      if ( addr == NULL )
+         cc = send( sd, p, left, 0 ) ;
+      else
+         cc = sendto( sd, p, left, 0, SA( addr ), sizeof( *addr ) ) ;
+
+      if ( cc == -1 ) {
+         if ( errno == EINTR )
+         {
+            cc = 0 ;
+            continue ;
+         }
+         else
+         {
+            msg( LOG_ERR, func, "%s: %m", addr ? "sendto" : "send" ) ;
+            return ;
+         }
+      }
+   }
+}
+
+
+static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp )
+{
+   socklen_t from_len = 0;
+   const char *func = "get_incoming_packet" ;
+
+   if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
+      from_len = sizeof( struct sockaddr_in );
+   if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) )
+      from_len = sizeof( struct sockaddr_in6 );
+
+   for ( ;; )
+   {
+      int cc ;
+
+      from_len = sizeof( pp->from ) ;
+      cc = recvfrom( INT_REMOTE( ip ), pp->data, pp->size,
+                                    0, SA( &pp->from ), &from_len ) ;
+      if ( cc == -1 )
+      {
+         if ( errno != EINTR )
+         {
+            msg( LOG_ERR, func, "recvfrom error: %m" ) ;
+            return( FAILED ) ;
+         }
+      }
+      else if ( cc == 0 )
+         return( FAILED ) ;
+      else
+      {
+         pp->size = cc ;
+         IDP( ip->int_priv )->received_packets++ ;
+         break ;
+      }
+   }
+
+   if ( from_len == 0 )
+   {
+      msg( LOG_ERR, func, "incoming packet had 0 length address" ) ;
+      return( FAILED ) ;
+   }
+   
+#ifdef DEBUG_UDPINT
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "Received %d bytes from address: %s,%d",
+         pp->size, xaddrname( &pp->from ), ntohs( xaddrport(&pp->from) ) );
+#endif
+
+   return( OK ) ;
+}
+
+
+static status_e udp_local_to_remote( channel_s *chp )
+{
+   char   buf[ MAX_DATAGRAM_SIZE ] ;
+   int    cc ;
+   const char   *func = "udp_local_to_remote" ;
+
+   for ( ;; )
+   {
+      cc = recv( chp->ch_local_socket, buf, sizeof( buf ), 0 ) ;
+   
+      if ( cc == -1 )
+      {
+         if ( errno != EINTR ) 
+         {
+            msg( LOG_ERR, func, "recv from daemon: %m" ) ;
+            return( FAILED ) ;
+         }
+      }
+      else if ( cc == 0 )
+         return( FAILED ) ;
+      else
+         break ;
+   }
+   
+#ifdef DEBUG_UDPINT
+   if ( debug.on )
+      msg( LOG_DEBUG, func, "sending %d bytes to address %s,%d",
+         cc, xaddrname( &chp->ch_from ), ntohs( xaddrport(&chp->ch_from) ) ) ;
+#endif
+
+   send_data( chp->ch_remote_socket, buf, cc, &chp->ch_from ) ;
+   return( OK ) ;
+}
+
diff --git a/xinetd/udpint.h b/xinetd/udpint.h
new file mode 100644 (file)
index 0000000..c49ac5d
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef UDPINT_H
+#define UDPINT_H
+
+#include "defs.h"
+#include "int.h"
+
+#ifdef __GNUC__
+__attribute__ ((noreturn))
+#endif
+void di_exit(void);
+struct intercept_s *di_init(struct server *serp);
+
+#endif
diff --git a/xinetd/util.c b/xinetd/util.c
new file mode 100644 (file)
index 0000000..7098ecf
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+
+#include "config.h"
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#if defined (HAVE_SYS_SOCKET_H)
+#include <sys/socket.h>
+#endif
+/*
+ * The following ifdef is for TIOCNOTTY
+ */
+#ifndef NO_TERMIOS
+#ifdef HAVE_SYS_TERMIOS_H
+#include <sys/termios.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#else
+#include <sys/ioctl.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#include <memory.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include "sio.h"
+#include "str.h"
+#include "util.h"
+#include "msg.h"
+
+void out_of_memory( const char *func )
+{
+   msg( LOG_CRIT, func, ES_NOMEM ) ;
+}
+
+
+const struct name_value *nv_find_value( const struct name_value nv_array[], const char *name )
+{
+   const struct name_value *nvp ;
+
+   for ( nvp = nv_array ; nvp->name ; nvp++ )
+   {
+      if ( EQ( name, nvp->name ) )
+         return( nvp ) ;
+   }
+   return( NULL ) ;
+}
+
+
+const struct name_value *nv_find_name( const struct name_value nv_array[], int value )
+{
+   const struct name_value *nvp ;
+
+   for ( nvp = nv_array ; nvp->name ; nvp++ )
+   {
+      if ( value == nvp->value )
+         return( nvp ) ;
+   }
+   return( NULL ) ;
+}
+
+
+/*
+ * A name-value list is exactly what its name says.
+ * The functions nv_get_name() and nv_get_value() return a pointer to
+ * the entry with the specified value or name respectively.
+ *
+ * The list ends when an antry with a NULL name is encountered.
+ * The value field of that entry is treated in a special manner: if it
+ * is non-zero, it is assumed that there exists one more entry whose
+ * name field will be returned by the nv_get_name function if it can't
+ * find an entry whose value field is equal to its 2nd parameter.
+ * If the value field of the NULL entry is 0, then nv_get_name() will
+ * return NULL.
+ */
+const char *nv_get_name( const struct name_value nv_array[], int value )
+{
+   const struct name_value *nvp ;
+
+   for ( nvp = nv_array ; nvp->name ; nvp++ )
+   {
+      if ( value == nvp->value )
+         return( nvp->name ) ;
+   }
+   return( nvp->value ? (nvp+1)->name : NULL ) ;
+}
+
+
+
+char **argv_alloc( unsigned count )
+{
+   unsigned argv_size = (count + 1) * sizeof( char *) ;
+   char **argv ;
+   const char *func = "new_argv" ;
+
+   argv = (char **) malloc( argv_size ) ;
+   if ( argv == NULL )
+   {
+      out_of_memory( func ) ;
+      return( NULL ) ;
+   }
+   (void) memset( (char *)argv, 0, argv_size ) ;
+   return( argv ) ;
+}
+
+
+/*
+ * If size is 0, the pset holds strings
+ */
+status_e copy_pset( const pset_h from, pset_h *to, unsigned size )
+{
+   unsigned u ;
+   const char *func = "copy_pset" ;
+
+   if ( *to == NULL )
+   {
+      *to = pset_create( pset_count( from ), 0 ) ;
+      if ( *to == NULL )
+      {
+         out_of_memory( func ) ;
+         return( FAILED ) ;
+      }
+   }
+
+   for ( u = 0 ; u < pset_count( from ) ; u++ )
+   {
+      char *p = (char *) pset_pointer( from, u ) ;
+      char *new_s ;
+      
+      if ( size == 0 )
+         new_s = new_string( p ) ;
+      else
+         new_s = (char *)malloc( size ) ;
+
+      if ( new_s == NULL )
+      {
+         out_of_memory( func ) ;
+         return( FAILED ) ;
+      }
+
+      if ( size != 0 )
+         (void) memcpy( new_s, p, size ) ;
+
+      if ( pset_add( *to, new_s ) == NULL )
+      {
+         free( new_s ) ;
+         out_of_memory( func ) ;
+         return( FAILED ) ;
+      }
+   }
+   return( OK ) ;
+}
+
+
+/*
+ * Disassociate from controlling terminal
+ */
+void no_control_tty(void)
+{
+#if !defined(HAVE_SETSID)
+   int fd ;
+   const char *func = "no_control_tty" ;
+
+   if ( ( fd = open( "/dev/tty", O_RDWR ) ) == -1 )
+      msg( LOG_WARNING, func, "open of /dev/tty failed: %m" ) ;
+   else
+   {
+      if ( ioctl( fd, TIOCNOTTY, (caddr_t)0 ) == -1 )
+         msg( LOG_WARNING, func, "ioctl on /dev/tty failed: %m" ) ;
+      (void) Sclose( fd ) ;
+   }
+   (void) setpgrp( getpid(), 0 ) ;
+#else
+   (void) setsid() ;
+#endif
+}
+
+
+/*
+ * Write the whole buffer to the given file descriptor ignoring interrupts
+ */
+status_e write_buf( int fd, const char *buf, int len )
+{
+   int cc, i ;
+
+   for ( i = 0 ; len > 0 ; i += cc, len -= cc )
+   {
+      cc = write( fd, buf+i, len ) ;
+      if ( cc == -1 )
+      {
+         if ( errno != EINTR )
+            return( FAILED ) ;
+         cc = 0 ;
+      }
+   }
+   return( OK ) ;
+}
+
+
+void tabprint( int fd, int tab_level, const char *fmt, ...)
+{
+   va_list ap ;
+   int i ;
+
+   for ( i = 0 ; i < tab_level ; i++ )
+      Sputchar( fd, '\t' ) ;
+
+   va_start( ap, fmt ) ;
+   Sprintv( fd, fmt, ap ) ;
+   va_end( ap ) ;
+}
+
+
+/*
+ * Empty the socket receive buffers of all data.
+ */
+void drain( int sd )
+{
+   char buf[ 256 ] ; /* This size is arbitrarily chosen */
+   int ret ;
+   int old_val ;
+
+   /* Put in non-blocking mode so we don't hang. */
+   old_val = fcntl( sd, F_GETFL, FNDELAY );
+   if ( fcntl( sd, F_SETFL, FNDELAY ) < 0 )
+   {
+      if ( debug.on )
+         msg( LOG_DEBUG, "drain",
+              "UDP socket could not be made non-blocking: %m" ) ;
+      return;
+   }
+
+   do {
+      ret = recv( sd, buf, sizeof( buf ), 0 ) ;
+   } while (ret > 0);
+
+   /* Restore the value since the connection will be freed, not closed. */
+   if (old_val >= 0)
+      fcntl( sd, F_SETFL, old_val );
+
+   if ( debug.on )
+      msg( LOG_DEBUG, "drain", "UDP socket should be empty" ) ;
+}
+
+/*
+ * Convert string to an int detecting errors.
+ */
+int parse_int(const char *str, int base, int term, int *res)
+{
+       char *endptr;
+       long strtol_res;
+
+/* SUSv2 says:
+ * "Because 0, LONG_MIN and LONG_MAX are returned on error and are also
+ * valid returns on success, an application wishing to check for error
+ * situations should set errno to 0, then call strtol(), then check errno." */
+       errno = 0;
+       strtol_res = strtol(str, (char **)&endptr, base);
+
+       if (errno == 0 && *str != NUL) {
+               /* Special case: -1 means allow trailing whitespace */
+               if (term == -1) {
+                       while (*endptr != NUL && isspace(*endptr))
+                               endptr++;
+                       term = NUL;
+               }
+
+               if (*endptr == term) {
+                       *res = strtol_res;
+                       return 0;
+               }
+       }
+
+       *res = 0;
+       return -1;
+}
+
+int parse_uint(const char *str, int base, int term, unsigned int *res)
+{
+       unsigned long long tmp;
+       int ret;
+       ret = parse_ull(str, base, term, &tmp);
+       *res = (unsigned int)tmp;
+       return ret;
+}
+
+int parse_ull(const char *str, int base, int term, unsigned long long *res)
+{
+       char *endptr;
+       unsigned long long strtol_res;
+
+/* SUSv2 says:
+ * "Because 0, LONG_MIN and LONG_MAX are returned on error and are also
+ * valid returns on success, an application wishing to check for error
+ * situations should set errno to 0, then call strtol(), then check errno." */
+       errno = 0;
+       strtol_res = strtoull(str, (char **)&endptr, base);
+
+       if (errno == 0 && *str != NUL) {
+               /* Special case: -1 means allow trailing whitespace */
+               if (term == -1) {
+                       while (*endptr != NUL && isspace(*endptr))
+                               endptr++;
+                       term = NUL;
+               }
+
+               if (*endptr == term) {
+                       *res = strtol_res;
+                       return 0;
+               }
+       }
+
+       *res = 0;
+       return -1;
+}
+
+int parse_ubase10(const char *str, unsigned int *res)
+{
+       return parse_uint(str, 10, -1, res);
+}
+
+int parse_base10(const char *str, int *res)
+{
+       return parse_int(str, 10, -1, res);
+}
+
+bool_int parse_all_digits(const char *ptr)
+{
+       size_t num=0, len = strlen(ptr);
+
+       while (isdigit(*ptr++))
+               num++;
+       if (num == len)
+               return TRUE;
+       else
+               return FALSE;
+}
diff --git a/xinetd/util.h b/xinetd/util.h
new file mode 100644 (file)
index 0000000..f46563d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "pset.h"
+#include "defs.h"
+
+void out_of_memory(const char *func);
+const struct name_value *nv_find_value(const struct name_value nv_array[],const char *name);
+const struct name_value *nv_find_name(const struct name_value nv_array[],int value);
+const char *nv_get_name(const struct name_value nv_array[],int value);
+char **argv_alloc(unsigned count);
+status_e copy_pset(const pset_h from,pset_h *to,unsigned size);
+void no_control_tty(void);
+status_e write_buf(int fd,const char *buf,int len);
+void tabprint(int fd, int tab_level, const char *fmt, ...)
+#ifdef __GNUC__
+        __attribute__ ((format (printf, 3, 4)));
+#else
+ ;
+#endif
+void drain(int sd);
+int parse_int(const char *, int , int , int *);
+int parse_uint(const char *, int , int , unsigned int *);
+int parse_ull(const char *, int , int , unsigned long long *);
+int parse_base10(const char *, int *);
+int parse_ubase10(const char *, unsigned int *);
+bool_int parse_all_digits(const char *ptr);
+
+#endif
diff --git a/xinetd/xconfig.h b/xinetd/xconfig.h
new file mode 100644 (file)
index 0000000..1315656
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * (c) Copyright 1992 by Panagiotis Tsirigotis
+ * (c) Sections Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef XCONFIG_H
+#define XCONFIG_H
+
+/*
+ * $Id: xconfig.h,v 1.1.1.1 2003/02/19 17:29:28 bbraun Exp $
+ */
+
+/*
+ * Deal with stupid Compaq (DEC) Unix problem ...
+ */
+#ifdef __osf__
+#undef DUMP_FILE
+#endif
+
+/*
+ * The purpose of customconf.h is to allow the override of
+ * constants defined in this file. These include all constants that
+ * cannot be overriden from the command line via some option.
+ */
+#ifdef CUSTOMCONF
+#include "customconf.h"
+#endif
+
+
+#define DEFAULT_CONFIG_FILE                    "/etc/xinetd.conf"
+
+/*
+ * This is the facility used by xinetd to log syslog messages
+ */
+#define DEFAULT_SYSLOG_FACILITY        LOG_DAEMON
+
+/*
+ * This is the level used for log messages when a service logs to syslog
+ */
+#define DEFAULT_SERVICE_SYSLOG_LEVEL   LOG_INFO
+
+/*
+ * Max number of concurrently running processes forked to get 
+ * the user id from the remote host
+ */
+#define DEFAULT_LOGPROCS                       15
+
+/*
+ * The loop rate is a bound on the rate of forking servers for a
+ * particular service. If that rate is exceeded, the service is deactivated.
+ */
+#define DEFAULT_LOOP_RATE                      50
+
+/*
+ * The number of seconds to wait before re-enabling a looping service.
+ */
+#define DEFAULT_LOOP_TIME                      10
+
+/*
+ * Signal-to-action mapping
+ */
+#ifndef RECONFIG_HARD_SIG
+#define RECONFIG_HARD_SIG                      SIGHUP
+#endif
+#ifndef OLD_RECONFIG_HARD_SIG
+#define OLD_RECONFIG_HARD_SIG                  SIGUSR2
+#endif
+#ifndef TERMINATION_SIG
+#define TERMINATION_SIG                                SIGTERM
+#endif
+#ifndef STATE_DUMP_SIG
+#define STATE_DUMP_SIG                         SIGUSR1
+#endif
+#ifndef CONSISTENCY_CHECK_SIG
+#define CONSISTENCY_CHECK_SIG                   SIGIOT
+#endif
+#ifndef SERVER_EXIT_SIG
+#define SERVER_EXIT_SIG                                SIGCHLD
+#endif
+#ifndef QUIT_SIG
+#define QUIT_SIG                               SIGQUIT
+#endif
+
+/*
+ * This is the file where the internal state of xinetd is dumped upon 
+ * receipt of STATE_DUMP_SIG
+ */
+#ifndef DUMP_FILE
+#define DUMP_FILE              "/var/run/xinetd.dump"
+#endif
+
+/*
+ * There are 2 timeouts (in seconds) when trying to get the user id from 
+ * the remote host. Any timeout value specified as 0 implies an infinite
+ * timeout.
+ * LOGUSER_SUCCESS_TIMEOUT is the timeout when access control has been passed 
+ * and a new process has been forked to exec the server. 
+ * LOGUSER_FAILURE_TIMEOUT is the timeout when the attempt to access the
+ * service has been rejected.
+ *
+ * Both timeouts should be at least 30 seconds as suggested in RFC 1413
+ * (assuming they are not 'infinite' timeouts).
+ */
+#ifndef LOGUSER_SUCCESS_TIMEOUT
+#define LOGUSER_SUCCESS_TIMEOUT                30
+#endif
+#ifndef LOGUSER_FAILURE_TIMEOUT
+#define LOGUSER_FAILURE_TIMEOUT                30
+#endif
+
+/*
+ * This is used when an instance limit is not specified for a service
+ * and the defaults entry does not specify an instance limit either.
+ * It can be a positive number or "UNLIMITED".
+ */
+#ifndef DEFAULT_INSTANCE_LIMIT
+#define DEFAULT_INSTANCE_LIMIT         UNLIMITED
+#endif
+
+/*
+ * This is the interval (in seconds) over which we check if the service 
+ * loop rate has been exceeded.
+ */
+#ifndef LOOP_INTERVAL
+#define LOOP_INTERVAL                  2
+#endif
+
+/*
+ * LOG_OPEN_FLAGS are the flags used to open a log file (this is used as 
+ * the 3rd argument of open(2))
+ */
+#ifndef LOG_OPEN_FLAGS
+#define LOG_OPEN_FLAGS                 O_CREAT+O_APPEND+O_WRONLY
+#endif
+
+/*
+ * Number of consecutive fork failures that we are willing to put up with
+ * before giving up.
+ */
+#ifndef MAX_FORK_FAILURES
+#define MAX_FORK_FAILURES              5
+#endif
+
+/*
+ * This is the time period during which we will not log subsequest attempts 
+ * to access a datagram-based service from the same bad address after logging 
+ * the first one.
+ * For example, if we receive a datagram at time t from address A which
+ * has a match in the no_access list, we will log the failed attempt and 
+ * during the interval (t, t+DGRAM_IGNORE_TIME) we will not log attempts 
+ * from address A (for the same service).
+ * In this context, the address is defined as (IP address, port number).
+ */
+#ifndef DGRAM_IGNORE_TIME
+#define DGRAM_IGNORE_TIME              60                      /* seconds */
+#endif
+
+#ifndef DUMP_FILE_MODE
+#define DUMP_FILE_MODE                 0644
+#endif
+
+#ifndef LOG_FILE_MODE
+#define LOG_FILE_MODE                  0644
+#endif
+
+/*
+ * The DATAGRAM_SIZE should be big enough for an ethernet packet
+ */
+#ifndef DATAGRAM_SIZE
+#define DATAGRAM_SIZE                  2048
+#endif
+
+/*
+ * Time interval between retry attempts
+ */
+#ifndef RETRY_INTERVAL
+#define RETRY_INTERVAL                 5               /* seconds */
+#endif
+
+/*
+ * LOG_EXTRA_MIN, LOG_EXTRA_MAX define the limits by which the hard limit
+ * on the log size can exceed the soft limit
+ */
+#ifndef LOG_EXTRA_MIN
+#define LOG_EXTRA_MIN                  (  5 * 1024 )
+#endif
+#ifndef LOG_EXTRA_MAX
+#define LOG_EXTRA_MAX                  ( 20 * 1024 )
+#endif
+
+/*
+ * If SENSORS are used and someone trips it, they are added to the
+ * global_no_access table for whatever the configured time is. This
+ * define determines the size of the table to use.
+ */
+#define MAX_GLOBAL_NO_ACCESS      10240
+
+
+#endif /* CONFIG_H */
diff --git a/xinetd/xconv-new.pl b/xinetd/xconv-new.pl
new file mode 100755 (executable)
index 0000000..e890308
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+
+# $RCSid = "$Id: xconv-new.pl,v 1.2 2003/02/27 22:16:54 steveg Exp $";
+
+use strict;
+
+print <DATA>;
+
+while (<>) {
+    next if /^#/ || /^$/;
+    s/\s+$//;
+    my ($service, $socket_type, $protocol, $wait, $user, $server,
+       @server_args) = split;
+
+    my ($cps, $id, $instances, $rpc_version, $type);
+
+    $service =~ s#^tcpmux/\+?##;
+
+    $protocol =~ s#^(tcp.*)/.*#$1#;
+    if ($protocol =~ s#^rpc/##) {
+       print STDERR "Warning: Service $service not added because\n";
+       print STDERR "xinetd does not handle rpc services well\n";
+       next;
+       $type = "RPC";
+       $rpc_version = $1 if $service =~ s#/(.*)##;
+    }
+
+    if ($wait =~ /\.(\d+)/) {                  # [no]wait[.maxcpm]
+       $cps = sprintf("%.f", $1/60);
+    } elsif ($wait =~ m#/(\d+)(/(\d+))?#) {    # [no]wait[/maxchild[/maxcpm]]
+       $instances = $1;
+       $cps = sprintf("%.f", $3/60) if $3;
+    }
+    $wait =~ s/^wait.*/yes/;
+    $wait =~ s/^nowait.*/no/;
+
+    $user =~ s#/.*##;                          # Strip /login-class
+    my $group = $1 if $user =~ s/[.:](.*)//;   # user.group or user:group
+
+    my $flags = "";
+    if ($server =~ m#/tcpd$#) {
+       $flags .= " NAMEINARGS NOLIBWRAP";
+    } else {
+       shift @server_args;
+       if ($server eq "internal") {
+           $type   = "INTERNAL";
+           $id     = "$service-$socket_type";
+           $server = undef;
+       }
+    }
+
+    print "service $service\n";
+    print "{\n";
+    print "\tflags       = $flags\n";
+    print "\trpc_version = $rpc_version\n"     if $rpc_version;
+    print "\tsocket_type = $socket_type\n";
+    print "\tprotocol    = $protocol\n";
+    print "\twait        = $wait\n";
+    print "\tinstances   = $instances\n"       if $instances;
+    print "\tcps         = $cps\n"             if $cps;
+    print "\tuser        = $user\n";
+    print "\tgroup       = $group\n"           if defined $group;
+    print "\ttype        = $type\n"            if $type;
+    print "\tid          = $id\n"              if $id;
+    print "\tserver      = $server\n"          if $server;
+    print "\tserver_args = @server_args\n"     if @server_args;
+    print "}\n\n";
+}
+
+__DATA__
+# This file generated by xconv.pl, included with the xinetd
+# package.  xconv.pl was written by Rob Braun (bbraun@synack.net)
+#
+# The file is merely a translation of your inetd.conf file into
+# the equivalent in xinetd.conf syntax.  xinetd has many
+# features that may not be taken advantage of with this translation.
+# Please refer to the xinetd.conf man page for more information
+# on how to properly configure xinetd.
+
+
+# The defaults section sets some information for all services
+defaults
+{
+       #The maximum number of requests a particular service may handle
+       # at once.
+       instances   = 25
+
+       # The type of logging.  This logs to a file that is specified.
+       # Another option is: SYSLOG syslog_facility [syslog_level]
+       log_type    = FILE /var/log/servicelog
+
+       # What to log when the connection succeeds.
+       # PID logs the pid of the server processing the request.
+       # HOST logs the remote host's ip address.
+       # USERID logs the remote user (using RFC 1413)
+       # EXIT logs the exit status of the server.
+       # DURATION logs the duration of the session.
+       log_on_success = HOST PID
+
+       # What to log when the connection fails.  Same options as above
+       log_on_failure = HOST 
+
+       # The maximum number of connections a specific IP address can
+       # have to a specific service.
+       per_source  = 5
+}
diff --git a/xinetd/xconv.pl b/xinetd/xconv.pl
new file mode 100755 (executable)
index 0000000..cc58868
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+#/*
+# * (c) Copyright 1998-2001 by Rob Braun
+# * All rights reserved.  The file named COPYRIGHT specifies the terms
+# * and conditions for redistribution.
+# */
+
+# $RCSid = "$Id: xconv.pl,v 1.3 2005/03/29 15:50:34 bbraun Exp $";
+
+sub print_header;
+sub print_defaults;
+
+
+print_header;
+print_defaults;
+
+while( <STDIN> ) {
+
+       chomp;
+
+       # Remove comment lines
+       if( grep /^#/, $_ ) {
+               next;
+       }
+
+       @command = split ;
+
+       if( !defined $command[0] ) {
+               next;
+       }
+
+       if( grep /rpc/, $command[2] ) {
+               print STDERR "Warning: Service $command[0] not added because\n";
+               print STDERR "xinetd does not handle rpc services well\n";
+               next;
+       }
+
+       print "service $command[0]\n";
+       print "{\n";
+       print "\tflags       = NAMEINARGS\n";
+       print "\tsocket_type = $command[1]\n";
+       print "\tprotocol    = $command[2]\n";
+       if( grep /no/, $command[3] ) {
+               print "\twait        = no\n";
+       } else {
+               print "\twait        = yes\n";
+       }
+       @user = split /[:\.]/, $command[4];
+       print "\tuser        = $user[0]\n";
+       if( defined $user[1] ) {
+               print "\tgroup       = $user[1]\n";
+       }
+       if( grep /internal/, $command[5] ) {
+               print "\ttype        = INTERNAL\n";
+               print "\tid          = $command[0]-$command[1]\n";
+       } else {
+               print "\tserver      = $command[5]\n";
+               print "\tserver_args = ";
+
+               $i = 6;
+               while( defined $command[$i] ) {
+                       print "$command[$i] ";
+                       $i++;
+               }
+
+               print "\n";
+       }
+       print "}\n";
+       print "\n";
+}
+
+sub print_defaults
+{
+       print "# The defaults section sets some information for all services\n";
+       print "defaults\n";
+       print "{\n";
+       print "\t#The maximum number of requests a particular service may handle\n";
+       print "\t# at once.\n";
+       print "\tinstances   = 25\n";
+       print "\n";
+       print "\t# The type of logging.  This logs to a file that is specified.\n";
+       print "\t# Another option is: SYSLOG syslog_facility [syslog_level]\n";
+       print "\tlog_type    = FILE /var/log/servicelog\n";
+       print "\n";
+       print "\t# What to log when the connection succeeds.\n";
+       print "\t# PID logs the pid of the server processing the request.\n";
+       print "\t# HOST logs the remote host's ip address.\n";
+       print "\t# USERID logs the remote user (using RFC 1413)\n";
+       print "\t# EXIT logs the exit status of the server.\n";
+       print "\t# DURATION logs the duration of the session.\n";
+       print "\tlog_on_success = HOST PID\n";
+       print "\n";
+       print "\t# What to log when the connection fails.  Same options as above\n";
+       print "\tlog_on_failure = HOST\n";
+       print "\n";
+       print "\t# The maximum number of connections a specific IP address can\n";
+       print "\t# have to a specific service.  \n";
+       print "\tper_source  = 5\n";
+
+       print "}\n";
+       print "\n";
+}
+
+sub print_header
+{
+       print "# This file generated by xconv.pl, included with the xinetd\n";
+       print "# package.  xconv.pl was written by Rob Braun (bbraun\@synack.net)\n";
+       print "#\n";
+       print "# The file is merely a translation of your inetd.conf file into\n";
+       print "# the equivalent in xinetd.conf syntax.  xinetd has many \n";
+       print "# features that may not be taken advantage of with this translation.\n";
+       print "# Please refer to the xinetd.conf man page for more information \n";
+       print "# on how to properly configure xinetd.\n";
+       print "\n";
+       print "\n";
+}
diff --git a/xinetd/xconv.pl.8 b/xinetd/xconv.pl.8
new file mode 100644 (file)
index 0000000..4f7d26a
--- /dev/null
@@ -0,0 +1,157 @@
+.\" Automatically generated by Pod::Man v1.3, Pod::Parser v1.13
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sh \" Subsection heading
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  | will give a
+.\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
+.\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
+.\" expand to `' in nroff, nothing in troff, for use with C<>.
+.tr \(*W-|\(bv\*(Tr
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.if \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.\"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.hy 0
+.if n .na
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "XCONV 8"
+.TH XCONV 8 "July 31 2002" " " "xinetd"
+.UC
+.SH "NAME"
+\&\fBxconv.pl\fR \- inetd.conf to xinetd.conf converter
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+xconv.pl can convert existing inetd.conf files (configuration
+for the \fBinetd\fR program) into xinetd.conf files (configuration
+for the \fBxinetd\fR program)
+.SH "USAGE"
+.IX Header "USAGE"
+\&\fBxconv.pl\fR < /etc/inetd.conf > /etc/xinetd.conf
+.SH "DESCRIPTION / PURPOSE"
+.IX Header "DESCRIPTION / PURPOSE"
+\&\fBxconv.pl\fR is provided by the xinetd package to assist in the
+migration from \fBinetd\fR based systems to ones based on \fBxinetd\fR.
+.PP
+Functionality is similar to the \fBitox\fR program, so reading \fIitox\fR\|(8)
+is recommended. An important note here is that \fBxconv.pl\fR does not
+support the \-daemon_dir argument.
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+xconv was written by Rob Braun and xinetd was written by 
+Panagiotis Tsirigotis.
+
diff --git a/xinetd/xgetloadavg.c b/xinetd/xgetloadavg.c
new file mode 100644 (file)
index 0000000..83297d7
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms
+ * and conditions for redistribution.
+ */
+/* This file contains OS dependant implementations of xgetloadavg().
+ * xgetloadavg takes no arguments and simply returns the 1 minute
+ * load average of the machine as a double.
+ * Feel free to add implementations here, please update configure.in
+ * to define HAVE_LOADAVG.  Defining this macro enables the option
+ * in the rest of the code.
+ *    --Rob
+ */
+
+#include "config.h"
+#ifdef HAVE_LOADAVG
+
+#ifdef linux
+#include <stdio.h>
+#include "xgetloadavg.h"
+
+#define LFILE "/proc/loadavg"
+#define MAX 32
+
+double xgetloadavg(void)
+{
+   FILE *fd;
+   double ret = 0;
+
+   fd = fopen(LFILE, "r");
+   if( fd == NULL ) {
+      return -1;
+   }
+
+   if( fscanf(fd, "%lf", &ret) != 1 ) {
+      perror("fscanf");
+      return -1;
+   }
+
+   fclose(fd);
+
+   return ret;
+}
+#endif /* linux */
+
+
+#ifdef solaris
+#ifdef HAVE_KSTAT_H
+#include <kstat.h>
+
+double xgetloadavg(void)
+{
+   kstat_ctl_t *kc = NULL;
+   kstat_t     *ks = NULL;
+   kstat_named_t *kn = NULL;
+
+   kc = kstat_open();
+   if( kc == NULL ) {
+      return -1;
+   }
+
+   ks = kstat_lookup(kc, "unix", 0, "system_misc");
+   if( ks == NULL ) {
+      return -1;
+   }
+
+   if( kstat_read(kc, ks, 0) == -1 ) {
+      return -1;
+   }
+
+   kn = kstat_data_lookup(ks, "avenrun_1min");
+   if( kn == NULL ) {
+      return -1;
+   }
+
+   if( ks->ks_type == KSTAT_TYPE_NAMED ) {
+      kn = ks->ks_data;
+      if( kn == NULL ) {
+         return -1;
+      }
+
+      return (double)(kn->value.ui32)/100;
+   }
+
+   kstat_close(kc);
+}
+#endif /* HAVE_KSTAT */
+#endif /* solaris */
+#ifdef __FreeBSD__
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/fcntl.h>
+
+double xgetloadavg ()
+{
+       double ret[3];
+
+       getloadavg (ret, sizeof (ret) / sizeof (ret[0]));
+
+       return ret[0];
+}
+#endif /* __FreeBSD__ */
+
+
+#if defined(bsdi) || defined(__APPLE__)
+#include <stdlib.h>
+
+double xgetloadavg(void)
+{                  
+   double loadavg[3];
+
+   if (getloadavg(loadavg, 1) == -1)
+   {
+      return -1;
+   }
+   else
+   {
+      return loadavg[0];
+   }
+}
+#endif /* bsdi || __APPLE__ */
+
+
+#ifdef __osf__
+#include <sys/table.h>
+
+double xgetloadavg(void)
+{
+  struct tbl_loadavg labuf;
+
+  if (table(TBL_LOADAVG, 0, &labuf, 1, sizeof(labuf)) < 0) {
+    perror("TBL_LOADAVG");
+    return (-1);
+  }
+
+  if (labuf.tl_lscale) {
+    return ((double)labuf.tl_avenrun.l[2] /
+       (double)labuf.tl_lscale);
+  }
+
+  return (labuf.tl_avenrun.d[2]);
+}
+#endif /* __osf__ */
+
+#endif /* HAVE_LOADAVG */      
+
diff --git a/xinetd/xgetloadavg.h b/xinetd/xgetloadavg.h
new file mode 100644 (file)
index 0000000..77609a5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef XGETLOADAVG_H
+#define XGETLOADAVG_H
+
+
+double xgetloadavg(void);
+
+
+#endif
diff --git a/xinetd/xinetd.conf.man b/xinetd/xinetd.conf.man
new file mode 100644 (file)
index 0000000..a006e48
--- /dev/null
@@ -0,0 +1,1244 @@
+.\"(c) Copyright 1992, by Panagiotis Tsirigotis
+.\"(c) Sections Copyright 1998-2001 by Rob Braun
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: xinetd.conf.man,v 1.18 2005/10/05 17:15:33 bbraun Exp $
+.TH XINETD.CONF 5 "14 June 2001"
+.\" *************************** NAME *********************************
+.SH NAME
+xinetd.conf \- Extended Internet Services Daemon configuration file
+.\" *********************** DESCRIPTION ****************************
+.SH DESCRIPTION
+.B "xinetd.conf"
+is the configuration file that
+determines the services provided by \fBxinetd\fP.
+Any line whose first non-white-space character is a '#' is considered
+a comment line. Empty lines are ignored.
+.LP
+The file contains entries of the form:
+.RS
+.nf
+.ft B
+.sp
+service <service_name>
+{
+.RS
+.ft B
+<attribute> <assign_op> <value> <value> ...
+.I "..."
+.RE
+}
+.ft R
+.fi
+.RE
+.LP
+The assignment operator,
+.I assign_op,
+can be one of 
+.B '=', 
+.B '+=',
+.B '-='.
+The majority of attributes support only the simple assignment operator,
+.B '='.
+Attributes whose value is a set of values support all assignment operators.
+For such attributes,
+.B '+=' 
+means adding a value to the set and 
+.B '-='
+means removing a value from the set.
+A list of these attributes will be given
+after all the attributes are described.
+.LP
+Each entry defines a service identified by the \fIservice_name\fP.
+The following is a list of available attributes:
+.TP 17
+.B id
+This attribute is used to uniquely identify a service.
+This is useful because there exist services that can use different 
+protocols and need to be described with different entries in the
+configuration file.
+By default, the service id is the same as the service name.
+.TP
+.B type
+Any combination of the following values may be used:
+.RS
+.TP 12
+.B RPC
+if this is an RPC service
+.TP
+.B INTERNAL
+if this is a service provided by \fBxinetd\fP.
+.TP
+.B TCPMUX/TCPMUXPLUS
+if this is a service that will be started according to the RFC 1078 protocol on the TCPMUX well-known port. See the section describing TCPMUX services below.
+.TP
+.B UNLISTED
+if this is a service not listed in a standard system file
+(like
+.I /etc/rpc 
+for RPC services, or
+.I /etc/services
+for non-RPC services).
+.RE
+.TP
+.B flags
+Any combination of the following flags may be used:
+.RS
+.TP 12
+.B INTERCEPT
+Intercept packets or accepted connections in order to verify that they
+are coming from acceptable locations (internal or multi-threaded
+services cannot be intercepted).
+.TP
+.B NORETRY
+Avoid retry attempts in case of fork failure.
+.TP
+.B IDONLY
+Accept connections only when the remote end identifies the remote user
+(i.e. the remote host must run an identification server).
+This flag applies only to connection-based services.
+This flag is ineffective if the
+.B USERID
+log option is not used.
+.TP
+.B NAMEINARGS
+This will cause the first argument in "server_args" to be argv[0] when
+executing the server, as specified in "server".  This allows you to use
+tcpd by putting tcpd in "server" and the name of the server in "server_args"
+like in normal inetd.
+.TP
+.B NODELAY
+If the service is a tcp service and the NODELAY flag is set, then the
+TCP_NODELAY flag will be set on the socket.  If the service is not
+a tcp service, this option has no effect.
+.TP
+.B KEEPALIVE
+If the service is a tcp service and the KEEPALIVE flag is set, then 
+the SO_KEEPALIVE socket flag will be set on the socket.  If the service
+is not a tcp service, this option has no effect.
+.TP
+.B NOLIBWRAP
+This disables internal calling of the tcpwrap library to determine access
+to the service.  This may be needed in order to use libwrap functionality
+not available to long-running processes such as xinetd; in this case,
+the tcpd program can be called explicitly (see also the NAMEINARGS flag).
+.TP
+.B SENSOR
+This replaces the service with a sensor that detects accesses to the 
+specified port. NOTE: It will NOT detect stealth scans. This flag 
+should be used only on services that you know you don't need. When an 
+access is made to this service's port, the IP Address is added to a global
+no_access list. This causes all subsequent accesses from the originating IP
+address to be denied access until the deny_time setting expires. The amount
+of time spent on this list is configurable as the deny_time attribute. The
+SENSOR flag will also cause xinetd to consider the server attribute to be
+INTERNAL no matter what is typed on the same line. Another important thing
+to remember is that if the socket_type is set to stream, then the wait 
+attribute should be set to no.
+.TP
+.B IPv4
+Sets the service to be an IPv4 service (AF_INET).
+.TP
+.B IPv6
+Sets the service to be an IPv6 service (AF_INET6), if IPv6 is available on the system.
+.TP
+.B REUSE
+The REUSE flag is deprecated.  All services now implicitly use the REUSE flag.
+.RE
+.TP
+.B disable
+This is boolean "yes" or "no".  This will result in the service
+being disabled and not starting.  See the DISABLE flag description.
+.RE
+.TP
+.B socket_type
+Possible values for this attribute include:
+.RS
+.TP 12
+.I stream
+stream-based service
+.TP
+.I dgram
+datagram-based service
+.TP
+.I raw
+service that requires direct access to IP
+.TP
+.I seqpacket
+service that requires reliable sequential datagram transmission
+.RE
+.TP
+.B protocol
+determines the protocol that is employed by the service.
+The protocol must exist in
+.I /etc/protocols.
+If this
+attribute is not defined, the default protocol employed by the service
+will be used.
+.TP
+.B wait
+This attribute determines if the service is single-threaded or
+multi-threaded and whether or not xinetd accepts the connection or the server
+program accepts the connection. If its value is \fIyes\fP, the service is 
+single-threaded; this means that \fBxinetd\fP will start the server and then 
+it will stop handling requests for the service until the server dies and that
+the server software will accept the connection. If the attribute value is 
+\fIno\fP, the service is multi-threaded and \fBxinetd\fP will keep handling 
+new service requests and xinetd will accept the connection. It should be noted 
+that udp/dgram services normally expect the value to be yes since udp is not
+connection oriented, while tcp/stream servers normally expect the value to be
+no.
+.TP
+.B user
+determines the uid for the server process. The user attribute can either 
+be numeric or a name. If a name is given (recommended),  the user name must 
+exist in
+.I /etc/passwd.
+This attribute is ineffective if the effective user ID 
+of \fBxinetd\fP is not super-user.
+.TP
+.B group
+determines the gid for the server process. The group attribute can either
+be numeric or a name. If a name is given (recommended), the group name must 
+exist in
+.I /etc/group.
+If a group is not specified, the group
+of \fIuser\fP will be used (from 
+.I /etc/passwd).
+This attribute is ineffective if the effective user ID 
+of \fBxinetd\fP is not super-user and if the \fBgroups\fP attribute
+is not set to 'yes'.
+.TP
+.B instances
+determines the number of servers that can be simultaneously active
+for a service (the default is no limit). The value of this
+attribute can be either a number or
+.B UNLIMITED
+which means that there is no limit.
+.TP
+.B nice
+determines the server priority. Its value is a (possibly negative) number;
+check nice(3) for more information.
+.TP
+.B server
+determines the program to execute for this service.
+.TP
+.B server_args
+determines the arguments passed to the server. In contrast to \fBinetd\fP,
+the server name should \fInot\fP be included in \fIserver_args\fP.
+.TP
++.B libwrap
+overrides the service name passed to libwrap (which defaults to the
+server name, the first server_args component with NAMEINARGS, the id
+for internal services and the service name for redirected services).
+This attribute is only valid if xinetd has been configured with the libwrap
+option.
+.TP
+.B only_from
+determines the remote hosts to which the particular
+service is available.
+Its value is a list of IP addresses which can be specified in any
+combination of the following ways:
+.RS
+.TP 5
+.B a)
+a numeric address in the form of %d.%d.%d.%d. If the rightmost components are 
+0, they are treated as wildcards 
+(for example, 128.138.12.0 matches all hosts on the 128.138.12 subnet).
+0.0.0.0 matches all Internet addresses.  IPv6 hosts may be specified in the form of abcd:ef01::2345:6789.  The rightmost rule for IPv4 addresses does not apply to IPv6 addresses.
+.TP
+.B b)
+a factorized address in the form of %d.%d.%d.{%d,%d,...}.
+There is no need for all 4 components (i.e. %d.%d.{%d,%d,...%d} is also ok).
+However, the factorized part must be at the end of the address.  This form does not work for IPv6 hosts.
+.TP
+.B c)
+a network name (from
+.I /etc/networks).  This form does not work for IPv6 hosts.
+.TP
+.B d)
+a host name.  When a connection is made to xinetd, a reverse lookup is
+performed, and the canonical name returned is compared to the specified host
+name.  You may also use domain names in the form of .domain.com.  If the
+reverse lookup of the client's IP is within .domain.com, a match occurs.
+.TP
+.B e)
+an ip address/netmask range in the form of 1.2.3.4/32.  IPv6 address/netmask
+ranges in the form of 1234::/46 are also valid.
+.RE
+.TP
+.B ""
+Specifying this attribute
+without a value makes the service available to nobody.
+.TP
+.B no_access
+determines the remote hosts to which the particular
+service is unavailable. Its value can be specified in the same way as the
+value of the \fBonly_from\fP
+attribute. These two attributes determine the location access control 
+enforced by \fBxinetd\fP. If none of the two is specified for a service,
+the service is available to anyone. If both are specified for a service,
+the one that is the better match for
+the address of the remote host determines
+if the service is available to that host (for example, if the 
+\fBonly_from\fP list contains 128.138.209.0 and the
+\fBno_access\fP list contains 128.138.209.10
+then the host with the address 128.138.209.10 can not access the service).
+.TP
+.B access_times
+determines the time intervals when the service is available. An interval
+has the form \fIhour:min-hour:min\fP (connections 
+.I will 
+be accepted at the bounds of an interval). Hours can range from 0 to 23 and
+minutes from 0 to 59.
+.TP
+.B log_type
+determines where the service log output is sent. There are two formats:
+.RS
+.TP
+.B SYSLOG " \fIsyslog_facility [syslog_level]\fP"
+The log output is sent to syslog at the specified facility. Possible facility
+names include:
+.I daemon,
+.I auth,
+.I authpriv,
+.I user,
+.I mail,
+.I lpr,
+.I news,
+.I uucp,
+.I ftp
+.I "local0-7."
+Possible level names include:
+.I emerg,
+.I alert,
+.I crit,
+.I err,
+.I warning,
+.I notice,
+.I info,
+.I debug.
+If a level is not present, the messages will be recorded at the
+.I info
+level.
+.TP
+.B FILE " \fIfile [soft_limit [hard_limit]]\fP"
+The log output is appended to \fIfile\fP which will be created if it does
+not exist. Two limits on the size of the log file can be optionally specified.
+The first limit is a soft one;
+.B xinetd 
+will log a message the first time this limit is exceeded (if 
+.B xinetd
+logs to syslog, the message will be sent at the 
+.I alert
+priority level).
+The second limit is a hard limit; 
+.B xinetd 
+will stop logging for the affected service (if the log file is a
+common log file, then more than one service may be affected)
+and will log a message about this (if
+.B xinetd
+logs to syslog, the message will be sent at the 
+.I alert
+priority level).
+If a hard limit is not specified, it defaults to the soft limit
+increased by 1% but the extra size must be within the parameters
+.SM LOG_EXTRA_MIN
+and
+.SM LOG_EXTRA_MAX
+which default to 5K and 20K respectively (these constants are defined in 
+\fIxconfig.h\fP).
+.RE
+.TP
+.B log_on_success
+determines what information is logged when a server is started and when
+that server exits (the service id is always included in the log entry).
+Any combination of the following values may be specified:
+.RS
+.TP 12
+.B PID
+logs the server process id (if the service is implemented by \fBxinetd\fP
+without forking another process the logged process id will be 0)
+.TP
+.B HOST
+logs the remote host address
+.TP
+.B USERID
+logs the user id of the remote user using the RFC 1413 identification protocol.
+This option is available only for multi-threaded stream services.
+.TP
+.B EXIT
+logs the fact that a server exited along with the exit status or the
+termination signal
+(the process id is also logged if the
+.B PID
+option is used)
+.TP
+.B DURATION 
+logs the duration of a service session
+.TP
+.B TRAFFIC
+logs the total bytes in and out for a redirected service.
+.RE
+.TP
+.B log_on_failure
+determines what information is logged when a server cannot be started
+(either because of a lack of resources or because of access control
+restrictions). The service id is always included in the log entry along
+with the reason for failure.
+Any combination of the following values may be specified:
+.RS
+.TP 12
+.B HOST
+logs the remote host address.
+.TP
+.B USERID
+logs the user id of the remote user using the RFC 1413 identification protocol.
+This option is available only for multi-threaded stream services.
+.TP 
+.B ATTEMPT
+logs the fact that a failed attempt was made
+(this option is implied by all others).
+.RE
+.TP
+.B rpc_version
+determines the RPC version for a RPC service. The version can be
+a single number or a range in the form \fInumber\fP-\fInumber\fP.
+.TP
+.B rpc_number
+determines the number for an
+.I UNLISTED
+RPC service (this attribute is ignored if the service is not unlisted).
+.TP
+.B env
+The value of this attribute is a list of strings of the form 'name=value'.
+These strings will be added to the environment before
+starting a server (therefore the server's environment will include
+\fBxinetd\fP's environment plus the specified strings).
+.TP
+.B passenv
+The value of this attribute is a list of environment variables from
+\fBxinetd\fP's environment that will be passed to the server.
+An empty list implies passing no variables to the server
+except for those explicitly defined using the
+.I env
+attribute.
+(notice that you can use this attribute in conjunction with the
+.I env
+attribute to specify exactly what environment will be passed to the server).
+.TP
+.B port
+determines the service port. If this attribute is specified for a service 
+listed in
+.I /etc/services,
+it must be equal to the port number listed in that file.
+.TP
+.B redirect
+Allows a tcp service to be redirected to another host.  When xinetd receives
+a tcp connection on this port it spawns a process that establishes a
+connection to the host and port number specified, and forwards all data
+between the two hosts.  This option is useful when your internal machines
+are not visible to the outside world.  Syntax is: redirect = (ip address) 
+(port).  You can also use a hostname instead of the IP address in this
+field.  The hostname lookup is performed only once, when xinetd is 
+started, and the first IP address returned is the one that is used
+until xinetd is restarted.
+The "server" attribute is not required when this option is specified.  If
+the "server" attribute is specified, this attribute takes priority.
+.TP
+.B bind
+Allows a service to be bound to a specific interface on the machine.
+This means you can have a telnet server listening on a local, secured
+interface, and not on the external interface.  Or one port on one interface
+can do something, while the same port on a different interface can do 
+something completely different.  Syntax: bind = (ip address of interface).
+.TP
+.B interface
+Synonym for bind.
+.TP
+.B banner
+Takes the name of a file to be splatted at the remote host when a 
+connection to that service is established.  This banner is printed
+regardless of access control.  It should *always* be printed when
+a connection has been made.  \fBxinetd\fP outputs the file as-is,
+so you must ensure the file is correctly formatted for the service's
+protocol.  In paticular, if the protocol requires CR-LF pairs for line
+termination, you must supply them.
+.TP
+.B banner_success
+Takes the name of a file to be splatted at the remote host when a
+connection to that service is granted.  This banner is printed
+as soon as access is granted for the service.  \fBxinetd\fP outputs the
+file as-is, so you must ensure the file is correctly formatted for
+the service's protocol.  In paticular, if the protocol requires CR-LF
+pairs for line termination, you must supply them.
+.TP
+.B banner_fail
+Takes the name of a file to be splatted at the remote host when a
+connection to that service is denied.  This banner is printed 
+immediately upon denial of access.  This is useful for informing
+your users that they are doing something bad and they shouldn't be
+doing it anymore.  \fBxinetd\fP outputs the file as-is,
+so you must ensure the file is correctly formatted for the service's
+protocol.  In paticular, if the protocol requires CR-LF pairs for line
+termination, you must supply them.
+.TP
+.B per_source
+Takes an integer or "UNLIMITED" as an argument.  This specifies the
+maximum instances of this service per source IP address.  This can
+also be specified in the defaults section.
+.TP
+.B cps
+Limits the rate of incoming connections.  Takes two arguments.  
+The first argument is the number of connections per second to handle.
+If the rate of incoming connections is higher than this, the service
+will be temporarily disabled.  The second argument is the number of
+seconds to wait before re-enabling the service after it has been disabled.
+The default for this setting is 50 incoming connections and the interval
+is 10 seconds.
+.TP
+.B max_load
+Takes a floating point value as the load at which the service will 
+stop accepting connections.  For example: 2 or 2.5.  The service
+will stop accepting connections at this load.  This is the one minute
+load average.  This is an OS dependent feature, and currently only
+Linux, Solaris, and FreeBSD are supported for this.  This feature is
+only avaliable if xinetd was configured with the -with-loadavg option.
+.TP
+.B groups
+Takes either "yes" or "no".  If the groups attribute is set to
+"yes", then the server is executed with access to the groups that the
+server's effective UID has access to.  Alternatively, if the \fBgroup\fP
+attribute is set, the server is executed with access to the groups
+specified.  If the groups attribute is set 
+to "no", then the server runs with no supplementary groups.  This
+attribute must be set to "yes" for many BSD systems.  This attribute
+can be set in the defaults section as well.
+.TP
+.B mdns
+Takes either "yes" or "no".  On systems that support mdns registration
+of services (currently only Mac OS X), this will enable or disable
+registration of the service.  This defaults to "yes".
+.TP
+.B umask
+Sets the inherited umask for the service.  Expects an octal value.  
+This option may be set in the "defaults" section to set a umask
+for all services.  xinetd sets its own umask to the previous umask
+OR'd with 022.  This is the umask that will be inherited by all 
+child processes if the umask option is not used.
+.TP
+.B enabled
+Takes a list of service ID's to enable.  This will enable only the
+services listed as arguments to this attribute; the rest will be
+disabled.  If you have 2 ftp services, you will need to list both of
+their ID's and not just ftp. (ftp is the service name, not the ID. It
+might accidentally be the ID, but you better check.) Note that the 
+service "disable" attribute and "DISABLE" flag can prevent a service 
+from being enabled despite being listed in this attribute. 
+.TP
+.B include
+Takes a filename in the form of "include /etc/xinetd/service".
+The file is then parsed as a new configuration file.  It is not 
+the same thing as pasting the file into xinetd.conf where the 
+include directive is given.  The included file must be in the 
+same form as xinetd.conf.  This may not be specified from within
+a service.  It must be specified outside a service declaration.
+.TP
+.B includedir
+Takes a directory name in the form of "includedir /etc/xinetd.d".
+Every file inside that directory, excluding files with names containing
+a dot ('.') or ending with a tilde ('~'), will be parsed as xinetd 
+configuration files.  The files will be parsed in alphabetical order
+according to the C locale. This allows you to specify services one 
+per file within a directory.  The
+.B includedir
+directive may not be specified from within a service declaration.  
+.TP
+.B rlimit_as
+Sets the Address Space resource limit for the service. One parameter
+is required, which is either a positive integer representing the number
+of bytes to set the limit to (K or M may be used to specify
+kilobytes/megabytes) or "UNLIMITED".  Due to the way Linux's libc malloc
+is implemented, it is more useful to set this limit than rlimit_data,
+rlimit_rss and rlimit_stack. This resource limit is only implemented on
+Linux systems.
+.TP
+.B rlimit_cpu
+Sets the maximum number of CPU seconds that the service may use.
+One parameter is required, which is either a positive integer representing
+the number of CPU seconds limit to, or "UNLIMITED".
+.TP
+.B rlimit_data
+Sets the maximum data size resource limit for the service.
+One parameter is required, which is either a positive integer representing
+the number of bytes or "UNLIMITED".
+.TP
+.B rlimit_rss
+Sets the maximum resident set size limit for the service.  Setting this
+value low will make the process a likely candidate for swapping out to
+disk when memory is low.
+One parameter is required, which is either a positive integer representing
+the number of bytes or "UNLIMITED".
+.TP
+.B rlimit_stack
+Set the maximum stack size limit for the service.
+One parameter is required, which is either a positive integer representing
+the number of bytes or "UNLIMITED".
+.TP
+.B deny_time
+Sets the time span that access to all services on all IP addresses are
+denied to someone that sets off the SENSOR. The unit of time is in minutes.
+Valid options are: FOREVER, NEVER, and a numeric value. FOREVER causes
+the IP address not to be purged until xinetd is restarted. NEVER has the
+effect of just logging the offending IP address. A typical time value would
+be 60 minutes. This should stop most DOS attacks while allowing IP addresses
+that come from a pool to be recycled for legitimate purposes. This option
+must be used in conjunction with the SENSOR flag.
+.LP
+You don't need to specify all of the above attributes for each service.
+The necessary attributes for a service are:
+.sp 1
+.PD .1v
+.RS
+.TP 18
+.B socket_type
+.TP
+.B user
+(non-\fIinternal\fP services only)
+.TP
+.B server
+(non-\fIinternal\fP services only)
+.TP
+.B wait
+.TP
+.B protocol
+(\fIRPC\fP and \fIunlisted\fP services only)
+.TP
+.B rpc_version
+(\fIRPC\fP services only)
+.TP
+.B rpc_number
+(\fIunlisted\fP RPC services only)
+.TP
+.B port
+(\fIunlisted\fP non-RPC services only)
+.RE
+.PD
+.LP
+The following attributes support all assignment operators:
+.sp 1
+.PD .1v
+.RS
+.TP 18
+.B only_from
+.TP
+.B no_access
+.TP
+.B log_on_success
+.TP
+.B log_on_failure
+.TP
+.B passenv
+.TP
+.B env
+(does not support the
+.B '-='
+operator)
+.RE
+.PD
+.LP
+These attributes can also appear more than once in a service entry.
+The remaining attributes support only the 
+.B '='
+operator and can appear at most once in a service entry.
+.LP
+The configuration file may also contain a single defaults entry
+that has the form
+.LP
+.RS
+.nf
+.ft B
+defaults
+{
+.RS
+.ft B
+<attribute> = <value> <value> ...
+.I "..."
+.RE
+.ft B
+}
+.ft R
+.fi
+.RE
+.LP
+This entry provides default attribute values for service entries that
+don't specify those attributes. Possible default attributes:
+.sp 1
+.PD .1v
+.RS
+.TP 18
+.B log_type
+(cumulative effect)
+.TP
+.B bind 
+.TP
+.B per_source 
+.TP
+.B umask 
+.TP
+.B log_on_success
+(cumulative effect)
+.TP
+.B log_on_failure
+(cumulative effect)
+.TP
+.B only_from
+(cumulative effect)
+.TP
+.B no_access
+(cumulative effect)
+.TP
+.B passenv
+(cumulative effect)
+.TP
+.B instances
+.TP
+.B disabled
+(cumulative effect)
+.TP
+.B enabled
+(cumulative effect)
+.TP
+.B banner 
+.TP
+.B banner_success 
+.TP
+.B banner_fail
+.TP
+.B per_source 
+.TP
+.B groups 
+.TP
+.B cps 
+.TP
+.B max_load 
+.TP
+.RE
+.PD
+.LP
+Attributes with a cumulative effect can be specified multiple times
+with the values specified each time accumulating (i.e. '=' does
+the same thing as '+=').
+With the exception of
+.I disabled
+they all have the same meaning as if they were specified in a service entry.
+.I disabled
+determines services that are disabled even if they have entries in
+the configuration file. This allows for quick reconfiguration by
+specifying disabled services with the
+.I disabled
+attribute instead of commenting them out.
+The value of this attribute is a list of space separated service ids.
+.I enabled 
+has the same properties as disabled.  The difference being that
+.I enabled 
+is a list of which services are to be enabled.  If 
+.I enabled 
+is specified, only the services specified are available.  If
+.I enabled 
+is not specified, all services are assumed to be enabled,
+except those listed in 
+.I disabled.
+
+.\" *********************** INTERNAL SERVICES ****************************
+.SH "INTERNAL SERVICES"
+.LP
+\fBxinetd\fP provides the following services internally (both
+stream and datagram based):
+.I echo,
+.I time,
+.I daytime,
+.I chargen,
+and
+.I discard.
+These services are under the same access restrictions as all other
+services except for the ones that don't require \fBxinetd\fP to fork
+another process for them. Those ones (\fItime\fP, \fIdaytime\fP,
+and the datagram-based \fIecho\fP, \fIchargen\fP, and \fIdiscard\fP) 
+have no limitation in the number of 
+.B instances.
+.LP
+.\" *********************** TCPMUX Services ****************************
+.SH "TCPMUX Services"
+.LP
+\fBxinetd\fP supports TCPMUX services that conform to RFC 1078. These services 
+may not have a well-known port associated with them, and can be accessed via 
+the TCPMUX well-known port.
+.LP
+For each service that is to be accessed via TCPMUX, a service entry in
+\fB/etc/xinetd.conf\fP or in a configuration file in an \fBincludedir\fP 
+directory must exist.
+.LP
+The \fIservice_name\fP field (as defined above for each service in any 
+\fBxinetd\fP 
+configuration file) must be identical to the string that is passed (according 
+to RFC 1078 protocol) to \fBxinetd\fP when the remote service requestor first 
+makes the connection on the TCPMUX well-known port.  Private protocols should 
+use a service name that has a high probability of being unique. One way is to 
+prepend the service name with some form of organization ID.
+.LP
+The \fItype\fP field can be either \fBTCPMUX\fP or \fBTCPMUXPLUS\fP. If the
+type is \fBTCPMUXPLUS\fP, \fBxinetd\fP will handle the initial protocol
+handshake (as defined in RFC 1078) with the calling process before initiating
+the service. If the type is \fBTCPMUX\fP, the server that is started is
+responsible for performing the handshake.
+.LP
+The \fItype\fP field should also include \fBUNLISTED\fP if the service is
+not listed in a standard system file
+(like
+.I /etc/rpc
+for RPC services, or
+.I /etc/services
+for non-RPC services).
+.LP    
+The \fIsocket_type\fP for these services must be \fBstream\fP, and the 
+\fIprotocol\fP must be \fBtcp\fP.
+.LP
+Following is a sample TCPMUX service configuration:
+.PD .1v
+.RS
+.nf
+
+service myorg_server
+{
+.RS
+.IP disable 20
+= no
+.IP type
+= TCPMUX
+.IP socket_type
+= stream
+.IP protocol
+= tcp
+.IP wait
+= no
+.IP user
+= root
+.IP server
+= /usr/etc/my_server_exec
+.RE
+}
+.fi
+.RE
+.PD
+.LP
+Besides a service entry for each service that can be accessed
+via the TCPMUX well-known port, a service entry for TCPMUX itself
+must also be included in the \fBxinetd\fP configuration. Consider the following
+sample:
+.PD .1v
+.RS
+.nf
+
+service tcpmux
+{
+.RS
+.IP type 20
+= INTERNAL
+.IP id
+= tcpmux
+.IP socket_type
+= stream
+.IP protocol
+= tcp
+.IP user
+= root
+.IP wait
+= no
+.RE
+}
+.fi
+.RE
+.PD                                                                               
+
+
+
+.\" *********************** NOTES ****************************
+.SH NOTES
+.IP 1. 4
+The following service attributes \fIcannot\fP be changed on reconfiguration:
+.B socket_type,
+.B wait,
+.B protocol,
+.B type.
+.IP 2.
+When the attributes
+.I only_from
+and
+.I no_access
+are not specified for a service (either directly or via \fIdefaults\fP)
+the address check is considered successful (i.e. access will not be
+denied).
+.IP 3.
+The address check is based on the IP address of the remote host and
+not on its domain address. We do this so that we can avoid
+remote name lookups which may take a long time (since
+.B xinetd
+is single-threaded, a name lookup will prevent the daemon from
+accepting any other requests until the lookup is resolved).
+The down side of this scheme is that if the IP address of a remote
+host changes, then access to that host may be denied until
+.B xinetd
+is reconfigured.
+Whether access is actually denied or not will depend on whether the
+new host IP address is among those allowed access. For example, if
+the IP address of a host changes from 1.2.3.4 to 1.2.3.5 and 
+only_from is specified as 1.2.3.0 then access will not be denied.
+.IP 4.
+If the
+.B USERID
+log option is specified and the remote host either does not run an 
+identification server or the server sends back a bad reply,
+access will not be denied unless the
+.I IDONLY
+service flag is used.
+.IP 5.
+Interception works by forking a process which acts as a filter
+between the remote host(s) and the local server. 
+This obviously has a performance impact so
+it is up to you to make the compromise between security and performance
+for each service.
+The following tables show the overhead of interception.
+The first table shows the time overhead-per-datagram for a UDP-based service
+using various datagram sizes.
+For TCP-based services we measured the bandwidth reduction 
+because of interception while sending
+a certain amount of data from client to server (the time overhead should
+the same as for UDP-based services but it is "paid" only by the first
+packet of a continuous data transmission).
+The amount of data is given
+in the table as \fIsystem_calls\fPx\fIdata_sent_per_call\fP, i.e.
+each
+.I "send(2)"
+system call transferred so many bytes of data. 
+The bandwidth reduction is given in terms of bytes per second and as
+a percentage of the bandwidth when interception is not performed.
+All measurements were done on a SparcStation IPC running SunOS 4.1.
+.sp 1
+.RS
+.RS
+.PD .1v
+.TP 25
+Datagram size (bytes)
+Latency (msec)
+.TP
+---------------------
+--------------
+.TP
+64
+1.19
+.TP
+256
+1.51
+.TP
+1024
+1.51
+.TP
+4096
+3.58
+.sp 2
+.TP
+Bytes sent
+Bandwidth reduction
+.TP
+----------
+-------------------
+.TP
+10000x64
+941 (1.2%)
+.TP
+10000x256
+4,231 (1.8%)
+.TP
+10000x1024
+319,300 (39.5%)
+.TP
+10000x4096
+824,461 (62.1%)
+.RE
+.RE
+.sp 1
+.\" *********************** EXAMPLE ****************************
+.SH EXAMPLE
+.LP
+.PD .1v
+.RS
+.nf
+#
+# Sample configuration file for xinetd
+#
+
+defaults
+{
+.RS
+.IP log_type 20
+= FILE /var/log/servicelog
+.IP log_on_success
+= PID
+.IP log_on_failure 
+= HOST 
+.IP only_from
+= 128.138.193.0 128.138.204.0 
+.IP only_from
+= 128.138.252.1 
+.IP instances
+= 10
+.IP disabled
+= rstatd
+.RE
+}
+
+#
+# Note 1: the protocol attribute is not required
+# Note 2: the instances attribute overrides the default
+#
+service login
+{
+.RS
+.IP socket_type 20
+= stream
+.IP protocol
+= tcp
+.IP wait
+= no
+.IP user
+= root
+.IP server
+= /usr/etc/in.rlogind
+.IP instances
+= UNLIMITED
+.RE
+}
+
+#
+# Note 1: the instances attribute overrides the default
+# Note 2: the log_on_success flags are augmented
+#
+service shell
+{
+.RS
+.IP socket_type 20
+= stream
+.IP wait
+= no
+.IP user
+= root
+.IP instances
+= UNLIMITED
+.IP server
+= /usr/etc/in.rshd
+.IP log_on_success
++= HOST 
+.RE
+}
+
+service ftp
+{
+.RS
+.IP socket_type 20
+= stream
+.IP wait
+= no
+.IP nice
+= 10
+.IP user
+= root
+.IP server
+= /usr/etc/in.ftpd
+.IP server_args
+= -l
+.IP instances
+= 4
+.IP log_on_success
++= DURATION HOST USERID
+.IP access_times
+= 2:00-9:00 12:00-24:00
+.RE
+}
+
+# Limit telnet sessions to 8 Mbytes of memory and a total
+# 20 CPU seconds for child processes.
+service telnet
+{
+.RS
+.IP socket_type 20
+= stream
+.IP wait
+= no
+.IP nice
+= 10
+.IP user
+= root
+.IP server
+= /usr/etc/in.telnetd
+.IP rlimit_as
+= 8M
+.IP rlimit_cpu
+= 20
+.RE
+}
+
+#
+# This entry and the next one specify internal services. Since
+# this is the same service using a different socket type, the
+# id attribute is used to uniquely identify each entry
+#
+service echo
+{
+.RS
+.IP id 20
+= echo-stream
+.IP type
+= INTERNAL
+.IP socket_type
+= stream
+.IP user
+= root
+.IP wait
+= no
+.RE
+}
+
+service echo
+{
+.RS
+.IP id 20
+= echo-dgram
+.IP type
+= INTERNAL
+.IP socket_type
+= dgram
+.IP user
+= root
+.IP wait
+= no
+.RE
+}
+
+#
+# Sample RPC service
+#
+service rstatd
+{
+.RS
+.IP type 20
+= RPC
+.IP socket_type
+= dgram
+.IP protocol
+= udp
+.IP server
+= /usr/etc/rpc.rstatd
+.IP wait
+= yes
+.IP user
+= root
+.IP rpc_version
+= 2-4
+.IP env
+= LD_LIBRARY_PATH=/etc/securelib
+.RE
+}
+
+#
+# Sample unlisted service
+#
+service unlisted
+{
+.RS
+.IP type 20
+= UNLISTED
+.IP socket_type
+= stream
+.IP protocol
+= tcp
+.IP wait
+= no
+.IP server
+= /home/user/some_server
+.IP port
+= 20020
+.RE
+}
+.RE
+.PD
+.\" *********************** SEE ALSO ****************************
+.SH "SEE ALSO"
+.I "xinetd(1L),"
+.LP
+.I "xinetd.log(5)"
+.LP
+Postel J.,
+.IR "Echo Protocol" ,
+RFC 862,
+May 1983
+.LP
+Postel J.,
+.IR "Discard Protocol" ,
+RFC 863,
+May 1983
+.LP
+Postel J.,
+.IR "Character Generator Protocol" ,
+RFC 864,
+May 1983
+.LP
+Postel J.,
+.IR "Daytime Protocol" ,
+RFC 867,
+May 1983
+.LP
+Postel J., Harrenstien K.,
+.IR "Time Protocol" ,
+RFC 868,
+May 1983
+.LP
+M. Lottor,
+.IR "TCP Port Service Multiplexer (TCPMUX)" ,
+RFC 1078
+Nov 1988
+.LP
+StJohns M.,
+.IR " Identification Protocol" ,
+RFC 1413,
+February 1993
+.\" *********************** BUGS ****************************
+.SH BUGS
+.LP
+If the
+.B INTERCEPT
+flag is not used,
+access control on the address of the remote host is not performed when
+\fIwait\fP is \fIyes\fP and \fIsocket_type\fP is \fIstream\fP.
+.LP
+If the 
+.B INTERCEPT
+flag is not used,
+access control on the address of the remote host for
+services where \fIwait\fP is \fIyes\fP and \fIsocket_type\fP is \fIdgram\fP
+is performed only on the first packet. The server may then accept packets
+from hosts not in the access control list. This can happen with 
+.B RPC
+services.
+.LP
+There is no way to put a
+.SM SPACE
+in an environment variable.
+.LP
+When \fIwait\fP is \fIyes\fP and \fIsocket_type\fP is \fIstream\fP,
+the socket passed to the server can only accept connections.
+.LP
+The
+.B INTERCEPT
+flag is not supported for internal services or multi-threaded services.
diff --git a/xinetd/xinetd.log.man b/xinetd/xinetd.log.man
new file mode 100644 (file)
index 0000000..5babc7f
--- /dev/null
@@ -0,0 +1,153 @@
+.\"(c) Copyright 1992 by Panagiotis Tsirigotis
+.\"(c) Sections Copyright 1998-2001 by Rob Braun
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: xinetd.log.man,v 1.3 2003/02/27 22:15:13 steveg Exp $
+.TH XINETD.LOG 5 "28 April 1993"
+.SH NAME
+xinetd.log \- xinetd service log format
+.\" *********************** DESCRIPTION ****************************
+.SH "DESCRIPTION"
+A service configuration may specify various degrees of logging when
+attempts are made to access the service. When logging for a service
+is enabled,
+.B xinetd
+will generate one-line log entries which have the following format
+(all entries have a timestamp as a prefix):
+.sp 1
+.RS
+\fIentry\fP: \fIservice-id\fP \fIdata\fP
+.RE
+.LP
+The \fIdata\fP depends on the \fIentry\fP.
+Possible \fIentry\fP types include:
+.RS
+.TP 12
+.B START
+generated when a server is started
+.TP
+.B EXIT
+generated when a server exits
+.TP
+.B FAIL
+generated when it is not possible to start a server
+.TP
+.B USERID
+generated if the \fIUSERID\fP log option is used.
+.TP
+.B NOID
+generated if the 
+.I USERID
+log option is used,
+and the 
+.I IDONLY
+service flag is used,
+and the remote end does not identify who is trying to access the service.
+.RE
+.LP
+In the following, the information enclosed in brackets appears 
+if the appropriate log option is used.
+.LP
+A \fISTART\fP entry has the format:
+.sp 1
+.RS
+START: \fIservice-id\fP [pid=%d] [from=%d.%d.%d.%d]
+.RE
+.LP
+An \fIEXIT\fP entry has the format:
+.sp 1
+.RS
+EXIT: \fIservice-id\fP [\fItype\fP=%d] [pid=%d] [duration=%d(sec)]
+.RE
+.sp 1
+.I type
+can be either
+.B status
+or
+.B signal.
+The number is either the exit status or the signal that caused process
+termination.
+.LP
+A \fIFAIL\fP entry has the format:
+.sp 1
+.RS
+FAIL: \fIservice-id\fP \fIreason\fP [from=%d.%d.%d.%d]
+.RE
+.sp 1
+Possible \fIreasons\fP are:
+.RS
+.TP 15
+.B fork
+a certain number of consecutive fork attempts failed (this number is
+a configurable parameter)
+.TP
+.B time
+the time check failed
+.TP
+.B address
+the address check failed
+.TP
+.B service_limit
+the allowed number of server instances for this service would be exceeded
+.TP
+.B process_limit
+a limit on the number of forked processes was specified and it would 
+be exceeded
+.RE
+.LP
+A \fIDATA\fP entry has the format:
+.sp 1
+.RS
+DATA: \fIservice-id\fP \fIdata\fP
+.RE
+.sp 1
+The \fIdata\fP logged depends on the service.
+.RS
+.TP 12
+.B login
+remote_user=%s local_user=%s tty=%s
+.TP
+.B exec
+remote_user=%s verify=\fIstatus\fP command=%s
+.br
+Possible
+.I status
+values:
+.RS
+.TP 10
+.I ok
+the password was correct
+.TP
+.I failed
+the password was incorrect
+.TP
+.I baduser
+no such user
+.RE
+.TP
+.B shell
+remote_user=%s local_user=%s command=%s
+.TP
+.B finger
+\fIreceived string\fP or
+.I EMPTY-LINE
+.RE
+.LP
+A \fIUSERID\fP entry has the format:
+.sp 1
+.RS
+USERID: \fIservice-id\fP \fItext\fP
+.RE
+.sp 1
+The \fItext\fP is the response of the identification daemon at the remote end
+excluding the port numbers (which are included in the response).
+.LP
+A \fINOID\fP entry has the format:
+.sp 1
+.RS
+NOID: \fIservice-id\fP \fIIP-address\fP \fIreason\fP 
+.RE
+.\" *********************** SEE ALSO ****************************
+.SH "SEE ALSO"
+.BR xinetd "(1L), " xinetd.conf (5)
diff --git a/xinetd/xinetd.man b/xinetd/xinetd.man
new file mode 100644 (file)
index 0000000..d52c2cc
--- /dev/null
@@ -0,0 +1,194 @@
+.\"(c) Copyright 1992 by Panagiotis Tsirigotis
+.\"(c) Sections Copyright 1998-2001 by Rob Braun
+.\"All rights reserved.  The file named COPYRIGHT specifies the terms 
+.\"and conditions for redistribution.
+.\"
+.\" $Id: xinetd.man,v 1.3 2003/05/30 15:10:57 steveg Exp $
+.TH XINETD 8 "14 June 2001"
+.\" *************************** NAME *********************************
+.SH NAME
+xinetd \- the extended Internet services daemon
+.\" *************************** SYNOPSIS *********************************
+.SH SYNOPSIS
+.B xinetd
+[\fIoptions\fP]
+.\" *************************** DESCRIPTION *********************************
+.SH DESCRIPTION
+\fBxinetd\fP performs the same function as \fBinetd\fP: it starts
+programs that provide Internet services.  Instead of having such
+servers started at system initialization time, and be dormant until a
+connection request arrives, \fBxinetd\fP is the only daemon process
+started and it listens on all service ports for the services listed in
+its configuration file. When a request comes in, \fBxinetd\fP starts
+the appropriate server.  Because of the way it operates, \fBxinetd\fP
+(as well as \fBinetd\fP) is also referred to as a super-server.
+.LP
+The services listed in \fBxinetd\fP's configuration file can be
+separated into two groups.  Services in the first group are called
+.I "multi-threaded"
+and they require the forking of a new server process for each new
+connection request.  The new server then handles that connection.  For
+such services, \fBxinetd\fP keeps listening for new requests so that it
+can spawn new servers.  On the other hand, the second group includes
+services for which the service daemon is responsible for handling all
+new connection requests.  Such services are called
+.I "single-threaded"
+and \fBxinetd\fP will stop handling new requests for them until the
+server dies.  Services in this group are usually datagram-based.
+.LP
+So far, the only reason for the existence of a super-server was to
+conserve system resources by avoiding to fork a lot of processes which
+might be dormant for most of their lifetime.  While fulfilling this
+function, \fBxinetd\fP takes advantage of the idea of a super-server to
+provide features such as access control and logging.  Furthermore,
+\fBxinetd\fP is not limited to services listed in
+.I /etc/services.
+Therefore, anybody can use \fBxinetd\fP to start special-purpose
+servers.
+.\" *************************** OPTIONS *********************************
+.SH OPTIONS
+.TP
+.BR \-d
+Enables debug mode. This produces a lot of debugging output, and it
+makes it possible to use a debugger on \fBxinetd\fP.
+.TP
+.BI \-syslog " syslog_facility"
+This option enables syslog logging of \fBxinetd\fP-produced messages
+using the specified syslog facility.
+The following facility names are supported:
+.I daemon,
+.I auth,
+.I user,
+.I "local[0-7]"
+(check \fIsyslog.conf(5)\fP for their meanings).
+This option is ineffective in debug mode since all relevant messages are sent
+to the terminal.
+.TP
+.BI \-filelog " logfile"
+\fBxinetd\fP-produced messages will be placed in the specified file.
+Messages are always appended to the file.
+If the file does not exist, it will be created.
+This option is ineffective in debug mode since all relevant messages are sent
+to the terminal.
+.TP
+.BI \-f " config_file"
+Determines the file that \fBxinetd\fP uses for configuration. The
+default is \fI/etc/xinetd.conf\fP.
+.TP
+.BR \-pidfile " pid_file"
+.br
+The process ID is written to the file. This option is ineffective in debug mode. 
+.TP
+.BI \-dontfork 
+Tells xinetd to stay in the foreground rather than detaching itself, to
+support being run from init or daemontools. This option automatically sets 
+.B \-stayalive
+(see below).
+.TP
+.BI \-stayalive 
+Tells xinetd to stay running even if no services are specified.
+.TP
+.BI \-limit " proc_limit"
+This option places a limit on the number of concurrently running processes
+that can be started by
+.B xinetd.
+Its purpose is to prevent process table overflows.
+.TP
+.BI \-logprocs " limit"
+This option places a limit on the number of concurrently running servers
+for remote userid acquisition.
+.TP
+.BI \-version
+This option causes xinetd to print out its version information.
+.TP
+.BI \-inetd_compat
+This option causes xinetd to read /etc/inetd.conf in addition to the
+standard xinetd config files.  /etc/inetd.conf is read after the
+standard xinetd config files.
+.TP
+.BI \-cc " interval"
+This option instructs
+.B xinetd
+to perform periodic consistency checks on its internal state every
+.I interval
+seconds.
+.LP
+The \fIsyslog\fP and \fIfilelog\fP options are mutually exclusive.
+If none is specified, the default is syslog using the
+.I daemon
+facility.
+You should not confuse \fBxinetd\fP messages with messages related to
+service logging. The latter are logged only if this is specified
+via the configuration file.
+.\" *********************** CONTROLLING XINETD ****************************
+.SH "CONTROLLING XINETD"
+.LP
+\fBxinetd\fP performs certain actions when it receives certain signals.
+The actions associated with the specific signals can be redefined
+by editing \fIconfig.h\fP and recompiling.
+.TP 15
+.B SIGHUP
+causes a hard reconfiguration, which means that \fBxinetd\fP re-reads 
+the configuration file and terminates the servers for services that 
+are no longer available. Access control is performed again on 
+running servers by checking the remote location, access times and 
+server instances. If the number of server instances is lowered, some 
+arbitrarily picked servers will be killed to satisfy the limit; this 
+will happen \fIafter\fP any servers are terminated because of failing 
+the remote location or access time checks.
+Also, if the
+.B INTERCEPT
+flag was clear and is set, any running servers for that service will
+be terminated;
+\fIthe purpose of this is to ensure that after a hard reconfiguration
+there will be no running servers that can accept packets from addresses
+that do not meet the access control criteria\fP.
+.TP
+.B SIGQUIT
+causes program termination.
+.TP
+.B SIGTERM
+terminates all running servers before terminating \fBxinetd\fP.
+.TP
+.B SIGUSR1
+causes an internal state dump (the default dump file is
+\fI/var/run/xinetd.dump\fP;
+to change the filename, edit \fIconfig.h\fP and recompile).
+.TP
+.B SIGIOT
+causes an internal consistency check to verify that the data structures
+used by the program have not been corrupted.
+When the check is completed
+.B xinetd
+will generate a message that says if the check was successful or not.
+.LP
+On reconfiguration the log files are closed and reopened. This allows
+removal of old log files.
+.\" *********************** FILES ****************************
+.SH FILES
+.LP
+.PD .1v
+.TP 20
+.B /etc/xinetd.conf
+default configuration file
+.TP
+.B /var/run/xinetd.dump
+default dump file
+.PD
+.\" *********************** SEE ALSO ****************************
+.SH "SEE ALSO"
+.I "inetd(8),"
+.LP
+.I "xinetd.conf(5),"
+.LP
+.I "xinetd.log(5)"
+.LP
+.I "http://cr.yp.to/daemontools.html"
+.\" *********************** AUTHOR ****************************
+.SH AUTHOR
+Panos Tsirigotis, CS Dept, University of Colorado, Boulder
+Rob Braun
+.\" *********************** PRONUNCIATION ****************************
+.SH PRONUNCIATION
+zy-net-d
+
diff --git a/xinetd/xmdns.c b/xinetd/xmdns.c
new file mode 100644 (file)
index 0000000..59acf11
--- /dev/null
@@ -0,0 +1,147 @@
+#include "config.h"
+#ifdef HAVE_MDNS
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "state.h"
+#include "service.h"
+#include "server.h"
+#include "sconf.h"
+#include "pset.h"
+
+#ifdef HAVE_DNSREGISTRATION
+#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
+#endif
+
+#ifdef HAVE_HOWL
+#include <howl.h>
+#endif
+
+extern struct program_state ps ;
+
+#ifdef HAVE_DNSREGISTRATION
+static void mdns_callback(DNSServiceRegistrationReplyErrorType err, void *d)
+{
+   return;
+}
+#endif
+
+#ifdef HAVE_HOWL
+static sw_result howl_callback(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_publish_status status, sw_opaque extra) {
+   if( debug.on ) {
+      const char *name = NULL;
+      unsigned u;
+      for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) {
+         struct service *sp;
+         struct service_config *scp;
+   
+         sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
+         scp = SVC_CONF(sp);
+         if( scp->mdns_state && (*(sw_discovery_oid *)scp->mdns_state == oid) ) {
+            name = SC_ID(scp);
+            break;
+         }
+      }
+      msg(LOG_DEBUG, "howl_callback", "callback status: %d for service %s (oid: %d)", status, name, oid);
+   }
+   return SW_OKAY;
+}
+#endif
+
+int xinetd_mdns_deregister(struct service_config *scp) {
+   if( (!scp) || (scp->mdns_state == NULL) )
+      return 0;
+
+   if( debug.on )
+      msg(LOG_DEBUG, "xinetd_mdns_deregister", "Deregistering service: %s", SC_ID(scp));
+
+#ifdef HAVE_DNSREGISTRATION
+   DNSServiceDiscoveryDeallocate(  (dns_service_discovery_ref)scp->mdns_state );
+   return 0;
+#endif
+
+#ifdef HAVE_HOWL
+   if( !ps.rws.mdns_state ) return 0;
+   if( sw_discovery_cancel(*(sw_discovery *)ps.rws.mdns_state, *(sw_discovery_oid *)scp->mdns_state) != SW_OKAY )
+      return -1;
+   return 0;
+#endif
+}
+
+int xinetd_mdns_register(struct service_config *scp) {
+   if( ps.rws.mdns_state == NULL )
+      return -1;
+   xinetd_mdns_deregister(scp);
+
+   if( SC_MDNS_NAME(scp) )
+      free(SC_MDNS_NAME(scp));
+   if( asprintf(&SC_MDNS_NAME(scp), "_%s._%s", SC_NAME(scp), SC_PROTONAME(scp)) < 0 )
+       return -1;
+
+   if( debug.on )
+      msg(LOG_DEBUG, "xinetd_mdns_register", "Registering service: %s (%s)", SC_MDNS_NAME(scp), SC_ID(scp));
+
+#ifdef HAVE_DNSREGISTRATION
+   scp->mdns_state = DNSServiceRegistrationCreate("", SC_MDNS_NAME(scp), "", htons(SC_PORT(scp)), "", mdns_callback, NULL);
+#endif
+
+#ifdef HAVE_HOWL
+   sw_discovery_publish(*(sw_discovery *)ps.rws.mdns_state, 0, SC_ID(scp), SC_MDNS_NAME(scp), NULL, NULL, SC_PORT(scp), NULL, 0, howl_callback, NULL, (sw_discovery_oid *)scp->mdns_state);
+   return 0;
+#endif
+
+   return 0;
+}
+
+int xinetd_mdns_init(void) {
+#ifdef HAVE_DNSREGISTRATION
+   ps.rws.mdns_state = (char *)1;
+   return 0;
+#endif
+
+#ifdef HAVE_HOWL
+   ps.rws.mdns_state = malloc(sizeof(sw_discovery));
+   if( !ps.rws.mdns_state )
+      return -1;
+   if( sw_discovery_init(ps.rws.mdns_state) != SW_OKAY ) {
+      free(ps.rws.mdns_state);
+      ps.rws.mdns_state = NULL;
+      return -1;
+   }
+   FD_SET( sw_discovery_socket(*(sw_discovery *)ps.rws.mdns_state), &ps.rws.socket_mask ) ;
+   return 0;
+#endif
+}
+
+int xinetd_mdns_svc_init(struct service_config *scp) {
+#ifdef HAVE_DNSREGISTRATION
+//   scp->mdns_state = malloc(sizeof(dns_service_discovery_ref));
+#endif
+
+#ifdef HAVE_HOWL
+   scp->mdns_state = malloc(sizeof(sw_discovery_oid));
+#endif
+
+   if( !scp->mdns_state )
+      return -1;
+   return 0;
+}
+
+int xinetd_mdns_svc_free(struct service_config *scp) {
+#ifndef HAVE_DNSREGISTRATION
+   if(scp->mdns_state)
+      free(scp->mdns_state);
+   scp->mdns_state = NULL;
+#endif
+   return 0;
+}
+
+int xinetd_mdns_poll(void) {
+#ifdef HAVE_HOWL
+   if( sw_discovery_read_socket(*(sw_discovery *)ps.rws.mdns_state) == SW_OKAY )
+      return 0;
+#endif
+   return -1;
+}
+#endif /* HAVE_MDNS */
diff --git a/xinetd/xmdns.h b/xinetd/xmdns.h
new file mode 100644 (file)
index 0000000..6eff1ec
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _XMDNS_H_
+#define _XMDNS_H_
+#include "sconf.h"
+
+int xinetd_mdns_deregister(struct service_config *scp) ;
+int xinetd_mdns_register(struct service_config *scp) ;
+int xinetd_mdns_init(void) ;
+int xinetd_mdns_svc_init(struct service_config *scp) ;
+int xinetd_mdns_svc_free(struct service_config *scp) ;
+int xinetd_mdns_poll(void) ;
+
+#endif /* _XMDNS_H_ */
diff --git a/xinetd/xtimer.c b/xinetd/xtimer.c
new file mode 100644 (file)
index 0000000..2a0c753
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#include <time.h>
+
+#include "config.h"
+#include "xtimer.h"
+#include "pset.h"
+#include "msg.h"
+
+/* A note on the usage of timers in these functions:
+ * The timers are composed of 3 elements, a pointer to a callback function,
+ * the expire time of the timer, and a unique (pseudo-monotomically increasing)
+ * identifier for the timer.
+ * Timers are kept in a pset_h (linked list) and are sorted at insertion
+ * time, with the nearest expire time first.  The sort at insertion is to
+ * avoid examining non-expired timers in the xtimer_poll() function, and
+ * to be able to easily retrieve the next expiring timer.  
+ * The timers are set in the main event loop, using select() as the
+ * timing device.  select() sleeps until the next timer is set to expire
+ * (or until an FD is ready, in which case it also examines the timer list).
+ */
+
+static pset_h xtimer_list = NULL;
+
+static int xtimer_init( void )
+{
+       if( xtimer_list != NULL )
+               return 0;
+
+       xtimer_list = pset_create( 0, 0 );
+       if( xtimer_list == NULL ) 
+               return -1;
+
+       return 0;
+}
+
+static int xtimer_compfunc( const void *_a, const void *_b )
+{
+       xtime_h **a = (xtime_h **)_a;
+       xtime_h **b = (xtime_h **)_b;
+       return ((*a)->when - (*b)->when);
+}
+
+/* xtimer_add:
+ * Adds a timer to the pset_h of timers, and sorts the timer list (least time
+ * remaining first).
+ * Return values:
+ * Success: the timer ID which can be used to later remove the timer (>0)
+ * Failure: -1
+ */
+int xtimer_add( void (*func)(void), time_t secs )
+{
+       xtime_h *new_xtimer = NULL;
+       time_t tmptime;
+       unsigned count;
+
+       if( xtimer_list == NULL ) {
+               if( xtimer_init() < 0 )
+                       return -1;
+       }
+
+       new_xtimer = (xtime_h *)malloc(sizeof(xtime_h));
+       if( new_xtimer == NULL ) {
+               return -1;
+       }
+
+       tmptime = time(NULL);
+       if( tmptime == -1 ) {
+               free( new_xtimer );
+               return -1;
+       }
+       
+       new_xtimer->timerfunc = func;
+       new_xtimer->when =  tmptime + secs;
+
+       if( (count = pset_count( xtimer_list )) == 0 ) {
+          new_xtimer->xtid = 1;
+       } else {
+          new_xtimer->xtid = ((xtime_h *)(pset_pointer(xtimer_list, count-1)))->xtid + 1;
+       }
+
+       if( pset_add( xtimer_list, new_xtimer ) == NULL ) {
+               free( new_xtimer );
+               return -1;
+       }
+               
+       pset_sort( xtimer_list, xtimer_compfunc );
+       
+       return(new_xtimer->xtid);
+}
+
+/* xtimer_poll:
+ * Traverses the pset_h of timers, and executes the callback for expired
+ * timers.  Timers that are expired, and have their callback executed
+ * are removed from the list of timers. 
+ */
+int xtimer_poll(void)
+{
+       unsigned int i;
+       
+       if( xtimer_list == NULL )
+               return(0);
+
+       for( i = 0; i < pset_count( xtimer_list ); i++ ) {
+               xtime_h *cur_timer = pset_pointer( xtimer_list, i );
+               time_t cur_time    = time(NULL);
+
+               /* The list is sorted, low to high.  If there's no
+                * timers left, return.
+                */
+               if( cur_timer->when > cur_time ) {
+                       return(0);
+               }
+               cur_timer->timerfunc();
+               pset_delete( xtimer_list, cur_timer );
+               free(cur_timer);
+               i--;
+               cur_timer = NULL;
+       }
+
+       return(0);
+}
+
+/* xtimer_remove:
+ * Removes a timer from the list of timers.  Takes the timer id as an argument
+ * Returns:
+ * Success: 0
+ * Failure: -1
+ */
+int xtimer_remove(int xtid)
+{
+       unsigned int i;
+       int ret = -1;
+
+       for( i = 0; i < pset_count( xtimer_list ); i++ ) {
+               xtime_h *cur_timer = pset_pointer( xtimer_list, i );
+               if( cur_timer->xtid == xtid ) {
+                       pset_delete( xtimer_list, cur_timer );
+                       free( cur_timer );
+                       cur_timer = NULL;
+                       ret = 0;
+               }
+       }
+
+       return(ret);
+}
+
+/* xtimer_nexttime:
+ * Returns the number of seconds until the next timer expires.
+ * Returns -1 when no timers are active.
+ */
+time_t xtimer_nexttime(void)
+{
+       time_t ret;
+
+       if(xtimer_list == NULL)
+               return -1;
+
+       if( pset_count(xtimer_list) == 0 )
+               return -1;
+
+       ret = ((xtime_h *)pset_pointer(xtimer_list, 0))->when - time(NULL) ;
+       if( ret < 0 )
+               ret = 0;
+       return( ret );
+}
+
diff --git a/xinetd/xtimer.h b/xinetd/xtimer.h
new file mode 100644 (file)
index 0000000..b0f8451
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (c) Copyright 1998-2001 by Rob Braun
+ * All rights reserved.  The file named COPYRIGHT specifies the terms 
+ * and conditions for redistribution.
+ */
+
+#ifndef _X_TIMER_H
+#define _X_TIMER_H
+
+#include <sys/time.h>
+#include <unistd.h>
+
+struct xtime {
+       void     (*timerfunc)(void);
+       time_t   when;
+       int xtid;
+};
+typedef struct xtime xtime_h;
+
+int xtimer_add( void (*func)(void), time_t );
+int xtimer_poll(void);
+int xtimer_remove(int);
+time_t xtimer_nexttime(void);
+
+#endif /* _X_TIMER_H */