aboutsummaryrefslogtreecommitdiff
path: root/lib/roken
diff options
context:
space:
mode:
Diffstat (limited to 'lib/roken')
-rw-r--r--lib/roken/ChangeLog2196
-rw-r--r--lib/roken/Makefile.am194
-rw-r--r--lib/roken/Makefile.in1426
-rw-r--r--lib/roken/acconfig.h36
-rw-r--r--lib/roken/acinclude.m49
-rw-r--r--lib/roken/base64-test.c99
-rw-r--r--lib/roken/base64.c136
-rw-r--r--lib/roken/base64.h53
-rw-r--r--lib/roken/bswap.c61
-rw-r--r--lib/roken/chown.c45
-rw-r--r--lib/roken/closefrom.c60
-rw-r--r--lib/roken/concat.c112
-rw-r--r--lib/roken/copyhostent.c102
-rw-r--r--lib/roken/daemon.c84
-rw-r--r--lib/roken/dumpdata.c57
-rw-r--r--lib/roken/ecalloc.384
-rw-r--r--lib/roken/ecalloc.c56
-rw-r--r--lib/roken/emalloc.c56
-rw-r--r--lib/roken/environment.c156
-rw-r--r--lib/roken/eread.c57
-rw-r--r--lib/roken/erealloc.c56
-rw-r--r--lib/roken/err.c48
-rw-r--r--lib/roken/err.hin88
-rw-r--r--lib/roken/errx.c48
-rw-r--r--lib/roken/esetenv.c48
-rw-r--r--lib/roken/estrdup.c56
-rw-r--r--lib/roken/ewrite.c57
-rw-r--r--lib/roken/fchown.c45
-rw-r--r--lib/roken/flock.c87
-rw-r--r--lib/roken/fnmatch.c169
-rw-r--r--lib/roken/fnmatch.hin64
-rw-r--r--lib/roken/freeaddrinfo.c57
-rw-r--r--lib/roken/freehostent.c62
-rw-r--r--lib/roken/gai_strerror.c77
-rw-r--r--lib/roken/get_default_username.c80
-rw-r--r--lib/roken/get_window_size.c102
-rw-r--r--lib/roken/getaddrinfo-test.c144
-rw-r--r--lib/roken/getaddrinfo.c417
-rw-r--r--lib/roken/getaddrinfo_hostspec.c104
-rw-r--r--lib/roken/getarg.3341
-rw-r--r--lib/roken/getarg.c595
-rw-r--r--lib/roken/getarg.h102
-rw-r--r--lib/roken/getcap.c1122
-rw-r--r--lib/roken/getcwd.c57
-rw-r--r--lib/roken/getdtablesize.c102
-rw-r--r--lib/roken/getegid.c49
-rw-r--r--lib/roken/geteuid.c49
-rw-r--r--lib/roken/getgid.c49
-rw-r--r--lib/roken/gethostname.c72
-rw-r--r--lib/roken/getifaddrs.c1250
-rw-r--r--lib/roken/getipnodebyaddr.c74
-rw-r--r--lib/roken/getipnodebyname.c86
-rw-r--r--lib/roken/getnameinfo.c127
-rw-r--r--lib/roken/getnameinfo_verified.c92
-rw-r--r--lib/roken/getopt.c124
-rw-r--r--lib/roken/getprogname.c51
-rw-r--r--lib/roken/gettimeofday.c55
-rw-r--r--lib/roken/getuid.c49
-rw-r--r--lib/roken/getusershell.c189
-rw-r--r--lib/roken/glob.c850
-rw-r--r--lib/roken/glob.hin104
-rw-r--r--lib/roken/h_errno.c41
-rw-r--r--lib/roken/hex-test.c110
-rw-r--r--lib/roken/hex.c103
-rw-r--r--lib/roken/hex.h55
-rw-r--r--lib/roken/hostent_find_fqdn.c59
-rw-r--r--lib/roken/hstrerror.c81
-rw-r--r--lib/roken/ifaddrs.hin77
-rw-r--r--lib/roken/inet_aton.c49
-rw-r--r--lib/roken/inet_ntop.c133
-rw-r--r--lib/roken/inet_pton.c49
-rw-r--r--lib/roken/initgroups.c45
-rw-r--r--lib/roken/innetgr.c49
-rwxr-xr-xlib/roken/install-sh251
-rw-r--r--lib/roken/iruserok.c284
-rw-r--r--lib/roken/issuid.c59
-rw-r--r--lib/roken/k_getpwnam.c64
-rw-r--r--lib/roken/k_getpwuid.c64
-rw-r--r--lib/roken/localtime_r.c57
-rw-r--r--lib/roken/lstat.c45
-rw-r--r--lib/roken/memmove.c65
-rw-r--r--lib/roken/mini_inetd.c148
-rwxr-xr-xlib/roken/missing190
-rwxr-xr-xlib/roken/mkinstalldirs40
-rw-r--r--lib/roken/mkstemp.c84
-rw-r--r--lib/roken/ndbm_wrap.c221
-rw-r--r--lib/roken/ndbm_wrap.h91
-rw-r--r--lib/roken/net_read.c74
-rw-r--r--lib/roken/net_write.c72
-rw-r--r--lib/roken/parse_bytes-test.c92
-rw-r--r--lib/roken/parse_bytes.c78
-rw-r--r--lib/roken/parse_bytes.h56
-rw-r--r--lib/roken/parse_reply-test.c129
-rw-r--r--lib/roken/parse_time-test.c118
-rw-r--r--lib/roken/parse_time.3173
-rw-r--r--lib/roken/parse_time.c78
-rw-r--r--lib/roken/parse_time.h59
-rw-r--r--lib/roken/parse_units.c330
-rw-r--r--lib/roken/parse_units.h79
-rw-r--r--lib/roken/print_version.c78
-rw-r--r--lib/roken/putenv.c80
-rw-r--r--lib/roken/rcmd.c52
-rw-r--r--lib/roken/readv.c67
-rw-r--r--lib/roken/realloc.c50
-rw-r--r--lib/roken/recvmsg.c69
-rw-r--r--lib/roken/resolve-test.c179
-rw-r--r--lib/roken/resolve.c711
-rw-r--r--lib/roken/resolve.h298
-rw-r--r--lib/roken/resource.h15
-rw-r--r--lib/roken/roken-common.h405
-rw-r--r--lib/roken/roken.awk40
-rw-r--r--lib/roken/roken.h.in706
-rw-r--r--lib/roken/roken_gethostby.c274
-rw-r--r--lib/roken/rtbl.3201
-rw-r--r--lib/roken/rtbl.c489
-rw-r--r--lib/roken/rtbl.h118
-rw-r--r--lib/roken/sendmsg.c65
-rw-r--r--lib/roken/setegid.c57
-rw-r--r--lib/roken/setenv.c66
-rw-r--r--lib/roken/seteuid.c57
-rw-r--r--lib/roken/setprogname.c61
-rw-r--r--lib/roken/signal.c80
-rw-r--r--lib/roken/simple_exec.c331
-rw-r--r--lib/roken/snprintf-test.c269
-rw-r--r--lib/roken/snprintf-test.h52
-rw-r--r--lib/roken/snprintf.c702
-rw-r--r--lib/roken/socket.c302
-rw-r--r--lib/roken/socket_wrapper.c1913
-rw-r--r--lib/roken/socket_wrapper.h146
-rw-r--r--lib/roken/strcasecmp.c58
-rw-r--r--lib/roken/strcollect.c96
-rw-r--r--lib/roken/strdup.c50
-rw-r--r--lib/roken/strerror.c57
-rw-r--r--lib/roken/strftime.c401
-rw-r--r--lib/roken/strlcat.c56
-rw-r--r--lib/roken/strlcpy.c60
-rw-r--r--lib/roken/strlwr.c53
-rw-r--r--lib/roken/strncasecmp.c62
-rw-r--r--lib/roken/strndup.c56
-rw-r--r--lib/roken/strnlen.c49
-rw-r--r--lib/roken/strpftime-test.c299
-rw-r--r--lib/roken/strpftime-test.h48
-rw-r--r--lib/roken/strpool.c110
-rw-r--r--lib/roken/strptime.c453
-rw-r--r--lib/roken/strsep.c61
-rw-r--r--lib/roken/strsep_copy.c69
-rw-r--r--lib/roken/strtok_r.c65
-rw-r--r--lib/roken/strupr.c53
-rw-r--r--lib/roken/swab.c54
-rw-r--r--lib/roken/test-mem.c199
-rw-r--r--lib/roken/test-mem.h39
-rw-r--r--lib/roken/test-readenv.c118
-rw-r--r--lib/roken/timegm.c88
-rw-r--r--lib/roken/timeval.c84
-rw-r--r--lib/roken/tm2time.c61
-rw-r--r--lib/roken/unsetenv.c70
-rw-r--r--lib/roken/unvis.c286
-rw-r--r--lib/roken/verify.c62
-rw-r--r--lib/roken/verr.c47
-rw-r--r--lib/roken/verrx.c47
-rw-r--r--lib/roken/vis.c335
-rw-r--r--lib/roken/vis.h115
-rw-r--r--lib/roken/vis.hin115
-rw-r--r--lib/roken/vsyslog.c115
-rw-r--r--lib/roken/vwarn.c46
-rw-r--r--lib/roken/vwarnx.c47
-rw-r--r--lib/roken/warn.c48
-rw-r--r--lib/roken/warnerr.c61
-rw-r--r--lib/roken/warnx.c48
-rw-r--r--lib/roken/write_pid.c99
-rw-r--r--lib/roken/writev.c64
-rw-r--r--lib/roken/xdbm.h52
172 files changed, 28718 insertions, 0 deletions
diff --git a/lib/roken/ChangeLog b/lib/roken/ChangeLog
new file mode 100644
index 0000000000000..6a9abe72078e1
--- /dev/null
+++ b/lib/roken/ChangeLog
@@ -0,0 +1,2196 @@
+2008-01-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add missing files.
+
+2007-08-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strftime.c: rewrite str[pf]time for testing.
+
+ * strptime.c: rewrite str[pf]time for testing.
+
+ * Makefile.am: add TEST_STRPFTIME
+
+2007-07-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ndbm_wrap.c (dbm_get): set dsize to 0 on failure.
+
+ * Makefile.am: add ndbm_wrap.[ch] to EXTRA_DIST
+
+ * ndbm_wrap.c (dbm_fetch): set dsize to 0 on failure.
+
+2007-07-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket_wrapper.c: Implement swrap_dup too.
+
+ * socket_wrapper.c: Add dup(dummy stub) and dup2(real).
+
+ * socket_wrapper.h: Add dup(dummy stub) and dup2(real).
+
+2007-07-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: New library version.
+
+2007-06-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken_gethostby.c: set proxy_port to 0 to pacify BEAM.
+
+2007-06-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * use "roken.h" consitantly
+
+2007-06-03 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * test-readenv.c: Free environment.
+
+ * environment.c (free_environment): free result of
+ read_environment().
+
+ * roken-common.h (free_environment): free result of
+ read_environment().
+
+2007-05-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * fnmatch.c: Do recursive call to rk_fnmatch
+
+2007-01-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c: Try harder to call res_ndestroy().
+
+2006-12-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: make sure built headers are copied to the
+ ${build_topdir}/include
+
+2006-12-15 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * unvis.c: Use internal version of rk_unvis
+
+ * unvis.c: Always include rk_versions.
+
+ * vis.c: Always include rk_versions.
+
+ * vis.hin: Fix argument for unvis and strsvisx.
+
+ * unvis.c: prefix unvis functions with rk_, and prototypes.
+
+2006-12-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * vis.c: Provide some prototypes for the rk_vis functions.
+
+2006-12-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ifaddrs.hin: Prefix getifaddrs functions with rk_ and do symbol
+ renaming.
+
+ * fnmatch.c: Prefix fnmatch functions with rk_ and do symbol
+ renaming.
+
+ * vis.hin: Prefix strvis functions with rk_ and do symbol
+ renaming.
+
+ * vis.c: prefix strvis functions with rk_
+
+ * Makefile.am: Install extra posix headers in <roken/...> to avoid
+ dup headers.
+
+2006-11-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket_wrapper.c (swrap_sendto): fail on to unknown si->type
+
+2006-11-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket_wrapper.c: A few fixes to have Heimdal pass the make
+ check under socket_wrapper. The first is a missing 'break' before
+ the (heimdal specific) IPv6 support. The second works around the
+ fact that sendto() *may* object to a destination being specified.
+ It appears to be that on Linux, this objects (with EISCONN) for
+ unix stream sockets, but not for TCP sockets. The alternate fix
+ would be to have the KDC use 'send()' in this case. Andrew Bartlett.
+
+2006-10-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: split dist and nondist HEADERS
+
+2006-10-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken.h.in: Add timegm glue.
+
+ * timegm.c: add timegm()
+
+ * socket_wrapper.c: Include <roken.h>, gives os socklen_t on IRIX
+ 6.4.
+
+ * socket_wrapper.c: Maybe include <sys/time.h> and/or maybe
+ include <time.h>.
+
+2006-10-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken.h.in: Revert prevois for now, the problem is that we have
+ to include symbols unconditionally, even for those that just needs
+ protos.
+
+ * roken.h.in: Provide symbol renaming, let see what breaks.
+
+ * socket_wrapper.c: Maybe include <sys/filio.h>.
+
+2006-10-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket_wrapper.c: more consitity check, remove dead code, add
+ socket length code, add missing break, make diffrent chars of type
+ type files for case-insensitiv filesystems
+
+ * socket_wrapper.c: try even hard to not use socket wrapper for
+ socket_wrapper itself.
+
+ * socket_wrapper.c: Force no socket wrapper for socket_wrapper
+ itself.
+
+2006-10-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket_wrapper.c: Maybe include <config.h>.
+
+ * socket_wrapper.c: Protect AF_INET6 with #ifdef HAVE_IPV6.
+
+ * socket_wrapper.c: Use a symbol for the v6 address.
+
+ * socket_wrapper.c: Add IPv6 suppport.
+
+ * socket_wrapper.[ch]: Include socket wrapper from samba4 (rev
+ 19179).
+
+2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add build_HEADERZ to EXTRA_DIST
+
+ * Makefile.am: Add man_MANS to EXTRA_DIST
+
+ * Makefile.am: Add to all objects BUILD_ROKEN_LIB.
+
+2006-09-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken.h.in: Add samba socket wrapper fragment.
+
+ * Makefile.am: Add samba socket wrapper fragment.
+
+2006-09-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * snprintf.c: reapply patch that went away in last commit
+
+ * snprintf-test.c: unbreak from previous commit
+
+ * snprintf.c: Add size_t formater (z modifer).
+
+ * snprintf-test.c: add tests for size_t printf formater
+
+2006-06-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rtbl.h: Add extern "C" for C++.
+
+ * rtbl.c: Add rtbl_add_column_entryv functions, printf like
+
+ * rtbl.h: Add rtbl_add_column_entryv functions, printf like
+
+2006-06-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * glob.hin: Add extern "C" for C++. From joerg at britannica dot
+ bec dot de
+
+ * fnmatch.hin: Add extern "C" for C++. From joerg at britannica
+ dot bec dot de
+
+2006-04-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * fnmatch.hin (fnmatch): CPP rename to rk_fnmatch
+
+2006-04-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c (dns_srv_order): change a if (ptr == NULL) continue
+ into a assert(ptr != NULL) since it could never happen, found by
+ the IBM code checker (beam). Thanks to Florian Krohm for
+ explaining it.
+
+2006-04-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken_gethostby.c (roken_gethostby): make addr_list one larger
+ to avoid a off-by-one error. Found by IBM checker.
+
+ * resolve.c: Plug memory leak found by IBM checker (and try to
+ please it).
+
+2006-02-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c: Spelling, from Alexey Dobriyan, via Jason McIntyre
+
+2006-01-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getcap.c: Don't use db support unless its build into libc but we
+ dont check for that now, so just disable the code. This removes
+ the dependency on libdb for roken, and that is a good thing since
+ it causes problem with nss plugins that uses DB3 that also
+ provides the same symbol, but with a diffrent ABI. so when the
+ application calls getpwnamn() and it linked to roken, it craches
+ in the nss functions.
+
+2006-01-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * hex.c (hex_decode): support decoding odd number of characters,
+ in the odd len case, the first character ends up in the first byte
+ in the lower nibble.
+
+ * hex-test.c: Check that we can decode single character hex chars.
+
+2005-12-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getifaddrs.c: Try handle HP/UX 11.nn, its diffrent from Solaris
+ large SIOCGIFCONF.
+
+2005-09-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken-common.h: Move rk_UNCONST to roken.h.in since it might use
+ uintptr_t depending on avaibility.
+
+ * roken.h.in: Include <stdint.h> if it exists. If avaiable, use
+ uintptr_t to define rk_UNCONST.
+
+2005-09-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken-common.h: Add rk_dumpdata.
+
+ * dumpdata.c: Add rk_dumpdata() that write a chunk of data into a
+ file for later processing by some other tool (like asn1_print).
+
+2005-09-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strptime.c: cast to unsigned char to make sure its not negative
+ when passing it to is* functions
+
+2005-09-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * socket.c: Add socket_set_ipv6only.
+
+ * roken-common.h: Add socket_set_ipv6only, remove some argument
+ names.
+
+2005-08-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strpool.c (rk_strpoolprintf): remove debug printf, plug memory
+ leak
+
+2005-08-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * setprogname.c (setprogname): const poision
+
+ * print_version.c: Removed, moved to libvers.
+
+2005-08-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c (dns_lookup_int): if we have res_ndestroy, prefeer
+ that before res_nclose
+
+2005-08-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getaddrinfo-test.c: Rename optind to optidx to avoid shadowing.
+
+2005-08-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gai_strerror.c: sprinkel more const
+
+ * gai_strerror.c, roken.h.in: Make return value of gai_strerror
+ const to match SUSv3. Prompted by Stefan Metzmacher change to
+ Samba.
+
+2005-07-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken.h.in: Remove parameter names to avoid shadow warnings.
+
+2005-07-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getifaddrs.c (nl_getlist): poll to get messages from kernel, and
+ retry if the message was lost
+ (free_nlmsglist): free all linked elements, not just the first one
+
+2005-07-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * snprintf-test.c: Check a very simple format string
+
+2005-07-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken.h.in: If we have <strings.h> include it, its needed for
+ strcasecmp() on those platforms that are SUS3/iso c99 strict (like
+ AIX)
+
+ * roken-common.h: remove duplicate ;
+
+2005-07-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken-common.h: rk_strpoolprintf first variable identifier is 3
+
+2005-06-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * base64.h: remove variable names
+
+2005-06-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken-common.h: fix format attribute
+
+ * Makefile.am (libroken_la_SOURCES): += strpool.c
+
+ * roken-common.h: add strpool, a printf collector to make it
+ eaiser to collect strings into one string
+
+ * strpool.c: add strpool, a printf collector to make it eaiser to
+ collect strings into one string
+
+2005-06-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * base64.c: Add const, from Andrew Abartlet <abartlet@samba.org>
+
+2005-06-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strpftime-test.c: test for "%Y%m"
+
+ * esetenv.c: unconst
+
+ * strptime.c: Write a new parse_number function that is possible
+ to limit that amount of numbers used, with this strptime can
+ handle strptime("200505", "%Y%m", &tm);
+
+2005-06-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getaddrinfo.c: avoid shadowing sin
+
+ * resolve-test.c: rename optind to optidx to avoid shadowing
+
+ * strptime.c: UNCONST return value from strptime
+
+ * strftime.c: rk_UNCONST argument mktime
+
+ * getnameinfo.c: avoid shadowing sin
+
+ * socket.c: avoid shadowing sin
+
+ * resolve.c (parse_record): fix casting to avoid losing const
+
+ * roken.awk: since we got no feedback regarding people running
+ heimdal on the crays, remove the quoted # version
+
+ * environment.c: rename index to idx to avoid shadowing
+
+2005-05-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse_reply-test.c: avoid signedness warnings
+
+ * test-mem.c: avoid signedness warnings
+
+2005-05-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * hex.c: include "roken.h" to avoid undefined size_t/ssize_t
+
+2005-05-24 Dave Love <fx@gnu.org>
+
+ * Makefile.am (snprintf_test_SOURCES): Add snprintf-test.h.
+
+2005-05-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * environment.c (rk_read_env_file): move assignment to later to
+ make pre c99 compiler happy
+
+2005-05-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strptime.c: use english spelling of March
+
+2005-05-17 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: only link with dblib if we need it
+
+ * Makefile.am: add test_readenv
+
+ * test-readenv.c: test for read_environment()
+
+ * environment.c: eliminate duplicates
+
+2005-05-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * issuid.c (issuid): change the #ifdef order to avoid unreachable
+ code warning.
+
+2005-05-10 Dave Love <fx@gnu.org>
+
+ * roken.h.in: Get daemon declared on Solaris (it's in unistd.h but
+ masked by a feature test), just to avoid a warning, since it has
+ int args. Include err.h unconditionally, since it's always
+ supplied.
+
+2005-05-04 Dave Love <fx@gnu.org>
+
+ * snprintf-test.c: Include snprintf-test.h earlier.
+
+2005-05-03 Dave Love <fx@gnu.org>
+
+ * snprintf.c: Include snprintf-test.h earlier.
+
+ * test-mem.c: Add member fd to map.
+ (rk_test_mem_alloc, rk_test_mem_free): Use it.
+
+2005-04-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getifaddrs.c: add break on default: statements, from Douglas
+ E. Engert
+
+ * snprintf.c (vsnprintf): don't write the NUL into the string if
+ the length was 0
+
+ * snprintf-test.c: add check that snprintf doesn't write the NUL
+ into the last byte when its a zero length input string
+
+ * parse_time-test.c: Include <err.h>.
+
+2005-04-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse_time-test.c: improve testing
+
+ * roken-common.h: add rk_realloc
+
+ * Makefile.am: add realloc
+
+ * realloc.c: add rk_realloc, unbroken version of realloc
+
+2005-04-26 Dave Love <fx@gnu.org>
+
+ * getusershell.c: Include roken.h
+
+2005-04-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * unvis.c: cast to unsigned char to make sure its not negative
+ when passing it to is* functions
+
+ * strptime.c: cast to unsigned char to make sure its not negative
+ when passing it to to* functions
+
+2005-04-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * simple_exec.c: don't close stderr, close all fd that is num 3
+ and larger
+
+ * simple_exec.c (pipe_execv): use closefrom
+
+ * add closefrom
+
+2005-04-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * add ROKEN_LIB_FUNCTION to all exported functions
+
+2005-04-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve-test.c: print DS
+
+2005-04-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse_time-test.c: remove unused variable
+
+2005-04-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strpftime-test.c: print size_t by casting to unsigned long
+
+ * base64-test.c: print size_t by casting to unsigned long
+
+ * hex-test.c: print size_t by casting to unsigned long
+
+ * resolve-test.c: print size_t by casting to unsigned long
+
+2005-04-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * snprintf-test.c (try): reset va_list argument between reuse,
+ from Peter Kruty <xkruty@fi.muni.cz>
+
+2005-03-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken_gethostby.c (roken_gethostby): s/sin/addr/ to avoid
+ shadowing
+
+ * resolve.c (dns_lookup_int): s/stat/state/ to avoid shadowing
+
+ * parse_units.c: avoid shadowing div
+
+2005-03-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * snprintf.c: use defined(TEST_SNPRINTF) like on all other places
+ in the same file
+
+2005-03-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * hex.c: check for overflows
+
+2005-03-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * vis.c: use RCSID instead of __RCSID
+
+2005-03-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: check_PROGRAMS += hex-test
+
+ * hex-test.c: hex encoding/decoding test
+
+ * hex.c: fix decodeing, it processed to much data and thus
+ returned the wrong length
+
+2005-03-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add hex.[ch]
+
+ * hex.c: add hex encoder/decoder
+
+2005-03-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * daemon.c fnmatch.c fnmatch.hin getcap.c getopt.c getusershell.c
+ glob.c glob.hin iruserok.c unvis.c vis.hin:
+
+ In 1997, the University of California, Berkeley issued a statement
+ retroactively relicensing all code held under their copyright from
+ a 4-clause 'traditional' BSD license to a new 3-clause 'revised'
+ BSD license, which removed the advertising clause.
+
+ From NetBSD, via Joel Baker, and Alistair G. Crooks
+
+ * getaddrinfo-test.c: remove stray ( in output
+
+ * vis.c: Update new revision from NetBSD (copyright update)
+
+2005-02-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: bump version to 17:0:1
+
+2005-01-19 Dave Love <d.love@dl.ac.uk>
+
+ * getusershell.c: Include ctype.h, cast argument to isspace to
+ unsigned char.
+
+2004-10-31 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse_time.3, parse_units.c: Change the behavior of the
+ parse_unit code to return the number of bytes needed to print the
+ whole string (minus the trailing '\0'), just like snprintf. Idea
+ from bugreport from Gabriel Kihlman <gk@stacken.kth.se>.
+
+ * parse_time-test.c Makefile.am test-mem.c test-mem.h: test parse_time
+
+2004-10-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c: put dns_type_to_string and dns_string_to_type in the
+ abi
+
+ * resolve.c: add ds_record
+
+ * resolve.h: add ds_record
+
+2004-10-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ndbm_wrap.c: undefine open so this works on solaris with large
+ file support From netbsd's pkgsrc via Gavan Fantom
+
+2004-09-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve-test.c: add --version/--help
+
+2004-09-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: make resolve-test a noinst program
+
+2004-09-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve-test.c: test program for libroken resolve from resolve.c
+
+ * Makefile.am: add resolve-test
+
+ * resolve.h: add constant for max DNS protocol packet size
+
+ * resolve.c (dns_lookup_int): grow the answer buffer to the size
+ the server send to us if the answer buffer was too small (limited
+ to the dns protocol max packet size)
+
+2004-08-26 Johan Danielsson <joda@pdc.kth.se>
+
+ * err.hin: no need to declare __progname here
+
+ * Makefile.am: always clean generated headers
+
+2004-06-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rtbl.3: use .In for header, remove trailing space
+
+2004-06-23 Johan Danielsson <joda@pdc.kth.se>
+
+ * rtbl.h: add protos and macros
+
+ * rtbl.c: implement a bunch of stuff:
+ - column separator (instead of global column prefix)
+ - per column suffix
+ - indexing columns by id-number instead of column header
+ - optional header supression (via settable flags)
+ - ability to end a row
+ - don't extend last column to full width
+
+2004-06-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.[ch]: add and use and bind9 version of rr type
+ (rk_ns_t_XXX) instead of the old bind4 version (T_XXX)
+
+2004-05-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c (stot): add AAAA
+
+2004-02-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * getarg.c (add_string): catch error from realloc
+
+2004-02-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * roken-common.h: add simple_execve_timed
+
+ * roken-common.h: add timed simple_exec
+
+ * simple_exec.c: add timed simple_exec
+
+2004-01-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gai_strerror.c: correct ifdef for EAI_ADDRFAMILY
+
+2003-12-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c: parse dns header, add support for SSHFP
+
+ * resolve.h: add cpp rewrite for sshfp_record
+
+ * resolve.h: add SSHFP, clean up the the dns_header
+
+2003-12-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.h: remove HEADER (only used for crays)
+
+ * resolve.c: number-of fields no longer stored in network order
+
+2003-12-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolve.c: remove depency on c99 types in resolv.h
+
+ * resolve.h: remove depency on c99 types
+
+2003-12-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * resolv.h: add more T_ types and inline the dns headers, all this
+ for bind9 resolvers
+
+2003-12-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gai_strerror.c: EAI_ADDRFAMILY and EAI_NODATA is deprecated
+
+ * roken-common.h: use EAI_NONAME instead of EAI_ADDRFAMILY to
+ check for if we need EAI_ macros
+
+2003-10-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * strptime.c: let t and n match zero or more whitespaces
+
+2003-08-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ndbm_wrap.c: patch for working with DB4 on heimdal-discuss
+ From: Luke Howard <lukeh@PADL.COM>
+
+2003-08-27 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: don't include discovered files in EXTRA_SOURCES;
+ don't depend on all header files, just the built ones
+
+2003-08-15 Johan Danielsson <joda@pdc.kth.se>
+
+ * emalloc.3: manpage
+
+2003-07-11 Love <lha@stacken.kth.se>
+
+ * resolve.c: AIX have broken res_nsearch() in 5.1 (5.0 also ?) so
+ just don't use res_nsearch on AIX
+
+2003-06-29 Johan Danielsson <joda@pdc.kth.se>
+
+ * snprintf.c: * don't ever print sign for unsigned conversions *
+ don't break when right justifying a number past the end of the
+ buffer * handle zero precision and the value zero more correctly
+
+2003-06-14 Love <lha@stacken.kth.se>
+
+ * glob.hin: prefix glob symbols with rk_
+
+2003-04-22 Love <lha@stacken.kth.se>
+
+ * resolve.c: copy NUL too, from janj@wenf.org via openbsd
+
+2003-04-16 Love <lha@stacken.kth.se>
+
+ * parse_units.h: remove typedef for units to avoid problems with
+ shadowing
+
+ * resolve.c: use strlcpy, from openbsd
+
+ * getcap.c: use strlcpy, from openbsd
+
+ * getarg.3: Change .Fd #include <header.h> to .In header.h
+ from Thomas Klausner <wiz@netbsd.org>
+
+2003-04-15 Love <lha@stacken.kth.se>
+
+ * socket.c (socket_set_tos): if setsockopt failed with EINVAL
+ failed, just ignore it, sock was probably a just a non AF_INET
+ socket
+
+2003-04-14 Love <lha@stacken.kth.se>
+
+ * strncasecmp.c: cast argument to toupper to unsigned char, from
+ Christian Biere <christianbiere@gmx.de> via NetBSD
+
+ * strlwr.c: cast argument to tolower to unsigned char, from
+ Christian Biere <christianbiere@gmx.de> via NetBSD
+
+ * strcasecmp.c: cast argument to toupper to unsigned char, from
+ Christian Biere <christianbiere@gmx.de> via NetBSD
+
+2003-03-19 Love <lha@stacken.kth.se>
+
+ * getarg.3: spelling, from <jmc@prioris.mini.pw.edu.pl>
+
+2003-03-07 Love <lha@stacken.kth.se>
+
+ * parse_bytes.c: use struct units instead of units
+
+ * parse_time.c: use struct units instead of units
+
+2003-03-04 Love <lha@stacken.kth.se>
+
+ * roken.awk: use full prototype for main
+
+2002-10-15 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.c: check length of txt records
+
+2002-09-10 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.awk: include config.h before stdio.h (breaks with
+ _FILE_OFFSET_BITS on solaris otherwise)
+
+2002-09-09 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.c: fix res_nsearch call, but don't use it for now, AIX5
+ has a broken version that trashes memory
+
+ * roken-common.h: fix typo in previous
+
+ * roken-common.h: change IRIX == 4 to IRIX4
+
+2002-09-04 Assar Westerlund <assar@kth.se>
+
+ * getifaddrs.c: remove some warnings from the linux-portion
+
+ * getnameinfo_verified.c (getnameinfo_verified): handle the case
+ of forward but no backward DNS information, and also describe the
+ desired behaviour. from Love <lha@stacken.kth.se>
+
+2002-09-04 Johan Danielsson <joda@pdc.kth.se>
+
+ * rtbl.c (rtbl_destroy): free whole table
+
+ * resolve.c: use res_nsearch if we have it (from Larry Greenfield)
+
+2002-09-03 Assar Westerlund <assar@kth.se>
+
+ * getifaddrs.c: add Linux AF_NETLINK getifaddrs from Hideaki
+ YOSHIFUJI of the Usagi project
+
+ * parse_reply-test.c: make this build and return 77 if there is no
+ mmap
+
+ * Makefile.am (parse_reply-test): add
+ * parse_reply-test.c: add a test case for parse_reply reading past
+ the given buffer
+ * resolve.c (parse_reply): update the arguments to more reasonable
+ types. allow parse_reply-test to call it
+
+2002-08-28 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.c (dns_srv_order): do alignment tricks with the random()
+ state (from NetBSD)
+
+2002-08-27 Assar Westerlund <assar@kth.se>
+
+ * resolve.c (parse_reply): verify the lengths (both external and
+ internal) are consistent and not too long
+ (dns_lookup_int): be conservative in the length sent in to to
+ parse_reply
+
+2002-08-26 Assar Westerlund <assar@kth.se>
+
+ * roken.h.in: add prototypes for str, unvis functions
+ * resolve.h: add fallback definition for T_AAAA
+
+2002-08-22 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: we may need a prototype for strndup
+
+2002-08-20 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: typedef ssize_t here
+
+ * getarg.c: don't put Ns before comma
+
+ * resolve.c: _res might not be available
+
+ * localtime_r.c: include stdio.h and roken.h
+
+ * strftime.c: only use altzone if we have it
+
+ * roken-common.h: AI_NUMERICHOST needs special handling
+
+ * strlcat.c: add some consistency checks
+
+ * strlcpy.c: make the logic simpler, and handle dst_sz == 0
+
+2002-08-19 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.h: prefix these functions to avoid conflicts with other
+ packages
+
+2002-08-14 Johan Danielsson <joda@pdc.kth.se>
+
+ * strsep_copy.c: don't write to buf if len == 0
+
+2002-05-31 Assar Westerlund <assar@pdc.kth.se>
+
+ * Makefile.am: *_LDADD: add LDADD, so that libroken is used
+
+2002-05-17 Johan Danielsson <joda@pdc.kth.se>
+
+ * xdbm.h: remove old dbm part
+
+2002-04-30 Johan Danielsson <joda@pdc.kth.se>
+
+ * ndbm_wrap.{c,h}: ndbm wrapper for newer db libraries
+
+2002-04-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: move mini_inetd protos to after addrinfo definition
+
+ * snprintf.c (append_number): make rep const
+
+ * getarg.h: rename optind and optarg to avoid some gcc warnings
+
+ * getarg.c: rename optind and optarg to avoid some gcc warnings
+
+2002-02-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * mini_inetd.c: mini_inetd_addrinfo that takes an addrinfo instead
+ of a port number
+
+2001-11-30 Assar Westerlund <assar@sics.se>
+
+ * getifaddrs.c: support SIOCGLIFCONF and SIOCGLIFFLAGS which are
+ used on Solaris 8 to retrieve addresses larger than `struct
+ sockaddr'. From Magnus Ahltorp <ahltorp@nada.kth.se> (with some
+ modifications by me)
+
+2001-10-27 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): set version to 15:0:6
+
+2001-10-22 Assar Westerlund <assar@sics.se>
+
+ * localtime_r.c: add
+
+2001-10-02 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.c (dns_srv_order): don't try to return a value
+
+2001-09-24 Johan Danielsson <joda@pdc.kth.se>
+
+ * snprintf.c: va_{start,end} fixes; from Thomas Klausner
+
+2001-09-20 Assar Westerlund <assar@sics.se>
+
+ * resolve.c (dns_srv_order): make sure of not reading after the
+ array
+
+2001-09-17 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): bump to 14:4:5
+ * snprintf.c: rename 'struct state' -> 'struct snprintf_test' to
+ avoid collision with resolv.h on aix
+
+2001-09-04 Assar Westerlund <assar@sics.se>
+
+ * parse_bytes-test.c, parse_bytes.c, parse_bytes.h, parse_units.c,
+ parse_units.h: use int instead of size_t as return values to be
+ compatible with snprintf
+
+ * strftime.c (strftime): check for return values from snprintf() <
+ 0
+
+2001-09-03 Johan Danielsson <joda@pdc.kth.se>
+
+ * socket.c: restrict is a keyword
+
+2001-09-03 Assar Westerlund <assar@sics.se>
+
+ * write_pid.c: handle atexit or on_exit
+
+ * Makefile.am (EXTRA_libroken_la_SOURCES): add vis.hin to help
+ solaris make
+
+2001-08-30 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: use LDADD directly
+
+2001-08-28 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): set to 14:3:5
+
+ * issuid.c (issuid): call issetugid if it exists
+
+2001-08-24 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: make it play better with recent automake
+
+2001-08-21 Assar Westerlund <assar@sics.se>
+
+ * glob.c: provide a fallback for ARG_MAX. from <tol@stacken.kth.se>
+
+ * roken.h.in: remove all winsock.h
+ for now, it does more harm than good under cygwin and if it should be
+ used, the correct conditional needs to be found
+ from <tol@stacken.kth.se>
+
+2001-08-17 Johan Danielsson <joda@pdc.kth.se>
+
+ * getaddrinfo.c: include a definition of in6addr_loopback if it
+ doesn't exist
+
+2001-08-10 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): update to 14:2:5
+
+2001-08-08 Assar Westerlund <assar@sics.se>
+
+ * hstrerror.c: move h_errno to its own file (h_errno.c)
+
+2001-08-04 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: add getarg.3
+
+2001-08-01 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (mini_inetd): explicitly use PF_UNSPEC. be more
+ resilient to bind/listen failing.
+
+2001-07-31 Assar Westerlund <assar@sics.se>
+
+ * getifaddrs.c (getifaddrs2): remove unused variables
+
+2001-07-31 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): update version to 14:1:5
+
+2001-07-23 Assar Westerlund <assar@sics.se>
+
+ * getarg.c (arg_match_long): fix parsing of arg_counter optional
+ argument
+
+2001-07-19 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): bump version to 14:0:5
+
+2001-07-17 Assar Westerlund <assar@sics.se>
+
+ * snprintf-test.h: add a file with renaming of the snprintf
+ functions, to be used for running the tests
+
+2001-07-11 Assar Westerlund <assar@sics.se>
+
+ * snprintf-test.c: add more %X tests, and long and conditional
+ long long tests
+ * snprintf.c: add support for printing long long (if available)
+
+2001-07-10 Assar Westerlund <assar@sics.se>
+
+ * getaddrinfo.c (add_hostent): adapt to const hostent_find_fqdn
+ * hostent_find_fqdn.c (hostent_find_fqdn): const-ize
+
+2001-07-09 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h (hostent_find_fqdn): add
+ * hostent_find_fqdn.c: separate out hostent_find_fqdn
+
+ * warnerr.c: move out getprogname, setprogname
+
+2001-07-03 Assar Westerlund <assar@sics.se>
+
+ * warnerr.c (setprogname): add const cast
+ * vis.c (SVIS): add some (unsigned char) before calling isfoo*
+ * Makefile.am (libroken_la_LDFLAGS:) set version to 13:0:4
+
+ * Makefile.am: add snprintf_test
+ * snprintf.c: rewrite so that it does not stop as soon as there
+ are no more characters to print, we need to figure out how long
+ the string would have to be. this also fixes snprintf(NULL, 0
+
+2001-06-21 Assar Westerlund <assar@sics.se>
+
+ * simple_exec.c (pipe_execv): remove unused variable
+
+2001-06-20 Johan Danielsson <joda@pdc.kth.se>
+
+ * getdtablesize.c: fix typo in obviously never used sysctl case
+
+ * simple_exec.c: rename check_status to wait_for_process, and
+ export it; function pipe_execv similar to popen, but with more
+ control over input and output
+
+ * roken-common.h: prototypes for wait_for_process and pipe_execv
+
+2001-06-17 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h: move emalloc et al to roken.h.in
+ * Makefile.am: make emalloc,ecalloc,erealloc,estrdup conditional
+ * emalloc.c, erealloc.c, estrup.c: use errx, since errno might not
+ be set reliably
+ * ecalloc.c: add for symmetry
+
+2001-06-09 Johan Danielsson <joda@pdc.kth.se>
+
+ * resolve.c: dns_srv_order to order srv records
+
+2001-06-08 Johan Danielsson <joda@pdc.kth.se>
+
+ * getarg.c: Grog tries to figure out if to use mdoc.old instead of
+ mdoc by looking at some macros that were only present in the old
+ version, and by looking at the number of .Oo's present. In
+ mdoc.old .Oo was a toggle, but in mdoc it's closed by .Oc, so if
+ the number of .Oo's is bigger than the number of .Oc's, it figures
+ it must be mdoc.old. This doesn't however account for called Oc's,
+ and thus grog thinks that valid pages are mdoc.old when they
+ infact are mdoc. So let's make sure that Oc's are not called by
+ other macros.
+
+2001-05-29 Assar Westerlund <assar@sics.se>
+
+ * base64-test.c (main): initialize numerr
+
+2001-05-28 Johan Danielsson <joda@pdc.kth.se>
+
+ * base64.c: clean up the decode mess somewhat
+
+ * base64-test.c: base64 tests
+
+2001-05-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: just use standard C types with bswap*
+
+ * bswap.c: just use standard C types
+
+2001-05-17 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: include all the headers that AC_GROK_TYPES tries for
+ finding u_int17_t et al
+
+ * Makefile.am: bump version to 12:0:3
+ * roken.h.in: re-add set_progname and get_progname for backwards
+ compatability
+ * warnerr.c: re-add set_progname and get_progname for backwards
+ compatability
+
+2001-05-12 Assar Westerlund <assar@sics.se>
+
+ * glob.c: add limits.h, from <shadow@dementia.org>
+
+2001-05-11 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: bswap.c
+
+ * bswap.c: bswap{16,32}
+
+2001-05-08 Assar Westerlund <assar@sics.se>
+
+ * freeaddrinfo.c (freeaddrinfo): also free every `struct
+ addrinfo'. from <tmartin@mirapoint.com>
+
+2001-04-25 Assar Westerlund <assar@sics.se>
+
+ * getarg.h (free_getarg_strings): add prototype
+ * getarg.c (free_getarg_strings): add function
+
+2001-04-21 Johan Danielsson <joda@pdc.kth.se>
+
+ * getarg.c: pack short flag options togther, to shorten the usage
+ string
+
+2001-04-17 Johan Danielsson <joda@pdc.kth.se>
+
+ * getifaddrs.c (getifaddrs2): close socket when done
+
+2001-03-26 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.awk: END has to be last with Sun's awk
+
+2001-03-26 Assar Westerlund <assar@sics.se>
+
+ * parse_units.c (parse_something): do not check the return value
+ from strtod, it might return != 0.0 when the string has no digits.
+ just testing if it consumed any characters is enough and more
+ resilient
+ * glob.c: add GLOB_LIMIT (from NetBSD)
+
+2001-02-20 Assar Westerlund <assar@sics.se>
+
+ * warnerr.c (warnerr): do not use __progname
+ * roken.h.in (setprogname, getprogname): add prototypes
+ * warnerr.c (setprogname, getprogname): rename to. change all
+ callers
+
+2001-02-12 Assar Westerlund <assar@sics.se>
+
+ * getnameinfo_verified.c (getnameinfo_verified): do the first
+ getnameinfo with NI_NUMERICSERV to avoid the error that bind 8.2.3
+ reports on not finding the service
+ (ENI_NOSERVNAME). reported by Ake Sandgren <ake@cs.umu.se>
+
+2001-02-09 Assar Westerlund <assar@sics.se>
+
+ * getnameinfo.c (doit): call inet_ntop with correct af, noted by
+ Ake Sandgren <ake@cs.umu.se>
+
+2001-02-08 Assar Westerlund <assar@sics.se>
+
+ * getnameinfo_verified.c (getnameinfo_verified): always capture
+ the service from getnameinfo so it can be sent back to getaddrinfo
+ and set socktype to avoid getaddrinfo not returning any addresses
+
+2001-01-30 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): bump version to 11:1:2
+ * print_version.c (print_version): add 2001
+
+2001-01-29 Assar Westerlund <assar@sics.se>
+
+ * getifaddrs.c (getifaddrs2): copy the entire sockaddr
+
+ * roken-common.h (_PATH_BSHELL): add
+
+2001-01-27 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: move __attribute__ to roken-common.h
+
+ * esetenv.c (esetenv): cast to handle a setenv that takes a `char
+ * which is the case on Unicos
+
+2000-12-29 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (EXTRA_libroken_la_SOURCES): ifaddrs.h ->
+ ifaddrs.hin
+
+2000-12-25 Assar Westerlund <assar@sics.se>
+
+ * getarg.c (print_arg): add a case for arg_strings
+
+2000-12-15 Johan Danielsson <joda@pdc.kth.se>
+
+ * snprintf.c (append_string): handle NULL strings by printing
+ `(null)'
+
+2000-12-12 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken-common.h: add c++ externs
+
+ * roken.h.in: fix last commit differently
+
+2000-12-11 Assar Westerlund <assar@sics.se>
+
+ * err.hin (warnerr): remove, it's not part of the err.h interface
+ * roken-common.h (warnerr): moved here from err.hin
+ * Makefile.am (libroken_la_LDFLAGS): set version to 11:0:2
+ * vis.c: s/u_int32_t/unsigned/ for systems that do not define
+ u_int32_t
+
+2000-12-10 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: rename some headers to avoid conflict with possible
+ system headers
+
+2000-12-06 Johan Danielsson <joda@pdc.kth.se>
+
+ * vis.c: make sure _DIAGASSERT is defined
+
+ * unvis.c: make sure _DIAGASSERT is defined
+
+ * Makefile.am: unvis.c, and vis.h
+
+ * vis.h: vis.h from NetBSD
+
+ * unvis.c: unvis from NetBSD
+
+ * roken.h.in: cleanup previous
+
+ * roken-common.h: make `extern "C"' into a macro, this make emacs
+ much happier
+
+ * vis.c: strvis implementation from NetBSD
+
+ * roken.h.in: add prototypes for strvis*
+
+2000-12-05 Johan Danielsson <joda@pdc.kth.se>
+
+ * ifaddrs.h: fix freeifaddrs prototype, and add ifa_broadaddr
+ macro
+
+ * getifaddrs.c: free some memory
+
+2000-12-04 Johan Danielsson <joda@pdc.kth.se>
+
+ * ifaddrs.h: getifaddrs implementation using SIOCGIFCONFIG etc
+
+ * getifaddrs.c: getifaddrs implementation using SIOCGIFCONFIG etc
+
+2000-10-08 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (mini_inetd): check that fds are not too large to
+ select on
+
+2000-09-24 Assar Westerlund <assar@sics.se>
+
+ * esetenv.c: new file/function
+
+2000-08-16 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 10:0:1
+
+2000-08-10 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (accept_it): type-correctness on parameters to
+ accept
+
+2000-08-07 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: add proto compat for getsockname
+
+2000-08-04 Johan Danielsson <joda@pdc.kth.se>
+
+ * write_pid.c: conditionalise pidfile
+
+ * write_pid.c: add pidfile function
+
+2000-07-25 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: bump version to 9:0:0
+
+ * warnerr.c: add get_progname
+
+2000-07-24 Assar Westerlund <assar@sics.se>
+
+ * getaddrinfo.c (add_hostent): if there's no fqdn in `he' try
+ reverse resolving to see if there's a fuller name there. don't
+ use just-freed memory
+
+2000-07-22 Assar Westerlund <assar@sics.se>
+
+ * xdbm.h: do not define ndbm functions in terms of dbm functions
+ if we're using db
+
+2000-07-20 Assar Westerlund <assar@sics.se>
+
+ * rtbl.c (rtbl_format): avoid printing an empty row at the end
+
+2000-07-19 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: make this compatible with `make dist'
+
+ * Makefile.am: revert version number for now
+
+2000-07-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * configure.in: AM_PROG_LIBTOOL -> AC_PROG_LIBTOOL
+
+2000-07-17 Johan Danielsson <joda@pdc.kth.se>
+
+ * Makefile.am: set ACLOCAL_AMFLAGS
+
+2000-07-15 Johan Danielsson <joda@pdc.kth.se>
+
+ * getaddrinfo_hostspec.c: add new function that takes socktype
+ hint as parameter
+
+2000-07-09 Assar Westerlund <assar@sics.se>
+
+ * rtbl.c (rtbl_add_column): initialize `col' completely
+
+ * configure.in: bring headers and functions more in-line with
+ what's actually being used
+
+2000-07-08 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.h.in: declare ether_addr and sockaddr_dl for AIX
+
+ * rtbl.{c,h}: simple table functions
+
+2000-07-08 Assar Westerlund <assar@sics.se>
+
+ * configure.in (AM_INIT_AUTOMAKE): bump version to 10
+ * configure.in (AC_BROKEN): add strsep_copy
+ * Makefile.am (ACLOCAL): fetch files from cf
+
+2000-07-01 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h (pid_file_*): fix protos
+
+2000-06-28 Assar Westerlund <assar@sics.se>
+
+ * getnameinfo_verified.c (getnameinfo_verified): free memory
+ returned from getaddrinfo
+
+2000-06-27 Assar Westerlund <assar@sics.se>
+
+ * resolve.c: export string_to_type and type_to_string
+ * resolve.c: add key,sig,cert update test-program
+ * resolve.h: add key,sig,cert
+
+2000-06-21 Assar Westerlund <assar@sics.se>
+
+ * resolve.h: add T_SIG, T_KEY
+ * resolve.c: add SIG and KEY
+ * Makefile.am (libroken_la_SOURCES): add environment.c and
+ write_pid.c
+
+ * write_pid.c: new file for writing a pid file.
+
+ * environment.c: new file with functionality for reading
+ /etc/environment. From Ake Sandgren <ake@cs.umu.se>
+
+2000-06-12 Johan Danielsson <joda@pdc.kth.se>
+
+ * strsep_copy.c: strsep, but with const stringp so returns string
+ in separate buffer
+
+2000-05-23 Assar Westerlund <assar@sics.se>
+
+ * vsyslog.c (vsyslog): calculate length of new format string
+ correctly
+
+2000-05-22 Johan Danielsson <joda@pdc.kth.se>
+
+ * getusershell.c: implment the AIX version use
+ /etc/security/login.cfg
+
+2000-05-21 Assar Westerlund <assar@sics.se>
+
+ * vsyslog.c (vsyslog): actually handle `%m'
+
+2000-05-15 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): set version to 8:1:3
+
+ * roken-common.h: moved __attribute__ to roken.h.in
+
+2000-04-14 Assar Westerlund <assar@sics.se>
+
+ * getaddrinfo_hostspec.c (roken_getaddrinfo_hostspec): copy the
+ correct length from `hostspec'. based on a patch from Love
+ <lha@s3.kth.se>
+
+2000-04-09 Assar Westerlund <assar@sics.se>
+
+ * xdbm.h: only include one of db.h and the dbm-series
+
+2000-04-05 Assar Westerlund <assar@sics.se>
+
+ * resolve.c (_resolve_debug): explicitly set to zero. this moves
+ the variable from bss to data and the dynamic linker on MacOS
+ X/Darwin seems unhappy with stuff in the bss segment.
+
+2000-04-03 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: set version to 8:0:3
+
+2000-03-11 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (_SS_PAD1SIZE): try to write an inpenetrable
+ expression that also works on Crays
+
+2000-03-09 Assar Westerlund <assar@sics.se>
+
+ * getarg.c (arg_match_short): backup optind when there's a missing
+ argument so that the error can point at the flag and not the
+ non-existant argument
+
+2000-03-03 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (SOURCES): add timeval.c
+ * Makefile.am (libroken_la_SOURCES): add timeval.c
+ * timeval.c: new file
+
+2000-02-19 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: set version to 7:1:2
+
+2000-02-16 Assar Westerlund <assar@sics.se>
+
+ * snprintf.c (PARSE_INT_FORMAT): note that shorts are actually
+ transmitted as ints
+ (according to the integer protomotion rules) in variable arguments
+ lists. Therefore, we should not call va_arg with short but rather
+ with int. See <http://www.debian.org/Bugs/db/57/57919.html> for
+ original bug report
+
+2000-02-13 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 7:0:2
+
+ * getarg.c (mandoc_template): also fix no- prefix in .Sh OPTIONS
+ * getarg.c (mandoc_template): better man-stuff for negative
+ options
+
+2000-02-07 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: set version to 6:0:1
+
+2000-02-06 Assar Westerlund <assar@sics.se>
+
+ * xdbm.h: hopefully catch a few more declarations by including
+ <ndbm.h> even if <db.h> was found
+
+2000-01-26 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (mini_inetd): separate number of allocated sockets
+ and number of actual ones
+ * mini_inetd.c (mini_inetd): count sockets properly. and fail if
+ we cannot bind any
+ * mini_inetd.c (mini_inetd): make failing to create a socket
+ non-fatal
+
+2000-01-09 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am(libroken_la_SOURCES): add strcollect.c
+ * Makefile.in: add strcollect.[co]
+ * simple_exec.c: use vstrcollect
+ * roken-common.h (_PATH_DEV): add
+ (strcollect, vstrcollect): add prototypes
+ * strcollect.c: new file. functions for collapsing an `va_list'
+ into an `char **'
+
+2000-01-06 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 5:0:0
+
+1999-12-30 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (strpftime_test_SOURCES): correct source file name
+
+ * roken.h.in (sockaddr_storage): change padding so that we have
+ one char[] of pad and then an unsigned long[] (for alignment and
+ padding). this works much better in practice.
+
+1999-12-22 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (sockaddr_storage): drop leading underscore on
+ `public' fields. this was the consensus on the ipng mailing list
+
+1999-12-21 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (strpftime-test): define sources to avoid having
+ '.o'
+ * Makefile.am (print_version.h): use $(EXEEXT)
+ * Makefile.am (roken.h): add $(EXEEXT) to make this work on cygwin
+ et al
+
+1999-12-20 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): bump version to 4:3:0
+
+ * getaddrinfo.c (get_nodes): use getipnodebyname instead of
+ gethostbyname(2)
+
+1999-12-16 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_LDFLAGS): bump version to 4:2:0
+
+ * roken.h.in (struct sockaddr_storage): redefine with the example
+ code from rfc2553
+
+ * getaddrinfo.c (get_null): set loopback with correct endianess
+ for v4. dunno about v6.
+
+1999-12-13 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: add prototypes for str[pf]time
+
+ * signal.c: macosx = rhapsody ~= nextstep also can't handle
+ various definitions of the same symbol.
+
+1999-12-12 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 4:1:0
+
+1999-12-06 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 4:0:0
+
+1999-12-05 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in: replace inaddr2str with getnameinfo_verified
+
+ * roken-common.h (INADDR_LOOPBACK): add fallback definition
+
+ * roken-common.h: move getnameinfo_verified to roken.h.in
+ * roken.h.in (inaddr2str): remove
+ * Makefile.am (libroken_la_SOURCES); removed inaddr2str
+ * roken-common.h (getnameinfo_verified): add prototype
+ * getnameinfo_verified.c: new file
+
+1999-12-04 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h: add constants for getaddrinfo, getnameinfo
+ * roken.h.in (socklen_t): make independent of sockaddr_storage
+ (AI_*, NI_*, EAI_*): move to roken-common.h
+
+1999-12-03 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (mini_inted): rewrite to use `getaddrinfo'
+ * getaddrinfo.c (const_v*): no sizeof(sizeof())
+ * getaddrinfo.c (add_hostent): search for the canonical name among
+ all aliases
+ (getaddrinfo): handle AI_NUMERICHOST correctly
+ * Makefile.am (EXTRA_libroken_la_SOURCES): add freeaddinfo,
+ getaddrinfo, getnameinfo, gai_strerror
+ (getaddrinfo_test): add
+ * Makefile.in (SOURCES): add freeaddinfo, getaddrinfo,
+ getnameinfo, gai_strerror
+ (getaddrinfo_test): add
+ * roken.h.in: arpa/inet.h: include
+ (socklen_t): add
+ (struct addrinfo): add
+ (EAI_*): add
+ (NI_*): add
+ (AI_*): add
+ (getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror): add
+ * getnameinfo.c: new file
+ * getaddrinfo-test.c: new file
+ * gai_strerror.c: new file
+ * getaddrinfo.c: new file
+ * freeaddrinfo.c: new file
+
+1999-11-25 Assar Westerlund <assar@sics.se>
+
+ * getopt.c (getopt): return -1 instead of EOF. From
+ <art@stacken.kth.se>
+
+1999-11-13 Assar Westerlund <assar@sics.se>
+
+ * strftime.c (strftime): handle `%z' and `%Z' in a tm_gmtoff-less
+ world
+
+ * getcap.c: make sure to use db only if we have both the library
+ and the header file
+
+1999-11-12 Assar Westerlund <assar@sics.se>
+
+ * getarg.h: add arg_counter
+ * getarg.c: add a new type of argument: `arg_counter' re-organize
+ the code somewhat
+
+ * Makefile.am: add strptime and strpftime-test
+
+ * snprintf.c (xyzprintf): try to do the right thing with an % at
+ the end of the format string
+
+ * strptime.c (strptime): implement '%U', '%V', '%W'
+ * strftime.c (strftime): implement '%U', '%V', '%W', '%z'
+
+ * strftime.c (strftime): correct %E and %O handling. do something
+ reasonable with "...%"
+
+ * strftime.c: replace the BSD implementation by one of our own
+ coding
+
+ * strptime.c : new file
+ * strpftime-test.c: new file
+
+1999-11-07 Assar Westerlund <assar@sics.se>
+
+ * parse_bytes-test.c: new file
+
+ * Makefile.am: add parse_bytes-test
+
+ * parse_units.c (parse_something): try to handle the case of no
+ value specified a little bit better
+
+1999-11-04 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 3:2:0
+
+1999-10-30 Assar Westerlund <assar@sics.se>
+
+ * snprintf.c (PARSE_INT_FORMAT): add redundant casts to work
+ around a gcc-bug that manifests itself on Linux-PPC. From Tom
+ Rini <trini@kernel.crashing.org>
+
+1999-10-28 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: bump version to 3:1:0
+
+ * roken.h.in: use `unsigned char' instead of `u_int8_t' to avoid
+ having to have that definition. this is the easy way out instead
+ of getting the definition here where it's needed. flame me.
+
+Fri Oct 22 15:39:31 1999 Bjoern Groenvall <bg@sics.se>
+
+ * k_getpwuid.c (k_getpwuid): getspuid() does not exist (even
+ though it should), use getspnam().
+
+1999-10-20 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: set version to 3:0:0
+
+1999-10-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * getarg.3: document arg_collect
+
+ * getarg.c: change the way arg_collect works; it's still quite
+ horrible though
+
+ * getarg.h: change type of the collect function
+
+1999-10-17 Assar Westerlund <assar@sics.se>
+
+ * xdbm.h: undo last commit
+
+ * xdbm.h: reorder db includes
+
+1999-10-10 Assar Westerlund <assar@sics.se>
+
+ * socket.c: const-ize and comment
+
+ * net_write.c: const-ize
+
+ * base64.c: const-ize
+
+1999-10-06 Assar Westerlund <assar@sics.se>
+
+ * getarg.c (getarg): also set optind when returning error
+
+1999-09-26 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: add parse_bytes.[ch]
+
+1999-09-24 Johan Danielsson <joda@pdc.kth.se>
+
+ * getarg.3: getarg manpage
+
+ * getarg.{c,h}: add a callback type to do more complicated processing
+
+ * getarg.{c,h}: add floating point support
+
+1999-09-16 Assar Westerlund <assar@sics.se>
+
+ * strlcat.c (strlcat): call strlcpy
+
+ * strlcpy.c: update name and prototype
+
+ * strlcat.c: update name and prototype
+
+ * roken.h.in: rename strc{py,at}_truncate to strlc{py,at}
+
+ * Makefile.am: rename strc{py,at}_truncate -> strlc{py,at}
+
+ * Makefile.in: rename strc{py,at}_truncate -> strlc{py,at}
+
+ * strcpy_truncate.c (strcpy_truncate): change return value to be
+ the length of `src'
+
+1999-08-16 Assar Westerlund <assar@sics.se>
+
+ * getcap.c: try to make this work on systems with DB
+
+1999-08-16 Johan Danielsson <joda@pdc.kth.se>
+
+ * getcap.c: protect from db-less systems
+
+1999-08-09 Johan Danielsson <joda@pdc.kth.se>
+
+ * simple_exec.c: add simple_exec{ve,le}
+
+ * getcap.c: getcap from NetBSD
+
+1999-08-06 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (sockaddr_storage): cater for those that have
+ v6-support also
+
+1999-08-05 Assar Westerlund <assar@sics.se>
+
+ * inet_ntop.c (inet_ntop_v4): remember to call ntohl
+
+1999-08-04 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h: add shutdown constants
+
+ * mini_inetd.c (listen_v4, listen_v6): handle the case of the
+ protocol not being supported
+
+1999-08-01 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (socket_set_reuseaddr): remove duplicate
+
+1999-07-29 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c (mini_inetd): fix my stupid bugs
+
+1999-07-28 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h: add socket* functions
+
+ * Makefile.am (libroken_la_SOURCES): add socket.c
+
+ * socket.c: new file, originally from appl/ftp/common
+
+ * Makefile.am: set version to 2:0:2
+
+ * roken.h.in (inet_pton): add prototype
+
+ * Makefile.am (EXTRA_libroken_la_SOURCES): add inet_pton
+
+ * inet_pton.c: new file
+
+ * getipnodebyname.c (getipnodebyname): try gethostbyname2 if we
+ have it
+
+1999-07-27 Assar Westerlund <assar@sics.se>
+
+ * mini_inetd.c: support IPv6
+
+1999-07-26 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am: set version to 1:0:1
+
+ * roken.h.in (inet_ntop): add prototype
+
+ * roken-common.h: (INET{,6}_ADDRSTRLEN): add
+
+ * inet_ntop.c: new file
+
+ * Makefile.am (EXTRA_libroken_la_SOURCES): add inet_ntop.c
+
+ * Makefile.am: move some files from libroken_la_SOURCES to
+ EXTRA_libroken_la_SOURCES
+
+ * snprintf.c: some signed vs unsigned casts
+
+1999-07-24 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (struct sockaddr_storage): define it needed
+
+1999-07-19 Assar Westerlund <assar@sics.se>
+
+ * Makefile.am (libroken_la_SOURCES): add copyhostent.c,
+ freehostent.c, getipnodebyname.c, getipnodebyaddr.c
+
+ * roken.h.in: <netdb.h>: include
+ (copyhostent, freehostent, getipnodebyname, getipnodebyaddr): add
+ prototypes
+
+ * roken-common.h: new constants for getipnodeby*
+
+ * Makefile.in (SOURCES): add freehostent, copyhostent,
+ getipnodebyname, getipnodebyaddr
+
+ * freehostent.c: new file
+
+ * copyhostent.c: new file
+
+ * getipnodebyaddr.c: new file
+
+ * getipnodebyname.c: new file
+
+1999-07-13 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (k_getpwnam): update prototype
+
+ * k_getpwnam.c (k_getpwnam): const-ize
+
+ * get_default_username.c (get_default_username): a better way of
+ guessing when the user has su:ed
+
+1999-07-08 Johan Danielsson <joda@pdc.kth.se>
+
+ * roken.awk: use puts, as suggested by Jeffrey Hutzelman
+ <jhutz+@cmu.edu>
+
+1999-07-06 Assar Westerlund <assar@sics.se>
+
+ * readv.c (readv): typo
+
+1999-07-03 Assar Westerlund <assar@sics.se>
+
+ * writev.c (writev): error check malloc properly
+
+ * sendmsg.c (sendmsg): error check malloc properly
+
+ * resolve.c (parse_reply): error check malloc properly
+
+ * recvmsg.c (recvmsg): error check malloc properly
+
+ * readv.c (readv): error check malloc properly
+
+1999-06-23 Assar Westerlund <assar@sics.se>
+
+ * parse_units.c (acc_units): move the special case of 0 -> 1 to
+ parse_something to avoid having it happen at the end of the string
+
+1999-06-15 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in: add get_default_username
+
+ * get_default_username.c: new file
+
+ * roken.h.in (get_default_username): add prototype
+
+ * Makefile.am: add get_default_username
+
+1999-05-08 Assar Westerlund <assar@sics.se>
+
+ * xdbm.h: also try <db.h> with DB_DBM_HSEARCH == 1
+
+ * strnlen.c (strnlen): update prototype
+
+ * Makefile.am: strndup.c: add
+
+ * Makefile.in: strndup.c: add
+
+ * roken.h.in (strndup): add
+ (strnlen): update prototype
+
+ * strndup.c: new file
+
+Fri Apr 16 17:59:30 1999 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: include strsep prototype if needed
+
+Thu Apr 15 14:04:03 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: make make-print-version.o depend on version.h
+
+Wed Apr 7 14:11:00 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: make it compile w/o krb4
+
+Sat Mar 27 17:33:03 1999 Johan Danielsson <joda@blubb.pdc.kth.se>
+
+ * snprintf.c (vasnprintf): correct check if realloc returns NULL
+
+Sat Mar 27 12:37:55 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: link print_version with -ldes to avoid unresolved
+ references if -lkrb is shared
+
+Sat Mar 20 03:42:30 1999 Assar Westerlund <assar@sics.se>
+
+ * roken-common.h (eread, ewrite): add
+
+ * simple_exec.c: add <roken.h>
+
+Fri Mar 19 21:29:58 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in: add eread, ewrite
+
+ * eread.c, ewrite.c: new files
+
+ * Makefile.am (libroken_la_SOURCES): add eread and ewrite
+
+Fri Mar 19 14:52:57 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: add version-info
+
+Thu Mar 18 12:53:32 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * Makefile.am: remove include_dir hack
+
+ * Makefile.am: parse_units.h
+
+ * Makefile.am: include Makefile.am.common
+
+Sat Mar 13 23:31:35 1999 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (SOURCES): add glob.c
+
+Thu Mar 11 15:02:21 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * iruserok.c: move innetgr() to separate file
+
+ * innetgr.c: move innetgr() to separate file
+
+ * hstrerror.c (hstrerror): add const to return type
+
+ * erealloc.c: fix types in format string
+
+ * emalloc.c: fix types in format string
+
+Wed Mar 10 16:36:55 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * resolve.c: ugly fix for crays
+
+Mon Mar 8 11:52:20 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * roken.h.in: protos for {un,}setenv
+
+1999-02-16 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (SOURCES): add fnmatch
+
+ * roken-common.h (abs): add
+
+Sat Feb 13 17:12:53 1999 Assar Westerlund <assar@sics.se>
+
+ * emalloc.c, erealloc.c, estrup.c: new files
+
+ * roken.h.in (mkstemp, gethostname): also includes prototypes if
+ they are needed.
+
+1998-12-23 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: mkstemp: add prototype
+
+1998-12-20 Assar Westerlund <assar@sics.se>
+
+ * snprintf.c, iruserok.c, parse-units.c: unsigned char-correctness
+
+ * roken.h.in (inet_aton): also chedk NEED_INET_ATON_PROTO
+
+ * roken-common.h: __attribute__: check for autoconf'd
+ HAVE___ATTRIBUTE__ instead of GNUC
+
+Sun Dec 6 19:53:21 1998 Assar Westerlund <assar@sics.se>
+
+ * parse_units.c (parse_something): func is called with val == 0 if
+ no unit was given
+ (acc_flags, acc_units): update to new standard
+
+Fri Nov 27 03:09:42 1998 Assar Westerlund <assar@sics.se>
+
+ * resolve.c (stot): constify
+ (type_to_string): always declare
+ (dns_lookup_int): correct debug output
+
+Thu Nov 26 23:43:55 1998 Assar Westerlund <assar@sics.se>
+
+ * resolve.c (dns_lookup_int): send rr_class to res_search
+
+Thu Nov 26 17:09:47 1998 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * resolve.c: some cleanup
+
+ * resolve.h: add T_NAPTR
+
+Sun Nov 22 10:23:07 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (WFLAGS): set
+
+ * k_getpwnam.c (k_getpwnam): check for `struct spwd'
+
+ * k_getpwuid.c (k_getpwuid): check for `struct spwd'
+
+Tue Sep 8 05:18:31 1998 Assar Westerlund <assar@sics.se>
+
+ * recvmsg.c (recvmsg): patch from bpreece@unity.ncsu.edu
+
+Fri Sep 4 16:29:27 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * vsyslog.c: asprintf -> vasprintf
+
+Tue Aug 18 22:25:52 1998 Assar Westerlund <assar@sics.se>
+
+ * getarg.h (arg_printusage): new signature
+
+ * getarg.c (arg_printusage): new parameter `progname'. NULL means
+ __progname.
+
+Sun Aug 9 14:53:44 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * Makefile.am: net_{read,write}.c
+
+Fri Jul 24 21:56:02 1998 Assar Westerlund <assar@sics.se>
+
+ * simple_exec.c (simple_execvp): loop around waitpid when errno ==
+ EINTR
+
+Thu Jul 23 20:24:35 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * Makefile.am: net_{read,write}.c
+
+Wed Jul 22 21:38:35 1998 Assar Westerlund <assar@sics.se>
+
+ * simple_exec.c (simple_execlp): initialize `argv'
+
+Mon Jul 13 23:01:22 1998 Assar Westerlund <assar@sics.se>
+
+ * inaddr2str.c (inaddr2str): don't advance hostent->h_addr_list,
+ use a copy instead
+
+Fri Jul 10 01:20:08 1998 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (net_write, net_read): add prototypes
+
+ * Makefile.in: net_{read,write}.c: add
+
+ * net_{read,write}.c: new files
+
+Tue Jun 30 17:29:09 1998 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in (issuid): add
+
+ * get_window_size.c: fix misspelling of TIOCGWINSZ and bad use of
+ fields
+
+Sun May 31 03:24:34 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c (mandoc_template): Put short and long options in
+ SYNOPSIS within the same [ ] pair.
+
+Sat May 30 00:13:01 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c (arg_printusage): try to keep options shorter than
+ column width
+
+ * get_window_size.c (get_window_size): check COLUMNS and LINES
+
+Fri May 29 00:05:04 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c (mandoc_template): Put short and long options in
+ DESCRIPTION on the same line.
+
+ * getarg.c (arg_match_long): make sure you only get an exact match
+ if the strings are the same length
+
+Thu May 14 02:23:40 1998 Assar Westerlund <assar@sics.se>
+
+ * roken.awk: stupid cray awk wants \#
+
+Fri May 1 01:29:36 1998 Assar Westerlund <assar@sics.se>
+
+ * print_version.c (print_version): according to ISO/ANSI C the
+ elements of `arg' are not constant and therefore not settable at
+ compile-time. Set the at run-time instead.
+
+Sun Apr 19 10:00:06 1998 Assar Westerlund <assar@sics.se>
+
+ * roken.h.in: include paths.h
+
+Sun Apr 5 12:30:49 1998 Assar Westerlund <assar@sics.se>
+
+ * Makefile.in (SOURCES): add roken_gethostby.c to make solaris
+ make happy
+
+Thu Mar 19 20:41:25 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * simple_exec.c: Simple fork+exec system() replacement.
+
+Fri Mar 6 00:21:53 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * roken_gethostby.c: Make `roken_gethostby_setup' take URL-like
+ specification instead of split up versions. Makes it easier for
+ calling applications.
+
+ * roken_gethostby.c: Another miracle of the 20th century:
+ gethostby* over HTTP.
+
+Sat Feb 21 15:18:36 1998 assar westerlund <assar@sics.se>
+
+ * parse_time.c (unparse_time_approx): new function that calls
+ `unparse_units_approx'
+
+ * parse_units.c (unparse_units_approx): new function that will
+ only print the first unit.
+
+ * Makefile.in: include parse_{time,units}
+
+Thu Feb 12 03:30:08 1998 Assar Westerlund <assar@sics.se>
+
+ * parse_time.c (print_time_table): don't return a void value.
+
+Tue Feb 3 11:06:24 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c (mandoc_template): Change date format to full month
+ name, and day of month without leading zero.
+
+Thu Jan 22 21:23:23 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c: Fix long form of negative flags.
+
+Mon Dec 29 23:31:10 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * roken.h.in: Include <err.h>, to get linux __progname.
+
+Sun Dec 21 09:45:18 1997 Assar Westerlund <assar@sics.se>
+
+ * parse_time.c (print_time_table): new function
+
+ * parse_units.c (print_flags_table, print_units_table): new
+ functions.
+
+Thu Dec 4 02:51:46 1997 Assar Westerlund <assar@sics.se>
+
+ * iruserok.c: moved here.
+
+ * snprintf.c (sn_append_char): don't write any terminating zero.
+ (as_reserve): don't loop. better heuristic for how much space to
+ realloc.
+ (vasnprintf): simplify initializing to one.
+
+Sun Nov 30 14:56:59 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * getarg.c: Add mandoc help back-end to getarg.
+
+Wed Nov 12 01:09:17 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * verr.c, verrx.c: Fix warnings by moving exit from.
+
+Tue Nov 11 21:12:09 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * parse_units.c: Change the list of separating characters (between
+ units) to comma, space, and tab, removing digits. Having digits in
+ this list makes a flag like `T42 generate a parse error. This
+ change makes `17m3s' an invalid time-spec (you need a space).
+
+Tue Nov 11 02:38:44 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: add <sys/socket.h>
+
+Sun Nov 9 04:48:46 1997 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * fnmatch.c: Add fnmatch from NetBSD
+
+Sun Nov 9 02:00:08 1997 Assar Westerlund <assar@sics.se>
+
+ * parse_units.c (parse_something): ignore white-space and ','
+
+Mon Nov 3 22:38:32 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: fclose prototype
+
+ * roken.h: add prototype for vsyslog
+
+ * Makefile.in: add some more source files to make soriasis make
+ happy
+
+Sat Nov 1 00:19:21 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: include <sys/uio.h> and <errno.h>.
+ prototypes for readv and writev
+
+ * readv.c, writev.c: new files
+
+Wed Oct 29 02:21:38 1997 Assar Westerlund <assar@sics.se>
+
+ * roken.h: Add ugly macros for openlog, gethostbyname,
+ gethostbyaddr, and getservbyname for the benefit of Crays. Add
+ default definition of MAXPATHLEN
diff --git a/lib/roken/Makefile.am b/lib/roken/Makefile.am
new file mode 100644
index 0000000000000..b1a4251fcddcb
--- /dev/null
+++ b/lib/roken/Makefile.am
@@ -0,0 +1,194 @@
+# $Id: Makefile.am 22409 2008-01-12 05:53:37Z lha $
+
+include $(top_srcdir)/Makefile.am.common
+
+ACLOCAL_AMFLAGS = -I ../../cf
+
+CLEANFILES = roken.h make-roken.c $(XHEADERS)
+
+lib_LTLIBRARIES = libroken.la
+libroken_la_LDFLAGS = -version-info 19:0:1
+libroken_la_CPPFLAGS = -DBUILD_ROKEN_LIB
+
+# XXX this is needed for the LIBOBJS objects
+CPPFLAGS = $(libroken_la_CPPFLAGS)
+
+noinst_PROGRAMS = make-roken snprintf-test resolve-test
+
+nodist_make_roken_SOURCES = make-roken.c
+
+check_PROGRAMS = \
+ base64-test \
+ getaddrinfo-test \
+ hex-test \
+ test-readenv \
+ parse_bytes-test \
+ parse_reply-test \
+ parse_time-test \
+ snprintf-test \
+ strpftime-test
+
+TESTS = $(check_PROGRAMS)
+
+LDADD = libroken.la $(LIB_crypt)
+make_roken_LDADD =
+
+noinst_LTLIBRARIES = libtest.la
+libtest_la_SOURCES = strftime.c strptime.c snprintf.c
+libtest_la_CFLAGS = -DTEST_SNPRINTF -DTEST_STRPFTIME
+
+parse_reply_test_SOURCES = parse_reply-test.c resolve.c
+parse_reply_test_CFLAGS = -DTEST_RESOLVE
+
+test_readenv_SOURCES = test-readenv.c test-mem.c
+
+parse_time_test_SOURCES = parse_time-test.c test-mem.c
+
+strpftime_test_SOURCES = strpftime-test.c strpftime-test.h
+strpftime_test_LDADD = libtest.la $(LDADD)
+strpftime_test_CFLAGS = -DTEST_STRPFTIME
+snprintf_test_SOURCES = snprintf-test.c snprintf-test.h
+snprintf_test_LDADD = libtest.la $(LDADD)
+snprintf_test_CFLAGS = -DTEST_SNPRINTF
+
+resolve_test_SOURCES = resolve-test.c
+
+libroken_la_SOURCES = \
+ base64.c \
+ bswap.c \
+ concat.c \
+ dumpdata.c \
+ environment.c \
+ eread.c \
+ esetenv.c \
+ ewrite.c \
+ getaddrinfo_hostspec.c \
+ get_default_username.c \
+ get_window_size.c \
+ getarg.c \
+ getnameinfo_verified.c \
+ getprogname.c \
+ h_errno.c \
+ hex.c \
+ hostent_find_fqdn.c \
+ issuid.c \
+ k_getpwnam.c \
+ k_getpwuid.c \
+ mini_inetd.c \
+ net_read.c \
+ net_write.c \
+ parse_bytes.c \
+ parse_time.c \
+ parse_units.c \
+ realloc.c \
+ resolve.c \
+ roken_gethostby.c \
+ rtbl.c \
+ rtbl.h \
+ setprogname.c \
+ signal.c \
+ simple_exec.c \
+ snprintf.c \
+ socket.c \
+ strcollect.c \
+ strpool.c \
+ timeval.c \
+ tm2time.c \
+ unvis.c \
+ verify.c \
+ vis.c \
+ vis.h \
+ warnerr.c \
+ write_pid.c \
+ xdbm.h
+
+EXTRA_libroken_la_SOURCES = \
+ err.hin \
+ glob.hin \
+ fnmatch.hin \
+ ifaddrs.hin \
+ vis.hin
+
+libroken_la_LIBADD = @LTLIBOBJS@
+
+$(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS)
+
+BUILT_SOURCES = make-roken.c roken.h
+
+if have_err_h
+err_h =
+else
+err_h = err.h
+endif
+
+if have_fnmatch_h
+fnmatch_h =
+else
+fnmatch_h = fnmatch.h
+endif
+
+if have_glob_h
+glob_h =
+else
+glob_h = glob.h
+endif
+
+if have_ifaddrs_h
+ifaddrs_h =
+else
+ifaddrs_h = ifaddrs.h
+endif
+
+if have_vis_h
+vis_h =
+else
+vis_h = vis.h
+endif
+
+## these are controlled by configure
+XHEADERS = $(err_h) $(fnmatch_h) $(glob_h) $(ifaddrs_h) $(vis_h)
+CLEANFILES += err.h fnmatch.h glob.h ifaddrs.h vis.h
+
+dist_include_HEADERS = \
+ base64.h \
+ getarg.h \
+ hex.h \
+ parse_bytes.h \
+ parse_time.h \
+ parse_units.h \
+ resolve.h \
+ roken-common.h \
+ rtbl.h \
+ xdbm.h
+
+if have_socket_wrapper
+libroken_la_SOURCES += socket_wrapper.c socket_wrapper.h
+dist_include_HEADERS += socket_wrapper.h
+endif
+
+build_HEADERZ = test-mem.h $(XHEADERS)
+
+nodist_include_HEADERS = roken.h
+rokenincludedir = $(includedir)/roken
+nodist_rokeninclude_HEADERS = $(XHEADERS)
+
+man_MANS = getarg.3 parse_time.3 rtbl.3 ecalloc.3
+
+SUFFIXES += .hin
+.hin.h:
+ cp $< $@
+
+roken.h: make-roken$(EXEEXT)
+ @./make-roken$(EXEEXT) > tmp.h ;\
+ if [ -f roken.h ] && cmp -s tmp.h roken.h ; then rm -f tmp.h ; \
+ else rm -f roken.h; mv tmp.h roken.h; fi
+
+make-roken.c: roken.h.in roken.awk
+ $(AWK) -f $(srcdir)/roken.awk $(srcdir)/roken.h.in > make-roken.c
+
+EXTRA_DIST = \
+ roken.awk roken.h.in \
+ $(man_MANS) \
+ test-mem.h \
+ ndbm_wrap.c \
+ ndbm_wrap.h
diff --git a/lib/roken/Makefile.in b/lib/roken/Makefile.in
new file mode 100644
index 0000000000000..0398523aae576
--- /dev/null
+++ b/lib/roken/Makefile.in
@@ -0,0 +1,1426 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# $Id: Makefile.am 22409 2008-01-12 05:53:37Z lha $
+
+# $Id: Makefile.am.common 10998 2002-05-19 18:35:37Z joda $
+
+# $Id: Makefile.am.common 22488 2008-01-21 11:47:22Z lha $
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(am__dist_include_HEADERS_DIST) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(top_srcdir)/Makefile.am.common \
+ $(top_srcdir)/cf/Makefile.am.common ChangeLog chown.c \
+ closefrom.c copyhostent.c daemon.c ecalloc.c emalloc.c \
+ erealloc.c err.c errx.c estrdup.c fchown.c flock.c fnmatch.c \
+ freeaddrinfo.c freehostent.c gai_strerror.c getaddrinfo.c \
+ getcap.c getcwd.c getdtablesize.c getegid.c geteuid.c getgid.c \
+ gethostname.c getifaddrs.c getipnodebyaddr.c getipnodebyname.c \
+ getnameinfo.c getopt.c gettimeofday.c getuid.c getusershell.c \
+ glob.c hstrerror.c inet_aton.c inet_ntop.c inet_pton.c \
+ initgroups.c innetgr.c install-sh iruserok.c localtime_r.c \
+ lstat.c memmove.c missing mkinstalldirs mkstemp.c putenv.c \
+ rcmd.c readv.c recvmsg.c sendmsg.c setegid.c setenv.c \
+ seteuid.c strcasecmp.c strdup.c strerror.c strftime.c \
+ strlcat.c strlcpy.c strlwr.c strncasecmp.c strndup.c strnlen.c \
+ strptime.c strsep.c strsep_copy.c strtok_r.c strupr.c swab.c \
+ timegm.c unsetenv.c verr.c verrx.c vsyslog.c vwarn.c vwarnx.c \
+ warn.c warnx.c writev.c
+noinst_PROGRAMS = make-roken$(EXEEXT) snprintf-test$(EXEEXT) \
+ resolve-test$(EXEEXT)
+check_PROGRAMS = base64-test$(EXEEXT) getaddrinfo-test$(EXEEXT) \
+ hex-test$(EXEEXT) test-readenv$(EXEEXT) \
+ parse_bytes-test$(EXEEXT) parse_reply-test$(EXEEXT) \
+ parse_time-test$(EXEEXT) snprintf-test$(EXEEXT) \
+ strpftime-test$(EXEEXT)
+@have_socket_wrapper_TRUE@am__append_1 = socket_wrapper.c socket_wrapper.h
+@have_socket_wrapper_TRUE@am__append_2 = socket_wrapper.h
+subdir = lib/roken
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
+ $(top_srcdir)/cf/auth-modules.m4 $(top_srcdir)/cf/autobuild.m4 \
+ $(top_srcdir)/cf/broken-getaddrinfo.m4 \
+ $(top_srcdir)/cf/broken-glob.m4 \
+ $(top_srcdir)/cf/broken-realloc.m4 \
+ $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \
+ $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \
+ $(top_srcdir)/cf/capabilities.m4 \
+ $(top_srcdir)/cf/check-compile-et.m4 \
+ $(top_srcdir)/cf/check-getpwnam_r-posix.m4 \
+ $(top_srcdir)/cf/check-man.m4 \
+ $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \
+ $(top_srcdir)/cf/check-type-extra.m4 \
+ $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \
+ $(top_srcdir)/cf/check-xau.m4 $(top_srcdir)/cf/crypto.m4 \
+ $(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/destdirs.m4 \
+ $(top_srcdir)/cf/dlopen.m4 \
+ $(top_srcdir)/cf/find-func-no-libs.m4 \
+ $(top_srcdir)/cf/find-func-no-libs2.m4 \
+ $(top_srcdir)/cf/find-func.m4 \
+ $(top_srcdir)/cf/find-if-not-broken.m4 \
+ $(top_srcdir)/cf/framework-security.m4 \
+ $(top_srcdir)/cf/have-struct-field.m4 \
+ $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.m4 \
+ $(top_srcdir)/cf/krb-bigendian.m4 \
+ $(top_srcdir)/cf/krb-func-getlogin.m4 \
+ $(top_srcdir)/cf/krb-ipv6.m4 $(top_srcdir)/cf/krb-prog-ln-s.m4 \
+ $(top_srcdir)/cf/krb-readline.m4 \
+ $(top_srcdir)/cf/krb-struct-spwd.m4 \
+ $(top_srcdir)/cf/krb-struct-winsize.m4 \
+ $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \
+ $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \
+ $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \
+ $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \
+ $(top_srcdir)/cf/resolv.m4 $(top_srcdir)/cf/retsigtype.m4 \
+ $(top_srcdir)/cf/roken-frag.m4 \
+ $(top_srcdir)/cf/socket-wrapper.m4 $(top_srcdir)/cf/sunos.m4 \
+ $(top_srcdir)/cf/telnet.m4 $(top_srcdir)/cf/test-package.m4 \
+ $(top_srcdir)/cf/version-script.m4 $(top_srcdir)/cf/wflags.m4 \
+ $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" \
+ "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" \
+ "$(DESTDIR)$(rokenincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
+libroken_la_DEPENDENCIES = @LTLIBOBJS@
+am__libroken_la_SOURCES_DIST = base64.c bswap.c concat.c dumpdata.c \
+ environment.c eread.c esetenv.c ewrite.c \
+ getaddrinfo_hostspec.c get_default_username.c \
+ get_window_size.c getarg.c getnameinfo_verified.c \
+ getprogname.c h_errno.c hex.c hostent_find_fqdn.c issuid.c \
+ k_getpwnam.c k_getpwuid.c mini_inetd.c net_read.c net_write.c \
+ parse_bytes.c parse_time.c parse_units.c realloc.c resolve.c \
+ roken_gethostby.c rtbl.c rtbl.h setprogname.c signal.c \
+ simple_exec.c snprintf.c socket.c strcollect.c strpool.c \
+ timeval.c tm2time.c unvis.c verify.c vis.c vis.h warnerr.c \
+ write_pid.c xdbm.h socket_wrapper.c socket_wrapper.h
+@have_socket_wrapper_TRUE@am__objects_1 = \
+@have_socket_wrapper_TRUE@ libroken_la-socket_wrapper.lo
+am_libroken_la_OBJECTS = libroken_la-base64.lo libroken_la-bswap.lo \
+ libroken_la-concat.lo libroken_la-dumpdata.lo \
+ libroken_la-environment.lo libroken_la-eread.lo \
+ libroken_la-esetenv.lo libroken_la-ewrite.lo \
+ libroken_la-getaddrinfo_hostspec.lo \
+ libroken_la-get_default_username.lo \
+ libroken_la-get_window_size.lo libroken_la-getarg.lo \
+ libroken_la-getnameinfo_verified.lo libroken_la-getprogname.lo \
+ libroken_la-h_errno.lo libroken_la-hex.lo \
+ libroken_la-hostent_find_fqdn.lo libroken_la-issuid.lo \
+ libroken_la-k_getpwnam.lo libroken_la-k_getpwuid.lo \
+ libroken_la-mini_inetd.lo libroken_la-net_read.lo \
+ libroken_la-net_write.lo libroken_la-parse_bytes.lo \
+ libroken_la-parse_time.lo libroken_la-parse_units.lo \
+ libroken_la-realloc.lo libroken_la-resolve.lo \
+ libroken_la-roken_gethostby.lo libroken_la-rtbl.lo \
+ libroken_la-setprogname.lo libroken_la-signal.lo \
+ libroken_la-simple_exec.lo libroken_la-snprintf.lo \
+ libroken_la-socket.lo libroken_la-strcollect.lo \
+ libroken_la-strpool.lo libroken_la-timeval.lo \
+ libroken_la-tm2time.lo libroken_la-unvis.lo \
+ libroken_la-verify.lo libroken_la-vis.lo \
+ libroken_la-warnerr.lo libroken_la-write_pid.lo \
+ $(am__objects_1)
+libroken_la_OBJECTS = $(am_libroken_la_OBJECTS)
+libroken_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libroken_la_LDFLAGS) $(LDFLAGS) -o $@
+libtest_la_LIBADD =
+am_libtest_la_OBJECTS = libtest_la-strftime.lo libtest_la-strptime.lo \
+ libtest_la-snprintf.lo
+libtest_la_OBJECTS = $(am_libtest_la_OBJECTS)
+libtest_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libtest_la_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(noinst_PROGRAMS)
+base64_test_SOURCES = base64-test.c
+base64_test_OBJECTS = base64-test.$(OBJEXT)
+base64_test_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+base64_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+getaddrinfo_test_SOURCES = getaddrinfo-test.c
+getaddrinfo_test_OBJECTS = getaddrinfo-test.$(OBJEXT)
+getaddrinfo_test_LDADD = $(LDADD)
+getaddrinfo_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+hex_test_SOURCES = hex-test.c
+hex_test_OBJECTS = hex-test.$(OBJEXT)
+hex_test_LDADD = $(LDADD)
+hex_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+nodist_make_roken_OBJECTS = make-roken.$(OBJEXT)
+make_roken_OBJECTS = $(nodist_make_roken_OBJECTS)
+make_roken_DEPENDENCIES =
+parse_bytes_test_SOURCES = parse_bytes-test.c
+parse_bytes_test_OBJECTS = parse_bytes-test.$(OBJEXT)
+parse_bytes_test_LDADD = $(LDADD)
+parse_bytes_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+am_parse_reply_test_OBJECTS = \
+ parse_reply_test-parse_reply-test.$(OBJEXT) \
+ parse_reply_test-resolve.$(OBJEXT)
+parse_reply_test_OBJECTS = $(am_parse_reply_test_OBJECTS)
+parse_reply_test_LDADD = $(LDADD)
+parse_reply_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+parse_reply_test_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(parse_reply_test_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_parse_time_test_OBJECTS = parse_time-test.$(OBJEXT) \
+ test-mem.$(OBJEXT)
+parse_time_test_OBJECTS = $(am_parse_time_test_OBJECTS)
+parse_time_test_LDADD = $(LDADD)
+parse_time_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+am_resolve_test_OBJECTS = resolve-test.$(OBJEXT)
+resolve_test_OBJECTS = $(am_resolve_test_OBJECTS)
+resolve_test_LDADD = $(LDADD)
+resolve_test_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+am_snprintf_test_OBJECTS = snprintf_test-snprintf-test.$(OBJEXT)
+snprintf_test_OBJECTS = $(am_snprintf_test_OBJECTS)
+am__DEPENDENCIES_2 = libroken.la $(am__DEPENDENCIES_1)
+snprintf_test_DEPENDENCIES = libtest.la $(am__DEPENDENCIES_2)
+snprintf_test_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(snprintf_test_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_strpftime_test_OBJECTS = strpftime_test-strpftime-test.$(OBJEXT)
+strpftime_test_OBJECTS = $(am_strpftime_test_OBJECTS)
+strpftime_test_DEPENDENCIES = libtest.la $(am__DEPENDENCIES_2)
+strpftime_test_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(strpftime_test_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_test_readenv_OBJECTS = test-readenv.$(OBJEXT) test-mem.$(OBJEXT)
+test_readenv_OBJECTS = $(am_test_readenv_OBJECTS)
+test_readenv_LDADD = $(LDADD)
+test_readenv_DEPENDENCIES = libroken.la $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libroken_la_SOURCES) $(EXTRA_libroken_la_SOURCES) \
+ $(libtest_la_SOURCES) base64-test.c getaddrinfo-test.c \
+ hex-test.c $(nodist_make_roken_SOURCES) parse_bytes-test.c \
+ $(parse_reply_test_SOURCES) $(parse_time_test_SOURCES) \
+ $(resolve_test_SOURCES) $(snprintf_test_SOURCES) \
+ $(strpftime_test_SOURCES) $(test_readenv_SOURCES)
+DIST_SOURCES = $(am__libroken_la_SOURCES_DIST) \
+ $(EXTRA_libroken_la_SOURCES) $(libtest_la_SOURCES) \
+ base64-test.c getaddrinfo-test.c hex-test.c parse_bytes-test.c \
+ $(parse_reply_test_SOURCES) $(parse_time_test_SOURCES) \
+ $(resolve_test_SOURCES) $(snprintf_test_SOURCES) \
+ $(strpftime_test_SOURCES) $(test_readenv_SOURCES)
+man3dir = $(mandir)/man3
+MANS = $(man_MANS)
+am__dist_include_HEADERS_DIST = base64.h getarg.h hex.h parse_bytes.h \
+ parse_time.h parse_units.h resolve.h roken-common.h rtbl.h \
+ xdbm.h socket_wrapper.h
+dist_includeHEADERS_INSTALL = $(INSTALL_HEADER)
+nodist_includeHEADERS_INSTALL = $(INSTALL_HEADER)
+nodist_rokenincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(dist_include_HEADERS) $(nodist_include_HEADERS) \
+ $(nodist_rokeninclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CC = @CC@
+CFLAGS = @CFLAGS@
+COMPILE_ET = @COMPILE_ET@
+CPP = @CPP@
+
+# XXX this is needed for the LIBOBJS objects
+CPPFLAGS = $(libroken_la_CPPFLAGS)
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBLIB = @DBLIB@
+DEFS = @DEFS@
+DIR_com_err = @DIR_com_err@
+DIR_hcrypto = @DIR_hcrypto@
+DIR_hdbdir = @DIR_hdbdir@
+DIR_roken = @DIR_roken@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+GROFF = @GROFF@
+INCLUDES_roken = @INCLUDES_roken@
+INCLUDE_hcrypto = @INCLUDE_hcrypto@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+INCLUDE_krb4 = @INCLUDE_krb4@
+INCLUDE_openldap = @INCLUDE_openldap@
+INCLUDE_readline = @INCLUDE_readline@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_VERSION_SCRIPT = @LDFLAGS_VERSION_SCRIPT@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_roken = @LIBADD_roken@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_NDBM = @LIB_NDBM@
+LIB_XauFileName = @LIB_XauFileName@
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_XauWriteAuth = @LIB_XauWriteAuth@
+LIB_bswap16 = @LIB_bswap16@
+LIB_bswap32 = @LIB_bswap32@
+LIB_com_err = @LIB_com_err@
+LIB_com_err_a = @LIB_com_err_a@
+LIB_com_err_so = @LIB_com_err_so@
+LIB_crypt = @LIB_crypt@
+LIB_db_create = @LIB_db_create@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_door_create = @LIB_door_create@
+LIB_el_init = @LIB_el_init@
+LIB_freeaddrinfo = @LIB_freeaddrinfo@
+LIB_gai_strerror = @LIB_gai_strerror@
+LIB_getaddrinfo = @LIB_getaddrinfo@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_gethostbyname2 = @LIB_gethostbyname2@
+LIB_getnameinfo = @LIB_getnameinfo@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_hcrypto = @LIB_hcrypto@
+LIB_hcrypto_a = @LIB_hcrypto_a@
+LIB_hcrypto_appl = @LIB_hcrypto_appl@
+LIB_hcrypto_so = @LIB_hcrypto_so@
+LIB_hesiod = @LIB_hesiod@
+LIB_hstrerror = @LIB_hstrerror@
+LIB_kdb = @LIB_kdb@
+LIB_krb4 = @LIB_krb4@
+LIB_loadquery = @LIB_loadquery@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_openldap = @LIB_openldap@
+LIB_openpty = @LIB_openpty@
+LIB_otp = @LIB_otp@
+LIB_pidfile = @LIB_pidfile@
+LIB_readline = @LIB_readline@
+LIB_res_ndestroy = @LIB_res_ndestroy@
+LIB_res_nsearch = @LIB_res_nsearch@
+LIB_res_search = @LIB_res_search@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VERSIONING = @VERSIONING@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dpagaix_cflags = @dpagaix_cflags@
+dpagaix_ldadd = @dpagaix_ldadd@
+dpagaix_ldflags = @dpagaix_ldflags@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUFFIXES = .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .hin
+AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken)
+@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME
+AM_CFLAGS = $(WFLAGS)
+CP = cp
+buildinclude = $(top_builddir)/include
+LIB_getattr = @LIB_getattr@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_setpcred = @LIB_setpcred@
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+NROFF_MAN = groff -mandoc -Tascii
+LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la \
+@KRB5_TRUE@ $(top_builddir)/lib/asn1/libasn1.la
+
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la
+@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la
+ACLOCAL_AMFLAGS = -I ../../cf
+CLEANFILES = roken.h make-roken.c $(XHEADERS) err.h fnmatch.h glob.h \
+ ifaddrs.h vis.h
+lib_LTLIBRARIES = libroken.la
+libroken_la_LDFLAGS = -version-info 19:0:1
+libroken_la_CPPFLAGS = -DBUILD_ROKEN_LIB
+nodist_make_roken_SOURCES = make-roken.c
+TESTS = $(check_PROGRAMS)
+LDADD = libroken.la $(LIB_crypt)
+make_roken_LDADD =
+noinst_LTLIBRARIES = libtest.la
+libtest_la_SOURCES = strftime.c strptime.c snprintf.c
+libtest_la_CFLAGS = -DTEST_SNPRINTF -DTEST_STRPFTIME
+parse_reply_test_SOURCES = parse_reply-test.c resolve.c
+parse_reply_test_CFLAGS = -DTEST_RESOLVE
+test_readenv_SOURCES = test-readenv.c test-mem.c
+parse_time_test_SOURCES = parse_time-test.c test-mem.c
+strpftime_test_SOURCES = strpftime-test.c strpftime-test.h
+strpftime_test_LDADD = libtest.la $(LDADD)
+strpftime_test_CFLAGS = -DTEST_STRPFTIME
+snprintf_test_SOURCES = snprintf-test.c snprintf-test.h
+snprintf_test_LDADD = libtest.la $(LDADD)
+snprintf_test_CFLAGS = -DTEST_SNPRINTF
+resolve_test_SOURCES = resolve-test.c
+libroken_la_SOURCES = base64.c bswap.c concat.c dumpdata.c \
+ environment.c eread.c esetenv.c ewrite.c \
+ getaddrinfo_hostspec.c get_default_username.c \
+ get_window_size.c getarg.c getnameinfo_verified.c \
+ getprogname.c h_errno.c hex.c hostent_find_fqdn.c issuid.c \
+ k_getpwnam.c k_getpwuid.c mini_inetd.c net_read.c net_write.c \
+ parse_bytes.c parse_time.c parse_units.c realloc.c resolve.c \
+ roken_gethostby.c rtbl.c rtbl.h setprogname.c signal.c \
+ simple_exec.c snprintf.c socket.c strcollect.c strpool.c \
+ timeval.c tm2time.c unvis.c verify.c vis.c vis.h warnerr.c \
+ write_pid.c xdbm.h $(am__append_1)
+EXTRA_libroken_la_SOURCES = \
+ err.hin \
+ glob.hin \
+ fnmatch.hin \
+ ifaddrs.hin \
+ vis.hin
+
+libroken_la_LIBADD = @LTLIBOBJS@
+BUILT_SOURCES = make-roken.c roken.h
+@have_err_h_FALSE@err_h = err.h
+@have_err_h_TRUE@err_h =
+@have_fnmatch_h_FALSE@fnmatch_h = fnmatch.h
+@have_fnmatch_h_TRUE@fnmatch_h =
+@have_glob_h_FALSE@glob_h = glob.h
+@have_glob_h_TRUE@glob_h =
+@have_ifaddrs_h_FALSE@ifaddrs_h = ifaddrs.h
+@have_ifaddrs_h_TRUE@ifaddrs_h =
+@have_vis_h_FALSE@vis_h = vis.h
+@have_vis_h_TRUE@vis_h =
+XHEADERS = $(err_h) $(fnmatch_h) $(glob_h) $(ifaddrs_h) $(vis_h)
+dist_include_HEADERS = base64.h getarg.h hex.h parse_bytes.h \
+ parse_time.h parse_units.h resolve.h roken-common.h rtbl.h \
+ xdbm.h $(am__append_2)
+build_HEADERZ = test-mem.h $(XHEADERS)
+nodist_include_HEADERS = roken.h
+rokenincludedir = $(includedir)/roken
+nodist_rokeninclude_HEADERS = $(XHEADERS)
+man_MANS = getarg.3 parse_time.3 rtbl.3 ecalloc.3
+EXTRA_DIST = \
+ roken.awk roken.h.in \
+ $(man_MANS) \
+ test-mem.h \
+ ndbm_wrap.c \
+ ndbm_wrap.h
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .hin .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps lib/roken/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign --ignore-deps lib/roken/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libroken.la: $(libroken_la_OBJECTS) $(libroken_la_DEPENDENCIES)
+ $(libroken_la_LINK) -rpath $(libdir) $(libroken_la_OBJECTS) $(libroken_la_LIBADD) $(LIBS)
+libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES)
+ $(libtest_la_LINK) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+base64-test$(EXEEXT): $(base64_test_OBJECTS) $(base64_test_DEPENDENCIES)
+ @rm -f base64-test$(EXEEXT)
+ $(LINK) $(base64_test_OBJECTS) $(base64_test_LDADD) $(LIBS)
+getaddrinfo-test$(EXEEXT): $(getaddrinfo_test_OBJECTS) $(getaddrinfo_test_DEPENDENCIES)
+ @rm -f getaddrinfo-test$(EXEEXT)
+ $(LINK) $(getaddrinfo_test_OBJECTS) $(getaddrinfo_test_LDADD) $(LIBS)
+hex-test$(EXEEXT): $(hex_test_OBJECTS) $(hex_test_DEPENDENCIES)
+ @rm -f hex-test$(EXEEXT)
+ $(LINK) $(hex_test_OBJECTS) $(hex_test_LDADD) $(LIBS)
+make-roken$(EXEEXT): $(make_roken_OBJECTS) $(make_roken_DEPENDENCIES)
+ @rm -f make-roken$(EXEEXT)
+ $(LINK) $(make_roken_OBJECTS) $(make_roken_LDADD) $(LIBS)
+parse_bytes-test$(EXEEXT): $(parse_bytes_test_OBJECTS) $(parse_bytes_test_DEPENDENCIES)
+ @rm -f parse_bytes-test$(EXEEXT)
+ $(LINK) $(parse_bytes_test_OBJECTS) $(parse_bytes_test_LDADD) $(LIBS)
+parse_reply-test$(EXEEXT): $(parse_reply_test_OBJECTS) $(parse_reply_test_DEPENDENCIES)
+ @rm -f parse_reply-test$(EXEEXT)
+ $(parse_reply_test_LINK) $(parse_reply_test_OBJECTS) $(parse_reply_test_LDADD) $(LIBS)
+parse_time-test$(EXEEXT): $(parse_time_test_OBJECTS) $(parse_time_test_DEPENDENCIES)
+ @rm -f parse_time-test$(EXEEXT)
+ $(LINK) $(parse_time_test_OBJECTS) $(parse_time_test_LDADD) $(LIBS)
+resolve-test$(EXEEXT): $(resolve_test_OBJECTS) $(resolve_test_DEPENDENCIES)
+ @rm -f resolve-test$(EXEEXT)
+ $(LINK) $(resolve_test_OBJECTS) $(resolve_test_LDADD) $(LIBS)
+snprintf-test$(EXEEXT): $(snprintf_test_OBJECTS) $(snprintf_test_DEPENDENCIES)
+ @rm -f snprintf-test$(EXEEXT)
+ $(snprintf_test_LINK) $(snprintf_test_OBJECTS) $(snprintf_test_LDADD) $(LIBS)
+strpftime-test$(EXEEXT): $(strpftime_test_OBJECTS) $(strpftime_test_DEPENDENCIES)
+ @rm -f strpftime-test$(EXEEXT)
+ $(strpftime_test_LINK) $(strpftime_test_OBJECTS) $(strpftime_test_LDADD) $(LIBS)
+test-readenv$(EXEEXT): $(test_readenv_OBJECTS) $(test_readenv_DEPENDENCIES)
+ @rm -f test-readenv$(EXEEXT)
+ $(LINK) $(test_readenv_OBJECTS) $(test_readenv_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -c -o $@ $<
+
+libroken_la-base64.lo: base64.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
+
+libroken_la-bswap.lo: bswap.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-bswap.lo `test -f 'bswap.c' || echo '$(srcdir)/'`bswap.c
+
+libroken_la-concat.lo: concat.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-concat.lo `test -f 'concat.c' || echo '$(srcdir)/'`concat.c
+
+libroken_la-dumpdata.lo: dumpdata.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-dumpdata.lo `test -f 'dumpdata.c' || echo '$(srcdir)/'`dumpdata.c
+
+libroken_la-environment.lo: environment.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-environment.lo `test -f 'environment.c' || echo '$(srcdir)/'`environment.c
+
+libroken_la-eread.lo: eread.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-eread.lo `test -f 'eread.c' || echo '$(srcdir)/'`eread.c
+
+libroken_la-esetenv.lo: esetenv.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-esetenv.lo `test -f 'esetenv.c' || echo '$(srcdir)/'`esetenv.c
+
+libroken_la-ewrite.lo: ewrite.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-ewrite.lo `test -f 'ewrite.c' || echo '$(srcdir)/'`ewrite.c
+
+libroken_la-getaddrinfo_hostspec.lo: getaddrinfo_hostspec.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-getaddrinfo_hostspec.lo `test -f 'getaddrinfo_hostspec.c' || echo '$(srcdir)/'`getaddrinfo_hostspec.c
+
+libroken_la-get_default_username.lo: get_default_username.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-get_default_username.lo `test -f 'get_default_username.c' || echo '$(srcdir)/'`get_default_username.c
+
+libroken_la-get_window_size.lo: get_window_size.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-get_window_size.lo `test -f 'get_window_size.c' || echo '$(srcdir)/'`get_window_size.c
+
+libroken_la-getarg.lo: getarg.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-getarg.lo `test -f 'getarg.c' || echo '$(srcdir)/'`getarg.c
+
+libroken_la-getnameinfo_verified.lo: getnameinfo_verified.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-getnameinfo_verified.lo `test -f 'getnameinfo_verified.c' || echo '$(srcdir)/'`getnameinfo_verified.c
+
+libroken_la-getprogname.lo: getprogname.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-getprogname.lo `test -f 'getprogname.c' || echo '$(srcdir)/'`getprogname.c
+
+libroken_la-h_errno.lo: h_errno.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-h_errno.lo `test -f 'h_errno.c' || echo '$(srcdir)/'`h_errno.c
+
+libroken_la-hex.lo: hex.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-hex.lo `test -f 'hex.c' || echo '$(srcdir)/'`hex.c
+
+libroken_la-hostent_find_fqdn.lo: hostent_find_fqdn.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-hostent_find_fqdn.lo `test -f 'hostent_find_fqdn.c' || echo '$(srcdir)/'`hostent_find_fqdn.c
+
+libroken_la-issuid.lo: issuid.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-issuid.lo `test -f 'issuid.c' || echo '$(srcdir)/'`issuid.c
+
+libroken_la-k_getpwnam.lo: k_getpwnam.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-k_getpwnam.lo `test -f 'k_getpwnam.c' || echo '$(srcdir)/'`k_getpwnam.c
+
+libroken_la-k_getpwuid.lo: k_getpwuid.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-k_getpwuid.lo `test -f 'k_getpwuid.c' || echo '$(srcdir)/'`k_getpwuid.c
+
+libroken_la-mini_inetd.lo: mini_inetd.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-mini_inetd.lo `test -f 'mini_inetd.c' || echo '$(srcdir)/'`mini_inetd.c
+
+libroken_la-net_read.lo: net_read.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-net_read.lo `test -f 'net_read.c' || echo '$(srcdir)/'`net_read.c
+
+libroken_la-net_write.lo: net_write.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-net_write.lo `test -f 'net_write.c' || echo '$(srcdir)/'`net_write.c
+
+libroken_la-parse_bytes.lo: parse_bytes.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-parse_bytes.lo `test -f 'parse_bytes.c' || echo '$(srcdir)/'`parse_bytes.c
+
+libroken_la-parse_time.lo: parse_time.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-parse_time.lo `test -f 'parse_time.c' || echo '$(srcdir)/'`parse_time.c
+
+libroken_la-parse_units.lo: parse_units.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-parse_units.lo `test -f 'parse_units.c' || echo '$(srcdir)/'`parse_units.c
+
+libroken_la-realloc.lo: realloc.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-realloc.lo `test -f 'realloc.c' || echo '$(srcdir)/'`realloc.c
+
+libroken_la-resolve.lo: resolve.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-resolve.lo `test -f 'resolve.c' || echo '$(srcdir)/'`resolve.c
+
+libroken_la-roken_gethostby.lo: roken_gethostby.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-roken_gethostby.lo `test -f 'roken_gethostby.c' || echo '$(srcdir)/'`roken_gethostby.c
+
+libroken_la-rtbl.lo: rtbl.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-rtbl.lo `test -f 'rtbl.c' || echo '$(srcdir)/'`rtbl.c
+
+libroken_la-setprogname.lo: setprogname.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-setprogname.lo `test -f 'setprogname.c' || echo '$(srcdir)/'`setprogname.c
+
+libroken_la-signal.lo: signal.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-signal.lo `test -f 'signal.c' || echo '$(srcdir)/'`signal.c
+
+libroken_la-simple_exec.lo: simple_exec.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-simple_exec.lo `test -f 'simple_exec.c' || echo '$(srcdir)/'`simple_exec.c
+
+libroken_la-snprintf.lo: snprintf.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-snprintf.lo `test -f 'snprintf.c' || echo '$(srcdir)/'`snprintf.c
+
+libroken_la-socket.lo: socket.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c
+
+libroken_la-strcollect.lo: strcollect.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-strcollect.lo `test -f 'strcollect.c' || echo '$(srcdir)/'`strcollect.c
+
+libroken_la-strpool.lo: strpool.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-strpool.lo `test -f 'strpool.c' || echo '$(srcdir)/'`strpool.c
+
+libroken_la-timeval.lo: timeval.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c
+
+libroken_la-tm2time.lo: tm2time.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-tm2time.lo `test -f 'tm2time.c' || echo '$(srcdir)/'`tm2time.c
+
+libroken_la-unvis.lo: unvis.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-unvis.lo `test -f 'unvis.c' || echo '$(srcdir)/'`unvis.c
+
+libroken_la-verify.lo: verify.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-verify.lo `test -f 'verify.c' || echo '$(srcdir)/'`verify.c
+
+libroken_la-vis.lo: vis.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-vis.lo `test -f 'vis.c' || echo '$(srcdir)/'`vis.c
+
+libroken_la-warnerr.lo: warnerr.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-warnerr.lo `test -f 'warnerr.c' || echo '$(srcdir)/'`warnerr.c
+
+libroken_la-write_pid.lo: write_pid.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-write_pid.lo `test -f 'write_pid.c' || echo '$(srcdir)/'`write_pid.c
+
+libroken_la-socket_wrapper.lo: socket_wrapper.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libroken_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libroken_la-socket_wrapper.lo `test -f 'socket_wrapper.c' || echo '$(srcdir)/'`socket_wrapper.c
+
+libtest_la-strftime.lo: strftime.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtest_la_CFLAGS) $(CFLAGS) -c -o libtest_la-strftime.lo `test -f 'strftime.c' || echo '$(srcdir)/'`strftime.c
+
+libtest_la-strptime.lo: strptime.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtest_la_CFLAGS) $(CFLAGS) -c -o libtest_la-strptime.lo `test -f 'strptime.c' || echo '$(srcdir)/'`strptime.c
+
+libtest_la-snprintf.lo: snprintf.c
+ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtest_la_CFLAGS) $(CFLAGS) -c -o libtest_la-snprintf.lo `test -f 'snprintf.c' || echo '$(srcdir)/'`snprintf.c
+
+parse_reply_test-parse_reply-test.o: parse_reply-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_reply_test_CFLAGS) $(CFLAGS) -c -o parse_reply_test-parse_reply-test.o `test -f 'parse_reply-test.c' || echo '$(srcdir)/'`parse_reply-test.c
+
+parse_reply_test-parse_reply-test.obj: parse_reply-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_reply_test_CFLAGS) $(CFLAGS) -c -o parse_reply_test-parse_reply-test.obj `if test -f 'parse_reply-test.c'; then $(CYGPATH_W) 'parse_reply-test.c'; else $(CYGPATH_W) '$(srcdir)/parse_reply-test.c'; fi`
+
+parse_reply_test-resolve.o: resolve.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_reply_test_CFLAGS) $(CFLAGS) -c -o parse_reply_test-resolve.o `test -f 'resolve.c' || echo '$(srcdir)/'`resolve.c
+
+parse_reply_test-resolve.obj: resolve.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parse_reply_test_CFLAGS) $(CFLAGS) -c -o parse_reply_test-resolve.obj `if test -f 'resolve.c'; then $(CYGPATH_W) 'resolve.c'; else $(CYGPATH_W) '$(srcdir)/resolve.c'; fi`
+
+snprintf_test-snprintf-test.o: snprintf-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snprintf_test_CFLAGS) $(CFLAGS) -c -o snprintf_test-snprintf-test.o `test -f 'snprintf-test.c' || echo '$(srcdir)/'`snprintf-test.c
+
+snprintf_test-snprintf-test.obj: snprintf-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snprintf_test_CFLAGS) $(CFLAGS) -c -o snprintf_test-snprintf-test.obj `if test -f 'snprintf-test.c'; then $(CYGPATH_W) 'snprintf-test.c'; else $(CYGPATH_W) '$(srcdir)/snprintf-test.c'; fi`
+
+strpftime_test-strpftime-test.o: strpftime-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(strpftime_test_CFLAGS) $(CFLAGS) -c -o strpftime_test-strpftime-test.o `test -f 'strpftime-test.c' || echo '$(srcdir)/'`strpftime-test.c
+
+strpftime_test-strpftime-test.obj: strpftime-test.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(strpftime_test_CFLAGS) $(CFLAGS) -c -o strpftime_test-strpftime-test.obj `if test -f 'strpftime-test.c'; then $(CYGPATH_W) 'strpftime-test.c'; else $(CYGPATH_W) '$(srcdir)/strpftime-test.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man3: $(man3_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
+ @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.3*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 3*) ;; \
+ *) ext='3' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \
+ done
+uninstall-man3:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.3*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 3*) ;; \
+ *) ext='3' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man3dir)/$$inst"; \
+ done
+install-dist_includeHEADERS: $(dist_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(dist_include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(dist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(dist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-dist_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+install-nodist_includeHEADERS: $(nodist_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(nodist_include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(nodist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+ $(nodist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+ done
+
+uninstall-nodist_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_include_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(includedir)/$$f"; \
+ done
+install-nodist_rokenincludeHEADERS: $(nodist_rokeninclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(rokenincludedir)" || $(MKDIR_P) "$(DESTDIR)$(rokenincludedir)"
+ @list='$(nodist_rokeninclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(nodist_rokenincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(rokenincludedir)/$$f'"; \
+ $(nodist_rokenincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(rokenincludedir)/$$f"; \
+ done
+
+uninstall-nodist_rokenincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_rokeninclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(rokenincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(rokenincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(HEADERS) \
+ all-local
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(rokenincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_includeHEADERS install-man \
+ install-nodist_includeHEADERS \
+ install-nodist_rokenincludeHEADERS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man3
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-man uninstall-nodist_includeHEADERS \
+ uninstall-nodist_rokenincludeHEADERS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+
+uninstall-man: uninstall-man3
+
+.MAKE: install-am install-data-am install-exec-am install-strip \
+ uninstall-am
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-TESTS check-am \
+ check-local clean clean-checkPROGRAMS clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS ctags dist-hook distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-hook install-dist_includeHEADERS install-dvi \
+ install-dvi-am install-exec install-exec-am install-exec-hook \
+ install-html install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-man3 \
+ install-nodist_includeHEADERS \
+ install-nodist_rokenincludeHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-dist_includeHEADERS \
+ uninstall-hook uninstall-libLTLIBRARIES uninstall-man \
+ uninstall-man3 uninstall-nodist_includeHEADERS \
+ uninstall-nodist_rokenincludeHEADERS
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ echo "*"; \
+ echo "* Failed to install $$x setuid root"; \
+ echo "*"; \
+ fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(nobase_include_HEADERS)
+ @foo='$(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " $(CP) $$file $(buildinclude)/$$f"; \
+ $(CP) $$file $(buildinclude)/$$f; \
+ fi ; \
+ done ; \
+ foo='$(nobase_include_HEADERS)'; \
+ for f in $$foo; do \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ $(mkdir_p) $(buildinclude)/`dirname $$f` ; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " $(CP) $$file $(buildinclude)/$$f"; \
+ $(CP) $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+
+check-local::
+ @if test '$(CHECK_LOCAL)' = "no-check-local"; then \
+ foo=''; elif test '$(CHECK_LOCAL)'; then \
+ foo='$(CHECK_LOCAL)'; else \
+ foo='$(PROGRAMS)'; fi; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if (./$$i --version && ./$$i --help) > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0 || exit 1; \
+ fi
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat-mans:
+ $(SHELL) $(top_srcdir)/cf/install-catman.sh install "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+
+uninstall-cat-mans:
+ $(SHELL) $(top_srcdir)/cf/install-catman.sh uninstall "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+
+install-data-hook: install-cat-mans
+uninstall-hook: uninstall-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+#
+# Useful target for debugging
+#
+
+check-valgrind:
+ tobjdir=`cd $(top_builddir) && pwd` ; \
+ tsrcdir=`cd $(top_srcdir) && pwd` ; \
+ env TESTS_ENVIRONMENT="$${tobjdir}/libtool --mode execute valgrind --leak-check=full --trace-children=yes --quiet -q --num-callers=30 --suppressions=$${tsrcdir}/cf/valgrind-suppressions" make check
+
+#
+# Target to please samba build farm, builds distfiles in-tree.
+# Will break when automake changes...
+#
+
+distdir-in-tree: $(DISTFILES) $(INFO_DEPS)
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" != .; then \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) distdir-in-tree) ; \
+ fi ; \
+ done
+
+$(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS)
+.hin.h:
+ cp $< $@
+
+roken.h: make-roken$(EXEEXT)
+ @./make-roken$(EXEEXT) > tmp.h ;\
+ if [ -f roken.h ] && cmp -s tmp.h roken.h ; then rm -f tmp.h ; \
+ else rm -f roken.h; mv tmp.h roken.h; fi
+
+make-roken.c: roken.h.in roken.awk
+ $(AWK) -f $(srcdir)/roken.awk $(srcdir)/roken.h.in > make-roken.c
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/roken/acconfig.h b/lib/roken/acconfig.h
new file mode 100644
index 0000000000000..5fbe685ce386d
--- /dev/null
+++ b/lib/roken/acconfig.h
@@ -0,0 +1,36 @@
+@BOTTOM@
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) isoc_realloc((X), (Y))
+#define isoc_realloc(X, Y) ((X) ? realloc((X), (Y)) : malloc(Y))
+#endif
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (const char *)rcsid, "\100(#)" msg }
+
+#undef PROTOTYPES
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+/*
+ * Define NDBM if you are using the 4.3 ndbm library (which is part of
+ * libc). If not defined, 4.2 dbm will be assumed.
+ */
+#if defined(HAVE_DBM_FIRSTKEY)
+#define NDBM
+#endif
+
+/*
+ * Defining this enables lots of useful (and used) extensions on
+ * glibc-based systems such as Linux
+ */
+
+#define _GNU_SOURCE
diff --git a/lib/roken/acinclude.m4 b/lib/roken/acinclude.m4
new file mode 100644
index 0000000000000..1d0197c5ce37b
--- /dev/null
+++ b/lib/roken/acinclude.m4
@@ -0,0 +1,9 @@
+dnl $Id$
+dnl
+dnl Only put things that for some reason can't live in the `cf'
+dnl directory in this file.
+dnl
+
+dnl $xId: misc.m4,v 1.1 1997/12/14 15:59:04 joda Exp $
+dnl
+define(upcase,`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`)dnl
diff --git a/lib/roken/base64-test.c b/lib/roken/base64-test.c
new file mode 100644
index 0000000000000..435e41b1832a3
--- /dev/null
+++ b/lib/roken/base64-test.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: base64-test.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include "roken.h"
+#include <base64.h>
+
+int
+main(int argc, char **argv)
+{
+ int numerr = 0;
+ int numtest = 1;
+ struct test {
+ void *data;
+ size_t len;
+ const char *result;
+ } *t, tests[] = {
+ { "", 0 , "" },
+ { "1", 1, "MQ==" },
+ { "22", 2, "MjI=" },
+ { "333", 3, "MzMz" },
+ { "4444", 4, "NDQ0NA==" },
+ { "55555", 5, "NTU1NTU=" },
+ { "abc:def", 7, "YWJjOmRlZg==" },
+ { NULL }
+ };
+ for(t = tests; t->data; t++) {
+ char *str;
+ int len;
+ len = base64_encode(t->data, t->len, &str);
+ if(strcmp(str, t->result) != 0) {
+ fprintf(stderr, "failed test %d: %s != %s\n", numtest,
+ str, t->result);
+ numerr++;
+ }
+ free(str);
+ str = strdup(t->result);
+ len = base64_decode(t->result, str);
+ if(len != t->len) {
+ fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+ (unsigned long)len, (unsigned long)t->len);
+ numerr++;
+ } else if(memcmp(str, t->data, t->len) != 0) {
+ fprintf(stderr, "failed test %d: data\n", numtest);
+ numerr++;
+ }
+ free(str);
+ numtest++;
+ }
+
+ {
+ char str[32];
+ if(base64_decode("M=M=", str) != -1) {
+ fprintf(stderr, "failed test %d: successful decode of `M=M='\n",
+ numtest++);
+ numerr++;
+ }
+ if(base64_decode("MQ===", str) != -1) {
+ fprintf(stderr, "failed test %d: successful decode of `MQ==='\n",
+ numtest++);
+ numerr++;
+ }
+ }
+ return numerr;
+}
diff --git a/lib/roken/base64.c b/lib/roken/base64.c
new file mode 100644
index 0000000000000..daf7fc567161b
--- /dev/null
+++ b/lib/roken/base64.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: base64.c 15506 2005-06-23 10:47:57Z lha $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "base64.h"
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int
+pos(char c)
+{
+ const char *p;
+ for (p = base64_chars; *p; p++)
+ if (*p == c)
+ return p - base64_chars;
+ return -1;
+}
+
+int ROKEN_LIB_FUNCTION
+base64_encode(const void *data, int size, char **str)
+{
+ char *s, *p;
+ int i;
+ int c;
+ const unsigned char *q;
+
+ p = s = (char *) malloc(size * 4 / 3 + 4);
+ if (p == NULL)
+ return -1;
+ q = (const unsigned char *) data;
+ i = 0;
+ for (i = 0; i < size;) {
+ c = q[i++];
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+ p[1] = base64_chars[(c & 0x0003f000) >> 12];
+ p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+ p[3] = base64_chars[(c & 0x0000003f) >> 0];
+ if (i > size)
+ p[3] = '=';
+ if (i > size + 1)
+ p[2] = '=';
+ p += 4;
+ }
+ *p = 0;
+ *str = s;
+ return strlen(s);
+}
+
+#define DECODE_ERROR 0xffffffff
+
+static unsigned int
+token_decode(const char *token)
+{
+ int i;
+ unsigned int val = 0;
+ int marker = 0;
+ if (strlen(token) < 4)
+ return DECODE_ERROR;
+ for (i = 0; i < 4; i++) {
+ val *= 64;
+ if (token[i] == '=')
+ marker++;
+ else if (marker > 0)
+ return DECODE_ERROR;
+ else
+ val += pos(token[i]);
+ }
+ if (marker > 2)
+ return DECODE_ERROR;
+ return (marker << 24) | val;
+}
+
+int ROKEN_LIB_FUNCTION
+base64_decode(const char *str, void *data)
+{
+ const char *p;
+ unsigned char *q;
+
+ q = data;
+ for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ unsigned int val = token_decode(p);
+ unsigned int marker = (val >> 24) & 0xff;
+ if (val == DECODE_ERROR)
+ return -1;
+ *q++ = (val >> 16) & 0xff;
+ if (marker < 2)
+ *q++ = (val >> 8) & 0xff;
+ if (marker < 1)
+ *q++ = val & 0xff;
+ }
+ return q - (unsigned char *) data;
+}
diff --git a/lib/roken/base64.h b/lib/roken/base64.h
new file mode 100644
index 0000000000000..09aadffe7c418
--- /dev/null
+++ b/lib/roken/base64.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: base64.h 15535 2005-06-30 07:13:33Z lha $ */
+
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+base64_encode(const void *, int, char **);
+
+int ROKEN_LIB_FUNCTION
+base64_decode(const char *, void *);
+
+#endif
diff --git a/lib/roken/bswap.c b/lib/roken/bswap.c
new file mode 100644
index 0000000000000..e669eb2e4c0b2
--- /dev/null
+++ b/lib/roken/bswap.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$Id: bswap.c 14773 2005-04-12 11:29:18Z lha $");
+
+#ifndef HAVE_BSWAP32
+
+unsigned int ROKEN_LIB_FUNCTION
+bswap32 (unsigned int val)
+{
+ return (val & 0xff) << 24 |
+ (val & 0xff00) << 8 |
+ (val & 0xff0000) >> 8 |
+ (val & 0xff000000) >> 24;
+}
+#endif
+
+#ifndef HAVE_BSWAP16
+
+unsigned short ROKEN_LIB_FUNCTION
+bswap16 (unsigned short val)
+{
+ return (val & 0xff) << 8 |
+ (val & 0xff00) >> 8;
+}
+#endif
diff --git a/lib/roken/chown.c b/lib/roken/chown.c
new file mode 100644
index 0000000000000..5eb9c92c806d7
--- /dev/null
+++ b/lib/roken/chown.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: chown.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+chown(const char *path, uid_t owner, gid_t group)
+{
+ return 0;
+}
diff --git a/lib/roken/closefrom.c b/lib/roken/closefrom.c
new file mode 100644
index 0000000000000..f56e556a81d93
--- /dev/null
+++ b/lib/roken/closefrom.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: closefrom.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+closefrom(int fd)
+{
+ int num = getdtablesize();
+
+ if (num < 0)
+ num = 1024; /* XXX */
+
+ for (; fd <= num; fd++)
+ close(fd);
+
+ return 0;
+}
diff --git a/lib/roken/concat.c b/lib/roken/concat.c
new file mode 100644
index 0000000000000..94e0fcc311039
--- /dev/null
+++ b/lib/roken/concat.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: concat.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+roken_concat (char *s, size_t len, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, len);
+ ret = roken_vconcat (s, len, args);
+ va_end(args);
+ return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+roken_vconcat (char *s, size_t len, va_list args)
+{
+ const char *a;
+
+ while ((a = va_arg(args, const char*))) {
+ size_t n = strlen (a);
+
+ if (n >= len)
+ return -1;
+ memcpy (s, a, n);
+ s += n;
+ len -= n;
+ }
+ *s = '\0';
+ return 0;
+}
+
+size_t ROKEN_LIB_FUNCTION
+roken_vmconcat (char **s, size_t max_len, va_list args)
+{
+ const char *a;
+ char *p, *q;
+ size_t len = 0;
+ *s = NULL;
+ p = malloc(1);
+ if(p == NULL)
+ return 0;
+ len = 1;
+ while ((a = va_arg(args, const char*))) {
+ size_t n = strlen (a);
+
+ if(max_len && len + n > max_len){
+ free(p);
+ return 0;
+ }
+ q = realloc(p, len + n);
+ if(q == NULL){
+ free(p);
+ return 0;
+ }
+ p = q;
+ memcpy (p + len - 1, a, n);
+ len += n;
+ }
+ p[len - 1] = '\0';
+ *s = p;
+ return len;
+}
+
+size_t ROKEN_LIB_FUNCTION
+roken_mconcat (char **s, size_t max_len, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, max_len);
+ ret = roken_vmconcat (s, max_len, args);
+ va_end(args);
+ return ret;
+}
diff --git a/lib/roken/copyhostent.c b/lib/roken/copyhostent.c
new file mode 100644
index 0000000000000..6410449ffbe6e
--- /dev/null
+++ b/lib/roken/copyhostent.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: copyhostent.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * return a malloced copy of `h'
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+copyhostent (const struct hostent *h)
+{
+ struct hostent *res;
+ char **p;
+ int i, n;
+
+ res = malloc (sizeof (*res));
+ if (res == NULL)
+ return NULL;
+ res->h_name = NULL;
+ res->h_aliases = NULL;
+ res->h_addrtype = h->h_addrtype;
+ res->h_length = h->h_length;
+ res->h_addr_list = NULL;
+ res->h_name = strdup (h->h_name);
+ if (res->h_name == NULL) {
+ freehostent (res);
+ return NULL;
+ }
+ for (n = 0, p = h->h_aliases; *p != NULL; ++p)
+ ++n;
+ res->h_aliases = malloc ((n + 1) * sizeof(*res->h_aliases));
+ if (res->h_aliases == NULL) {
+ freehostent (res);
+ return NULL;
+ }
+ for (i = 0; i < n + 1; ++i)
+ res->h_aliases[i] = NULL;
+ for (i = 0; i < n; ++i) {
+ res->h_aliases[i] = strdup (h->h_aliases[i]);
+ if (res->h_aliases[i] == NULL) {
+ freehostent (res);
+ return NULL;
+ }
+ }
+
+ for (n = 0, p = h->h_addr_list; *p != NULL; ++p)
+ ++n;
+ res->h_addr_list = malloc ((n + 1) * sizeof(*res->h_addr_list));
+ if (res->h_addr_list == NULL) {
+ freehostent (res);
+ return NULL;
+ }
+ for (i = 0; i < n + 1; ++i) {
+ res->h_addr_list[i] = NULL;
+ }
+ for (i = 0; i < n; ++i) {
+ res->h_addr_list[i] = malloc (h->h_length);
+ if (res->h_addr_list[i] == NULL) {
+ freehostent (res);
+ return NULL;
+ }
+ memcpy (res->h_addr_list[i], h->h_addr_list[i], h->h_length);
+ }
+ return res;
+}
+
diff --git a/lib/roken/daemon.c b/lib/roken/daemon.c
new file mode 100644
index 0000000000000..2bc2350054c82
--- /dev/null
+++ b/lib/roken/daemon.c
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 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. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id: daemon.c 14773 2005-04-12 11:29:18Z lha $");
+
+#ifndef HAVE_DAEMON
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+daemon(int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1)
+ return (-1);
+
+ if (!nochdir)
+ chdir("/");
+
+ if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close (fd);
+ }
+ return (0);
+}
+
+#endif /* HAVE_DAEMON */
diff --git a/lib/roken/dumpdata.c b/lib/roken/dumpdata.c
new file mode 100644
index 0000000000000..4750cac1a5bbf
--- /dev/null
+++ b/lib/roken/dumpdata.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: dumpdata.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <unistd.h>
+
+#include "roken.h"
+
+/*
+ * Write datablob to a filename, don't care about errors.
+ */
+
+void ROKEN_LIB_FUNCTION
+rk_dumpdata (const char *filename, const void *buf, size_t size)
+{
+ int fd;
+
+ fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0640);
+ if (fd < 0)
+ return;
+ net_write(fd, buf, size);
+ close(fd);
+}
diff --git a/lib/roken/ecalloc.3 b/lib/roken/ecalloc.3
new file mode 100644
index 0000000000000..194ad271cf9a1
--- /dev/null
+++ b/lib/roken/ecalloc.3
@@ -0,0 +1,84 @@
+.\" Copyright (c) 2001, 2003 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+.\" $Id: ecalloc.3 12527 2003-08-15 12:28:14Z joda $
+.\"
+.Dd August 14, 2003
+.Dt ECALLOC 3
+.Os HEIMDAL
+.Sh NAME
+.Nm ecalloc ,
+.Nm emalloc ,
+.Nm eread ,
+.Nm erealloc ,
+.Nm esetenv ,
+.Nm estrdup ,
+.Nm ewrite
+.Nd exit-on-failure wrapper functions
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.Fd #include <roken.h>
+.Ft "void *"
+.Fn ecalloc "size_t number" "size_t size"
+.Ft "void *"
+.Fn emalloc "size_t sz"
+.Ft ssize_t
+.Fn eread "int fd" "void *buf" "size_t nbytes"
+.Ft "void *"
+.Fn erealloc "void *ptr" "size_t sz"
+.Ft void
+.Fn esetenv "const char *var" "const char *val" "int rewrite"
+.Ft "char *"
+.Fn estrdup "const char *str"
+.Ft ssize_t
+.Fn ewrite "int fd" "const void *buf" "size_t nbytes"
+.Sh DESCRIPTION
+These functions do the same as the ones without the
+.Dq e
+prefix, but if there is an error they will print a message with
+.Xr errx 3 ,
+and exit. For
+.Nm eread
+and
+.Nm ewrite
+this is also true for partial data.
+.Pp
+This is useful in applications when there is no need for a more
+advanced failure mode.
+.Sh SEE ALSO
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr calloc 3 ,
+.Xr errx 3 ,
+.Xr malloc 3 ,
+.Xr realloc 3 ,
+.Xr setenv 3 ,
+.Xr strdup 3
diff --git a/lib/roken/ecalloc.c b/lib/roken/ecalloc.c
new file mode 100644
index 0000000000000..c5ef4a7b24502
--- /dev/null
+++ b/lib/roken/ecalloc.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: ecalloc.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like calloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+ecalloc (size_t number, size_t size)
+{
+ void *tmp = calloc (number, size);
+
+ if (tmp == NULL && number * size != 0)
+ errx (1, "calloc %lu failed", (unsigned long)number * size);
+ return tmp;
+}
diff --git a/lib/roken/emalloc.c b/lib/roken/emalloc.c
new file mode 100644
index 0000000000000..a39fcc0d22bf3
--- /dev/null
+++ b/lib/roken/emalloc.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: emalloc.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like malloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+emalloc (size_t sz)
+{
+ void *tmp = malloc (sz);
+
+ if (tmp == NULL && sz != 0)
+ errx (1, "malloc %lu failed", (unsigned long)sz);
+ return tmp;
+}
diff --git a/lib/roken/environment.c b/lib/roken/environment.c
new file mode 100644
index 0000000000000..3822e4c6ffe5c
--- /dev/null
+++ b/lib/roken/environment.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2000, 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: environment.c 20866 2007-06-03 21:00:29Z lha $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "roken.h"
+
+/* find assignment in env list; len is length of variable including
+ * equal
+ */
+
+static int
+find_var(char **env, char *assignment, size_t len)
+{
+ int i;
+ for(i = 0; env != NULL && env[i] != NULL; i++)
+ if(strncmp(env[i], assignment, len) == 0)
+ return i;
+ return -1;
+}
+
+/*
+ * return count of environment assignments from open file F in
+ * assigned and list of malloced strings in env, return 0 or errno
+ * number
+ */
+
+static int
+rk_read_env_file(FILE *F, char ***env, int *assigned)
+{
+ int idx = 0;
+ int i;
+ char **l;
+ char buf[BUFSIZ], *p, *r;
+ char **tmp;
+ int ret = 0;
+
+ *assigned = 0;
+
+ for(idx = 0; *env != NULL && (*env)[idx] != NULL; idx++);
+ l = *env;
+
+ /* This is somewhat more relaxed on what it accepts then
+ * Wietses sysv_environ from K4 was...
+ */
+ while (fgets(buf, BUFSIZ, F) != NULL) {
+ buf[strcspn(buf, "#\n")] = '\0';
+
+ for(p = buf; isspace((unsigned char)*p); p++);
+ if (*p == '\0')
+ continue;
+
+ /* Here one should check that it's a 'valid' env string... */
+ r = strchr(p, '=');
+ if (r == NULL)
+ continue;
+
+ if((i = find_var(l, p, r - p + 1)) >= 0) {
+ char *val = strdup(p);
+ if(val == NULL) {
+ ret = ENOMEM;
+ break;
+ }
+ free(l[i]);
+ l[i] = val;
+ (*assigned)++;
+ continue;
+ }
+
+ tmp = realloc(l, (idx+2) * sizeof (char *));
+ if(tmp == NULL) {
+ ret = ENOMEM;
+ break;
+ }
+
+ l = tmp;
+ l[idx] = strdup(p);
+ if(l[idx] == NULL) {
+ ret = ENOMEM;
+ break;
+ }
+ l[++idx] = NULL;
+ (*assigned)++;
+ }
+ if(ferror(F))
+ ret = errno;
+ *env = l;
+ return ret;
+}
+
+/*
+ * return count of environment assignments from file and
+ * list of malloced strings in `env'
+ */
+
+int ROKEN_LIB_FUNCTION
+read_environment(const char *file, char ***env)
+{
+ int assigned;
+ FILE *F;
+
+ if ((F = fopen(file, "r")) == NULL)
+ return 0;
+
+ rk_read_env_file(F, env, &assigned);
+ fclose(F);
+ return assigned;
+}
+
+void ROKEN_LIB_FUNCTION
+free_environment(char **env)
+{
+ int i;
+ if (env == NULL)
+ return;
+ for (i = 0; env[i]; i++)
+ free(env[i]);
+ free(env);
+}
diff --git a/lib/roken/eread.c b/lib/roken/eread.c
new file mode 100644
index 0000000000000..ec4eed412e103
--- /dev/null
+++ b/lib/roken/eread.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: eread.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <unistd.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like read but never fails (and never returns partial data).
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+eread (int fd, void *buf, size_t nbytes)
+{
+ ssize_t ret;
+
+ ret = net_read (fd, buf, nbytes);
+ if (ret < 0)
+ err (1, "read");
+ return ret;
+}
diff --git a/lib/roken/erealloc.c b/lib/roken/erealloc.c
new file mode 100644
index 0000000000000..c38236085cb19
--- /dev/null
+++ b/lib/roken/erealloc.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: erealloc.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like realloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+erealloc (void *ptr, size_t sz)
+{
+ void *tmp = realloc (ptr, sz);
+
+ if (tmp == NULL && sz != 0)
+ errx (1, "realloc %lu failed", (unsigned long)sz);
+ return tmp;
+}
diff --git a/lib/roken/err.c b/lib/roken/err.c
new file mode 100644
index 0000000000000..dcb820bba6b5f
--- /dev/null
+++ b/lib/roken/err.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: err.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verr(eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/roken/err.hin b/lib/roken/err.hin
new file mode 100644
index 0000000000000..2f1232d3e7f86
--- /dev/null
+++ b/lib/roken/err.hin
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1995 - 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: err.hin 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef __ERR_H__
+#define __ERR_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+void ROKEN_LIB_FUNCTION
+verr(int eval, const char *fmt, va_list ap)
+ __attribute__ ((noreturn, format (printf, 2, 0)));
+
+void ROKEN_LIB_FUNCTION
+err(int eval, const char *fmt, ...)
+ __attribute__ ((noreturn, format (printf, 2, 3)));
+
+void ROKEN_LIB_FUNCTION
+verrx(int eval, const char *fmt, va_list ap)
+ __attribute__ ((noreturn, format (printf, 2, 0)));
+
+void ROKEN_LIB_FUNCTION
+errx(int eval, const char *fmt, ...)
+ __attribute__ ((noreturn, format (printf, 2, 3)));
+void ROKEN_LIB_FUNCTION
+vwarn(const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 1, 0)));
+
+void ROKEN_LIB_FUNCTION
+warn(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+void ROKEN_LIB_FUNCTION
+vwarnx(const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 1, 0)));
+
+void ROKEN_LIB_FUNCTION
+warnx(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif /* __ERR_H__ */
diff --git a/lib/roken/errx.c b/lib/roken/errx.c
new file mode 100644
index 0000000000000..1090ac79d0291
--- /dev/null
+++ b/lib/roken/errx.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: errx.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/roken/esetenv.c b/lib/roken/esetenv.c
new file mode 100644
index 0000000000000..e92f04ab32f08
--- /dev/null
+++ b/lib/roken/esetenv.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2000, 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: esetenv.c 15502 2005-06-21 18:56:15Z lha $");
+#endif
+
+#include "roken.h"
+
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+esetenv(const char *var, const char *val, int rewrite)
+{
+ if (setenv (rk_UNCONST(var), rk_UNCONST(val), rewrite))
+ errx (1, "failed setting environment variable %s", var);
+}
diff --git a/lib/roken/estrdup.c b/lib/roken/estrdup.c
new file mode 100644
index 0000000000000..262412bd35e8f
--- /dev/null
+++ b/lib/roken/estrdup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: estrdup.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like strdup but never fails.
+ */
+
+char * ROKEN_LIB_FUNCTION
+estrdup (const char *str)
+{
+ char *tmp = strdup (str);
+
+ if (tmp == NULL)
+ errx (1, "strdup failed");
+ return tmp;
+}
diff --git a/lib/roken/ewrite.c b/lib/roken/ewrite.c
new file mode 100644
index 0000000000000..a2323d6ffd9e3
--- /dev/null
+++ b/lib/roken/ewrite.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: ewrite.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <unistd.h>
+#include <err.h>
+
+#include "roken.h"
+
+/*
+ * Like write but never fails (and never returns partial data).
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+ewrite (int fd, const void *buf, size_t nbytes)
+{
+ ssize_t ret;
+
+ ret = net_write (fd, buf, nbytes);
+ if (ret < 0)
+ err (1, "write");
+ return ret;
+}
diff --git a/lib/roken/fchown.c b/lib/roken/fchown.c
new file mode 100644
index 0000000000000..87a205179f2dc
--- /dev/null
+++ b/lib/roken/fchown.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: fchown.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+fchown(int fd, uid_t owner, gid_t group)
+{
+ return 0;
+}
diff --git a/lib/roken/flock.c b/lib/roken/flock.c
new file mode 100644
index 0000000000000..911d5ff31ed37
--- /dev/null
+++ b/lib/roken/flock.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_FLOCK
+RCSID("$Id: flock.c 14773 2005-04-12 11:29:18Z lha $");
+
+#include "roken.h"
+
+
+#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN)
+
+int ROKEN_LIB_FUNCTION
+flock(int fd, int operation)
+{
+#if defined(HAVE_FCNTL) && defined(F_SETLK)
+ struct flock arg;
+ int code, cmd;
+
+ arg.l_whence = SEEK_SET;
+ arg.l_start = 0;
+ arg.l_len = 0; /* means to EOF */
+
+ if (operation & LOCK_NB)
+ cmd = F_SETLK;
+ else
+ cmd = F_SETLKW; /* Blocking */
+
+ switch (operation & OP_MASK) {
+ case LOCK_UN:
+ arg.l_type = F_UNLCK;
+ code = fcntl(fd, F_SETLK, &arg);
+ break;
+ case LOCK_SH:
+ arg.l_type = F_RDLCK;
+ code = fcntl(fd, cmd, &arg);
+ break;
+ case LOCK_EX:
+ arg.l_type = F_WRLCK;
+ code = fcntl(fd, cmd, &arg);
+ break;
+ default:
+ errno = EINVAL;
+ code = -1;
+ break;
+ }
+ return code;
+#else
+ return -1;
+#endif
+}
+
+#endif
+
diff --git a/lib/roken/fnmatch.c b/lib/roken/fnmatch.c
new file mode 100644
index 0000000000000..126949a8e08d1
--- /dev/null
+++ b/lib/roken/fnmatch.c
@@ -0,0 +1,169 @@
+/* $NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
+#else
+static char rcsid[] = "$NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include <fnmatch.h>
+#include <string.h>
+
+#define EOS '\0'
+
+static const char *rangematch (const char *, int, int);
+
+int ROKEN_LIB_FUNCTION
+rk_fnmatch(const char *pattern, const char *string, int flags)
+{
+ const char *stringstart;
+ char c, test;
+
+ for (stringstart = string;;)
+ switch (c = *pattern++) {
+ case EOS:
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS)
+ if (flags & FNM_PATHNAME)
+ return (strchr(string, '/') == NULL ?
+ 0 : FNM_NOMATCH);
+ else
+ return (0);
+ else if (c == '/' && flags & FNM_PATHNAME) {
+ if ((string = strchr(string, '/')) == NULL)
+ return (FNM_NOMATCH);
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!rk_fnmatch(pattern, string, flags & ~FNM_PERIOD))
+ return (0);
+ if (test == '/' && flags & FNM_PATHNAME)
+ break;
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && flags & FNM_PATHNAME)
+ return (FNM_NOMATCH);
+ if ((pattern =
+ rangematch(pattern, *string, flags)) == NULL)
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ if (c != *string++)
+ return (FNM_NOMATCH);
+ break;
+ }
+ /* NOTREACHED */
+}
+
+static const char *
+rangematch(const char *pattern, int test, int flags)
+{
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if (negate = (*pattern == '!' || *pattern == '^'))
+ ++pattern;
+
+ for (ok = 0; (c = *pattern++) != ']';) {
+ if (c == '\\' && !(flags & FNM_NOESCAPE))
+ c = *pattern++;
+ if (c == EOS)
+ return (NULL);
+ if (*pattern == '-'
+ && (c2 = *(pattern+1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+ c2 = *pattern++;
+ if (c2 == EOS)
+ return (NULL);
+ if (c <= test && test <= c2)
+ ok = 1;
+ } else if (c == test)
+ ok = 1;
+ }
+ return (ok == negate ? NULL : pattern);
+}
diff --git a/lib/roken/fnmatch.hin b/lib/roken/fnmatch.hin
new file mode 100644
index 0000000000000..d5d54a56225e4
--- /dev/null
+++ b/lib/roken/fnmatch.hin
@@ -0,0 +1,64 @@
+/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 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. 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.
+ *
+ * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _FNMATCH_H_
+#define _FNMATCH_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FNM_NOMATCH 1 /* Match failed. */
+
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+
+int ROKEN_LIB_FUNCTION
+rk_fnmatch (const char *, const char *, int);
+
+#define fnmatch(a,b,c) rk_fnmatch(a,b,c)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_FNMATCH_H_ */
diff --git a/lib/roken/freeaddrinfo.c b/lib/roken/freeaddrinfo.c
new file mode 100644
index 0000000000000..a61536ddf8815
--- /dev/null
+++ b/lib/roken/freeaddrinfo.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: freeaddrinfo.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * free the list of `struct addrinfo' starting at `ai'
+ */
+
+void ROKEN_LIB_FUNCTION
+freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *tofree;
+
+ while(ai != NULL) {
+ free (ai->ai_canonname);
+ free (ai->ai_addr);
+ tofree = ai;
+ ai = ai->ai_next;
+ free (tofree);
+ }
+}
diff --git a/lib/roken/freehostent.c b/lib/roken/freehostent.c
new file mode 100644
index 0000000000000..54fc49532b204
--- /dev/null
+++ b/lib/roken/freehostent.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: freehostent.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * free a malloced hostent
+ */
+
+void ROKEN_LIB_FUNCTION
+freehostent (struct hostent *h)
+{
+ char **p;
+
+ free (h->h_name);
+ if (h->h_aliases != NULL) {
+ for (p = h->h_aliases; *p != NULL; ++p)
+ free (*p);
+ free (h->h_aliases);
+ }
+ if (h->h_addr_list != NULL) {
+ for (p = h->h_addr_list; *p != NULL; ++p)
+ free (*p);
+ free (h->h_addr_list);
+ }
+ free (h);
+}
diff --git a/lib/roken/gai_strerror.c b/lib/roken/gai_strerror.c
new file mode 100644
index 0000000000000..c86274358b669
--- /dev/null
+++ b/lib/roken/gai_strerror.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: gai_strerror.c 15837 2005-08-05 09:31:35Z lha $");
+#endif
+
+#include "roken.h"
+
+static struct gai_error {
+ int code;
+ const char *str;
+} errors[] = {
+{EAI_NOERROR, "no error"},
+#ifdef EAI_ADDRFAMILY
+{EAI_ADDRFAMILY, "address family for nodename not supported"},
+#endif
+{EAI_AGAIN, "temporary failure in name resolution"},
+{EAI_BADFLAGS, "invalid value for ai_flags"},
+{EAI_FAIL, "non-recoverable failure in name resolution"},
+{EAI_FAMILY, "ai_family not supported"},
+{EAI_MEMORY, "memory allocation failure"},
+#ifdef EAI_NODATA
+{EAI_NODATA, "no address associated with nodename"},
+#endif
+{EAI_NONAME, "nodename nor servname provided, or not known"},
+{EAI_SERVICE, "servname not supported for ai_socktype"},
+{EAI_SOCKTYPE, "ai_socktype not supported"},
+{EAI_SYSTEM, "system error returned in errno"},
+{0, NULL},
+};
+
+/*
+ *
+ */
+
+const char * ROKEN_LIB_FUNCTION
+gai_strerror(int ecode)
+{
+ struct gai_error *g;
+
+ for (g = errors; g->str != NULL; ++g)
+ if (g->code == ecode)
+ return g->str;
+ return "unknown error code in gai_strerror";
+}
diff --git a/lib/roken/get_default_username.c b/lib/roken/get_default_username.c
new file mode 100644
index 0000000000000..754b60d2a8b11
--- /dev/null
+++ b/lib/roken/get_default_username.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: get_default_username.c 14773 2005-04-12 11:29:18Z lha $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+
+/*
+ * Try to return what should be considered the default username or
+ * NULL if we can't guess at all.
+ */
+
+const char * ROKEN_LIB_FUNCTION
+get_default_username (void)
+{
+ const char *user;
+
+ user = getenv ("USER");
+ if (user == NULL)
+ user = getenv ("LOGNAME");
+ if (user == NULL)
+ user = getenv ("USERNAME");
+
+#if defined(HAVE_GETLOGIN) && !defined(POSIX_GETLOGIN)
+ if (user == NULL) {
+ user = (const char *)getlogin ();
+ if (user != NULL)
+ return user;
+ }
+#endif
+#ifdef HAVE_PWD_H
+ {
+ uid_t uid = getuid ();
+ struct passwd *pwd;
+
+ if (user != NULL) {
+ pwd = k_getpwnam (user);
+ if (pwd != NULL && pwd->pw_uid == uid)
+ return user;
+ }
+ pwd = k_getpwuid (uid);
+ if (pwd != NULL)
+ return pwd->pw_name;
+ }
+#endif
+ return user;
+}
diff --git a/lib/roken/get_window_size.c b/lib/roken/get_window_size.c
new file mode 100644
index 0000000000000..7fa91d6522709
--- /dev/null
+++ b/lib/roken/get_window_size.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: get_window_size.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if 0 /* Where were those needed? /confused */
+#ifdef HAVE_SYS_PROC_H
+#include <sys/proc.h>
+#endif
+
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+get_window_size(int fd, struct winsize *wp)
+{
+ int ret = -1;
+
+ memset(wp, 0, sizeof(*wp));
+
+#if defined(TIOCGWINSZ)
+ ret = ioctl(fd, TIOCGWINSZ, wp);
+#elif defined(TIOCGSIZE)
+ {
+ struct ttysize ts;
+
+ ret = ioctl(fd, TIOCGSIZE, &ts);
+ if(ret == 0) {
+ wp->ws_row = ts.ts_lines;
+ wp->ws_col = ts.ts_cols;
+ }
+ }
+#elif defined(HAVE__SCRSIZE)
+ {
+ int dst[2];
+
+ _scrsize(dst);
+ wp->ws_row = dst[1];
+ wp->ws_col = dst[0];
+ ret = 0;
+ }
+#endif
+ if (ret != 0) {
+ char *s;
+ if((s = getenv("COLUMNS")))
+ wp->ws_col = atoi(s);
+ if((s = getenv("LINES")))
+ wp->ws_row = atoi(s);
+ if(wp->ws_col > 0 && wp->ws_row > 0)
+ ret = 0;
+ }
+ return ret;
+}
diff --git a/lib/roken/getaddrinfo-test.c b/lib/roken/getaddrinfo-test.c
new file mode 100644
index 0000000000000..027e32a742c88
--- /dev/null
+++ b/lib/roken/getaddrinfo-test.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getaddrinfo-test.c 15930 2005-08-12 13:42:17Z lha $");
+#endif
+
+#include "roken.h"
+#include "getarg.h"
+
+static int flags;
+static int family;
+static int socktype;
+
+static int version_flag;
+static int help_flag;
+
+static struct getargs args[] = {
+ {"flags", 0, arg_integer, &flags, "flags", NULL},
+ {"family", 0, arg_integer, &family, "family", NULL},
+ {"socktype",0, arg_integer, &socktype, "socktype", NULL},
+ {"version", 0, arg_flag, &version_flag, "print version",NULL},
+ {"help", 0, arg_flag, &help_flag, NULL, NULL}
+};
+
+static void
+usage(int ret)
+{
+ arg_printusage (args,
+ sizeof(args) / sizeof(args[0]),
+ NULL,
+ "[nodename servname...]");
+ exit (ret);
+}
+
+static void
+doit (const char *nodename, const char *servname)
+{
+ struct addrinfo hints;
+ struct addrinfo *res, *r;
+ int ret;
+
+ printf ("(%s,%s)... ", nodename ? nodename : "null", servname);
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_flags = flags;
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+
+ ret = getaddrinfo (nodename, servname, &hints, &res);
+ if (ret) {
+ printf ("error: %s\n", gai_strerror(ret));
+ return;
+ }
+ printf ("\n");
+
+ for (r = res; r != NULL; r = r->ai_next) {
+ char addrstr[256];
+
+ if (inet_ntop (r->ai_family,
+ socket_get_address (r->ai_addr),
+ addrstr, sizeof(addrstr)) == NULL) {
+ printf ("\tbad address?\n");
+ continue;
+ }
+ printf ("\tfamily = %d, socktype = %d, protocol = %d, "
+ "address = \"%s\", port = %d",
+ r->ai_family, r->ai_socktype, r->ai_protocol,
+ addrstr,
+ ntohs(socket_get_port (r->ai_addr)));
+ if (r->ai_canonname)
+ printf (", canonname = \"%s\"", r->ai_canonname);
+ printf ("\n");
+ }
+ freeaddrinfo (res);
+}
+
+int
+main(int argc, char **argv)
+{
+ int optidx = 0;
+ int i;
+
+ setprogname (argv[0]);
+
+ if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
+ &optidx))
+ usage (1);
+
+ if (help_flag)
+ usage (0);
+
+ if (version_flag) {
+ fprintf (stderr, "%s from %s-%s)\n", getprogname(), PACKAGE, VERSION);
+ return 0;
+ }
+
+ argc -= optidx;
+ argv += optidx;
+
+ if (argc % 2 != 0)
+ usage (1);
+
+ for (i = 0; i < argc; i += 2) {
+ const char *nodename = argv[i];
+
+ if (strcmp (nodename, "null") == 0)
+ nodename = NULL;
+
+ doit (nodename, argv[i+1]);
+ }
+ return 0;
+}
diff --git a/lib/roken/getaddrinfo.c b/lib/roken/getaddrinfo.c
new file mode 100644
index 0000000000000..f9ffcd865142c
--- /dev/null
+++ b/lib/roken/getaddrinfo.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getaddrinfo.c 15417 2005-06-16 17:49:29Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * uses hints->ai_socktype and hints->ai_protocol
+ */
+
+static int
+get_port_protocol_socktype (const char *servname,
+ const struct addrinfo *hints,
+ int *port,
+ int *protocol,
+ int *socktype)
+{
+ struct servent *se;
+ const char *proto_str = NULL;
+
+ *socktype = 0;
+
+ if (hints != NULL && hints->ai_protocol != 0) {
+ struct protoent *protoent = getprotobynumber (hints->ai_protocol);
+
+ if (protoent == NULL)
+ return EAI_SOCKTYPE; /* XXX */
+
+ proto_str = protoent->p_name;
+ *protocol = protoent->p_proto;
+ }
+
+ if (hints != NULL)
+ *socktype = hints->ai_socktype;
+
+ if (*socktype == SOCK_STREAM) {
+ se = getservbyname (servname, proto_str ? proto_str : "tcp");
+ if (proto_str == NULL)
+ *protocol = IPPROTO_TCP;
+ } else if (*socktype == SOCK_DGRAM) {
+ se = getservbyname (servname, proto_str ? proto_str : "udp");
+ if (proto_str == NULL)
+ *protocol = IPPROTO_UDP;
+ } else if (*socktype == 0) {
+ if (proto_str != NULL) {
+ se = getservbyname (servname, proto_str);
+ } else {
+ se = getservbyname (servname, "tcp");
+ *protocol = IPPROTO_TCP;
+ *socktype = SOCK_STREAM;
+ if (se == NULL) {
+ se = getservbyname (servname, "udp");
+ *protocol = IPPROTO_UDP;
+ *socktype = SOCK_DGRAM;
+ }
+ }
+ } else
+ return EAI_SOCKTYPE;
+
+ if (se == NULL) {
+ char *endstr;
+
+ *port = htons(strtol (servname, &endstr, 10));
+ if (servname == endstr)
+ return EAI_NONAME;
+ } else {
+ *port = se->s_port;
+ }
+ return 0;
+}
+
+static int
+add_one (int port, int protocol, int socktype,
+ struct addrinfo ***ptr,
+ int (*func)(struct addrinfo *, void *data, int port),
+ void *data,
+ char *canonname)
+{
+ struct addrinfo *a;
+ int ret;
+
+ a = malloc (sizeof (*a));
+ if (a == NULL)
+ return EAI_MEMORY;
+ memset (a, 0, sizeof(*a));
+ a->ai_flags = 0;
+ a->ai_next = NULL;
+ a->ai_protocol = protocol;
+ a->ai_socktype = socktype;
+ a->ai_canonname = canonname;
+ ret = (*func)(a, data, port);
+ if (ret) {
+ free (a);
+ return ret;
+ }
+ **ptr = a;
+ *ptr = &a->ai_next;
+ return 0;
+}
+
+static int
+const_v4 (struct addrinfo *a, void *data, int port)
+{
+ struct sockaddr_in *sin4;
+ struct in_addr *addr = (struct in_addr *)data;
+
+ a->ai_family = PF_INET;
+ a->ai_addrlen = sizeof(*sin4);
+ a->ai_addr = malloc (sizeof(*sin4));
+ if (a->ai_addr == NULL)
+ return EAI_MEMORY;
+ sin4 = (struct sockaddr_in *)a->ai_addr;
+ memset (sin4, 0, sizeof(*sin4));
+ sin4->sin_family = AF_INET;
+ sin4->sin_port = port;
+ sin4->sin_addr = *addr;
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int
+const_v6 (struct addrinfo *a, void *data, int port)
+{
+ struct sockaddr_in6 *sin6;
+ struct in6_addr *addr = (struct in6_addr *)data;
+
+ a->ai_family = PF_INET6;
+ a->ai_addrlen = sizeof(*sin6);
+ a->ai_addr = malloc (sizeof(*sin6));
+ if (a->ai_addr == NULL)
+ return EAI_MEMORY;
+ sin6 = (struct sockaddr_in6 *)a->ai_addr;
+ memset (sin6, 0, sizeof(*sin6));
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = port;
+ sin6->sin6_addr = *addr;
+ return 0;
+}
+#endif
+
+/* this is mostly a hack for some versions of AIX that has a prototype
+ for in6addr_loopback but no actual symbol in libc */
+#if defined(HAVE_IPV6) && !defined(HAVE_IN6ADDR_LOOPBACK) && defined(IN6ADDR_LOOPBACK_INIT)
+#define in6addr_loopback _roken_in6addr_loopback
+struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#endif
+
+static int
+get_null (const struct addrinfo *hints,
+ int port, int protocol, int socktype,
+ struct addrinfo **res)
+{
+ struct in_addr v4_addr;
+#ifdef HAVE_IPV6
+ struct in6_addr v6_addr;
+#endif
+ struct addrinfo *first = NULL;
+ struct addrinfo **current = &first;
+ int family = PF_UNSPEC;
+ int ret;
+
+ if (hints != NULL)
+ family = hints->ai_family;
+
+ if (hints && hints->ai_flags & AI_PASSIVE) {
+ v4_addr.s_addr = INADDR_ANY;
+#ifdef HAVE_IPV6
+ v6_addr = in6addr_any;
+#endif
+ } else {
+ v4_addr.s_addr = htonl(INADDR_LOOPBACK);
+#ifdef HAVE_IPV6
+ v6_addr = in6addr_loopback;
+#endif
+ }
+
+#ifdef HAVE_IPV6
+ if (family == PF_INET6 || family == PF_UNSPEC) {
+ ret = add_one (port, protocol, socktype,
+ &current, const_v6, &v6_addr, NULL);
+ }
+#endif
+ if (family == PF_INET || family == PF_UNSPEC) {
+ ret = add_one (port, protocol, socktype,
+ &current, const_v4, &v4_addr, NULL);
+ }
+ *res = first;
+ return 0;
+}
+
+static int
+add_hostent (int port, int protocol, int socktype,
+ struct addrinfo ***current,
+ int (*func)(struct addrinfo *, void *data, int port),
+ struct hostent *he, int *flags)
+{
+ int ret;
+ char *canonname = NULL;
+ char **h;
+
+ if (*flags & AI_CANONNAME) {
+ struct hostent *he2 = NULL;
+ const char *tmp_canon;
+
+ tmp_canon = hostent_find_fqdn (he);
+ if (strchr (tmp_canon, '.') == NULL) {
+ int error;
+
+ he2 = getipnodebyaddr (he->h_addr_list[0], he->h_length,
+ he->h_addrtype, &error);
+ if (he2 != NULL) {
+ const char *tmp = hostent_find_fqdn (he2);
+
+ if (strchr (tmp, '.') != NULL)
+ tmp_canon = tmp;
+ }
+ }
+
+ canonname = strdup (tmp_canon);
+ if (he2 != NULL)
+ freehostent (he2);
+ if (canonname == NULL)
+ return EAI_MEMORY;
+ }
+
+ for (h = he->h_addr_list; *h != NULL; ++h) {
+ ret = add_one (port, protocol, socktype,
+ current, func, *h, canonname);
+ if (ret)
+ return ret;
+ if (*flags & AI_CANONNAME) {
+ *flags &= ~AI_CANONNAME;
+ canonname = NULL;
+ }
+ }
+ return 0;
+}
+
+static int
+get_number (const char *nodename,
+ const struct addrinfo *hints,
+ int port, int protocol, int socktype,
+ struct addrinfo **res)
+{
+ struct addrinfo *first = NULL;
+ struct addrinfo **current = &first;
+ int family = PF_UNSPEC;
+ int ret;
+
+ if (hints != NULL) {
+ family = hints->ai_family;
+ }
+
+#ifdef HAVE_IPV6
+ if (family == PF_INET6 || family == PF_UNSPEC) {
+ struct in6_addr v6_addr;
+
+ if (inet_pton (PF_INET6, nodename, &v6_addr) == 1) {
+ ret = add_one (port, protocol, socktype,
+ &current, const_v6, &v6_addr, NULL);
+ *res = first;
+ return ret;
+ }
+ }
+#endif
+ if (family == PF_INET || family == PF_UNSPEC) {
+ struct in_addr v4_addr;
+
+ if (inet_pton (PF_INET, nodename, &v4_addr) == 1) {
+ ret = add_one (port, protocol, socktype,
+ &current, const_v4, &v4_addr, NULL);
+ *res = first;
+ return ret;
+ }
+ }
+ return EAI_NONAME;
+}
+
+static int
+get_nodes (const char *nodename,
+ const struct addrinfo *hints,
+ int port, int protocol, int socktype,
+ struct addrinfo **res)
+{
+ struct addrinfo *first = NULL;
+ struct addrinfo **current = &first;
+ int family = PF_UNSPEC;
+ int flags = 0;
+ int ret = EAI_NONAME;
+ int error;
+
+ if (hints != NULL) {
+ family = hints->ai_family;
+ flags = hints->ai_flags;
+ }
+
+#ifdef HAVE_IPV6
+ if (family == PF_INET6 || family == PF_UNSPEC) {
+ struct hostent *he;
+
+ he = getipnodebyname (nodename, PF_INET6, 0, &error);
+
+ if (he != NULL) {
+ ret = add_hostent (port, protocol, socktype,
+ &current, const_v6, he, &flags);
+ freehostent (he);
+ }
+ }
+#endif
+ if (family == PF_INET || family == PF_UNSPEC) {
+ struct hostent *he;
+
+ he = getipnodebyname (nodename, PF_INET, 0, &error);
+
+ if (he != NULL) {
+ ret = add_hostent (port, protocol, socktype,
+ &current, const_v4, he, &flags);
+ freehostent (he);
+ }
+ }
+ *res = first;
+ return ret;
+}
+
+/*
+ * hints:
+ *
+ * struct addrinfo {
+ * int ai_flags;
+ * int ai_family;
+ * int ai_socktype;
+ * int ai_protocol;
+ * ...
+ * };
+ */
+
+int ROKEN_LIB_FUNCTION
+getaddrinfo(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ int ret;
+ int port = 0;
+ int protocol = 0;
+ int socktype = 0;
+
+ *res = NULL;
+
+ if (servname == NULL && nodename == NULL)
+ return EAI_NONAME;
+
+ if (hints != NULL
+ && hints->ai_family != PF_UNSPEC
+ && hints->ai_family != PF_INET
+#ifdef HAVE_IPV6
+ && hints->ai_family != PF_INET6
+#endif
+ )
+ return EAI_FAMILY;
+
+ if (servname != NULL) {
+ ret = get_port_protocol_socktype (servname, hints,
+ &port, &protocol, &socktype);
+ if (ret)
+ return ret;
+ }
+ if (nodename != NULL) {
+ ret = get_number (nodename, hints, port, protocol, socktype, res);
+ if (ret) {
+ if(hints && hints->ai_flags & AI_NUMERICHOST)
+ ret = EAI_NONAME;
+ else
+ ret = get_nodes (nodename, hints, port, protocol, socktype,
+ res);
+ }
+ } else {
+ ret = get_null (hints, port, protocol, socktype, res);
+ }
+ if (ret)
+ freeaddrinfo (*res);
+ return ret;
+}
diff --git a/lib/roken/getaddrinfo_hostspec.c b/lib/roken/getaddrinfo_hostspec.c
new file mode 100644
index 0000000000000..29eae31e4caa4
--- /dev/null
+++ b/lib/roken/getaddrinfo_hostspec.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getaddrinfo_hostspec.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/* getaddrinfo via string specifying host and port */
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec2(const char *hostspec,
+ int socktype,
+ int port,
+ struct addrinfo **ai)
+{
+ const char *p;
+ char portstr[NI_MAXSERV];
+ char host[MAXHOSTNAMELEN];
+ struct addrinfo hints;
+ int hostspec_len;
+
+ struct hst {
+ const char *prefix;
+ int socktype;
+ int protocol;
+ int port;
+ } *hstp, hst[] = {
+ { "http://", SOCK_STREAM, IPPROTO_TCP, 80 },
+ { "http/", SOCK_STREAM, IPPROTO_TCP, 80 },
+ { "tcp/", SOCK_STREAM, IPPROTO_TCP },
+ { "udp/", SOCK_DGRAM, IPPROTO_UDP },
+ { NULL }
+ };
+
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_socktype = socktype;
+
+ for(hstp = hst; hstp->prefix; hstp++) {
+ if(strncmp(hostspec, hstp->prefix, strlen(hstp->prefix)) == 0) {
+ hints.ai_socktype = hstp->socktype;
+ hints.ai_protocol = hstp->protocol;
+ if(port == 0)
+ port = hstp->port;
+ hostspec += strlen(hstp->prefix);
+ break;
+ }
+ }
+
+ p = strchr (hostspec, ':');
+ if (p != NULL) {
+ char *end;
+
+ port = strtol (p + 1, &end, 0);
+ hostspec_len = p - hostspec;
+ } else {
+ hostspec_len = strlen(hostspec);
+ }
+ snprintf (portstr, sizeof(portstr), "%u", port);
+
+ snprintf (host, sizeof(host), "%.*s", hostspec_len, hostspec);
+ return getaddrinfo (host, portstr, &hints, ai);
+}
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec(const char *hostspec,
+ int port,
+ struct addrinfo **ai)
+{
+ return roken_getaddrinfo_hostspec2(hostspec, 0, port, ai);
+}
diff --git a/lib/roken/getarg.3 b/lib/roken/getarg.3
new file mode 100644
index 0000000000000..fd5ed3de0e82f
--- /dev/null
+++ b/lib/roken/getarg.3
@@ -0,0 +1,341 @@
+.\" Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+.\"
+.\" $Id: getarg.3 13380 2004-02-17 12:04:59Z lha $
+.Dd September 24, 1999
+.Dt GETARG 3
+.Os ROKEN
+.Sh NAME
+.Nm getarg ,
+.Nm arg_printusage
+.Nd collect command line options
+.Sh SYNOPSIS
+.In getarg.h
+.Ft int
+.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind"
+.Ft void
+.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string"
+.Sh DESCRIPTION
+.Fn getarg
+collects any command line options given to a program in an easily used way.
+.Fn arg_printusage
+pretty-prints the available options, with a short help text.
+.Pp
+.Fa args
+is the option specification to use, and it's an array of
+.Fa struct getargs
+elements.
+.Fa num_args
+is the size of
+.Fa args
+(in elements).
+.Fa argc
+and
+.Fa argv
+are the argument count and argument vector to extract option from.
+.Fa optind
+is a pointer to an integer where the index to the last processed
+argument is stored, it must be initialised to the first index (minus
+one) to process (normally 0) before the first call.
+.Pp
+.Fa arg_printusage
+take the same
+.Fa args
+and
+.Fa num_args
+as getarg;
+.Fa progname
+is the name of the program (to be used in the help text), and
+.Fa extra_string
+is a string to print after the actual options to indicate more
+arguments. The usefulness of this function is realised only be people
+who has used programs that has help strings that doesn't match what
+the code does.
+.Pp
+The
+.Fa getargs
+struct has the following elements.
+.Bd -literal
+struct getargs{
+ const char *long_name;
+ char short_name;
+ enum { arg_integer,
+ arg_string,
+ arg_flag,
+ arg_negative_flag,
+ arg_strings,
+ arg_double,
+ arg_collect
+ } type;
+ void *value;
+ const char *help;
+ const char *arg_help;
+};
+.Ed
+.Pp
+.Fa long_name
+is the long name of the option, it can be
+.Dv NULL ,
+if you don't want a long name.
+.Fa short_name
+is the characted to use as short option, it can be zero. If the option
+has a value the
+.Fa value
+field gets filled in with that value interpreted as specified by the
+.Fa type
+field.
+.Fa help
+is a longer help string for the option as a whole, if it's
+.Dv NULL
+the help text for the option is omitted (but it's still displayed in
+the synopsis).
+.Fa arg_help
+is a description of the argument, if
+.Dv NULL
+a default value will be used, depending on the type of the option:
+.Pp
+.Bl -hang -width arg_negative_flag
+.It arg_integer
+the argument is a signed integer, and
+.Fa value
+should point to an
+.Fa int .
+.It Fa arg_string
+the argument is a string, and
+.Fa value
+should point to a
+.Fa char* .
+.It Fa arg_flag
+the argument is a flag, and
+.Fa value
+should point to a
+.Fa int .
+It gets filled in with either zero or one, depending on how the option
+is given, the normal case being one. Note that if the option isn't
+given, the value isn't altered, so it should be initialised to some
+useful default.
+.It Fa arg_negative_flag
+this is the same as
+.Fa arg_flag
+but it reverses the meaning of the flag (a given short option clears
+the flag), and the synopsis of a long option is negated.
+.It Fa arg_strings
+the argument can be given multiple times, and the values are collected
+in an array;
+.Fa value
+should be a pointer to a
+.Fa struct getarg_strings
+structure, which holds a length and a string pointer.
+.It Fa arg_double
+argument is a double precision floating point value, and
+.Fa value
+should point to a
+.Fa double .
+.It Fa arg_collect
+allows more fine-grained control of the option parsing process.
+.Fa value
+should be a pointer to a
+.Fa getarg_collect_info
+structure:
+.Bd -literal
+typedef int (*getarg_collect_func)(int short_opt,
+ int argc,
+ char **argv,
+ int *optind,
+ int *optarg,
+ void *data);
+
+typedef struct getarg_collect_info {
+ getarg_collect_func func;
+ void *data;
+} getarg_collect_info;
+.Ed
+.Pp
+With the
+.Fa func
+member set to a function to call, and
+.Fa data
+to some application specific data. The parameters to the collect function are:
+.Bl -inset
+.It Fa short_flag
+non-zero if this call is via a short option flag, zero otherwise
+.It Fa argc , argv
+the whole argument list
+.It Fa optind
+pointer to the index in argv where the flag is
+.It Fa optarg
+pointer to the index in argv[*optind] where the flag name starts
+.It Fa data
+application specific data
+.El
+.Pp
+You can modify
+.Fa *optind ,
+and
+.Fa *optarg ,
+but to do this correct you (more or less) have to know about the inner
+workings of getarg.
+.Pp
+You can skip parts of arguments by increasing
+.Fa *optarg
+(you could
+implement the
+.Fl z Ns Ar 3
+set of flags from
+.Nm gzip
+with this), or whole argument strings by increasing
+.Fa *optind
+(let's say you want a flag
+.Fl c Ar x y z
+to specify a coordinate); if you also have to set
+.Fa *optarg
+to a sane value.
+.Pp
+The collect function should return one of
+.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG, ENOMEM
+on error, zero otherwise.
+.Pp
+For your convenience there is a function,
+.Fn getarg_optarg ,
+that returns the traditional argument string, and you pass it all
+arguments, sans data, that where given to the collection function.
+.Pp
+Don't use this more this unless you absolutely have to.
+.El
+.Pp
+Option parsing is similar to what
+.Xr getopt
+uses. Short options without arguments can be compressed
+.Pf ( Fl xyz
+is the same as
+.Fl x y z ) ,
+and short
+options with arguments take these as either the rest of the
+argv-string or as the next option
+.Pf ( Fl o Ns Ar foo ,
+or
+.Fl o Ar foo ) .
+.Pp
+Long option names are prefixed with -- (double dash), and the value
+with a = (equal),
+.Fl -foo= Ns Ar bar .
+Long option flags can either be specified as they are
+.Pf ( Fl -help ) ,
+or with an (boolean parsable) option
+.Pf ( Fl -help= Ns Ar yes ,
+.Fl -help= Ns Ar true ,
+or similar), or they can also be negated
+.Pf ( Fl -no-help
+is the same as
+.Fl -help= Ns no ) ,
+and if you're really confused you can do it multiple times
+.Pf ( Fl -no-no-help= Ns Ar false ,
+or even
+.Fl -no-no-help= Ns Ar maybe ) .
+.Sh EXAMPLE
+.Bd -literal
+#include <stdio.h>
+#include <string.h>
+#include <getarg.h>
+
+char *source = "Ouagadougou";
+char *destination;
+int weight;
+int include_catalog = 1;
+int help_flag;
+
+struct getargs args[] = {
+ { "source", 's', arg_string, &source,
+ "source of shippment", "city" },
+ { "destination", 'd', arg_string, &destination,
+ "destination of shippment", "city" },
+ { "weight", 'w', arg_integer, &weight,
+ "weight of shippment", "tons" },
+ { "catalog", 'c', arg_negative_flag, &include_catalog,
+ "include product catalog" },
+ { "help", 'h', arg_flag, &help_flag }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
+
+const char *progname = "ship++";
+
+int
+main(int argc, char **argv)
+{
+ int optind = 0;
+ if (getarg(args, num_args, argc, argv, &optind)) {
+ arg_printusage(args, num_args, progname, "stuff...");
+ exit (1);
+ }
+ if (help_flag) {
+ arg_printusage(args, num_args, progname, "stuff...");
+ exit (0);
+ }
+ if (destination == NULL) {
+ fprintf(stderr, "%s: must specify destination\en", progname);
+ exit(1);
+ }
+ if (strcmp(source, destination) == 0) {
+ fprintf(stderr, "%s: destination must be different from source\en");
+ exit(1);
+ }
+ /* include more stuff here ... */
+ exit(2);
+}
+.Ed
+.Pp
+The output help output from this program looks like this:
+.Bd -literal
+$ ship++ --help
+Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
+ [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
+-s city, --source=city source of shippment
+-d city, --destination=city destination of shippment
+-w tons, --weight=tons weight of shippment
+-c, --no-catalog include product catalog
+.Ed
+.Sh BUGS
+It should be more flexible, so it would be possible to use other more
+complicated option syntaxes, such as what
+.Xr ps 1 ,
+and
+.Xr tar 1 ,
+uses, or the AFS model where you can skip the flag names as long as
+the options come in the correct order.
+.Pp
+Options with multiple arguments should be handled better.
+.Pp
+Should be integreated with SL.
+.Pp
+It's very confusing that the struct you pass in is called getargS.
+.Sh SEE ALSO
+.Xr getopt 3
diff --git a/lib/roken/getarg.c b/lib/roken/getarg.c
new file mode 100644
index 0000000000000..c732d2fd43a59
--- /dev/null
+++ b/lib/roken/getarg.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getarg.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "roken.h"
+#include "getarg.h"
+
+#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
+
+static size_t
+print_arg (char *string, size_t len, int mdoc, int longp, struct getargs *arg)
+{
+ const char *s;
+
+ *string = '\0';
+
+ if (ISFLAG(*arg) || (!longp && arg->type == arg_counter))
+ return 0;
+
+ if(mdoc){
+ if(longp)
+ strlcat(string, "= Ns", len);
+ strlcat(string, " Ar ", len);
+ } else {
+ if (longp)
+ strlcat (string, "=", len);
+ else
+ strlcat (string, " ", len);
+ }
+
+ if (arg->arg_help)
+ s = arg->arg_help;
+ else if (arg->type == arg_integer || arg->type == arg_counter)
+ s = "integer";
+ else if (arg->type == arg_string)
+ s = "string";
+ else if (arg->type == arg_strings)
+ s = "strings";
+ else if (arg->type == arg_double)
+ s = "float";
+ else
+ s = "<undefined>";
+
+ strlcat(string, s, len);
+ return 1 + strlen(s);
+}
+
+static void
+mandoc_template(struct getargs *args,
+ size_t num_args,
+ const char *progname,
+ const char *extra_string)
+{
+ int i;
+ char timestr[64], cmd[64];
+ char buf[128];
+ const char *p;
+ time_t t;
+
+ printf(".\\\" Things to fix:\n");
+ printf(".\\\" * correct section, and operating system\n");
+ printf(".\\\" * remove Op from mandatory flags\n");
+ printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
+ printf(".\\\"\n");
+ t = time(NULL);
+ strftime(timestr, sizeof(timestr), "%B %e, %Y", localtime(&t));
+ printf(".Dd %s\n", timestr);
+ p = strrchr(progname, '/');
+ if(p) p++; else p = progname;
+ strlcpy(cmd, p, sizeof(cmd));
+ strupr(cmd);
+
+ printf(".Dt %s SECTION\n", cmd);
+ printf(".Os OPERATING_SYSTEM\n");
+ printf(".Sh NAME\n");
+ printf(".Nm %s\n", p);
+ printf(".Nd\n");
+ printf("in search of a description\n");
+ printf(".Sh SYNOPSIS\n");
+ printf(".Nm\n");
+ for(i = 0; i < num_args; i++){
+ /* we seem to hit a limit on number of arguments if doing
+ short and long flags with arguments -- split on two lines */
+ if(ISFLAG(args[i]) ||
+ args[i].short_name == 0 || args[i].long_name == NULL) {
+ printf(".Op ");
+
+ if(args[i].short_name) {
+ print_arg(buf, sizeof(buf), 1, 0, args + i);
+ printf("Fl %c%s", args[i].short_name, buf);
+ if(args[i].long_name)
+ printf(" | ");
+ }
+ if(args[i].long_name) {
+ print_arg(buf, sizeof(buf), 1, 1, args + i);
+ printf("Fl -%s%s%s",
+ args[i].type == arg_negative_flag ? "no-" : "",
+ args[i].long_name, buf);
+ }
+ printf("\n");
+ } else {
+ print_arg(buf, sizeof(buf), 1, 0, args + i);
+ printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf);
+ print_arg(buf, sizeof(buf), 1, 1, args + i);
+ printf(".Fl -%s%s\n.Xc\n.Oc\n", args[i].long_name, buf);
+ }
+ /*
+ if(args[i].type == arg_strings)
+ fprintf (stderr, "...");
+ */
+ }
+ if (extra_string && *extra_string)
+ printf (".Ar %s\n", extra_string);
+ printf(".Sh DESCRIPTION\n");
+ printf("Supported options:\n");
+ printf(".Bl -tag -width Ds\n");
+ for(i = 0; i < num_args; i++){
+ printf(".It Xo\n");
+ if(args[i].short_name){
+ printf(".Fl %c", args[i].short_name);
+ print_arg(buf, sizeof(buf), 1, 0, args + i);
+ printf("%s", buf);
+ if(args[i].long_name)
+ printf(" ,");
+ printf("\n");
+ }
+ if(args[i].long_name){
+ printf(".Fl -%s%s",
+ args[i].type == arg_negative_flag ? "no-" : "",
+ args[i].long_name);
+ print_arg(buf, sizeof(buf), 1, 1, args + i);
+ printf("%s\n", buf);
+ }
+ printf(".Xc\n");
+ if(args[i].help)
+ printf("%s\n", args[i].help);
+ /*
+ if(args[i].type == arg_strings)
+ fprintf (stderr, "...");
+ */
+ }
+ printf(".El\n");
+ printf(".\\\".Sh ENVIRONMENT\n");
+ printf(".\\\".Sh FILES\n");
+ printf(".\\\".Sh EXAMPLES\n");
+ printf(".\\\".Sh DIAGNOSTICS\n");
+ printf(".\\\".Sh SEE ALSO\n");
+ printf(".\\\".Sh STANDARDS\n");
+ printf(".\\\".Sh HISTORY\n");
+ printf(".\\\".Sh AUTHORS\n");
+ printf(".\\\".Sh BUGS\n");
+}
+
+static int
+check_column(FILE *f, int col, int len, int columns)
+{
+ if(col + len > columns) {
+ fprintf(f, "\n");
+ col = fprintf(f, " ");
+ }
+ return col;
+}
+
+void ROKEN_LIB_FUNCTION
+arg_printusage (struct getargs *args,
+ size_t num_args,
+ const char *progname,
+ const char *extra_string)
+{
+ int i;
+ size_t max_len = 0;
+ char buf[128];
+ int col = 0, columns;
+ struct winsize ws;
+
+ if (progname == NULL)
+ progname = getprogname();
+
+ if(getenv("GETARGMANDOC")){
+ mandoc_template(args, num_args, progname, extra_string);
+ return;
+ }
+ if(get_window_size(2, &ws) == 0)
+ columns = ws.ws_col;
+ else
+ columns = 80;
+ col = 0;
+ col += fprintf (stderr, "Usage: %s", progname);
+ buf[0] = '\0';
+ for (i = 0; i < num_args; ++i) {
+ if(args[i].short_name && ISFLAG(args[i])) {
+ char s[2];
+ if(buf[0] == '\0')
+ strlcpy(buf, "[-", sizeof(buf));
+ s[0] = args[i].short_name;
+ s[1] = '\0';
+ strlcat(buf, s, sizeof(buf));
+ }
+ }
+ if(buf[0] != '\0') {
+ strlcat(buf, "]", sizeof(buf));
+ col = check_column(stderr, col, strlen(buf) + 1, columns);
+ col += fprintf(stderr, " %s", buf);
+ }
+
+ for (i = 0; i < num_args; ++i) {
+ size_t len = 0;
+
+ if (args[i].long_name) {
+ buf[0] = '\0';
+ strlcat(buf, "[--", sizeof(buf));
+ len += 2;
+ if(args[i].type == arg_negative_flag) {
+ strlcat(buf, "no-", sizeof(buf));
+ len += 3;
+ }
+ strlcat(buf, args[i].long_name, sizeof(buf));
+ len += strlen(args[i].long_name);
+ len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ 0, 1, &args[i]);
+ strlcat(buf, "]", sizeof(buf));
+ if(args[i].type == arg_strings)
+ strlcat(buf, "...", sizeof(buf));
+ col = check_column(stderr, col, strlen(buf) + 1, columns);
+ col += fprintf(stderr, " %s", buf);
+ }
+ if (args[i].short_name && !ISFLAG(args[i])) {
+ snprintf(buf, sizeof(buf), "[-%c", args[i].short_name);
+ len += 2;
+ len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ 0, 0, &args[i]);
+ strlcat(buf, "]", sizeof(buf));
+ if(args[i].type == arg_strings)
+ strlcat(buf, "...", sizeof(buf));
+ col = check_column(stderr, col, strlen(buf) + 1, columns);
+ col += fprintf(stderr, " %s", buf);
+ }
+ if (args[i].long_name && args[i].short_name)
+ len += 2; /* ", " */
+ max_len = max(max_len, len);
+ }
+ if (extra_string) {
+ col = check_column(stderr, col, strlen(extra_string) + 1, columns);
+ fprintf (stderr, " %s\n", extra_string);
+ } else
+ fprintf (stderr, "\n");
+ for (i = 0; i < num_args; ++i) {
+ if (args[i].help) {
+ size_t count = 0;
+
+ if (args[i].short_name) {
+ count += fprintf (stderr, "-%c", args[i].short_name);
+ print_arg (buf, sizeof(buf), 0, 0, &args[i]);
+ count += fprintf(stderr, "%s", buf);
+ }
+ if (args[i].short_name && args[i].long_name)
+ count += fprintf (stderr, ", ");
+ if (args[i].long_name) {
+ count += fprintf (stderr, "--");
+ if (args[i].type == arg_negative_flag)
+ count += fprintf (stderr, "no-");
+ count += fprintf (stderr, "%s", args[i].long_name);
+ print_arg (buf, sizeof(buf), 0, 1, &args[i]);
+ count += fprintf(stderr, "%s", buf);
+ }
+ while(count++ <= max_len)
+ putc (' ', stderr);
+ fprintf (stderr, "%s\n", args[i].help);
+ }
+ }
+}
+
+static int
+add_string(getarg_strings *s, char *value)
+{
+ char **strings;
+
+ strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings));
+ if (strings == NULL) {
+ free(s->strings);
+ s->strings = NULL;
+ s->num_strings = 0;
+ return ENOMEM;
+ }
+ s->strings = strings;
+ s->strings[s->num_strings] = value;
+ s->num_strings++;
+ return 0;
+}
+
+static int
+arg_match_long(struct getargs *args, size_t num_args,
+ char *argv, int argc, char **rargv, int *goptind)
+{
+ int i;
+ char *goptarg = NULL;
+ int negate = 0;
+ int partial_match = 0;
+ struct getargs *partial = NULL;
+ struct getargs *current = NULL;
+ int argv_len;
+ char *p;
+ int p_len;
+
+ argv_len = strlen(argv);
+ p = strchr (argv, '=');
+ if (p != NULL)
+ argv_len = p - argv;
+
+ for (i = 0; i < num_args; ++i) {
+ if(args[i].long_name) {
+ int len = strlen(args[i].long_name);
+ p = argv;
+ p_len = argv_len;
+ negate = 0;
+
+ for (;;) {
+ if (strncmp (args[i].long_name, p, p_len) == 0) {
+ if(p_len == len)
+ current = &args[i];
+ else {
+ ++partial_match;
+ partial = &args[i];
+ }
+ goptarg = p + p_len;
+ } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) {
+ negate = !negate;
+ p += 3;
+ p_len -= 3;
+ continue;
+ }
+ break;
+ }
+ if (current)
+ break;
+ }
+ }
+ if (current == NULL) {
+ if (partial_match == 1)
+ current = partial;
+ else
+ return ARG_ERR_NO_MATCH;
+ }
+
+ if(*goptarg == '\0'
+ && !ISFLAG(*current)
+ && current->type != arg_collect
+ && current->type != arg_counter)
+ return ARG_ERR_NO_MATCH;
+ switch(current->type){
+ case arg_integer:
+ {
+ int tmp;
+ if(sscanf(goptarg + 1, "%d", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(int*)current->value = tmp;
+ return 0;
+ }
+ case arg_string:
+ {
+ *(char**)current->value = goptarg + 1;
+ return 0;
+ }
+ case arg_strings:
+ {
+ return add_string((getarg_strings*)current->value, goptarg + 1);
+ }
+ case arg_flag:
+ case arg_negative_flag:
+ {
+ int *flag = current->value;
+ if(*goptarg == '\0' ||
+ strcmp(goptarg + 1, "yes") == 0 ||
+ strcmp(goptarg + 1, "true") == 0){
+ *flag = !negate;
+ return 0;
+ } else if (*goptarg && strcmp(goptarg + 1, "maybe") == 0) {
+#ifdef HAVE_RANDOM
+ *flag = random() & 1;
+#else
+ *flag = rand() & 1;
+#endif
+ } else {
+ *flag = negate;
+ return 0;
+ }
+ return ARG_ERR_BAD_ARG;
+ }
+ case arg_counter :
+ {
+ int val;
+
+ if (*goptarg == '\0')
+ val = 1;
+ else if(sscanf(goptarg + 1, "%d", &val) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(int *)current->value += val;
+ return 0;
+ }
+ case arg_double:
+ {
+ double tmp;
+ if(sscanf(goptarg + 1, "%lf", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(double*)current->value = tmp;
+ return 0;
+ }
+ case arg_collect:{
+ struct getarg_collect_info *c = current->value;
+ int o = argv - rargv[*goptind];
+ return (*c->func)(FALSE, argc, rargv, goptind, &o, c->data);
+ }
+
+ default:
+ abort ();
+ }
+}
+
+static int
+arg_match_short (struct getargs *args, size_t num_args,
+ char *argv, int argc, char **rargv, int *goptind)
+{
+ int j, k;
+
+ for(j = 1; j > 0 && j < strlen(rargv[*goptind]); j++) {
+ for(k = 0; k < num_args; k++) {
+ char *goptarg;
+
+ if(args[k].short_name == 0)
+ continue;
+ if(argv[j] == args[k].short_name) {
+ if(args[k].type == arg_flag) {
+ *(int*)args[k].value = 1;
+ break;
+ }
+ if(args[k].type == arg_negative_flag) {
+ *(int*)args[k].value = 0;
+ break;
+ }
+ if(args[k].type == arg_counter) {
+ ++*(int *)args[k].value;
+ break;
+ }
+ if(args[k].type == arg_collect) {
+ struct getarg_collect_info *c = args[k].value;
+
+ if((*c->func)(TRUE, argc, rargv, goptind, &j, c->data))
+ return ARG_ERR_BAD_ARG;
+ break;
+ }
+
+ if(argv[j + 1])
+ goptarg = &argv[j + 1];
+ else {
+ ++*goptind;
+ goptarg = rargv[*goptind];
+ }
+ if(goptarg == NULL) {
+ --*goptind;
+ return ARG_ERR_NO_ARG;
+ }
+ if(args[k].type == arg_integer) {
+ int tmp;
+ if(sscanf(goptarg, "%d", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(int*)args[k].value = tmp;
+ return 0;
+ } else if(args[k].type == arg_string) {
+ *(char**)args[k].value = goptarg;
+ return 0;
+ } else if(args[k].type == arg_strings) {
+ return add_string((getarg_strings*)args[k].value, goptarg);
+ } else if(args[k].type == arg_double) {
+ double tmp;
+ if(sscanf(goptarg, "%lf", &tmp) != 1)
+ return ARG_ERR_BAD_ARG;
+ *(double*)args[k].value = tmp;
+ return 0;
+ }
+ return ARG_ERR_BAD_ARG;
+ }
+ }
+ if (k == num_args)
+ return ARG_ERR_NO_MATCH;
+ }
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+getarg(struct getargs *args, size_t num_args,
+ int argc, char **argv, int *goptind)
+{
+ int i;
+ int ret = 0;
+
+#if defined(HAVE_SRANDOMDEV)
+ srandomdev();
+#elif defined(HAVE_RANDOM)
+ srandom(time(NULL));
+#else
+ srand (time(NULL));
+#endif
+ (*goptind)++;
+ for(i = *goptind; i < argc; i++) {
+ if(argv[i][0] != '-')
+ break;
+ if(argv[i][1] == '-'){
+ if(argv[i][2] == 0){
+ i++;
+ break;
+ }
+ ret = arg_match_long (args, num_args, argv[i] + 2,
+ argc, argv, &i);
+ } else {
+ ret = arg_match_short (args, num_args, argv[i],
+ argc, argv, &i);
+ }
+ if(ret)
+ break;
+ }
+ *goptind = i;
+ return ret;
+}
+
+void ROKEN_LIB_FUNCTION
+free_getarg_strings (getarg_strings *s)
+{
+ free (s->strings);
+}
+
+#if TEST
+int foo_flag = 2;
+int flag1 = 0;
+int flag2 = 0;
+int bar_int;
+char *baz_string;
+
+struct getargs args[] = {
+ { NULL, '1', arg_flag, &flag1, "one", NULL },
+ { NULL, '2', arg_flag, &flag2, "two", NULL },
+ { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
+ { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
+ { "baz", 'x', arg_string, &baz_string, "baz", "name" },
+};
+
+int main(int argc, char **argv)
+{
+ int goptind = 0;
+ while(getarg(args, 5, argc, argv, &goptind))
+ printf("Bad arg: %s\n", argv[goptind]);
+ printf("flag1 = %d\n", flag1);
+ printf("flag2 = %d\n", flag2);
+ printf("foo_flag = %d\n", foo_flag);
+ printf("bar_int = %d\n", bar_int);
+ printf("baz_flag = %s\n", baz_string);
+ arg_printusage (args, 5, argv[0], "nothing here");
+}
+#endif
diff --git a/lib/roken/getarg.h b/lib/roken/getarg.h
new file mode 100644
index 0000000000000..62d1b6687c365
--- /dev/null
+++ b/lib/roken/getarg.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: getarg.h 14776 2005-04-13 05:52:27Z lha $ */
+
+#ifndef __GETARG_H__
+#define __GETARG_H__
+
+#include <stddef.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+struct getargs{
+ const char *long_name;
+ char short_name;
+ enum { arg_integer,
+ arg_string,
+ arg_flag,
+ arg_negative_flag,
+ arg_strings,
+ arg_double,
+ arg_collect,
+ arg_counter
+ } type;
+ void *value;
+ const char *help;
+ const char *arg_help;
+};
+
+enum {
+ ARG_ERR_NO_MATCH = 1,
+ ARG_ERR_BAD_ARG,
+ ARG_ERR_NO_ARG
+};
+
+typedef struct getarg_strings {
+ int num_strings;
+ char **strings;
+} getarg_strings;
+
+typedef int (*getarg_collect_func)(int short_opt,
+ int argc,
+ char **argv,
+ int *goptind,
+ int *goptarg,
+ void *data);
+
+typedef struct getarg_collect_info {
+ getarg_collect_func func;
+ void *data;
+} getarg_collect_info;
+
+int ROKEN_LIB_FUNCTION
+getarg(struct getargs *args, size_t num_args,
+ int argc, char **argv, int *goptind);
+
+void ROKEN_LIB_FUNCTION
+arg_printusage (struct getargs *args,
+ size_t num_args,
+ const char *progname,
+ const char *extra_string);
+
+void ROKEN_LIB_FUNCTION
+free_getarg_strings (getarg_strings *);
+
+#endif /* __GETARG_H__ */
diff --git a/lib/roken/getcap.c b/lib/roken/getcap.c
new file mode 100644
index 0000000000000..a4e3a7de5d98d
--- /dev/null
+++ b/lib/roken/getcap.c
@@ -0,0 +1,1122 @@
+/* $NetBSD: getcap.c,v 1.29 1999/03/29 09:27:29 abs Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Casey Leedom of Lawrence Livermore National Laboratory.
+ *
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+RCSID("$Id: getcap.c 22071 2007-11-14 20:04:50Z lha $");
+
+#include <sys/types.h>
+#include <ctype.h>
+#if defined(HAVE_DB_185_H)
+#include <db_185.h>
+#elif defined(HAVE_DB_H)
+#include <db.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BFRAG 1024
+#if 0
+#define BSIZE 1024
+#endif
+#define ESC ('[' & 037) /* ASCII ESC */
+#define MAX_RECURSION 32 /* maximum getent recursion */
+#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */
+
+#define RECOK (char)0
+#define TCERR (char)1
+#define SHADOW (char)2
+
+static size_t topreclen; /* toprec length */
+static char *toprec; /* Additional record specified by cgetset() */
+static int gottoprec; /* Flag indicating retrieval of toprecord */
+
+#if 0 /*
+ * Don't use db support unless it's build into libc but we don't
+ * check for that now, so just disable the code.
+ */
+#if defined(HAVE_DBOPEN) && defined(HAVE_DB_H)
+#define USE_DB
+#endif
+#endif
+
+#ifdef USE_DB
+static int cdbget (DB *, char **, const char *);
+#endif
+static int getent (char **, size_t *, char **, int, const char *, int, char *);
+static int nfcmp (char *, char *);
+
+
+int ROKEN_LIB_FUNCTION cgetset(const char *ent);
+char *ROKEN_LIB_FUNCTION cgetcap(char *buf, const char *cap, int type);
+int ROKEN_LIB_FUNCTION cgetent(char **buf, char **db_array, const char *name);
+int ROKEN_LIB_FUNCTION cgetmatch(const char *buf, const char *name);
+int ROKEN_LIB_FUNCTION cgetclose(void);
+#if 0
+int cgetfirst(char **buf, char **db_array);
+int cgetnext(char **bp, char **db_array);
+#endif
+int ROKEN_LIB_FUNCTION cgetstr(char *buf, const char *cap, char **str);
+int ROKEN_LIB_FUNCTION cgetustr(char *buf, const char *cap, char **str);
+int ROKEN_LIB_FUNCTION cgetnum(char *buf, const char *cap, long *num);
+/*
+ * Cgetset() allows the addition of a user specified buffer to be added
+ * to the database array, in effect "pushing" the buffer on top of the
+ * virtual database. 0 is returned on success, -1 on failure.
+ */
+int ROKEN_LIB_FUNCTION
+cgetset(const char *ent)
+{
+ const char *source, *check;
+ char *dest;
+
+ if (ent == NULL) {
+ if (toprec)
+ free(toprec);
+ toprec = NULL;
+ topreclen = 0;
+ return (0);
+ }
+ topreclen = strlen(ent);
+ if ((toprec = malloc (topreclen + 1)) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ gottoprec = 0;
+
+ source=ent;
+ dest=toprec;
+ while (*source) { /* Strip whitespace */
+ *dest++ = *source++; /* Do not check first field */
+ while (*source == ':') {
+ check=source+1;
+ while (*check && (isspace((unsigned char)*check) ||
+ (*check=='\\' && isspace((unsigned char)check[1]))))
+ ++check;
+ if( *check == ':' )
+ source=check;
+ else
+ break;
+
+ }
+ }
+ *dest=0;
+
+ return (0);
+}
+
+/*
+ * Cgetcap searches the capability record buf for the capability cap with
+ * type `type'. A pointer to the value of cap is returned on success, NULL
+ * if the requested capability couldn't be found.
+ *
+ * Specifying a type of ':' means that nothing should follow cap (:cap:).
+ * In this case a pointer to the terminating ':' or NUL will be returned if
+ * cap is found.
+ *
+ * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
+ * return NULL.
+ */
+char * ROKEN_LIB_FUNCTION
+cgetcap(char *buf, const char *cap, int type)
+{
+ char *bp;
+ const char *cp;
+
+ bp = buf;
+ for (;;) {
+ /*
+ * Skip past the current capability field - it's either the
+ * name field if this is the first time through the loop, or
+ * the remainder of a field whose name failed to match cap.
+ */
+ for (;;)
+ if (*bp == '\0')
+ return (NULL);
+ else
+ if (*bp++ == ':')
+ break;
+
+ /*
+ * Try to match (cap, type) in buf.
+ */
+ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
+ continue;
+ if (*cp != '\0')
+ continue;
+ if (*bp == '@')
+ return (NULL);
+ if (type == ':') {
+ if (*bp != '\0' && *bp != ':')
+ continue;
+ return(bp);
+ }
+ if (*bp != type)
+ continue;
+ bp++;
+ return (*bp == '@' ? NULL : bp);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetent extracts the capability record name from the NULL terminated file
+ * array db_array and returns a pointer to a malloc'd copy of it in buf.
+ * Buf must be retained through all subsequent calls to cgetcap, cgetnum,
+ * cgetflag, and cgetstr, but may then be free'd. 0 is returned on success,
+ * -1 if the requested record couldn't be found, -2 if a system error was
+ * encountered (couldn't open/read a file, etc.), and -3 if a potential
+ * reference loop is detected.
+ */
+int ROKEN_LIB_FUNCTION
+cgetent(char **buf, char **db_array, const char *name)
+{
+ size_t dummy;
+
+ return (getent(buf, &dummy, db_array, -1, name, 0, NULL));
+}
+
+/*
+ * Getent implements the functions of cgetent. If fd is non-negative,
+ * *db_array has already been opened and fd is the open file descriptor. We
+ * do this to save time and avoid using up file descriptors for tc=
+ * recursions.
+ *
+ * Getent returns the same success/failure codes as cgetent. On success, a
+ * pointer to a malloc'ed capability record with all tc= capabilities fully
+ * expanded and its length (not including trailing ASCII NUL) are left in
+ * *cap and *len.
+ *
+ * Basic algorithm:
+ * + Allocate memory incrementally as needed in chunks of size BFRAG
+ * for capability buffer.
+ * + Recurse for each tc=name and interpolate result. Stop when all
+ * names interpolated, a name can't be found, or depth exceeds
+ * MAX_RECURSION.
+ */
+static int
+getent(char **cap, size_t *len, char **db_array, int fd,
+ const char *name, int depth, char *nfield)
+{
+ char *r_end, *rp = NULL, **db_p; /* pacify gcc */
+ int myfd = 0, eof, foundit;
+ char *record;
+ int tc_not_resolved;
+
+ /*
+ * Return with ``loop detected'' error if we've recursed more than
+ * MAX_RECURSION times.
+ */
+ if (depth > MAX_RECURSION)
+ return (-3);
+
+ /*
+ * Check if we have a top record from cgetset().
+ */
+ if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) {
+ size_t len = topreclen + BFRAG;
+ if ((record = malloc (len)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ (void)strlcpy(record, toprec, len);
+ db_p = db_array;
+ rp = record + topreclen + 1;
+ r_end = rp + BFRAG;
+ goto tc_exp;
+ }
+ /*
+ * Allocate first chunk of memory.
+ */
+ if ((record = malloc(BFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ r_end = record + BFRAG;
+ foundit = 0;
+ /*
+ * Loop through database array until finding the record.
+ */
+
+ for (db_p = db_array; *db_p != NULL; db_p++) {
+ eof = 0;
+
+ /*
+ * Open database if not already open.
+ */
+
+ if (fd >= 0) {
+ (void)lseek(fd, (off_t)0, SEEK_SET);
+ } else {
+#ifdef USE_DB
+ char pbuf[_POSIX_PATH_MAX];
+ char *cbuf;
+ size_t clen;
+ int retval;
+ DB *capdbp;
+
+ (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p);
+ if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0))
+ != NULL) {
+ free(record);
+ retval = cdbget(capdbp, &record, name);
+ if (retval < 0) {
+ /* no record available */
+ (void)capdbp->close(capdbp);
+ return (retval);
+ }
+ /* save the data; close frees it */
+ clen = strlen(record);
+ cbuf = malloc(clen + 1);
+ if (cbuf == NULL)
+ return (-2);
+ memmove(cbuf, record, clen + 1);
+ if (capdbp->close(capdbp) < 0) {
+ free(cbuf);
+ return (-2);
+ }
+ *len = clen;
+ *cap = cbuf;
+ return (retval);
+ } else
+#endif
+ {
+ fd = open(*db_p, O_RDONLY, 0);
+ if (fd < 0) {
+ /* No error on unfound file. */
+ continue;
+ }
+ myfd = 1;
+ }
+ }
+ /*
+ * Find the requested capability record ...
+ */
+ {
+ char buf[BUFSIZ];
+ char *b_end, *bp, *cp;
+ int c, slash;
+
+ /*
+ * Loop invariants:
+ * There is always room for one more character in record.
+ * R_end always points just past end of record.
+ * Rp always points just past last character in record.
+ * B_end always points just past last character in buf.
+ * Bp always points at next character in buf.
+ * Cp remembers where the last colon was.
+ */
+ b_end = buf;
+ bp = buf;
+ cp = 0;
+ slash = 0;
+ for (;;) {
+
+ /*
+ * Read in a line implementing (\, newline)
+ * line continuation.
+ */
+ rp = record;
+ for (;;) {
+ if (bp >= b_end) {
+ int n;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (myfd)
+ (void)close(fd);
+ if (n < 0) {
+ free(record);
+ return (-2);
+ } else {
+ fd = -1;
+ eof = 1;
+ break;
+ }
+ }
+ b_end = buf+n;
+ bp = buf;
+ }
+
+ c = *bp++;
+ if (c == '\n') {
+ if (slash) {
+ slash = 0;
+ rp--;
+ continue;
+ } else
+ break;
+ }
+ if (slash) {
+ slash = 0;
+ cp = 0;
+ }
+ if (c == ':') {
+ /*
+ * If the field was `empty' (i.e.
+ * contained only white space), back up
+ * to the colon (eliminating the
+ * field).
+ */
+ if (cp)
+ rp = cp;
+ else
+ cp = rp;
+ } else if (c == '\\') {
+ slash = 1;
+ } else if (c != ' ' && c != '\t') {
+ /*
+ * Forget where the colon was, as this
+ * is not an empty field.
+ */
+ cp = 0;
+ }
+ *rp++ = c;
+
+ /*
+ * Enforce loop invariant: if no room
+ * left in record buffer, try to get
+ * some more.
+ */
+ if (rp >= r_end) {
+ u_int pos;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + BFRAG;
+ record = realloc(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)close(fd);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ }
+ }
+ /* Eliminate any white space after the last colon. */
+ if (cp)
+ rp = cp + 1;
+ /* Loop invariant lets us do this. */
+ *rp++ = '\0';
+
+ /*
+ * If encountered eof check next file.
+ */
+ if (eof)
+ break;
+
+ /*
+ * Toss blank lines and comments.
+ */
+ if (*record == '\0' || *record == '#')
+ continue;
+
+ /*
+ * See if this is the record we want ...
+ */
+ if (cgetmatch(record, name) == 0) {
+ if (nfield == NULL || !nfcmp(nfield, record)) {
+ foundit = 1;
+ break; /* found it! */
+ }
+ }
+ }
+ }
+ if (foundit)
+ break;
+ }
+
+ if (!foundit)
+ return (-1);
+
+ /*
+ * Got the capability record, but now we have to expand all tc=name
+ * references in it ...
+ */
+ tc_exp: {
+ char *newicap, *s;
+ size_t ilen, newilen;
+ int diff, iret, tclen;
+ char *icap, *scan, *tc, *tcstart, *tcend;
+
+ /*
+ * Loop invariants:
+ * There is room for one more character in record.
+ * R_end points just past end of record.
+ * Rp points just past last character in record.
+ * Scan points at remainder of record that needs to be
+ * scanned for tc=name constructs.
+ */
+ scan = record;
+ tc_not_resolved = 0;
+ for (;;) {
+ if ((tc = cgetcap(scan, "tc", '=')) == NULL)
+ break;
+
+ /*
+ * Find end of tc=name and stomp on the trailing `:'
+ * (if present) so we can use it to call ourselves.
+ */
+ s = tc;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':') {
+ *(s - 1) = '\0';
+ break;
+ }
+ tcstart = tc - 3;
+ tclen = s - tcstart;
+ tcend = s;
+
+ iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
+ NULL);
+ newicap = icap; /* Put into a register. */
+ newilen = ilen;
+ if (iret != 0) {
+ /* an error */
+ if (iret < -1) {
+ if (myfd)
+ (void)close(fd);
+ free(record);
+ return (iret);
+ }
+ if (iret == 1)
+ tc_not_resolved = 1;
+ /* couldn't resolve tc */
+ if (iret == -1) {
+ *(s - 1) = ':';
+ scan = s - 1;
+ tc_not_resolved = 1;
+ continue;
+
+ }
+ }
+ /* not interested in name field of tc'ed record */
+ s = newicap;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':')
+ break;
+ newilen -= s - newicap;
+ newicap = s;
+
+ /* make sure interpolated record is `:'-terminated */
+ s += newilen;
+ if (*(s-1) != ':') {
+ *s = ':'; /* overwrite NUL with : */
+ newilen++;
+ }
+
+ /*
+ * Make sure there's enough room to insert the
+ * new record.
+ */
+ diff = newilen - tclen;
+ if (diff >= r_end - rp) {
+ u_int pos, tcpos, tcposend;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + diff + BFRAG;
+ tcpos = tcstart - record;
+ tcposend = tcend - record;
+ record = realloc(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)close(fd);
+ free(icap);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ tcstart = record + tcpos;
+ tcend = record + tcposend;
+ }
+
+ /*
+ * Insert tc'ed record into our record.
+ */
+ s = tcstart + newilen;
+ memmove(s, tcend, (size_t)(rp - tcend));
+ memmove(tcstart, newicap, newilen);
+ rp += diff;
+ free(icap);
+
+ /*
+ * Start scan on `:' so next cgetcap works properly
+ * (cgetcap always skips first field).
+ */
+ scan = s-1;
+ }
+
+ }
+ /*
+ * Close file (if we opened it), give back any extra memory, and
+ * return capability, length and success.
+ */
+ if (myfd)
+ (void)close(fd);
+ *len = rp - record - 1; /* don't count NUL */
+ if (r_end > rp)
+ if ((record =
+ realloc(record, (size_t)(rp - record))) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+
+ *cap = record;
+ if (tc_not_resolved)
+ return (1);
+ return (0);
+}
+
+#ifdef USE_DB
+static int
+cdbget(DB *capdbp, char **bp, const char *name)
+{
+ DBT key;
+ DBT data;
+
+ /* LINTED key is not modified */
+ key.data = (char *)name;
+ key.size = strlen(name);
+
+ for (;;) {
+ /* Get the reference. */
+ switch(capdbp->get(capdbp, &key, &data, 0)) {
+ case -1:
+ return (-2);
+ case 1:
+ return (-1);
+ }
+
+ /* If not an index to another record, leave. */
+ if (((char *)data.data)[0] != SHADOW)
+ break;
+
+ key.data = (char *)data.data + 1;
+ key.size = data.size - 1;
+ }
+
+ *bp = (char *)data.data + 1;
+ return (((char *)(data.data))[0] == TCERR ? 1 : 0);
+}
+#endif /* USE_DB */
+
+/*
+ * Cgetmatch will return 0 if name is one of the names of the capability
+ * record buf, -1 if not.
+ */
+int
+cgetmatch(const char *buf, const char *name)
+{
+ const char *np, *bp;
+
+ /*
+ * Start search at beginning of record.
+ */
+ bp = buf;
+ for (;;) {
+ /*
+ * Try to match a record name.
+ */
+ np = name;
+ for (;;)
+ if (*np == '\0') {
+ if (*bp == '|' || *bp == ':' || *bp == '\0')
+ return (0);
+ else
+ break;
+ } else
+ if (*bp++ != *np++)
+ break;
+
+ /*
+ * Match failed, skip to next name in record.
+ */
+ bp--; /* a '|' or ':' may have stopped the match */
+ for (;;)
+ if (*bp == '\0' || *bp == ':')
+ return (-1); /* match failed totally */
+ else
+ if (*bp++ == '|')
+ break; /* found next name */
+ }
+}
+
+#if 0
+int
+cgetfirst(char **buf, char **db_array)
+{
+ (void)cgetclose();
+ return (cgetnext(buf, db_array));
+}
+#endif
+
+static FILE *pfp;
+static int slash;
+static char **dbp;
+
+int ROKEN_LIB_FUNCTION
+cgetclose(void)
+{
+ if (pfp != NULL) {
+ (void)fclose(pfp);
+ pfp = NULL;
+ }
+ dbp = NULL;
+ gottoprec = 0;
+ slash = 0;
+ return(0);
+}
+
+#if 0
+/*
+ * Cgetnext() gets either the first or next entry in the logical database
+ * specified by db_array. It returns 0 upon completion of the database, 1
+ * upon returning an entry with more remaining, and -1 if an error occurs.
+ */
+int
+cgetnext(char **bp, char **db_array)
+{
+ size_t len;
+ int status, done;
+ char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
+ size_t dummy;
+
+ if (dbp == NULL)
+ dbp = db_array;
+
+ if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ }
+ for(;;) {
+ if (toprec && !gottoprec) {
+ gottoprec = 1;
+ line = toprec;
+ } else {
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ if (ferror(pfp)) {
+ (void)cgetclose();
+ return (-1);
+ } else {
+ (void)fclose(pfp);
+ pfp = NULL;
+ if (*++dbp == NULL) {
+ (void)cgetclose();
+ return (0);
+ } else if ((pfp =
+ fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ } else
+ continue;
+ }
+ } else
+ line[len - 1] = '\0';
+ if (len == 1) {
+ slash = 0;
+ continue;
+ }
+ if (isspace((unsigned char)*line) ||
+ *line == ':' || *line == '#' || slash) {
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ continue;
+ }
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ }
+
+
+ /*
+ * Line points to a name line.
+ */
+ done = 0;
+ np = nbuf;
+ for (;;) {
+ for (cp = line; *cp != '\0'; cp++) {
+ if (*cp == ':') {
+ *np++ = ':';
+ done = 1;
+ break;
+ }
+ if (*cp == '\\')
+ break;
+ *np++ = *cp;
+ }
+ if (done) {
+ *np = '\0';
+ break;
+ } else { /* name field extends beyond the line */
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ if (ferror(pfp)) {
+ (void)cgetclose();
+ return (-1);
+ }
+ (void)fclose(pfp);
+ pfp = NULL;
+ *np = '\0';
+ break;
+ } else
+ line[len - 1] = '\0';
+ }
+ }
+ rp = buf;
+ for(cp = nbuf; *cp != '\0'; cp++)
+ if (*cp == '|' || *cp == ':')
+ break;
+ else
+ *rp++ = *cp;
+
+ *rp = '\0';
+ /*
+ * XXX
+ * Last argument of getent here should be nbuf if we want true
+ * sequential access in the case of duplicates.
+ * With NULL, getent will return the first entry found
+ * rather than the duplicate entry record. This is a
+ * matter of semantics that should be resolved.
+ */
+ status = getent(bp, &dummy, db_array, -1, buf, 0, NULL);
+ if (status == -2 || status == -3)
+ (void)cgetclose();
+
+ return (status + 1);
+ }
+ /* NOTREACHED */
+}
+#endif
+
+/*
+ * Cgetstr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. A pointer to a decoded, NUL
+ * terminated, malloc'd copy of the string is returned in the char *
+ * pointed to by str. The length of the string not including the trailing
+ * NUL is returned on success, -1 if the requested string capability
+ * couldn't be found, -2 if a system error was encountered (storage
+ * allocation failure).
+ */
+int ROKEN_LIB_FUNCTION
+cgetstr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ const char *bp;
+ char *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ bp = cgetcap(buf, cap, '=');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ if (*bp == '^') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ *mp++ = *bp++ & 037;
+ } else if (*bp == '\\') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ if ('0' <= *bp && *bp <= '7') {
+ int n, i;
+
+ n = 0;
+ i = 3; /* maximum of three octal digits */
+ do {
+ n = n * 8 + (*bp++ - '0');
+ } while (--i && '0' <= *bp && *bp <= '7');
+ *mp++ = n;
+ }
+ else switch (*bp++) {
+ case 'b': case 'B':
+ *mp++ = '\b';
+ break;
+ case 't': case 'T':
+ *mp++ = '\t';
+ break;
+ case 'n': case 'N':
+ *mp++ = '\n';
+ break;
+ case 'f': case 'F':
+ *mp++ = '\f';
+ break;
+ case 'r': case 'R':
+ *mp++ = '\r';
+ break;
+ case 'e': case 'E':
+ *mp++ = ESC;
+ break;
+ case 'c': case 'C':
+ *mp++ = ':';
+ break;
+ default:
+ /*
+ * Catches '\', '^', and
+ * everything else.
+ */
+ *mp++ = *(bp-1);
+ break;
+ }
+ } else
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = realloc(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = realloc(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetustr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. The difference between cgetustr()
+ * and cgetstr() is that cgetustr does not decode escapes but rather treats
+ * all characters literally. A pointer to a NUL terminated malloc'd
+ * copy of the string is returned in the char pointed to by str. The
+ * length of the string not including the trailing NUL is returned on success,
+ * -1 if the requested string capability couldn't be found, -2 if a system
+ * error was encountered (storage allocation failure).
+ */
+int ROKEN_LIB_FUNCTION
+cgetustr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ const char *bp;
+ char *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ if ((bp = cgetcap(buf, cap, '=')) == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = realloc(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = realloc(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetnum retrieves the value of the numeric capability cap from the
+ * capability record pointed to by buf. The numeric value is returned in
+ * the long pointed to by num. 0 is returned on success, -1 if the requested
+ * numeric capability couldn't be found.
+ */
+int ROKEN_LIB_FUNCTION
+cgetnum(char *buf, const char *cap, long *num)
+{
+ long n;
+ int base, digit;
+ const char *bp;
+
+ /*
+ * Find numeric capability cap
+ */
+ bp = cgetcap(buf, cap, '#');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Look at value and determine numeric base:
+ * 0x... or 0X... hexadecimal,
+ * else 0... octal,
+ * else decimal.
+ */
+ if (*bp == '0') {
+ bp++;
+ if (*bp == 'x' || *bp == 'X') {
+ bp++;
+ base = 16;
+ } else
+ base = 8;
+ } else
+ base = 10;
+
+ /*
+ * Conversion loop ...
+ */
+ n = 0;
+ for (;;) {
+ if ('0' <= *bp && *bp <= '9')
+ digit = *bp - '0';
+ else if ('a' <= *bp && *bp <= 'f')
+ digit = 10 + *bp - 'a';
+ else if ('A' <= *bp && *bp <= 'F')
+ digit = 10 + *bp - 'A';
+ else
+ break;
+
+ if (digit >= base)
+ break;
+
+ n = n * base + digit;
+ bp++;
+ }
+
+ /*
+ * Return value and success.
+ */
+ *num = n;
+ return (0);
+}
+
+
+/*
+ * Compare name field of record.
+ */
+static int
+nfcmp(char *nf, char *rec)
+{
+ char *cp, tmp;
+ int ret;
+
+ for (cp = rec; *cp != ':'; cp++)
+ ;
+
+ tmp = *(cp + 1);
+ *(cp + 1) = '\0';
+ ret = strcmp(nf, rec);
+ *(cp + 1) = tmp;
+
+ return (ret);
+}
diff --git a/lib/roken/getcwd.c b/lib/roken/getcwd.c
new file mode 100644
index 0000000000000..a32149c212941
--- /dev/null
+++ b/lib/roken/getcwd.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getcwd.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "roken.h"
+
+char* ROKEN_LIB_FUNCTION
+getcwd(char *path, size_t size)
+{
+ char xxx[MaxPathLen];
+ char *ret;
+ ret = getwd(xxx);
+ if(ret)
+ strlcpy(path, xxx, size);
+ return ret;
+}
diff --git a/lib/roken/getdtablesize.c b/lib/roken/getdtablesize.c
new file mode 100644
index 0000000000000..a6ef38b2957f1
--- /dev/null
+++ b/lib/roken/getdtablesize.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getdtablesize.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+int ROKEN_LIB_FUNCTION
+getdtablesize(void)
+{
+ int files = -1;
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ files = sysconf(_SC_OPEN_MAX);
+#else /* !defined(HAVE_SYSCONF) */
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ struct rlimit res;
+ if (getrlimit(RLIMIT_NOFILE, &res) == 0)
+ files = res.rlim_cur;
+#else /* !definded(HAVE_GETRLIMIT) */
+#if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_MAXFILES)
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_MAXFILES;
+ len = sizeof(files);
+ sysctl(&mib, 2, &files, sizeof(files), NULL, 0);
+#endif /* defined(HAVE_SYSCTL) */
+#endif /* !definded(HAVE_GETRLIMIT) */
+#endif /* !defined(HAVE_SYSCONF) */
+
+#ifdef OPEN_MAX
+ if (files < 0)
+ files = OPEN_MAX;
+#endif
+
+#ifdef NOFILE
+ if (files < 0)
+ files = NOFILE;
+#endif
+
+ return files;
+}
diff --git a/lib/roken/getegid.c b/lib/roken/getegid.c
new file mode 100644
index 0000000000000..57ea19857388d
--- /dev/null
+++ b/lib/roken/getegid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETEGID
+
+RCSID("$Id: getegid.c 14773 2005-04-12 11:29:18Z lha $");
+
+int ROKEN_LIB_FUNCTION
+getegid(void)
+{
+ return getgid();
+}
+
+#endif
diff --git a/lib/roken/geteuid.c b/lib/roken/geteuid.c
new file mode 100644
index 0000000000000..f2f771ede0739
--- /dev/null
+++ b/lib/roken/geteuid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETEUID
+
+RCSID("$Id: geteuid.c 14773 2005-04-12 11:29:18Z lha $");
+
+int ROKEN_LIB_FUNCTION
+geteuid(void)
+{
+ return getuid();
+}
+
+#endif
diff --git a/lib/roken/getgid.c b/lib/roken/getgid.c
new file mode 100644
index 0000000000000..fbe4f6d1d272c
--- /dev/null
+++ b/lib/roken/getgid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETGID
+
+RCSID("$Id: getgid.c 14773 2005-04-12 11:29:18Z lha $");
+
+int ROKEN_LIB_FUNCTION
+getgid(void)
+{
+ return 17;
+}
+
+#endif
diff --git a/lib/roken/gethostname.c b/lib/roken/gethostname.c
new file mode 100644
index 0000000000000..f291ce2cb77cd
--- /dev/null
+++ b/lib/roken/gethostname.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETHOSTNAME
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+/*
+ * Return the local host's name in "name", up to "namelen" characters.
+ * "name" will be null-terminated if "namelen" is big enough.
+ * The return code is 0 on success, -1 on failure. (The calling
+ * interface is identical to gethostname(2).)
+ */
+
+int ROKEN_LIB_FUNCTION
+gethostname(char *name, int namelen)
+{
+#if defined(HAVE_UNAME)
+ {
+ struct utsname utsname;
+ int ret;
+
+ ret = uname (&utsname);
+ if (ret < 0)
+ return ret;
+ strlcpy (name, utsname.nodename, namelen);
+ return 0;
+ }
+#else
+ strlcpy (name, "some.random.host", namelen);
+ return 0;
+#endif
+}
+
+#endif /* GETHOSTNAME */
diff --git a/lib/roken/getifaddrs.c b/lib/roken/getifaddrs.c
new file mode 100644
index 0000000000000..485c0d6222154
--- /dev/null
+++ b/lib/roken/getifaddrs.c
@@ -0,0 +1,1250 @@
+/*
+ * Copyright (c) 2000 - 2002, 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getifaddrs.c 21745 2007-07-31 16:11:25Z lha $");
+#endif
+#include "roken.h"
+
+#ifdef __osf__
+/* hate */
+struct rtentry;
+struct mbuf;
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif /* HAVE_SYS_SOCKIO_H */
+
+#ifdef HAVE_NETINET_IN6_VAR_H
+#include <netinet/in6_var.h>
+#endif /* HAVE_NETINET_IN6_VAR_H */
+
+#include <ifaddrs.h>
+
+#ifdef __hpux
+#define lifconf if_laddrconf
+#define lifc_len iflc_len
+#define lifc_buf iflc_buf
+#define lifc_req iflc_req
+
+#define lifreq if_laddrreq
+#define lifr_addr iflr_addr
+#define lifr_name iflr_name
+#define lifr_dstaddr iflr_dstaddr
+#define lifr_broadaddr iflr_broadaddr
+#define lifr_flags iflr_flags
+#define lifr_index iflr_index
+#endif
+
+#ifdef AF_NETLINK
+
+/*
+ * The linux - AF_NETLINK version of getifaddrs - from Usagi.
+ * Linux does not return v6 addresses from SIOCGIFCONF.
+ */
+
+/* $USAGI: ifaddrs.c,v 1.18 2002/03/06 01:50:46 yoshfuji Exp $ */
+
+/**************************************************************************
+ * ifaddrs.c
+ * Copyright (C)2000 Hideaki YOSHIFUJI, 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. Neither the name of the author 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <time.h>
+#include <malloc.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h> /* the L2 protocols */
+#include <sys/uio.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#define __set_errno(e) (errno = (e))
+#define __close(fd) (close(fd))
+#undef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr
+#define IFA_NETMASK
+
+/* ====================================================================== */
+struct nlmsg_list{
+ struct nlmsg_list *nlm_next;
+ struct nlmsghdr *nlh;
+ int size;
+ time_t seq;
+};
+
+struct rtmaddr_ifamap {
+ void *address;
+ void *local;
+#ifdef IFA_NETMASK
+ void *netmask;
+#endif
+ void *broadcast;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+ void *anycast;
+#endif
+ int address_len;
+ int local_len;
+#ifdef IFA_NETMASK
+ int netmask_len;
+#endif
+ int broadcast_len;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+ int anycast_len;
+#endif
+};
+
+/* ====================================================================== */
+static size_t
+ifa_sa_len(sa_family_t family, int len)
+{
+ size_t size;
+ switch(family){
+ case AF_INET:
+ size = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ size = sizeof(struct sockaddr_in6);
+ break;
+ case AF_PACKET:
+ size = (size_t)(((struct sockaddr_ll *)NULL)->sll_addr) + len;
+ if (size < sizeof(struct sockaddr_ll))
+ size = sizeof(struct sockaddr_ll);
+ break;
+ default:
+ size = (size_t)(((struct sockaddr *)NULL)->sa_data) + len;
+ if (size < sizeof(struct sockaddr))
+ size = sizeof(struct sockaddr);
+ break;
+ }
+ return size;
+}
+
+static void
+ifa_make_sockaddr(sa_family_t family,
+ struct sockaddr *sa,
+ void *p, size_t len,
+ uint32_t scope, uint32_t scopeid)
+{
+ if (sa == NULL) return;
+ switch(family){
+ case AF_INET:
+ memcpy(&((struct sockaddr_in*)sa)->sin_addr, (char *)p, len);
+ break;
+ case AF_INET6:
+ memcpy(&((struct sockaddr_in6*)sa)->sin6_addr, (char *)p, len);
+ if (IN6_IS_ADDR_LINKLOCAL(p) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(p)){
+ ((struct sockaddr_in6*)sa)->sin6_scope_id = scopeid;
+ }
+ break;
+ case AF_PACKET:
+ memcpy(((struct sockaddr_ll*)sa)->sll_addr, (char *)p, len);
+ ((struct sockaddr_ll*)sa)->sll_halen = len;
+ break;
+ default:
+ memcpy(sa->sa_data, p, len); /*XXX*/
+ break;
+ }
+ sa->sa_family = family;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sa->sa_len = ifa_sa_len(family, len);
+#endif
+}
+
+#ifndef IFA_NETMASK
+static struct sockaddr *
+ifa_make_sockaddr_mask(sa_family_t family,
+ struct sockaddr *sa,
+ uint32_t prefixlen)
+{
+ int i;
+ char *p = NULL, c;
+ uint32_t max_prefixlen = 0;
+
+ if (sa == NULL) return NULL;
+ switch(family){
+ case AF_INET:
+ memset(&((struct sockaddr_in*)sa)->sin_addr, 0, sizeof(((struct sockaddr_in*)sa)->sin_addr));
+ p = (char *)&((struct sockaddr_in*)sa)->sin_addr;
+ max_prefixlen = 32;
+ break;
+ case AF_INET6:
+ memset(&((struct sockaddr_in6*)sa)->sin6_addr, 0, sizeof(((struct sockaddr_in6*)sa)->sin6_addr));
+ p = (char *)&((struct sockaddr_in6*)sa)->sin6_addr;
+#if 0 /* XXX: fill scope-id? */
+ if (IN6_IS_ADDR_LINKLOCAL(p) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(p)){
+ ((struct sockaddr_in6*)sa)->sin6_scope_id = scopeid;
+ }
+#endif
+ max_prefixlen = 128;
+ break;
+ default:
+ return NULL;
+ }
+ sa->sa_family = family;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sa->sa_len = ifa_sa_len(family, len);
+#endif
+ if (p){
+ if (prefixlen > max_prefixlen)
+ prefixlen = max_prefixlen;
+ for (i=0; i<(prefixlen / 8); i++)
+ *p++ = 0xff;
+ c = 0xff;
+ c <<= (8 - (prefixlen % 8));
+ *p = c;
+ }
+ return sa;
+}
+#endif
+
+/* ====================================================================== */
+static int
+nl_sendreq(int sd, int request, int flags, int *seq)
+{
+ char reqbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct rtgenmsg))];
+ struct sockaddr_nl nladdr;
+ struct nlmsghdr *req_hdr;
+ struct rtgenmsg *req_msg;
+ time_t t = time(NULL);
+
+ if (seq) *seq = t;
+ memset(&reqbuf, 0, sizeof(reqbuf));
+ req_hdr = (struct nlmsghdr *)reqbuf;
+ req_msg = (struct rtgenmsg *)NLMSG_DATA(req_hdr);
+ req_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*req_msg));
+ req_hdr->nlmsg_type = request;
+ req_hdr->nlmsg_flags = flags | NLM_F_REQUEST;
+ req_hdr->nlmsg_pid = 0;
+ req_hdr->nlmsg_seq = t;
+ req_msg->rtgen_family = AF_UNSPEC;
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ return (sendto(sd, (void *)req_hdr, req_hdr->nlmsg_len, 0,
+ (struct sockaddr *)&nladdr, sizeof(nladdr)));
+}
+
+static int
+nl_recvmsg(int sd, int request, int seq,
+ void *buf, size_t buflen,
+ int *flags)
+{
+ struct msghdr msg;
+ struct iovec iov = { buf, buflen };
+ struct sockaddr_nl nladdr;
+ int read_len;
+
+ for (;;){
+ msg.msg_name = (void *)&nladdr;
+ msg.msg_namelen = sizeof(nladdr);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+ read_len = recvmsg(sd, &msg, 0);
+ if ((read_len < 0 && errno == EINTR) || (msg.msg_flags & MSG_TRUNC))
+ continue;
+ if (flags) *flags = msg.msg_flags;
+ break;
+ }
+ return read_len;
+}
+
+static int
+nl_getmsg(int sd, int request, int seq,
+ struct nlmsghdr **nlhp,
+ int *done)
+{
+ struct nlmsghdr *nh;
+ size_t bufsize = 65536, lastbufsize = 0;
+ void *buff = NULL;
+ int result = 0, read_size;
+ int msg_flags;
+ pid_t pid = getpid();
+ for (;;){
+ void *newbuff = realloc(buff, bufsize);
+ if (newbuff == NULL || bufsize < lastbufsize) {
+ result = -1;
+ break;
+ }
+ buff = newbuff;
+ result = read_size = nl_recvmsg(sd, request, seq, buff, bufsize, &msg_flags);
+ if (read_size < 0 || (msg_flags & MSG_TRUNC)){
+ lastbufsize = bufsize;
+ bufsize *= 2;
+ continue;
+ }
+ if (read_size == 0) break;
+ nh = (struct nlmsghdr *)buff;
+ for (nh = (struct nlmsghdr *)buff;
+ NLMSG_OK(nh, read_size);
+ nh = (struct nlmsghdr *)NLMSG_NEXT(nh, read_size)){
+ if (nh->nlmsg_pid != pid ||
+ nh->nlmsg_seq != seq)
+ continue;
+ if (nh->nlmsg_type == NLMSG_DONE){
+ (*done)++;
+ break; /* ok */
+ }
+ if (nh->nlmsg_type == NLMSG_ERROR){
+ struct nlmsgerr *nlerr = (struct nlmsgerr *)NLMSG_DATA(nh);
+ result = -1;
+ if (nh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
+ __set_errno(EIO);
+ else
+ __set_errno(-nlerr->error);
+ break;
+ }
+ }
+ break;
+ }
+ if (result < 0)
+ if (buff){
+ int saved_errno = errno;
+ free(buff);
+ __set_errno(saved_errno);
+ }
+ *nlhp = (struct nlmsghdr *)buff;
+ return result;
+}
+
+static int
+nl_getlist(int sd, int seq,
+ int request,
+ struct nlmsg_list **nlm_list,
+ struct nlmsg_list **nlm_end)
+{
+ struct nlmsghdr *nlh = NULL;
+ int status;
+ int done = 0;
+ int tries = 3;
+
+ try_again:
+ status = nl_sendreq(sd, request, NLM_F_ROOT|NLM_F_MATCH, &seq);
+ if (status < 0)
+ return status;
+ if (seq == 0)
+ seq = (int)time(NULL);
+ while(!done){
+ struct pollfd pfd;
+
+ pfd.fd = sd;
+ pfd.events = POLLIN | POLLPRI;
+ pfd.revents = 0;
+ status = poll(&pfd, 1, 1000);
+ if (status < 0)
+ return status;
+ else if (status == 0) {
+ seq++;
+ if (tries-- > 0)
+ goto try_again;
+ return -1;
+ }
+
+ status = nl_getmsg(sd, request, seq, &nlh, &done);
+ if (status < 0)
+ return status;
+ if (nlh){
+ struct nlmsg_list *nlm_next = (struct nlmsg_list *)malloc(sizeof(struct nlmsg_list));
+ if (nlm_next == NULL){
+ int saved_errno = errno;
+ free(nlh);
+ __set_errno(saved_errno);
+ status = -1;
+ } else {
+ nlm_next->nlm_next = NULL;
+ nlm_next->nlh = (struct nlmsghdr *)nlh;
+ nlm_next->size = status;
+ nlm_next->seq = seq;
+ if (*nlm_list == NULL){
+ *nlm_list = nlm_next;
+ *nlm_end = nlm_next;
+ } else {
+ (*nlm_end)->nlm_next = nlm_next;
+ *nlm_end = nlm_next;
+ }
+ }
+ }
+ }
+ return status >= 0 ? seq : status;
+}
+
+/* ---------------------------------------------------------------------- */
+static void
+free_nlmsglist(struct nlmsg_list *nlm0)
+{
+ struct nlmsg_list *nlm, *nlm_next;
+ int saved_errno;
+ if (!nlm0)
+ return;
+ saved_errno = errno;
+ for (nlm=nlm0; nlm; nlm=nlm_next){
+ if (nlm->nlh)
+ free(nlm->nlh);
+ nlm_next=nlm->nlm_next;
+ free(nlm);
+ }
+ __set_errno(saved_errno);
+}
+
+static void
+free_data(void *data, void *ifdata)
+{
+ int saved_errno = errno;
+ if (data != NULL) free(data);
+ if (ifdata != NULL) free(ifdata);
+ __set_errno(saved_errno);
+}
+
+/* ---------------------------------------------------------------------- */
+static void
+nl_close(int sd)
+{
+ int saved_errno = errno;
+ if (sd >= 0) __close(sd);
+ __set_errno(saved_errno);
+}
+
+/* ---------------------------------------------------------------------- */
+static int
+nl_open(void)
+{
+ struct sockaddr_nl nladdr;
+ int sd;
+
+ sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (sd < 0) return -1;
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ if (bind(sd, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0){
+ nl_close(sd);
+ return -1;
+ }
+ return sd;
+}
+
+/* ====================================================================== */
+int ROKEN_LIB_FUNCTION
+rk_getifaddrs(struct ifaddrs **ifap)
+{
+ int sd;
+ struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
+ /* - - - - - - - - - - - - - - - */
+ int icnt;
+ size_t dlen, xlen, nlen;
+ uint32_t max_ifindex = 0;
+
+ pid_t pid = getpid();
+ int seq;
+ int result;
+ int build ; /* 0 or 1 */
+
+/* ---------------------------------- */
+ /* initialize */
+ icnt = dlen = xlen = nlen = 0;
+ nlmsg_list = nlmsg_end = NULL;
+
+ if (ifap)
+ *ifap = NULL;
+
+/* ---------------------------------- */
+ /* open socket and bind */
+ sd = nl_open();
+ if (sd < 0)
+ return -1;
+
+/* ---------------------------------- */
+ /* gather info */
+ if ((seq = nl_getlist(sd, 0, RTM_GETLINK,
+ &nlmsg_list, &nlmsg_end)) < 0){
+ free_nlmsglist(nlmsg_list);
+ nl_close(sd);
+ return -1;
+ }
+ if ((seq = nl_getlist(sd, seq+1, RTM_GETADDR,
+ &nlmsg_list, &nlmsg_end)) < 0){
+ free_nlmsglist(nlmsg_list);
+ nl_close(sd);
+ return -1;
+ }
+
+/* ---------------------------------- */
+ /* Estimate size of result buffer and fill it */
+ for (build=0; build<=1; build++){
+ struct ifaddrs *ifl = NULL, *ifa = NULL;
+ struct nlmsghdr *nlh, *nlh0;
+ char *data = NULL, *xdata = NULL;
+ void *ifdata = NULL;
+ char *ifname = NULL, **iflist = NULL;
+ uint16_t *ifflist = NULL;
+ struct rtmaddr_ifamap ifamap;
+
+ if (build){
+ data = calloc(1,
+ NLMSG_ALIGN(sizeof(struct ifaddrs[icnt]))
+ + dlen + xlen + nlen);
+ ifa = (struct ifaddrs *)data;
+ ifdata = calloc(1,
+ NLMSG_ALIGN(sizeof(char *[max_ifindex+1]))
+ + NLMSG_ALIGN(sizeof(uint16_t [max_ifindex+1])));
+ if (ifap != NULL)
+ *ifap = (ifdata != NULL) ? ifa : NULL;
+ else{
+ free_data(data, ifdata);
+ result = 0;
+ break;
+ }
+ if (data == NULL || ifdata == NULL){
+ free_data(data, ifdata);
+ result = -1;
+ break;
+ }
+ ifl = NULL;
+ data += NLMSG_ALIGN(sizeof(struct ifaddrs)) * icnt;
+ xdata = data + dlen;
+ ifname = xdata + xlen;
+ iflist = ifdata;
+ ifflist = (uint16_t *)(((char *)iflist) + NLMSG_ALIGN(sizeof(char *[max_ifindex+1])));
+ }
+
+ for (nlm=nlmsg_list; nlm; nlm=nlm->nlm_next){
+ int nlmlen = nlm->size;
+ if (!(nlh0 = nlm->nlh))
+ continue;
+ for (nlh = nlh0;
+ NLMSG_OK(nlh, nlmlen);
+ nlh=NLMSG_NEXT(nlh,nlmlen)){
+ struct ifinfomsg *ifim = NULL;
+ struct ifaddrmsg *ifam = NULL;
+ struct rtattr *rta;
+
+ size_t nlm_struct_size = 0;
+ sa_family_t nlm_family = 0;
+ uint32_t nlm_scope = 0, nlm_index = 0;
+ size_t sockaddr_size = 0;
+ uint32_t nlm_prefixlen = 0;
+ size_t rtasize;
+
+ memset(&ifamap, 0, sizeof(ifamap));
+
+ /* check if the message is what we want */
+ if (nlh->nlmsg_pid != pid ||
+ nlh->nlmsg_seq != nlm->seq)
+ continue;
+ if (nlh->nlmsg_type == NLMSG_DONE){
+ break; /* ok */
+ }
+ switch (nlh->nlmsg_type){
+ case RTM_NEWLINK:
+ ifim = (struct ifinfomsg *)NLMSG_DATA(nlh);
+ nlm_struct_size = sizeof(*ifim);
+ nlm_family = ifim->ifi_family;
+ nlm_scope = 0;
+ nlm_index = ifim->ifi_index;
+ nlm_prefixlen = 0;
+ if (build)
+ ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags;
+ break;
+ case RTM_NEWADDR:
+ ifam = (struct ifaddrmsg *)NLMSG_DATA(nlh);
+ nlm_struct_size = sizeof(*ifam);
+ nlm_family = ifam->ifa_family;
+ nlm_scope = ifam->ifa_scope;
+ nlm_index = ifam->ifa_index;
+ nlm_prefixlen = ifam->ifa_prefixlen;
+ if (build)
+ ifa->ifa_flags = ifflist[nlm_index];
+ break;
+ default:
+ continue;
+ }
+
+ if (!build){
+ if (max_ifindex < nlm_index)
+ max_ifindex = nlm_index;
+ } else {
+ if (ifl != NULL)
+ ifl->ifa_next = ifa;
+ }
+
+ rtasize = NLMSG_PAYLOAD(nlh, nlmlen) - NLMSG_ALIGN(nlm_struct_size);
+ for (rta = (struct rtattr *)(((char *)NLMSG_DATA(nlh)) + NLMSG_ALIGN(nlm_struct_size));
+ RTA_OK(rta, rtasize);
+ rta = RTA_NEXT(rta, rtasize)){
+ struct sockaddr **sap = NULL;
+ void *rtadata = RTA_DATA(rta);
+ size_t rtapayload = RTA_PAYLOAD(rta);
+ socklen_t sa_len;
+
+ switch(nlh->nlmsg_type){
+ case RTM_NEWLINK:
+ switch(rta->rta_type){
+ case IFLA_ADDRESS:
+ case IFLA_BROADCAST:
+ if (build){
+ sap = (rta->rta_type == IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa->ifa_broadaddr;
+ *sap = (struct sockaddr *)data;
+ }
+ sa_len = ifa_sa_len(AF_PACKET, rtapayload);
+ if (rta->rta_type == IFLA_ADDRESS)
+ sockaddr_size = NLMSG_ALIGN(sa_len);
+ if (!build){
+ dlen += NLMSG_ALIGN(sa_len);
+ } else {
+ memset(*sap, 0, sa_len);
+ ifa_make_sockaddr(AF_PACKET, *sap, rtadata,rtapayload, 0,0);
+ ((struct sockaddr_ll *)*sap)->sll_ifindex = nlm_index;
+ ((struct sockaddr_ll *)*sap)->sll_hatype = ifim->ifi_type;
+ data += NLMSG_ALIGN(sa_len);
+ }
+ break;
+ case IFLA_IFNAME:/* Name of Interface */
+ if (!build)
+ nlen += NLMSG_ALIGN(rtapayload + 1);
+ else{
+ ifa->ifa_name = ifname;
+ if (iflist[nlm_index] == NULL)
+ iflist[nlm_index] = ifa->ifa_name;
+ strncpy(ifa->ifa_name, rtadata, rtapayload);
+ ifa->ifa_name[rtapayload] = '\0';
+ ifname += NLMSG_ALIGN(rtapayload + 1);
+ }
+ break;
+ case IFLA_STATS:/* Statistics of Interface */
+ if (!build)
+ xlen += NLMSG_ALIGN(rtapayload);
+ else{
+ ifa->ifa_data = xdata;
+ memcpy(ifa->ifa_data, rtadata, rtapayload);
+ xdata += NLMSG_ALIGN(rtapayload);
+ }
+ break;
+ case IFLA_UNSPEC:
+ break;
+ case IFLA_MTU:
+ break;
+ case IFLA_LINK:
+ break;
+ case IFLA_QDISC:
+ break;
+ default:
+ break;
+ }
+ break;
+ case RTM_NEWADDR:
+ if (nlm_family == AF_PACKET) break;
+ switch(rta->rta_type){
+ case IFA_ADDRESS:
+ ifamap.address = rtadata;
+ ifamap.address_len = rtapayload;
+ break;
+ case IFA_LOCAL:
+ ifamap.local = rtadata;
+ ifamap.local_len = rtapayload;
+ break;
+ case IFA_BROADCAST:
+ ifamap.broadcast = rtadata;
+ ifamap.broadcast_len = rtapayload;
+ break;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+ case IFA_ANYCAST:
+ ifamap.anycast = rtadata;
+ ifamap.anycast_len = rtapayload;
+ break;
+#endif
+ case IFA_LABEL:
+ if (!build)
+ nlen += NLMSG_ALIGN(rtapayload + 1);
+ else{
+ ifa->ifa_name = ifname;
+ if (iflist[nlm_index] == NULL)
+ iflist[nlm_index] = ifname;
+ strncpy(ifa->ifa_name, rtadata, rtapayload);
+ ifa->ifa_name[rtapayload] = '\0';
+ ifname += NLMSG_ALIGN(rtapayload + 1);
+ }
+ break;
+ case IFA_UNSPEC:
+ break;
+ case IFA_CACHEINFO:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (nlh->nlmsg_type == RTM_NEWADDR &&
+ nlm_family != AF_PACKET) {
+ if (!ifamap.local) {
+ ifamap.local = ifamap.address;
+ ifamap.local_len = ifamap.address_len;
+ }
+ if (!ifamap.address) {
+ ifamap.address = ifamap.local;
+ ifamap.address_len = ifamap.local_len;
+ }
+ if (ifamap.address_len != ifamap.local_len ||
+ (ifamap.address != NULL &&
+ memcmp(ifamap.address, ifamap.local, ifamap.address_len))) {
+ /* p2p; address is peer and local is ours */
+ ifamap.broadcast = ifamap.address;
+ ifamap.broadcast_len = ifamap.address_len;
+ ifamap.address = ifamap.local;
+ ifamap.address_len = ifamap.local_len;
+ }
+ if (ifamap.address) {
+#ifndef IFA_NETMASK
+ sockaddr_size = NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
+#endif
+ if (!build)
+ dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
+ else {
+ ifa->ifa_addr = (struct sockaddr *)data;
+ ifa_make_sockaddr(nlm_family, ifa->ifa_addr, ifamap.address, ifamap.address_len,
+ nlm_scope, nlm_index);
+ data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.address_len));
+ }
+ }
+#ifdef IFA_NETMASK
+ if (ifamap.netmask) {
+ if (!build)
+ dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.netmask_len));
+ else {
+ ifa->ifa_netmask = (struct sockaddr *)data;
+ ifa_make_sockaddr(nlm_family, ifa->ifa_netmask, ifamap.netmask, ifamap.netmask_len,
+ nlm_scope, nlm_index);
+ data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.netmask_len));
+ }
+ }
+#endif
+ if (ifamap.broadcast) {
+ if (!build)
+ dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.broadcast_len));
+ else {
+ ifa->ifa_broadaddr = (struct sockaddr *)data;
+ ifa_make_sockaddr(nlm_family, ifa->ifa_broadaddr, ifamap.broadcast, ifamap.broadcast_len,
+ nlm_scope, nlm_index);
+ data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.broadcast_len));
+ }
+ }
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+ if (ifamap.anycast) {
+ if (!build)
+ dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.anycast_len));
+ else {
+ ifa->ifa_anycast = (struct sockaddr *)data;
+ ifa_make_sockaddr(nlm_family, ifa->ifa_anyaddr, ifamap.anycast, ifamap.anycast_len,
+ nlm_scope, nlm_index);
+ data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.anycast_len));
+ }
+ }
+#endif
+ }
+ if (!build){
+#ifndef IFA_NETMASK
+ dlen += sockaddr_size;
+#endif
+ icnt++;
+ } else {
+ if (ifa->ifa_name == NULL)
+ ifa->ifa_name = iflist[nlm_index];
+#ifndef IFA_NETMASK
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family != AF_UNSPEC &&
+ ifa->ifa_addr->sa_family != AF_PACKET){
+ ifa->ifa_netmask = (struct sockaddr *)data;
+ ifa_make_sockaddr_mask(ifa->ifa_addr->sa_family, ifa->ifa_netmask, nlm_prefixlen);
+ }
+ data += sockaddr_size;
+#endif
+ ifl = ifa++;
+ }
+ }
+ }
+ if (!build){
+ if (icnt == 0 && (dlen + nlen + xlen == 0)){
+ if (ifap != NULL)
+ *ifap = NULL;
+ break; /* cannot found any addresses */
+ }
+ }
+ else
+ free_data(NULL, ifdata);
+ }
+
+/* ---------------------------------- */
+ /* Finalize */
+ free_nlmsglist(nlmsg_list);
+ nl_close(sd);
+ return 0;
+}
+
+#else /* !AF_NETLINK */
+
+/*
+ * The generic SIOCGIFCONF version.
+ */
+
+static int
+getifaddrs2(struct ifaddrs **ifap,
+ int af, int siocgifconf, int siocgifflags,
+ size_t ifreq_sz)
+{
+ int ret;
+ int fd;
+ size_t buf_size;
+ char *buf;
+ struct ifconf ifconf;
+ char *p;
+ size_t sz;
+ struct sockaddr sa_zero;
+ struct ifreq *ifr;
+ struct ifaddrs *start = NULL, **end = &start;
+
+ buf = NULL;
+
+ memset (&sa_zero, 0, sizeof(sa_zero));
+ fd = socket(af, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return -1;
+
+ buf_size = 8192;
+ for (;;) {
+ buf = calloc(1, buf_size);
+ if (buf == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ ifconf.ifc_len = buf_size;
+ ifconf.ifc_buf = buf;
+
+ /*
+ * Solaris returns EINVAL when the buffer is too small.
+ */
+ if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
+ ret = errno;
+ goto error_out;
+ }
+ /*
+ * Can the difference between a full and a overfull buf
+ * be determined?
+ */
+
+ if (ifconf.ifc_len < buf_size)
+ break;
+ free (buf);
+ buf_size *= 2;
+ }
+
+ for (p = ifconf.ifc_buf;
+ p < ifconf.ifc_buf + ifconf.ifc_len;
+ p += sz) {
+ struct ifreq ifreq;
+ struct sockaddr *sa;
+ size_t salen;
+
+ ifr = (struct ifreq *)p;
+ sa = &ifr->ifr_addr;
+
+ sz = ifreq_sz;
+ salen = sizeof(struct sockaddr);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ salen = sa->sa_len;
+ sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
+#endif
+#ifdef SA_LEN
+ salen = SA_LEN(sa);
+ sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
+#endif
+ memset (&ifreq, 0, sizeof(ifreq));
+ memcpy (ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
+
+ if (ioctl(fd, siocgifflags, &ifreq) < 0) {
+ ret = errno;
+ goto error_out;
+ }
+
+ *end = malloc(sizeof(**end));
+ if (*end == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+
+ (*end)->ifa_next = NULL;
+ (*end)->ifa_name = strdup(ifr->ifr_name);
+ if ((*end)->ifa_name == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ (*end)->ifa_flags = ifreq.ifr_flags;
+ (*end)->ifa_addr = malloc(salen);
+ if ((*end)->ifa_addr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_addr, sa, salen);
+ (*end)->ifa_netmask = NULL;
+
+#if 0
+ /* fix these when we actually need them */
+ if(ifreq.ifr_flags & IFF_BROADCAST) {
+ (*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
+ if ((*end)->ifa_broadaddr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
+ sizeof(ifr->ifr_broadaddr));
+ } else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
+ (*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
+ if ((*end)->ifa_dstaddr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
+ sizeof(ifr->ifr_dstaddr));
+ } else
+ (*end)->ifa_dstaddr = NULL;
+#else
+ (*end)->ifa_dstaddr = NULL;
+#endif
+
+ (*end)->ifa_data = NULL;
+
+ end = &(*end)->ifa_next;
+
+ }
+ *ifap = start;
+ close(fd);
+ free(buf);
+ return 0;
+ error_out:
+ rk_freeifaddrs(start);
+ close(fd);
+ free(buf);
+ errno = ret;
+ return -1;
+}
+
+#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
+static int
+getlifaddrs2(struct ifaddrs **ifap,
+ int af, int siocgifconf, int siocgifflags,
+ size_t ifreq_sz)
+{
+ int ret;
+ int fd;
+ size_t buf_size;
+ char *buf;
+ struct lifconf ifconf;
+ char *p;
+ size_t sz;
+ struct sockaddr sa_zero;
+ struct lifreq *ifr;
+ struct ifaddrs *start = NULL, **end = &start;
+
+ buf = NULL;
+
+ memset (&sa_zero, 0, sizeof(sa_zero));
+ fd = socket(af, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return -1;
+
+ buf_size = 8192;
+ for (;;) {
+ buf = calloc(1, buf_size);
+ if (buf == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+#ifndef __hpux
+ ifconf.lifc_family = AF_UNSPEC;
+ ifconf.lifc_flags = 0;
+#endif
+ ifconf.lifc_len = buf_size;
+ ifconf.lifc_buf = buf;
+
+ /*
+ * Solaris returns EINVAL when the buffer is too small.
+ */
+ if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
+ ret = errno;
+ goto error_out;
+ }
+ /*
+ * Can the difference between a full and a overfull buf
+ * be determined?
+ */
+
+ if (ifconf.lifc_len < buf_size)
+ break;
+ free (buf);
+ buf_size *= 2;
+ }
+
+ for (p = ifconf.lifc_buf;
+ p < ifconf.lifc_buf + ifconf.lifc_len;
+ p += sz) {
+ struct lifreq ifreq;
+ struct sockaddr_storage *sa;
+ size_t salen;
+
+ ifr = (struct lifreq *)p;
+ sa = &ifr->lifr_addr;
+
+ sz = ifreq_sz;
+ salen = sizeof(struct sockaddr_storage);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ salen = sa->sa_len;
+ sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
+#endif
+#ifdef SA_LEN
+ salen = SA_LEN(sa);
+ sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
+#endif
+ memset (&ifreq, 0, sizeof(ifreq));
+ memcpy (ifreq.lifr_name, ifr->lifr_name, sizeof(ifr->lifr_name));
+
+ if (ioctl(fd, siocgifflags, &ifreq) < 0) {
+ ret = errno;
+ goto error_out;
+ }
+
+ *end = malloc(sizeof(**end));
+ if (*end == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+
+ (*end)->ifa_next = NULL;
+ (*end)->ifa_name = strdup(ifr->lifr_name);
+ if ((*end)->ifa_name == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ (*end)->ifa_flags = ifreq.lifr_flags;
+ (*end)->ifa_addr = malloc(salen);
+ if ((*end)->ifa_addr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_addr, sa, salen);
+ (*end)->ifa_netmask = NULL;
+
+#if 0
+ /* fix these when we actually need them */
+ if(ifreq.ifr_flags & IFF_BROADCAST) {
+ (*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
+ if ((*end)->ifa_broadaddr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
+ sizeof(ifr->ifr_broadaddr));
+ } else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
+ (*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
+ if ((*end)->ifa_dstaddr == NULL) {
+ ret = ENOMEM;
+ goto error_out;
+ }
+ memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
+ sizeof(ifr->ifr_dstaddr));
+ } else
+ (*end)->ifa_dstaddr = NULL;
+#else
+ (*end)->ifa_dstaddr = NULL;
+#endif
+
+ (*end)->ifa_data = NULL;
+
+ end = &(*end)->ifa_next;
+
+ }
+ *ifap = start;
+ close(fd);
+ free(buf);
+ return 0;
+ error_out:
+ rk_freeifaddrs(start);
+ close(fd);
+ free(buf);
+ errno = ret;
+ return -1;
+}
+#endif /* defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS) */
+
+int ROKEN_LIB_FUNCTION
+rk_getifaddrs(struct ifaddrs **ifap)
+{
+ int ret = -1;
+ errno = ENXIO;
+#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
+ if (ret)
+ ret = getifaddrs2 (ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
+ sizeof(struct in6_ifreq));
+#endif
+#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
+ if (ret)
+ ret = getlifaddrs2 (ifap, AF_INET6, SIOCGLIFCONF, SIOCGLIFFLAGS,
+ sizeof(struct lifreq));
+#endif
+#if defined(HAVE_IPV6) && defined(SIOCGIFCONF)
+ if (ret)
+ ret = getifaddrs2 (ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
+ sizeof(struct ifreq));
+#endif
+#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
+ if (ret)
+ ret = getifaddrs2 (ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
+ sizeof(struct ifreq));
+#endif
+ return ret;
+}
+
+#endif /* !AF_NETLINK */
+
+void ROKEN_LIB_FUNCTION
+rk_freeifaddrs(struct ifaddrs *ifp)
+{
+ struct ifaddrs *p, *q;
+
+ for(p = ifp; p; ) {
+ free(p->ifa_name);
+ if(p->ifa_addr)
+ free(p->ifa_addr);
+ if(p->ifa_dstaddr)
+ free(p->ifa_dstaddr);
+ if(p->ifa_netmask)
+ free(p->ifa_netmask);
+ if(p->ifa_data)
+ free(p->ifa_data);
+ q = p;
+ p = p->ifa_next;
+ free(q);
+ }
+}
+
+#ifdef TEST
+
+void
+print_addr(const char *s, struct sockaddr *sa)
+{
+ int i;
+ printf(" %s=%d/", s, sa->sa_family);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ for(i = 0; i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
+ printf("%02x", ((unsigned char*)sa->sa_data)[i]);
+#else
+ for(i = 0; i < sizeof(sa->sa_data); i++)
+ printf("%02x", ((unsigned char*)sa->sa_data)[i]);
+#endif
+ printf("\n");
+}
+
+void
+print_ifaddrs(struct ifaddrs *x)
+{
+ struct ifaddrs *p;
+
+ for(p = x; p; p = p->ifa_next) {
+ printf("%s\n", p->ifa_name);
+ printf(" flags=%x\n", p->ifa_flags);
+ if(p->ifa_addr)
+ print_addr("addr", p->ifa_addr);
+ if(p->ifa_dstaddr)
+ print_addr("dstaddr", p->ifa_dstaddr);
+ if(p->ifa_netmask)
+ print_addr("netmask", p->ifa_netmask);
+ printf(" %p\n", p->ifa_data);
+ }
+}
+
+int
+main()
+{
+ struct ifaddrs *a = NULL, *b;
+ getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq));
+ print_ifaddrs(a);
+ printf("---\n");
+ getifaddrs(&b);
+ print_ifaddrs(b);
+ return 0;
+}
+#endif
diff --git a/lib/roken/getipnodebyaddr.c b/lib/roken/getipnodebyaddr.c
new file mode 100644
index 0000000000000..56ae860aff152
--- /dev/null
+++ b/lib/roken/getipnodebyaddr.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getipnodebyaddr.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * lookup `src, len' (address family `af') in DNS and return a pointer
+ * to a malloced struct hostent or NULL.
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyaddr (const void *src, size_t len, int af, int *error_num)
+{
+ struct hostent *tmp;
+
+ tmp = gethostbyaddr (src, len, af);
+ if (tmp == NULL) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND :
+ case TRY_AGAIN :
+ case NO_RECOVERY :
+ *error_num = h_errno;
+ break;
+ case NO_DATA :
+ *error_num = NO_ADDRESS;
+ break;
+ default :
+ *error_num = NO_RECOVERY;
+ break;
+ }
+ return NULL;
+ }
+ tmp = copyhostent (tmp);
+ if (tmp == NULL) {
+ *error_num = TRY_AGAIN;
+ return NULL;
+ }
+ return tmp;
+}
diff --git a/lib/roken/getipnodebyname.c b/lib/roken/getipnodebyname.c
new file mode 100644
index 0000000000000..739b329e21a2c
--- /dev/null
+++ b/lib/roken/getipnodebyname.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getipnodebyname.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE_H_ERRNO
+static int h_errno = NO_RECOVERY;
+#endif
+
+/*
+ * lookup `name' (address family `af') in DNS and return a pointer
+ * to a malloced struct hostent or NULL.
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyname (const char *name, int af, int flags, int *error_num)
+{
+ struct hostent *tmp;
+
+#ifdef HAVE_GETHOSTBYNAME2
+ tmp = gethostbyname2 (name, af);
+#else
+ if (af != AF_INET) {
+ *error_num = NO_ADDRESS;
+ return NULL;
+ }
+ tmp = gethostbyname (name);
+#endif
+ if (tmp == NULL) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND :
+ case TRY_AGAIN :
+ case NO_RECOVERY :
+ *error_num = h_errno;
+ break;
+ case NO_DATA :
+ *error_num = NO_ADDRESS;
+ break;
+ default :
+ *error_num = NO_RECOVERY;
+ break;
+ }
+ return NULL;
+ }
+ tmp = copyhostent (tmp);
+ if (tmp == NULL) {
+ *error_num = TRY_AGAIN;
+ return NULL;
+ }
+ return tmp;
+}
diff --git a/lib/roken/getnameinfo.c b/lib/roken/getnameinfo.c
new file mode 100644
index 0000000000000..4f820f0a74a0e
--- /dev/null
+++ b/lib/roken/getnameinfo.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getnameinfo.c 15412 2005-06-16 16:53:09Z lha $");
+#endif
+
+#include "roken.h"
+
+static int
+doit (int af,
+ const void *addr,
+ size_t addrlen,
+ int port,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags)
+{
+ if (host != NULL) {
+ if (flags & NI_NUMERICHOST) {
+ if (inet_ntop (af, addr, host, hostlen) == NULL)
+ return EAI_SYSTEM;
+ } else {
+ struct hostent *he = gethostbyaddr (addr,
+ addrlen,
+ af);
+ if (he != NULL) {
+ strlcpy (host, hostent_find_fqdn(he), hostlen);
+ if (flags & NI_NOFQDN) {
+ char *dot = strchr (host, '.');
+ if (dot != NULL)
+ *dot = '\0';
+ }
+ } else if (flags & NI_NAMEREQD) {
+ return EAI_NONAME;
+ } else if (inet_ntop (af, addr, host, hostlen) == NULL)
+ return EAI_SYSTEM;
+ }
+ }
+
+ if (serv != NULL) {
+ if (flags & NI_NUMERICSERV) {
+ snprintf (serv, servlen, "%u", ntohs(port));
+ } else {
+ const char *proto = "tcp";
+ struct servent *se;
+
+ if (flags & NI_DGRAM)
+ proto = "udp";
+
+ se = getservbyport (port, proto);
+ if (se == NULL) {
+ snprintf (serv, servlen, "%u", ntohs(port));
+ } else {
+ strlcpy (serv, se->s_name, servlen);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+
+int ROKEN_LIB_FUNCTION
+getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags)
+{
+ switch (sa->sa_family) {
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+
+ return doit (AF_INET6, &sin6->sin6_addr, sizeof(sin6->sin6_addr),
+ sin6->sin6_port,
+ host, hostlen,
+ serv, servlen,
+ flags);
+ }
+#endif
+ case AF_INET : {
+ const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
+
+ return doit (AF_INET, &sin4->sin_addr, sizeof(sin4->sin_addr),
+ sin4->sin_port,
+ host, hostlen,
+ serv, servlen,
+ flags);
+ }
+ default :
+ return EAI_FAMILY;
+ }
+}
diff --git a/lib/roken/getnameinfo_verified.c b/lib/roken/getnameinfo_verified.c
new file mode 100644
index 0000000000000..91f938a8b22a1
--- /dev/null
+++ b/lib/roken/getnameinfo_verified.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getnameinfo_verified.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Try to obtain a verified name for the address in `sa, salen' (much
+ * similar to getnameinfo).
+ * Verified in this context means that forwards and backwards lookups
+ * in DNS are consistent. If that fails, return an error if the
+ * NI_NAMEREQD flag is set or return the numeric address as a string.
+ */
+
+int ROKEN_LIB_FUNCTION
+getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags)
+{
+ int ret;
+ struct addrinfo *ai, *a;
+ char servbuf[NI_MAXSERV];
+ struct addrinfo hints;
+
+ if (host == NULL)
+ return EAI_NONAME;
+
+ if (serv == NULL) {
+ serv = servbuf;
+ servlen = sizeof(servbuf);
+ }
+
+ ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
+ flags | NI_NUMERICSERV);
+ if (ret)
+ goto fail;
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ ret = getaddrinfo (host, serv, &hints, &ai);
+ if (ret)
+ goto fail;
+ for (a = ai; a != NULL; a = a->ai_next) {
+ if (a->ai_addrlen == salen
+ && memcmp (a->ai_addr, sa, salen) == 0) {
+ freeaddrinfo (ai);
+ return 0;
+ }
+ }
+ freeaddrinfo (ai);
+ fail:
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+ ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
+ flags | NI_NUMERICSERV | NI_NUMERICHOST);
+ return ret;
+}
diff --git a/lib/roken/getopt.c b/lib/roken/getopt.c
new file mode 100644
index 0000000000000..12bf138d0263f
--- /dev/null
+++ b/lib/roken/getopt.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1987, 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. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifndef __STDC__
+#define const
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * get option letter from argument vector
+ */
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+int ROKEN_LIB_FUNCTION
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+ char *p;
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return(-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return(-1);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1 (EOF).
+ */
+ if (optopt == (int)'-')
+ return(-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':') {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ fprintf(stderr, "%s: illegal option -- %c\n",
+ p, optopt);
+ }
+ return(BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ if (*ostr == ':')
+ return(BADARG);
+ if (opterr)
+ fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ p, optopt);
+ return(BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return(optopt); /* dump back option letter */
+}
diff --git a/lib/roken/getprogname.c b/lib/roken/getprogname.c
new file mode 100644
index 0000000000000..6d0bfeec9ba1f
--- /dev/null
+++ b/lib/roken/getprogname.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: getprogname.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE___PROGNAME
+const char *__progname;
+#endif
+
+#ifndef HAVE_GETPROGNAME
+const char * ROKEN_LIB_FUNCTION
+getprogname(void)
+{
+ return __progname;
+}
+#endif /* HAVE_GETPROGNAME */
diff --git a/lib/roken/gettimeofday.c b/lib/roken/gettimeofday.c
new file mode 100644
index 0000000000000..d8e4e750026aa
--- /dev/null
+++ b/lib/roken/gettimeofday.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#ifndef HAVE_GETTIMEOFDAY
+
+RCSID("$Id: gettimeofday.c 14773 2005-04-12 11:29:18Z lha $");
+
+/*
+ * Simple gettimeofday that only returns seconds.
+ */
+int ROKEN_LIB_FUNCTION
+gettimeofday (struct timeval *tp, void *ignore)
+{
+ time_t t;
+
+ t = time(NULL);
+ tp->tv_sec = t;
+ tp->tv_usec = 0;
+ return 0;
+}
+#endif
diff --git a/lib/roken/getuid.c b/lib/roken/getuid.c
new file mode 100644
index 0000000000000..f558ab6815dd0
--- /dev/null
+++ b/lib/roken/getuid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETUID
+
+RCSID("$Id: getuid.c 14773 2005-04-12 11:29:18Z lha $");
+
+int ROKEN_LIB_FUNCTION
+getuid(void)
+{
+ return 17;
+}
+
+#endif
diff --git a/lib/roken/getusershell.c b/lib/roken/getusershell.c
new file mode 100644
index 0000000000000..8def1ca10f8a4
--- /dev/null
+++ b/lib/roken/getusershell.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1985, 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id: getusershell.c 21005 2007-06-08 01:54:35Z lha $");
+
+#ifndef HAVE_GETUSERSHELL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_USERSEC_H
+struct aud_rec;
+#include <usersec.h>
+#endif
+#ifdef HAVE_USERCONF_H
+#include <userconf.h>
+#endif
+#include "roken.h"
+
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef _PATH_CSHELL
+#define _PATH_CSHELL "/bin/csh"
+#endif
+
+/*
+ * Local shells should NOT be added here. They should be added in
+ * /etc/shells.
+ */
+
+static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
+static char **curshell, **shells, *strings;
+static char **initshells (void);
+
+/*
+ * Get a list of shells from _PATH_SHELLS, if it exists.
+ */
+char * ROKEN_LIB_FUNCTION
+getusershell()
+{
+ char *ret;
+
+ if (curshell == NULL)
+ curshell = initshells();
+ ret = *curshell;
+ if (ret != NULL)
+ curshell++;
+ return (ret);
+}
+
+void ROKEN_LIB_FUNCTION
+endusershell()
+{
+ if (shells != NULL)
+ free(shells);
+ shells = NULL;
+ if (strings != NULL)
+ free(strings);
+ strings = NULL;
+ curshell = NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+setusershell()
+{
+ curshell = initshells();
+}
+
+static char **
+initshells()
+{
+ char **sp, *cp;
+#ifdef HAVE_GETCONFATTR
+ char *tmp;
+ int nsh;
+#else
+ FILE *fp;
+#endif
+ struct stat statb;
+
+ free(shells);
+ shells = NULL;
+ free(strings);
+ strings = NULL;
+#ifdef HAVE_GETCONFATTR
+ if(getconfattr(SC_SYS_LOGIN, SC_SHELLS, &tmp, SEC_LIST) != 0)
+ return okshells;
+
+ for(cp = tmp, nsh = 0; *cp; cp += strlen(cp) + 1, nsh++);
+
+ shells = calloc(nsh + 1, sizeof(*shells));
+ if(shells == NULL)
+ return okshells;
+
+ strings = malloc(cp - tmp);
+ if(strings == NULL) {
+ free(shells);
+ shells = NULL;
+ return okshells;
+ }
+ memcpy(strings, tmp, cp - tmp);
+ for(sp = shells, cp = strings; *cp; cp += strlen(cp) + 1, sp++)
+ *sp = cp;
+#else
+ if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
+ return (okshells);
+ if (fstat(fileno(fp), &statb) == -1) {
+ fclose(fp);
+ return (okshells);
+ }
+ if ((strings = malloc((u_int)statb.st_size)) == NULL) {
+ fclose(fp);
+ return (okshells);
+ }
+ shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
+ if (shells == NULL) {
+ fclose(fp);
+ free(strings);
+ strings = NULL;
+ return (okshells);
+ }
+ sp = shells;
+ cp = strings;
+ while (fgets(cp, MaxPathLen + 1, fp) != NULL) {
+ while (*cp != '#' && *cp != '/' && *cp != '\0')
+ cp++;
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ *sp++ = cp;
+ while (!isspace((unsigned char)*cp) && *cp != '#' && *cp != '\0')
+ cp++;
+ *cp++ = '\0';
+ }
+ fclose(fp);
+#endif
+ *sp = NULL;
+ return (shells);
+}
+#endif /* HAVE_GETUSERSHELL */
diff --git a/lib/roken/glob.c b/lib/roken/glob.c
new file mode 100644
index 0000000000000..803eda17d1e79
--- /dev/null
+++ b/lib/roken/glob.c
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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. 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.
+ */
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "glob.h"
+#include "roken.h"
+
+#ifndef ARG_MAX
+#define ARG_MAX _POSIX_ARG_MAX
+#endif
+
+#define CHAR_DOLLAR '$'
+#define CHAR_DOT '.'
+#define CHAR_EOS '\0'
+#define CHAR_LBRACKET '['
+#define CHAR_NOT '!'
+#define CHAR_QUESTION '?'
+#define CHAR_QUOTE '\\'
+#define CHAR_RANGE '-'
+#define CHAR_RBRACKET ']'
+#define CHAR_SEP '/'
+#define CHAR_STAR '*'
+#define CHAR_TILDE '~'
+#define CHAR_UNDERSCORE '_'
+#define CHAR_LBRACE '{'
+#define CHAR_RBRACE '}'
+#define CHAR_SLASH '/'
+#define CHAR_COMMA ','
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef u_short Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_ASCII 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_ASCII))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+
+static int compare (const void *, const void *);
+static void g_Ctoc (const Char *, char *);
+static int g_lstat (Char *, struct stat *, glob_t *);
+static DIR *g_opendir (Char *, glob_t *);
+static Char *g_strchr (const Char *, int);
+#ifdef notdef
+static Char *g_strcat (Char *, const Char *);
+#endif
+static int g_stat (Char *, struct stat *, glob_t *);
+static int glob0 (const Char *, glob_t *);
+static int glob1 (Char *, glob_t *, size_t *);
+static int glob2 (Char *, Char *, Char *, glob_t *, size_t *);
+static int glob3 (Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int globextend (const Char *, glob_t *, size_t *);
+static const Char * globtilde (const Char *, Char *, glob_t *);
+static int globexp1 (const Char *, glob_t *);
+static int globexp2 (const Char *, const Char *, glob_t *, int *);
+static int match (Char *, Char *, Char *);
+#ifdef DEBUG
+static void qprintf (const char *, Char *);
+#endif
+
+int ROKEN_LIB_FUNCTION
+glob(const char *pattern,
+ int flags,
+ int (*errfunc)(const char *, int),
+ glob_t *pglob)
+{
+ const u_char *patnext;
+ int c;
+ Char *bufnext, *bufend, patbuf[MaxPathLen+1];
+
+ patnext = (const u_char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MaxPathLen;
+ if (flags & GLOB_QUOTE) {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != CHAR_EOS)
+ if (c == CHAR_QUOTE) {
+ if ((c = *patnext++) == CHAR_EOS) {
+ c = CHAR_QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ }
+ else
+ *bufnext++ = c;
+ }
+ else
+ while (bufnext < bufend && (c = *patnext++) != CHAR_EOS)
+ *bufnext++ = c;
+ *bufnext = CHAR_EOS;
+
+ if (flags & GLOB_BRACE)
+ return globexp1(patbuf, pglob);
+ else
+ return glob0(patbuf, pglob);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int globexp1(const Char *pattern, glob_t *pglob)
+{
+ const Char* ptr = pattern;
+ int rv;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == CHAR_LBRACE && pattern[1] == CHAR_RBRACE && pattern[2] == CHAR_EOS)
+ return glob0(pattern, pglob);
+
+ while ((ptr = (const Char *) g_strchr(ptr, CHAR_LBRACE)) != NULL)
+ if (!globexp2(ptr, pattern, pglob, &rv))
+ return rv;
+
+ return glob0(pattern, pglob);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int globexp2(const Char *ptr, const Char *pattern,
+ glob_t *pglob, int *rv)
+{
+ int i;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pl;
+ Char patbuf[MaxPathLen + 1];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == CHAR_LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != CHAR_RBRACKET && *pe != CHAR_EOS; pe++)
+ continue;
+ if (*pe == CHAR_EOS) {
+ /*
+ * We could not find a matching CHAR_RBRACKET.
+ * Ignore and just look for CHAR_RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == CHAR_LBRACE)
+ i++;
+ else if (*pe == CHAR_RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == CHAR_EOS) {
+ *rv = glob0(patbuf, pglob);
+ return 0;
+ }
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case CHAR_LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; *pm != CHAR_RBRACKET && *pm != CHAR_EOS; pm++)
+ continue;
+ if (*pm == CHAR_EOS) {
+ /*
+ * We could not find a matching CHAR_RBRACKET.
+ * Ignore and just look for CHAR_RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case CHAR_LBRACE:
+ i++;
+ break;
+
+ case CHAR_RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case CHAR_COMMA:
+ if (i && *pm == CHAR_COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != CHAR_EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ *rv = globexp1(patbuf, pglob);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *rv = 0;
+ return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h;
+ const Char *p;
+ Char *b;
+
+ if (*pattern != CHAR_TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return pattern;
+
+ /* Copy up to the end of the string or / */
+ for (p = pattern + 1, h = (char *) patbuf; *p && *p != CHAR_SLASH;
+ *h++ = *p++)
+ continue;
+
+ *h = CHAR_EOS;
+
+ if (((char *) patbuf)[0] == CHAR_EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if ((h = getenv("HOME")) == NULL) {
+ if ((pwd = k_getpwuid(getuid())) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if ((pwd = k_getpwnam((char*) patbuf)) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; *h; *b++ = *h++)
+ continue;
+
+ /* Append the rest of the pattern */
+ while ((*b++ = *p++) != CHAR_EOS)
+ continue;
+
+ return patbuf;
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob)
+{
+ const Char *qpatnext;
+ int c, err, oldpathc;
+ Char *bufnext, patbuf[MaxPathLen+1];
+ size_t limit = 0;
+
+ qpatnext = globtilde(pattern, patbuf, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != CHAR_EOS) {
+ switch (c) {
+ case CHAR_LBRACKET:
+ c = *qpatnext;
+ if (c == CHAR_NOT)
+ ++qpatnext;
+ if (*qpatnext == CHAR_EOS ||
+ g_strchr(qpatnext+1, CHAR_RBRACKET) == NULL) {
+ *bufnext++ = CHAR_LBRACKET;
+ if (c == CHAR_NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == CHAR_NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == CHAR_RANGE &&
+ (c = qpatnext[1]) != CHAR_RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != CHAR_RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case CHAR_QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case CHAR_STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = CHAR_EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob, &limit)) != 0)
+ return(err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc &&
+ ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR))))
+ return(globextend(pattern, pglob, &limit));
+ else if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ return(0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return(strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob, size_t *limit)
+{
+ Char pathbuf[MaxPathLen+1];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == CHAR_EOS)
+ return(0);
+ return(glob2(pathbuf, pathbuf, pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+
+#ifndef S_ISLNK
+#if defined(S_IFLNK) && defined(S_IFMT)
+#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#else
+#define S_ISLNK(mode) 0
+#endif
+#endif
+
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob,
+ size_t *limit)
+{
+ struct stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == CHAR_EOS) { /* End of pattern? */
+ *pathend = CHAR_EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return(0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != CHAR_SEP) && (S_ISDIR(sb.st_mode)
+ || (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ *pathend++ = CHAR_SEP;
+ *pathend = CHAR_EOS;
+ }
+ ++pglob->gl_matchc;
+ return(globextend(pathbuf, pglob, limit));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != CHAR_EOS && *p != CHAR_SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (*pattern == CHAR_SEP)
+ *pathend++ = *pattern++;
+ } else /* Need expansion, recurse. */
+ return(glob3(pathbuf, pathend, pattern, p, pglob,
+ limit));
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pattern, Char *restpattern,
+ glob_t *pglob, size_t *limit)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[MaxPathLen];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc)(void *);
+
+ *pathend = CHAR_EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (pglob->gl_errfunc) {
+ g_Ctoc(pathbuf, buf);
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return (GLOB_ABEND);
+ }
+ return(0);
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = (struct dirent *(*)(void *))readdir;
+ while ((dp = (*readdirfunc)(dirp))) {
+ u_char *sc;
+ Char *dc;
+
+ /* Initial CHAR_DOT must be matched literally. */
+ if (dp->d_name[0] == CHAR_DOT && *pattern != CHAR_DOT)
+ continue;
+ for (sc = (u_char *) dp->d_name, dc = pathend;
+ (*dc++ = *sc++) != CHAR_EOS;)
+ continue;
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = CHAR_EOS;
+ continue;
+ }
+ err = glob2(pathbuf, --dc, restpattern, pglob, limit);
+ if (err)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ return(err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, size_t *limit)
+{
+ char **pathv;
+ int i;
+ size_t newsize, len;
+ char *copy;
+ const Char *p;
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = pglob->gl_pathv ?
+ realloc(pglob->gl_pathv, newsize) :
+ malloc(newsize);
+ if (pathv == NULL)
+ return(GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ len = (size_t)(p - path);
+ *limit += len;
+ if ((copy = malloc(len)) != NULL) {
+ g_Ctoc(path, copy);
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) {
+ errno = 0;
+ return(GLOB_NOSPACE);
+ }
+
+ return(copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k;
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return(1);
+ do
+ if (match(name, pat, patend))
+ return(1);
+ while (*name++ != CHAR_EOS);
+ return(0);
+ case M_ONE:
+ if (*name++ == CHAR_EOS)
+ return(0);
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == CHAR_EOS)
+ return(0);
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != CHAR_EOS)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (c <= k && k <= pat[1])
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ return(0);
+ break;
+ default:
+ if (*name++ != c)
+ return(0);
+ break;
+ }
+ }
+ return(*name == CHAR_EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void ROKEN_LIB_FUNCTION
+globfree(glob_t *pglob)
+{
+ int i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ if (!*str)
+ strlcpy(buf, ".", sizeof(buf));
+ else
+ g_Ctoc(str, buf);
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_opendir)(buf));
+
+ return(opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_lstat)(buf, sb));
+ return(lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MaxPathLen];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_stat)(buf, sb));
+ return(stat(buf, sb));
+}
+
+static Char *
+g_strchr(const Char *str, int ch)
+{
+ do {
+ if (*str == ch)
+ return (Char *)str;
+ } while (*str++);
+ return (NULL);
+}
+
+#ifdef notdef
+static Char *
+g_strcat(Char *dst, const Char *src)
+{
+ Char *sdst = dst;
+
+ while (*dst++)
+ continue;
+ --dst;
+ while((*dst++ = *src++) != CHAR_EOS)
+ continue;
+
+ return (sdst);
+}
+#endif
+
+static void
+g_Ctoc(const Char *str, char *buf)
+{
+ char *dc;
+
+ for (dc = buf; (*dc++ = *str++) != CHAR_EOS;)
+ continue;
+}
+
+#ifdef DEBUG
+static void
+qprintf(const Char *str, Char *s)
+{
+ Char *p;
+
+ printf("%s:\n", str);
+ for (p = s; *p; p++)
+ printf("%c", CHAR(*p));
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", *p & M_PROTECT ? '"' : ' ');
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", ismeta(*p) ? '_' : ' ');
+ printf("\n");
+}
+#endif
diff --git a/lib/roken/glob.hin b/lib/roken/glob.hin
new file mode 100644
index 0000000000000..ffb6081046fea
--- /dev/null
+++ b/lib/roken/glob.hin
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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. 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.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _GLOB_H_
+#define _GLOB_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define glob_t rk_glob_t
+#define glob rk_glob
+#define globfree rk_globfree
+
+struct stat;
+typedef struct {
+ int gl_pathc; /* Count of total paths so far. */
+ int gl_matchc; /* Count of paths matching pattern. */
+ int gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+ /* Copy of errfunc parameter to glob. */
+ int (*gl_errfunc) (const char *, int);
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir) (void *);
+ struct dirent *(*gl_readdir) (void *);
+ void *(*gl_opendir) (const char *);
+ int (*gl_lstat) (const char *, struct stat *);
+ int (*gl_stat) (const char *, struct stat *);
+} glob_t;
+
+#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_MARK 0x0008 /* Append / to matching directories. */
+#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
+#define GLOB_NOSORT 0x0020 /* Don't sort. */
+
+#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
+#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
+#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
+#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
+#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
+#define GLOB_LIMIT 0x1000 /* Limit memory used by matches to ARG_MAX */
+
+#define GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define GLOB_ABEND (-2) /* Unignored error. */
+
+int ROKEN_LIB_FUNCTION
+glob (const char *, int, int (*)(const char *, int), glob_t *);
+
+void ROKEN_LIB_FUNCTION
+globfree (glob_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_GLOB_H_ */
diff --git a/lib/roken/h_errno.c b/lib/roken/h_errno.c
new file mode 100644
index 0000000000000..11dcb08ac2431
--- /dev/null
+++ b/lib/roken/h_errno.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: h_errno.c 10442 2001-08-08 03:47:23Z assar $");
+#endif
+
+#ifndef HAVE_H_ERRNO
+int h_errno = -17; /* Some magic number */
+#endif
diff --git a/lib/roken/hex-test.c b/lib/roken/hex-test.c
new file mode 100644
index 0000000000000..72aea1ed71350
--- /dev/null
+++ b/lib/roken/hex-test.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999 - 2001, 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+
+RCSID("$Id: hex-test.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include "roken.h"
+#include <hex.h>
+
+int
+main(int argc, char **argv)
+{
+ int numerr = 0;
+ int numtest = 1;
+ struct test {
+ void *data;
+ size_t len;
+ const char *result;
+ } *t, tests[] = {
+ { "", 0 , "" },
+ { "a", 1, "61" },
+ { "ab", 2, "6162" },
+ { "abc", 3, "616263" },
+ { "abcd", 4, "61626364" },
+ { "abcde", 5, "6162636465" },
+ { "abcdef", 6, "616263646566" },
+ { "abcdefg", 7, "61626364656667" },
+ { "=", 1, "3D" },
+ { NULL }
+ };
+ for(t = tests; t->data; t++) {
+ char *str;
+ int len;
+ len = hex_encode(t->data, t->len, &str);
+ if(strcmp(str, t->result) != 0) {
+ fprintf(stderr, "failed test %d: %s != %s\n", numtest,
+ str, t->result);
+ numerr++;
+ }
+ free(str);
+ str = strdup(t->result);
+ len = strlen(str);
+ len = hex_decode(t->result, str, len);
+ if(len != t->len) {
+ fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+ (unsigned long)len, (unsigned long)t->len);
+ numerr++;
+ } else if(memcmp(str, t->data, t->len) != 0) {
+ fprintf(stderr, "failed test %d: data\n", numtest);
+ numerr++;
+ }
+ free(str);
+ numtest++;
+ }
+
+ {
+ unsigned char buf[2] = { 0, 0xff } ;
+ int len;
+
+ len = hex_decode("A", buf, 1);
+ if (len != 1) {
+ fprintf(stderr, "len != 1");
+ numerr++;
+ }
+ if (buf[0] != 10) {
+ fprintf(stderr, "buf != 10");
+ numerr++;
+ }
+ if (buf[1] != 0xff) {
+ fprintf(stderr, "buf != 0xff");
+ numerr++;
+ }
+
+ }
+
+ return numerr;
+}
diff --git a/lib/roken/hex.c b/lib/roken/hex.c
new file mode 100644
index 0000000000000..89fb0e116ef0b
--- /dev/null
+++ b/lib/roken/hex.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: hex.c 16504 2006-01-09 17:09:29Z lha $");
+#endif
+#include "roken.h"
+#include <ctype.h>
+#include "hex.h"
+
+const static char hexchar[] = "0123456789ABCDEF";
+
+static int
+pos(char c)
+{
+ const char *p;
+ c = toupper((unsigned char)c);
+ for (p = hexchar; *p; p++)
+ if (*p == c)
+ return p - hexchar;
+ return -1;
+}
+
+ssize_t ROKEN_LIB_FUNCTION
+hex_encode(const void *data, size_t size, char **str)
+{
+ const unsigned char *q = data;
+ size_t i;
+ char *p;
+
+ /* check for overflow */
+ if (size * 2 < size)
+ return -1;
+
+ p = malloc(size * 2 + 1);
+ if (p == NULL)
+ return -1;
+
+ for (i = 0; i < size; i++) {
+ p[i * 2] = hexchar[(*q >> 4) & 0xf];
+ p[i * 2 + 1] = hexchar[*q & 0xf];
+ q++;
+ }
+ p[i * 2] = '\0';
+ *str = p;
+
+ return i * 2;
+}
+
+ssize_t ROKEN_LIB_FUNCTION
+hex_decode(const char *str, void *data, size_t len)
+{
+ size_t l;
+ unsigned char *p = data;
+ size_t i;
+
+ l = strlen(str);
+
+ /* check for overflow, same as (l+1)/2 but overflow safe */
+ if ((l/2) + (l&1) > len)
+ return -1;
+
+ i = 0;
+ if (l & 1) {
+ p[0] = pos(str[0]);
+ str++;
+ p++;
+ }
+ for (i = 0; i < l / 2; i++)
+ p[i] = pos(str[i * 2]) << 4 | pos(str[(i * 2) + 1]);
+ return i + (l & 1);
+}
diff --git a/lib/roken/hex.h b/lib/roken/hex.h
new file mode 100644
index 0000000000000..4c4b8508ed4dc
--- /dev/null
+++ b/lib/roken/hex.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: hex.h 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef _rk_HEX_H_
+#define _rk_HEX_H_ 1
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#define hex_encode rk_hex_encode
+#define hex_decode rk_hex_decode
+
+ssize_t ROKEN_LIB_FUNCTION
+ hex_encode(const void *, size_t, char **);
+ssize_t ROKEN_LIB_FUNCTION
+ hex_decode(const char *, void *, size_t);
+
+#endif /* _rk_HEX_H_ */
diff --git a/lib/roken/hostent_find_fqdn.c b/lib/roken/hostent_find_fqdn.c
new file mode 100644
index 0000000000000..299ed6d38b462
--- /dev/null
+++ b/lib/roken/hostent_find_fqdn.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: hostent_find_fqdn.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Try to find a fqdn (with `.') in he if possible, else return h_name
+ */
+
+const char * ROKEN_LIB_FUNCTION
+hostent_find_fqdn (const struct hostent *he)
+{
+ const char *ret = he->h_name;
+ const char **h;
+
+ if (strchr (ret, '.') == NULL)
+ for (h = (const char **)he->h_aliases; *h != NULL; ++h) {
+ if (strchr (*h, '.') != NULL) {
+ ret = *h;
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/lib/roken/hstrerror.c b/lib/roken/hstrerror.c
new file mode 100644
index 0000000000000..32dab23f13d33
--- /dev/null
+++ b/lib/roken/hstrerror.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: hstrerror.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifndef HAVE_HSTRERROR
+
+#if (defined(SunOS) && (SunOS >= 50))
+#define hstrerror broken_proto
+#endif
+#include "roken.h"
+#if (defined(SunOS) && (SunOS >= 50))
+#undef hstrerror
+#endif
+
+#if !(defined(HAVE_H_ERRLIST) && defined(HAVE_H_NERR))
+static const char *const h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /* 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /* 2 TRY_AGAIN */
+ "Unknown server error", /* 3 NO_RECOVERY */
+ "No address associated with name", /* 4 NO_ADDRESS */
+};
+
+static
+const
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+#else
+
+#if !HAVE_DECL_H_ERRLIST
+extern const char *h_errlist[];
+extern int h_nerr;
+#endif
+
+#endif
+
+const char * ROKEN_LIB_FUNCTION
+hstrerror(int herr)
+{
+ if (0 <= herr && herr < h_nerr)
+ return h_errlist[herr];
+ else if(herr == -17)
+ return "unknown error";
+ else
+ return "Error number out of range (hstrerror)";
+}
+
+#endif
diff --git a/lib/roken/ifaddrs.hin b/lib/roken/ifaddrs.hin
new file mode 100644
index 0000000000000..0951c8cbc1b21
--- /dev/null
+++ b/lib/roken/ifaddrs.hin
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: ifaddrs.hin 19309 2006-12-11 18:58:15Z lha $ */
+
+#ifndef __ifaddrs_h__
+#define __ifaddrs_h__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+/*
+ * the interface is defined in terms of the fields below, and this is
+ * sometimes #define'd, so there seems to be no simple way of solving
+ * this and this seemed the best. */
+
+#undef ifa_dstaddr
+
+struct ifaddrs {
+ struct ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ struct sockaddr *ifa_addr;
+ struct sockaddr *ifa_netmask;
+ struct sockaddr *ifa_dstaddr;
+ void *ifa_data;
+};
+
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr
+#endif
+
+int ROKEN_LIB_FUNCTION
+rk_getifaddrs(struct ifaddrs**);
+
+void ROKEN_LIB_FUNCTION
+rk_freeifaddrs(struct ifaddrs*);
+
+#define getifaddrs(a) rk_getifaddrs(a)
+#define freeifaddrs(a) rk_freeifaddrs(a)
+
+#endif /* __ifaddrs_h__ */
diff --git a/lib/roken/inet_aton.c b/lib/roken/inet_aton.c
new file mode 100644
index 0000000000000..3010935045f22
--- /dev/null
+++ b/lib/roken/inet_aton.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: inet_aton.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/* Minimal implementation of inet_aton.
+ * Cannot distinguish between failure and a local broadcast address. */
+
+int ROKEN_LIB_FUNCTION
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ addr->s_addr = inet_addr(cp);
+ return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
diff --git a/lib/roken/inet_ntop.c b/lib/roken/inet_ntop.c
new file mode 100644
index 0000000000000..7433c3725e28e
--- /dev/null
+++ b/lib/roken/inet_ntop.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: inet_ntop.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ *
+ */
+
+static const char *
+inet_ntop_v4 (const void *src, char *dst, size_t size)
+{
+ const char digits[] = "0123456789";
+ int i;
+ struct in_addr *addr = (struct in_addr *)src;
+ u_long a = ntohl(addr->s_addr);
+ const char *orig_dst = dst;
+
+ if (size < INET_ADDRSTRLEN) {
+ errno = ENOSPC;
+ return NULL;
+ }
+ for (i = 0; i < 4; ++i) {
+ int n = (a >> (24 - i * 8)) & 0xFF;
+ int non_zerop = 0;
+
+ if (non_zerop || n / 100 > 0) {
+ *dst++ = digits[n / 100];
+ n %= 100;
+ non_zerop = 1;
+ }
+ if (non_zerop || n / 10 > 0) {
+ *dst++ = digits[n / 10];
+ n %= 10;
+ non_zerop = 1;
+ }
+ *dst++ = digits[n];
+ if (i != 3)
+ *dst++ = '.';
+ }
+ *dst++ = '\0';
+ return orig_dst;
+}
+
+#ifdef HAVE_IPV6
+static const char *
+inet_ntop_v6 (const void *src, char *dst, size_t size)
+{
+ const char xdigits[] = "0123456789abcdef";
+ int i;
+ const struct in6_addr *addr = (struct in6_addr *)src;
+ const u_char *ptr = addr->s6_addr;
+ const char *orig_dst = dst;
+
+ if (size < INET6_ADDRSTRLEN) {
+ errno = ENOSPC;
+ return NULL;
+ }
+ for (i = 0; i < 8; ++i) {
+ int non_zerop = 0;
+
+ if (non_zerop || (ptr[0] >> 4)) {
+ *dst++ = xdigits[ptr[0] >> 4];
+ non_zerop = 1;
+ }
+ if (non_zerop || (ptr[0] & 0x0F)) {
+ *dst++ = xdigits[ptr[0] & 0x0F];
+ non_zerop = 1;
+ }
+ if (non_zerop || (ptr[1] >> 4)) {
+ *dst++ = xdigits[ptr[1] >> 4];
+ non_zerop = 1;
+ }
+ *dst++ = xdigits[ptr[1] & 0x0F];
+ if (i != 7)
+ *dst++ = ':';
+ ptr += 2;
+ }
+ *dst++ = '\0';
+ return orig_dst;
+}
+#endif /* HAVE_IPV6 */
+
+const char * ROKEN_LIB_FUNCTION
+inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+ switch (af) {
+ case AF_INET :
+ return inet_ntop_v4 (src, dst, size);
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ return inet_ntop_v6 (src, dst, size);
+#endif
+ default :
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+}
diff --git a/lib/roken/inet_pton.c b/lib/roken/inet_pton.c
new file mode 100644
index 0000000000000..390233a72d015
--- /dev/null
+++ b/lib/roken/inet_pton.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: inet_pton.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+inet_pton(int af, const char *src, void *dst)
+{
+ if (af != AF_INET) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ return inet_aton (src, dst);
+}
diff --git a/lib/roken/initgroups.c b/lib/roken/initgroups.c
new file mode 100644
index 0000000000000..f326e5f1fd2dc
--- /dev/null
+++ b/lib/roken/initgroups.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: initgroups.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+initgroups(const char *name, gid_t basegid)
+{
+ return 0;
+}
diff --git a/lib/roken/innetgr.c b/lib/roken/innetgr.c
new file mode 100644
index 0000000000000..598bad21c2acd
--- /dev/null
+++ b/lib/roken/innetgr.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_INNETGR
+
+RCSID("$Id: innetgr.c 14773 2005-04-12 11:29:18Z lha $");
+
+int ROKEN_LIB_FUNCTION
+innetgr(const char *netgroup, const char *machine,
+ const char *user, const char *domain)
+{
+ return 0;
+}
+#endif
+
diff --git a/lib/roken/install-sh b/lib/roken/install-sh
new file mode 100755
index 0000000000000..e9de23842dcd4
--- /dev/null
+++ b/lib/roken/install-sh
@@ -0,0 +1,251 @@
+#!/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=:
+ chmodcmd=""
+ 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/lib/roken/iruserok.c b/lib/roken/iruserok.c
new file mode 100644
index 0000000000000..ca93e1cc5eb5a
--- /dev/null
+++ b/lib/roken/iruserok.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: iruserok.c 17879 2006-08-08 21:50:40Z lha $");
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_RPCSVC_YPCLNT_H
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include "roken.h"
+
+int __check_rhosts_file = 1;
+char *__rcmd_errstr = 0;
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static
+int
+__icheckhost(unsigned raddr, const char *lhost)
+{
+ struct hostent *hp;
+ u_long laddr;
+ char **pp;
+
+ /* Try for raw ip address first. */
+ if (isdigit((unsigned char)*lhost)
+ && (long)(laddr = inet_addr(lhost)) != -1)
+ return (raddr == laddr);
+
+ /* Better be a hostname. */
+ if ((hp = gethostbyname(lhost)) == NULL)
+ return (0);
+
+ /* Spin through ip addresses. */
+ for (pp = hp->h_addr_list; *pp; ++pp)
+ if (memcmp(&raddr, *pp, sizeof(u_long)) == 0)
+ return (1);
+
+ /* No match. */
+ return (0);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ */
+static
+int
+__ivaliduser(FILE *hostf, unsigned raddr, const char *luser,
+ const char *ruser)
+{
+ char *user, *p;
+ int ch;
+ char buf[MaxHostNameLen + 128]; /* host + login */
+ char hname[MaxHostNameLen];
+ struct hostent *hp;
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+#ifdef HAVE_YP_GET_DEFAULT_DOMAIN
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if ((hp = gethostbyaddr((char *)&raddr,
+ sizeof(u_long),
+ AF_INET)) == NULL)
+ return (-1);
+ strlcpy(hname, hp->h_name, sizeof(hname));
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ if (isupper((unsigned char)*p))
+ *p = tolower((unsigned char)*p);
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr,(char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr,(char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, buf);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, (char *)ruser,
+ ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ (char *)ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int ROKEN_LIB_FUNCTION
+iruserok(unsigned raddr, int superuser, const char *ruser, const char *luser)
+{
+ char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MaxPathLen];
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+ fclose(hostf);
+ return (0);
+ }
+ fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = k_getpwnam((char*)luser)) == NULL)
+ return (-1);
+ snprintf (pbuf, sizeof(pbuf), "%s/.rhosts", pwd->pw_dir);
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ if (seteuid(pwd->pw_uid) < 0)
+ return (-1);
+ hostf = fopen(pbuf, "r");
+ seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
diff --git a/lib/roken/issuid.c b/lib/roken/issuid.c
new file mode 100644
index 0000000000000..46bde77b78547
--- /dev/null
+++ b/lib/roken/issuid.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: issuid.c 15131 2005-05-13 07:42:03Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+issuid(void)
+{
+#if defined(HAVE_ISSETUGID)
+ return issetugid();
+#else /* !HAVE_ISSETUGID */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
+ if(getuid() != geteuid())
+ return 1;
+#endif
+#if defined(HAVE_GETGID) && defined(HAVE_GETEGID)
+ if(getgid() != getegid())
+ return 2;
+#endif
+
+ return 0;
+#endif /* HAVE_ISSETUGID */
+}
diff --git a/lib/roken/k_getpwnam.c b/lib/roken/k_getpwnam.c
new file mode 100644
index 0000000000000..81eba28692068
--- /dev/null
+++ b/lib/roken/k_getpwnam.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: k_getpwnam.c 14773 2005-04-12 11:29:18Z lha $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd * ROKEN_LIB_FUNCTION
+k_getpwnam (const char *user)
+{
+ struct passwd *p;
+
+ p = getpwnam (user);
+#if defined(HAVE_GETSPNAM) && defined(HAVE_STRUCT_SPWD)
+ if(p)
+ {
+ struct spwd *spwd;
+
+ spwd = getspnam (user);
+ if (spwd)
+ p->pw_passwd = spwd->sp_pwdp;
+ endspent ();
+ }
+#else
+ endpwent ();
+#endif
+ return p;
+}
diff --git a/lib/roken/k_getpwuid.c b/lib/roken/k_getpwuid.c
new file mode 100644
index 0000000000000..7fe03b98f8cf9
--- /dev/null
+++ b/lib/roken/k_getpwuid.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: k_getpwuid.c 14773 2005-04-12 11:29:18Z lha $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd * ROKEN_LIB_FUNCTION
+k_getpwuid (uid_t uid)
+{
+ struct passwd *p;
+
+ p = getpwuid (uid);
+#if defined(HAVE_GETSPNAM) && defined(HAVE_STRUCT_SPWD)
+ if (p)
+ {
+ struct spwd *spwd;
+
+ spwd = getspnam (p->pw_name);
+ if (spwd)
+ p->pw_passwd = spwd->sp_pwdp;
+ endspent ();
+ }
+#else
+ endpwent ();
+#endif
+ return p;
+}
diff --git a/lib/roken/localtime_r.c b/lib/roken/localtime_r.c
new file mode 100644
index 0000000000000..ad515c1465668
--- /dev/null
+++ b/lib/roken/localtime_r.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: localtime_r.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include "roken.h"
+
+#ifndef HAVE_LOCALTIME_R
+
+struct tm * ROKEN_LIB_FUNCTION
+localtime_r(const time_t *timer, struct tm *result)
+{
+ struct tm *tm;
+
+ tm = localtime((time_t *)timer);
+ if (tm == NULL)
+ return NULL;
+ *result = *tm;
+ return result;
+}
+
+#endif
diff --git a/lib/roken/lstat.c b/lib/roken/lstat.c
new file mode 100644
index 0000000000000..9357e1234587f
--- /dev/null
+++ b/lib/roken/lstat.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: lstat.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+lstat(const char *path, struct stat *buf)
+{
+ return stat(path, buf);
+}
diff --git a/lib/roken/memmove.c b/lib/roken/memmove.c
new file mode 100644
index 0000000000000..5f78ac293fdde
--- /dev/null
+++ b/lib/roken/memmove.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: memmove.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+/*
+ * memmove for systems that doesn't have it
+ */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+void* ROKEN_LIB_FUNCTION
+memmove(void *s1, const void *s2, size_t n)
+{
+ char *s=(char*)s2, *d=(char*)s1;
+
+ if(d > s){
+ s+=n-1;
+ d+=n-1;
+ while(n){
+ *d--=*s--;
+ n--;
+ }
+ }else if(d < s)
+ while(n){
+ *d++=*s++;
+ n--;
+ }
+ return s1;
+}
diff --git a/lib/roken/mini_inetd.c b/lib/roken/mini_inetd.c
new file mode 100644
index 0000000000000..9eb114d74e7f2
--- /dev/null
+++ b/lib/roken/mini_inetd.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: mini_inetd.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <err.h>
+#include "roken.h"
+
+/*
+ * accept a connection on `s' and pretend it's served by inetd.
+ */
+
+static void
+accept_it (int s)
+{
+ int s2;
+
+ s2 = accept(s, NULL, NULL);
+ if(s2 < 0)
+ err (1, "accept");
+ close(s);
+ dup2(s2, STDIN_FILENO);
+ dup2(s2, STDOUT_FILENO);
+ /* dup2(s2, STDERR_FILENO); */
+ close(s2);
+}
+
+/*
+ * Listen on a specified port, emulating inetd.
+ */
+
+void ROKEN_LIB_FUNCTION
+mini_inetd_addrinfo (struct addrinfo *ai)
+{
+ int ret;
+ struct addrinfo *a;
+ int n, nalloc, i;
+ int *fds;
+ fd_set orig_read_set, read_set;
+ int max_fd = -1;
+
+ for (nalloc = 0, a = ai; a != NULL; a = a->ai_next)
+ ++nalloc;
+
+ fds = malloc (nalloc * sizeof(*fds));
+ if (fds == NULL)
+ errx (1, "mini_inetd: out of memory");
+
+ FD_ZERO(&orig_read_set);
+
+ for (i = 0, a = ai; a != NULL; a = a->ai_next) {
+ fds[i] = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+ if (fds[i] < 0) {
+ warn ("socket af = %d", a->ai_family);
+ continue;
+ }
+ socket_set_reuseaddr (fds[i], 1);
+ if (bind (fds[i], a->ai_addr, a->ai_addrlen) < 0) {
+ warn ("bind af = %d", a->ai_family);
+ close(fds[i]);
+ continue;
+ }
+ if (listen (fds[i], SOMAXCONN) < 0) {
+ warn ("listen af = %d", a->ai_family);
+ close(fds[i]);
+ continue;
+ }
+ if (fds[i] >= FD_SETSIZE)
+ errx (1, "fd too large");
+ FD_SET(fds[i], &orig_read_set);
+ max_fd = max(max_fd, fds[i]);
+ ++i;
+ }
+ if (i == 0)
+ errx (1, "no sockets");
+ n = i;
+
+ do {
+ read_set = orig_read_set;
+
+ ret = select (max_fd + 1, &read_set, NULL, NULL, NULL);
+ if (ret < 0 && errno != EINTR)
+ err (1, "select");
+ } while (ret <= 0);
+
+ for (i = 0; i < n; ++i)
+ if (FD_ISSET (fds[i], &read_set)) {
+ accept_it (fds[i]);
+ return;
+ }
+ abort ();
+}
+
+void ROKEN_LIB_FUNCTION
+mini_inetd (int port)
+{
+ int error;
+ struct addrinfo *ai, hints;
+ char portstr[NI_MAXSERV];
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ snprintf (portstr, sizeof(portstr), "%d", ntohs(port));
+
+ error = getaddrinfo (NULL, portstr, &hints, &ai);
+ if (error)
+ errx (1, "getaddrinfo: %s", gai_strerror (error));
+
+ mini_inetd_addrinfo(ai);
+
+ freeaddrinfo(ai);
+}
diff --git a/lib/roken/missing b/lib/roken/missing
new file mode 100755
index 0000000000000..7789652e877fb
--- /dev/null
+++ b/lib/roken/missing
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program 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, 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.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/lib/roken/mkinstalldirs b/lib/roken/mkinstalldirs
new file mode 100755
index 0000000000000..6b3b5fc5d4d34
--- /dev/null
+++ b/lib/roken/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/lib/roken/mkstemp.c b/lib/roken/mkstemp.c
new file mode 100644
index 0000000000000..ccb2e700b8959
--- /dev/null
+++ b/lib/roken/mkstemp.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+
+RCSID("$Id: mkstemp.c 14773 2005-04-12 11:29:18Z lha $");
+
+#ifndef HAVE_MKSTEMP
+
+int ROKEN_LIB_FUNCTION
+mkstemp(char *template)
+{
+ int start, i;
+ pid_t val;
+ val = getpid();
+ start = strlen(template) - 1;
+ while(template[start] == 'X') {
+ template[start] = '0' + val % 10;
+ val /= 10;
+ start--;
+ }
+
+ do{
+ int fd;
+ fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if(fd >= 0 || errno != EEXIST)
+ return fd;
+ i = start + 1;
+ do{
+ if(template[i] == 0)
+ return -1;
+ template[i]++;
+ if(template[i] == '9' + 1)
+ template[i] = 'a';
+ if(template[i] <= 'z')
+ break;
+ template[i] = 'a';
+ i++;
+ }while(1);
+ }while(1);
+}
+
+#endif
diff --git a/lib/roken/ndbm_wrap.c b/lib/roken/ndbm_wrap.c
new file mode 100644
index 0000000000000..8bc5d93e48fe6
--- /dev/null
+++ b/lib/roken/ndbm_wrap.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: ndbm_wrap.c 21634 2007-07-17 11:30:36Z lha $");
+#endif
+
+#include "ndbm_wrap.h"
+#if defined(HAVE_DB4_DB_H)
+#include <db4/db.h>
+#elif defined(HAVE_DB3_DB_H)
+#include <db3/db.h>
+#else
+#include <db.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+/* XXX undefine open so this works on Solaris with large file support */
+#undef open
+
+#define DBT2DATUM(DBT, DATUM) do { (DATUM)->dptr = (DBT)->data; (DATUM)->dsize = (DBT)->size; } while(0)
+#define DATUM2DBT(DATUM, DBT) do { (DBT)->data = (DATUM)->dptr; (DBT)->size = (DATUM)->dsize; } while(0)
+#define RETURN(X) return ((X) == 0) ? 0 : -1
+
+#ifdef HAVE_DB3
+static DBC *cursor;
+#endif
+
+#define D(X) ((DB*)(X))
+
+void ROKEN_LIB_FUNCTION
+dbm_close (DBM *db)
+{
+#ifdef HAVE_DB3
+ D(db)->close(D(db), 0);
+ cursor = NULL;
+#else
+ D(db)->close(D(db));
+#endif
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_delete (DBM *db, datum dkey)
+{
+ DBT key;
+ DATUM2DBT(&dkey, &key);
+#ifdef HAVE_DB3
+ RETURN(D(db)->del(D(db), NULL, &key, 0));
+#else
+ RETURN(D(db)->del(D(db), &key, 0));
+#endif
+}
+
+datum
+dbm_fetch (DBM *db, datum dkey)
+{
+ datum dvalue;
+ DBT key, value;
+ DATUM2DBT(&dkey, &key);
+ if(D(db)->get(D(db),
+#ifdef HAVE_DB3
+ NULL,
+#endif
+ &key, &value, 0) != 0) {
+ dvalue.dptr = NULL;
+ dvalue.dsize = 0;
+ }
+ else
+ DBT2DATUM(&value, &dvalue);
+
+ return dvalue;
+}
+
+static datum
+dbm_get (DB *db, int flags)
+{
+ DBT key, value;
+ datum datum;
+#ifdef HAVE_DB3
+ if(cursor == NULL)
+ db->cursor(db, NULL, &cursor, 0);
+ if(cursor->c_get(cursor, &key, &value, flags) != 0) {
+ datum.dptr = NULL;
+ datum.dsize = 0;
+ } else
+ DBT2DATUM(&value, &datum);
+#else
+ db->seq(db, &key, &value, flags);
+#endif
+ return datum;
+}
+
+#ifndef DB_FIRST
+#define DB_FIRST R_FIRST
+#define DB_NEXT R_NEXT
+#define DB_NOOVERWRITE R_NOOVERWRITE
+#define DB_KEYEXIST 1
+#endif
+
+datum ROKEN_LIB_FUNCTION
+dbm_firstkey (DBM *db)
+{
+ return dbm_get(D(db), DB_FIRST);
+}
+
+datum ROKEN_LIB_FUNCTION
+dbm_nextkey (DBM *db)
+{
+ return dbm_get(D(db), DB_NEXT);
+}
+
+DBM* ROKEN_LIB_FUNCTION
+dbm_open (const char *file, int flags, mode_t mode)
+{
+ DB *db;
+ int myflags = 0;
+ char *fn = malloc(strlen(file) + 4);
+ if(fn == NULL)
+ return NULL;
+ strcpy(fn, file);
+ strcat(fn, ".db");
+#ifdef HAVE_DB3
+ if (flags & O_CREAT)
+ myflags |= DB_CREATE;
+
+ if (flags & O_EXCL)
+ myflags |= DB_EXCL;
+
+ if (flags & O_RDONLY)
+ myflags |= DB_RDONLY;
+
+ if (flags & O_TRUNC)
+ myflags |= DB_TRUNCATE;
+ if(db_create(&db, NULL, 0) != 0) {
+ free(fn);
+ return NULL;
+ }
+
+#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
+ if(db->open(db, NULL, fn, NULL, DB_BTREE, myflags, mode) != 0) {
+#else
+ if(db->open(db, fn, NULL, DB_BTREE, myflags, mode) != 0) {
+#endif
+ free(fn);
+ db->close(db, 0);
+ return NULL;
+ }
+#else
+ db = dbopen(fn, flags, mode, DB_BTREE, NULL);
+#endif
+ free(fn);
+ return (DBM*)db;
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_store (DBM *db, datum dkey, datum dvalue, int flags)
+{
+ int ret;
+ DBT key, value;
+ int myflags = 0;
+ if((flags & DBM_REPLACE) == 0)
+ myflags |= DB_NOOVERWRITE;
+ DATUM2DBT(&dkey, &key);
+ DATUM2DBT(&dvalue, &value);
+ ret = D(db)->put(D(db),
+#ifdef HAVE_DB3
+ NULL,
+#endif
+&key, &value, myflags);
+ if(ret == DB_KEYEXIST)
+ return 1;
+ RETURN(ret);
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_error (DBM *db)
+{
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_clearerr (DBM *db)
+{
+ return 0;
+}
+
diff --git a/lib/roken/ndbm_wrap.h b/lib/roken/ndbm_wrap.h
new file mode 100644
index 0000000000000..414940249dba8
--- /dev/null
+++ b/lib/roken/ndbm_wrap.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: ndbm_wrap.h 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef __ndbm_wrap_h__
+#define __ndbm_wrap_h__
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifndef dbm_rename
+#define dbm_rename(X) __roken_ ## X
+#endif
+
+#define dbm_open dbm_rename(dbm_open)
+#define dbm_close dbm_rename(dbm_close)
+#define dbm_delete dbm_rename(dbm_delete)
+#define dbm_fetch dbm_rename(dbm_fetch)
+#define dbm_get dbm_rename(dbm_get)
+#define dbm_firstkey dbm_rename(dbm_firstkey)
+#define dbm_nextkey dbm_rename(dbm_nextkey)
+#define dbm_store dbm_rename(dbm_store)
+#define dbm_error dbm_rename(dbm_error)
+#define dbm_clearerr dbm_rename(dbm_clearerr)
+
+#define datum dbm_rename(datum)
+
+typedef struct {
+ void *dptr;
+ size_t dsize;
+} datum;
+
+#define DBM_REPLACE 1
+typedef struct DBM DBM;
+
+#if 0
+typedef struct {
+ int dummy;
+} DBM;
+#endif
+
+int ROKEN_LIB_FUNCTION dbm_clearerr (DBM*);
+void ROKEN_LIB_FUNCTION dbm_close (DBM*);
+int ROKEN_LIB_FUNCTION dbm_delete (DBM*, datum);
+int ROKEN_LIB_FUNCTION dbm_error (DBM*);
+datum ROKEN_LIB_FUNCTION dbm_fetch (DBM*, datum);
+datum ROKEN_LIB_FUNCTION dbm_firstkey (DBM*);
+datum ROKEN_LIB_FUNCTION dbm_nextkey (DBM*);
+DBM* ROKEN_LIB_FUNCTION dbm_open (const char*, int, mode_t);
+int ROKEN_LIB_FUNCTION dbm_store (DBM*, datum, datum, int);
+
+#endif /* __ndbm_wrap_h__ */
diff --git a/lib/roken/net_read.c b/lib/roken/net_read.c
new file mode 100644
index 0000000000000..effc00112b7d6
--- /dev/null
+++ b/lib/roken/net_read.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: net_read.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "roken.h"
+
+/*
+ * Like read but never return partial data.
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+net_read (int fd, void *buf, size_t nbytes)
+{
+ char *cbuf = (char *)buf;
+ ssize_t count;
+ size_t rem = nbytes;
+
+ while (rem > 0) {
+#ifdef WIN32
+ count = recv (fd, cbuf, rem, 0);
+#else
+ count = read (fd, cbuf, rem);
+#endif
+ if (count < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return count;
+ } else if (count == 0) {
+ return count;
+ }
+ cbuf += count;
+ rem -= count;
+ }
+ return nbytes;
+}
diff --git a/lib/roken/net_write.c b/lib/roken/net_write.c
new file mode 100644
index 0000000000000..a68317f61247a
--- /dev/null
+++ b/lib/roken/net_write.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: net_write.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "roken.h"
+
+/*
+ * Like write but never return partial data.
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+net_write (int fd, const void *buf, size_t nbytes)
+{
+ const char *cbuf = (const char *)buf;
+ ssize_t count;
+ size_t rem = nbytes;
+
+ while (rem > 0) {
+#ifdef WIN32
+ count = send (fd, cbuf, rem, 0);
+#else
+ count = write (fd, cbuf, rem);
+#endif
+ if (count < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return count;
+ }
+ cbuf += count;
+ rem -= count;
+ }
+ return nbytes;
+}
diff --git a/lib/roken/parse_bytes-test.c b/lib/roken/parse_bytes-test.c
new file mode 100644
index 0000000000000..5e55b307c1633
--- /dev/null
+++ b/lib/roken/parse_bytes-test.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_bytes-test.c 10655 2001-09-04 09:56:00Z assar $");
+#endif
+
+#include "roken.h"
+#include "parse_bytes.h"
+
+static struct testcase {
+ int canonicalp;
+ int val;
+ const char *def_unit;
+ const char *str;
+} tests[] = {
+ {0, 0, NULL, "0 bytes"},
+ {1, 0, NULL, "0"},
+ {0, 1, NULL, "1"},
+ {1, 1, NULL, "1 byte"},
+ {0, 0, "kilobyte", "0"},
+ {0, 1024, "kilobyte", "1"},
+ {1, 1024, "kilobyte", "1 kilobyte"},
+ {1, 1024 * 1024, NULL, "1 megabyte"},
+ {0, 1025, NULL, "1 kilobyte 1"},
+ {1, 1025, NULL, "1 kilobyte 1 byte"},
+};
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+ char buf[256];
+ int val = parse_bytes (tests[i].str, tests[i].def_unit);
+ int len;
+
+ if (val != tests[i].val) {
+ printf ("parse_bytes (%s, %s) = %d != %d\n",
+ tests[i].str,
+ tests[i].def_unit ? tests[i].def_unit : "none",
+ val, tests[i].val);
+ ++ret;
+ }
+ if (tests[i].canonicalp) {
+ len = unparse_bytes (tests[i].val, buf, sizeof(buf));
+ if (strcmp (tests[i].str, buf) != 0) {
+ printf ("unparse_bytes (%d) = \"%s\" != \"%s\"\n",
+ tests[i].val, buf, tests[i].str);
+ ++ret;
+ }
+ }
+ }
+ if (ret) {
+ printf ("%d errors\n", ret);
+ return 1;
+ } else
+ return 0;
+}
diff --git a/lib/roken/parse_bytes.c b/lib/roken/parse_bytes.c
new file mode 100644
index 0000000000000..4ab02b41557c9
--- /dev/null
+++ b/lib/roken/parse_bytes.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_bytes.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <parse_units.h>
+#include "parse_bytes.h"
+
+static struct units bytes_units[] = {
+ { "gigabyte", 1024 * 1024 * 1024 },
+ { "gbyte", 1024 * 1024 * 1024 },
+ { "GB", 1024 * 1024 * 1024 },
+ { "megabyte", 1024 * 1024 },
+ { "mbyte", 1024 * 1024 },
+ { "MB", 1024 * 1024 },
+ { "kilobyte", 1024 },
+ { "KB", 1024 },
+ { "byte", 1 },
+ { NULL, 0 }
+};
+
+static struct units bytes_short_units[] = {
+ { "GB", 1024 * 1024 * 1024 },
+ { "MB", 1024 * 1024 },
+ { "KB", 1024 },
+ { NULL, 0 }
+};
+
+int ROKEN_LIB_FUNCTION
+parse_bytes (const char *s, const char *def_unit)
+{
+ return parse_units (s, bytes_units, def_unit);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes (int t, char *s, size_t len)
+{
+ return unparse_units (t, bytes_units, s, len);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes_short (int t, char *s, size_t len)
+{
+ return unparse_units_approx (t, bytes_short_units, s, len);
+}
diff --git a/lib/roken/parse_bytes.h b/lib/roken/parse_bytes.h
new file mode 100644
index 0000000000000..1998f70736ada
--- /dev/null
+++ b/lib/roken/parse_bytes.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: parse_bytes.h 14787 2005-04-13 13:19:07Z lha $ */
+
+#ifndef __PARSE_BYTES_H__
+#define __PARSE_BYTES_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+parse_bytes (const char *s, const char *def_unit);
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes (int t, char *s, size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes_short (int t, char *s, size_t len);
+
+#endif /* __PARSE_BYTES_H__ */
diff --git a/lib/roken/parse_reply-test.c b/lib/roken/parse_reply-test.c
new file mode 100644
index 0000000000000..f6342efd7e353
--- /dev/null
+++ b/lib/roken/parse_reply-test.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_reply-test.c 15287 2005-05-29 21:21:12Z lha $");
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+
+#include "roken.h"
+#include "resolve.h"
+
+struct dns_reply*
+parse_reply(const unsigned char *, size_t);
+
+enum { MAX_BUF = 36};
+
+static struct testcase {
+ unsigned char buf[MAX_BUF];
+ size_t buf_len;
+} tests[] = {
+ {{0x12, 0x67, 0x84, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 'f', 'o', 'o', 0x00,
+ 0x00, 0x10, 0x00, 0x01,
+ 0x03, 'f', 'o', 'o', 0x00,
+ 0x00, 0x10, 0x00, 0x01,
+ 0x00, 0x00, 0x12, 0x67, 0xff, 0xff}, 36}
+};
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+
+static sig_atomic_t val = 0;
+
+static RETSIGTYPE
+segv_handler(int sig)
+{
+ val = 1;
+}
+
+int
+main(int argc, char **argv)
+{
+#ifndef HAVE_MMAP
+ return 77; /* signal to automake that this test
+ cannot be run */
+#else /* HAVE_MMAP */
+ int ret;
+ int i;
+ struct sigaction sa;
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = segv_handler;
+ sigaction (SIGSEGV, &sa, NULL);
+
+ for (i = 0; val == 0 && i < sizeof(tests)/sizeof(tests[0]); ++i) {
+ const struct testcase *t = &tests[i];
+ unsigned char *p1, *p2;
+ int flags;
+ int fd;
+ size_t pagesize = getpagesize();
+ unsigned char *buf;
+
+#ifdef MAP_ANON
+ flags = MAP_ANON;
+ fd = -1;
+#else
+ flags = 0;
+ fd = open ("/dev/zero", O_RDONLY);
+ if(fd < 0)
+ err (1, "open /dev/zero");
+#endif
+ flags |= MAP_PRIVATE;
+
+ p1 = (unsigned char *)mmap(0, 2 * pagesize, PROT_READ | PROT_WRITE,
+ flags, fd, 0);
+ if (p1 == (unsigned char *)MAP_FAILED)
+ err (1, "mmap");
+ p2 = p1 + pagesize;
+ ret = mprotect ((void *)p2, pagesize, 0);
+ if (ret < 0)
+ err (1, "mprotect");
+ buf = p2 - t->buf_len;
+ memcpy (buf, t->buf, t->buf_len);
+ parse_reply (buf, t->buf_len);
+ ret = munmap ((void *)p1, 2 * pagesize);
+ if (ret < 0)
+ err (1, "munmap");
+ }
+ return val;
+#endif /* HAVE_MMAP */
+}
diff --git a/lib/roken/parse_time-test.c b/lib/roken/parse_time-test.c
new file mode 100644
index 0000000000000..0ce7063b381f5
--- /dev/null
+++ b/lib/roken/parse_time-test.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_time-test.c 15028 2005-04-30 14:48:29Z lha $");
+#endif
+
+#include "roken.h"
+#include "parse_time.h"
+#include "test-mem.h"
+#include "err.h"
+
+static struct testcase {
+ size_t size;
+ time_t val;
+ char *str;
+} tests[] = {
+ { 8, 1, "1 second" },
+ { 17, 61, "1 minute 1 second" },
+ { 18, 62, "1 minute 2 seconds" },
+ { 8, 60, "1 minute" },
+ { 6, 3600, "1 hour" },
+ { 15, 3601, "1 hour 1 second" },
+ { 16, 3602, "1 hour 2 seconds" }
+};
+
+int
+main(int argc, char **argv)
+{
+ size_t sz;
+ size_t buf_sz;
+ int i, j;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+ char *buf;
+
+ sz = unparse_time(tests[i].val, NULL, 0);
+ if (sz != tests[i].size)
+ errx(1, "sz (%lu) != tests[%d].size (%lu)",
+ (unsigned long)sz, i, (unsigned long)tests[i].size);
+
+ for (buf_sz = 0; buf_sz < tests[i].size + 2; buf_sz++) {
+
+ buf = rk_test_mem_alloc(RK_TM_OVERRUN, "overrun",
+ NULL, buf_sz);
+ sz = unparse_time(tests[i].val, buf, buf_sz);
+ if (sz != tests[i].size)
+ errx(1, "sz (%lu) != tests[%d].size (%lu) with in size %lu",
+ (unsigned long)sz, i,
+ (unsigned long)tests[i].size,
+ (unsigned long)buf_sz);
+ if (buf_sz > 0 && memcmp(buf, tests[i].str, buf_sz - 1) != 0)
+ errx(1, "test %i wrong result %s vs %s", i, buf, tests[i].str);
+ if (buf_sz > 0 && buf[buf_sz - 1] != '\0')
+ errx(1, "test %i not zero terminated", i);
+ rk_test_mem_free("overrun");
+
+ buf = rk_test_mem_alloc(RK_TM_UNDERRUN, "underrun",
+ NULL, tests[i].size);
+ sz = unparse_time(tests[i].val, buf, buf_sz);
+ if (sz != tests[i].size)
+ errx(1, "sz (%lu) != tests[%d].size (%lu) with insize %lu",
+ (unsigned long)sz, i,
+ (unsigned long)tests[i].size,
+ (unsigned long)buf_sz);
+ if (buf_sz > 0 && strncmp(buf, tests[i].str, buf_sz - 1) != 0)
+ errx(1, "test %i wrong result %s vs %s", i, buf, tests[i].str);
+ if (buf_sz > 0 && buf[buf_sz - 1] != '\0')
+ errx(1, "test %i not zero terminated", i);
+ rk_test_mem_free("underrun");
+ }
+ buf = rk_test_mem_alloc(RK_TM_OVERRUN, "overrun",
+ tests[i].str, tests[i].size + 1);
+ j = parse_time(buf, "s");
+ if (j != tests[i].val)
+ errx(1, "parse_time failed for test %d", i);
+ rk_test_mem_free("overrun");
+
+ buf = rk_test_mem_alloc(RK_TM_UNDERRUN, "underrun",
+ tests[i].str, tests[i].size + 1);
+ j = parse_time(buf, "s");
+ if (j != tests[i].val)
+ errx(1, "parse_time failed for test %d", i);
+ rk_test_mem_free("underrun");
+ }
+ return 0;
+}
diff --git a/lib/roken/parse_time.3 b/lib/roken/parse_time.3
new file mode 100644
index 0000000000000..f7a801b51f69d
--- /dev/null
+++ b/lib/roken/parse_time.3
@@ -0,0 +1,173 @@
+.\" Copyright (c) 2004 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+.\" $Id: parse_time.3 14325 2004-10-30 22:34:28Z lha $
+.\"
+.Dd October 31, 2004
+.Dt PARSE_TIME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm parse_time ,
+.Nm print_time_table ,
+.Nm unparse_time ,
+.Nm unparse_time_approx ,
+.Nd parse and unparse time intervals
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.Fd #include <parse_time.h>
+.Ft int
+.Fn parse_time "const char *timespec" "const char *def_unit"
+.Ft void
+.Fn print_time_table "FILE *f"
+.Ft size_t
+.Fn unparse_time "int seconds" "char *buf" "size_t len"
+.Ft size_t
+.Fn unparse_time_approx "int seconds" "char *buf" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn parse_time
+function converts a the period of time specified in
+into a number of seconds.
+The
+.Fa timespec
+can be any number of
+.Aq number unit
+pairs separated by comma and whitespace. The number can be
+negative. Number without explicit units are taken as being
+.Fa def_unit .
+.Pp
+The
+.Fn unparse_time
+and
+.Fn unparse_time_approx
+does the opposite of
+.Fn parse_time ,
+that is they take a number of seconds and express that as human
+readable string.
+.Fa unparse_time
+produces an exact time, while
+.Fa unparse_time_approx
+restricts the result to only include one units.
+.Pp
+.Fn print_time_table
+prints a descriptive list of available units on the passed file
+descriptor.
+.Pp
+The possible units include:
+.Bl -tag -width "month" -compact -offset indent
+.It Li second , s
+.It Li minute , m
+.It Li hour , h
+.It day
+.It week
+seven days
+.It month
+30 days
+.It year
+365 days
+.El
+.Pp
+Units names can be arbitrarily abbreviated (as long as they are
+unique).
+.Sh RETURN VALUES
+.Fn parse_time
+returns the number of seconds that represents the expression in
+.Fa timespec
+or -1 on error.
+.Fn unparse_time
+and
+.Fn unparse_time_approx
+return the number of characters written to
+.Fa buf .
+if the return value is greater than or equal to the
+.Fa len
+argument, the string was too short and some of the printed characters
+were discarded.
+.Sh EXAMPLES
+.Bd -literal
+#include <stdio.h>
+#include <parse_time.h>
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ int result;
+ char buf[128];
+ print_time_table(stdout);
+ for (i = 1; i < argc; i++) {
+ result = parse_time(argv[i], "second");
+ if(result == -1) {
+ fprintf(stderr, "%s: parse error\\n", argv[i]);
+ continue;
+ }
+ printf("--\\n");
+ printf("parse_time = %d\\n", result);
+ unparse_time(result, buf, sizeof(buf));
+ printf("unparse_time = %s\\n", buf);
+ unparse_time_approx(result, buf, sizeof(buf));
+ printf("unparse_time_approx = %s\\n", buf);
+ }
+ return 0;
+}
+.Ed
+.Bd -literal
+$ ./a.out "1 minute 30 seconds" "90 s" "1 y -1 s"
+1 year = 365 days
+1 month = 30 days
+1 week = 7 days
+1 day = 24 hours
+1 hour = 60 minutes
+1 minute = 60 seconds
+1 second
+--
+parse_time = 90
+unparse_time = 1 minute 30 seconds
+unparse_time_approx = 1 minute
+--
+parse_time = 90
+unparse_time = 1 minute 30 seconds
+unparse_time_approx = 1 minute
+--
+parse_time = 31535999
+unparse_time = 12 months 4 days 23 hours 59 minutes 59 seconds
+unparse_time_approx = 12 months
+.Ed
+.Sh BUGS
+Since
+.Fn parse_time
+returns -1 on error there is no way to parse "minus one second".
+Currently "s" at the end of units is ignored. This is a hack for
+English plural forms. If these functions are ever localised, this
+scheme will have to change.
+.\".Sh SEE ALSO
+.\".Xr parse_bytes 3
+.\".Xr parse_units 3
diff --git a/lib/roken/parse_time.c b/lib/roken/parse_time.c
new file mode 100644
index 0000000000000..1c39bde4e8a01
--- /dev/null
+++ b/lib/roken/parse_time.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_time.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <parse_units.h>
+#include "parse_time.h"
+
+static struct units time_units[] = {
+ {"year", 365 * 24 * 60 * 60},
+ {"month", 30 * 24 * 60 * 60},
+ {"week", 7 * 24 * 60 * 60},
+ {"day", 24 * 60 * 60},
+ {"hour", 60 * 60},
+ {"h", 60 * 60},
+ {"minute", 60},
+ {"m", 60},
+ {"second", 1},
+ {"s", 1},
+ {NULL, 0},
+};
+
+int ROKEN_LIB_FUNCTION
+parse_time (const char *s, const char *def_unit)
+{
+ return parse_units (s, time_units, def_unit);
+}
+
+size_t ROKEN_LIB_FUNCTION
+unparse_time (int t, char *s, size_t len)
+{
+ return unparse_units (t, time_units, s, len);
+}
+
+size_t ROKEN_LIB_FUNCTION
+unparse_time_approx (int t, char *s, size_t len)
+{
+ return unparse_units_approx (t, time_units, s, len);
+}
+
+void ROKEN_LIB_FUNCTION
+print_time_table (FILE *f)
+{
+ print_units_table (time_units, f);
+}
diff --git a/lib/roken/parse_time.h b/lib/roken/parse_time.h
new file mode 100644
index 0000000000000..4dc2da08bcb28
--- /dev/null
+++ b/lib/roken/parse_time.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: parse_time.h 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef __PARSE_TIME_H__
+#define __PARSE_TIME_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int
+parse_time (const char *s, const char *def_unit);
+
+size_t
+unparse_time (int t, char *s, size_t len);
+
+size_t
+unparse_time_approx (int t, char *s, size_t len);
+
+void
+print_time_table (FILE *f);
+
+#endif /* __PARSE_TIME_H__ */
diff --git a/lib/roken/parse_units.c b/lib/roken/parse_units.c
new file mode 100644
index 0000000000000..1960beca07106
--- /dev/null
+++ b/lib/roken/parse_units.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: parse_units.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "roken.h"
+#include "parse_units.h"
+
+/*
+ * Parse string in `s' according to `units' and return value.
+ * def_unit defines the default unit.
+ */
+
+static int
+parse_something (const char *s, const struct units *units,
+ const char *def_unit,
+ int (*func)(int res, int val, unsigned mult),
+ int init,
+ int accept_no_val_p)
+{
+ const char *p;
+ int res = init;
+ unsigned def_mult = 1;
+
+ if (def_unit != NULL) {
+ const struct units *u;
+
+ for (u = units; u->name; ++u) {
+ if (strcasecmp (u->name, def_unit) == 0) {
+ def_mult = u->mult;
+ break;
+ }
+ }
+ if (u->name == NULL)
+ return -1;
+ }
+
+ p = s;
+ while (*p) {
+ double val;
+ char *next;
+ const struct units *u, *partial_unit;
+ size_t u_len;
+ unsigned partial;
+ int no_val_p = 0;
+
+ while(isspace((unsigned char)*p) || *p == ',')
+ ++p;
+
+ val = strtod (p, &next); /* strtol(p, &next, 0); */
+ if (p == next) {
+ val = 0;
+ if(!accept_no_val_p)
+ return -1;
+ no_val_p = 1;
+ }
+ p = next;
+ while (isspace((unsigned char)*p))
+ ++p;
+ if (*p == '\0') {
+ res = (*func)(res, val, def_mult);
+ if (res < 0)
+ return res;
+ break;
+ } else if (*p == '+') {
+ ++p;
+ val = 1;
+ } else if (*p == '-') {
+ ++p;
+ val = -1;
+ }
+ if (no_val_p && val == 0)
+ val = 1;
+ u_len = strcspn (p, ", \t");
+ partial = 0;
+ partial_unit = NULL;
+ if (u_len > 1 && p[u_len - 1] == 's')
+ --u_len;
+ for (u = units; u->name; ++u) {
+ if (strncasecmp (p, u->name, u_len) == 0) {
+ if (u_len == strlen (u->name)) {
+ p += u_len;
+ res = (*func)(res, val, u->mult);
+ if (res < 0)
+ return res;
+ break;
+ } else {
+ ++partial;
+ partial_unit = u;
+ }
+ }
+ }
+ if (u->name == NULL) {
+ if (partial == 1) {
+ p += u_len;
+ res = (*func)(res, val, partial_unit->mult);
+ if (res < 0)
+ return res;
+ } else {
+ return -1;
+ }
+ }
+ if (*p == 's')
+ ++p;
+ }
+ return res;
+}
+
+/*
+ * The string consists of a sequence of `n unit'
+ */
+
+static int
+acc_units(int res, int val, unsigned mult)
+{
+ return res + val * mult;
+}
+
+int ROKEN_LIB_FUNCTION
+parse_units (const char *s, const struct units *units,
+ const char *def_unit)
+{
+ return parse_something (s, units, def_unit, acc_units, 0, 0);
+}
+
+/*
+ * The string consists of a sequence of `[+-]flag'. `orig' consists
+ * the original set of flags, those are then modified and returned as
+ * the function value.
+ */
+
+static int
+acc_flags(int res, int val, unsigned mult)
+{
+ if(val == 1)
+ return res | mult;
+ else if(val == -1)
+ return res & ~mult;
+ else if (val == 0)
+ return mult;
+ else
+ return -1;
+}
+
+int ROKEN_LIB_FUNCTION
+parse_flags (const char *s, const struct units *units,
+ int orig)
+{
+ return parse_something (s, units, NULL, acc_flags, orig, 1);
+}
+
+/*
+ * Return a string representation according to `units' of `num' in `s'
+ * with maximum length `len'. The actual length is the function value.
+ */
+
+static int
+unparse_something (int num, const struct units *units, char *s, size_t len,
+ int (*print) (char *, size_t, int, const char *, int),
+ int (*update) (int, unsigned),
+ const char *zero_string)
+{
+ const struct units *u;
+ int ret = 0, tmp;
+
+ if (num == 0)
+ return snprintf (s, len, "%s", zero_string);
+
+ for (u = units; num > 0 && u->name; ++u) {
+ int divisor;
+
+ divisor = num / u->mult;
+ if (divisor) {
+ num = (*update) (num, u->mult);
+ tmp = (*print) (s, len, divisor, u->name, num);
+ if (tmp < 0)
+ return tmp;
+ if (tmp > len) {
+ len = 0;
+ s = NULL;
+ } else {
+ len -= tmp;
+ s += tmp;
+ }
+ ret += tmp;
+ }
+ }
+ return ret;
+}
+
+static int
+print_unit (char *s, size_t len, int divisor, const char *name, int rem)
+{
+ return snprintf (s, len, "%u %s%s%s",
+ divisor, name,
+ divisor == 1 ? "" : "s",
+ rem > 0 ? " " : "");
+}
+
+static int
+update_unit (int in, unsigned mult)
+{
+ return in % mult;
+}
+
+static int
+update_unit_approx (int in, unsigned mult)
+{
+ if (in / mult > 0)
+ return 0;
+ else
+ return update_unit (in, mult);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_units (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_unit,
+ update_unit,
+ "0");
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_units_approx (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_unit,
+ update_unit_approx,
+ "0");
+}
+
+void ROKEN_LIB_FUNCTION
+print_units_table (const struct units *units, FILE *f)
+{
+ const struct units *u, *u2;
+ unsigned max_sz = 0;
+
+ for (u = units; u->name; ++u) {
+ max_sz = max(max_sz, strlen(u->name));
+ }
+
+ for (u = units; u->name;) {
+ char buf[1024];
+ const struct units *next;
+
+ for (next = u + 1; next->name && next->mult == u->mult; ++next)
+ ;
+
+ if (next->name) {
+ for (u2 = next;
+ u2->name && u->mult % u2->mult != 0;
+ ++u2)
+ ;
+ if (u2->name == NULL)
+ --u2;
+ unparse_units (u->mult, u2, buf, sizeof(buf));
+ fprintf (f, "1 %*s = %s\n", max_sz, u->name, buf);
+ } else {
+ fprintf (f, "1 %s\n", u->name);
+ }
+ u = next;
+ }
+}
+
+static int
+print_flag (char *s, size_t len, int divisor, const char *name, int rem)
+{
+ return snprintf (s, len, "%s%s", name, rem > 0 ? ", " : "");
+}
+
+static int
+update_flag (int in, unsigned mult)
+{
+ return in - mult;
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_flags (int num, const struct units *units, char *s, size_t len)
+{
+ return unparse_something (num, units, s, len,
+ print_flag,
+ update_flag,
+ "");
+}
+
+void ROKEN_LIB_FUNCTION
+print_flags_table (const struct units *units, FILE *f)
+{
+ const struct units *u;
+
+ for(u = units; u->name; ++u)
+ fprintf(f, "%s%s", u->name, (u+1)->name ? ", " : "\n");
+}
diff --git a/lib/roken/parse_units.h b/lib/roken/parse_units.h
new file mode 100644
index 0000000000000..a42154d4869f6
--- /dev/null
+++ b/lib/roken/parse_units.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: parse_units.h 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef __PARSE_UNITS_H__
+#define __PARSE_UNITS_H__
+
+#include <stdio.h>
+#include <stddef.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+struct units {
+ const char *name;
+ unsigned mult;
+};
+
+int ROKEN_LIB_FUNCTION
+parse_units (const char *s, const struct units *units,
+ const char *def_unit);
+
+void ROKEN_LIB_FUNCTION
+print_units_table (const struct units *units, FILE *f);
+
+int ROKEN_LIB_FUNCTION
+parse_flags (const char *s, const struct units *units,
+ int orig);
+
+int ROKEN_LIB_FUNCTION
+unparse_units (int num, const struct units *units, char *s, size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_units_approx (int num, const struct units *units, char *s,
+ size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_flags (int num, const struct units *units, char *s, size_t len);
+
+void ROKEN_LIB_FUNCTION
+print_flags_table (const struct units *units, FILE *f);
+
+#endif /* __PARSE_UNITS_H__ */
diff --git a/lib/roken/print_version.c b/lib/roken/print_version.c
new file mode 100644
index 0000000000000..b5ce816eb604e
--- /dev/null
+++ b/lib/roken/print_version.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: print_version.c,v 1.8 2001/02/20 01:44:55 assar Exp $");
+#endif
+#include "roken.h"
+
+#include "print_version.h"
+
+void
+print_version(const char *progname)
+{
+ const char *arg[] = VERSIONLIST;
+ const int num_args = sizeof(arg) / sizeof(arg[0]);
+ char *msg;
+ size_t len = 0;
+ int i;
+
+ if(progname == NULL)
+ progname = getprogname();
+
+ if(num_args == 0)
+ msg = "no version information";
+ else {
+ for(i = 0; i < num_args; i++) {
+ if(i > 0)
+ len += 2;
+ len += strlen(arg[i]);
+ }
+ msg = malloc(len + 1);
+ if(msg == NULL) {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ return;
+ }
+ msg[0] = '\0';
+ for(i = 0; i < num_args; i++) {
+ if(i > 0)
+ strcat(msg, ", ");
+ strcat(msg, arg[i]);
+ }
+ }
+ fprintf(stderr, "%s (%s)\n", progname, msg);
+ fprintf(stderr, "Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan\n");
+ if(num_args != 0)
+ free(msg);
+}
diff --git a/lib/roken/putenv.c b/lib/roken/putenv.c
new file mode 100644
index 0000000000000..5e501dcc0f27a
--- /dev/null
+++ b/lib/roken/putenv.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: putenv.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <stdlib.h>
+
+extern char **environ;
+
+/*
+ * putenv --
+ * String points to a string of the form name=value.
+ *
+ * Makes the value of the environment variable name equal to
+ * value by altering an existing variable or creating a new one.
+ */
+
+int ROKEN_LIB_FUNCTION
+putenv(const char *string)
+{
+ int i;
+ const char *eq = (const char *)strchr(string, '=');
+ int len;
+
+ if (eq == NULL)
+ return 1;
+ len = eq - string;
+
+ if(environ == NULL) {
+ environ = malloc(sizeof(char*));
+ if(environ == NULL)
+ return 1;
+ environ[0] = NULL;
+ }
+
+ for(i = 0; environ[i] != NULL; i++)
+ if(strncmp(string, environ[i], len) == 0) {
+ environ[i] = string;
+ return 0;
+ }
+ environ = realloc(environ, sizeof(char*) * (i + 2));
+ if(environ == NULL)
+ return 1;
+ environ[i] = string;
+ environ[i+1] = NULL;
+ return 0;
+}
diff --git a/lib/roken/rcmd.c b/lib/roken/rcmd.c
new file mode 100644
index 0000000000000..e732fe3c2a866
--- /dev/null
+++ b/lib/roken/rcmd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: rcmd.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include <stdio.h>
+
+int ROKEN_LIB_FUNCTION
+rcmd(char **ahost,
+ unsigned short inport,
+ const char *locuser,
+ const char *remuser,
+ const char *cmd,
+ int *fd2p)
+{
+ fprintf(stderr, "Only kerberized services are implemented\n");
+ return -1;
+}
diff --git a/lib/roken/readv.c b/lib/roken/readv.c
new file mode 100644
index 0000000000000..b49890ebd6ed3
--- /dev/null
+++ b/lib/roken/readv.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: readv.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+readv(int d, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret, nb;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+
+ for(i = 0; i < iovcnt; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (tot != 0 && buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ nb = ret = read (d, buf, tot);
+ p = buf;
+ while (nb > 0) {
+ ssize_t cnt = min(nb, iov->iov_len);
+
+ memcpy (iov->iov_base, p, cnt);
+ p += cnt;
+ nb -= cnt;
+ }
+ free(buf);
+ return ret;
+}
diff --git a/lib/roken/realloc.c b/lib/roken/realloc.c
new file mode 100644
index 0000000000000..33e898c34302c
--- /dev/null
+++ b/lib/roken/realloc.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#undef realloc
+#endif
+#include <stdlib.h>
+#include "roken.h"
+
+RCSID("$Id");
+
+
+void * ROKEN_LIB_FUNCTION
+rk_realloc(void *ptr, size_t size)
+{
+ if (ptr == NULL)
+ return malloc(size);
+ return realloc(ptr, size);
+}
diff --git a/lib/roken/recvmsg.c b/lib/roken/recvmsg.c
new file mode 100644
index 0000000000000..d92186c1b9f6d
--- /dev/null
+++ b/lib/roken/recvmsg.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: recvmsg.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+recvmsg(int s, struct msghdr *msg, int flags)
+{
+ ssize_t ret, nb;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+ struct iovec *iov = msg->msg_iov;
+
+ for(i = 0; i < msg->msg_iovlen; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (tot != 0 && buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ nb = ret = recvfrom (s, buf, tot, flags, msg->msg_name, &msg->msg_namelen);
+ p = buf;
+ while (nb > 0) {
+ ssize_t cnt = min(nb, iov->iov_len);
+
+ memcpy (iov->iov_base, p, cnt);
+ p += cnt;
+ nb -= cnt;
+ ++iov;
+ }
+ free(buf);
+ return ret;
+}
diff --git a/lib/roken/resolve-test.c b/lib/roken/resolve-test.c
new file mode 100644
index 0000000000000..106cfd71b3e79
--- /dev/null
+++ b/lib/roken/resolve-test.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1995 - 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#include "getarg.h"
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include "resolve.h"
+
+RCSID("$Id: resolve-test.c 15415 2005-06-16 16:58:45Z lha $");
+
+static int version_flag = 0;
+static int help_flag = 0;
+
+static struct getargs args[] = {
+ {"version", 0, arg_flag, &version_flag,
+ "print version", NULL },
+ {"help", 0, arg_flag, &help_flag,
+ NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+ arg_printusage (args,
+ sizeof(args)/sizeof(*args),
+ NULL,
+ "dns-record resource-record-type");
+ exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct dns_reply *r;
+ struct resource_record *rr;
+ int optidx = 0;
+
+ setprogname (argv[0]);
+
+ if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
+ usage(1);
+
+ if (help_flag)
+ usage (0);
+
+ if(version_flag){
+ printf("some version\n");
+ exit(0);
+ }
+
+ argc -= optidx;
+ argv += optidx;
+
+ if (argc != 2)
+ usage(1);
+
+ r = dns_lookup(argv[0], argv[1]);
+ if(r == NULL){
+ printf("No reply.\n");
+ return 1;
+ }
+ if(r->q.type == rk_ns_t_srv)
+ dns_srv_order(r);
+
+ for(rr = r->head; rr;rr=rr->next){
+ printf("%-30s %-5s %-6d ", rr->domain, dns_type_to_string(rr->type), rr->ttl);
+ switch(rr->type){
+ case rk_ns_t_ns:
+ case rk_ns_t_cname:
+ case rk_ns_t_ptr:
+ printf("%s\n", (char*)rr->u.data);
+ break;
+ case rk_ns_t_a:
+ printf("%s\n", inet_ntoa(*rr->u.a));
+ break;
+ case rk_ns_t_mx:
+ case rk_ns_t_afsdb:{
+ printf("%d %s\n", rr->u.mx->preference, rr->u.mx->domain);
+ break;
+ }
+ case rk_ns_t_srv:{
+ struct srv_record *srv = rr->u.srv;
+ printf("%d %d %d %s\n", srv->priority, srv->weight,
+ srv->port, srv->target);
+ break;
+ }
+ case rk_ns_t_txt: {
+ printf("%s\n", rr->u.txt);
+ break;
+ }
+ case rk_ns_t_sig : {
+ struct sig_record *sig = rr->u.sig;
+ const char *type_string = dns_type_to_string (sig->type);
+
+ printf ("type %u (%s), algorithm %u, labels %u, orig_ttl %u, sig_expiration %u, sig_inception %u, key_tag %u, signer %s\n",
+ sig->type, type_string ? type_string : "",
+ sig->algorithm, sig->labels, sig->orig_ttl,
+ sig->sig_expiration, sig->sig_inception, sig->key_tag,
+ sig->signer);
+ break;
+ }
+ case rk_ns_t_key : {
+ struct key_record *key = rr->u.key;
+
+ printf ("flags %u, protocol %u, algorithm %u\n",
+ key->flags, key->protocol, key->algorithm);
+ break;
+ }
+ case rk_ns_t_sshfp : {
+ struct sshfp_record *sshfp = rr->u.sshfp;
+ int i;
+
+ printf ("alg %u type %u length %lu data ", sshfp->algorithm,
+ sshfp->type, (unsigned long)sshfp->sshfp_len);
+ for (i = 0; i < sshfp->sshfp_len; i++)
+ printf("%02X", sshfp->sshfp_data[i]);
+ printf("\n");
+
+ break;
+ }
+ case rk_ns_t_ds : {
+ struct ds_record *ds = rr->u.ds;
+ int i;
+
+ printf ("key tag %u alg %u type %u length %u data ",
+ ds->key_tag, ds->algorithm, ds->digest_type,
+ ds->digest_len);
+ for (i = 0; i < ds->digest_len; i++)
+ printf("%02X", ds->digest_data[i]);
+ printf("\n");
+
+ break;
+ }
+ default:
+ printf("\n");
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/roken/resolve.c b/lib/roken/resolve.c
new file mode 100644
index 0000000000000..8f8fec7657e4b
--- /dev/null
+++ b/lib/roken/resolve.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include "resolve.h"
+
+#include <assert.h>
+
+RCSID("$Id: resolve.c 19869 2007-01-12 16:03:14Z lha $");
+
+#ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */
+#undef HAVE_RES_NSEARCH
+#endif
+
+#define DECL(X) {#X, rk_ns_t_##X}
+
+static struct stot{
+ const char *name;
+ int type;
+}stot[] = {
+ DECL(a),
+ DECL(aaaa),
+ DECL(ns),
+ DECL(cname),
+ DECL(soa),
+ DECL(ptr),
+ DECL(mx),
+ DECL(txt),
+ DECL(afsdb),
+ DECL(sig),
+ DECL(key),
+ DECL(srv),
+ DECL(naptr),
+ DECL(sshfp),
+ DECL(ds),
+ {NULL, 0}
+};
+
+int _resolve_debug = 0;
+
+int ROKEN_LIB_FUNCTION
+dns_string_to_type(const char *name)
+{
+ struct stot *p = stot;
+ for(p = stot; p->name; p++)
+ if(strcasecmp(name, p->name) == 0)
+ return p->type;
+ return -1;
+}
+
+const char * ROKEN_LIB_FUNCTION
+dns_type_to_string(int type)
+{
+ struct stot *p = stot;
+ for(p = stot; p->name; p++)
+ if(type == p->type)
+ return p->name;
+ return NULL;
+}
+
+#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
+
+static void
+dns_free_rr(struct resource_record *rr)
+{
+ if(rr->domain)
+ free(rr->domain);
+ if(rr->u.data)
+ free(rr->u.data);
+ free(rr);
+}
+
+void ROKEN_LIB_FUNCTION
+dns_free_data(struct dns_reply *r)
+{
+ struct resource_record *rr;
+ if(r->q.domain)
+ free(r->q.domain);
+ for(rr = r->head; rr;){
+ struct resource_record *tmp = rr;
+ rr = rr->next;
+ dns_free_rr(tmp);
+ }
+ free (r);
+}
+
+static int
+parse_record(const unsigned char *data, const unsigned char *end_data,
+ const unsigned char **pp, struct resource_record **ret_rr)
+{
+ struct resource_record *rr;
+ int type, class, ttl, size;
+ int status;
+ char host[MAXDNAME];
+ const unsigned char *p = *pp;
+
+ *ret_rr = NULL;
+
+ status = dn_expand(data, end_data, p, host, sizeof(host));
+ if(status < 0)
+ return -1;
+ if (p + status + 10 > end_data)
+ return -1;
+
+ p += status;
+ type = (p[0] << 8) | p[1];
+ p += 2;
+ class = (p[0] << 8) | p[1];
+ p += 2;
+ ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ p += 4;
+ size = (p[0] << 8) | p[1];
+ p += 2;
+
+ if (p + size > end_data)
+ return -1;
+
+ rr = calloc(1, sizeof(*rr));
+ if(rr == NULL)
+ return -1;
+ rr->domain = strdup(host);
+ if(rr->domain == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->type = type;
+ rr->class = class;
+ rr->ttl = ttl;
+ rr->size = size;
+ switch(type){
+ case rk_ns_t_ns:
+ case rk_ns_t_cname:
+ case rk_ns_t_ptr:
+ status = dn_expand(data, end_data, p, host, sizeof(host));
+ if(status < 0) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->u.txt = strdup(host);
+ if(rr->u.txt == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ break;
+ case rk_ns_t_mx:
+ case rk_ns_t_afsdb:{
+ size_t hostlen;
+
+ status = dn_expand(data, end_data, p + 2, host, sizeof(host));
+ if(status < 0){
+ dns_free_rr(rr);
+ return -1;
+ }
+ if (status + 2 > size) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ hostlen = strlen(host);
+ rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
+ hostlen);
+ if(rr->u.mx == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->u.mx->preference = (p[0] << 8) | p[1];
+ strlcpy(rr->u.mx->domain, host, hostlen + 1);
+ break;
+ }
+ case rk_ns_t_srv:{
+ size_t hostlen;
+ status = dn_expand(data, end_data, p + 6, host, sizeof(host));
+ if(status < 0){
+ dns_free_rr(rr);
+ return -1;
+ }
+ if (status + 6 > size) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ hostlen = strlen(host);
+ rr->u.srv =
+ (struct srv_record*)malloc(sizeof(struct srv_record) +
+ hostlen);
+ if(rr->u.srv == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->u.srv->priority = (p[0] << 8) | p[1];
+ rr->u.srv->weight = (p[2] << 8) | p[3];
+ rr->u.srv->port = (p[4] << 8) | p[5];
+ strlcpy(rr->u.srv->target, host, hostlen + 1);
+ break;
+ }
+ case rk_ns_t_txt:{
+ if(size == 0 || size < *p + 1) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->u.txt = (char*)malloc(*p + 1);
+ if(rr->u.txt == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ strncpy(rr->u.txt, (const char*)(p + 1), *p);
+ rr->u.txt[*p] = '\0';
+ break;
+ }
+ case rk_ns_t_key : {
+ size_t key_len;
+
+ if (size < 4) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ key_len = size - 4;
+ rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
+ if (rr->u.key == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ rr->u.key->flags = (p[0] << 8) | p[1];
+ rr->u.key->protocol = p[2];
+ rr->u.key->algorithm = p[3];
+ rr->u.key->key_len = key_len;
+ memcpy (rr->u.key->key_data, p + 4, key_len);
+ break;
+ }
+ case rk_ns_t_sig : {
+ size_t sig_len, hostlen;
+
+ if(size <= 18) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ status = dn_expand (data, end_data, p + 18, host, sizeof(host));
+ if (status < 0) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ if (status + 18 > size) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ /* the signer name is placed after the sig_data, to make it
+ easy to free this structure; the size calculation below
+ includes the zero-termination if the structure itself.
+ don't you just love C?
+ */
+ sig_len = size - 18 - status;
+ hostlen = strlen(host);
+ rr->u.sig = malloc(sizeof(*rr->u.sig)
+ + hostlen + sig_len);
+ if (rr->u.sig == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ rr->u.sig->type = (p[0] << 8) | p[1];
+ rr->u.sig->algorithm = p[2];
+ rr->u.sig->labels = p[3];
+ rr->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16)
+ | (p[6] << 8) | p[7];
+ rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
+ | (p[10] << 8) | p[11];
+ rr->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16)
+ | (p[14] << 8) | p[15];
+ rr->u.sig->key_tag = (p[16] << 8) | p[17];
+ rr->u.sig->sig_len = sig_len;
+ memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len);
+ rr->u.sig->signer = &rr->u.sig->sig_data[sig_len];
+ strlcpy(rr->u.sig->signer, host, hostlen + 1);
+ break;
+ }
+
+ case rk_ns_t_cert : {
+ size_t cert_len;
+
+ if (size < 5) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ cert_len = size - 5;
+ rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1);
+ if (rr->u.cert == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ rr->u.cert->type = (p[0] << 8) | p[1];
+ rr->u.cert->tag = (p[2] << 8) | p[3];
+ rr->u.cert->algorithm = p[4];
+ rr->u.cert->cert_len = cert_len;
+ memcpy (rr->u.cert->cert_data, p + 5, cert_len);
+ break;
+ }
+ case rk_ns_t_sshfp : {
+ size_t sshfp_len;
+
+ if (size < 2) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ sshfp_len = size - 2;
+
+ rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1);
+ if (rr->u.sshfp == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ rr->u.sshfp->algorithm = p[0];
+ rr->u.sshfp->type = p[1];
+ rr->u.sshfp->sshfp_len = sshfp_len;
+ memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len);
+ break;
+ }
+ case rk_ns_t_ds: {
+ size_t digest_len;
+
+ if (size < 4) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ digest_len = size - 4;
+
+ rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1);
+ if (rr->u.ds == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+
+ rr->u.ds->key_tag = (p[0] << 8) | p[1];
+ rr->u.ds->algorithm = p[2];
+ rr->u.ds->digest_type = p[3];
+ rr->u.ds->digest_len = digest_len;
+ memcpy (rr->u.ds->digest_data, p + 4, digest_len);
+ break;
+ }
+ default:
+ rr->u.data = (unsigned char*)malloc(size);
+ if(size != 0 && rr->u.data == NULL) {
+ dns_free_rr(rr);
+ return -1;
+ }
+ if (size)
+ memcpy(rr->u.data, p, size);
+ }
+ *pp = p + size;
+ *ret_rr = rr;
+
+ return 0;
+}
+
+#ifndef TEST_RESOLVE
+static
+#endif
+struct dns_reply*
+parse_reply(const unsigned char *data, size_t len)
+{
+ const unsigned char *p;
+ int status;
+ int i;
+ char host[MAXDNAME];
+ const unsigned char *end_data = data + len;
+ struct dns_reply *r;
+ struct resource_record **rr;
+
+ r = calloc(1, sizeof(*r));
+ if (r == NULL)
+ return NULL;
+
+ p = data;
+
+ r->h.id = (p[0] << 8) | p[1];
+ r->h.flags = 0;
+ if (p[2] & 0x01)
+ r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG;
+ r->h.opcode = (p[2] >> 1) & 0xf;
+ if (p[2] & 0x20)
+ r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
+ if (p[2] & 0x40)
+ r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE;
+ if (p[2] & 0x80)
+ r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED;
+ if (p[3] & 0x01)
+ r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE;
+ if (p[3] & 0x04)
+ r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
+ if (p[3] & 0x08)
+ r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED;
+ r->h.response_code = (p[3] >> 4) & 0xf;
+ r->h.qdcount = (p[4] << 8) | p[5];
+ r->h.ancount = (p[6] << 8) | p[7];
+ r->h.nscount = (p[8] << 8) | p[9];
+ r->h.arcount = (p[10] << 8) | p[11];
+
+ p += 12;
+
+ if(r->h.qdcount != 1) {
+ free(r);
+ return NULL;
+ }
+ status = dn_expand(data, end_data, p, host, sizeof(host));
+ if(status < 0){
+ dns_free_data(r);
+ return NULL;
+ }
+ r->q.domain = strdup(host);
+ if(r->q.domain == NULL) {
+ dns_free_data(r);
+ return NULL;
+ }
+ if (p + status + 4 > end_data) {
+ dns_free_data(r);
+ return NULL;
+ }
+ p += status;
+ r->q.type = (p[0] << 8 | p[1]);
+ p += 2;
+ r->q.class = (p[0] << 8 | p[1]);
+ p += 2;
+
+ rr = &r->head;
+ for(i = 0; i < r->h.ancount; i++) {
+ if(parse_record(data, end_data, &p, rr) != 0) {
+ dns_free_data(r);
+ return NULL;
+ }
+ rr = &(*rr)->next;
+ }
+ for(i = 0; i < r->h.nscount; i++) {
+ if(parse_record(data, end_data, &p, rr) != 0) {
+ dns_free_data(r);
+ return NULL;
+ }
+ rr = &(*rr)->next;
+ }
+ for(i = 0; i < r->h.arcount; i++) {
+ if(parse_record(data, end_data, &p, rr) != 0) {
+ dns_free_data(r);
+ return NULL;
+ }
+ rr = &(*rr)->next;
+ }
+ *rr = NULL;
+ return r;
+}
+
+#ifdef HAVE_RES_NSEARCH
+#ifdef HAVE_RES_NDESTROY
+#define rk_res_free(x) res_ndestroy(x)
+#else
+#define rk_res_free(x) res_nclose(x)
+#endif
+#endif
+
+static struct dns_reply *
+dns_lookup_int(const char *domain, int rr_class, int rr_type)
+{
+ struct dns_reply *r;
+ unsigned char *reply = NULL;
+ int size;
+ int len;
+#ifdef HAVE_RES_NSEARCH
+ struct __res_state state;
+ memset(&state, 0, sizeof(state));
+ if(res_ninit(&state))
+ return NULL; /* is this the best we can do? */
+#elif defined(HAVE__RES)
+ u_long old_options = 0;
+#endif
+
+ size = 0;
+ len = 1000;
+ do {
+ if (reply) {
+ free(reply);
+ reply = NULL;
+ }
+ if (size <= len)
+ size = len;
+ if (_resolve_debug) {
+#ifdef HAVE_RES_NSEARCH
+ state.options |= RES_DEBUG;
+#elif defined(HAVE__RES)
+ old_options = _res.options;
+ _res.options |= RES_DEBUG;
+#endif
+ fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
+ rr_class, dns_type_to_string(rr_type), size);
+ }
+ reply = malloc(size);
+ if (reply == NULL) {
+#ifdef HAVE_RES_NSEARCH
+ rk_res_free(&state);
+#endif
+ return NULL;
+ }
+#ifdef HAVE_RES_NSEARCH
+ len = res_nsearch(&state, domain, rr_class, rr_type, reply, size);
+#else
+ len = res_search(domain, rr_class, rr_type, reply, size);
+#endif
+ if (_resolve_debug) {
+#if defined(HAVE__RES) && !defined(HAVE_RES_NSEARCH)
+ _res.options = old_options;
+#endif
+ fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
+ domain, rr_class, dns_type_to_string(rr_type), len);
+ }
+ if (len < 0) {
+#ifdef HAVE_RES_NSEARCH
+ rk_res_free(&state);
+#endif
+ free(reply);
+ return NULL;
+ }
+ } while (size < len && len < rk_DNS_MAX_PACKET_SIZE);
+#ifdef HAVE_RES_NSEARCH
+ rk_res_free(&state);
+#endif
+
+ len = min(len, size);
+ r = parse_reply(reply, len);
+ free(reply);
+ return r;
+}
+
+struct dns_reply * ROKEN_LIB_FUNCTION
+dns_lookup(const char *domain, const char *type_name)
+{
+ int type;
+
+ type = dns_string_to_type(type_name);
+ if(type == -1) {
+ if(_resolve_debug)
+ fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
+ type_name);
+ return NULL;
+ }
+ return dns_lookup_int(domain, C_IN, type);
+}
+
+static int
+compare_srv(const void *a, const void *b)
+{
+ const struct resource_record *const* aa = a, *const* bb = b;
+
+ if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
+ return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
+ return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
+}
+
+#ifndef HAVE_RANDOM
+#define random() rand()
+#endif
+
+/* try to rearrange the srv-records by the algorithm in RFC2782 */
+void ROKEN_LIB_FUNCTION
+dns_srv_order(struct dns_reply *r)
+{
+ struct resource_record **srvs, **ss, **headp;
+ struct resource_record *rr;
+ int num_srv = 0;
+
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+ int state[256 / sizeof(int)];
+ char *oldstate;
+#endif
+
+ for(rr = r->head; rr; rr = rr->next)
+ if(rr->type == rk_ns_t_srv)
+ num_srv++;
+
+ if(num_srv == 0)
+ return;
+
+ srvs = malloc(num_srv * sizeof(*srvs));
+ if(srvs == NULL)
+ return; /* XXX not much to do here */
+
+ /* unlink all srv-records from the linked list and put them in
+ a vector */
+ for(ss = srvs, headp = &r->head; *headp; )
+ if((*headp)->type == rk_ns_t_srv) {
+ *ss = *headp;
+ *headp = (*headp)->next;
+ (*ss)->next = NULL;
+ ss++;
+ } else
+ headp = &(*headp)->next;
+
+ /* sort them by priority and weight */
+ qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
+
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+ oldstate = initstate(time(NULL), (char*)state, sizeof(state));
+#endif
+
+ headp = &r->head;
+
+ for(ss = srvs; ss < srvs + num_srv; ) {
+ int sum, rnd, count;
+ struct resource_record **ee, **tt;
+ /* find the last record with the same priority and count the
+ sum of all weights */
+ for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
+ assert(*tt != NULL);
+ if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
+ break;
+ sum += (*tt)->u.srv->weight;
+ }
+ ee = tt;
+ /* ss is now the first record of this priority and ee is the
+ first of the next */
+ while(ss < ee) {
+ rnd = random() % (sum + 1);
+ for(count = 0, tt = ss; ; tt++) {
+ if(*tt == NULL)
+ continue;
+ count += (*tt)->u.srv->weight;
+ if(count >= rnd)
+ break;
+ }
+
+ assert(tt < ee);
+
+ /* insert the selected record at the tail (of the head) of
+ the list */
+ (*tt)->next = *headp;
+ *headp = *tt;
+ headp = &(*tt)->next;
+ sum -= (*tt)->u.srv->weight;
+ *tt = NULL;
+ while(ss < ee && *ss == NULL)
+ ss++;
+ }
+ }
+
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+ setstate(oldstate);
+#endif
+ free(srvs);
+ return;
+}
+
+#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
+
+struct dns_reply * ROKEN_LIB_FUNCTION
+dns_lookup(const char *domain, const char *type_name)
+{
+ return NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+dns_free_data(struct dns_reply *r)
+{
+}
+
+void ROKEN_LIB_FUNCTION
+dns_srv_order(struct dns_reply *r)
+{
+}
+
+#endif
diff --git a/lib/roken/resolve.h b/lib/roken/resolve.h
new file mode 100644
index 0000000000000..fe83115b1ec21
--- /dev/null
+++ b/lib/roken/resolve.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: resolve.h 14773 2005-04-12 11:29:18Z lha $ */
+
+#ifndef __RESOLVE_H__
+#define __RESOLVE_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+typedef enum {
+ rk_ns_t_invalid = 0, /* Cookie. */
+ rk_ns_t_a = 1, /* Host address. */
+ rk_ns_t_ns = 2, /* Authoritative server. */
+ rk_ns_t_md = 3, /* Mail destination. */
+ rk_ns_t_mf = 4, /* Mail forwarder. */
+ rk_ns_t_cname = 5, /* Canonical name. */
+ rk_ns_t_soa = 6, /* Start of authority zone. */
+ rk_ns_t_mb = 7, /* Mailbox domain name. */
+ rk_ns_t_mg = 8, /* Mail group member. */
+ rk_ns_t_mr = 9, /* Mail rename name. */
+ rk_ns_t_null = 10, /* Null resource record. */
+ rk_ns_t_wks = 11, /* Well known service. */
+ rk_ns_t_ptr = 12, /* Domain name pointer. */
+ rk_ns_t_hinfo = 13, /* Host information. */
+ rk_ns_t_minfo = 14, /* Mailbox information. */
+ rk_ns_t_mx = 15, /* Mail routing information. */
+ rk_ns_t_txt = 16, /* Text strings. */
+ rk_ns_t_rp = 17, /* Responsible person. */
+ rk_ns_t_afsdb = 18, /* AFS cell database. */
+ rk_ns_t_x25 = 19, /* X_25 calling address. */
+ rk_ns_t_isdn = 20, /* ISDN calling address. */
+ rk_ns_t_rt = 21, /* Router. */
+ rk_ns_t_nsap = 22, /* NSAP address. */
+ rk_ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
+ rk_ns_t_sig = 24, /* Security signature. */
+ rk_ns_t_key = 25, /* Security key. */
+ rk_ns_t_px = 26, /* X.400 mail mapping. */
+ rk_ns_t_gpos = 27, /* Geographical position (withdrawn). */
+ rk_ns_t_aaaa = 28, /* Ip6 Address. */
+ rk_ns_t_loc = 29, /* Location Information. */
+ rk_ns_t_nxt = 30, /* Next domain (security). */
+ rk_ns_t_eid = 31, /* Endpoint identifier. */
+ rk_ns_t_nimloc = 32, /* Nimrod Locator. */
+ rk_ns_t_srv = 33, /* Server Selection. */
+ rk_ns_t_atma = 34, /* ATM Address */
+ rk_ns_t_naptr = 35, /* Naming Authority PoinTeR */
+ rk_ns_t_kx = 36, /* Key Exchange */
+ rk_ns_t_cert = 37, /* Certification record */
+ rk_ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */
+ rk_ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
+ rk_ns_t_sink = 40, /* Kitchen sink (experimentatl) */
+ rk_ns_t_opt = 41, /* EDNS0 option (meta-RR) */
+ rk_ns_t_apl = 42, /* Address prefix list (RFC 3123) */
+ rk_ns_t_ds = 43, /* Delegation Signer (RFC 3658) */
+ rk_ns_t_sshfp = 44, /* SSH fingerprint */
+ rk_ns_t_tkey = 249, /* Transaction key */
+ rk_ns_t_tsig = 250, /* Transaction signature. */
+ rk_ns_t_ixfr = 251, /* Incremental zone transfer. */
+ rk_ns_t_axfr = 252, /* Transfer zone of authority. */
+ rk_ns_t_mailb = 253, /* Transfer mailbox records. */
+ rk_ns_t_maila = 254, /* Transfer mail agent records. */
+ rk_ns_t_any = 255, /* Wildcard match. */
+ rk_ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
+ rk_ns_t_max = 65536
+} rk_ns_type;
+
+/* We use these, but they are not always present in <arpa/nameser.h> */
+
+#ifndef C_IN
+#define C_IN 1
+#endif
+
+#ifndef T_A
+#define T_A 1
+#endif
+#ifndef T_NS
+#define T_NS 2
+#endif
+#ifndef T_CNAME
+#define T_CNAME 5
+#endif
+#ifndef T_SOA
+#define T_SOA 5
+#endif
+#ifndef T_PTR
+#define T_PTR 12
+#endif
+#ifndef T_MX
+#define T_MX 15
+#endif
+#ifndef T_TXT
+#define T_TXT 16
+#endif
+#ifndef T_AFSDB
+#define T_AFSDB 18
+#endif
+#ifndef T_SIG
+#define T_SIG 24
+#endif
+#ifndef T_KEY
+#define T_KEY 25
+#endif
+#ifndef T_AAAA
+#define T_AAAA 28
+#endif
+#ifndef T_SRV
+#define T_SRV 33
+#endif
+#ifndef T_NAPTR
+#define T_NAPTR 35
+#endif
+#ifndef T_CERT
+#define T_CERT 37
+#endif
+#ifndef T_SSHFP
+#define T_SSHFP 44
+#endif
+
+#ifndef MAXDNAME
+#define MAXDNAME 1025
+#endif
+
+#define dns_query rk_dns_query
+#define mx_record rk_mx_record
+#define srv_record rk_srv_record
+#define key_record rk_key_record
+#define sig_record rk_sig_record
+#define cert_record rk_cert_record
+#define sshfp_record rk_sshfp_record
+#define resource_record rk_resource_record
+#define dns_reply rk_dns_reply
+
+#define dns_lookup rk_dns_lookup
+#define dns_free_data rk_dns_free_data
+#define dns_string_to_type rk_dns_string_to_type
+#define dns_type_to_string rk_dns_type_to_string
+#define dns_srv_order rk_dns_srv_order
+
+struct dns_query{
+ char *domain;
+ unsigned type;
+ unsigned class;
+};
+
+struct mx_record{
+ unsigned preference;
+ char domain[1];
+};
+
+struct srv_record{
+ unsigned priority;
+ unsigned weight;
+ unsigned port;
+ char target[1];
+};
+
+struct key_record {
+ unsigned flags;
+ unsigned protocol;
+ unsigned algorithm;
+ size_t key_len;
+ u_char key_data[1];
+};
+
+struct sig_record {
+ unsigned type;
+ unsigned algorithm;
+ unsigned labels;
+ unsigned orig_ttl;
+ unsigned sig_expiration;
+ unsigned sig_inception;
+ unsigned key_tag;
+ char *signer;
+ unsigned sig_len;
+ char sig_data[1]; /* also includes signer */
+};
+
+struct cert_record {
+ unsigned type;
+ unsigned tag;
+ unsigned algorithm;
+ size_t cert_len;
+ u_char cert_data[1];
+};
+
+struct sshfp_record {
+ unsigned algorithm;
+ unsigned type;
+ size_t sshfp_len;
+ u_char sshfp_data[1];
+};
+
+struct ds_record {
+ unsigned key_tag;
+ unsigned algorithm;
+ unsigned digest_type;
+ unsigned digest_len;
+ u_char digest_data[1];
+};
+
+struct resource_record{
+ char *domain;
+ unsigned type;
+ unsigned class;
+ unsigned ttl;
+ unsigned size;
+ union {
+ void *data;
+ struct mx_record *mx;
+ struct mx_record *afsdb; /* mx and afsdb are identical */
+ struct srv_record *srv;
+ struct in_addr *a;
+ char *txt;
+ struct key_record *key;
+ struct cert_record *cert;
+ struct sig_record *sig;
+ struct sshfp_record *sshfp;
+ struct ds_record *ds;
+ }u;
+ struct resource_record *next;
+};
+
+#define rk_DNS_MAX_PACKET_SIZE 0xffff
+
+struct dns_header {
+ unsigned id;
+ unsigned flags;
+#define rk_DNS_HEADER_RESPONSE_FLAG 1
+#define rk_DNS_HEADER_AUTHORITIVE_ANSWER 2
+#define rk_DNS_HEADER_TRUNCATED_MESSAGE 4
+#define rk_DNS_HEADER_RECURSION_DESIRED 8
+#define rk_DNS_HEADER_RECURSION_AVAILABLE 16
+#define rk_DNS_HEADER_AUTHENTIC_DATA 32
+#define rk_DNS_HEADER_CHECKING_DISABLED 64
+ unsigned opcode;
+ unsigned response_code;
+ unsigned qdcount;
+ unsigned ancount;
+ unsigned nscount;
+ unsigned arcount;
+};
+
+struct dns_reply{
+ struct dns_header h;
+ struct dns_query q;
+ struct resource_record *head;
+};
+
+
+struct dns_reply* ROKEN_LIB_FUNCTION
+ dns_lookup(const char *, const char *);
+void ROKEN_LIB_FUNCTION
+ dns_free_data(struct dns_reply *);
+int ROKEN_LIB_FUNCTION
+ dns_string_to_type(const char *name);
+const char *ROKEN_LIB_FUNCTION
+ dns_type_to_string(int type);
+void ROKEN_LIB_FUNCTION
+ dns_srv_order(struct dns_reply*);
+
+#endif /* __RESOLVE_H__ */
diff --git a/lib/roken/resource.h b/lib/roken/resource.h
new file mode 100644
index 0000000000000..01cd01d76c8c4
--- /dev/null
+++ b/lib/roken/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by roken.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/lib/roken/roken-common.h b/lib/roken/roken-common.h
new file mode 100644
index 0000000000000..b835e880a2498
--- /dev/null
+++ b/lib/roken/roken-common.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 1995 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: roken-common.h 20867 2007-06-03 21:00:45Z lha $ */
+
+#ifndef __ROKEN_COMMON_H__
+#define __ROKEN_COMMON_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifdef __cplusplus
+#define ROKEN_CPP_START extern "C" {
+#define ROKEN_CPP_END }
+#else
+#define ROKEN_CPP_START
+#define ROKEN_CPP_END
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+#ifndef SOMAXCONN
+#define SOMAXCONN 5
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef LOG_DAEMON
+#define openlog(id,option,facility) openlog((id),(option))
+#define LOG_DAEMON 0
+#endif
+#ifndef LOG_ODELAY
+#define LOG_ODELAY 0
+#endif
+#ifndef LOG_NDELAY
+#define LOG_NDELAY 0x08
+#endif
+#ifndef LOG_CONS
+#define LOG_CONS 0
+#endif
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE 003
+#endif
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _PATH_HEQUIV
+#define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN "/var/run/"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024+4)
+#endif
+
+#ifndef SIG_ERR
+#define SIG_ERR ((RETSIGTYPE (*)(int))-1)
+#endif
+
+/*
+ * error code for getipnodeby{name,addr}
+ */
+
+#ifndef HOST_NOT_FOUND
+#define HOST_NOT_FOUND 1
+#endif
+
+#ifndef TRY_AGAIN
+#define TRY_AGAIN 2
+#endif
+
+#ifndef NO_RECOVERY
+#define NO_RECOVERY 3
+#endif
+
+#ifndef NO_DATA
+#define NO_DATA 4
+#endif
+
+#ifndef NO_ADDRESS
+#define NO_ADDRESS NO_DATA
+#endif
+
+/*
+ * error code for getaddrinfo
+ */
+
+#ifndef EAI_NOERROR
+#define EAI_NOERROR 0 /* no error */
+#endif
+
+#ifndef EAI_NONAME
+
+#define EAI_ADDRFAMILY 1 /* address family for nodename not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with nodename */
+#define EAI_NONAME 8 /* nodename nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+
+#endif /* EAI_NONAME */
+
+/* flags for getaddrinfo() */
+
+#ifndef AI_PASSIVE
+#define AI_PASSIVE 0x01
+#define AI_CANONNAME 0x02
+#endif /* AI_PASSIVE */
+
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST 0x04
+#endif
+
+/* flags for getnameinfo() */
+
+#ifndef NI_DGRAM
+#define NI_DGRAM 0x01
+#define NI_NAMEREQD 0x02
+#define NI_NOFQDN 0x04
+#define NI_NUMERICHOST 0x08
+#define NI_NUMERICSERV 0x10
+#endif
+
+/*
+ * constants for getnameinfo
+ */
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+#endif
+
+/*
+ * constants for inet_ntop
+ */
+
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+/*
+ * for shutdown(2)
+ */
+
+#ifndef SHUT_RD
+#define SHUT_RD 0
+#endif
+
+#ifndef SHUT_WR
+#define SHUT_WR 1
+#endif
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+ROKEN_CPP_START
+
+#ifndef IRIX4 /* fix for compiler bug */
+#ifdef RETSIGTYPE
+typedef RETSIGTYPE (*SigAction)(int);
+SigAction signal(int iSig, SigAction pAction); /* BSD compatible */
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+simple_execve(const char*, char*const[], char*const[]);
+
+int ROKEN_LIB_FUNCTION
+simple_execve_timed(const char *, char *const[],
+ char *const [], time_t (*)(void *),
+ void *, time_t);
+int ROKEN_LIB_FUNCTION
+simple_execvp(const char*, char *const[]);
+
+int ROKEN_LIB_FUNCTION
+simple_execvp_timed(const char *, char *const[],
+ time_t (*)(void *), void *, time_t);
+int ROKEN_LIB_FUNCTION
+simple_execlp(const char*, ...);
+
+int ROKEN_LIB_FUNCTION
+simple_execle(const char*, ...);
+
+int ROKEN_LIB_FUNCTION
+simple_execl(const char *file, ...);
+
+int ROKEN_LIB_FUNCTION
+wait_for_process(pid_t);
+
+int ROKEN_LIB_FUNCTION
+wait_for_process_timed(pid_t, time_t (*)(void *),
+ void *, time_t);
+int ROKEN_LIB_FUNCTION
+pipe_execv(FILE**, FILE**, FILE**, const char*, ...);
+
+void ROKEN_LIB_FUNCTION
+print_version(const char *);
+
+ssize_t ROKEN_LIB_FUNCTION
+eread (int fd, void *buf, size_t nbytes);
+
+ssize_t ROKEN_LIB_FUNCTION
+ewrite (int fd, const void *buf, size_t nbytes);
+
+struct hostent;
+
+const char * ROKEN_LIB_FUNCTION
+hostent_find_fqdn (const struct hostent *);
+
+void ROKEN_LIB_FUNCTION
+esetenv(const char *, const char *, int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_address_and_port (struct sockaddr *, const void *, int);
+
+size_t ROKEN_LIB_FUNCTION
+socket_addr_size (const struct sockaddr *);
+
+void ROKEN_LIB_FUNCTION
+socket_set_any (struct sockaddr *, int);
+
+size_t ROKEN_LIB_FUNCTION
+socket_sockaddr_size (const struct sockaddr *);
+
+void * ROKEN_LIB_FUNCTION
+socket_get_address (struct sockaddr *);
+
+int ROKEN_LIB_FUNCTION
+socket_get_port (const struct sockaddr *);
+
+void ROKEN_LIB_FUNCTION
+socket_set_port (struct sockaddr *, int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_portrange (int, int, int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_debug (int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_tos (int, int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_reuseaddr (int, int);
+
+void ROKEN_LIB_FUNCTION
+socket_set_ipv6only (int, int);
+
+char ** ROKEN_LIB_FUNCTION
+vstrcollect(va_list *ap);
+
+char ** ROKEN_LIB_FUNCTION
+strcollect(char *first, ...);
+
+void ROKEN_LIB_FUNCTION
+timevalfix(struct timeval *t1);
+
+void ROKEN_LIB_FUNCTION
+timevaladd(struct timeval *t1, const struct timeval *t2);
+
+void ROKEN_LIB_FUNCTION
+timevalsub(struct timeval *t1, const struct timeval *t2);
+
+char *ROKEN_LIB_FUNCTION
+pid_file_write (const char *progname);
+
+void ROKEN_LIB_FUNCTION
+pid_file_delete (char **);
+
+int ROKEN_LIB_FUNCTION
+read_environment(const char *file, char ***env);
+
+void ROKEN_LIB_FUNCTION
+free_environment(char **);
+
+void ROKEN_LIB_FUNCTION
+warnerr(int doerrno, const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 2, 0)));
+
+void * ROKEN_LIB_FUNCTION
+rk_realloc(void *, size_t);
+
+struct rk_strpool;
+
+char * ROKEN_LIB_FUNCTION
+rk_strpoolcollect(struct rk_strpool *);
+
+struct rk_strpool * ROKEN_LIB_FUNCTION
+rk_strpoolprintf(struct rk_strpool *, const char *, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+void ROKEN_LIB_FUNCTION
+rk_strpoolfree(struct rk_strpool *);
+
+void ROKEN_LIB_FUNCTION
+rk_dumpdata (const char *, const void *, size_t);
+
+ROKEN_CPP_END
+
+#endif /* __ROKEN_COMMON_H__ */
diff --git a/lib/roken/roken.awk b/lib/roken/roken.awk
new file mode 100644
index 0000000000000..e0c19d7823afd
--- /dev/null
+++ b/lib/roken/roken.awk
@@ -0,0 +1,40 @@
+# $Id: roken.awk 15409 2005-06-16 16:29:58Z lha $
+
+BEGIN {
+ print "#ifdef HAVE_CONFIG_H"
+ print "#include <config.h>"
+ print "#endif"
+ print "#include <stdio.h>"
+ print ""
+ print "int main(int argc, char **argv)"
+ print "{"
+ print "puts(\"/* This is an OS dependent, generated file */\");"
+ print "puts(\"\\n\");"
+ print "puts(\"#ifndef __ROKEN_H__\");"
+ print "puts(\"#define __ROKEN_H__\");"
+ print "puts(\"\");"
+}
+
+$1 == "#ifdef" || $1 == "#ifndef" || $1 == "#if" || $1 == "#else" || $1 == "#elif" || $1 == "#endif" {
+ print $0;
+ next
+}
+
+{
+ s = ""
+ for(i = 1; i <= length; i++){
+ x = substr($0, i, 1)
+ if(x == "\"" || x == "\\")
+ s = s "\\";
+ s = s x;
+ }
+ print "puts(\"" s "\");"
+}
+
+END {
+ print "puts(\"#define ROKEN_VERSION \" VERSION );"
+ print "puts(\"\");"
+ print "puts(\"#endif /* __ROKEN_H__ */\");"
+ print "return 0;"
+ print "}"
+}
diff --git a/lib/roken/roken.h.in b/lib/roken/roken.h.in
new file mode 100644
index 0000000000000..cf2ee9ed7bdb8
--- /dev/null
+++ b/lib/roken/roken.h.in
@@ -0,0 +1,706 @@
+/* -*- C -*- */
+/*
+ * Copyright (c) 1995-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: roken.h.in 18612 2006-10-19 16:35:16Z lha $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <string.h>
+#include <signal.h>
+
+#ifdef _AIX
+struct ether_addr;
+struct sockaddr_dl;
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_BIND_BITYPES_H
+#include <bind/bitypes.h>
+#endif
+#ifdef HAVE_NETINET_IN6_MACHTYPES_H
+#include <netinet/in6_machtypes.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <err.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+
+#include <roken-common.h>
+
+ROKEN_CPP_START
+
+#ifdef HAVE_UINTPTR_T
+#define rk_UNCONST(x) ((void *)(uintptr_t)(const void *)(x))
+#else
+#define rk_UNCONST(x) ((void *)(unsigned long)(const void *)(x))
+#endif
+
+#if !defined(HAVE_SETSID) && defined(HAVE__SETSID)
+#define setsid _setsid
+#endif
+
+#ifndef HAVE_PUTENV
+int ROKEN_LIB_FUNCTION putenv(const char *);
+#endif
+
+#if !defined(HAVE_SETENV) || defined(NEED_SETENV_PROTO)
+int ROKEN_LIB_FUNCTION setenv(const char *, const char *, int);
+#endif
+
+#if !defined(HAVE_UNSETENV) || defined(NEED_UNSETENV_PROTO)
+void ROKEN_LIB_FUNCTION unsetenv(const char *);
+#endif
+
+#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO)
+char * ROKEN_LIB_FUNCTION getusershell(void);
+void ROKEN_LIB_FUNCTION endusershell(void);
+#endif
+
+#if !defined(HAVE_SNPRINTF) || defined(NEED_SNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION snprintf (char *, size_t, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+ vsnprintf (char *, size_t, const char *, va_list)
+ __attribute__((format (printf, 3, 0)));
+#endif
+
+#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+ asprintf (char **, const char *, ...)
+ __attribute__ ((format (printf, 2, 3)));
+#endif
+
+#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+ vasprintf (char **, const char *, va_list)
+ __attribute__((format (printf, 2, 0)));
+#endif
+
+#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+ asnprintf (char **, size_t, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+ vasnprintf (char **, size_t, const char *, va_list)
+ __attribute__((format (printf, 3, 0)));
+#endif
+
+#ifndef HAVE_STRDUP
+char * ROKEN_LIB_FUNCTION strdup(const char *);
+#endif
+
+#if !defined(HAVE_STRNDUP) || defined(NEED_STRNDUP_PROTO)
+char * ROKEN_LIB_FUNCTION strndup(const char *, size_t);
+#endif
+
+#ifndef HAVE_STRLWR
+char * ROKEN_LIB_FUNCTION strlwr(char *);
+#endif
+
+#ifndef HAVE_STRNLEN
+size_t ROKEN_LIB_FUNCTION strnlen(const char*, size_t);
+#endif
+
+#if !defined(HAVE_STRSEP) || defined(NEED_STRSEP_PROTO)
+char * ROKEN_LIB_FUNCTION strsep(char**, const char*);
+#endif
+
+#if !defined(HAVE_STRSEP_COPY) || defined(NEED_STRSEP_COPY_PROTO)
+ssize_t ROKEN_LIB_FUNCTION strsep_copy(const char**, const char*, char*, size_t);
+#endif
+
+#ifndef HAVE_STRCASECMP
+int ROKEN_LIB_FUNCTION strcasecmp(const char *, const char *);
+#endif
+
+#ifdef NEED_FCLOSE_PROTO
+int ROKEN_LIB_FUNCTION fclose(FILE *);
+#endif
+
+#ifdef NEED_STRTOK_R_PROTO
+char * ROKEN_LIB_FUNCTION strtok_r(char *, const char *, char **);
+#endif
+
+#ifndef HAVE_STRUPR
+char * ROKEN_LIB_FUNCTION strupr(char *);
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t ROKEN_LIB_FUNCTION strlcpy (char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_STRLCAT
+size_t ROKEN_LIB_FUNCTION strlcat (char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_GETDTABLESIZE
+int ROKEN_LIB_FUNCTION getdtablesize(void);
+#endif
+
+#if !defined(HAVE_STRERROR) && !defined(strerror)
+char * ROKEN_LIB_FUNCTION strerror(int);
+#endif
+
+#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO)
+/* This causes a fatal error under Psoriasis */
+#if !(defined(SunOS) && (SunOS >= 50))
+const char * ROKEN_LIB_FUNCTION hstrerror(int);
+#endif
+#endif
+
+#if !HAVE_DECL_H_ERRNO
+extern int h_errno;
+#endif
+
+#if !defined(HAVE_INET_ATON) || defined(NEED_INET_ATON_PROTO)
+int ROKEN_LIB_FUNCTION inet_aton(const char *, struct in_addr *);
+#endif
+
+#ifndef HAVE_INET_NTOP
+const char * ROKEN_LIB_FUNCTION
+inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifndef HAVE_INET_PTON
+int ROKEN_LIB_FUNCTION
+inet_pton(int, const char *, void *);
+#endif
+
+#if !defined(HAVE_GETCWD)
+char* ROKEN_LIB_FUNCTION getcwd(char *, size_t);
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+struct passwd * ROKEN_LIB_FUNCTION k_getpwnam (const char *);
+struct passwd * ROKEN_LIB_FUNCTION k_getpwuid (uid_t);
+#endif
+
+const char * ROKEN_LIB_FUNCTION get_default_username (void);
+
+#ifndef HAVE_SETEUID
+int ROKEN_LIB_FUNCTION seteuid(uid_t);
+#endif
+
+#ifndef HAVE_SETEGID
+int ROKEN_LIB_FUNCTION setegid(gid_t);
+#endif
+
+#ifndef HAVE_LSTAT
+int ROKEN_LIB_FUNCTION lstat(const char *, struct stat *);
+#endif
+
+#if !defined(HAVE_MKSTEMP) || defined(NEED_MKSTEMP_PROTO)
+int ROKEN_LIB_FUNCTION mkstemp(char *);
+#endif
+
+#ifndef HAVE_CGETENT
+int ROKEN_LIB_FUNCTION cgetent(char **, char **, const char *);
+int ROKEN_LIB_FUNCTION cgetstr(char *, const char *, char **);
+#endif
+
+#ifndef HAVE_INITGROUPS
+int ROKEN_LIB_FUNCTION initgroups(const char *, gid_t);
+#endif
+
+#ifndef HAVE_FCHOWN
+int ROKEN_LIB_FUNCTION fchown(int, uid_t, gid_t);
+#endif
+
+#if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO)
+int ROKEN_LIB_FUNCTION daemon(int, int);
+#endif
+
+#ifndef HAVE_INNETGR
+int ROKEN_LIB_FUNCTION innetgr(const char *, const char *,
+ const char *, const char *);
+#endif
+
+#ifndef HAVE_CHOWN
+int ROKEN_LIB_FUNCTION chown(const char *, uid_t, gid_t);
+#endif
+
+#ifndef HAVE_RCMD
+int ROKEN_LIB_FUNCTION
+ rcmd(char **, unsigned short, const char *,
+ const char *, const char *, int *);
+#endif
+
+#if !defined(HAVE_INNETGR) || defined(NEED_INNETGR_PROTO)
+int ROKEN_LIB_FUNCTION innetgr(const char*, const char*,
+ const char*, const char*);
+#endif
+
+#ifndef HAVE_IRUSEROK
+int ROKEN_LIB_FUNCTION iruserok(unsigned, int,
+ const char *, const char *);
+#endif
+
+#if !defined(HAVE_GETHOSTNAME) || defined(NEED_GETHOSTNAME_PROTO)
+int ROKEN_LIB_FUNCTION gethostname(char *, int);
+#endif
+
+#ifndef HAVE_WRITEV
+ssize_t ROKEN_LIB_FUNCTION
+writev(int, const struct iovec *, int);
+#endif
+
+#ifndef HAVE_READV
+ssize_t ROKEN_LIB_FUNCTION
+readv(int, const struct iovec *, int);
+#endif
+
+#ifndef HAVE_MKSTEMP
+int ROKEN_LIB_FUNCTION
+mkstemp(char *);
+#endif
+
+#ifndef HAVE_PIDFILE
+void ROKEN_LIB_FUNCTION pidfile (const char*);
+#endif
+
+#ifndef HAVE_BSWAP32
+unsigned int ROKEN_LIB_FUNCTION bswap32(unsigned int);
+#endif
+
+#ifndef HAVE_BSWAP16
+unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short);
+#endif
+
+#ifndef HAVE_FLOCK
+#ifndef LOCK_SH
+#define LOCK_SH 1 /* Shared lock */
+#endif
+#ifndef LOCK_EX
+#define LOCK_EX 2 /* Exclusive lock */
+#endif
+#ifndef LOCK_NB
+#define LOCK_NB 4 /* Don't block when locking */
+#endif
+#ifndef LOCK_UN
+#define LOCK_UN 8 /* Unlock */
+#endif
+
+int flock(int fd, int operation);
+#endif /* HAVE_FLOCK */
+
+time_t ROKEN_LIB_FUNCTION tm2time (struct tm, int);
+
+int ROKEN_LIB_FUNCTION unix_verify_user(char *, char *);
+
+int ROKEN_LIB_FUNCTION roken_concat (char *, size_t, ...);
+
+size_t ROKEN_LIB_FUNCTION roken_mconcat (char **, size_t, ...);
+
+int ROKEN_LIB_FUNCTION roken_vconcat (char *, size_t, va_list);
+
+size_t ROKEN_LIB_FUNCTION
+ roken_vmconcat (char **, size_t, va_list);
+
+ssize_t ROKEN_LIB_FUNCTION net_write (int, const void *, size_t);
+
+ssize_t ROKEN_LIB_FUNCTION net_read (int, void *, size_t);
+
+int ROKEN_LIB_FUNCTION issuid(void);
+
+#ifndef HAVE_STRUCT_WINSIZE
+struct winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+#endif
+
+int ROKEN_LIB_FUNCTION get_window_size(int fd, struct winsize *);
+
+#ifndef HAVE_VSYSLOG
+void ROKEN_LIB_FUNCTION vsyslog(int, const char *, va_list);
+#endif
+
+#if !HAVE_DECL_OPTARG
+extern char *optarg;
+#endif
+#if !HAVE_DECL_OPTIND
+extern int optind;
+#endif
+#if !HAVE_DECL_OPTERR
+extern int opterr;
+#endif
+
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
+#ifndef HAVE_GETIPNODEBYNAME
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyname (const char *, int, int, int *);
+#endif
+
+#ifndef HAVE_GETIPNODEBYADDR
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyaddr (const void *, size_t, int, int *);
+#endif
+
+#ifndef HAVE_FREEHOSTENT
+void ROKEN_LIB_FUNCTION
+freehostent (struct hostent *);
+#endif
+
+#ifndef HAVE_COPYHOSTENT
+struct hostent * ROKEN_LIB_FUNCTION
+copyhostent (const struct hostent *);
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+
+#ifndef HAVE_SA_FAMILY_T
+typedef unsigned short sa_family_t;
+#endif
+
+#ifdef HAVE_IPV6
+#define _SS_MAXSIZE sizeof(struct sockaddr_in6)
+#else
+#define _SS_MAXSIZE sizeof(struct sockaddr_in)
+#endif
+
+#define _SS_ALIGNSIZE sizeof(unsigned long)
+
+#if HAVE_STRUCT_SOCKADDR_SA_LEN
+
+typedef unsigned char roken_sa_family_t;
+
+#define _SS_PAD1SIZE ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t) - sizeof(unsigned char)) % _SS_ALIGNSIZE)
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + sizeof(unsigned char) + _SS_PAD1SIZE + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+ unsigned char ss_len;
+ roken_sa_family_t ss_family;
+ char __ss_pad1[_SS_PAD1SIZE];
+ unsigned long __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1];
+};
+
+#else /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+typedef unsigned short roken_sa_family_t;
+
+#define _SS_PAD1SIZE ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t)) % _SS_ALIGNSIZE)
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + _SS_PAD1SIZE + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+ roken_sa_family_t ss_family;
+ char __ss_pad1[_SS_PAD1SIZE];
+ unsigned long __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1];
+};
+
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+
+#ifndef HAVE_GETADDRINFO
+int ROKEN_LIB_FUNCTION
+getaddrinfo(const char *,
+ const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+#endif
+
+#ifndef HAVE_GETNAMEINFO
+int ROKEN_LIB_FUNCTION
+getnameinfo(const struct sockaddr *, socklen_t,
+ char *, size_t,
+ char *, size_t,
+ int);
+#endif
+
+#ifndef HAVE_FREEADDRINFO
+void ROKEN_LIB_FUNCTION
+freeaddrinfo(struct addrinfo *);
+#endif
+
+#ifndef HAVE_GAI_STRERROR
+const char * ROKEN_LIB_FUNCTION
+gai_strerror(int);
+#endif
+
+int ROKEN_LIB_FUNCTION
+getnameinfo_verified(const struct sockaddr *, socklen_t,
+ char *, size_t,
+ char *, size_t,
+ int);
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec(const char *, int, struct addrinfo **);
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **);
+
+#ifndef HAVE_STRFTIME
+size_t ROKEN_LIB_FUNCTION
+strftime (char *, size_t, const char *, const struct tm *);
+#endif
+
+#ifndef HAVE_STRPTIME
+char * ROKEN_LIB_FUNCTION
+strptime (const char *, const char *, struct tm *);
+#endif
+
+#ifndef HAVE_EMALLOC
+void * ROKEN_LIB_FUNCTION emalloc (size_t);
+#endif
+#ifndef HAVE_ECALLOC
+void * ROKEN_LIB_FUNCTION ecalloc(size_t, size_t);
+#endif
+#ifndef HAVE_EREALLOC
+void * ROKEN_LIB_FUNCTION erealloc (void *, size_t);
+#endif
+#ifndef HAVE_ESTRDUP
+char * ROKEN_LIB_FUNCTION estrdup (const char *);
+#endif
+
+/*
+ * kludges and such
+ */
+
+#if 1
+int ROKEN_LIB_FUNCTION
+roken_gethostby_setup(const char*, const char*);
+struct hostent* ROKEN_LIB_FUNCTION
+roken_gethostbyname(const char*);
+struct hostent* ROKEN_LIB_FUNCTION
+roken_gethostbyaddr(const void*, size_t, int);
+#else
+#ifdef GETHOSTBYNAME_PROTO_COMPATIBLE
+#define roken_gethostbyname(x) gethostbyname(x)
+#else
+#define roken_gethostbyname(x) gethostbyname((char *)x)
+#endif
+
+#ifdef GETHOSTBYADDR_PROTO_COMPATIBLE
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr(a, l, t)
+#else
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr((char *)a, l, t)
+#endif
+#endif
+
+#ifdef GETSERVBYNAME_PROTO_COMPATIBLE
+#define roken_getservbyname(x,y) getservbyname(x,y)
+#else
+#define roken_getservbyname(x,y) getservbyname((char *)x, (char *)y)
+#endif
+
+#ifdef OPENLOG_PROTO_COMPATIBLE
+#define roken_openlog(a,b,c) openlog(a,b,c)
+#else
+#define roken_openlog(a,b,c) openlog((char *)a,b,c)
+#endif
+
+#ifdef GETSOCKNAME_PROTO_COMPATIBLE
+#define roken_getsockname(a,b,c) getsockname(a,b,c)
+#else
+#define roken_getsockname(a,b,c) getsockname(a, b, (void*)c)
+#endif
+
+#ifndef HAVE_SETPROGNAME
+void ROKEN_LIB_FUNCTION setprogname(const char *);
+#endif
+
+#ifndef HAVE_GETPROGNAME
+const char * ROKEN_LIB_FUNCTION getprogname(void);
+#endif
+
+#if !defined(HAVE_SETPROGNAME) && !defined(HAVE_GETPROGNAME) && !HAVE_DECL___PROGNAME
+extern const char *__progname;
+#endif
+
+void ROKEN_LIB_FUNCTION mini_inetd_addrinfo (struct addrinfo*);
+void ROKEN_LIB_FUNCTION mini_inetd (int);
+
+#ifndef HAVE_LOCALTIME_R
+struct tm * ROKEN_LIB_FUNCTION
+localtime_r(const time_t *, struct tm *);
+#endif
+
+#if !defined(HAVE_STRSVIS) || defined(NEED_STRSVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strsvis(char *, const char *, int, const char *);
+#endif
+
+#if !defined(HAVE_STRUNVIS) || defined(NEED_STRUNVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strunvis(char *, const char *);
+#endif
+
+#if !defined(HAVE_STRVIS) || defined(NEED_STRVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strvis(char *, const char *, int);
+#endif
+
+#if !defined(HAVE_STRVISX) || defined(NEED_STRVISX_PROTO)
+int ROKEN_LIB_FUNCTION
+strvisx(char *, const char *, size_t, int);
+#endif
+
+#if !defined(HAVE_SVIS) || defined(NEED_SVIS_PROTO)
+char * ROKEN_LIB_FUNCTION
+svis(char *, int, int, int, const char *);
+#endif
+
+#if !defined(HAVE_UNVIS) || defined(NEED_UNVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+unvis(char *, int, int *, int);
+#endif
+
+#if !defined(HAVE_VIS) || defined(NEED_VIS_PROTO)
+char * ROKEN_LIB_FUNCTION
+vis(char *, int, int, int);
+#endif
+
+#if !defined(HAVE_CLOSEFROM)
+int ROKEN_LIB_FUNCTION
+closefrom(int);
+#endif
+
+#if !defined(HAVE_TIMEGM)
+#define timegm rk_timegm
+time_t ROKEN_LIB_FUNCTION
+rk_timegm(struct tm *tm);
+#endif
+
+#ifdef SOCKET_WRAPPER_REPLACE
+#include <socket_wrapper.h>
+#endif
+
+ROKEN_CPP_END
diff --git a/lib/roken/roken_gethostby.c b/lib/roken/roken_gethostby.c
new file mode 100644
index 0000000000000..ff0af86ef4c1f
--- /dev/null
+++ b/lib/roken/roken_gethostby.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: roken_gethostby.c 21157 2007-06-18 22:03:13Z lha $");
+#endif
+
+#include "roken.h"
+
+#undef roken_gethostbyname
+#undef roken_gethostbyaddr
+
+static struct sockaddr_in dns_addr;
+static char *dns_req;
+
+static int
+make_address(const char *address, struct in_addr *ip)
+{
+ if(inet_aton(address, ip) == 0){
+ /* try to resolve as hostname, it might work if the address we
+ are trying to lookup is local, for instance a web proxy */
+ struct hostent *he = gethostbyname(address);
+ if(he) {
+ unsigned char *p = (unsigned char*)he->h_addr;
+ ip->s_addr = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+setup_int(const char *proxy_host, short proxy_port,
+ const char *dns_host, short dns_port,
+ const char *dns_path)
+{
+ memset(&dns_addr, 0, sizeof(dns_addr));
+ if(dns_req)
+ free(dns_req);
+ if(proxy_host) {
+ if(make_address(proxy_host, &dns_addr.sin_addr) != 0)
+ return -1;
+ dns_addr.sin_port = htons(proxy_port);
+ asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path);
+ } else {
+ if(make_address(dns_host, &dns_addr.sin_addr) != 0)
+ return -1;
+ dns_addr.sin_port = htons(dns_port);
+ asprintf(&dns_req, "%s", dns_path);
+ }
+ dns_addr.sin_family = AF_INET;
+ return 0;
+}
+
+static void
+split_spec(const char *spec, char **host, int *port, char **path, int def_port)
+{
+ char *p;
+ *host = strdup(spec);
+ p = strchr(*host, ':');
+ if(p) {
+ *p++ = '\0';
+ if(sscanf(p, "%d", port) != 1)
+ *port = def_port;
+ } else
+ *port = def_port;
+ p = strchr(p ? p : *host, '/');
+ if(p) {
+ if(path)
+ *path = strdup(p);
+ *p = '\0';
+ }else
+ if(path)
+ *path = NULL;
+}
+
+
+int ROKEN_LIB_FUNCTION
+roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
+{
+ char *proxy_host = NULL;
+ int proxy_port = 0;
+ char *dns_host, *dns_path;
+ int dns_port;
+
+ int ret = -1;
+
+ split_spec(dns_spec, &dns_host, &dns_port, &dns_path, 80);
+ if(dns_path == NULL)
+ goto out;
+ if(proxy_spec)
+ split_spec(proxy_spec, &proxy_host, &proxy_port, NULL, 80);
+ ret = setup_int(proxy_host, proxy_port, dns_host, dns_port, dns_path);
+out:
+ free(proxy_host);
+ free(dns_host);
+ free(dns_path);
+ return ret;
+}
+
+
+/* Try to lookup a name or an ip-address using http as transport
+ mechanism. See the end of this file for an example program. */
+static struct hostent*
+roken_gethostby(const char *hostname)
+{
+ int s;
+ struct sockaddr_in addr;
+ char *request;
+ char buf[1024];
+ int offset = 0;
+ int n;
+ char *p, *foo;
+
+ if(dns_addr.sin_family == 0)
+ return NULL; /* no configured host */
+ addr = dns_addr;
+ asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname);
+ if(request == NULL)
+ return NULL;
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if(s < 0) {
+ free(request);
+ return NULL;
+ }
+ if(connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ close(s);
+ free(request);
+ return NULL;
+ }
+ if(write(s, request, strlen(request)) != strlen(request)) {
+ close(s);
+ free(request);
+ return NULL;
+ }
+ free(request);
+ while(1) {
+ n = read(s, buf + offset, sizeof(buf) - offset);
+ if(n <= 0)
+ break;
+ offset += n;
+ }
+ buf[offset] = '\0';
+ close(s);
+ p = strstr(buf, "\r\n\r\n"); /* find end of header */
+ if(p) p += 4;
+ else return NULL;
+ foo = NULL;
+ p = strtok_r(p, " \t\r\n", &foo);
+ if(p == NULL)
+ return NULL;
+ {
+ /* make a hostent to return */
+#define MAX_ADDRS 16
+ static struct hostent he;
+ static char addrs[4 * MAX_ADDRS];
+ static char *addr_list[MAX_ADDRS + 1];
+ int num_addrs = 0;
+
+ he.h_name = p;
+ he.h_aliases = NULL;
+ he.h_addrtype = AF_INET;
+ he.h_length = 4;
+
+ while((p = strtok_r(NULL, " \t\r\n", &foo)) && num_addrs < MAX_ADDRS) {
+ struct in_addr ip;
+ inet_aton(p, &ip);
+ ip.s_addr = ntohl(ip.s_addr);
+ addr_list[num_addrs] = &addrs[num_addrs * 4];
+ addrs[num_addrs * 4 + 0] = (ip.s_addr >> 24) & 0xff;
+ addrs[num_addrs * 4 + 1] = (ip.s_addr >> 16) & 0xff;
+ addrs[num_addrs * 4 + 2] = (ip.s_addr >> 8) & 0xff;
+ addrs[num_addrs * 4 + 3] = (ip.s_addr >> 0) & 0xff;
+ addr_list[++num_addrs] = NULL;
+ }
+ he.h_addr_list = addr_list;
+ return &he;
+ }
+}
+
+struct hostent*
+roken_gethostbyname(const char *hostname)
+{
+ struct hostent *he;
+ he = gethostbyname(hostname);
+ if(he)
+ return he;
+ return roken_gethostby(hostname);
+}
+
+struct hostent* ROKEN_LIB_FUNCTION
+roken_gethostbyaddr(const void *addr, size_t len, int type)
+{
+ struct in_addr a;
+ const char *p;
+ struct hostent *he;
+ he = gethostbyaddr(addr, len, type);
+ if(he)
+ return he;
+ if(type != AF_INET || len != 4)
+ return NULL;
+ p = addr;
+ a.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+ return roken_gethostby(inet_ntoa(a));
+}
+
+#if 0
+
+/* this program can be used as a cgi `script' to lookup names and
+ ip-addresses */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <sys/param.h>
+
+int
+main(int argc, char **argv)
+{
+ char *query = getenv("QUERY_STRING");
+ char host[MAXHOSTNAMELEN];
+ int i;
+ struct hostent *he;
+
+ printf("Content-type: text/plain\n\n");
+ if(query == NULL)
+ exit(0);
+ he = gethostbyname(query);
+ strncpy(host, he->h_name, sizeof(host));
+ host[sizeof(host) - 1] = '\0';
+ he = gethostbyaddr(he->h_addr, he->h_length, AF_INET);
+ printf("%s\n", he->h_name);
+ for(i = 0; he->h_addr_list[i]; i++) {
+ struct in_addr ip;
+ unsigned char *p = (unsigned char*)he->h_addr_list[i];
+ ip.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+ printf("%s\n", inet_ntoa(ip));
+ }
+ exit(0);
+}
+
+#endif
diff --git a/lib/roken/rtbl.3 b/lib/roken/rtbl.3
new file mode 100644
index 0000000000000..ccdc73f77a313
--- /dev/null
+++ b/lib/roken/rtbl.3
@@ -0,0 +1,201 @@
+.\" Copyright (c) 2004 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+.\" $Id: rtbl.3 22088 2007-11-25 14:10:15Z lha $
+.\"
+.Dd June 26, 2004
+.Dt RTBL 3
+.Os HEIMDAL
+.Sh NAME
+.Nm rtbl_create ,
+.Nm rtbl_destroy ,
+.Nm rtbl_set_flags ,
+.Nm rtbl_get_flags ,
+.Nm rtbl_set_prefix ,
+.Nm rtbl_set_separator ,
+.Nm rtbl_set_column_prefix ,
+.Nm rtbl_set_column_affix_by_id ,
+.Nm rtbl_add_column ,
+.Nm rtbl_add_column_by_id ,
+.Nm rtbl_add_column_entry ,
+.Nm rtbl_add_column_entry_by_id ,
+.Nm rtbl_new_row ,
+.Nm rtbl_format
+.Nd format data in simple tables
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.In rtbl.h
+.Ft int
+.Fn rtbl_add_column "rtbl_t table" "const char *column_name" "unsigned int flags"
+.Ft int
+.Fn rtbl_add_column_by_id "rtbl_t table" "unsigned int column_id" "const char *column_header" "unsigned int flags"
+.Ft int
+.Fn rtbl_add_column_entry "rtbl_t table" "const char *column_name" "const char *cell_entry"
+.Ft int
+.Fn rtbl_add_column_entry_by_id "rtbl_t table" "unsigned int column_id" "const char *cell_entry"
+.Ft rtbl_t
+.Fn rtbl_create "void"
+.Ft void
+.Fn rtbl_destroy "rtbl_t table"
+.Ft int
+.Fn rtbl_new_row "rtbl_t table"
+.Ft int
+.Fn rtbl_set_column_affix_by_id "rtbl_t table" "unsigned int column_id "const char *prefix" "const char *suffix"
+.Ft int
+.Fn rtbl_set_column_prefix "rtbl_t table" "const char *column_name" "const char *prefix"
+.Ft "unsigned int"
+.Fn rtbl_get_flags "rtbl_t table"
+.Ft void
+.Fn rtbl_set_flags "rtbl_t table" "unsigned int flags"
+.Ft int
+.Fn rtbl_set_prefix "rtbl_t table" "const char *prefix"
+.Ft int
+.Fn rtbl_set_separator "rtbl_t table" "const char *separator"
+.Ft int
+.Fn rtbl_format "rtbl_t table "FILE *file"
+.Sh DESCRIPTION
+This set of functions assemble a simple table consisting of rows and
+columns, allowing it to be printed with certain options. Typical use
+would be output from tools such as
+.Xr ls 1
+or
+.Xr netstat 1 ,
+where you have a fixed number of columns, but don't know the column
+widthds before hand.
+.Pp
+A table is created with
+.Fn rtbl_create
+and destroyed with
+.Fn rtbl_destroy .
+.Pp
+Global flags on the table are set with
+.Fa rtbl_set_flags
+and retrieved with
+.Fa rtbl_get_flags .
+At present the only defined flag is
+.Dv RTBL_HEADER_STYLE_NONE
+which suppresses printing the header.
+.Pp
+Before adding data to the table, one or more columns need to be
+created. This would normally be done with
+.Fn rtbl_add_column_by_id ,
+.Fa column_id
+is any number of your choice (it's used only to identify columns),
+.Fa column_header
+is the header to print at the top of the column, and
+.Fa flags
+are flags specific to this column. Currently the only defined flag is
+.Dv RTBL_ALIGN_RIGHT ,
+aligning column entries to the right. Columns are printed in the order
+they are added.
+.Pp
+There's also a way to add columns by column name with
+.Fn rtbl_add_column ,
+but this is less flexible (you need unique header names), and is
+considered deprecated.
+.Pp
+To add data to a column you use
+.Fn rtbl_add_column_entry_by_id ,
+where the
+.Fa column_id
+is the same as when the column was added (adding data to a
+non-existent column is undefined), and
+.Fa cell_entry
+is whatever string you wish to include in that cell. It should not
+include newlines.
+For columns added with
+.Fn rtbl_add_column
+you must use
+.Fn rtbl_add_column_entry
+instead.
+.Pp
+.Fn rtbl_new_row
+fills all columns with blank entries until they all have the same
+number of rows.
+.Pp
+Each column can have a separate prefix and suffix, set with
+.Fa rtbl_set_column_affix_by_id ;
+.Fa rtbl_set_column_prefix
+allows setting the prefix only by column name. In addition to this,
+columns may be separated by a string set with
+.Fa rtbl_set_separator ( Ns
+by default columns are not seprated by anything).
+.Pp
+The finished table is printed to
+.Fa file
+with
+.Fa rtbl_format .
+.Sh EXAMPLES
+This program:
+.Bd -literal -offset xxxx
+#include <stdio.h>
+#include <rtbl.h>
+int
+main(int argc, char **argv)
+{
+ rtbl_t table;
+ table = rtbl_create();
+ rtbl_set_separator(table, " ");
+ rtbl_add_column_by_id(table, 0, "Column A", 0);
+ rtbl_add_column_by_id(table, 1, "Column B", RTBL_ALIGN_RIGHT);
+ rtbl_add_column_by_id(table, 2, "Column C", 0);
+ rtbl_add_column_entry_by_id(table, 0, "A-1");
+ rtbl_add_column_entry_by_id(table, 0, "A-2");
+ rtbl_add_column_entry_by_id(table, 0, "A-3");
+ rtbl_add_column_entry_by_id(table, 1, "B-1");
+ rtbl_add_column_entry_by_id(table, 2, "C-1");
+ rtbl_add_column_entry_by_id(table, 2, "C-2");
+ rtbl_add_column_entry_by_id(table, 1, "B-2");
+ rtbl_add_column_entry_by_id(table, 1, "B-3");
+ rtbl_add_column_entry_by_id(table, 2, "C-3");
+ rtbl_add_column_entry_by_id(table, 0, "A-4");
+ rtbl_new_row(table);
+ rtbl_add_column_entry_by_id(table, 1, "B-4");
+ rtbl_new_row(table);
+ rtbl_add_column_entry_by_id(table, 2, "C-4");
+ rtbl_new_row(table);
+ rtbl_format(table, stdout);
+ rtbl_destroy(table);
+ return 0;
+}
+.Ed
+.Pp
+will output the following:
+.Bd -literal -offset xxxx
+Column A Column B Column C
+A-1 B-1 C-1
+A-2 B-2 C-2
+A-3 B-3 C-3
+A-4
+ B-4
+ C-4
+.Ed
+.\" .Sh SEE ALSO
diff --git a/lib/roken/rtbl.c b/lib/roken/rtbl.c
new file mode 100644
index 0000000000000..dd4328f362089
--- /dev/null
+++ b/lib/roken/rtbl.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2000, 2002, 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID ("$Id: rtbl.c 17758 2006-06-30 13:41:40Z lha $");
+#endif
+#include "roken.h"
+#include "rtbl.h"
+
+struct column_entry {
+ char *data;
+};
+
+struct column_data {
+ char *header;
+ char *prefix;
+ int width;
+ unsigned flags;
+ size_t num_rows;
+ struct column_entry *rows;
+ unsigned int column_id;
+ char *suffix;
+};
+
+struct rtbl_data {
+ char *column_prefix;
+ size_t num_columns;
+ struct column_data **columns;
+ unsigned int flags;
+ char *column_separator;
+};
+
+rtbl_t ROKEN_LIB_FUNCTION
+rtbl_create (void)
+{
+ return calloc (1, sizeof (struct rtbl_data));
+}
+
+void ROKEN_LIB_FUNCTION
+rtbl_set_flags (rtbl_t table, unsigned int flags)
+{
+ table->flags = flags;
+}
+
+unsigned int ROKEN_LIB_FUNCTION
+rtbl_get_flags (rtbl_t table)
+{
+ return table->flags;
+}
+
+static struct column_data *
+rtbl_get_column_by_id (rtbl_t table, unsigned int id)
+{
+ int i;
+ for(i = 0; i < table->num_columns; i++)
+ if(table->columns[i]->column_id == id)
+ return table->columns[i];
+ return NULL;
+}
+
+static struct column_data *
+rtbl_get_column (rtbl_t table, const char *column)
+{
+ int i;
+ for(i = 0; i < table->num_columns; i++)
+ if(strcmp(table->columns[i]->header, column) == 0)
+ return table->columns[i];
+ return NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+rtbl_destroy (rtbl_t table)
+{
+ int i, j;
+
+ for (i = 0; i < table->num_columns; i++) {
+ struct column_data *c = table->columns[i];
+
+ for (j = 0; j < c->num_rows; j++)
+ free (c->rows[j].data);
+ free (c->rows);
+ free (c->header);
+ free (c->prefix);
+ free (c->suffix);
+ free (c);
+ }
+ free (table->column_prefix);
+ free (table->column_separator);
+ free (table->columns);
+ free (table);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_by_id (rtbl_t table, unsigned int id,
+ const char *header, unsigned int flags)
+{
+ struct column_data *col, **tmp;
+
+ tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp));
+ if (tmp == NULL)
+ return ENOMEM;
+ table->columns = tmp;
+ col = malloc (sizeof (*col));
+ if (col == NULL)
+ return ENOMEM;
+ col->header = strdup (header);
+ if (col->header == NULL) {
+ free (col);
+ return ENOMEM;
+ }
+ col->prefix = NULL;
+ col->width = 0;
+ col->flags = flags;
+ col->num_rows = 0;
+ col->rows = NULL;
+ col->column_id = id;
+ col->suffix = NULL;
+ table->columns[table->num_columns++] = col;
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
+{
+ return rtbl_add_column_by_id(table, 0, header, flags);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_new_row(rtbl_t table)
+{
+ size_t max_rows = 0;
+ size_t c;
+ for (c = 0; c < table->num_columns; c++)
+ if(table->columns[c]->num_rows > max_rows)
+ max_rows = table->columns[c]->num_rows;
+ for (c = 0; c < table->num_columns; c++) {
+ struct column_entry *tmp;
+
+ if(table->columns[c]->num_rows == max_rows)
+ continue;
+ tmp = realloc(table->columns[c]->rows,
+ max_rows * sizeof(table->columns[c]->rows));
+ if(tmp == NULL)
+ return ENOMEM;
+ table->columns[c]->rows = tmp;
+ while(table->columns[c]->num_rows < max_rows) {
+ if((tmp[table->columns[c]->num_rows++].data = strdup("")) == NULL)
+ return ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static void
+column_compute_width (rtbl_t table, struct column_data *column)
+{
+ int i;
+
+ if(table->flags & RTBL_HEADER_STYLE_NONE)
+ column->width = 0;
+ else
+ column->width = strlen (column->header);
+ for (i = 0; i < column->num_rows; i++)
+ column->width = max (column->width, strlen (column->rows[i].data));
+}
+
+/* DEPRECATED */
+int ROKEN_LIB_FUNCTION
+rtbl_set_prefix (rtbl_t table, const char *prefix)
+{
+ if (table->column_prefix)
+ free (table->column_prefix);
+ table->column_prefix = strdup (prefix);
+ if (table->column_prefix == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_separator (rtbl_t table, const char *separator)
+{
+ if (table->column_separator)
+ free (table->column_separator);
+ table->column_separator = strdup (separator);
+ if (table->column_separator == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_prefix (rtbl_t table, const char *column,
+ const char *prefix)
+{
+ struct column_data *c = rtbl_get_column (table, column);
+
+ if (c == NULL)
+ return -1;
+ if (c->prefix)
+ free (c->prefix);
+ c->prefix = strdup (prefix);
+ if (c->prefix == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_affix_by_id(rtbl_t table, unsigned int id,
+ const char *prefix, const char *suffix)
+{
+ struct column_data *c = rtbl_get_column_by_id (table, id);
+
+ if (c == NULL)
+ return -1;
+ if (c->prefix)
+ free (c->prefix);
+ if(prefix == NULL)
+ c->prefix = NULL;
+ else {
+ c->prefix = strdup (prefix);
+ if (c->prefix == NULL)
+ return ENOMEM;
+ }
+
+ if (c->suffix)
+ free (c->suffix);
+ if(suffix == NULL)
+ c->suffix = NULL;
+ else {
+ c->suffix = strdup (suffix);
+ if (c->suffix == NULL)
+ return ENOMEM;
+ }
+ return 0;
+}
+
+
+static const char *
+get_column_prefix (rtbl_t table, struct column_data *c)
+{
+ if (c == NULL)
+ return "";
+ if (c->prefix)
+ return c->prefix;
+ if (table->column_prefix)
+ return table->column_prefix;
+ return "";
+}
+
+static const char *
+get_column_suffix (rtbl_t table, struct column_data *c)
+{
+ if (c && c->suffix)
+ return c->suffix;
+ return "";
+}
+
+static int
+add_column_entry (struct column_data *c, const char *data)
+{
+ struct column_entry row, *tmp;
+
+ row.data = strdup (data);
+ if (row.data == NULL)
+ return ENOMEM;
+ tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp));
+ if (tmp == NULL) {
+ free (row.data);
+ return ENOMEM;
+ }
+ c->rows = tmp;
+ c->rows[c->num_rows++] = row;
+ return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry_by_id (rtbl_t table, unsigned int id, const char *data)
+{
+ struct column_data *c = rtbl_get_column_by_id (table, id);
+
+ if (c == NULL)
+ return -1;
+
+ return add_column_entry(c, data);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entryv_by_id (rtbl_t table, unsigned int id,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vasprintf(&str, fmt, ap);
+ va_end(ap);
+ if (ret == -1)
+ return -1;
+ ret = rtbl_add_column_entry_by_id(table, id, str);
+ free(str);
+ return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
+{
+ struct column_data *c = rtbl_get_column (table, column);
+
+ if (c == NULL)
+ return -1;
+
+ return add_column_entry(c, data);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entryv (rtbl_t table, const char *column, const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vasprintf(&str, fmt, ap);
+ va_end(ap);
+ if (ret == -1)
+ return -1;
+ ret = rtbl_add_column_entry(table, column, str);
+ free(str);
+ return ret;
+}
+
+
+int ROKEN_LIB_FUNCTION
+rtbl_format (rtbl_t table, FILE * f)
+{
+ int i, j;
+
+ for (i = 0; i < table->num_columns; i++)
+ column_compute_width (table, table->columns[i]);
+ if((table->flags & RTBL_HEADER_STYLE_NONE) == 0) {
+ for (i = 0; i < table->num_columns; i++) {
+ struct column_data *c = table->columns[i];
+
+ if(table->column_separator != NULL && i > 0)
+ fprintf (f, "%s", table->column_separator);
+ fprintf (f, "%s", get_column_prefix (table, c));
+ if(i == table->num_columns - 1 && c->suffix == NULL)
+ /* last column, so no need to pad with spaces */
+ fprintf (f, "%-*s", 0, c->header);
+ else
+ fprintf (f, "%-*s", (int)c->width, c->header);
+ fprintf (f, "%s", get_column_suffix (table, c));
+ }
+ fprintf (f, "\n");
+ }
+
+ for (j = 0;; j++) {
+ int flag = 0;
+
+ /* are there any more rows left? */
+ for (i = 0; flag == 0 && i < table->num_columns; ++i) {
+ struct column_data *c = table->columns[i];
+
+ if (c->num_rows > j) {
+ ++flag;
+ break;
+ }
+ }
+ if (flag == 0)
+ break;
+
+ for (i = 0; i < table->num_columns; i++) {
+ int w;
+ struct column_data *c = table->columns[i];
+
+ if(table->column_separator != NULL && i > 0)
+ fprintf (f, "%s", table->column_separator);
+
+ w = c->width;
+
+ if ((c->flags & RTBL_ALIGN_RIGHT) == 0) {
+ if(i == table->num_columns - 1 && c->suffix == NULL)
+ /* last column, so no need to pad with spaces */
+ w = 0;
+ else
+ w = -w;
+ }
+ fprintf (f, "%s", get_column_prefix (table, c));
+ if (c->num_rows <= j)
+ fprintf (f, "%*s", w, "");
+ else
+ fprintf (f, "%*s", w, c->rows[j].data);
+ fprintf (f, "%s", get_column_suffix (table, c));
+ }
+ fprintf (f, "\n");
+ }
+ return 0;
+}
+
+#ifdef TEST
+int
+main (int argc, char **argv)
+{
+ rtbl_t table;
+
+ table = rtbl_create ();
+ rtbl_add_column_by_id (table, 0, "Issued", 0);
+ rtbl_add_column_by_id (table, 1, "Expires", 0);
+ rtbl_add_column_by_id (table, 2, "Foo", RTBL_ALIGN_RIGHT);
+ rtbl_add_column_by_id (table, 3, "Principal", 0);
+
+ rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
+ rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
+ rtbl_add_column_entry_by_id (table, 2, "73");
+ rtbl_add_column_entry_by_id (table, 2, "0");
+ rtbl_add_column_entry_by_id (table, 2, "-2000");
+ rtbl_add_column_entry_by_id (table, 3, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
+
+ rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
+ rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
+ rtbl_add_column_entry_by_id (table, 3, "afs/pdc.kth.se@NADA.KTH.SE");
+
+ rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
+ rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
+ rtbl_add_column_entry_by_id (table, 3, "afs@NADA.KTH.SE");
+
+ rtbl_set_separator (table, " ");
+
+ rtbl_format (table, stdout);
+
+ rtbl_destroy (table);
+
+ printf("\n");
+
+ table = rtbl_create ();
+ rtbl_add_column_by_id (table, 0, "Column A", 0);
+ rtbl_set_column_affix_by_id (table, 0, "<", ">");
+ rtbl_add_column_by_id (table, 1, "Column B", 0);
+ rtbl_set_column_affix_by_id (table, 1, "[", "]");
+ rtbl_add_column_by_id (table, 2, "Column C", 0);
+ rtbl_set_column_affix_by_id (table, 2, "(", ")");
+
+ rtbl_add_column_entry_by_id (table, 0, "1");
+ rtbl_new_row(table);
+ rtbl_add_column_entry_by_id (table, 1, "2");
+ rtbl_new_row(table);
+ rtbl_add_column_entry_by_id (table, 2, "3");
+ rtbl_new_row(table);
+
+ rtbl_set_separator (table, " ");
+ rtbl_format (table, stdout);
+
+ rtbl_destroy (table);
+
+ return 0;
+}
+
+#endif
diff --git a/lib/roken/rtbl.h b/lib/roken/rtbl.h
new file mode 100644
index 0000000000000..9b168c7e73063
--- /dev/null
+++ b/lib/roken/rtbl.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2000,2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+/* $Id: rtbl.h 17760 2006-06-30 13:42:39Z lha $ */
+
+#ifndef __rtbl_h__
+#define __rtbl_h__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rtbl_data;
+typedef struct rtbl_data *rtbl_t;
+
+#define RTBL_ALIGN_LEFT 0
+#define RTBL_ALIGN_RIGHT 1
+
+/* flags */
+#define RTBL_HEADER_STYLE_NONE 1
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column (rtbl_t, const char*, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_by_id (rtbl_t, unsigned int, const char*, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entryv_by_id (rtbl_t table, unsigned int id,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 0)));
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry (rtbl_t, const char*, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entryv (rtbl_t, const char*, const char*, ...)
+ __attribute__ ((format (printf, 3, 0)));
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry_by_id (rtbl_t, unsigned int, const char*);
+
+rtbl_t ROKEN_LIB_FUNCTION
+rtbl_create (void);
+
+void ROKEN_LIB_FUNCTION
+rtbl_destroy (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_format (rtbl_t, FILE*);
+
+unsigned int ROKEN_LIB_FUNCTION
+rtbl_get_flags (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_new_row (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_affix_by_id (rtbl_t, unsigned int, const char*, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_prefix (rtbl_t, const char*, const char*);
+
+void ROKEN_LIB_FUNCTION
+rtbl_set_flags (rtbl_t, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_prefix (rtbl_t, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_separator (rtbl_t, const char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __rtbl_h__ */
diff --git a/lib/roken/sendmsg.c b/lib/roken/sendmsg.c
new file mode 100644
index 0000000000000..e7478bfe2d69d
--- /dev/null
+++ b/lib/roken/sendmsg.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: sendmsg.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+sendmsg(int s, const struct msghdr *msg, int flags)
+{
+ ssize_t ret;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+ struct iovec *iov = msg->msg_iov;
+
+ for(i = 0; i < msg->msg_iovlen; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (tot != 0 && buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ p = buf;
+ for (i = 0; i < msg->msg_iovlen; ++i) {
+ memcpy (p, iov[i].iov_base, iov[i].iov_len);
+ p += iov[i].iov_len;
+ }
+ ret = sendto (s, buf, tot, flags, msg->msg_name, msg->msg_namelen);
+ free (buf);
+ return ret;
+}
diff --git a/lib/roken/setegid.c b/lib/roken/setegid.c
new file mode 100644
index 0000000000000..14d99eecb86a8
--- /dev/null
+++ b/lib/roken/setegid.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: setegid.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+setegid(gid_t egid)
+{
+#ifdef HAVE_SETREGID
+ return setregid(-1, egid);
+#endif
+
+#ifdef HAVE_SETRESGID
+ return setresgid(-1, egid, -1);
+#endif
+
+ return -1;
+}
diff --git a/lib/roken/setenv.c b/lib/roken/setenv.c
new file mode 100644
index 0000000000000..2bf09bec9d839
--- /dev/null
+++ b/lib/roken/setenv.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: setenv.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This is the easy way out, use putenv to implement setenv. We might
+ * leak some memory but that is ok since we are usally about to exec
+ * anyway.
+ */
+
+int ROKEN_LIB_FUNCTION
+setenv(const char *var, const char *val, int rewrite)
+{
+ char *t;
+
+ if (!rewrite && getenv(var) != 0)
+ return 0;
+
+ asprintf (&t, "%s=%s", var, val);
+ if (t == NULL)
+ return -1;
+
+ if (putenv(t) == 0)
+ return 0;
+ else
+ return -1;
+}
diff --git a/lib/roken/seteuid.c b/lib/roken/seteuid.c
new file mode 100644
index 0000000000000..4f786bbf47155
--- /dev/null
+++ b/lib/roken/seteuid.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: seteuid.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+seteuid(uid_t euid)
+{
+#ifdef HAVE_SETREUID
+ return setreuid(-1, euid);
+#endif
+
+#ifdef HAVE_SETRESUID
+ return setresuid(-1, euid, -1);
+#endif
+
+ return -1;
+}
diff --git a/lib/roken/setprogname.c b/lib/roken/setprogname.c
new file mode 100644
index 0000000000000..b24c785b1bc64
--- /dev/null
+++ b/lib/roken/setprogname.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: setprogname.c 15955 2005-08-23 10:19:20Z lha $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE___PROGNAME
+extern const char *__progname;
+#endif
+
+#ifndef HAVE_SETPROGNAME
+void ROKEN_LIB_FUNCTION
+setprogname(const char *argv0)
+{
+#ifndef HAVE___PROGNAME
+ const char *p;
+ if(argv0 == NULL)
+ return;
+ p = strrchr(argv0, '/');
+ if(p == NULL)
+ p = argv0;
+ else
+ p++;
+ __progname = p;
+#endif
+}
+#endif /* HAVE_SETPROGNAME */
diff --git a/lib/roken/signal.c b/lib/roken/signal.c
new file mode 100644
index 0000000000000..e18439040f916
--- /dev/null
+++ b/lib/roken/signal.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: signal.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <signal.h>
+#include "roken.h"
+
+/*
+ * We would like to always use this signal but there is a link error
+ * on NEXTSTEP
+ */
+#if !defined(NeXT) && !defined(__APPLE__)
+/*
+ * Bugs:
+ *
+ * Do we need any extra hacks for SIGCLD and/or SIGCHLD?
+ */
+
+SigAction ROKEN_LIB_FUNCTION
+signal(int iSig, SigAction pAction)
+{
+ struct sigaction saNew, saOld;
+
+ saNew.sa_handler = pAction;
+ sigemptyset(&saNew.sa_mask);
+ saNew.sa_flags = 0;
+
+ if (iSig == SIGALRM)
+ {
+#ifdef SA_INTERRUPT
+ saNew.sa_flags |= SA_INTERRUPT;
+#endif
+ }
+ else
+ {
+#ifdef SA_RESTART
+ saNew.sa_flags |= SA_RESTART;
+#endif
+ }
+
+ if (sigaction(iSig, &saNew, &saOld) < 0)
+ return(SIG_ERR);
+
+ return(saOld.sa_handler);
+}
+#endif
diff --git a/lib/roken/simple_exec.c b/lib/roken/simple_exec.c
new file mode 100644
index 0000000000000..447b5bfd02703
--- /dev/null
+++ b/lib/roken/simple_exec.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1998 - 2001, 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: simple_exec.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include "roken.h"
+
+#define EX_NOEXEC 126
+#define EX_NOTFOUND 127
+
+/* return values:
+ -1 on `unspecified' system errors
+ -2 on fork failures
+ -3 on waitpid errors
+ -4 exec timeout
+ 0- is return value from subprocess
+ 126 if the program couldn't be executed
+ 127 if the program couldn't be found
+ 128- is 128 + signal that killed subprocess
+
+ possible values `func' can return:
+ ((time_t)-2) exit loop w/o killing child and return
+ `exec timeout'/-4 from simple_exec
+ ((time_t)-1) kill child with SIGTERM and wait for child to exit
+ 0 don't timeout again
+ n seconds to next timeout
+ */
+
+static int sig_alarm;
+
+static RETSIGTYPE
+sigtimeout(int sig)
+{
+ sig_alarm = 1;
+ SIGRETURN(0);
+}
+
+int ROKEN_LIB_FUNCTION
+wait_for_process_timed(pid_t pid, time_t (*func)(void *),
+ void *ptr, time_t timeout)
+{
+ RETSIGTYPE (*old_func)(int sig) = NULL;
+ unsigned int oldtime = 0;
+ int ret;
+
+ sig_alarm = 0;
+
+ if (func) {
+ old_func = signal(SIGALRM, sigtimeout);
+ oldtime = alarm(timeout);
+ }
+
+ while(1) {
+ int status;
+
+ while(waitpid(pid, &status, 0) < 0) {
+ if (errno != EINTR) {
+ ret = -3;
+ goto out;
+ }
+ if (func == NULL)
+ continue;
+ if (sig_alarm == 0)
+ continue;
+ timeout = (*func)(ptr);
+ if (timeout == (time_t)-1) {
+ kill(pid, SIGTERM);
+ continue;
+ } else if (timeout == (time_t)-2) {
+ ret = -4;
+ goto out;
+ }
+ alarm(timeout);
+ }
+ if(WIFSTOPPED(status))
+ continue;
+ if(WIFEXITED(status)) {
+ ret = WEXITSTATUS(status);
+ break;
+ }
+ if(WIFSIGNALED(status)) {
+ ret = WTERMSIG(status) + 128;
+ break;
+ }
+ }
+ out:
+ if (func) {
+ signal(SIGALRM, old_func);
+ alarm(oldtime);
+ }
+ return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+wait_for_process(pid_t pid)
+{
+ return wait_for_process_timed(pid, NULL, NULL, 0);
+}
+
+int ROKEN_LIB_FUNCTION
+pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd,
+ const char *file, ...)
+{
+ int in_fd[2], out_fd[2], err_fd[2];
+ pid_t pid;
+ va_list ap;
+ char **argv;
+
+ if(stdin_fd != NULL)
+ pipe(in_fd);
+ if(stdout_fd != NULL)
+ pipe(out_fd);
+ if(stderr_fd != NULL)
+ pipe(err_fd);
+ pid = fork();
+ switch(pid) {
+ case 0:
+ va_start(ap, file);
+ argv = vstrcollect(&ap);
+ va_end(ap);
+ if(argv == NULL)
+ exit(-1);
+
+ /* close pipes we're not interested in */
+ if(stdin_fd != NULL)
+ close(in_fd[1]);
+ if(stdout_fd != NULL)
+ close(out_fd[0]);
+ if(stderr_fd != NULL)
+ close(err_fd[0]);
+
+ /* pipe everything caller doesn't care about to /dev/null */
+ if(stdin_fd == NULL)
+ in_fd[0] = open(_PATH_DEVNULL, O_RDONLY);
+ if(stdout_fd == NULL)
+ out_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
+ if(stderr_fd == NULL)
+ err_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
+
+ /* move to proper descriptors */
+ if(in_fd[0] != STDIN_FILENO) {
+ dup2(in_fd[0], STDIN_FILENO);
+ close(in_fd[0]);
+ }
+ if(out_fd[1] != STDOUT_FILENO) {
+ dup2(out_fd[1], STDOUT_FILENO);
+ close(out_fd[1]);
+ }
+ if(err_fd[1] != STDERR_FILENO) {
+ dup2(err_fd[1], STDERR_FILENO);
+ close(err_fd[1]);
+ }
+
+ closefrom(3);
+
+ execv(file, argv);
+ exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+ case -1:
+ if(stdin_fd != NULL) {
+ close(in_fd[0]);
+ close(in_fd[1]);
+ }
+ if(stdout_fd != NULL) {
+ close(out_fd[0]);
+ close(out_fd[1]);
+ }
+ if(stderr_fd != NULL) {
+ close(err_fd[0]);
+ close(err_fd[1]);
+ }
+ return -2;
+ default:
+ if(stdin_fd != NULL) {
+ close(in_fd[0]);
+ *stdin_fd = fdopen(in_fd[1], "w");
+ }
+ if(stdout_fd != NULL) {
+ close(out_fd[1]);
+ *stdout_fd = fdopen(out_fd[0], "r");
+ }
+ if(stderr_fd != NULL) {
+ close(err_fd[1]);
+ *stderr_fd = fdopen(err_fd[0], "r");
+ }
+ }
+ return pid;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execvp_timed(const char *file, char *const args[],
+ time_t (*func)(void *), void *ptr, time_t timeout)
+{
+ pid_t pid = fork();
+ switch(pid){
+ case -1:
+ return -2;
+ case 0:
+ execvp(file, args);
+ exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+ default:
+ return wait_for_process_timed(pid, func, ptr, timeout);
+ }
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execvp(const char *file, char *const args[])
+{
+ return simple_execvp_timed(file, args, NULL, NULL, 0);
+}
+
+/* gee, I'd like a execvpe */
+int ROKEN_LIB_FUNCTION
+simple_execve_timed(const char *file, char *const args[], char *const envp[],
+ time_t (*func)(void *), void *ptr, time_t timeout)
+{
+ pid_t pid = fork();
+ switch(pid){
+ case -1:
+ return -2;
+ case 0:
+ execve(file, args, envp);
+ exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+ default:
+ return wait_for_process_timed(pid, func, ptr, timeout);
+ }
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execve(const char *file, char *const args[], char *const envp[])
+{
+ return simple_execve_timed(file, args, envp, NULL, NULL, 0);
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execlp(const char *file, ...)
+{
+ va_list ap;
+ char **argv;
+ int ret;
+
+ va_start(ap, file);
+ argv = vstrcollect(&ap);
+ va_end(ap);
+ if(argv == NULL)
+ return -1;
+ ret = simple_execvp(file, argv);
+ free(argv);
+ return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execle(const char *file, ... /* ,char *const envp[] */)
+{
+ va_list ap;
+ char **argv;
+ char *const* envp;
+ int ret;
+
+ va_start(ap, file);
+ argv = vstrcollect(&ap);
+ envp = va_arg(ap, char **);
+ va_end(ap);
+ if(argv == NULL)
+ return -1;
+ ret = simple_execve(file, argv, envp);
+ free(argv);
+ return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execl(const char *file, ...)
+{
+ va_list ap;
+ char **argv;
+ int ret;
+
+ va_start(ap, file);
+ argv = vstrcollect(&ap);
+ va_end(ap);
+ if(argv == NULL)
+ return -1;
+ ret = simple_execve(file, argv, environ);
+ free(argv);
+ return ret;
+}
diff --git a/lib/roken/snprintf-test.c b/lib/roken/snprintf-test.c
new file mode 100644
index 0000000000000..047d54b63ffd8
--- /dev/null
+++ b/lib/roken/snprintf-test.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "snprintf-test.h"
+#include "roken.h"
+#include <limits.h>
+
+RCSID("$Id: snprintf-test.c 21627 2007-07-17 10:53:17Z lha $");
+
+static int
+try (const char *format, ...)
+{
+ int ret;
+ va_list ap;
+ char buf1[256], buf2[256];
+
+ va_start (ap, format);
+ ret = vsnprintf (buf1, sizeof(buf1), format, ap);
+ if (ret >= sizeof(buf1))
+ errx (1, "increase buf and try again");
+ va_end (ap);
+ va_start (ap, format);
+ vsprintf (buf2, format, ap);
+ ret = strcmp (buf1, buf2);
+ if (ret)
+ printf ("failed: format = \"%s\", \"%s\" != \"%s\"\n",
+ format, buf1, buf2);
+ va_end (ap);
+ return ret;
+}
+
+static int
+cmp_with_sprintf_int (void)
+{
+ int tot = 0;
+ int int_values[] = {INT_MIN, -17, -1, 0, 1, 17, 4711, 65535, INT_MAX};
+ int i;
+
+ for (i = 0; i < sizeof(int_values) / sizeof(int_values[0]); ++i) {
+ tot += try ("%d", int_values[i]);
+ tot += try ("%x", int_values[i]);
+ tot += try ("%X", int_values[i]);
+ tot += try ("%o", int_values[i]);
+ tot += try ("%#x", int_values[i]);
+ tot += try ("%#X", int_values[i]);
+ tot += try ("%#o", int_values[i]);
+ tot += try ("%10d", int_values[i]);
+ tot += try ("%10x", int_values[i]);
+ tot += try ("%10X", int_values[i]);
+ tot += try ("%10o", int_values[i]);
+ tot += try ("%#10x", int_values[i]);
+ tot += try ("%#10X", int_values[i]);
+ tot += try ("%#10o", int_values[i]);
+ tot += try ("%-10d", int_values[i]);
+ tot += try ("%-10x", int_values[i]);
+ tot += try ("%-10X", int_values[i]);
+ tot += try ("%-10o", int_values[i]);
+ tot += try ("%-#10x", int_values[i]);
+ tot += try ("%-#10X", int_values[i]);
+ tot += try ("%-#10o", int_values[i]);
+ }
+ return tot;
+}
+
+static int
+cmp_with_sprintf_long (void)
+{
+ int tot = 0;
+ long long_values[] = {LONG_MIN, -17, -1, 0, 1, 17, 4711, 65535, LONG_MAX};
+ int i;
+
+ for (i = 0; i < sizeof(long_values) / sizeof(long_values[0]); ++i) {
+ tot += try ("%ld", long_values[i]);
+ tot += try ("%lx", long_values[i]);
+ tot += try ("%lX", long_values[i]);
+ tot += try ("%lo", long_values[i]);
+ tot += try ("%#lx", long_values[i]);
+ tot += try ("%#lX", long_values[i]);
+ tot += try ("%#lo", long_values[i]);
+ tot += try ("%10ld", long_values[i]);
+ tot += try ("%10lx", long_values[i]);
+ tot += try ("%10lX", long_values[i]);
+ tot += try ("%10lo", long_values[i]);
+ tot += try ("%#10lx", long_values[i]);
+ tot += try ("%#10lX", long_values[i]);
+ tot += try ("%#10lo", long_values[i]);
+ tot += try ("%-10ld", long_values[i]);
+ tot += try ("%-10lx", long_values[i]);
+ tot += try ("%-10lX", long_values[i]);
+ tot += try ("%-10lo", long_values[i]);
+ tot += try ("%-#10lx", long_values[i]);
+ tot += try ("%-#10lX", long_values[i]);
+ tot += try ("%-#10lo", long_values[i]);
+ }
+ return tot;
+}
+
+#ifdef HAVE_LONG_LONG
+
+/* XXX doesn't work as expected on lp64 platforms with sizeof(long
+ * long) == sizeof(long) */
+
+static int
+cmp_with_sprintf_long_long (void)
+{
+ int tot = 0;
+ long long long_long_values[] = {
+ ((long long)LONG_MIN) -1, LONG_MIN, -17, -1,
+ 0,
+ 1, 17, 4711, 65535, LONG_MAX, ((long long)LONG_MAX) + 1};
+ int i;
+
+ for (i = 0; i < sizeof(long_long_values) / sizeof(long_long_values[0]); ++i) {
+ tot += try ("%lld", long_long_values[i]);
+ tot += try ("%llx", long_long_values[i]);
+ tot += try ("%llX", long_long_values[i]);
+ tot += try ("%llo", long_long_values[i]);
+ tot += try ("%#llx", long_long_values[i]);
+ tot += try ("%#llX", long_long_values[i]);
+ tot += try ("%#llo", long_long_values[i]);
+ tot += try ("%10lld", long_long_values[i]);
+ tot += try ("%10llx", long_long_values[i]);
+ tot += try ("%10llX", long_long_values[i]);
+ tot += try ("%10llo", long_long_values[i]);
+ tot += try ("%#10llx", long_long_values[i]);
+ tot += try ("%#10llX", long_long_values[i]);
+ tot += try ("%#10llo", long_long_values[i]);
+ tot += try ("%-10lld", long_long_values[i]);
+ tot += try ("%-10llx", long_long_values[i]);
+ tot += try ("%-10llX", long_long_values[i]);
+ tot += try ("%-10llo", long_long_values[i]);
+ tot += try ("%-#10llx", long_long_values[i]);
+ tot += try ("%-#10llX", long_long_values[i]);
+ tot += try ("%-#10llo", long_long_values[i]);
+ }
+ return tot;
+}
+
+#endif
+
+#if 0
+static int
+cmp_with_sprintf_float (void)
+{
+ int tot = 0;
+ double double_values[] = {-99999, -999, -17.4, -4.3, -3.0, -1.5, -1,
+ 0, 0.1, 0.2342374852, 0.2340007,
+ 3.1415926, 14.7845, 34.24758, 9999, 9999999};
+ int i;
+
+ for (i = 0; i < sizeof(double_values) / sizeof(double_values[0]); ++i) {
+ tot += try ("%f", double_values[i]);
+ tot += try ("%10f", double_values[i]);
+ tot += try ("%.2f", double_values[i]);
+ tot += try ("%7.0f", double_values[i]);
+ tot += try ("%5.2f", double_values[i]);
+ tot += try ("%0f", double_values[i]);
+ tot += try ("%#f", double_values[i]);
+ tot += try ("%e", double_values[i]);
+ tot += try ("%10e", double_values[i]);
+ tot += try ("%.2e", double_values[i]);
+ tot += try ("%7.0e", double_values[i]);
+ tot += try ("%5.2e", double_values[i]);
+ tot += try ("%0e", double_values[i]);
+ tot += try ("%#e", double_values[i]);
+ tot += try ("%E", double_values[i]);
+ tot += try ("%10E", double_values[i]);
+ tot += try ("%.2E", double_values[i]);
+ tot += try ("%7.0E", double_values[i]);
+ tot += try ("%5.2E", double_values[i]);
+ tot += try ("%0E", double_values[i]);
+ tot += try ("%#E", double_values[i]);
+ tot += try ("%g", double_values[i]);
+ tot += try ("%10g", double_values[i]);
+ tot += try ("%.2g", double_values[i]);
+ tot += try ("%7.0g", double_values[i]);
+ tot += try ("%5.2g", double_values[i]);
+ tot += try ("%0g", double_values[i]);
+ tot += try ("%#g", double_values[i]);
+ tot += try ("%G", double_values[i]);
+ tot += try ("%10G", double_values[i]);
+ tot += try ("%.2G", double_values[i]);
+ tot += try ("%7.0G", double_values[i]);
+ tot += try ("%5.2G", double_values[i]);
+ tot += try ("%0G", double_values[i]);
+ tot += try ("%#G", double_values[i]);
+ }
+ return tot;
+}
+#endif
+
+static int
+test_null (void)
+{
+ return snprintf (NULL, 0, "foo") != 3;
+}
+
+static int
+test_sizet (void)
+{
+ int tot = 0;
+ size_t sizet_values[] = { 0, 1, 2, 200, 4294967295u }; /* SIZE_MAX */
+ char *result[] = { "0", "1", "2", "200", "4294967295" };
+ int i;
+
+ for (i = 0; i < sizeof(sizet_values) / sizeof(sizet_values[0]); ++i) {
+#if 0
+ tot += try("%zu", sizet_values[i]);
+ tot += try("%zx", sizet_values[i]);
+ tot += try("%zX", sizet_values[i]);
+#else
+ char buf[256];
+ snprintf(buf, sizeof(buf), "%zu", sizet_values[i]);
+ if (strcmp(buf, result[i]) != 0) {
+ printf("%s != %s", buf, result[i]);
+ tot++;
+ }
+#endif
+ }
+ return tot;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += cmp_with_sprintf_int ();
+ ret += cmp_with_sprintf_long ();
+#ifdef HAVE_LONG_LONG
+ ret += cmp_with_sprintf_long_long ();
+#endif
+ ret += test_null ();
+ ret += test_sizet ();
+ return ret;
+}
diff --git a/lib/roken/snprintf-test.h b/lib/roken/snprintf-test.h
new file mode 100644
index 0000000000000..d672873679bc5
--- /dev/null
+++ b/lib/roken/snprintf-test.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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.
+ */
+
+/* $Id: snprintf-test.h 10377 2001-07-19 18:39:14Z assar $ */
+
+#ifndef __SNPRINTF_TEST_H__
+#define __SNPRINTF_TEST_H__
+
+/*
+ * we cannot use the real names of the functions when testing, since
+ * they might have different prototypes as the system functions, hence
+ * these evil hacks
+ */
+
+#define snprintf test_snprintf
+#define asprintf test_asprintf
+#define asnprintf test_asnprintf
+#define vasprintf test_vasprintf
+#define vasnprintf test_vasnprintf
+#define vsnprintf test_vsnprintf
+
+#endif /* __SNPRINTF_TEST_H__ */
diff --git a/lib/roken/snprintf.c b/lib/roken/snprintf.c
new file mode 100644
index 0000000000000..6b3352f96b89b
--- /dev/null
+++ b/lib/roken/snprintf.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 1995-2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: snprintf.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#if defined(TEST_SNPRINTF)
+#include "snprintf-test.h"
+#endif /* TEST_SNPRINTF */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "roken.h"
+#include <assert.h>
+
+enum format_flags {
+ minus_flag = 1,
+ plus_flag = 2,
+ space_flag = 4,
+ alternate_flag = 8,
+ zero_flag = 16
+};
+
+/*
+ * Common state
+ */
+
+struct snprintf_state {
+ unsigned char *str;
+ unsigned char *s;
+ unsigned char *theend;
+ size_t sz;
+ size_t max_sz;
+ void (*append_char)(struct snprintf_state *, unsigned char);
+ /* XXX - methods */
+};
+
+#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
+static int
+sn_reserve (struct snprintf_state *state, size_t n)
+{
+ return state->s + n > state->theend;
+}
+
+static void
+sn_append_char (struct snprintf_state *state, unsigned char c)
+{
+ if (!sn_reserve (state, 1))
+ *state->s++ = c;
+}
+#endif
+
+static int
+as_reserve (struct snprintf_state *state, size_t n)
+{
+ if (state->s + n > state->theend) {
+ int off = state->s - state->str;
+ unsigned char *tmp;
+
+ if (state->max_sz && state->sz >= state->max_sz)
+ return 1;
+
+ state->sz = max(state->sz * 2, state->sz + n);
+ if (state->max_sz)
+ state->sz = min(state->sz, state->max_sz);
+ tmp = realloc (state->str, state->sz);
+ if (tmp == NULL)
+ return 1;
+ state->str = tmp;
+ state->s = state->str + off;
+ state->theend = state->str + state->sz - 1;
+ }
+ return 0;
+}
+
+static void
+as_append_char (struct snprintf_state *state, unsigned char c)
+{
+ if(!as_reserve (state, 1))
+ *state->s++ = c;
+}
+
+/* longest integer types */
+
+#ifdef HAVE_LONG_LONG
+typedef unsigned long long u_longest;
+typedef long long longest;
+#else
+typedef unsigned long u_longest;
+typedef long longest;
+#endif
+
+
+
+static int
+pad(struct snprintf_state *state, int width, char c)
+{
+ int len = 0;
+ while(width-- > 0){
+ (*state->append_char)(state, c);
+ ++len;
+ }
+ return len;
+}
+
+/* return true if we should use alternatve hex form */
+static int
+use_alternative (int flags, u_longest num, unsigned base)
+{
+ return (flags & alternate_flag) && base == 16 && num != 0;
+}
+
+static int
+append_number(struct snprintf_state *state,
+ u_longest num, unsigned base, const char *rep,
+ int width, int prec, int flags, int minusp)
+{
+ int len = 0;
+ u_longest n = num;
+ char nstr[64]; /* enough for <192 bit octal integers */
+ int nstart, nlen;
+ char signchar;
+
+ /* given precision, ignore zero flag */
+ if(prec != -1)
+ flags &= ~zero_flag;
+ else
+ prec = 1;
+
+ /* format number as string */
+ nstart = sizeof(nstr);
+ nlen = 0;
+ nstr[--nstart] = '\0';
+ do {
+ assert(nstart > 0);
+ nstr[--nstart] = rep[n % base];
+ ++nlen;
+ n /= base;
+ } while(n);
+
+ /* zero value with zero precision should produce no digits */
+ if(prec == 0 && num == 0) {
+ nlen--;
+ nstart++;
+ }
+
+ /* figure out what char to use for sign */
+ if(minusp)
+ signchar = '-';
+ else if((flags & plus_flag))
+ signchar = '+';
+ else if((flags & space_flag))
+ signchar = ' ';
+ else
+ signchar = '\0';
+
+ if((flags & alternate_flag) && base == 8) {
+ /* if necessary, increase the precision to
+ make first digit a zero */
+
+ /* XXX C99 claims (regarding # and %o) that "if the value and
+ precision are both 0, a single 0 is printed", but there is
+ no such wording for %x. This would mean that %#.o would
+ output "0", but %#.x "". This does not make sense, and is
+ also not what other printf implementations are doing. */
+
+ if(prec <= nlen && nstr[nstart] != '0' && nstr[nstart] != '\0')
+ prec = nlen + 1;
+ }
+
+ /* possible formats:
+ pad | sign | alt | zero | digits
+ sign | alt | zero | digits | pad minus_flag
+ sign | alt | zero | digits zero_flag */
+
+ /* if not right justifying or padding with zeros, we need to
+ compute the length of the rest of the string, and then pad with
+ spaces */
+ if(!(flags & (minus_flag | zero_flag))) {
+ if(prec > nlen)
+ width -= prec;
+ else
+ width -= nlen;
+
+ if(use_alternative(flags, num, base))
+ width -= 2;
+
+ if(signchar != '\0')
+ width--;
+
+ /* pad to width */
+ len += pad(state, width, ' ');
+ }
+ if(signchar != '\0') {
+ (*state->append_char)(state, signchar);
+ ++len;
+ }
+ if(use_alternative(flags, num, base)) {
+ (*state->append_char)(state, '0');
+ (*state->append_char)(state, rep[10] + 23); /* XXX */
+ len += 2;
+ }
+ if(flags & zero_flag) {
+ /* pad to width with zeros */
+ if(prec - nlen > width - len - nlen)
+ len += pad(state, prec - nlen, '0');
+ else
+ len += pad(state, width - len - nlen, '0');
+ } else
+ /* pad to prec with zeros */
+ len += pad(state, prec - nlen, '0');
+
+ while(nstr[nstart] != '\0') {
+ (*state->append_char)(state, nstr[nstart++]);
+ ++len;
+ }
+
+ if(flags & minus_flag)
+ len += pad(state, width - len, ' ');
+
+ return len;
+}
+
+/*
+ * return length
+ */
+
+static int
+append_string (struct snprintf_state *state,
+ const unsigned char *arg,
+ int width,
+ int prec,
+ int flags)
+{
+ int len = 0;
+
+ if(arg == NULL)
+ arg = (const unsigned char*)"(null)";
+
+ if(prec != -1)
+ width -= prec;
+ else
+ width -= strlen((const char *)arg);
+ if(!(flags & minus_flag))
+ len += pad(state, width, ' ');
+
+ if (prec != -1) {
+ while (*arg && prec--) {
+ (*state->append_char) (state, *arg++);
+ ++len;
+ }
+ } else {
+ while (*arg) {
+ (*state->append_char) (state, *arg++);
+ ++len;
+ }
+ }
+ if(flags & minus_flag)
+ len += pad(state, width, ' ');
+ return len;
+}
+
+static int
+append_char(struct snprintf_state *state,
+ unsigned char arg,
+ int width,
+ int flags)
+{
+ int len = 0;
+
+ while(!(flags & minus_flag) && --width > 0) {
+ (*state->append_char) (state, ' ') ;
+ ++len;
+ }
+ (*state->append_char) (state, arg);
+ ++len;
+ while((flags & minus_flag) && --width > 0) {
+ (*state->append_char) (state, ' ');
+ ++len;
+ }
+ return 0;
+}
+
+/*
+ * This can't be made into a function...
+ */
+
+#ifdef HAVE_LONG_LONG
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_long_flag) \
+ res = (unsig long long)va_arg(arg, unsig long long); \
+else if (long_flag) \
+ res = (unsig long)va_arg(arg, unsig long); \
+else if (size_t_flag) \
+ res = (unsig long)va_arg(arg, size_t); \
+else if (short_flag) \
+ res = (unsig short)va_arg(arg, unsig int); \
+else \
+ res = (unsig int)va_arg(arg, unsig int)
+
+#else
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_flag) \
+ res = (unsig long)va_arg(arg, unsig long); \
+else if (size_t_flag) \
+ res = (unsig long)va_arg(arg, size_t); \
+else if (short_flag) \
+ res = (unsig short)va_arg(arg, unsig int); \
+else \
+ res = (unsig int)va_arg(arg, unsig int)
+
+#endif
+
+/*
+ * zyxprintf - return length, as snprintf
+ */
+
+static int
+xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap)
+{
+ const unsigned char *format = (const unsigned char *)char_format;
+ unsigned char c;
+ int len = 0;
+
+ while((c = *format++)) {
+ if (c == '%') {
+ int flags = 0;
+ int width = 0;
+ int prec = -1;
+ int size_t_flag = 0;
+ int long_long_flag = 0;
+ int long_flag = 0;
+ int short_flag = 0;
+
+ /* flags */
+ while((c = *format++)){
+ if(c == '-')
+ flags |= minus_flag;
+ else if(c == '+')
+ flags |= plus_flag;
+ else if(c == ' ')
+ flags |= space_flag;
+ else if(c == '#')
+ flags |= alternate_flag;
+ else if(c == '0')
+ flags |= zero_flag;
+ else if(c == '\'')
+ ; /* just ignore */
+ else
+ break;
+ }
+
+ if((flags & space_flag) && (flags & plus_flag))
+ flags ^= space_flag;
+
+ if((flags & minus_flag) && (flags & zero_flag))
+ flags ^= zero_flag;
+
+ /* width */
+ if (isdigit(c))
+ do {
+ width = width * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if(c == '*') {
+ width = va_arg(ap, int);
+ c = *format++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ prec = 0;
+ c = *format++;
+ if (isdigit(c))
+ do {
+ prec = prec * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if (c == '*') {
+ prec = va_arg(ap, int);
+ c = *format++;
+ }
+ }
+
+ /* size */
+
+ if (c == 'h') {
+ short_flag = 1;
+ c = *format++;
+ } else if (c == 'z') {
+ size_t_flag = 1;
+ c = *format++;
+ } else if (c == 'l') {
+ long_flag = 1;
+ c = *format++;
+ if (c == 'l') {
+ long_long_flag = 1;
+ c = *format++;
+ }
+ }
+
+ if(c != 'd' && c != 'i')
+ flags &= ~(plus_flag | space_flag);
+
+ switch (c) {
+ case 'c' :
+ append_char(state, va_arg(ap, int), width, flags);
+ ++len;
+ break;
+ case 's' :
+ len += append_string(state,
+ va_arg(ap, unsigned char*),
+ width,
+ prec,
+ flags);
+ break;
+ case 'd' :
+ case 'i' : {
+ longest arg;
+ u_longest num;
+ int minusp = 0;
+
+ PARSE_INT_FORMAT(arg, ap, signed);
+
+ if (arg < 0) {
+ minusp = 1;
+ num = -arg;
+ } else
+ num = arg;
+
+ len += append_number (state, num, 10, "0123456789",
+ width, prec, flags, minusp);
+ break;
+ }
+ case 'u' : {
+ u_longest arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ len += append_number (state, arg, 10, "0123456789",
+ width, prec, flags, 0);
+ break;
+ }
+ case 'o' : {
+ u_longest arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ len += append_number (state, arg, 010, "01234567",
+ width, prec, flags, 0);
+ break;
+ }
+ case 'x' : {
+ u_longest arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ len += append_number (state, arg, 0x10, "0123456789abcdef",
+ width, prec, flags, 0);
+ break;
+ }
+ case 'X' :{
+ u_longest arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ len += append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0);
+ break;
+ }
+ case 'p' : {
+ unsigned long arg = (unsigned long)va_arg(ap, void*);
+
+ len += append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0);
+ break;
+ }
+ case 'n' : {
+ int *arg = va_arg(ap, int*);
+ *arg = state->s - state->str;
+ break;
+ }
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ (*state->append_char)(state, c);
+ ++len;
+ break;
+ default :
+ (*state->append_char)(state, '%');
+ (*state->append_char)(state, c);
+ len += 2;
+ break;
+ }
+ } else {
+ (*state->append_char) (state, c);
+ ++len;
+ }
+ }
+ return len;
+}
+
+#if !defined(HAVE_SNPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+snprintf (char *str, size_t sz, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = vsnprintf (str, sz, format, args);
+ va_end(args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+
+ tmp = malloc (sz);
+ if (tmp == NULL)
+ abort ();
+
+ va_start(args, format);
+ ret2 = vsprintf (tmp, format, args);
+ va_end(args);
+ if (ret != ret2 || strcmp(str, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ return ret;
+}
+#endif
+
+#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+asprintf (char **ret, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasprintf (ret, format, args);
+ va_end(args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ va_start(args, format);
+ ret2 = vsprintf (tmp, format, args);
+ va_end(args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ return val;
+}
+#endif
+
+#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+asnprintf (char **ret, size_t max_sz, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasnprintf (ret, max_sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+vasprintf (char **ret, const char *format, va_list args)
+{
+ return vasnprintf (ret, 0, format, args);
+}
+#endif
+
+
+#if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+{
+ int st;
+ struct snprintf_state state;
+
+ state.max_sz = max_sz;
+ state.sz = 1;
+ state.str = malloc(state.sz);
+ if (state.str == NULL) {
+ *ret = NULL;
+ return -1;
+ }
+ state.s = state.str;
+ state.theend = state.s + state.sz - 1;
+ state.append_char = as_append_char;
+
+ st = xyzprintf (&state, format, args);
+ if (st > state.sz) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ } else {
+ char *tmp;
+
+ *state.s = '\0';
+ tmp = realloc (state.str, st+1);
+ if (tmp == NULL) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ }
+ *ret = tmp;
+ return st;
+ }
+}
+#endif
+
+#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
+int ROKEN_LIB_FUNCTION
+vsnprintf (char *str, size_t sz, const char *format, va_list args)
+{
+ struct snprintf_state state;
+ int ret;
+ unsigned char *ustr = (unsigned char *)str;
+
+ state.max_sz = 0;
+ state.sz = sz;
+ state.str = ustr;
+ state.s = ustr;
+ state.theend = ustr + sz - (sz > 0);
+ state.append_char = sn_append_char;
+
+ ret = xyzprintf (&state, format, args);
+ if (state.s != NULL && sz != 0)
+ *state.s = '\0';
+ return ret;
+}
+#endif
diff --git a/lib/roken/socket.c b/lib/roken/socket.c
new file mode 100644
index 0000000000000..a82dd0186c92c
--- /dev/null
+++ b/lib/roken/socket.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: socket.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+/*
+ * Set `sa' to the unitialized address of address family `af'
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_any (struct sockaddr *sa, int af)
+{
+ switch (af) {
+ case AF_INET : {
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
+
+ memset (sin4, 0, sizeof(*sin4));
+ sin4->sin_family = AF_INET;
+ sin4->sin_port = 0;
+ sin4->sin_addr.s_addr = INADDR_ANY;
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ memset (sin6, 0, sizeof(*sin6));
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = 0;
+ sin6->sin6_addr = in6addr_any;
+ break;
+ }
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * set `sa' to (`ptr', `port')
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
+{
+ switch (sa->sa_family) {
+ case AF_INET : {
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
+
+ memset (sin4, 0, sizeof(*sin4));
+ sin4->sin_family = AF_INET;
+ sin4->sin_port = port;
+ memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ memset (sin6, 0, sizeof(*sin6));
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = port;
+ memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
+ break;
+ }
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Return the size of an address of the type in `sa'
+ */
+
+size_t ROKEN_LIB_FUNCTION
+socket_addr_size (const struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET :
+ return sizeof(struct in_addr);
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ return sizeof(struct in6_addr);
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Return the size of a `struct sockaddr' in `sa'.
+ */
+
+size_t ROKEN_LIB_FUNCTION
+socket_sockaddr_size (const struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET :
+ return sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ return sizeof(struct sockaddr_in6);
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Return the binary address of `sa'.
+ */
+
+void * ROKEN_LIB_FUNCTION
+socket_get_address (struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET : {
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
+ return &sin4->sin_addr;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ return &sin6->sin6_addr;
+ }
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Return the port number from `sa'.
+ */
+
+int ROKEN_LIB_FUNCTION
+socket_get_port (const struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET : {
+ const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
+ return sin4->sin_port;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+ return sin6->sin6_port;
+ }
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Set the port in `sa' to `port'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_port (struct sockaddr *sa, int port)
+{
+ switch (sa->sa_family) {
+ case AF_INET : {
+ struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
+ sin4->sin_port = port;
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ sin6->sin6_port = port;
+ break;
+ }
+#endif
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+ break;
+ }
+}
+
+/*
+ * Set the range of ports to use when binding with port = 0.
+ */
+void ROKEN_LIB_FUNCTION
+socket_set_portrange (int sock, int restr, int af)
+{
+#if defined(IP_PORTRANGE)
+ if (af == AF_INET) {
+ int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
+ if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on,
+ sizeof(on)) < 0)
+ warn ("setsockopt IP_PORTRANGE (ignored)");
+ }
+#endif
+#if defined(IPV6_PORTRANGE)
+ if (af == AF_INET6) {
+ int on = restr ? IPV6_PORTRANGE_HIGH :
+ IPV6_PORTRANGE_DEFAULT;
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on,
+ sizeof(on)) < 0)
+ warn ("setsockopt IPV6_PORTRANGE (ignored)");
+ }
+#endif
+}
+
+/*
+ * Enable debug on `sock'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_debug (int sock)
+{
+#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
+ int on = 1;
+
+ if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0)
+ warn ("setsockopt SO_DEBUG (ignored)");
+#endif
+}
+
+/*
+ * Set the type-of-service of `sock' to `tos'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_tos (int sock, int tos)
+{
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0)
+ if (errno != EINVAL)
+ warn ("setsockopt TOS (ignored)");
+#endif
+}
+
+/*
+ * set the reuse of addresses on `sock' to `val'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_reuseaddr (int sock, int val)
+{
+#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
+ sizeof(val)) < 0)
+ err (1, "setsockopt SO_REUSEADDR");
+#endif
+}
+
+/*
+ * Set the that the `sock' should bind to only IPv6 addresses.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_ipv6only (int sock, int val)
+{
+#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
+#endif
+}
diff --git a/lib/roken/socket_wrapper.c b/lib/roken/socket_wrapper.c
new file mode 100644
index 0000000000000..9e6bfdd09811e
--- /dev/null
+++ b/lib/roken/socket_wrapper.c
@@ -0,0 +1,1913 @@
+/*
+ * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
+ * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
+ *
+ * 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. Neither the name of the author 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 AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+/*
+ Socket wrapper library. Passes all socket communication over
+ unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
+ is set.
+*/
+
+#define SOCKET_WRAPPER_NOT_REPLACE
+
+#ifdef _SAMBA_BUILD_
+
+#include "includes.h"
+#include "system/network.h"
+#include "system/filesys.h"
+
+#ifdef malloc
+#undef malloc
+#endif
+#ifdef calloc
+#undef calloc
+#endif
+#ifdef strdup
+#undef strdup
+#endif
+
+#else /* _SAMBA_BUILD_ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#undef SOCKET_WRAPPER_REPLACE
+
+#include <sys/types.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#include <errno.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include "roken.h"
+
+#include "socket_wrapper.h"
+
+#define HAVE_GETTIMEOFDAY_TZ 1
+
+#define _PUBLIC_
+
+#endif
+
+#define SWRAP_DLIST_ADD(list,item) do { \
+ if (!(list)) { \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+ (list) = (item); \
+ } else { \
+ (item)->prev = NULL; \
+ (item)->next = (list); \
+ (list)->prev = (item); \
+ (list) = (item); \
+ } \
+} while (0)
+
+#define SWRAP_DLIST_REMOVE(list,item) do { \
+ if ((list) == (item)) { \
+ (list) = (item)->next; \
+ if (list) { \
+ (list)->prev = NULL; \
+ } \
+ } else { \
+ if ((item)->prev) { \
+ (item)->prev->next = (item)->next; \
+ } \
+ if ((item)->next) { \
+ (item)->next->prev = (item)->prev; \
+ } \
+ } \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+} while (0)
+
+/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
+ * for now */
+#define REWRITE_CALLS
+
+#ifdef REWRITE_CALLS
+#define real_accept accept
+#define real_connect connect
+#define real_bind bind
+#define real_listen listen
+#define real_getpeername getpeername
+#define real_getsockname getsockname
+#define real_getsockopt getsockopt
+#define real_setsockopt setsockopt
+#define real_recvfrom recvfrom
+#define real_sendto sendto
+#define real_ioctl ioctl
+#define real_recv recv
+#define real_send send
+#define real_socket socket
+#define real_close close
+#define real_dup dup
+#define real_dup2 dup2
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY_TZ
+#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
+#else
+#define swrapGetTimeOfDay(tval) gettimeofday(tval)
+#endif
+
+/* we need to use a very terse format here as IRIX 6.4 silently
+ truncates names to 16 chars, so if we use a longer name then we
+ can't tell which port a packet came from with recvfrom()
+
+ with this format we have 8 chars left for the directory name
+*/
+#define SOCKET_FORMAT "%c%02X%04X"
+#define SOCKET_TYPE_CHAR_TCP 'T'
+#define SOCKET_TYPE_CHAR_UDP 'U'
+#define SOCKET_TYPE_CHAR_TCP_V6 'X'
+#define SOCKET_TYPE_CHAR_UDP_V6 'Y'
+
+#define MAX_WRAPPED_INTERFACES 16
+
+#define SW_IPV6_ADDRESS 1
+
+static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
+{
+ struct sockaddr *ret = (struct sockaddr *)malloc(len);
+ memcpy(ret, data, len);
+ return ret;
+}
+
+static void set_port(int family, int prt, struct sockaddr *addr)
+{
+ switch (family) {
+ case AF_INET:
+ ((struct sockaddr_in *)addr)->sin_port = htons(prt);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
+ break;
+#endif
+ }
+}
+
+static int socket_length(int family)
+{
+ switch (family) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+#endif
+ }
+ return -1;
+}
+
+
+
+struct socket_info
+{
+ int fd;
+
+ int family;
+ int type;
+ int protocol;
+ int bound;
+ int bcast;
+ int is_server;
+
+ char *path;
+ char *tmp_path;
+
+ struct sockaddr *myname;
+ socklen_t myname_len;
+
+ struct sockaddr *peername;
+ socklen_t peername_len;
+
+ struct {
+ unsigned long pck_snd;
+ unsigned long pck_rcv;
+ } io;
+
+ struct socket_info *prev, *next;
+};
+
+static struct socket_info *sockets;
+
+
+static const char *socket_wrapper_dir(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DIR");
+ if (s == NULL) {
+ return NULL;
+ }
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+ return s;
+}
+
+static unsigned int socket_wrapper_default_iface(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
+ if (s) {
+ unsigned int iface;
+ if (sscanf(s, "%u", &iface) == 1) {
+ if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
+ return iface;
+ }
+ }
+ }
+
+ return 1;/* 127.0.0.1 */
+}
+
+static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
+{
+ unsigned int iface;
+ unsigned int prt;
+ const char *p;
+ char type;
+
+ p = strrchr(un->sun_path, '/');
+ if (p) p++; else p = un->sun_path;
+
+ if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (prt > 0xFFFF) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch(type) {
+ case SOCKET_TYPE_CHAR_TCP:
+ case SOCKET_TYPE_CHAR_UDP: {
+ struct sockaddr_in *in2 = (struct sockaddr_in *)in;
+
+ if ((*len) < sizeof(*in2)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(in2, 0, sizeof(*in2));
+ in2->sin_family = AF_INET;
+ in2->sin_addr.s_addr = htonl((127<<24) | iface);
+ in2->sin_port = htons(prt);
+
+ *len = sizeof(*in2);
+ break;
+ }
+#ifdef HAVE_IPV6
+ case SOCKET_TYPE_CHAR_TCP_V6:
+ case SOCKET_TYPE_CHAR_UDP_V6: {
+ struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
+
+ if ((*len) < sizeof(*in2)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(in2, 0, sizeof(*in2));
+ in2->sin6_family = AF_INET6;
+ in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
+ in2->sin6_port = htons(prt);
+
+ *len = sizeof(*in2);
+ break;
+ }
+#endif
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
+ int *bcast)
+{
+ char type = '\0';
+ unsigned int prt;
+ unsigned int iface;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ switch (si->family) {
+ case AF_INET: {
+ const struct sockaddr_in *in =
+ (const struct sockaddr_in *)inaddr;
+ unsigned int addr = ntohl(in->sin_addr.s_addr);
+ char u_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP;
+ a_type = SOCKET_TYPE_CHAR_UDP;
+ b_type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ }
+
+ prt = ntohs(in->sin_port);
+ if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ iface = socket_wrapper_default_iface();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ iface = socket_wrapper_default_iface();
+ } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
+ /* 127.0.0.X */
+ is_bcast = 0;
+ type = u_type;
+ iface = (addr & 0x000000FF);
+ } else {
+ errno = ENETUNREACH;
+ return -1;
+ }
+ if (bcast) *bcast = is_bcast;
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *in =
+ (const struct sockaddr_in6 *)inaddr;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6;
+ break;
+ }
+
+ /* XXX no multicast/broadcast */
+
+ prt = ntohs(in->sin6_port);
+ iface = SW_IPV6_ADDRESS;
+
+ break;
+ }
+#endif
+ default:
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+ if (prt == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (is_bcast) {
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
+ socket_wrapper_dir());
+ /* the caller need to do more processing */
+ return 0;
+ }
+
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+
+ return 0;
+}
+
+static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
+ int *bcast)
+{
+ char type = '\0';
+ unsigned int prt;
+ unsigned int iface;
+ struct stat st;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ switch (si->family) {
+ case AF_INET: {
+ const struct sockaddr_in *in =
+ (const struct sockaddr_in *)inaddr;
+ unsigned int addr = ntohl(in->sin_addr.s_addr);
+ char u_type = '\0';
+ char d_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+
+ prt = ntohs(in->sin_port);
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP;
+ d_type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP;
+ d_type = SOCKET_TYPE_CHAR_UDP;
+ a_type = SOCKET_TYPE_CHAR_UDP;
+ b_type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ }
+
+ if (addr == 0) {
+ /* 0.0.0.0 */
+ is_bcast = 0;
+ type = d_type;
+ iface = socket_wrapper_default_iface();
+ } else if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ iface = socket_wrapper_default_iface();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ iface = socket_wrapper_default_iface();
+ } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
+ /* 127.0.0.X */
+ is_bcast = 0;
+ type = u_type;
+ iface = (addr & 0x000000FF);
+ } else {
+ errno = EADDRNOTAVAIL;
+ return -1;
+ }
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *in =
+ (const struct sockaddr_in6 *)inaddr;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6;
+ break;
+ }
+
+ /* XXX no multicast/broadcast */
+
+ prt = ntohs(in->sin6_port);
+ iface = SW_IPV6_ADDRESS;
+
+ break;
+ }
+#endif
+ default:
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+
+ if (bcast) *bcast = is_bcast;
+
+ if (prt == 0) {
+ /* handle auto-allocation of ephemeral ports */
+ for (prt = 5001; prt < 10000; prt++) {
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un->sun_path, &st) == 0) continue;
+
+ set_port(si->family, prt, si->myname);
+ }
+ }
+
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ return 0;
+}
+
+static struct socket_info *find_socket_info(int fd)
+{
+ struct socket_info *i;
+ for (i = sockets; i; i = i->next) {
+ if (i->fd == fd)
+ return i;
+ }
+
+ return NULL;
+}
+
+static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
+ struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
+{
+ if (!out_addr)
+ return 0;
+
+ out_addr->sun_family = AF_UNIX;
+
+ switch (in_addr->sa_family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ if (alloc_sock) {
+ return convert_in_un_alloc(si, in_addr, out_addr, bcast);
+ } else {
+ return convert_in_un_remote(si, in_addr, out_addr, bcast);
+ }
+ default:
+ break;
+ }
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+static int sockaddr_convert_from_un(const struct socket_info *si,
+ const struct sockaddr_un *in_addr,
+ socklen_t un_addrlen,
+ int family,
+ struct sockaddr *out_addr,
+ socklen_t *out_addrlen)
+{
+ if (out_addr == NULL || out_addrlen == NULL)
+ return 0;
+
+ if (un_addrlen == 0) {
+ *out_addrlen = 0;
+ return 0;
+ }
+
+ switch (family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ return convert_un_in(in_addr, out_addr, out_addrlen);
+ default:
+ break;
+ }
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+enum swrap_packet_type {
+ SWRAP_CONNECT_SEND,
+ SWRAP_CONNECT_UNREACH,
+ SWRAP_CONNECT_RECV,
+ SWRAP_CONNECT_ACK,
+ SWRAP_ACCEPT_SEND,
+ SWRAP_ACCEPT_RECV,
+ SWRAP_ACCEPT_ACK,
+ SWRAP_RECVFROM,
+ SWRAP_SENDTO,
+ SWRAP_SENDTO_UNREACH,
+ SWRAP_PENDING_RST,
+ SWRAP_RECV,
+ SWRAP_RECV_RST,
+ SWRAP_SEND,
+ SWRAP_SEND_RST,
+ SWRAP_CLOSE_SEND,
+ SWRAP_CLOSE_RECV,
+ SWRAP_CLOSE_ACK
+};
+
+struct swrap_file_hdr {
+ unsigned long magic;
+ unsigned short version_major;
+ unsigned short version_minor;
+ long timezone;
+ unsigned long sigfigs;
+ unsigned long frame_max_len;
+#define SWRAP_FRAME_LENGTH_MAX 0xFFFF
+ unsigned long link_type;
+};
+#define SWRAP_FILE_HDR_SIZE 24
+
+struct swrap_packet {
+ struct {
+ unsigned long seconds;
+ unsigned long micro_seconds;
+ unsigned long recorded_length;
+ unsigned long full_length;
+ } frame;
+#define SWRAP_PACKET__FRAME_SIZE 16
+
+ struct {
+ struct {
+ unsigned char ver_hdrlen;
+ unsigned char tos;
+ unsigned short packet_length;
+ unsigned short identification;
+ unsigned char flags;
+ unsigned char fragment;
+ unsigned char ttl;
+ unsigned char protocol;
+ unsigned short hdr_checksum;
+ unsigned long src_addr;
+ unsigned long dest_addr;
+ } hdr;
+#define SWRAP_PACKET__IP_HDR_SIZE 20
+
+ union {
+ struct {
+ unsigned short source_port;
+ unsigned short dest_port;
+ unsigned long seq_num;
+ unsigned long ack_num;
+ unsigned char hdr_length;
+ unsigned char control;
+ unsigned short window;
+ unsigned short checksum;
+ unsigned short urg;
+ } tcp;
+#define SWRAP_PACKET__IP_P_TCP_SIZE 20
+ struct {
+ unsigned short source_port;
+ unsigned short dest_port;
+ unsigned short length;
+ unsigned short checksum;
+ } udp;
+#define SWRAP_PACKET__IP_P_UDP_SIZE 8
+ struct {
+ unsigned char type;
+ unsigned char code;
+ unsigned short checksum;
+ unsigned long unused;
+ } icmp;
+#define SWRAP_PACKET__IP_P_ICMP_SIZE 8
+ } p;
+ } ip;
+};
+#define SWRAP_PACKET_SIZE 56
+
+static const char *socket_wrapper_pcap_file(void)
+{
+ static int initialized = 0;
+ static const char *s = NULL;
+ static const struct swrap_file_hdr h;
+ static const struct swrap_packet p;
+
+ if (initialized == 1) {
+ return s;
+ }
+ initialized = 1;
+
+ /*
+ * TODO: don't use the structs use plain buffer offsets
+ * and PUSH_U8(), PUSH_U16() and PUSH_U32()
+ *
+ * for now make sure we disable PCAP support
+ * if the struct has alignment!
+ */
+ if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p) != SWRAP_PACKET_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
+ return NULL;
+ }
+
+ s = getenv("SOCKET_WRAPPER_PCAP_FILE");
+ if (s == NULL) {
+ return NULL;
+ }
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+ return s;
+}
+
+static struct swrap_packet *swrap_packet_init(struct timeval *tval,
+ const struct sockaddr_in *src_addr,
+ const struct sockaddr_in *dest_addr,
+ int socket_type,
+ const unsigned char *payload,
+ size_t payload_len,
+ unsigned long tcp_seq,
+ unsigned long tcp_ack,
+ unsigned char tcp_ctl,
+ int unreachable,
+ size_t *_packet_len)
+{
+ struct swrap_packet *ret;
+ struct swrap_packet *packet;
+ size_t packet_len;
+ size_t alloc_len;
+ size_t nonwire_len = sizeof(packet->frame);
+ size_t wire_hdr_len = 0;
+ size_t wire_len = 0;
+ size_t icmp_hdr_len = 0;
+ size_t icmp_truncate_len = 0;
+ unsigned char protocol = 0, icmp_protocol = 0;
+ unsigned short src_port = src_addr->sin_port;
+ unsigned short dest_port = dest_addr->sin_port;
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ protocol = 0x06; /* TCP */
+ wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+
+ case SOCK_DGRAM:
+ protocol = 0x11; /* UDP */
+ wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+ }
+
+ if (unreachable) {
+ icmp_protocol = protocol;
+ protocol = 0x01; /* ICMP */
+ if (wire_len > 64 ) {
+ icmp_truncate_len = wire_len - 64;
+ }
+ icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
+ wire_hdr_len += icmp_hdr_len;
+ wire_len += icmp_hdr_len;
+ }
+
+ packet_len = nonwire_len + wire_len;
+ alloc_len = packet_len;
+ if (alloc_len < sizeof(struct swrap_packet)) {
+ alloc_len = sizeof(struct swrap_packet);
+ }
+ ret = (struct swrap_packet *)malloc(alloc_len);
+ if (!ret) return NULL;
+
+ packet = ret;
+
+ packet->frame.seconds = tval->tv_sec;
+ packet->frame.micro_seconds = tval->tv_usec;
+ packet->frame.recorded_length = wire_len - icmp_truncate_len;
+ packet->frame.full_length = wire_len - icmp_truncate_len;
+
+ packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ packet->ip.hdr.tos = 0x00;
+ packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
+ packet->ip.hdr.identification = htons(0xFFFF);
+ packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
+ packet->ip.hdr.fragment = htons(0x0000);
+ packet->ip.hdr.ttl = 0xFF;
+ packet->ip.hdr.protocol = protocol;
+ packet->ip.hdr.hdr_checksum = htons(0x0000);
+ packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
+ packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
+
+ if (unreachable) {
+ packet->ip.p.icmp.type = 0x03; /* destination unreachable */
+ packet->ip.p.icmp.code = 0x01; /* host unreachable */
+ packet->ip.p.icmp.checksum = htons(0x0000);
+ packet->ip.p.icmp.unused = htonl(0x00000000);
+
+ /* set the ip header in the ICMP payload */
+ packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
+ packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ packet->ip.hdr.tos = 0x00;
+ packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
+ packet->ip.hdr.identification = htons(0xFFFF);
+ packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
+ packet->ip.hdr.fragment = htons(0x0000);
+ packet->ip.hdr.ttl = 0xFF;
+ packet->ip.hdr.protocol = icmp_protocol;
+ packet->ip.hdr.hdr_checksum = htons(0x0000);
+ packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
+ packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
+
+ src_port = dest_addr->sin_port;
+ dest_port = src_addr->sin_port;
+ }
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ packet->ip.p.tcp.source_port = src_port;
+ packet->ip.p.tcp.dest_port = dest_port;
+ packet->ip.p.tcp.seq_num = htonl(tcp_seq);
+ packet->ip.p.tcp.ack_num = htonl(tcp_ack);
+ packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
+ packet->ip.p.tcp.control = tcp_ctl;
+ packet->ip.p.tcp.window = htons(0x7FFF);
+ packet->ip.p.tcp.checksum = htons(0x0000);
+ packet->ip.p.tcp.urg = htons(0x0000);
+
+ break;
+
+ case SOCK_DGRAM:
+ packet->ip.p.udp.source_port = src_addr->sin_port;
+ packet->ip.p.udp.dest_port = dest_addr->sin_port;
+ packet->ip.p.udp.length = htons(8 + payload_len);
+ packet->ip.p.udp.checksum = htons(0x0000);
+
+ break;
+ }
+
+ if (payload && payload_len > 0) {
+ unsigned char *p = (unsigned char *)ret;
+ p += nonwire_len;
+ p += wire_hdr_len;
+ memcpy(p, payload, payload_len);
+ }
+
+ *_packet_len = packet_len - icmp_truncate_len;
+ return ret;
+}
+
+static int swrap_get_pcap_fd(const char *fname)
+{
+ static int fd = -1;
+
+ if (fd != -1) return fd;
+
+ fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
+ if (fd != -1) {
+ struct swrap_file_hdr file_hdr;
+ file_hdr.magic = 0xA1B2C3D4;
+ file_hdr.version_major = 0x0002;
+ file_hdr.version_minor = 0x0004;
+ file_hdr.timezone = 0x00000000;
+ file_hdr.sigfigs = 0x00000000;
+ file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
+ file_hdr.link_type = 0x0065; /* 101 RAW IP */
+
+ write(fd, &file_hdr, sizeof(file_hdr));
+ return fd;
+ }
+
+ fd = open(fname, O_WRONLY|O_APPEND, 0644);
+
+ return fd;
+}
+
+static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
+ enum swrap_packet_type type,
+ const void *buf, size_t len)
+{
+ const struct sockaddr_in *src_addr;
+ const struct sockaddr_in *dest_addr;
+ const char *file_name;
+ unsigned long tcp_seq = 0;
+ unsigned long tcp_ack = 0;
+ unsigned char tcp_ctl = 0;
+ int unreachable = 0;
+ struct timeval tv;
+ struct swrap_packet *packet;
+ size_t packet_len = 0;
+ int fd;
+
+ file_name = socket_wrapper_pcap_file();
+ if (!file_name) {
+ return;
+ }
+
+ switch (si->family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ return;
+ }
+
+ switch (type) {
+ case SWRAP_CONNECT_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CONNECT_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x12; /** SYN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CONNECT_UNREACH:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
+ tcp_seq = si->io.pck_snd - 1;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_CONNECT_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_ACCEPT_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x12; /* SYN,ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_SEND:
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SEND_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ swrap_dump_packet(si, si->peername,
+ SWRAP_SENDTO_UNREACH,
+ buf, len);
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /** RST,ACK */
+
+ break;
+
+ case SWRAP_PENDING_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_RECV:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_RECV_RST:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ if (si->type == SOCK_DGRAM) {
+ return;
+ }
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_SENDTO:
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)addr;
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SENDTO_UNREACH:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_RECVFROM:
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)addr;
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_CLOSE_SEND:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x11; /* FIN, ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CLOSE_RECV:
+ if (si->type != SOCK_STREAM) return;
+
+ dest_addr = (const struct sockaddr_in *)si->myname;
+ src_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x11; /* FIN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CLOSE_ACK:
+ if (si->type != SOCK_STREAM) return;
+
+ src_addr = (const struct sockaddr_in *)si->myname;
+ dest_addr = (const struct sockaddr_in *)si->peername;
+
+ tcp_seq = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+ default:
+ return;
+ }
+
+ swrapGetTimeOfDay(&tv);
+
+ packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
+ (const unsigned char *)buf, len,
+ tcp_seq, tcp_ack, tcp_ctl, unreachable,
+ &packet_len);
+ if (!packet) {
+ return;
+ }
+
+ fd = swrap_get_pcap_fd(file_name);
+ if (fd != -1) {
+ write(fd, packet, packet_len);
+ }
+
+ free(packet);
+}
+
+_PUBLIC_ int swrap_socket(int family, int type, int protocol)
+{
+ struct socket_info *si;
+ int fd;
+
+ if (!socket_wrapper_dir()) {
+ return real_socket(family, type, protocol);
+ }
+
+ switch (family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ break;
+ case AF_UNIX:
+ return real_socket(family, type, protocol);
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ switch (type) {
+ case SOCK_STREAM:
+ break;
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+#if 0
+ switch (protocol) {
+ case 0:
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+#endif
+
+ fd = real_socket(AF_UNIX, type, 0);
+
+ if (fd == -1) return -1;
+
+ si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+
+ si->family = family;
+ si->type = type;
+ si->protocol = protocol;
+ si->fd = fd;
+
+ SWRAP_DLIST_ADD(sockets, si);
+
+ return si->fd;
+}
+
+_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct socket_info *parent_si, *child_si;
+ int fd;
+ struct sockaddr_un un_addr;
+ socklen_t un_addrlen = sizeof(un_addr);
+ struct sockaddr_un un_my_addr;
+ socklen_t un_my_addrlen = sizeof(un_my_addr);
+ struct sockaddr *my_addr;
+ socklen_t my_addrlen, len;
+ int ret;
+
+ parent_si = find_socket_info(s);
+ if (!parent_si) {
+ return real_accept(s, addr, addrlen);
+ }
+
+ /*
+ * assume out sockaddr have the same size as the in parent
+ * socket family
+ */
+ my_addrlen = socket_length(parent_si->family);
+ if (my_addrlen < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ my_addr = malloc(my_addrlen);
+ if (my_addr == NULL) {
+ return -1;
+ }
+
+ memset(&un_addr, 0, sizeof(un_addr));
+ memset(&un_my_addr, 0, sizeof(un_my_addr));
+
+ ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
+ if (ret == -1) {
+ free(my_addr);
+ return ret;
+ }
+
+ fd = ret;
+
+ len = my_addrlen;
+ ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
+ parent_si->family, my_addr, &len);
+ if (ret == -1) {
+ free(my_addr);
+ close(fd);
+ return ret;
+ }
+
+ child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
+ memset(child_si, 0, sizeof(*child_si));
+
+ child_si->fd = fd;
+ child_si->family = parent_si->family;
+ child_si->type = parent_si->type;
+ child_si->protocol = parent_si->protocol;
+ child_si->bound = 1;
+ child_si->is_server = 1;
+
+ child_si->peername_len = len;
+ child_si->peername = sockaddr_dup(my_addr, len);
+
+ if (addr != NULL && addrlen != NULL) {
+ *addrlen = len;
+ if (*addrlen >= len)
+ memcpy(addr, my_addr, len);
+ *addrlen = 0;
+ }
+
+ ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
+ if (ret == -1) {
+ free(child_si);
+ close(fd);
+ return ret;
+ }
+
+ len = my_addrlen;
+ ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
+ child_si->family, my_addr, &len);
+ if (ret == -1) {
+ free(child_si);
+ free(my_addr);
+ close(fd);
+ return ret;
+ }
+
+ child_si->myname_len = len;
+ child_si->myname = sockaddr_dup(my_addr, len);
+ free(my_addr);
+
+ SWRAP_DLIST_ADD(sockets, child_si);
+
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
+ swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
+
+ return fd;
+}
+
+static int autobind_start_init;
+static int autobind_start;
+
+/* using sendto() or connect() on an unbound socket would give the
+ recipient no way to reply, as unlike UDP and TCP, a unix domain
+ socket can't auto-assign emphemeral port numbers, so we need to
+ assign it here */
+static int swrap_auto_bind(struct socket_info *si)
+{
+ struct sockaddr_un un_addr;
+ int i;
+ char type;
+ int ret;
+ int port;
+ struct stat st;
+
+ if (autobind_start_init != 1) {
+ autobind_start_init = 1;
+ autobind_start = getpid();
+ autobind_start %= 50000;
+ autobind_start += 10000;
+ }
+
+ un_addr.sun_family = AF_UNIX;
+
+ switch (si->family) {
+ case AF_INET: {
+ struct sockaddr_in in;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP;
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ in.sin_addr.s_addr = htonl(127<<24 |
+ socket_wrapper_default_iface());
+
+ si->myname_len = sizeof(in);
+ si->myname = sockaddr_dup(&in, si->myname_len);
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 in6;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6;
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ memset(&in6, 0, sizeof(in6));
+ in6.sin6_family = AF_INET6;
+ in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS;
+ si->myname_len = sizeof(in6);
+ si->myname = sockaddr_dup(&in6, si->myname_len);
+ break;
+ }
+#endif
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ if (autobind_start > 60000) {
+ autobind_start = 10000;
+ }
+
+ for (i=0;i<1000;i++) {
+ port = autobind_start + i;
+ snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
+ "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
+ type, socket_wrapper_default_iface(), port);
+ if (stat(un_addr.sun_path, &st) == 0) continue;
+
+ ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
+ if (ret == -1) return ret;
+
+ si->tmp_path = strdup(un_addr.sun_path);
+ si->bound = 1;
+ autobind_start = port + 1;
+ break;
+ }
+ if (i == 1000) {
+ errno = ENFILE;
+ return -1;
+ }
+
+ set_port(si->family, port, si->myname);
+
+ return 0;
+}
+
+
+_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+ int ret;
+ struct sockaddr_un un_addr;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_connect(s, serv_addr, addrlen);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(si);
+ if (ret == -1) return -1;
+ }
+
+ if (si->family != serv_addr->sa_family) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
+ if (ret == -1) return -1;
+
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
+
+ ret = real_connect(s, (struct sockaddr *)&un_addr,
+ sizeof(struct sockaddr_un));
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == 0) {
+ si->peername_len = addrlen;
+ si->peername = sockaddr_dup(serv_addr, addrlen);
+
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
+ } else {
+ swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
+{
+ int ret;
+ struct sockaddr_un un_addr;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_bind(s, myaddr, addrlen);
+ }
+
+ si->myname_len = addrlen;
+ si->myname = sockaddr_dup(myaddr, addrlen);
+
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
+ if (ret == -1) return -1;
+
+ unlink(un_addr.sun_path);
+
+ ret = real_bind(s, (struct sockaddr *)&un_addr,
+ sizeof(struct sockaddr_un));
+
+ if (ret == 0) {
+ si->bound = 1;
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_listen(int s, int backlog)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_listen(s, backlog);
+ }
+
+ ret = real_listen(s, backlog);
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getpeername(s, name, addrlen);
+ }
+
+ if (!si->peername)
+ {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ memcpy(name, si->peername, si->peername_len);
+ *addrlen = si->peername_len;
+
+ return 0;
+}
+
+_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getsockname(s, name, addrlen);
+ }
+
+ memcpy(name, si->myname, si->myname_len);
+ *addrlen = si->myname_len;
+
+ return 0;
+}
+
+_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_getsockopt(s, level, optname, optval, optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ return real_getsockopt(s, level, optname, optval, optlen);
+ }
+
+ errno = ENOPROTOOPT;
+ return -1;
+}
+
+_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_setsockopt(s, level, optname, optval, optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ return real_setsockopt(s, level, optname, optval, optlen);
+ }
+
+ switch (si->family) {
+ case AF_INET:
+ return 0;
+ default:
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+}
+
+_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
+{
+ struct sockaddr_un un_addr;
+ socklen_t un_addrlen = sizeof(un_addr);
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_recvfrom(s, buf, len, flags, from, fromlen);
+ }
+
+ /* irix 6.4 forgets to null terminate the sun_path string :-( */
+ memset(&un_addr, 0, sizeof(un_addr));
+ ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
+ if (ret == -1)
+ return ret;
+
+ if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
+ si->family, from, fromlen) == -1) {
+ return -1;
+ }
+
+ swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
+
+ return ret;
+}
+
+
+_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
+{
+ struct sockaddr_un un_addr;
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+ int bcast = 0;
+
+ if (!si) {
+ return real_sendto(s, buf, len, flags, to, tolen);
+ }
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ ret = real_send(s, buf, len, flags);
+ break;
+ case SOCK_DGRAM:
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(si);
+ if (ret == -1) return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
+ if (ret == -1) return -1;
+
+ if (bcast) {
+ struct stat st;
+ unsigned int iface;
+ unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
+ char type;
+
+ type = SOCKET_TYPE_CHAR_UDP;
+
+ for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
+ snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un_addr.sun_path, &st) != 0) continue;
+
+ /* ignore the any errors in broadcast sends */
+ real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
+ }
+
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+
+ return len;
+ }
+
+ ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
+ break;
+ default:
+ ret = -1;
+ errno = EHOSTUNREACH;
+ break;
+ }
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == -1) {
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+ swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
+ } else {
+ swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_ioctl(int s, int r, void *p)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+ int value;
+
+ if (!si) {
+ return real_ioctl(s, r, p);
+ }
+
+ ret = real_ioctl(s, r, p);
+
+ switch (r) {
+ case FIONREAD:
+ value = *((int *)p);
+ if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
+ swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ } else if (value == 0) { /* END OF FILE */
+ swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ }
+ break;
+ }
+
+ return ret;
+}
+
+_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_recv(s, buf, len, flags);
+ }
+
+ ret = real_recv(s, buf, len, flags);
+ if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
+ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else if (ret == 0) { /* END OF FILE */
+ swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else {
+ swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+ }
+
+ return ret;
+}
+
+
+_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return real_send(s, buf, len, flags);
+ }
+
+ ret = real_send(s, buf, len, flags);
+
+ if (ret == -1) {
+ swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+ swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
+ } else {
+ swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
+ }
+
+ return ret;
+}
+
+_PUBLIC_ int swrap_close(int fd)
+{
+ struct socket_info *si = find_socket_info(fd);
+ int ret;
+
+ if (!si) {
+ return real_close(fd);
+ }
+
+ SWRAP_DLIST_REMOVE(sockets, si);
+
+ if (si->myname && si->peername) {
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
+ }
+
+ ret = real_close(fd);
+
+ if (si->myname && si->peername) {
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
+ swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
+ }
+
+ if (si->path) free(si->path);
+ if (si->myname) free(si->myname);
+ if (si->peername) free(si->peername);
+ if (si->tmp_path) {
+ unlink(si->tmp_path);
+ free(si->tmp_path);
+ }
+ free(si);
+
+ return ret;
+}
+
+static int
+dup_internal(const struct socket_info *si_oldd, int fd)
+{
+ struct socket_info *si_newd;
+
+ si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+
+ si_newd->fd = fd;
+
+ si_newd->family = si_oldd->family;
+ si_newd->type = si_oldd->type;
+ si_newd->protocol = si_oldd->protocol;
+ si_newd->bound = si_oldd->bound;
+ si_newd->bcast = si_oldd->bcast;
+ if (si_oldd->path)
+ si_newd->path = strdup(si_oldd->path);
+ if (si_oldd->tmp_path)
+ si_newd->tmp_path = strdup(si_oldd->tmp_path);
+ si_newd->myname =
+ sockaddr_dup(si_oldd->myname, si_oldd->myname_len);
+ si_newd->myname_len = si_oldd->myname_len;
+ si_newd->peername =
+ sockaddr_dup(si_oldd->peername, si_oldd->peername_len);
+ si_newd->peername_len = si_oldd->peername_len;
+
+ si_newd->io = si_oldd->io;
+
+ SWRAP_DLIST_ADD(sockets, si_newd);
+
+ return fd;
+}
+
+
+_PUBLIC_ int swrap_dup(int oldd)
+{
+ struct socket_info *si;
+ int fd;
+
+ si = find_socket_info(oldd);
+ if (si == NULL)
+ return real_dup(oldd);
+
+ fd = real_dup(si->fd);
+ if (fd < 0)
+ return fd;
+
+ return dup_internal(si, fd);
+}
+
+
+_PUBLIC_ int swrap_dup2(int oldd, int newd)
+{
+ struct socket_info *si_newd, *si_oldd;
+ int fd;
+
+ if (newd == oldd)
+ return newd;
+
+ si_oldd = find_socket_info(oldd);
+ si_newd = find_socket_info(newd);
+
+ if (si_oldd == NULL && si_newd == NULL)
+ return real_dup2(oldd, newd);
+
+ fd = real_dup2(si_oldd->fd, newd);
+ if (fd < 0)
+ return fd;
+
+ /* close new socket first */
+ if (si_newd)
+ swrap_close(newd);
+
+ return dup_internal(si_oldd, fd);
+}
diff --git a/lib/roken/socket_wrapper.h b/lib/roken/socket_wrapper.h
new file mode 100644
index 0000000000000..316b024326b1c
--- /dev/null
+++ b/lib/roken/socket_wrapper.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
+ * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
+ *
+ * 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. Neither the name of the author 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 AUTHOR 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 AUTHOR 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 __SOCKET_WRAPPER_H__
+#define __SOCKET_WRAPPER_H__
+
+int swrap_socket(int family, int type, int protocol);
+int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen);
+int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen);
+int swrap_listen(int s, int backlog);
+int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen);
+int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
+int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
+int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
+ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
+ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
+int swrap_ioctl(int s, int req, void *ptr);
+ssize_t swrap_recv(int s, void *buf, size_t len, int flags);
+ssize_t swrap_send(int s, const void *buf, size_t len, int flags);
+int swrap_close(int);
+int swrap_dup(int);
+int swrap_dup2(int, int);
+
+#ifdef SOCKET_WRAPPER_REPLACE
+
+#ifdef accept
+#undef accept
+#endif
+#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen)
+
+#ifdef connect
+#undef connect
+#endif
+#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen)
+
+#ifdef bind
+#undef bind
+#endif
+#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen)
+
+#ifdef listen
+#undef listen
+#endif
+#define listen(s,blog) swrap_listen(s,blog)
+
+#ifdef getpeername
+#undef getpeername
+#endif
+#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen)
+
+#ifdef getsockname
+#undef getsockname
+#endif
+#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen)
+
+#ifdef getsockopt
+#undef getsockopt
+#endif
+#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen)
+
+#ifdef setsockopt
+#undef setsockopt
+#endif
+#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen)
+
+#ifdef recvfrom
+#undef recvfrom
+#endif
+#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen)
+
+#ifdef sendto
+#undef sendto
+#endif
+#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen)
+
+#ifdef ioctl
+#undef ioctl
+#endif
+#define ioctl(s,req,ptr) swrap_ioctl(s,req,ptr)
+
+#ifdef recv
+#undef recv
+#endif
+#define recv(s,buf,len,flags) swrap_recv(s,buf,len,flags)
+
+#ifdef send
+#undef send
+#endif
+#define send(s,buf,len,flags) swrap_send(s,buf,len,flags)
+
+#ifdef socket
+#undef socket
+#endif
+#define socket(domain,type,protocol) swrap_socket(domain,type,protocol)
+
+#ifdef close
+#undef close
+#endif
+#define close(s) swrap_close(s)
+
+#ifdef dup
+#undef dup
+#endif
+#define dup(oldd) swrap_dup(oldd)
+
+#ifdef dup2
+#undef dup2
+#endif
+#define dup2(oldd, newd) swrap_dup2(oldd, newd)
+
+#endif
+
+#endif /* __SOCKET_WRAPPER_H__ */
diff --git a/lib/roken/strcasecmp.c b/lib/roken/strcasecmp.c
new file mode 100644
index 0000000000000..4788d4fb51269
--- /dev/null
+++ b/lib/roken/strcasecmp.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strcasecmp.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+#include "roken.h"
+
+#ifndef HAVE_STRCASECMP
+
+int ROKEN_LIB_FUNCTION
+strcasecmp(const char *s1, const char *s2)
+{
+ while(toupper((unsigned char)*s1) == toupper((unsigned char)*s2)) {
+ if(*s1 == '\0')
+ return 0;
+ s1++;
+ s2++;
+ }
+ return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
+}
+
+#endif
diff --git a/lib/roken/strcollect.c b/lib/roken/strcollect.c
new file mode 100644
index 0000000000000..f29189159e164
--- /dev/null
+++ b/lib/roken/strcollect.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strcollect.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "roken.h"
+
+enum { initial = 10, increment = 5 };
+
+static char **
+sub (char **argv, int i, int argc, va_list *ap)
+{
+ do {
+ if(i == argc) {
+ /* realloc argv */
+ char **tmp = realloc(argv, (argc + increment) * sizeof(*argv));
+ if(tmp == NULL) {
+ free(argv);
+ errno = ENOMEM;
+ return NULL;
+ }
+ argv = tmp;
+ argc += increment;
+ }
+ argv[i++] = va_arg(*ap, char*);
+ } while(argv[i - 1] != NULL);
+ return argv;
+}
+
+/*
+ * return a malloced vector of pointers to the strings in `ap'
+ * terminated by NULL.
+ */
+
+char ** ROKEN_LIB_FUNCTION
+vstrcollect(va_list *ap)
+{
+ return sub (NULL, 0, 0, ap);
+}
+
+/*
+ *
+ */
+
+char ** ROKEN_LIB_FUNCTION
+strcollect(char *first, ...)
+{
+ va_list ap;
+ char **ret = malloc (initial * sizeof(char *));
+
+ if (ret == NULL)
+ return ret;
+
+ ret[0] = first;
+ va_start(ap, first);
+ ret = sub (ret, 1, initial, &ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/lib/roken/strdup.c b/lib/roken/strdup.c
new file mode 100644
index 0000000000000..a832120da2595
--- /dev/null
+++ b/lib/roken/strdup.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strdup.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef HAVE_STRDUP
+char * ROKEN_LIB_FUNCTION
+strdup(const char *old)
+{
+ char *t = malloc(strlen(old)+1);
+ if (t != 0)
+ strcpy(t, old);
+ return t;
+}
+#endif
diff --git a/lib/roken/strerror.c b/lib/roken/strerror.c
new file mode 100644
index 0000000000000..ca152f46b56cc
--- /dev/null
+++ b/lib/roken/strerror.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strerror.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char* ROKEN_LIB_FUNCTION
+strerror(int eno)
+{
+ static char emsg[1024];
+
+ if(eno < 0 || eno >= sys_nerr)
+ snprintf(emsg, sizeof(emsg), "Error %d occurred.", eno);
+ else
+ snprintf(emsg, sizeof(emsg), "%s", sys_errlist[eno]);
+
+ return emsg;
+}
diff --git a/lib/roken/strftime.c b/lib/roken/strftime.c
new file mode 100644
index 0000000000000..b7176b60b7bd3
--- /dev/null
+++ b/lib/roken/strftime.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef TEST_STRPFTIME
+#include "strpftime-test.h"
+#endif
+#include "roken.h"
+
+RCSID("$Id: strftime.c 21896 2007-08-09 08:46:08Z lha $");
+
+static const char *abb_weekdays[] = {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+};
+
+static const char *full_weekdays[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+};
+
+static const char *abb_month[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+};
+
+static const char *full_month[] = {
+ "January",
+ "February",
+ "Mars",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+};
+
+static const char *ampm[] = {
+ "AM",
+ "PM"
+};
+
+/*
+ * Convert hour in [0, 24] to [12 1 - 11 12 1 - 11 12]
+ */
+
+static int
+hour_24to12 (int hour)
+{
+ int ret = hour % 12;
+
+ if (ret == 0)
+ ret = 12;
+ return ret;
+}
+
+/*
+ * Return AM or PM for `hour'
+ */
+
+static const char *
+hour_to_ampm (int hour)
+{
+ return ampm[hour / 12];
+}
+
+/*
+ * Return the week number of `tm' (Sunday being the first day of the week)
+ * as [0, 53]
+ */
+
+static int
+week_number_sun (const struct tm *tm)
+{
+ return (tm->tm_yday + 7 - (tm->tm_yday % 7 - tm->tm_wday + 7) % 7) / 7;
+}
+
+/*
+ * Return the week number of `tm' (Monday being the first day of the week)
+ * as [0, 53]
+ */
+
+static int
+week_number_mon (const struct tm *tm)
+{
+ int wday = (tm->tm_wday + 6) % 7;
+
+ return (tm->tm_yday + 7 - (tm->tm_yday % 7 - wday + 7) % 7) / 7;
+}
+
+/*
+ * Return the week number of `tm' (Monday being the first day of the
+ * week) as [01, 53]. Week number one is the one that has four or more
+ * days in that year.
+ */
+
+static int
+week_number_mon4 (const struct tm *tm)
+{
+ int wday = (tm->tm_wday + 6) % 7;
+ int w1day = (wday - tm->tm_yday % 7 + 7) % 7;
+ int ret;
+
+ ret = (tm->tm_yday + w1day) / 7;
+ if (w1day >= 4)
+ --ret;
+ if (ret == -1)
+ ret = 53;
+ else
+ ++ret;
+ return ret;
+}
+
+/*
+ *
+ */
+
+size_t ROKEN_LIB_FUNCTION
+strftime (char *buf, size_t maxsize, const char *format,
+ const struct tm *tm)
+{
+ size_t n = 0;
+ int ret;
+
+ while (*format != '\0' && n < maxsize) {
+ if (*format == '%') {
+ ++format;
+ if(*format == 'E' || *format == 'O')
+ ++format;
+ switch (*format) {
+ case 'a' :
+ ret = snprintf (buf, maxsize - n,
+ "%s", abb_weekdays[tm->tm_wday]);
+ break;
+ case 'A' :
+ ret = snprintf (buf, maxsize - n,
+ "%s", full_weekdays[tm->tm_wday]);
+ break;
+ case 'h' :
+ case 'b' :
+ ret = snprintf (buf, maxsize - n,
+ "%s", abb_month[tm->tm_mon]);
+ break;
+ case 'B' :
+ ret = snprintf (buf, maxsize - n,
+ "%s", full_month[tm->tm_mon]);
+ break;
+ case 'c' :
+ ret = snprintf (buf, maxsize - n,
+ "%d:%02d:%02d %02d:%02d:%02d",
+ tm->tm_year,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ break;
+ case 'C' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", (tm->tm_year + 1900) / 100);
+ break;
+ case 'd' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", tm->tm_mday);
+ break;
+ case 'D' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d/%02d/%02d",
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ (tm->tm_year + 1900) % 100);
+ break;
+ case 'e' :
+ ret = snprintf (buf, maxsize - n,
+ "%2d", tm->tm_mday);
+ break;
+ case 'F':
+ ret = snprintf (buf, maxsize - n,
+ "%04d-%02d-%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday);
+ break;
+ case 'g':
+ /* last two digits of week-based year */
+ abort();
+ case 'G':
+ /* week-based year */
+ abort();
+ case 'H' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", tm->tm_hour);
+ break;
+ case 'I' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d",
+ hour_24to12 (tm->tm_hour));
+ break;
+ case 'j' :
+ ret = snprintf (buf, maxsize - n,
+ "%03d", tm->tm_yday + 1);
+ break;
+ case 'k' :
+ ret = snprintf (buf, maxsize - n,
+ "%2d", tm->tm_hour);
+ break;
+ case 'l' :
+ ret = snprintf (buf, maxsize - n,
+ "%2d",
+ hour_24to12 (tm->tm_hour));
+ break;
+ case 'm' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", tm->tm_mon + 1);
+ break;
+ case 'M' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", tm->tm_min);
+ break;
+ case 'n' :
+ ret = snprintf (buf, maxsize - n, "\n");
+ break;
+ case 'p' :
+ ret = snprintf (buf, maxsize - n, "%s",
+ hour_to_ampm (tm->tm_hour));
+ break;
+ case 'r' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d:%02d:%02d %s",
+ hour_24to12 (tm->tm_hour),
+ tm->tm_min,
+ tm->tm_sec,
+ hour_to_ampm (tm->tm_hour));
+ break;
+ case 'R' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d:%02d",
+ tm->tm_hour,
+ tm->tm_min);
+
+ case 's' :
+ ret = snprintf (buf, maxsize - n,
+ "%d", (int)mktime(rk_UNCONST(tm)));
+ break;
+ case 'S' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", tm->tm_sec);
+ break;
+ case 't' :
+ ret = snprintf (buf, maxsize - n, "\t");
+ break;
+ case 'T' :
+ case 'X' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d:%02d:%02d",
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ break;
+ case 'u' :
+ ret = snprintf (buf, maxsize - n,
+ "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
+ break;
+ case 'U' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", week_number_sun (tm));
+ break;
+ case 'V' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", week_number_mon4 (tm));
+ break;
+ case 'w' :
+ ret = snprintf (buf, maxsize - n,
+ "%d", tm->tm_wday);
+ break;
+ case 'W' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", week_number_mon (tm));
+ break;
+ case 'x' :
+ ret = snprintf (buf, maxsize - n,
+ "%d:%02d:%02d",
+ tm->tm_year,
+ tm->tm_mon + 1,
+ tm->tm_mday);
+ break;
+ case 'y' :
+ ret = snprintf (buf, maxsize - n,
+ "%02d", (tm->tm_year + 1900) % 100);
+ break;
+ case 'Y' :
+ ret = snprintf (buf, maxsize - n,
+ "%d", tm->tm_year + 1900);
+ break;
+ case 'z':
+ ret = snprintf (buf, maxsize - n,
+ "%ld",
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+ (long)tm->tm_gmtoff
+#elif defined(HAVE_TIMEZONE)
+#ifdef HAVE_ALTZONE
+ tm->tm_isdst ?
+ (long)altzone :
+#endif
+ (long)timezone
+#else
+#error Where in timezone chaos are you?
+#endif
+ );
+ break;
+ case 'Z' :
+ ret = snprintf (buf, maxsize - n,
+ "%s",
+
+#if defined(HAVE_STRUCT_TM_TM_ZONE)
+ tm->tm_zone
+#elif defined(HAVE_TIMEZONE)
+ tzname[tm->tm_isdst]
+#else
+#error what?
+#endif
+ );
+ break;
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ ret = snprintf (buf, maxsize - n,
+ "%%");
+ break;
+ default :
+ ret = snprintf (buf, maxsize - n,
+ "%%%c", *format);
+ break;
+ }
+ if (ret < 0 || ret >= maxsize - n)
+ return 0;
+ n += ret;
+ buf += ret;
+ ++format;
+ } else {
+ *buf++ = *format++;
+ ++n;
+ }
+ }
+ *buf++ = '\0';
+ return n;
+}
diff --git a/lib/roken/strlcat.c b/lib/roken/strlcat.c
new file mode 100644
index 0000000000000..3f9c085210c82
--- /dev/null
+++ b/lib/roken/strlcat.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995-2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$Id: strlcat.c 14773 2005-04-12 11:29:18Z lha $");
+
+#ifndef HAVE_STRLCAT
+
+size_t ROKEN_LIB_FUNCTION
+strlcat (char *dst, const char *src, size_t dst_sz)
+{
+ size_t len = strlen(dst);
+
+ if (dst_sz < len)
+ /* the total size of dst is less than the string it contains;
+ this could be considered bad input, but we might as well
+ handle it */
+ return len + strlen(src);
+
+ return len + strlcpy (dst + len, src, dst_sz - len);
+}
+#endif
diff --git a/lib/roken/strlcpy.c b/lib/roken/strlcpy.c
new file mode 100644
index 0000000000000..6797317bf40b4
--- /dev/null
+++ b/lib/roken/strlcpy.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1995-2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$Id: strlcpy.c 14773 2005-04-12 11:29:18Z lha $");
+
+#ifndef HAVE_STRLCPY
+
+size_t ROKEN_LIB_FUNCTION
+strlcpy (char *dst, const char *src, size_t dst_sz)
+{
+ size_t n;
+
+ for (n = 0; n < dst_sz; n++) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+
+ if (n < dst_sz)
+ return n;
+ if (n > 0)
+ *(dst - 1) = '\0';
+ return n + strlen (src);
+}
+
+#endif
diff --git a/lib/roken/strlwr.c b/lib/roken/strlwr.c
new file mode 100644
index 0000000000000..9e5e9739fc1c6
--- /dev/null
+++ b/lib/roken/strlwr.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strlwr.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRLWR
+char * ROKEN_LIB_FUNCTION
+strlwr(char *str)
+{
+ char *s;
+
+ for(s = str; *s; s++)
+ *s = tolower((unsigned char)*s);
+ return str;
+}
+#endif
diff --git a/lib/roken/strncasecmp.c b/lib/roken/strncasecmp.c
new file mode 100644
index 0000000000000..e534393c7d56e
--- /dev/null
+++ b/lib/roken/strncasecmp.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strncasecmp.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#ifndef HAVE_STRNCASECMP
+
+int ROKEN_LIB_FUNCTION
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ while(n > 0
+ && toupper((unsigned char)*s1) == toupper((unsigned char)*s2))
+ {
+ if(*s1 == '\0')
+ return 0;
+ s1++;
+ s2++;
+ n--;
+ }
+ if(n == 0)
+ return 0;
+ return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
+}
+
+#endif
diff --git a/lib/roken/strndup.c b/lib/roken/strndup.c
new file mode 100644
index 0000000000000..1960fd28c2aaa
--- /dev/null
+++ b/lib/roken/strndup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strndup.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRNDUP
+char * ROKEN_LIB_FUNCTION
+strndup(const char *old, size_t sz)
+{
+ size_t len = strnlen (old, sz);
+ char *t = malloc(len + 1);
+
+ if (t != NULL) {
+ memcpy (t, old, len);
+ t[len] = '\0';
+ }
+ return t;
+}
+#endif /* HAVE_STRNDUP */
diff --git a/lib/roken/strnlen.c b/lib/roken/strnlen.c
new file mode 100644
index 0000000000000..3ba61a582318a
--- /dev/null
+++ b/lib/roken/strnlen.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strnlen.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+size_t ROKEN_LIB_FUNCTION
+strnlen(const char *s, size_t len)
+{
+ size_t i;
+
+ for(i = 0; i < len && s[i]; i++)
+ ;
+ return i;
+}
diff --git a/lib/roken/strpftime-test.c b/lib/roken/strpftime-test.c
new file mode 100644
index 0000000000000..a1c13f3dced24
--- /dev/null
+++ b/lib/roken/strpftime-test.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef TEST_STRPFTIME
+#include "strpftime-test.h"
+#endif
+#include "roken.h"
+
+RCSID("$Id: strpftime-test.c 21897 2007-08-09 08:46:34Z lha $");
+
+enum { MAXSIZE = 26 };
+
+static struct testcase {
+ time_t t;
+ struct {
+ const char *format;
+ const char *result;
+ } vals[MAXSIZE];
+} tests[] = {
+ {0,
+ {
+ {"%A", "Thursday"},
+ {"%a", "Thu"},
+ {"%B", "January"},
+ {"%b", "Jan"},
+ {"%C", "19"},
+ {"%d", "01"},
+ {"%e", " 1"},
+ {"%H", "00"},
+ {"%I", "12"},
+ {"%j", "001"},
+ {"%k", " 0"},
+ {"%l", "12"},
+ {"%M", "00"},
+ {"%m", "01"},
+ {"%n", "\n"},
+ {"%p", "AM"},
+ {"%S", "00"},
+ {"%t", "\t"},
+ {"%w", "4"},
+ {"%Y", "1970"},
+ {"%y", "70"},
+ {"%U", "00"},
+ {"%W", "00"},
+ {"%V", "01"},
+ {"%%", "%"},
+ {NULL, NULL}}
+ },
+ {90000,
+ {
+ {"%A", "Friday"},
+ {"%a", "Fri"},
+ {"%B", "January"},
+ {"%b", "Jan"},
+ {"%C", "19"},
+ {"%d", "02"},
+ {"%e", " 2"},
+ {"%H", "01"},
+ {"%I", "01"},
+ {"%j", "002"},
+ {"%k", " 1"},
+ {"%l", " 1"},
+ {"%M", "00"},
+ {"%m", "01"},
+ {"%n", "\n"},
+ {"%p", "AM"},
+ {"%S", "00"},
+ {"%t", "\t"},
+ {"%w", "5"},
+ {"%Y", "1970"},
+ {"%y", "70"},
+ {"%U", "00"},
+ {"%W", "00"},
+ {"%V", "01"},
+ {"%%", "%"},
+ {NULL, NULL}
+ }
+ },
+ {216306,
+ {
+ {"%A", "Saturday"},
+ {"%a", "Sat"},
+ {"%B", "January"},
+ {"%b", "Jan"},
+ {"%C", "19"},
+ {"%d", "03"},
+ {"%e", " 3"},
+ {"%H", "12"},
+ {"%I", "12"},
+ {"%j", "003"},
+ {"%k", "12"},
+ {"%l", "12"},
+ {"%M", "05"},
+ {"%m", "01"},
+ {"%n", "\n"},
+ {"%p", "PM"},
+ {"%S", "06"},
+ {"%t", "\t"},
+ {"%w", "6"},
+ {"%Y", "1970"},
+ {"%y", "70"},
+ {"%U", "00"},
+ {"%W", "00"},
+ {"%V", "01"},
+ {"%%", "%"},
+ {NULL, NULL}
+ }
+ },
+ {259200,
+ {
+ {"%A", "Sunday"},
+ {"%a", "Sun"},
+ {"%B", "January"},
+ {"%b", "Jan"},
+ {"%C", "19"},
+ {"%d", "04"},
+ {"%e", " 4"},
+ {"%H", "00"},
+ {"%I", "12"},
+ {"%j", "004"},
+ {"%k", " 0"},
+ {"%l", "12"},
+ {"%M", "00"},
+ {"%m", "01"},
+ {"%n", "\n"},
+ {"%p", "AM"},
+ {"%S", "00"},
+ {"%t", "\t"},
+ {"%w", "0"},
+ {"%Y", "1970"},
+ {"%y", "70"},
+ {"%U", "01"},
+ {"%W", "00"},
+ {"%V", "01"},
+ {"%%", "%"},
+ {NULL, NULL}
+ }
+ },
+ {915148800,
+ {
+ {"%A", "Friday"},
+ {"%a", "Fri"},
+ {"%B", "January"},
+ {"%b", "Jan"},
+ {"%C", "19"},
+ {"%d", "01"},
+ {"%e", " 1"},
+ {"%H", "00"},
+ {"%I", "12"},
+ {"%j", "001"},
+ {"%k", " 0"},
+ {"%l", "12"},
+ {"%M", "00"},
+ {"%m", "01"},
+ {"%n", "\n"},
+ {"%p", "AM"},
+ {"%S", "00"},
+ {"%t", "\t"},
+ {"%w", "5"},
+ {"%Y", "1999"},
+ {"%y", "99"},
+ {"%U", "00"},
+ {"%W", "00"},
+ {"%V", "53"},
+ {"%%", "%"},
+ {NULL, NULL}}
+ },
+ {942161105,
+ {
+
+ {"%A", "Tuesday"},
+ {"%a", "Tue"},
+ {"%B", "November"},
+ {"%b", "Nov"},
+ {"%C", "19"},
+ {"%d", "09"},
+ {"%e", " 9"},
+ {"%H", "15"},
+ {"%I", "03"},
+ {"%j", "313"},
+ {"%k", "15"},
+ {"%l", " 3"},
+ {"%M", "25"},
+ {"%m", "11"},
+ {"%n", "\n"},
+ {"%p", "PM"},
+ {"%S", "05"},
+ {"%t", "\t"},
+ {"%w", "2"},
+ {"%Y", "1999"},
+ {"%y", "99"},
+ {"%U", "45"},
+ {"%W", "45"},
+ {"%V", "45"},
+ {"%%", "%"},
+ {NULL, NULL}
+ }
+ }
+};
+
+int
+main(int argc, char **argv)
+{
+ int i, j;
+ int ret = 0;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+ struct tm *tm;
+
+ tm = gmtime (&tests[i].t);
+
+ for (j = 0; tests[i].vals[j].format != NULL; ++j) {
+ char buf[128];
+ size_t len;
+ struct tm tm2;
+ char *ptr;
+
+ len = strftime (buf, sizeof(buf), tests[i].vals[j].format, tm);
+ if (len != strlen (buf)) {
+ printf ("length of strftime(\"%s\") = %lu (\"%s\")\n",
+ tests[i].vals[j].format, (unsigned long)len,
+ buf);
+ ++ret;
+ continue;
+ }
+ if (strcmp (buf, tests[i].vals[j].result) != 0) {
+ printf ("result of strftime(\"%s\") = \"%s\" != \"%s\"\n",
+ tests[i].vals[j].format, buf,
+ tests[i].vals[j].result);
+ ++ret;
+ continue;
+ }
+ memset (&tm2, 0, sizeof(tm2));
+ ptr = strptime (tests[i].vals[j].result,
+ tests[i].vals[j].format,
+ &tm2);
+ if (ptr == NULL || *ptr != '\0') {
+ printf ("bad return value from strptime("
+ "\"%s\", \"%s\")\n",
+ tests[i].vals[j].result,
+ tests[i].vals[j].format);
+ ++ret;
+ }
+ strftime (buf, sizeof(buf), tests[i].vals[j].format, &tm2);
+ if (strcmp (buf, tests[i].vals[j].result) != 0) {
+ printf ("reverse of \"%s\" failed: \"%s\" vs \"%s\"\n",
+ tests[i].vals[j].format,
+ buf, tests[i].vals[j].result);
+ ++ret;
+ }
+ }
+ }
+ {
+ struct tm tm;
+ memset(&tm, 0, sizeof(tm));
+ strptime ("200505", "%Y%m", &tm);
+ if (tm.tm_year != 105)
+ ++ret;
+ if (tm.tm_mon != 4)
+ ++ret;
+ }
+ if (ret) {
+ printf ("%d errors\n", ret);
+ return 1;
+ } else
+ return 0;
+}
diff --git a/lib/roken/strpftime-test.h b/lib/roken/strpftime-test.h
new file mode 100644
index 0000000000000..546e5529539a3
--- /dev/null
+++ b/lib/roken/strpftime-test.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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.
+ */
+
+/* $Id: snprintf-test.h 10377 2001-07-19 18:39:14Z assar $ */
+
+#ifndef __STRFTIME_TEST_H__
+#define __STRFTIME_TEST_H__
+
+/*
+ * we cannot use the real names of the functions when testing, since
+ * they might have different prototypes as the system functions, hence
+ * these evil hacks
+ */
+
+#define strftime test_strftime
+#define strptime test_strptime
+
+#endif /* __STRFTIME_TEST_H__ */
diff --git a/lib/roken/strpool.c b/lib/roken/strpool.c
new file mode 100644
index 0000000000000..6ebe0ce6c4b81
--- /dev/null
+++ b/lib/roken/strpool.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strpool.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include "roken.h"
+
+struct rk_strpool {
+ char *str;
+ size_t len;
+};
+
+/*
+ *
+ */
+
+void ROKEN_LIB_FUNCTION
+rk_strpoolfree(struct rk_strpool *p)
+{
+ if (p->str) {
+ free(p->str);
+ p->str = NULL;
+ }
+ free(p);
+}
+
+/*
+ *
+ */
+
+struct rk_strpool * ROKEN_LIB_FUNCTION
+rk_strpoolprintf(struct rk_strpool *p, const char *fmt, ...)
+{
+ va_list ap;
+ char *str, *str2;
+ int len;
+
+ if (p == NULL) {
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return NULL;
+ p->str = NULL;
+ p->len = 0;
+ }
+ va_start(ap, fmt);
+ len = vasprintf(&str, fmt, ap);
+ va_end(ap);
+ if (str == NULL) {
+ rk_strpoolfree(p);
+ return NULL;
+ }
+ str2 = realloc(p->str, len + p->len + 1);
+ if (str2 == NULL) {
+ rk_strpoolfree(p);
+ return NULL;
+ }
+ p->str = str2;
+ memcpy(p->str + p->len, str, len + 1);
+ p->len += len;
+ free(str);
+ return p;
+}
+
+/*
+ *
+ */
+
+char * ROKEN_LIB_FUNCTION
+rk_strpoolcollect(struct rk_strpool *p)
+{
+ char *str = p->str;
+ p->str = NULL;
+ free(p);
+ return str;
+}
diff --git a/lib/roken/strptime.c b/lib/roken/strptime.c
new file mode 100644
index 0000000000000..9cd133357a56e
--- /dev/null
+++ b/lib/roken/strptime.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 1999, 2003, 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef TEST_STRPFTIME
+#include "strpftime-test.h"
+#endif
+#include <ctype.h>
+#include "roken.h"
+
+RCSID("$Id: strptime.c 21895 2007-08-09 08:45:54Z lha $");
+
+static const char *abb_weekdays[] = {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ NULL
+};
+
+static const char *full_weekdays[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ NULL
+};
+
+static const char *abb_month[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+ NULL
+};
+
+static const char *full_month[] = {
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ NULL,
+};
+
+static const char *ampm[] = {
+ "am",
+ "pm",
+ NULL
+};
+
+/*
+ * Try to match `*buf' to one of the strings in `strs'. Return the
+ * index of the matching string (or -1 if none). Also advance buf.
+ */
+
+static int
+match_string (const char **buf, const char **strs)
+{
+ int i = 0;
+
+ for (i = 0; strs[i] != NULL; ++i) {
+ int len = strlen (strs[i]);
+
+ if (strncasecmp (*buf, strs[i], len) == 0) {
+ *buf += len;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Try to match `*buf' to at the most `n' characters and return the
+ * resulting number in `num'. Returns 0 or an error. Also advance
+ * buf.
+ */
+
+static int
+parse_number (const char **buf, int n, int *num)
+{
+ char *s, *str;
+ int i;
+
+ str = malloc(n + 1);
+ if (str == NULL)
+ return -1;
+
+ /* skip whitespace */
+ for (; **buf != '\0' && isspace((unsigned char)(**buf)); (*buf)++)
+ ;
+
+ /* parse at least n characters */
+ for (i = 0; **buf != '\0' && i < n && isdigit((unsigned char)(**buf)); i++, (*buf)++)
+ str[i] = **buf;
+ str[i] = '\0';
+
+ *num = strtol (str, &s, 10);
+ free(str);
+ if (s == str)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * tm_year is relative this year
+ */
+
+const int tm_year_base = 1900;
+
+/*
+ * Return TRUE iff `year' was a leap year.
+ */
+
+static int
+is_leap_year (int year)
+{
+ return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
+}
+
+/*
+ * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
+ */
+
+static int
+first_day (int year)
+{
+ int ret = 4;
+
+ for (; year > 1970; --year)
+ ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
+ return ret;
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_sun (struct tm *timeptr, int wnum)
+{
+ int fday = first_day (timeptr->tm_year + tm_year_base);
+
+ timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = fday;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon (struct tm *timeptr, int wnum)
+{
+ int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+
+ timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = (fday + 1) % 7;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon4 (struct tm *timeptr, int wnum)
+{
+ int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+ int offset = 0;
+
+ if (fday < 4)
+ offset += 7;
+
+ timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
+ if (timeptr->tm_yday < 0) {
+ timeptr->tm_wday = fday;
+ timeptr->tm_yday = 0;
+ }
+}
+
+/*
+ *
+ */
+
+char * ROKEN_LIB_FUNCTION
+strptime (const char *buf, const char *format, struct tm *timeptr)
+{
+ char c;
+
+ for (; (c = *format) != '\0'; ++format) {
+ char *s;
+ int ret;
+
+ if (isspace ((unsigned char)c)) {
+ while (isspace ((unsigned char)*buf))
+ ++buf;
+ } else if (c == '%' && format[1] != '\0') {
+ c = *++format;
+ if (c == 'E' || c == 'O')
+ c = *++format;
+ switch (c) {
+ case 'A' :
+ ret = match_string (&buf, full_weekdays);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'a' :
+ ret = match_string (&buf, abb_weekdays);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'B' :
+ ret = match_string (&buf, full_month);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_mon = ret;
+ break;
+ case 'b' :
+ case 'h' :
+ ret = match_string (&buf, abb_month);
+ if (ret < 0)
+ return NULL;
+ timeptr->tm_mon = ret;
+ break;
+ case 'C' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ timeptr->tm_year = (ret * 100) - tm_year_base;
+ break;
+ case 'c' :
+ abort ();
+ case 'D' : /* %m/%d/%y */
+ s = strptime (buf, "%m/%d/%y", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'd' :
+ case 'e' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ timeptr->tm_mday = ret;
+ break;
+ case 'H' :
+ case 'k' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ timeptr->tm_hour = ret;
+ break;
+ case 'I' :
+ case 'l' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ if (ret == 12)
+ timeptr->tm_hour = 0;
+ else
+ timeptr->tm_hour = ret;
+ break;
+ case 'j' :
+ if (parse_number(&buf, 3, &ret))
+ return NULL;
+ if (ret == 0)
+ return NULL;
+ timeptr->tm_yday = ret - 1;
+ break;
+ case 'm' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ if (ret == 0)
+ return NULL;
+ timeptr->tm_mon = ret - 1;
+ break;
+ case 'M' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ timeptr->tm_min = ret;
+ break;
+ case 'n' :
+ while (isspace ((unsigned char)*buf))
+ buf++;
+ break;
+ case 'p' :
+ ret = match_string (&buf, ampm);
+ if (ret < 0)
+ return NULL;
+ if (timeptr->tm_hour == 0) {
+ if (ret == 1)
+ timeptr->tm_hour = 12;
+ } else
+ timeptr->tm_hour += 12;
+ break;
+ case 'r' : /* %I:%M:%S %p */
+ s = strptime (buf, "%I:%M:%S %p", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'R' : /* %H:%M */
+ s = strptime (buf, "%H:%M", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'S' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ timeptr->tm_sec = ret;
+ break;
+ case 't' :
+ while (isspace ((unsigned char)*buf))
+ buf++;
+ break;
+ case 'T' : /* %H:%M:%S */
+ case 'X' :
+ s = strptime (buf, "%H:%M:%S", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'u' :
+ if (parse_number(&buf, 1, &ret))
+ return NULL;
+ if (ret <= 0)
+ return NULL;
+ timeptr->tm_wday = ret - 1;
+ break;
+ case 'w' :
+ if (parse_number(&buf, 1, &ret))
+ return NULL;
+ timeptr->tm_wday = ret;
+ break;
+ case 'U' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ set_week_number_sun (timeptr, ret);
+ break;
+ case 'V' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ set_week_number_mon4 (timeptr, ret);
+ break;
+ case 'W' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ set_week_number_mon (timeptr, ret);
+ break;
+ case 'x' :
+ s = strptime (buf, "%Y:%m:%d", timeptr);
+ if (s == NULL)
+ return NULL;
+ buf = s;
+ break;
+ case 'y' :
+ if (parse_number(&buf, 2, &ret))
+ return NULL;
+ if (ret < 70)
+ timeptr->tm_year = 100 + ret;
+ else
+ timeptr->tm_year = ret;
+ break;
+ case 'Y' :
+ if (parse_number(&buf, 4, &ret))
+ return NULL;
+ timeptr->tm_year = ret - tm_year_base;
+ break;
+ case 'Z' :
+ abort ();
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ if (*buf == '%')
+ ++buf;
+ else
+ return NULL;
+ break;
+ default :
+ if (*buf == '%' || *++buf == c)
+ ++buf;
+ else
+ return NULL;
+ break;
+ }
+ } else {
+ if (*buf == c)
+ ++buf;
+ else
+ return NULL;
+ }
+ }
+ return rk_UNCONST(buf);
+}
diff --git a/lib/roken/strsep.c b/lib/roken/strsep.c
new file mode 100644
index 0000000000000..dd191c4022987
--- /dev/null
+++ b/lib/roken/strsep.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strsep.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRSEP
+
+char * ROKEN_LIB_FUNCTION
+strsep(char **str, const char *delim)
+{
+ char *save = *str;
+ if(*str == NULL)
+ return NULL;
+ *str = *str + strcspn(*str, delim);
+ if(**str == 0)
+ *str = NULL;
+ else{
+ **str = 0;
+ (*str)++;
+ }
+ return save;
+}
+
+#endif
diff --git a/lib/roken/strsep_copy.c b/lib/roken/strsep_copy.c
new file mode 100644
index 0000000000000..4a0a8b05333af
--- /dev/null
+++ b/lib/roken/strsep_copy.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strsep_copy.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRSEP_COPY
+
+/* strsep, but with const stringp, so return string in buf */
+
+ssize_t ROKEN_LIB_FUNCTION
+strsep_copy(const char **stringp, const char *delim, char *buf, size_t len)
+{
+ const char *save = *stringp;
+ size_t l;
+ if(save == NULL)
+ return -1;
+ *stringp = *stringp + strcspn(*stringp, delim);
+ l = min(len, *stringp - save);
+ if(len > 0) {
+ memcpy(buf, save, l);
+ buf[l] = '\0';
+ }
+
+ l = *stringp - save;
+ if(**stringp == '\0')
+ *stringp = NULL;
+ else
+ (*stringp)++;
+ return l;
+}
+
+#endif
diff --git a/lib/roken/strtok_r.c b/lib/roken/strtok_r.c
new file mode 100644
index 0000000000000..fb72f5dc77282
--- /dev/null
+++ b/lib/roken/strtok_r.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strtok_r.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRTOK_R
+
+char * ROKEN_LIB_FUNCTION
+strtok_r(char *s1, const char *s2, char **lasts)
+{
+ char *ret;
+
+ if (s1 == NULL)
+ s1 = *lasts;
+ while(*s1 && strchr(s2, *s1))
+ ++s1;
+ if(*s1 == '\0')
+ return NULL;
+ ret = s1;
+ while(*s1 && !strchr(s2, *s1))
+ ++s1;
+ if(*s1)
+ *s1++ = '\0';
+ *lasts = s1;
+ return ret;
+}
+
+#endif /* HAVE_STRTOK_R */
diff --git a/lib/roken/strupr.c b/lib/roken/strupr.c
new file mode 100644
index 0000000000000..2a5322677f5c5
--- /dev/null
+++ b/lib/roken/strupr.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: strupr.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRUPR
+char * ROKEN_LIB_FUNCTION
+strupr(char *str)
+{
+ char *s;
+
+ for(s = str; *s; s++)
+ *s = toupper((unsigned char)*s);
+ return str;
+}
+#endif
diff --git a/lib/roken/swab.c b/lib/roken/swab.c
new file mode 100644
index 0000000000000..20744ca02ff9b
--- /dev/null
+++ b/lib/roken/swab.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_SWAB
+
+RCSID("$Id: swab.c 14773 2005-04-12 11:29:18Z lha $");
+
+void ROKEN_LIB_FUNCTION
+swab (char *from, char *to, int nbytes)
+{
+ while(nbytes >= 2) {
+ *(to + 1) = *from;
+ *to = *(from + 1);
+ to += 2;
+ from += 2;
+ nbytes -= 2;
+ }
+}
+#endif
diff --git a/lib/roken/test-mem.c b/lib/roken/test-mem.c
new file mode 100644
index 0000000000000..d955c1a489fc5
--- /dev/null
+++ b/lib/roken/test-mem.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include "roken.h"
+
+#include "test-mem.h"
+
+RCSID("$Id: test-mem.c 21005 2007-06-08 01:54:35Z lha $");
+
+/* #undef HAVE_MMAP */
+
+struct {
+ void *start;
+ size_t size;
+ void *data_start;
+ size_t data_size;
+ enum rk_test_mem_type type;
+ int fd;
+} map;
+
+struct sigaction sa, osa;
+
+char *testname;
+
+static RETSIGTYPE
+segv_handler(int sig)
+{
+ int fd;
+ char msg[] = "SIGSEGV i current test: ";
+
+ fd = open("/dev/stdout", O_WRONLY, 0600);
+ if (fd >= 0) {
+ write(fd, msg, sizeof(msg) - 1);
+ write(fd, testname, strlen(testname));
+ write(fd, "\n", 1);
+ close(fd);
+ }
+ _exit(1);
+}
+
+#define TESTREC() \
+ if (testname) \
+ errx(1, "test %s run recursively on %s", name, testname); \
+ testname = strdup(name); \
+ if (testname == NULL) \
+ errx(1, "malloc");
+
+
+void * ROKEN_LIB_FUNCTION
+rk_test_mem_alloc(enum rk_test_mem_type type, const char *name,
+ void *buf, size_t size)
+{
+#ifndef HAVE_MMAP
+ unsigned char *p;
+
+ TESTREC();
+
+ p = malloc(size + 2);
+ if (p == NULL)
+ errx(1, "malloc");
+ map.type = type;
+ map.start = p;
+ map.size = size + 2;
+ p[0] = 0xff;
+ p[map.size] = 0xff;
+ map.data_start = p + 1;
+#else
+ unsigned char *p;
+ int flags, ret, fd;
+ size_t pagesize = getpagesize();
+
+ TESTREC();
+
+ map.type = type;
+
+#ifdef MAP_ANON
+ flags = MAP_ANON;
+ fd = -1;
+#else
+ flags = 0;
+ fd = open ("/dev/zero", O_RDONLY);
+ if(fd < 0)
+ err (1, "open /dev/zero");
+#endif
+ map.fd = fd;
+ flags |= MAP_PRIVATE;
+
+ map.size = size + pagesize - (size % pagesize) + pagesize * 2;
+
+ p = (unsigned char *)mmap(0, map.size, PROT_READ | PROT_WRITE,
+ flags, fd, 0);
+ if (p == (unsigned char *)MAP_FAILED)
+ err (1, "mmap");
+
+ map.start = p;
+
+ ret = mprotect ((void *)p, pagesize, 0);
+ if (ret < 0)
+ err (1, "mprotect");
+
+ ret = mprotect (p + map.size - pagesize, pagesize, 0);
+ if (ret < 0)
+ err (1, "mprotect");
+
+ switch (type) {
+ case RK_TM_OVERRUN:
+ map.data_start = p + map.size - pagesize - size;
+ break;
+ case RK_TM_UNDERRUN:
+ map.data_start = p + pagesize;
+ break;
+ default:
+ abort();
+ }
+#endif
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+#ifdef SA_RESETHAND
+ sa.sa_flags |= SA_RESETHAND;
+#endif
+ sa.sa_handler = segv_handler;
+ sigaction (SIGSEGV, &sa, &osa);
+
+ map.data_size = size;
+ if (buf)
+ memcpy(map.data_start, buf, size);
+ return map.data_start;
+}
+
+void ROKEN_LIB_FUNCTION
+rk_test_mem_free(const char *map_name)
+{
+#ifndef HAVE_MMAP
+ unsigned char *p = map.start;
+
+ if (testname == NULL)
+ errx(1, "test_mem_free call on no free");
+
+ if (p[0] != 0xff)
+ errx(1, "%s: %s underrun %x\n", testname, map_name, p[0]);
+ if (p[map.size] != 0xff)
+ errx(1, "%s: %s overrun %x\n", testname, map_name, p[map.size - 1]);
+ free(map.start);
+#else
+ int ret;
+
+ if (testname == NULL)
+ errx(1, "test_mem_free call on no free");
+
+ ret = munmap (map.start, map.size);
+ if (ret < 0)
+ err (1, "munmap");
+ if (map.fd > 0)
+ close(map.fd);
+#endif
+ free(testname);
+ testname = NULL;
+
+ sigaction (SIGSEGV, &osa, NULL);
+}
diff --git a/lib/roken/test-mem.h b/lib/roken/test-mem.h
new file mode 100644
index 0000000000000..896222f8d76f1
--- /dev/null
+++ b/lib/roken/test-mem.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+enum rk_test_mem_type { RK_TM_OVERRUN, RK_TM_UNDERRUN };
+
+void * ROKEN_LIB_FUNCTION
+ rk_test_mem_alloc(enum rk_test_mem_type, const char *, void *, size_t);
+void ROKEN_LIB_FUNCTION
+ rk_test_mem_free(const char *);
diff --git a/lib/roken/test-readenv.c b/lib/roken/test-readenv.c
new file mode 100644
index 0000000000000..2cbf8166716b1
--- /dev/null
+++ b/lib/roken/test-readenv.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: test-readenv.c 20868 2007-06-03 21:02:04Z lha $");
+#endif
+
+#include "roken.h"
+#include "test-mem.h"
+
+char *s1 = "VAR1=VAL1#comment\n\
+VAR2=VAL2 VAL2 #comment\n\
+#this another comment\n\
+\n\
+VAR3=FOO";
+
+char *s2 = "VAR1=ENV2\n\
+";
+
+static void
+make_file(char *tmpl, size_t l)
+{
+ int fd;
+ strlcpy(tmpl, "env.XXXXXX", l);
+ fd = mkstemp(tmpl);
+ if(fd < 0)
+ err(1, "mkstemp");
+ close(fd);
+}
+
+static void
+write_file(const char *fn, const char *s)
+{
+ FILE *f;
+ f = fopen(fn, "w");
+ if(f == NULL) {
+ unlink(fn);
+ err(1, "fopen");
+ }
+ if(fwrite(s, 1, strlen(s), f) != strlen(s))
+ err(1, "short write");
+ if(fclose(f) != 0) {
+ unlink(fn);
+ err(1, "fclose");
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ char **env = NULL;
+ int count = 0;
+ char fn[MAXPATHLEN];
+ int error = 0;
+
+ make_file(fn, sizeof(fn));
+
+ write_file(fn, s1);
+ count = read_environment(fn, &env);
+ if(count != 3) {
+ warnx("test 1: variable count %d != 3", count);
+ error++;
+ }
+
+ write_file(fn, s2);
+ count = read_environment(fn, &env);
+ if(count != 1) {
+ warnx("test 2: variable count %d != 1", count);
+ error++;
+ }
+
+ unlink(fn);
+ count = read_environment(fn, &env);
+ if(count != 0) {
+ warnx("test 3: variable count %d != 0", count);
+ error++;
+ }
+ for(count = 0; env && env[count]; count++);
+ if(count != 3) {
+ warnx("total variable count %d != 3", count);
+ error++;
+ }
+ free_environment(env);
+
+
+ return error;
+}
diff --git a/lib/roken/timegm.c b/lib/roken/timegm.c
new file mode 100644
index 0000000000000..41eb48716d12a
--- /dev/null
+++ b/lib/roken/timegm.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1997, 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: timegm.c 18606 2006-10-19 16:19:10Z lha $");
+#endif
+
+#include "roken.h"
+
+static int
+is_leap(unsigned y)
+{
+ y += 1900;
+ return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
+}
+
+/*
+ * XXX This is a simplifed version of timegm, it needs to support out of
+ * bounds values.
+ */
+
+time_t
+rk_timegm (struct tm *tm)
+{
+ static const unsigned ndays[2][12] ={
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
+ time_t res = 0;
+ unsigned i;
+
+ if (tm->tm_year < 0)
+ return -1;
+ if (tm->tm_mon < 0 || tm->tm_mon > 11)
+ return -1;
+ if (tm->tm_mday < 1 || tm->tm_mday > ndays[is_leap(tm->tm_year)][tm->tm_mon])
+ return -1;
+ if (tm->tm_hour < 0 || tm->tm_hour > 23)
+ return -1;
+ if (tm->tm_min < 0 || tm->tm_min > 59)
+ return -1;
+ if (tm->tm_sec < 0 || tm->tm_sec > 59)
+ return -1;
+
+ for (i = 70; i < tm->tm_year; ++i)
+ res += is_leap(i) ? 366 : 365;
+
+ for (i = 0; i < tm->tm_mon; ++i)
+ res += ndays[is_leap(tm->tm_year)][i];
+ res += tm->tm_mday - 1;
+ res *= 24;
+ res += tm->tm_hour;
+ res *= 60;
+ res += tm->tm_min;
+ res *= 60;
+ res += tm->tm_sec;
+ return res;
+}
diff --git a/lib/roken/timeval.c b/lib/roken/timeval.c
new file mode 100644
index 0000000000000..b72e2023f00ba
--- /dev/null
+++ b/lib/roken/timeval.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * Timeval stuff
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: timeval.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Make `t1' consistent.
+ */
+
+void ROKEN_LIB_FUNCTION
+timevalfix(struct timeval *t1)
+{
+ if (t1->tv_usec < 0) {
+ t1->tv_sec--;
+ t1->tv_usec += 1000000;
+ }
+ if (t1->tv_usec >= 1000000) {
+ t1->tv_sec++;
+ t1->tv_usec -= 1000000;
+ }
+}
+
+/*
+ * t1 += t2
+ */
+
+void ROKEN_LIB_FUNCTION
+timevaladd(struct timeval *t1, const struct timeval *t2)
+{
+ t1->tv_sec += t2->tv_sec;
+ t1->tv_usec += t2->tv_usec;
+ timevalfix(t1);
+}
+
+/*
+ * t1 -= t2
+ */
+
+void ROKEN_LIB_FUNCTION
+timevalsub(struct timeval *t1, const struct timeval *t2)
+{
+ t1->tv_sec -= t2->tv_sec;
+ t1->tv_usec -= t2->tv_usec;
+ timevalfix(t1);
+}
diff --git a/lib/roken/tm2time.c b/lib/roken/tm2time.c
new file mode 100644
index 0000000000000..7bcba8379ca45
--- /dev/null
+++ b/lib/roken/tm2time.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: tm2time.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include "roken.h"
+
+time_t ROKEN_LIB_FUNCTION
+tm2time (struct tm tm, int local)
+{
+ time_t t;
+
+ tm.tm_isdst = local ? -1 : 0;
+
+ t = mktime (&tm);
+
+ if (!local)
+ t += t - mktime (gmtime (&t));
+ return t;
+}
diff --git a/lib/roken/unsetenv.c b/lib/roken/unsetenv.c
new file mode 100644
index 0000000000000..54cf7b77dc906
--- /dev/null
+++ b/lib/roken/unsetenv.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: unsetenv.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "roken.h"
+
+extern char **environ;
+
+/*
+ * unsetenv --
+ */
+void ROKEN_LIB_FUNCTION
+unsetenv(const char *name)
+{
+ int len;
+ const char *np;
+ char **p;
+
+ if (name == 0 || environ == 0)
+ return;
+
+ for (np = name; *np && *np != '='; np++)
+ /* nop */;
+ len = np - name;
+
+ for (p = environ; *p != 0; p++)
+ if (strncmp(*p, name, len) == 0 && (*p)[len] == '=')
+ break;
+
+ for (; *p != 0; p++)
+ *p = *(p + 1);
+}
+
diff --git a/lib/roken/unvis.c b/lib/roken/unvis.c
new file mode 100644
index 0000000000000..72d5f161b083d
--- /dev/null
+++ b/lib/roken/unvis.c
@@ -0,0 +1,286 @@
+/* $NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1989, 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. 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.
+ */
+
+#if 1
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: unvis.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#include "roken.h"
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+#else
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#define __LIBC12_SOURCE__
+
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <vis.h>
+
+#if 0
+#ifdef __weak_alias
+__weak_alias(strunvis,_strunvis)
+__weak_alias(unvis,_unvis)
+#endif
+
+__warn_references(unvis,
+ "warning: reference to compatibility unvis(); include <vis.h> for correct reference")
+#endif
+
+/*
+ * decode driven by state machine
+ */
+#define S_GROUND 0 /* haven't seen escape char */
+#define S_START 1 /* start decoding special sequence */
+#define S_META 2 /* metachar started (M) */
+#define S_META1 3 /* metachar more, regular char (-) */
+#define S_CTRL 4 /* control char started (^) */
+#define S_OCTAL2 5 /* octal digit 2 */
+#define S_OCTAL3 6 /* octal digit 3 */
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+int ROKEN_LIB_FUNCTION
+ rk_strunvis (char *, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_unvis (char *, int, int *, int);
+
+/*
+ * unvis - decode characters previously encoded by vis
+ */
+
+int ROKEN_LIB_FUNCTION
+rk_unvis(char *cp, int c, int *astate, int flag)
+{
+
+ _DIAGASSERT(cp != NULL);
+ _DIAGASSERT(astate != NULL);
+
+ if (flag & UNVIS_END) {
+ if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ }
+ return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
+ }
+
+ switch (*astate) {
+
+ case S_GROUND:
+ *cp = 0;
+ if (c == '\\') {
+ *astate = S_START;
+ return (0);
+ }
+ *cp = c;
+ return (UNVIS_VALID);
+
+ case S_START:
+ switch(c) {
+ case '\\':
+ *cp = c;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *cp = (c - '0');
+ *astate = S_OCTAL2;
+ return (0);
+ case 'M':
+ *cp = (char)0200;
+ *astate = S_META;
+ return (0);
+ case '^':
+ *astate = S_CTRL;
+ return (0);
+ case 'n':
+ *cp = '\n';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'r':
+ *cp = '\r';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'b':
+ *cp = '\b';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'a':
+ *cp = '\007';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'v':
+ *cp = '\v';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 't':
+ *cp = '\t';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'f':
+ *cp = '\f';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 's':
+ *cp = ' ';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'E':
+ *cp = '\033';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '\n':
+ /*
+ * hidden newline
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ case '$':
+ /*
+ * hidden marker
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ }
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+
+ case S_META:
+ if (c == '-')
+ *astate = S_META1;
+ else if (c == '^')
+ *astate = S_CTRL;
+ else {
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+ return (0);
+
+ case S_META1:
+ *astate = S_GROUND;
+ *cp |= c;
+ return (UNVIS_VALID);
+
+ case S_CTRL:
+ if (c == '?')
+ *cp |= 0177;
+ else
+ *cp |= c & 037;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+
+ case S_OCTAL2: /* second possible octal digit */
+ if (isoctal(c)) {
+ /*
+ * yes - and maybe a third
+ */
+ *cp = (*cp << 3) + (c - '0');
+ *astate = S_OCTAL3;
+ return (0);
+ }
+ /*
+ * no - done with current sequence, push back passed char
+ */
+ *astate = S_GROUND;
+ return (UNVIS_VALIDPUSH);
+
+ case S_OCTAL3: /* third possible octal digit */
+ *astate = S_GROUND;
+ if (isoctal(c)) {
+ *cp = (*cp << 3) + (c - '0');
+ return (UNVIS_VALID);
+ }
+ /*
+ * we were done, push back passed char
+ */
+ return (UNVIS_VALIDPUSH);
+
+ default:
+ /*
+ * decoder in unknown state - (probably uninitialized)
+ */
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+}
+
+/*
+ * strunvis - decode src into dst
+ *
+ * Number of chars decoded into dst is returned, -1 on error.
+ * Dst is null terminated.
+ */
+
+int ROKEN_LIB_FUNCTION
+rk_strunvis(char *dst, const char *src)
+{
+ char c;
+ char *start = dst;
+ int state = 0;
+
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(dst != NULL);
+
+ while ((c = *src++) != '\0') {
+ again:
+ switch (rk_unvis(dst, (unsigned char)c, &state, 0)) {
+ case UNVIS_VALID:
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ return (-1);
+ }
+ }
+ if (unvis(dst, (unsigned char)c, &state, UNVIS_END) == UNVIS_VALID)
+ dst++;
+ *dst = '\0';
+ return (dst - start);
+}
diff --git a/lib/roken/verify.c b/lib/roken/verify.c
new file mode 100644
index 0000000000000..54ad814e9827e
--- /dev/null
+++ b/lib/roken/verify.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: verify.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+unix_verify_user(char *user, char *password)
+{
+ struct passwd *pw;
+
+ pw = k_getpwnam(user);
+ if(pw == NULL)
+ return -1;
+ if(strlen(pw->pw_passwd) == 0 && strlen(password) == 0)
+ return 0;
+ if(strcmp(crypt(password, pw->pw_passwd), pw->pw_passwd) == 0)
+ return 0;
+ return -1;
+}
+
diff --git a/lib/roken/verr.c b/lib/roken/verr.c
new file mode 100644
index 0000000000000..3db3c1c37c097
--- /dev/null
+++ b/lib/roken/verr.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: verr.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+verr(int eval, const char *fmt, va_list ap)
+{
+ warnerr(1, fmt, ap);
+ exit(eval);
+}
diff --git a/lib/roken/verrx.c b/lib/roken/verrx.c
new file mode 100644
index 0000000000000..a3a59d02b130e
--- /dev/null
+++ b/lib/roken/verrx.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: verrx.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+verrx(int eval, const char *fmt, va_list ap)
+{
+ warnerr(0, fmt, ap);
+ exit(eval);
+}
diff --git a/lib/roken/vis.c b/lib/roken/vis.c
new file mode 100644
index 0000000000000..1114223a2974c
--- /dev/null
+++ b/lib/roken/vis.c
@@ -0,0 +1,335 @@
+/* $NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $ */
+
+/*-
+ * Copyright (c) 1989, 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. 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.
+ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ *
+ * 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.
+ */
+
+
+#if 1
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: vis.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+#include "roken.h"
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+#else
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $");
+#endif /* not lint */
+#endif
+
+#if 0
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <vis.h>
+
+#if 0
+#ifdef __weak_alias
+__weak_alias(strsvis,_strsvis)
+__weak_alias(strsvisx,_strsvisx)
+__weak_alias(strvis,_strvis)
+__weak_alias(strvisx,_strvisx)
+__weak_alias(svis,_svis)
+__weak_alias(vis,_vis)
+#endif
+#endif
+
+#undef BELL
+#if defined(__STDC__)
+#define BELL '\a'
+#else
+#define BELL '\007'
+#endif
+
+char ROKEN_LIB_FUNCTION
+ *rk_vis (char *, int, int, int);
+char ROKEN_LIB_FUNCTION
+ *rk_svis (char *, int, int, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvis (char *, const char *, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvis (char *, const char *, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvisx (char *, const char *, size_t, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvisx (char *, const char *, size_t, int, const char *);
+
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
+#define issafe(c) (c == '\b' || c == BELL || c == '\r')
+
+#define MAXEXTRAS 5
+
+
+#define MAKEEXTRALIST(flag, extra) \
+do { \
+ char *pextra = extra; \
+ if (flag & VIS_SP) *pextra++ = ' '; \
+ if (flag & VIS_TAB) *pextra++ = '\t'; \
+ if (flag & VIS_NL) *pextra++ = '\n'; \
+ if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\'; \
+ *pextra = '\0'; \
+} while (/*CONSTCOND*/0)
+
+/*
+ * This is SVIS, the central macro of vis.
+ * dst: Pointer to the destination buffer
+ * c: Character to encode
+ * flag: Flag word
+ * nextc: The character following 'c'
+ * extra: Pointer to the list of extra characters to be
+ * backslash-protected.
+ */
+#define SVIS(dst, c, flag, nextc, extra) \
+do { \
+ int isextra, isc; \
+ isextra = strchr(extra, c) != NULL; \
+ if (!isextra && \
+ isascii((unsigned char)c) && \
+ (isgraph((unsigned char)c) || iswhite(c) || \
+ ((flag & VIS_SAFE) && issafe(c)))) { \
+ *dst++ = c; \
+ break; \
+ } \
+ isc = 0; \
+ if (flag & VIS_CSTYLE) { \
+ switch (c) { \
+ case '\n': \
+ isc = 1; *dst++ = '\\'; *dst++ = 'n'; \
+ break; \
+ case '\r': \
+ isc = 1; *dst++ = '\\'; *dst++ = 'r'; \
+ break; \
+ case '\b': \
+ isc = 1; *dst++ = '\\'; *dst++ = 'b'; \
+ break; \
+ case BELL: \
+ isc = 1; *dst++ = '\\'; *dst++ = 'a'; \
+ break; \
+ case '\v': \
+ isc = 1; *dst++ = '\\'; *dst++ = 'v'; \
+ break; \
+ case '\t': \
+ isc = 1; *dst++ = '\\'; *dst++ = 't'; \
+ break; \
+ case '\f': \
+ isc = 1; *dst++ = '\\'; *dst++ = 'f'; \
+ break; \
+ case ' ': \
+ isc = 1; *dst++ = '\\'; *dst++ = 's'; \
+ break; \
+ case '\0': \
+ isc = 1; *dst++ = '\\'; *dst++ = '0'; \
+ if (isoctal(nextc)) { \
+ *dst++ = '0'; \
+ *dst++ = '0'; \
+ } \
+ } \
+ } \
+ if (isc) break; \
+ if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
+ *dst++ = '\\'; \
+ *dst++ = (u_char)(((unsigned)(u_char)c >> 6) & 03) + '0'; \
+ *dst++ = (u_char)(((unsigned)(u_char)c >> 3) & 07) + '0'; \
+ *dst++ = (c & 07) + '0'; \
+ } else { \
+ if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
+ if (c & 0200) { \
+ c &= 0177; *dst++ = 'M'; \
+ } \
+ if (iscntrl((unsigned char)c)) { \
+ *dst++ = '^'; \
+ if (c == 0177) \
+ *dst++ = '?'; \
+ else \
+ *dst++ = c + '@'; \
+ } else { \
+ *dst++ = '-'; *dst++ = c; \
+ } \
+ } \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * svis - visually encode characters, also encoding the characters
+ * pointed to by `extra'
+ */
+
+char * ROKEN_LIB_FUNCTION
+rk_svis(char *dst, int c, int flag, int nextc, const char *extra)
+{
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(extra != NULL);
+
+ SVIS(dst, c, flag, nextc, extra);
+ *dst = '\0';
+ return(dst);
+}
+
+
+/*
+ * strsvis, strsvisx - visually encode characters from src into dst
+ *
+ * Extra is a pointer to a \0-terminated list of characters to
+ * be encoded, too. These functions are useful e. g. to
+ * encode strings in such a way so that they are not interpreted
+ * by a shell.
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strsvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+
+int ROKEN_LIB_FUNCTION
+rk_strsvis(char *dst, const char *src, int flag, const char *extra)
+{
+ char c;
+ char *start;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ SVIS(dst, c, flag, *src, extra);
+ *dst = '\0';
+ return (dst - start);
+}
+
+
+int ROKEN_LIB_FUNCTION
+rk_strsvisx(char *dst, const char *src, size_t len, int flag, const char *extra)
+{
+ char c;
+ char *start;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(extra != NULL);
+
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ SVIS(dst, c, flag, len ? *src : '\0', extra);
+ }
+ *dst = '\0';
+ return (dst - start);
+}
+
+
+/*
+ * vis - visually encode characters
+ */
+char * ROKEN_LIB_FUNCTION
+rk_vis(char *dst, int c, int flag, int nextc)
+{
+ char extra[MAXEXTRAS];
+
+ _DIAGASSERT(dst != NULL);
+
+ MAKEEXTRALIST(flag, extra);
+ SVIS(dst, c, flag, nextc, extra);
+ *dst = '\0';
+ return (dst);
+}
+
+
+/*
+ * strvis, strvisx - visually encode characters from src into dst
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+
+int ROKEN_LIB_FUNCTION
+rk_strvis(char *dst, const char *src, int flag)
+{
+ char extra[MAXEXTRAS];
+
+ MAKEEXTRALIST(flag, extra);
+ return (rk_strsvis(dst, src, flag, extra));
+}
+
+
+int ROKEN_LIB_FUNCTION
+rk_strvisx(char *dst, const char *src, size_t len, int flag)
+{
+ char extra[MAXEXTRAS];
+
+ MAKEEXTRALIST(flag, extra);
+ return (rk_strsvisx(dst, src, len, flag, extra));
+}
diff --git a/lib/roken/vis.h b/lib/roken/vis.h
new file mode 100644
index 0000000000000..224870b00af1b
--- /dev/null
+++ b/lib/roken/vis.h
@@ -0,0 +1,115 @@
+/* $NetBSD: vis.h,v 1.11 1999/11/25 16:55:50 wennmach Exp $ */
+/* $Id: vis.hin 19341 2006-12-15 11:53:09Z lha $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ *
+ * @(#)vis.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _VIS_H_
+#define _VIS_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+char ROKEN_LIB_FUNCTION
+ *rk_vis (char *, int, int, int);
+char ROKEN_LIB_FUNCTION
+ *rk_svis (char *, int, int, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvis (char *, const char *, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvis (char *, const char *, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvisx (char *, const char *, size_t, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvisx (char *, const char *, size_t, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strunvis (char *, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_unvis (char *, int, int *, int);
+
+#undef vis
+#define vis(a,b,c,d) rk_vis(a,b,c,d)
+#undef svis
+#define svis(a,b,c,d,e) rk_svis(a,b,c,d,e)
+#undef strvis
+#define strvis(a,b,c) rk_strvis(a,b,c)
+#undef strsvis
+#define strsvis(a,b,c,d) rk_strsvis(a,b,c,d)
+#undef strvisx
+#define strvisx(a,b,c,d) rk_strvisx(a,b,c,d)
+#undef strsvisx
+#define strsvisx(a,b,c,d,e) rk_strsvisx(a,b,c,d,e)
+#undef strunvis
+#define strunvis(a,b) rk_strunvis(a,b)
+#undef unvis
+#define unvis(a,b,c,d) rk_unvis(a,b,c,d)
+
+#endif /* !_VIS_H_ */
diff --git a/lib/roken/vis.hin b/lib/roken/vis.hin
new file mode 100644
index 0000000000000..224870b00af1b
--- /dev/null
+++ b/lib/roken/vis.hin
@@ -0,0 +1,115 @@
+/* $NetBSD: vis.h,v 1.11 1999/11/25 16:55:50 wennmach Exp $ */
+/* $Id: vis.hin 19341 2006-12-15 11:53:09Z lha $ */
+
+/*-
+ * Copyright (c) 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. 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.
+ *
+ * @(#)vis.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _VIS_H_
+#define _VIS_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+char ROKEN_LIB_FUNCTION
+ *rk_vis (char *, int, int, int);
+char ROKEN_LIB_FUNCTION
+ *rk_svis (char *, int, int, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvis (char *, const char *, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvis (char *, const char *, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strvisx (char *, const char *, size_t, int);
+int ROKEN_LIB_FUNCTION
+ rk_strsvisx (char *, const char *, size_t, int, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_strunvis (char *, const char *);
+int ROKEN_LIB_FUNCTION
+ rk_unvis (char *, int, int *, int);
+
+#undef vis
+#define vis(a,b,c,d) rk_vis(a,b,c,d)
+#undef svis
+#define svis(a,b,c,d,e) rk_svis(a,b,c,d,e)
+#undef strvis
+#define strvis(a,b,c) rk_strvis(a,b,c)
+#undef strsvis
+#define strsvis(a,b,c,d) rk_strsvis(a,b,c,d)
+#undef strvisx
+#define strvisx(a,b,c,d) rk_strvisx(a,b,c,d)
+#undef strsvisx
+#define strsvisx(a,b,c,d,e) rk_strsvisx(a,b,c,d,e)
+#undef strunvis
+#define strunvis(a,b) rk_strunvis(a,b)
+#undef unvis
+#define unvis(a,b,c,d) rk_unvis(a,b,c,d)
+
+#endif /* !_VIS_H_ */
diff --git a/lib/roken/vsyslog.c b/lib/roken/vsyslog.c
new file mode 100644
index 0000000000000..690eb7dc075af
--- /dev/null
+++ b/lib/roken/vsyslog.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: vsyslog.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#ifndef HAVE_VSYSLOG
+
+#include <stdio.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "roken.h"
+
+/*
+ * the theory behind this is that we might be trying to call vsyslog
+ * when there's no memory left, and we should try to be as useful as
+ * possible. And the format string should say something about what's
+ * failing.
+ */
+
+static void
+simple_vsyslog(int pri, const char *fmt, va_list ap)
+{
+ syslog (pri, "%s", fmt);
+}
+
+/*
+ * do like syslog but with a `va_list'
+ */
+
+void ROKEN_LIB_FUNCTION
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+ char *fmt2;
+ const char *p;
+ char *p2;
+ int saved_errno = errno;
+ int fmt_len = strlen (fmt);
+ int fmt2_len = fmt_len;
+ char *buf;
+
+ fmt2 = malloc (fmt_len + 1);
+ if (fmt2 == NULL) {
+ simple_vsyslog (pri, fmt, ap);
+ return;
+ }
+
+ for (p = fmt, p2 = fmt2; *p != '\0'; ++p) {
+ if (p[0] == '%' && p[1] == 'm') {
+ const char *e = strerror (saved_errno);
+ int e_len = strlen (e);
+ char *tmp;
+ int pos;
+
+ pos = p2 - fmt2;
+ fmt2_len += e_len - 2;
+ tmp = realloc (fmt2, fmt2_len + 1);
+ if (tmp == NULL) {
+ free (fmt2);
+ simple_vsyslog (pri, fmt, ap);
+ return;
+ }
+ fmt2 = tmp;
+ p2 = fmt2 + pos;
+ memmove (p2, e, e_len);
+ p2 += e_len;
+ ++p;
+ } else
+ *p2++ = *p;
+ }
+ *p2 = '\0';
+
+ vasprintf (&buf, fmt2, ap);
+ free (fmt2);
+ if (buf == NULL) {
+ simple_vsyslog (pri, fmt, ap);
+ return;
+ }
+ syslog (pri, "%s", buf);
+ free (buf);
+}
+#endif
diff --git a/lib/roken/vwarn.c b/lib/roken/vwarn.c
new file mode 100644
index 0000000000000..c25ca629ca227
--- /dev/null
+++ b/lib/roken/vwarn.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: vwarn.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+vwarn(const char *fmt, va_list ap)
+{
+ warnerr(1, fmt, ap);
+}
diff --git a/lib/roken/vwarnx.c b/lib/roken/vwarnx.c
new file mode 100644
index 0000000000000..e35c0deb09b83
--- /dev/null
+++ b/lib/roken/vwarnx.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: vwarnx.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+vwarnx(const char *fmt, va_list ap)
+{
+ warnerr(0, fmt, ap);
+}
+
diff --git a/lib/roken/warn.c b/lib/roken/warn.c
new file mode 100644
index 0000000000000..0924880e4cb68
--- /dev/null
+++ b/lib/roken/warn.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: warn.c 7463 1999-12-02 16:58:55Z joda $");
+#endif
+
+#include "err.h"
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/roken/warnerr.c b/lib/roken/warnerr.c
new file mode 100644
index 0000000000000..6dee466bc670c
--- /dev/null
+++ b/lib/roken/warnerr.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: warnerr.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+warnerr(int doerrno, const char *fmt, va_list ap)
+{
+ int sverrno = errno;
+ const char *progname = getprogname();
+
+ if(progname != NULL){
+ fprintf(stderr, "%s", progname);
+ if(fmt != NULL || doerrno)
+ fprintf(stderr, ": ");
+ }
+ if (fmt != NULL){
+ vfprintf(stderr, fmt, ap);
+ if(doerrno)
+ fprintf(stderr, ": ");
+ }
+ if(doerrno)
+ fprintf(stderr, "%s", strerror(sverrno));
+ fprintf(stderr, "\n");
+}
diff --git a/lib/roken/warnx.c b/lib/roken/warnx.c
new file mode 100644
index 0000000000000..7e1de7acc1b61
--- /dev/null
+++ b/lib/roken/warnx.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: warnx.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/roken/write_pid.c b/lib/roken/write_pid.c
new file mode 100644
index 0000000000000..edadf5ceb33e4
--- /dev/null
+++ b/lib/roken/write_pid.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: write_pid.c 21005 2007-06-08 01:54:35Z lha $");
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "roken.h"
+
+#include "roken.h"
+
+char * ROKEN_LIB_FUNCTION
+pid_file_write (const char *progname)
+{
+ FILE *fp;
+ char *ret;
+
+ asprintf (&ret, "%s%s.pid", _PATH_VARRUN, progname);
+ if (ret == NULL)
+ return NULL;
+ fp = fopen (ret, "w");
+ if (fp == NULL) {
+ free (ret);
+ return NULL;
+ }
+ fprintf (fp, "%u", (unsigned)getpid());
+ fclose (fp);
+ return ret;
+}
+
+void ROKEN_LIB_FUNCTION
+pid_file_delete (char **filename)
+{
+ if (*filename != NULL) {
+ unlink (*filename);
+ free (*filename);
+ *filename = NULL;
+ }
+}
+
+#ifndef HAVE_PIDFILE
+static char *pidfile_path;
+
+static void
+pidfile_cleanup(void)
+{
+ if(pidfile_path != NULL)
+ pid_file_delete(&pidfile_path);
+}
+
+void
+pidfile(const char *basename)
+{
+ if(pidfile_path != NULL)
+ return;
+ if(basename == NULL)
+ basename = getprogname();
+ pidfile_path = pid_file_write(basename);
+#if defined(HAVE_ATEXIT)
+ atexit(pidfile_cleanup);
+#elif defined(HAVE_ON_EXIT)
+ on_exit(pidfile_cleanup);
+#endif
+}
+#endif
diff --git a/lib/roken/writev.c b/lib/roken/writev.c
new file mode 100644
index 0000000000000..2500e6d28f0d9
--- /dev/null
+++ b/lib/roken/writev.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: writev.c 14773 2005-04-12 11:29:18Z lha $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+writev(int d, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret;
+ size_t tot = 0;
+ int i;
+ char *buf, *p;
+
+ for(i = 0; i < iovcnt; ++i)
+ tot += iov[i].iov_len;
+ buf = malloc(tot);
+ if (tot != 0 && buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ p = buf;
+ for (i = 0; i < iovcnt; ++i) {
+ memcpy (p, iov[i].iov_base, iov[i].iov_len);
+ p += iov[i].iov_len;
+ }
+ ret = write (d, buf, tot);
+ free (buf);
+ return ret;
+}
diff --git a/lib/roken/xdbm.h b/lib/roken/xdbm.h
new file mode 100644
index 0000000000000..618e074d1e66d
--- /dev/null
+++ b/lib/roken/xdbm.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: xdbm.h 10986 2002-05-17 16:02:22Z joda $ */
+
+/* Generic *dbm include file */
+
+#ifndef __XDBM_H__
+#define __XDBM_H__
+
+#if HAVE_DB_NDBM
+#define DB_DBM_HSEARCH 1
+#include <db.h>
+#elif HAVE_NDBM
+#if defined(HAVE_GDBM_NDBM_H)
+#include <gdbm/ndbm.h>
+#elif defined(HAVE_NDBM_H)
+#include <ndbm.h>
+#endif
+#endif /* HAVE_NDBM */
+
+#endif /* __XDBM_H__ */