From 7d80dea6e340c708819fa904651114351bdd8318 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 26 Nov 2007 15:57:13 +0100 Subject: [PATCH 1/1] Import upstream 2.3.14 Signed-off-by: Pierre Habouzit --- AUDIT | 173 + CHANGELOG | 909 ++ COPYRIGHT | 51 + INSTALL | 25 + Makefile.in | 123 + README | 126 + TODO | 3 + aclocal.m4 | 27 + config.guess | 1321 +++ config.h.in | 133 + config.sub | 1443 ++++ configure | 11419 +++++++++++++++++++++++++ configure.in | 316 + contrib/empty.conf | 71 + contrib/xinetd | 140 + contrib/xinetd.conf | 50 + contrib/xinetd.d/chargen-dgram | 67 + contrib/xinetd.d/chargen-stream | 67 + contrib/xinetd.d/daytime-dgram | 67 + contrib/xinetd.d/daytime-stream | 67 + contrib/xinetd.d/discard-dgram | 67 + contrib/xinetd.d/discard-stream | 67 + contrib/xinetd.d/echo-dgram | 67 + contrib/xinetd.d/echo-stream | 67 + contrib/xinetd.d/ftp-sensor | 70 + contrib/xinetd.d/tcpmux-server | 68 + contrib/xinetd.d/time-dgram | 67 + contrib/xinetd.d/time-stream | 67 + install-sh | 250 + libs/include/.cvsignore | 0 libs/lib/.cvsignore | 0 libs/man/.cvsignore | 0 libs/src/misc/COPYRIGHT | 33 + libs/src/misc/Makefile.in | 105 + libs/src/misc/README | 14 + libs/src/misc/install-sh | 250 + libs/src/misc/m_env.3 | 162 + libs/src/misc/m_env.c | 247 + libs/src/misc/m_env.h | 51 + libs/src/misc/misc.3 | 94 + libs/src/misc/misc.c | 34 + libs/src/misc/misc.h | 19 + libs/src/portable/Makefile.in | 94 + libs/src/portable/compat.h | 18 + libs/src/portable/cvt.c | 269 + libs/src/portable/difftime.c | 9 + libs/src/portable/fake-getaddrinfo.c | 117 + libs/src/portable/fake-getaddrinfo.h | 55 + libs/src/portable/fake-getnameinfo.c | 63 + libs/src/portable/inet_aton.c | 193 + libs/src/portable/inet_ntop.c | 216 + libs/src/portable/libportable.h | 111 + libs/src/portable/strcasecmp.c | 15 + libs/src/portable/strerror.c | 75 + libs/src/pset/COPYRIGHT | 30 + libs/src/pset/Makefile.in | 95 + libs/src/pset/install-sh | 250 + libs/src/pset/ops.c | 60 + libs/src/pset/pset.3 | 270 + libs/src/pset/pset.c | 137 + libs/src/pset/pset.h | 96 + libs/src/pset/psi.3 | 89 + libs/src/sio/COPYRIGHT | 29 + libs/src/sio/Makefile.in | 96 + libs/src/sio/README | 128 + libs/src/sio/Sprint.3 | 157 + libs/src/sio/impl.h | 170 + libs/src/sio/install-sh | 250 + libs/src/sio/sio.3 | 416 + libs/src/sio/sio.c | 442 + libs/src/sio/sio.h | 198 + libs/src/sio/sioconf.h | 191 + libs/src/sio/siosup.c | 899 ++ libs/src/sio/sprint.c | 742 ++ libs/src/str/CHANGELOG | 19 + libs/src/str/COPYRIGHT | 29 + libs/src/str/Makefile.in | 109 + libs/src/str/README | 73 + libs/src/str/install-sh | 250 + libs/src/str/str.h | 84 + libs/src/str/strparse.3 | 161 + libs/src/str/strparse.c | 184 + libs/src/str/strparse.h | 35 + libs/src/str/strprint.3 | 157 + libs/src/str/strprint.c | 117 + libs/src/str/strutil.3 | 62 + libs/src/str/strutil.c | 107 + libs/src/xlog/CHANGELOG | 12 + libs/src/xlog/COPYRIGHT | 30 + libs/src/xlog/Makefile.in | 102 + libs/src/xlog/filelog.c | 300 + libs/src/xlog/filelog.h | 46 + libs/src/xlog/impl.h | 107 + libs/src/xlog/install-sh | 250 + libs/src/xlog/slog.c | 196 + libs/src/xlog/slog.h | 33 + libs/src/xlog/util.c | 53 + libs/src/xlog/xlog.3 | 297 + libs/src/xlog/xlog.c | 259 + libs/src/xlog/xlog.h | 64 + xinetd.spec | 88 + xinetd.spec.in | 88 + xinetd/Makefile.in | 237 + xinetd/access.c | 366 + xinetd/access.h | 57 + xinetd/addr.c | 796 ++ xinetd/addr.h | 31 + xinetd/attr.h | 82 + xinetd/builtins.c | 609 ++ xinetd/builtins.h | 47 + xinetd/child.c | 463 + xinetd/child.h | 21 + xinetd/conf.c | 216 + xinetd/conf.h | 37 + xinetd/confparse.c | 964 +++ xinetd/confparse.h | 11 + xinetd/connection.c | 227 + xinetd/connection.h | 92 + xinetd/defs.h | 180 + xinetd/env.c | 181 + xinetd/env.h | 12 + xinetd/ident.c | 342 + xinetd/ident.h | 10 + xinetd/includedir.c | 158 + xinetd/includedir.h | 8 + xinetd/inet.c | 420 + xinetd/inet.h | 10 + xinetd/init.c | 388 + xinetd/init.h | 9 + xinetd/int.c | 290 + xinetd/int.h | 76 + xinetd/intcommon.c | 227 + xinetd/intcommon.h | 21 + xinetd/internals.c | 468 + xinetd/internals.h | 10 + xinetd/itox.8 | 19 + xinetd/itox.c | 306 + xinetd/log.c | 241 + xinetd/log.h | 71 + xinetd/logctl.c | 172 + xinetd/logctl.h | 12 + xinetd/main.c | 311 + xinetd/main.h | 19 + xinetd/mask.h | 42 + xinetd/msg.c | 226 + xinetd/msg.h | 21 + xinetd/nvlists.c | 136 + xinetd/nvlists.h | 14 + xinetd/options.c | 150 + xinetd/options.h | 25 + xinetd/parse.c | 707 ++ xinetd/parse.h | 53 + xinetd/parsers.c | 1515 ++++ xinetd/parsers.h | 74 + xinetd/parsesup.c | 207 + xinetd/parsesup.h | 12 + xinetd/reconfig.c | 508 ++ xinetd/reconfig.h | 9 + xinetd/redirect.c | 219 + xinetd/redirect.h | 11 + xinetd/retry.c | 208 + xinetd/retry.h | 10 + xinetd/sample.conf | 347 + xinetd/sconf.c | 521 ++ xinetd/sconf.h | 305 + xinetd/sconst.h | 32 + xinetd/sensor.c | 222 + xinetd/sensor.h | 18 + xinetd/server.c | 329 + xinetd/server.h | 92 + xinetd/service.c | 904 ++ xinetd/service.h | 157 + xinetd/signals.c | 500 ++ xinetd/signals.h | 20 + xinetd/special.c | 118 + xinetd/special.h | 12 + xinetd/state.h | 91 + xinetd/tcpint.c | 375 + xinetd/tcpint.h | 13 + xinetd/time.c | 167 + xinetd/timex.h | 17 + xinetd/udpint.c | 339 + xinetd/udpint.h | 13 + xinetd/util.c | 354 + xinetd/util.h | 29 + xinetd/xconfig.h | 201 + xinetd/xconv-new.pl | 106 + xinetd/xconv.pl | 116 + xinetd/xconv.pl.8 | 157 + xinetd/xgetloadavg.c | 147 + xinetd/xgetloadavg.h | 8 + xinetd/xinetd.conf.man | 1244 +++ xinetd/xinetd.log.man | 153 + xinetd/xinetd.man | 194 + xinetd/xmdns.c | 147 + xinetd/xmdns.h | 12 + xinetd/xtimer.c | 171 + xinetd/xtimer.h | 25 + 198 files changed, 47709 insertions(+) create mode 100644 AUDIT create mode 100644 CHANGELOG create mode 100644 COPYRIGHT create mode 100644 INSTALL create mode 100644 Makefile.in create mode 100644 README create mode 100644 TODO create mode 100644 aclocal.m4 create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.in create mode 100644 contrib/empty.conf create mode 100755 contrib/xinetd create mode 100644 contrib/xinetd.conf create mode 100644 contrib/xinetd.d/chargen-dgram create mode 100644 contrib/xinetd.d/chargen-stream create mode 100644 contrib/xinetd.d/daytime-dgram create mode 100644 contrib/xinetd.d/daytime-stream create mode 100644 contrib/xinetd.d/discard-dgram create mode 100644 contrib/xinetd.d/discard-stream create mode 100644 contrib/xinetd.d/echo-dgram create mode 100644 contrib/xinetd.d/echo-stream create mode 100644 contrib/xinetd.d/ftp-sensor create mode 100644 contrib/xinetd.d/tcpmux-server create mode 100644 contrib/xinetd.d/time-dgram create mode 100644 contrib/xinetd.d/time-stream create mode 100755 install-sh create mode 100644 libs/include/.cvsignore create mode 100644 libs/lib/.cvsignore create mode 100644 libs/man/.cvsignore create mode 100644 libs/src/misc/COPYRIGHT create mode 100644 libs/src/misc/Makefile.in create mode 100644 libs/src/misc/README create mode 100755 libs/src/misc/install-sh create mode 100644 libs/src/misc/m_env.3 create mode 100644 libs/src/misc/m_env.c create mode 100644 libs/src/misc/m_env.h create mode 100644 libs/src/misc/misc.3 create mode 100644 libs/src/misc/misc.c create mode 100644 libs/src/misc/misc.h create mode 100644 libs/src/portable/Makefile.in create mode 100644 libs/src/portable/compat.h create mode 100644 libs/src/portable/cvt.c create mode 100644 libs/src/portable/difftime.c create mode 100644 libs/src/portable/fake-getaddrinfo.c create mode 100644 libs/src/portable/fake-getaddrinfo.h create mode 100644 libs/src/portable/fake-getnameinfo.c create mode 100644 libs/src/portable/inet_aton.c create mode 100644 libs/src/portable/inet_ntop.c create mode 100644 libs/src/portable/libportable.h create mode 100644 libs/src/portable/strcasecmp.c create mode 100644 libs/src/portable/strerror.c create mode 100644 libs/src/pset/COPYRIGHT create mode 100644 libs/src/pset/Makefile.in create mode 100755 libs/src/pset/install-sh create mode 100644 libs/src/pset/ops.c create mode 100644 libs/src/pset/pset.3 create mode 100644 libs/src/pset/pset.c create mode 100644 libs/src/pset/pset.h create mode 100644 libs/src/pset/psi.3 create mode 100644 libs/src/sio/COPYRIGHT create mode 100644 libs/src/sio/Makefile.in create mode 100644 libs/src/sio/README create mode 100644 libs/src/sio/Sprint.3 create mode 100644 libs/src/sio/impl.h create mode 100755 libs/src/sio/install-sh create mode 100644 libs/src/sio/sio.3 create mode 100644 libs/src/sio/sio.c create mode 100644 libs/src/sio/sio.h create mode 100644 libs/src/sio/sioconf.h create mode 100644 libs/src/sio/siosup.c create mode 100644 libs/src/sio/sprint.c create mode 100644 libs/src/str/CHANGELOG create mode 100644 libs/src/str/COPYRIGHT create mode 100644 libs/src/str/Makefile.in create mode 100644 libs/src/str/README create mode 100755 libs/src/str/install-sh create mode 100644 libs/src/str/str.h create mode 100644 libs/src/str/strparse.3 create mode 100644 libs/src/str/strparse.c create mode 100644 libs/src/str/strparse.h create mode 100644 libs/src/str/strprint.3 create mode 100644 libs/src/str/strprint.c create mode 100644 libs/src/str/strutil.3 create mode 100644 libs/src/str/strutil.c create mode 100644 libs/src/xlog/CHANGELOG create mode 100644 libs/src/xlog/COPYRIGHT create mode 100644 libs/src/xlog/Makefile.in create mode 100644 libs/src/xlog/filelog.c create mode 100644 libs/src/xlog/filelog.h create mode 100644 libs/src/xlog/impl.h create mode 100755 libs/src/xlog/install-sh create mode 100644 libs/src/xlog/slog.c create mode 100644 libs/src/xlog/slog.h create mode 100644 libs/src/xlog/util.c create mode 100644 libs/src/xlog/xlog.3 create mode 100644 libs/src/xlog/xlog.c create mode 100644 libs/src/xlog/xlog.h create mode 100644 xinetd.spec create mode 100644 xinetd.spec.in create mode 100644 xinetd/Makefile.in create mode 100644 xinetd/access.c create mode 100644 xinetd/access.h create mode 100644 xinetd/addr.c create mode 100644 xinetd/addr.h create mode 100644 xinetd/attr.h create mode 100644 xinetd/builtins.c create mode 100644 xinetd/builtins.h create mode 100644 xinetd/child.c create mode 100644 xinetd/child.h create mode 100644 xinetd/conf.c create mode 100644 xinetd/conf.h create mode 100644 xinetd/confparse.c create mode 100644 xinetd/confparse.h create mode 100644 xinetd/connection.c create mode 100644 xinetd/connection.h create mode 100644 xinetd/defs.h create mode 100644 xinetd/env.c create mode 100644 xinetd/env.h create mode 100644 xinetd/ident.c create mode 100644 xinetd/ident.h create mode 100644 xinetd/includedir.c create mode 100644 xinetd/includedir.h create mode 100644 xinetd/inet.c create mode 100644 xinetd/inet.h create mode 100644 xinetd/init.c create mode 100644 xinetd/init.h create mode 100644 xinetd/int.c create mode 100644 xinetd/int.h create mode 100644 xinetd/intcommon.c create mode 100644 xinetd/intcommon.h create mode 100644 xinetd/internals.c create mode 100644 xinetd/internals.h create mode 100644 xinetd/itox.8 create mode 100644 xinetd/itox.c create mode 100644 xinetd/log.c create mode 100644 xinetd/log.h create mode 100644 xinetd/logctl.c create mode 100644 xinetd/logctl.h create mode 100644 xinetd/main.c create mode 100644 xinetd/main.h create mode 100644 xinetd/mask.h create mode 100644 xinetd/msg.c create mode 100644 xinetd/msg.h create mode 100644 xinetd/nvlists.c create mode 100644 xinetd/nvlists.h create mode 100644 xinetd/options.c create mode 100644 xinetd/options.h create mode 100644 xinetd/parse.c create mode 100644 xinetd/parse.h create mode 100644 xinetd/parsers.c create mode 100644 xinetd/parsers.h create mode 100644 xinetd/parsesup.c create mode 100644 xinetd/parsesup.h create mode 100644 xinetd/reconfig.c create mode 100644 xinetd/reconfig.h create mode 100644 xinetd/redirect.c create mode 100644 xinetd/redirect.h create mode 100644 xinetd/retry.c create mode 100644 xinetd/retry.h create mode 100644 xinetd/sample.conf create mode 100644 xinetd/sconf.c create mode 100644 xinetd/sconf.h create mode 100644 xinetd/sconst.h create mode 100644 xinetd/sensor.c create mode 100644 xinetd/sensor.h create mode 100644 xinetd/server.c create mode 100644 xinetd/server.h create mode 100644 xinetd/service.c create mode 100644 xinetd/service.h create mode 100644 xinetd/signals.c create mode 100644 xinetd/signals.h create mode 100644 xinetd/special.c create mode 100644 xinetd/special.h create mode 100644 xinetd/state.h create mode 100644 xinetd/tcpint.c create mode 100644 xinetd/tcpint.h create mode 100644 xinetd/time.c create mode 100644 xinetd/timex.h create mode 100644 xinetd/udpint.c create mode 100644 xinetd/udpint.h create mode 100644 xinetd/util.c create mode 100644 xinetd/util.h create mode 100644 xinetd/xconfig.h create mode 100755 xinetd/xconv-new.pl create mode 100755 xinetd/xconv.pl create mode 100644 xinetd/xconv.pl.8 create mode 100644 xinetd/xgetloadavg.c create mode 100644 xinetd/xgetloadavg.h create mode 100644 xinetd/xinetd.conf.man create mode 100644 xinetd/xinetd.log.man create mode 100644 xinetd/xinetd.man create mode 100644 xinetd/xmdns.c create mode 100644 xinetd/xmdns.h create mode 100644 xinetd/xtimer.c create mode 100644 xinetd/xtimer.h diff --git a/AUDIT b/AUDIT new file mode 100644 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 + ++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 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 +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 +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 +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 + Fixed a bug in sio/sprint.c + Thanks to Steven Stanfield +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 + $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". +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 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 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 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 ..) 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 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 index 0000000..7511efd --- /dev/null +++ b/Makefile.in @@ -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 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 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 index 0000000..6e6f32c --- /dev/null +++ b/aclocal.m4 @@ -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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 index 0000000..ed2e03b --- /dev/null +++ b/config.guess @@ -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 . +# Please send patches to . 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 ." + +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 <$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 /* 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 + + 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 + #include + + 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 + 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 + #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' /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 + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 < +# include +#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 + 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 +# 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 < 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 index 0000000..f66130a --- /dev/null +++ b/config.h.in @@ -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 index 0000000..f365797 --- /dev/null +++ b/config.sub @@ -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 . 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 ." + +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 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 +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#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 if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + 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 &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &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 +#include +#include +#include +/* 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 +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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares strerror. + For example, HP-UX 11i declares gettimeofday. */ +#define strerror innocuous_strerror + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strerror (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares strcasecmp. + For example, HP-UX 11i declares gettimeofday. */ +#define strcasecmp innocuous_strcasecmp + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strcasecmp (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares socket. + For example, HP-UX 11i declares gettimeofday. */ +#define socket innocuous_socket + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char socket (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares inet_aton. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares setenv. + For example, HP-UX 11i declares gettimeofday. */ +#define setenv innocuous_setenv + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char setenv (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares strsignal. + For example, HP-UX 11i declares gettimeofday. */ +#define strsignal innocuous_strsignal + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strsignal (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares gai_strerror. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares freeaddrinfo. + For example, HP-UX 11i declares gettimeofday. */ +#define freeaddrinfo innocuous_freeaddrinfo + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char freeaddrinfo (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares getaddrinfo. + For example, HP-UX 11i declares gettimeofday. */ +#define getaddrinfo innocuous_getaddrinfo + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char getaddrinfo (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 +#include +#include +#include + +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 + +_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 + +_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 +#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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +_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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#if STDC_HEADERS +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_RLIM_T +#include +#endif +#if HAVE_STDINT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#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 +#include +#ifdef HAVE_NETDB_H +#include +#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 +#include + +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 +#include + +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 +#include + +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 +_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 +_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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 +#include + +#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 +# 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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 ." +_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 <>$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 <>$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 index 0000000..1e01a59 --- /dev/null +++ b/configure.in @@ -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 +#include +#ifdef HAVE_NETDB_H +#include +#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 +#include + ], + [ 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 +#include + ], + [ 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 +#include + ], + [ 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 index 0000000..19101e0 --- /dev/null +++ b/contrib/empty.conf @@ -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 index 0000000..de0e294 --- /dev/null +++ b/contrib/xinetd @@ -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 index 0000000..41904e0 --- /dev/null +++ b/contrib/xinetd.conf @@ -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 index 0000000..e3a604a --- /dev/null +++ b/contrib/xinetd.d/chargen-dgram @@ -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 index 0000000..545cec9 --- /dev/null +++ b/contrib/xinetd.d/chargen-stream @@ -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 index 0000000..a0d83b1 --- /dev/null +++ b/contrib/xinetd.d/daytime-dgram @@ -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 index 0000000..ab3e670 --- /dev/null +++ b/contrib/xinetd.d/daytime-stream @@ -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 index 0000000..e47a812 --- /dev/null +++ b/contrib/xinetd.d/discard-dgram @@ -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 index 0000000..8feefae --- /dev/null +++ b/contrib/xinetd.d/discard-stream @@ -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 index 0000000..48802af --- /dev/null +++ b/contrib/xinetd.d/echo-dgram @@ -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 index 0000000..6a4f46f --- /dev/null +++ b/contrib/xinetd.d/echo-stream @@ -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 index 0000000..8e72be5 --- /dev/null +++ b/contrib/xinetd.d/ftp-sensor @@ -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 index 0000000..43d04b3 --- /dev/null +++ b/contrib/xinetd.d/tcpmux-server @@ -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 index 0000000..eac2066 --- /dev/null +++ b/contrib/xinetd.d/time-dgram @@ -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 index 0000000..b4b81e4 --- /dev/null +++ b/contrib/xinetd.d/time-stream @@ -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 index 0000000..ebc6691 --- /dev/null +++ b/install-sh @@ -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 index 0000000..e69de29 diff --git a/libs/lib/.cvsignore b/libs/lib/.cvsignore new file mode 100644 index 0000000..e69de29 diff --git a/libs/man/.cvsignore b/libs/man/.cvsignore new file mode 100644 index 0000000..e69de29 diff --git a/libs/src/misc/COPYRIGHT b/libs/src/misc/COPYRIGHT new file mode 100644 index 0000000..7c11bad --- /dev/null +++ b/libs/src/misc/COPYRIGHT @@ -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 ..) 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 index 0000000..a84127d --- /dev/null +++ b/libs/src/misc/Makefile.in @@ -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 instead of +# + +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 index 0000000..d3740d1 --- /dev/null +++ b/libs/src/misc/README @@ -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 index 0000000..ebc6691 --- /dev/null +++ b/libs/src/misc/install-sh @@ -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 index 0000000..db6d1c3 --- /dev/null +++ b/libs/src/misc/m_env.3 @@ -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 index 0000000..090811b --- /dev/null +++ b/libs/src/misc/m_env.c @@ -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 +#include +#include + +#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 index 0000000..9dada5b --- /dev/null +++ b/libs/src/misc/m_env.h @@ -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 index 0000000..bba1db4 --- /dev/null +++ b/libs/src/misc/misc.3 @@ -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 index 0000000..777cf14 --- /dev/null +++ b/libs/src/misc/misc.c @@ -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 +#include + +/* + * 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 index 0000000..38e430d --- /dev/null +++ b/libs/src/misc/misc.h @@ -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 index 0000000..f172cd7 --- /dev/null +++ b/libs/src/portable/Makefile.in @@ -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 instead of +# + +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 index 0000000..16f4286 --- /dev/null +++ b/libs/src/portable/compat.h @@ -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 index 0000000..4bd99fc --- /dev/null +++ b/libs/src/portable/cvt.c @@ -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 + +#include +#include +#include +#include +#include + +#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 index 0000000..1c572d6 --- /dev/null +++ b/libs/src/portable/difftime.c @@ -0,0 +1,9 @@ +#include "config.h" +#ifndef HAVE_DIFFTIME +#include + +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 index 0000000..9b0c544 --- /dev/null +++ b/libs/src/portable/fake-getaddrinfo.c @@ -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 index 0000000..0940e37 --- /dev/null +++ b/libs/src/portable/fake-getaddrinfo.h @@ -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 index 0000000..7af6c33 --- /dev/null +++ b/libs/src/portable/fake-getnameinfo.c @@ -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 +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#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 index 0000000..0a05e61 --- /dev/null +++ b/libs/src/portable/inet_aton.c @@ -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 +#include +#include +#include +#include + +#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 index 0000000..3c57ccd --- /dev/null +++ b/libs/src/portable/inet_ntop.c @@ -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 +#include +#include +#include +#include +#ifndef HAVE_CYGWIN +#include +#endif +#include +#include +#include + +#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 index 0000000..825f3c3 --- /dev/null +++ b/libs/src/portable/libportable.h @@ -0,0 +1,111 @@ +#ifndef _XINETD_LIBPORTABLE +#define _XINETD_LIBPORTABLE 1 + +#include "config.h" +#include +#include +#include +#include + +#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 index 0000000..35b92c6 --- /dev/null +++ b/libs/src/portable/strcasecmp.c @@ -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 index 0000000..2fa75f6 --- /dev/null +++ b/libs/src/portable/strerror.c @@ -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 +#include + +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 index 0000000..362419b --- /dev/null +++ b/libs/src/pset/COPYRIGHT @@ -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 ..) 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 index 0000000..8b6382d --- /dev/null +++ b/libs/src/pset/Makefile.in @@ -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 index 0000000..ebc6691 --- /dev/null +++ b/libs/src/pset/install-sh @@ -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 index 0000000..331a861 --- /dev/null +++ b/libs/src/pset/ops.c @@ -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 + +#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 index 0000000..7835529 --- /dev/null +++ b/libs/src/pset/pset.3 @@ -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 index 0000000..a5f8069 --- /dev/null +++ b/libs/src/pset/pset.c @@ -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 +#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 index 0000000..4a726a1 --- /dev/null +++ b/libs/src/pset/pset.h @@ -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 + +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 index 0000000..bd24184 --- /dev/null +++ b/libs/src/pset/psi.3 @@ -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 index 0000000..d149511 --- /dev/null +++ b/libs/src/sio/COPYRIGHT @@ -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. ..) 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 index 0000000..40ae2c5 --- /dev/null +++ b/libs/src/sio/Makefile.in @@ -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 index 0000000..ce127e5 --- /dev/null +++ b/libs/src/sio/README @@ -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 index 0000000..31bc948 --- /dev/null +++ b/libs/src/sio/Sprint.3 @@ -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 index 0000000..f22cef2 --- /dev/null +++ b/libs/src/sio/impl.h @@ -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 + + +/* + * 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 + +/* + * 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 +#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 index 0000000..ebc6691 --- /dev/null +++ b/libs/src/sio/install-sh @@ -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 index 0000000..6f02380 --- /dev/null +++ b/libs/src/sio/sio.3 @@ -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 +.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 index 0000000..58f70b4 --- /dev/null +++ b/libs/src/sio/sio.c @@ -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 +#endif + +#ifdef _APPLE_ +#undef HAVE_MMAP +#endif + +#include +#include +#include + +#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 index 0000000..dfc3af1 --- /dev/null +++ b/libs/src/sio/sio.h @@ -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 +#include + +/* + * 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 index 0000000..5f8fd13 --- /dev/null +++ b/libs/src/sio/sioconf.h @@ -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_. + * 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 +#include +#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 +#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 index 0000000..e717941 --- /dev/null +++ b/libs/src/sio/siosup.c @@ -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 +#include +#include +#include +#include +#include + +#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 + +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 + +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 index 0000000..87ecf92 --- /dev/null +++ b/libs/src/sio/sprint.c @@ -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 +#include +#include + +#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 % */ + + /* + * 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 % 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 % (like syslog). + * Note that we can't point s inside fmt because the + * unknown 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 index 0000000..2fbea8d --- /dev/null +++ b/libs/src/str/CHANGELOG @@ -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 index 0000000..dfb323c --- /dev/null +++ b/libs/src/str/COPYRIGHT @@ -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 ..) 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 index 0000000..cc74b71 --- /dev/null +++ b/libs/src/str/Makefile.in @@ -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 index 0000000..d07936e --- /dev/null +++ b/libs/src/str/README @@ -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 index 0000000..ebc6691 --- /dev/null +++ b/libs/src/str/install-sh @@ -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 index 0000000..e1d234c --- /dev/null +++ b/libs/src/str/str.h @@ -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 + +#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 index 0000000..ade2757 --- /dev/null +++ b/libs/src/str/strparse.3 @@ -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 index 0000000..4c0c355 --- /dev/null +++ b/libs/src/str/strparse.c @@ -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 +#include +#include + +#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 index 0000000..3bf7875 --- /dev/null +++ b/libs/src/str/strparse.h @@ -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 index 0000000..9cd9eb0 --- /dev/null +++ b/libs/src/str/strprint.3 @@ -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 index 0000000..0fd7ec8 --- /dev/null +++ b/libs/src/str/strprint.c @@ -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 index 0000000..ab24e1d --- /dev/null +++ b/libs/src/str/strutil.3 @@ -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 index 0000000..094da45 --- /dev/null +++ b/libs/src/str/strutil.c @@ -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 +#include + +#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 index 0000000..e076e44 --- /dev/null +++ b/libs/src/xlog/CHANGELOG @@ -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 index 0000000..362419b --- /dev/null +++ b/libs/src/xlog/COPYRIGHT @@ -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 ..) 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 index 0000000..4a89870 --- /dev/null +++ b/libs/src/xlog/Makefile.in @@ -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 index 0000000..ee688e5 --- /dev/null +++ b/libs/src/xlog/filelog.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#ifndef NO_SYSLOG +#include +#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( ¤t_time ) ; + tmp = localtime( ¤t_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 index 0000000..bc5877a --- /dev/null +++ b/libs/src/xlog/filelog.h @@ -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 index 0000000..3760e58 --- /dev/null +++ b/libs/src/xlog/impl.h @@ -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 /* For malloc() & free() prototypes */ +#include +#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 index 0000000..ebc6691 --- /dev/null +++ b/libs/src/xlog/install-sh @@ -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 index 0000000..7aefa42 --- /dev/null +++ b/libs/src/xlog/slog.c @@ -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 +#endif + +#include "xlog.h" +#include "impl.h" +#include "slog.h" +#include "str.h" +#include + +#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 index 0000000..763badd --- /dev/null +++ b/libs/src/xlog/slog.h @@ -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 index 0000000..2b34e32 --- /dev/null +++ b/libs/src/xlog/util.c @@ -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 +#include +#include +#include + +#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 index 0000000..c89fb5c --- /dev/null +++ b/libs/src/xlog/xlog.3 @@ -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 index 0000000..f0c992f --- /dev/null +++ b/libs/src/xlog/xlog.c @@ -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 +#include + +#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 index 0000000..14b26d0 --- /dev/null +++ b/libs/src/xlog/xlog.h @@ -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 index 0000000..19ed13f --- /dev/null +++ b/xinetd.spec @@ -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 +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 +- Refined installation and added services. + diff --git a/xinetd.spec.in b/xinetd.spec.in new file mode 100644 index 0000000..7647877 --- /dev/null +++ b/xinetd.spec.in @@ -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 +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 +- Refined installation and added services. + diff --git a/xinetd/Makefile.in b/xinetd/Makefile.in new file mode 100644 index 0000000..f8957cd --- /dev/null +++ b/xinetd/Makefile.in @@ -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 index 0000000..2af9dfe --- /dev/null +++ b/xinetd/access.c @@ -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 +#include +#include +#include +#include +#include + +#ifdef HAVE_STDINT_H +#include +#endif + +#include "str.h" +#include "access.h" +#ifdef LIBWRAP +#include +#include +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 index 0000000..d3a5959 --- /dev/null +++ b/xinetd/access.h @@ -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 index 0000000..cd26be9 --- /dev/null +++ b/xinetd/addr.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#endif + +#if defined(HAVE_ARPA_INET_H) +#include +#endif +#include + +#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 index 0000000..3711212 --- /dev/null +++ b/xinetd/addr.h @@ -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 +#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 index 0000000..fa2e209 --- /dev/null +++ b/xinetd/attr.h @@ -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 index 0000000..aac5dfe --- /dev/null +++ b/xinetd/builtins.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#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 index 0000000..4b828e2 --- /dev/null +++ b/xinetd/builtins.h @@ -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 index 0000000..89ee54c --- /dev/null +++ b/xinetd/child.c @@ -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 +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined (HAVE_GRP_H) +#include +#endif +#ifdef HAVE_NETDB_H +#include +#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: + * 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 index 0000000..70bdceb --- /dev/null +++ b/xinetd/child.h @@ -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 index 0000000..7ec7d1e --- /dev/null +++ b/xinetd/conf.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..0330e30 --- /dev/null +++ b/xinetd/conf.h @@ -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 index 0000000..db9f431 --- /dev/null +++ b/xinetd/confparse.c @@ -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 +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_RPC_RPC_H +#include +#endif + +#ifdef HAVE_RPC_RPCENT_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#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 index 0000000..677c30f --- /dev/null +++ b/xinetd/confparse.h @@ -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 index 0000000..fae7f77 --- /dev/null +++ b/xinetd/connection.c @@ -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 +#include +#include +#include +#include +#include +#include + +#include + +#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 ""; + + 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 ""; + } + 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 index 0000000..dda823f --- /dev/null +++ b/xinetd/connection.h @@ -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 +#include +#if defined( HAVE_ARPA_INET_H ) +#include +#endif +#include + +#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 index 0000000..d19699c --- /dev/null +++ b/xinetd/defs.h @@ -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 +#include +#include +#include +#include + +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 index 0000000..89a06c0 --- /dev/null +++ b/xinetd/env.c @@ -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 +#include +#include + +#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 index 0000000..541a6b4 --- /dev/null +++ b/xinetd/env.h @@ -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 index 0000000..c526fcc --- /dev/null +++ b/xinetd/ident.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 index 0000000..aba1719 --- /dev/null +++ b/xinetd/ident.h @@ -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 index 0000000..0f3be61 --- /dev/null +++ b/xinetd/includedir.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..b79a830 --- /dev/null +++ b/xinetd/includedir.h @@ -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 index 0000000..1cb2ba2 --- /dev/null +++ b/xinetd/inet.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..3d87059 --- /dev/null +++ b/xinetd/inet.h @@ -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 index 0000000..f93cece --- /dev/null +++ b/xinetd/init.c @@ -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 +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include +#include + +#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 index 0000000..88ddbfa --- /dev/null +++ b/xinetd/init.h @@ -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 index 0000000..b9dabbd --- /dev/null +++ b/xinetd/int.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +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 index 0000000..4653ef3 --- /dev/null +++ b/xinetd/int.h @@ -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 +#include + +#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 index 0000000..730c27e --- /dev/null +++ b/xinetd/intcommon.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..3a4019f --- /dev/null +++ b/xinetd/intcommon.h @@ -0,0 +1,21 @@ +#ifndef INTCOMMON_H +#define INTCOMMON_H + +#include "config.h" +#include +#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 index 0000000..ec67bfc --- /dev/null +++ b/xinetd/internals.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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( ¤t_time ) ; + Sprint( dump_fd, "INTERNAL STATE DUMP: %s\n", program_version ) ; + Sprint( dump_fd, "Current time: %s\n", ctime( ¤t_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 index 0000000..4d2c59e --- /dev/null +++ b/xinetd/internals.h @@ -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 index 0000000..de109db --- /dev/null +++ b/xinetd/itox.8 @@ -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 ] +.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 +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 . diff --git a/xinetd/itox.c b/xinetd/itox.c new file mode 100644 index 0000000..dd37e8f --- /dev/null +++ b/xinetd/itox.c @@ -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 +#include +#include "sio.h" +#include "str.h" +#if !defined(linux) +#include "misc.h" +#else +#include +#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 : 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 index 0000000..f1351c4 --- /dev/null +++ b/xinetd/log.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#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, "", 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( ¤t_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 index 0000000..1b9ff95 --- /dev/null +++ b/xinetd/log.h @@ -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 + +#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 index 0000000..c92f656 --- /dev/null +++ b/xinetd/logctl.c @@ -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 +#include +#include +#include + +#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 index 0000000..0b303e4 --- /dev/null +++ b/xinetd/logctl.h @@ -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 index 0000000..4ca383a --- /dev/null +++ b/xinetd/main.c @@ -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 +#include +#include +#include +#include +#include + +#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 index 0000000..8ca1d87 --- /dev/null +++ b/xinetd/main.h @@ -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 index 0000000..f511557 --- /dev/null +++ b/xinetd/mask.h @@ -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 +#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 index 0000000..4acdec9 --- /dev/null +++ b/xinetd/msg.c @@ -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 +#include +#include +#include + +#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 index 0000000..736bba3 --- /dev/null +++ b/xinetd/msg.h @@ -0,0 +1,21 @@ +#ifndef MSG_H +#define MSG_H + +#include + +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 index 0000000..b66eda6 --- /dev/null +++ b/xinetd/nvlists.c @@ -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 +#include +#include + +#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 index 0000000..432f4d4 --- /dev/null +++ b/xinetd/nvlists.h @@ -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 index 0000000..b058b6a --- /dev/null +++ b/xinetd/options.c @@ -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 +#include +#include + +#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 index 0000000..5b78cba --- /dev/null +++ b/xinetd/options.h @@ -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 index 0000000..563940b --- /dev/null +++ b/xinetd/parse.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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: + * + * service + * + * 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 . + * + * 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 index 0000000..6aafb6d --- /dev/null +++ b/xinetd/parse.h @@ -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 index 0000000..84297c5 --- /dev/null +++ b/xinetd/parsers.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For LONG_MIN and LONG_MAX */ +#include +#ifdef HAVE_LOADAVG +#include +#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; uvalue ) ; + 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: [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 index 0000000..50a5688 --- /dev/null +++ b/xinetd/parsers.h @@ -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 index 0000000..5846fcc --- /dev/null +++ b/xinetd/parsesup.c @@ -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 +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +#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 index 0000000..0c1ac86 --- /dev/null +++ b/xinetd/parsesup.h @@ -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 index 0000000..cc065a3 --- /dev/null +++ b/xinetd/reconfig.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#ifndef NO_RPC + #ifdef HAVE_RPC_PMAP_CLNT_H + #ifdef __sun + #include + #include + #endif + #include + #include + #include + #include + #include + #endif + #include +#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 index 0000000..de2ea5d --- /dev/null +++ b/xinetd/reconfig.h @@ -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 index 0000000..cf93b73 --- /dev/null +++ b/xinetd/redirect.c @@ -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 +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_SYS_SIGNAL_H +#include +#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 index 0000000..fadedc0 --- /dev/null +++ b/xinetd/redirect.h @@ -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 index 0000000..505797f --- /dev/null +++ b/xinetd/retry.c @@ -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 +#include + +#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 index 0000000..74fa440 --- /dev/null +++ b/xinetd/retry.h @@ -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 index 0000000..178cba8 --- /dev/null +++ b/xinetd/sample.conf @@ -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 index 0000000..71b6a30 --- /dev/null +++ b/xinetd/sconf.c @@ -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 +#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 index 0000000..08dc804 --- /dev/null +++ b/xinetd/sconf.h @@ -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 +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#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 index 0000000..8dd2047 --- /dev/null +++ b/xinetd/sconst.h @@ -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 index 0000000..09d0877 --- /dev/null +++ b/xinetd/sensor.c @@ -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 +#include +#include +#include + +#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 index 0000000..b3c5591 --- /dev/null +++ b/xinetd/sensor.h @@ -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 index 0000000..4999d01 --- /dev/null +++ b/xinetd/server.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_FILE_H +#include +#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 +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 index 0000000..b4f1947 --- /dev/null +++ b/xinetd/server.h @@ -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 +#include +#include + +#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 index 0000000..3d68d78 --- /dev/null +++ b/xinetd/service.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_MDNS +#include "xmdns.h" +#endif +#ifndef NO_RPC + #ifdef HAVE_RPC_PMAP_CLNT_H + #ifdef __sun + #include + #include + #endif + #include + #include + #include + #include + #include + #endif + #include +#endif + +#ifdef HAVE_SYS_FILE_H +#include +#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( ¤t_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( ¤t_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 index 0000000..2777667 --- /dev/null +++ b/xinetd/service.h @@ -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 +#include +#include + +#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 index 0000000..4a61dd4 --- /dev/null +++ b/xinetd/signals.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_FILIO_H +#include +#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( ¤t_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 index 0000000..6acf97c --- /dev/null +++ b/xinetd/signals.h @@ -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 index 0000000..22b2fd5 --- /dev/null +++ b/xinetd/special.c @@ -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 +#include +#include +#include +#include + +#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 index 0000000..ffc16b5 --- /dev/null +++ b/xinetd/special.h @@ -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 index 0000000..6c9ada8 --- /dev/null +++ b/xinetd/state.h @@ -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 +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include "libportable.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#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 index 0000000..f0bf040 --- /dev/null +++ b/xinetd/tcpint.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SELECT_H +#include +#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 index 0000000..309ed29 --- /dev/null +++ b/xinetd/tcpint.h @@ -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 index 0000000..a4d63fb --- /dev/null +++ b/xinetd/time.c @@ -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 +#include +#include +#include + +#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( ¤t_time ) ; + tmp = localtime( ¤t_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 index 0000000..f4d1b8e --- /dev/null +++ b/xinetd/timex.h @@ -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 index 0000000..6f65951 --- /dev/null +++ b/xinetd/udpint.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SELECT_H +#include +#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 index 0000000..c49ac5d --- /dev/null +++ b/xinetd/udpint.h @@ -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 index 0000000..7098ecf --- /dev/null +++ b/xinetd/util.c @@ -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 +#include +#include +#include +#if defined (HAVE_SYS_SOCKET_H) +#include +#endif +/* + * The following ifdef is for TIOCNOTTY + */ +#ifndef NO_TERMIOS +#ifdef HAVE_SYS_TERMIOS_H +#include +#endif +#ifdef HAVE_TERMIOS_H +#include +#endif +#else +#include +#endif +#include +#ifdef HAVE_SYS_FILE_H +#include +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#include +#include +#include + +#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 index 0000000..f46563d --- /dev/null +++ b/xinetd/util.h @@ -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 index 0000000..1315656 --- /dev/null +++ b/xinetd/xconfig.h @@ -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 index 0000000..e890308 --- /dev/null +++ b/xinetd/xconv-new.pl @@ -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 ; + +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 index 0000000..cc58868 --- /dev/null +++ b/xinetd/xconv.pl @@ -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( ) { + + 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 index 0000000..4f7d26a --- /dev/null +++ b/xinetd/xconv.pl.8 @@ -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 index 0000000..83297d7 --- /dev/null +++ b/xinetd/xgetloadavg.c @@ -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 +#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 + +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 +#include +#include + +double xgetloadavg () +{ + double ret[3]; + + getloadavg (ret, sizeof (ret) / sizeof (ret[0])); + + return ret[0]; +} +#endif /* __FreeBSD__ */ + + +#if defined(bsdi) || defined(__APPLE__) +#include + +double xgetloadavg(void) +{ + double loadavg[3]; + + if (getloadavg(loadavg, 1) == -1) + { + return -1; + } + else + { + return loadavg[0]; + } +} +#endif /* bsdi || __APPLE__ */ + + +#ifdef __osf__ +#include + +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 index 0000000..77609a5 --- /dev/null +++ b/xinetd/xgetloadavg.h @@ -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 index 0000000..a006e48 --- /dev/null +++ b/xinetd/xinetd.conf.man @@ -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 +{ +.RS +.ft B + ... +.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 + = ... +.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 index 0000000..5babc7f --- /dev/null +++ b/xinetd/xinetd.log.man @@ -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 index 0000000..d52c2cc --- /dev/null +++ b/xinetd/xinetd.man @@ -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 index 0000000..59acf11 --- /dev/null +++ b/xinetd/xmdns.c @@ -0,0 +1,147 @@ +#include "config.h" +#ifdef HAVE_MDNS +#define _GNU_SOURCE +#include +#include +#include +#include "state.h" +#include "service.h" +#include "server.h" +#include "sconf.h" +#include "pset.h" + +#ifdef HAVE_DNSREGISTRATION +#include +#endif + +#ifdef HAVE_HOWL +#include +#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 index 0000000..6eff1ec --- /dev/null +++ b/xinetd/xmdns.h @@ -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 index 0000000..2a0c753 --- /dev/null +++ b/xinetd/xtimer.c @@ -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 + +#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 index 0000000..b0f8451 --- /dev/null +++ b/xinetd/xtimer.h @@ -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 +#include + +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 */ -- 2.20.1