diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /third_party/heimdal/lib/roken | |
parent | Initial commit. (diff) | |
download | samba-upstream.tar.xz samba-upstream.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/heimdal/lib/roken')
214 files changed, 36245 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/roken/ChangeLog b/third_party/heimdal/lib/roken/ChangeLog new file mode 100644 index 0000000..518987b --- /dev/null +++ b/third_party/heimdal/lib/roken/ChangeLog @@ -0,0 +1,2229 @@ +2008-07-12 Love Hörnquist Åstrand <lha@kth.se> + + * rkpty.c: Always print output for status. + +2008-04-27 Love Hörnquist Åstrand <lha@it.su.se> + + * getaddrinfo-test.c: drop ) + + * Makefile.am: Add rkpty. + + * rkpty.c: More includes. + + * rkpty.c: Add timeout, add password command, add diffrent + verbosity levels. + +2008-04-26 Love Hörnquist Åstrand <lha@it.su.se> + + * rkpty.c: pty testing application + +2008-04-07 Love Hörnquist Åstrand <lha@it.su.se> + + * resolve.c: Use unsigned where appropriate. + +2008-02-23 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: make AM_CPPFLAGS += + +2008-02-22 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Use AM_CPPFLAGS instead, not really right, but + definatly better then CPPFLAGS. Thanks to Mike Whitton for + pointing this out. + +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/third_party/heimdal/lib/roken/Makefile.am b/third_party/heimdal/lib/roken/Makefile.am new file mode 100644 index 0000000..35d7532 --- /dev/null +++ b/third_party/heimdal/lib/roken/Makefile.am @@ -0,0 +1,290 @@ +# $Id$ + +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 20:0:1 +libroken_la_CPPFLAGS = -DBUILD_ROKEN_LIB + +if versionscript +libroken_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +endif + +AM_CPPFLAGS += $(libroken_la_CPPFLAGS) +if HAVE_DBHEADER +AM_CPPFLAGS += -I$(DBHEADER) +endif + +bin_PROGRAMS = rkvis rkbase32 rkbase64 +noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach test-auxval rtbl timeval + +CHECK_LOCAL = snprintf-test resolve-test rkpty make-roken + +check_PROGRAMS = \ + base32-test \ + base64-test \ + getaddrinfo-test \ + getifaddrs-test \ + hex-test \ + test-auxval \ + test-getuserinfo \ + test-readenv \ + resolve-test \ + parse_bytes-test \ + parse_reply-test \ + parse_time-test \ + snprintf-test \ + strpftime-test \ + timeval \ + tsearch-test + +TESTS = $(check_PROGRAMS) + +LDADD = libroken.la +make_roken_LDADD = + +noinst_LTLIBRARIES = libtest.la +libtest_la_SOURCES = strftime.c strptime.c snprintf.c tsearch.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 +test_auxval_SOURCES = test-auxval.c +test_getuserinfo_SOURCES = test-getuserinfo.c +test_getuserinfo_LDADD = libtest.la $(LDADD) + +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_ifaddrs_h +ifaddrs_h = +else +ifaddrs_h = ifaddrs.h +endif + +if have_search_h +search_h = +else +search_h = search.h +endif + +if have_vis_h +vis_h = +else +vis_h = vis.h +endif + +timeval_SOURCES = timeval.c +timeval_CPPFLAGS = -DTEST + +rkvis_SOURCES = vis.c $(vis_h) vis-extras.h +rkvis_CPPFLAGS = -DTEST + +rkbase32_SOURCES = base32.c +rkbase32_CPPFLAGS = -DTEST + +rkbase64_SOURCES = base64.c +rkbase64_CPPFLAGS = -DTEST + +rtbl_SOURCES = rtbl.c +rtbl_CPPFLAGS = -DTEST + +test_detach_SOURCES = test-detach.c + +rkpty_LDADD = $(LIB_openpty) $(LDADD) + +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_LDADD = libtest.la $(LDADD) +snprintf_test_CFLAGS = -DTEST_SNPRINTF +tsearch_test_SOURCES = tsearch-test.c +tsearch_test_LDADD = libtest.la $(LDADD) +tsearch_test_CFLAGS = -DTEST_TSEARCH + +resolve_test_SOURCES = resolve-test.c + +libroken_la_SOURCES = \ + base32.c \ + base64.c \ + bswap.c \ + concat.c \ + cloexec.c \ + clz.c \ + ct.c \ + detach.c \ + doxygen.c \ + dumpdata.c \ + environment.c \ + eread.c \ + esetenv.c \ + ewrite.c \ + fseeko.c \ + ftello.c \ + getaddrinfo_hostspec.c \ + get_window_size.c \ + getarg.c \ + getauxval.c \ + getauxval.h \ + getnameinfo_verified.c \ + getprogname.c \ + getuserinfo.c \ + h_errno.c \ + hex.c \ + hostent_find_fqdn.c \ + issuid.c \ + memmem.c \ + mini_inetd.c \ + mkdir.c \ + mkdtemp.c \ + mkostemp.c \ + net_read.c \ + net_write.c \ + parse_bytes.c \ + parse_time.c \ + parse_units.c \ + qsort.c \ + rand.c \ + realloc.c \ + resolve.c \ + roken_gethostby.c \ + rtbl.c \ + rtbl.h \ + secure_getenv.c \ + secure_getenv.h \ + setprogname.c \ + signal.c \ + simple_exec.c \ + snprintf.c \ + socket.c \ + strcollect.c \ + strerror_r.c \ + strpool.c \ + timeval.c \ + tm2time.c \ + unvis.c \ + vis.c \ + $(vis_h) \ + vis-extras.h \ + warnerr.c \ + write_pid.c \ + xfree.c \ + xdbm.h + +EXTRA_libroken_la_SOURCES = \ + err.hin \ + fnmatch.hin \ + ifaddrs.hin \ + search.hin \ + vis.hin + +libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt) $(LIB_pidfile) + +$(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS) + +BUILT_SOURCES = roken.h $(err_h) $(fnmatch_h) $(ifadds_h) $(search_h) $(vis_h) + +## these are controlled by configure +XHEADERS = $(err_h) $(fnmatch_h) $(ifaddrs_h) $(search_h) $(vis_h) +CLEANFILES += err.h fnmatch.h ifaddrs.h search.h vis.h + +dist_include_HEADERS = \ + base32.h \ + 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 $< $@ + +# Make make-roken deprecated in 1.4 when we know that roken-h-process.pl works +if !CROSS_COMPILE + +noinst_PROGRAMS += make-roken +BUILT_SOURCES += make-roken.c + +nodist_make_roken_SOURCES = make-roken.c + +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 + +else + +roken.h: $(top_srcdir)/cf/roken-h-process.pl roken.h.in + perl $(top_srcdir)/cf/roken-h-process.pl \ + -c $(top_builddir)/include/config.h \ + -p $(srcdir)/roken.h.in -o roken.h + +endif + + +EXTRA_DIST = \ + NTMakefile \ + roken.awk roken.h.in \ + $(man_MANS) \ + dirent.c \ + dirent.hin \ + dirent-test.c \ + dlfcn.hin \ + dlfcn_w32.c \ + getifaddrs_w32.c \ + ndbm_wrap.c \ + ndbm_wrap.h \ + rename.c \ + simple_exec_w32.c \ + sleep.c \ + sockstartup_w32.c \ + stdbool.hin \ + stdint.hin \ + syslogc.c \ + syslog.hin \ + test-auxval.c \ + test-mem.h \ + test-mini_inetd.c \ + win32_alloc.c \ + version-script.map diff --git a/third_party/heimdal/lib/roken/NTMakefile b/third_party/heimdal/lib/roken/NTMakefile new file mode 100644 index 0000000..5749efd --- /dev/null +++ b/third_party/heimdal/lib/roken/NTMakefile @@ -0,0 +1,312 @@ +######################################################################## +# +# Copyright (c) 2009 - 2017, Secure Endpoints Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - 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. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 +# COPYRIGHT HOLDER 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. +# + +RELDIR=lib\roken + +!include ../../windows/NTMakefile.w32 + +libroken_la_OBJS = \ + $(OBJ)\base32.obj \ + $(OBJ)\base64.obj \ + $(OBJ)\bswap.obj \ + $(OBJ)\concat.obj \ + $(OBJ)\cloexec.obj \ + $(OBJ)\clz.obj \ + $(OBJ)\ct.obj \ + $(OBJ)\detach.obj \ + $(OBJ)\dirent.obj \ + $(OBJ)\dlfcn_w32.obj \ + $(OBJ)\dumpdata.obj \ + $(OBJ)\ecalloc.obj \ + $(OBJ)\emalloc.obj \ + $(OBJ)\environment.obj \ + $(OBJ)\eread.obj \ + $(OBJ)\erealloc.obj \ + $(OBJ)\err.obj \ + $(OBJ)\errx.obj \ + $(OBJ)\esetenv.obj \ + $(OBJ)\estrdup.obj \ + $(OBJ)\ewrite.obj \ + $(OBJ)\flock.obj \ + $(OBJ)\fnmatch.obj \ + $(OBJ)\fseeko.obj \ + $(OBJ)\ftello.obj \ + $(OBJ)\getauxval.obj \ + $(OBJ)\getaddrinfo_hostspec.obj \ + $(OBJ)\get_window_size.obj \ + $(OBJ)\getarg.obj \ + $(OBJ)\getifaddrs_w32.obj \ + $(OBJ)\getnameinfo_verified.obj \ + $(OBJ)\getopt.obj \ + $(OBJ)\getprogname.obj \ + $(OBJ)\gettimeofday.obj \ + $(OBJ)\getuserinfo.obj \ + $(OBJ)\hex.obj \ + $(OBJ)\hostent_find_fqdn.obj \ + $(OBJ)\inet_aton.obj \ + $(OBJ)\issuid.obj \ + $(OBJ)\localtime_r.obj \ + $(OBJ)\lstat.obj \ + $(OBJ)\memmem.obj \ + $(OBJ)\memset_s.obj \ + $(OBJ)\mergesort_r.obj \ + $(OBJ)\mkdir.obj \ + $(OBJ)\mini_inetd.obj \ + $(OBJ)\mkdtemp.obj \ + $(OBJ)\mkstemp.obj \ + $(OBJ)\mkostemp.obj \ + $(OBJ)\net_read.obj \ + $(OBJ)\net_write.obj \ + $(OBJ)\parse_bytes.obj \ + $(OBJ)\parse_time.obj \ + $(OBJ)\parse_units.obj \ + $(OBJ)\realloc.obj \ + $(OBJ)\rename.obj \ + $(OBJ)\resolve.obj \ + $(OBJ)\rand.obj \ + $(OBJ)\roken_gethostby.obj \ + $(OBJ)\rtbl.obj \ + $(OBJ)\secure_getenv.obj \ + $(OBJ)\sendmsg.obj \ + $(OBJ)\setenv.obj \ + $(OBJ)\setprogname.obj \ + $(OBJ)\simple_exec_w32.obj \ + $(OBJ)\sleep.obj \ + $(OBJ)\snprintf.obj \ + $(OBJ)\socket.obj \ + $(OBJ)\sockstartup_w32.obj \ + $(OBJ)\strcollect.obj \ + $(OBJ)\strerror_r.obj \ + $(OBJ)\strftime.obj \ + $(OBJ)\strlcat.obj \ + $(OBJ)\strlcpy.obj \ + $(OBJ)\strndup.obj \ + $(OBJ)\strpool.obj \ + $(OBJ)\strptime.obj \ + $(OBJ)\strsep.obj \ + $(OBJ)\strsep_copy.obj \ + $(OBJ)\strtok_r.obj \ + $(OBJ)\strtoll.obj \ + $(OBJ)\strtoull.obj \ + $(OBJ)\syslogc.obj \ + $(OBJ)\timegm.obj \ + $(OBJ)\timeval.obj \ + $(OBJ)\tm2time.obj \ + $(OBJ)\tsearch.obj \ + $(OBJ)\unvis.obj \ + $(OBJ)\verr.obj \ + $(OBJ)\verrx.obj \ + $(OBJ)\vis.obj \ + $(OBJ)\vwarn.obj \ + $(OBJ)\vwarnx.obj \ + $(OBJ)\warn.obj \ + $(OBJ)\warnerr.obj \ + $(OBJ)\warnx.obj \ + $(OBJ)\win32_alloc.obj \ + $(OBJ)\win32_version.obj \ + $(OBJ)\writev.obj \ + $(OBJ)\xfree.obj + +!if $(NMAKE_WINVER) < 0x0600 +libroken_la_OBJS=$(libroken_la_OBJS) \ + $(OBJ)\inet_ntop.obj \ + $(OBJ)\inet_pton.obj +!endif + +{}.c{$(OBJ)}.obj:: + $(C2OBJ_P) -DBUILD_ROKEN_LIB + +$(LIBROKEN): $(libroken_la_OBJS) + $(LIBCON_C) -out:$@ @<< +$(**: = +) +<< + +$(OBJ)\make-roken.exe: $(OBJ)\make-roken.obj + $(EXECONLINK) + +$(OBJ)\make-roken.c: roken.h.in roken.awk $(INCDIR)\config.h + $(AWK) -f roken.awk roken.h.in > $(OBJ)\make-roken.c || $(RM) $(OBJ)\make-roken.c + +$(INCDIR)\roken.h: $(OBJ)\make-roken.exe + $(OBJ)\make-roken.exe > $@ || $(RM) $@ + +INCFILES = \ + $(INCDIR)\base32.h \ + $(INCDIR)\base64.h \ + $(INCDIR)\dirent.h \ + $(INCDIR)\dlfcn.h \ + $(INCDIR)\err.h \ + $(INCDIR)\fnmatch.h \ + $(INCDIR)\getarg.h \ + $(INCDIR)\hex.h \ + $(INCDIR)\ifaddrs.h \ + $(INCDIR)\parse_bytes.h \ + $(INCDIR)\parse_time.h \ + $(INCDIR)\parse_units.h \ + $(INCDIR)\resolve.h \ + $(INCDIR)\roken.h \ + $(INCDIR)\roken-common.h \ + $(INCDIR)\rtbl.h \ + $(INCDIR)\search.h \ + $(INCDIR)\stdbool.h \ + $(INCDIR)\syslog.h \ + $(INCDIR)\vis.h \ + $(INCDIR)\vis-extras.h \ +!ifndef HAVE_STDINT_H + $(INCDIR)\stdint.h \ +!endif + $(INCDIR)\versionsupport.h \ + $(INCDIR)\xdbm.h + +clean:: + -$(RM) $(XHEADERS) + +all:: $(INCFILES) $(LIBROKEN) + +clean:: + -$(RM) $(LIBROKEN) + +TMP_PROGS = $(OBJ)\snprintf-test.exe $(OBJ)\resolve-test.exe $(OBJ)\test-getuserinfo.exe + +# Tests + +TEST_PROGS = \ + $(OBJ)\base32-test.exe \ + $(OBJ)\base64-test.exe \ + $(OBJ)\getaddrinfo-test.exe \ + $(OBJ)\getifaddrs-test.exe \ + $(OBJ)\hex-test.exe \ + $(OBJ)\test-detach.exe \ + $(OBJ)\test-getuserinfo.exe \ + $(OBJ)\test-readenv.exe \ + $(OBJ)\parse_bytes-test.exe \ + $(OBJ)\parse_reply-test.exe \ + $(OBJ)\parse_time-test.exe \ + $(OBJ)\snprintf-test.exe \ + $(OBJ)\strpftime-test.exe \ + $(OBJ)\dirent-test.exe \ + $(OBJ)\test-mini_inetd.exe + +$(OBJ)\strftime_test.obj: strftime.c + $(C2OBJ) -DTEST_SNPRINTF -DTEST_STRPFTIME -DBUILD_ROKEN_LIB + +$(OBJ)\strptime_test.obj: strptime.c + $(C2OBJ) -DTEST_SNPRINTF -DTEST_STRPFTIME -DBUILD_ROKEN_LIB + +$(OBJ)\snprintf_test.obj: snprintf.c + $(C2OBJ) -DTEST_SNPRINTF -DTEST_STRPFTIME -DBUILD_ROKEN_LIB + +$(OBJ)\libtest.lib: $(OBJ)\strftime_test.obj $(OBJ)\strptime_test.obj $(OBJ)\snprintf_test.obj + $(LIBCON) + +$(OBJ)\parse_reply-test.obj: parse_reply-test.c + $(C2OBJ) -DTEST_RESOLVE -DBUILD_ROKEN_LIB + +$(OBJ)\resolve_test.obj: resolve.c + $(C2OBJ) -DTEST_RESOLVE -DBUILD_ROKEN_LIB + +$(OBJ)\parse_reply-test.exe: $(OBJ)\parse_reply-test.obj $(OBJ)\resolve_test.obj $(LIBROKEN) + $(EXECONLINK) DnsAPI.lib + +$(OBJ)\test-readenv.exe: $(OBJ)\test-readenv.obj $(OBJ)\test-mem.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\parse_time-test.exe: $(OBJ)\parse_time-test.obj $(OBJ)\test-mem.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\strpftime-test.obj: strpftime-test.c + $(C2OBJ) -DTEST_STRPFTIME -DBUILD_ROKEN_LIB + +$(OBJ)\strpftime-test.exe: $(OBJ)\strpftime-test.obj $(OBJ)\libtest.lib $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\snprintf-test.obj: snprintf-test.c + $(C2OBJ) -DTEST_SNPRINTF -DBUILD_ROKEN_LIB + +$(OBJ)\snprintf-test.exe: $(OBJ)\snprintf-test.obj $(OBJ)\libtest.lib $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\resolve-test.exe: $(OBJ)\resolve-test.obj $(LIBROKEN) + $(EXECONLINK) DnsAPI.lib + +$(OBJ)\base32-test.exe: $(OBJ)\base32-test.obj $(OBJ)\base32.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\base64-test.exe: $(OBJ)\base64-test.obj $(OBJ)\base64.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\getaddrinfo-test.exe: $(OBJ)\getaddrinfo-test.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\hex-test.exe: $(OBJ)\hex-test.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\parse_bytes-test.exe: $(OBJ)\parse_bytes-test.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\test-detach.exe: $(OBJ)\test-detach.obj $(OBJ)\detach.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\test-getuserinfo.exe: $(OBJ)\test-getuserinfo.obj $(OBJ)\getuserinfo.obj $(LIBROKEN) + $(EXECONLINK) Secur32.lib Shell32.lib + +$(OBJ)\dirent-test.exe: $(OBJ)\dirent-test.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\getifaddrs-test.exe: $(OBJ)\getifaddrs-test.obj $(LIBROKEN) + $(EXECONLINK) + +$(OBJ)\test-mini_inetd.exe: $(OBJ)\test-mini_inetd.obj $(LIBROKEN) + $(EXECONLINK) + +test-binaries: $(TEST_PROGS) $(TMP_PROGS) + +test-run: + cd $(OBJ) + -test-mini_inetd.exe + -dirent-test.exe + -base32-test.exe + -base64-test.exe + -getaddrinfo-test.exe www.h5l.org http + -getifaddrs-test.exe + -hex-test.exe + -test-readenv.exe + -parse_bytes-test.exe +# Need to rewrite this test: +# -parse_reply-test.exe + -parse_time-test.exe + -snprintf-test.exe + -strpftime-test.exe + cd $(SRCDIR) + +test:: test-binaries test-run + diff --git a/third_party/heimdal/lib/roken/base32-test.c b/third_party/heimdal/lib/roken/base32-test.c new file mode 100644 index 0000000..e30c193 --- /dev/null +++ b/third_party/heimdal/lib/roken/base32-test.c @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <base32.h> + +int +main(int argc, char **argv) +{ + int numerr = 0; + int numtest = 1; + struct test { + int preserve_order; + void *data; + size_t len; + const char *result; + } *t, tests[] = { + { 0, "", 0 , "" }, + { 0, "f", 1, "MY======" }, + { 0, "fo", 2, "MZXQ====" }, + { 0, "foo", 3, "MZXW6===" }, + { 0, "foob", 4, "MZXW6YQ=" }, + { 0, "fooba", 5, "MZXW6YTB" }, + { 0, "foobar", 6, "MZXW6YTBOI======" }, + { 1, "", 0 , "" }, + { 1, "f", 1, "CO======" }, + { 1, "fo", 2, "CPNG====" }, + { 1, "foo", 3, "CPNMU===" }, + { 1, "foob", 4, "CPNMUOG=" }, + { 1, "fooba", 5, "CPNMUOJ1" }, + { 1, "foobar", 6, "CPNMUOJ1E8======" }, + { 0, NULL, 0, NULL } + }; + for(t = tests; t->data; t++) { + char *str; + int len; + + (void) rk_base32_encode(t->data, t->len, &str, t->preserve_order); + 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 = rk_base32_decode(t->result, str, t->preserve_order); + 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 (rk_base32_decode("M=M=", str, 1) != -1) { + fprintf(stderr, "failed test %d: successful decode of `M=M='\n", + numtest++); + numerr++; + } + if (rk_base32_decode("MQ===", str, 1) != -1) { + fprintf(stderr, "failed test %d: successful decode of `MQ==='\n", + numtest++); + numerr++; + } + } + return numerr; +} diff --git a/third_party/heimdal/lib/roken/base32.c b/third_party/heimdal/lib/roken/base32.c new file mode 100644 index 0000000..ef74336 --- /dev/null +++ b/third_party/heimdal/lib/roken/base32.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2020 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. + */ + +#include <config.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#ifdef TEST +#include <stdio.h> +#include <getarg.h> +#include <err.h> +#endif +#include "base32.h" +#include "roken.h" + +static const unsigned char base32_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; +static const unsigned char base32op_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base32_encode(const void *data, int size, char **str, enum rk_base32_flags flags) +{ + const unsigned char *chars = + (flags & RK_BASE32_FLAG_PRESERVE_ORDER) ? base32op_chars : + base32_chars; + uint64_t c; + char *s, *p; + int i; + const unsigned char *q; + + if (size > INT_MAX/8 || size < 0) { + *str = NULL; + errno = ERANGE; + return -1; + } + + p = s = malloc(((size + 5 - 1) / 5) * 8 + 1); + if (p == NULL) { + *str = NULL; + return -1; + } + q = (const unsigned char *) data; + + for (i = 0; i < size;) { + /* 5 bytes of input will give us 8 output bytes' worth of bits */ + c = q[i++]; + c <<= 8; + if (i < size) + c += q[i]; + i++; + c <<= 8; + if (i < size) + c += q[i]; + i++; + c <<= 8; + if (i < size) + c += q[i]; + i++; + c <<= 8; + if (i < size) + c += q[i]; + i++; + p[0] = chars[(c & 0x00000000f800000000ULL) >> 35]; + p[1] = chars[(c & 0x0000000007c0000000ULL) >> 30]; + p[2] = chars[(c & 0x00000000003e000000ULL) >> 25]; + p[3] = chars[(c & 0x000000000001f00000ULL) >> 20]; + p[4] = chars[(c & 0x0000000000000f8000ULL) >> 15]; + p[5] = chars[(c & 0x000000000000007c00ULL) >> 10]; + p[6] = chars[(c & 0x0000000000000003e0ULL) >> 5]; + p[7] = chars[(c & 0x00000000000000001fULL) >> 0]; + switch (i - size) { + case 4: p[2] = p[3] = '='; fallthrough; + case 3: p[4] = '='; fallthrough; + case 2: p[5] = p[6] = '='; fallthrough; + case 1: p[7] = '='; fallthrough; + default: break; + } + p += 8; + } + *p = 0; + *str = s; + return (int) strlen(s); +} + +#define DECODE_ERROR ((uint64_t)-1) + +static int +pos(char c, int preserve_order) +{ + /* EBCDIC need not apply */ + if (preserve_order) { + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'A' && c <= 'V') + return c - 'A' + ('9' - '0') + 1; + } else { + if (c >= 'A' && c <= 'Z') + return c - 'A'; + if (c >= '2' && c <= '7') + return c - '2' + ('Z' - 'A') + 1; + } + return -1; +} + +static uint64_t +token_decode(const char *token, enum rk_base32_flags flags) +{ + uint64_t marker = 0; + uint64_t val = 0; + int preserve_order = !!(flags & RK_BASE32_FLAG_PRESERVE_ORDER); + int i, c; + + if (strlen(token) < 8) + return DECODE_ERROR; + for (i = 0; i < 8; i++) { + val <<= 5; + if (token[i] == '=') + marker++; + else if (marker) + return DECODE_ERROR; + else if ((c = pos(token[i], preserve_order)) == -1 && + (flags & RK_BASE32_FLAG_STOP_ON_GARBAGE)) + break; + else if (c == -1) + return DECODE_ERROR; + else + val |= c; + } + if (marker > 6) + return DECODE_ERROR; + return (marker << 40) | val; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base32_decode(const char *str, void *data, enum rk_base32_flags flags) +{ + const char *p; + unsigned char *q; + int preserve_order = !!(flags & RK_BASE32_FLAG_PRESERVE_ORDER); + + q = data; + for (p = str; *p && (*p == '=' || pos(*p, preserve_order) != -1); p += 8) { + uint64_t val = token_decode(p, flags); + uint64_t marker = (val >> 40) & 0xffULL; + + if (val == DECODE_ERROR) { + errno = EINVAL; + return -1; + } + *q++ = (val >> 32) & 0xffULL; + if (marker < 6) + *q++ = (val >> 24) & 0xffULL; + if (marker < 4) + *q++ = (val >> 16) & 0xffULL; + if (marker < 3) + *q++ = (val >> 8) & 0xffULL; + if (marker < 1) + *q++ = val & 0xffULL; + if (marker && !(flags & RK_BASE32_FLAG_INTERIOR_PADDING_OK)) + break; + } + if (q - (unsigned char *) data > INT_MAX) { + errno = EOVERFLOW; + return -1; + } + return q - (unsigned char *) data; +} + +#ifdef TEST +static int interior_padding_ok; +static int preserve_order_flag; +static int stop_on_garbage; +static int decode_flag; +static int help_flag; + +/* + * The short options are compatible with a subset of the FreeBSD contrib + * vis(1). Heimdal additions have long option names only. + */ +static struct getargs args[] = { + { "preserve-order", 'P', arg_flag, &preserve_order_flag, + "Use order-preserving alphabet", NULL }, + { "interior-padding-ok", 'O', arg_flag, &interior_padding_ok, + "Decode concatenated padded base32 strings as one", NULL }, + { "stop-on-garbage", 'G', arg_flag, &stop_on_garbage, + "Do not error on garbage", NULL }, + { "decode", 'd', arg_flag, &decode_flag, "Decode", NULL }, + { "help", 'h', arg_flag, &help_flag, "Print help message", NULL }, +}; +static size_t num_args = sizeof(args)/sizeof(args[0]); + +int +main(int argc, char **argv) +{ + enum rk_base32_flags flags = 0; + unsigned char *buf = NULL; + size_t buflen = 0; + size_t bufsz = 0; + int goptind = 0; + int ret; + + setprogname("rkbase32"); + if (getarg(args, num_args, argc, argv, &goptind) || help_flag) { + arg_printusage(args, num_args, NULL, "FILE | -"); + return help_flag ? 0 : 1; + } + + argc -= goptind; + argv += goptind; + + flags |= preserve_order_flag ? RK_BASE32_FLAG_PRESERVE_ORDER : 0; + flags |= interior_padding_ok ? RK_BASE32_FLAG_INTERIOR_PADDING_OK : 0; + flags |= stop_on_garbage ? RK_BASE32_FLAG_STOP_ON_GARBAGE : 0; + + if (help_flag) + return arg_printusage(args, num_args, NULL, "FILE | -- -"), 0; + if (argc != 1) + return arg_printusage(args, num_args, NULL, "FILE | -- -"), 1; + + if (strcmp(argv[0], "-") == 0) { + unsigned char *tmp; + unsigned char d[4096]; + size_t bytes; + + while (!feof(stdin) && !ferror(stdin)) { + bytes = fread(d, 1, sizeof(d), stdin); + if (bytes == 0) + continue; + if (buflen + bytes > bufsz) { + if ((tmp = realloc(buf, bufsz + (bufsz >> 2) + sizeof(d))) == NULL) + err(1, "Could not read stdin"); + buf = tmp; + bufsz = bufsz + (bufsz >> 2) + sizeof(d); + } + memcpy(buf + buflen, d, bytes); + buflen += bytes; + } + if (ferror(stdin)) + err(1, "Could not read stdin"); + } else { + void *d; + + if ((errno = rk_undumpdata(argv[0], &d, &bufsz))) + err(1, "Could not read %s", argv[0]); + buflen = bufsz; + buf = d; + } + + if (decode_flag) { + unsigned char *d; + + if (buflen == bufsz) { + unsigned char *tmp; + + if ((tmp = realloc(buf, bufsz + 1)) == NULL) + err(1, "Could not decode data"); + buf = tmp; + bufsz++; + } + buf[buflen] = '\0'; + + if ((d = malloc(buflen * 5 / 8 + 4)) == NULL) + err(1, "Could not decode data"); + + if ((ret = rk_base32_decode((const char *)buf, d, flags)) < 0) + err(1, "Could not decode data"); + if (fwrite(d, ret, 1, stdout) != 1) + err(1, "Could not write decoded data"); + free(d); + } else if (buf) { /* buf can be NULL if we read from an empty file */ + char *e; + + if ((ret = rk_base32_encode(buf, buflen, &e, flags)) < 0) + err(1, "Could not encode data"); + if (fwrite(e, ret, 1, stdout) != 1) + err(1, "Could not write decoded data"); + free(e); + if (fwrite("\n", 1, 1, stdout) != 1) + err(1, "Could not write decoded data"); + } + free(buf); + return 0; +} +#endif diff --git a/third_party/heimdal/lib/roken/base32.h b/third_party/heimdal/lib/roken/base32.h new file mode 100644 index 0000000..1dc0dd0 --- /dev/null +++ b/third_party/heimdal/lib/roken/base32.h @@ -0,0 +1,61 @@ +/* + * 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$ */ + +#ifndef _BASE32_H_ +#define _BASE32_H_ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +enum rk_base32_flags { + RK_BASE32_FLAG_PRESERVE_ORDER = 1, + RK_BASE32_FLAG_STOP_ON_GARBAGE = 2, + RK_BASE32_FLAG_INTERIOR_PADDING_OK = 4, +}; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base32_encode(const void *, int, char **, enum rk_base32_flags); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base32_decode(const char *, void *, enum rk_base32_flags); + +#endif diff --git a/third_party/heimdal/lib/roken/base64-test.c b/third_party/heimdal/lib/roken/base64-test.c new file mode 100644 index 0000000..8fb3f52 --- /dev/null +++ b/third_party/heimdal/lib/roken/base64-test.c @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#include <config.h> + +#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, 0, NULL } + }; + for(t = tests; t->data; t++) { + char *str; + int len; + + (void) rk_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 = rk_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(rk_base64_decode("M=M=", str) != -1) { + fprintf(stderr, "failed test %d: successful decode of `M=M='\n", + numtest++); + numerr++; + } + if(rk_base64_decode("MQ===", str) != -1) { + fprintf(stderr, "failed test %d: successful decode of `MQ==='\n", + numtest++); + numerr++; + } + } + return numerr; +} diff --git a/third_party/heimdal/lib/roken/base64.c b/third_party/heimdal/lib/roken/base64.c new file mode 100644 index 0000000..582d183 --- /dev/null +++ b/third_party/heimdal/lib/roken/base64.c @@ -0,0 +1,258 @@ +/* + * 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. + */ + +#include <config.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#ifdef TEST +#include <stdio.h> +#include <getarg.h> +#include <err.h> +#endif +#include "base64.h" +#include "roken.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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base64_encode(const void *data, int size, char **str) +{ + char *s, *p; + int i; + int c; + const unsigned char *q; + + if (size > INT_MAX/4 || size < 0) { + *str = NULL; + errno = ERANGE; + return -1; + } + + p = s = (char *) malloc(size * 4 / 3 + 4); + if (p == NULL) { + *str = NULL; + return -1; + } + q = (const unsigned char *) data; + + 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 (int) 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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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) { + errno = EINVAL; + return -1; + } + *q++ = (val >> 16) & 0xff; + if (marker < 2) + *q++ = (val >> 8) & 0xff; + if (marker < 1) + *q++ = val & 0xff; + } + if (q - (unsigned char *) data > INT_MAX) { + errno = EOVERFLOW; + return -1; + } + return q - (unsigned char *) data; +} + +#ifdef TEST +static int decode_flag; +static int help_flag; + +/* + * The short options are compatible with a subset of the FreeBSD contrib + * vis(1). Heimdal additions have long option names only. + */ +static struct getargs args[] = { + { "decode", 'd', arg_flag, &decode_flag, "Decode", NULL }, + { "help", 'h', arg_flag, &help_flag, "Print help message", NULL }, +}; +static size_t num_args = sizeof(args)/sizeof(args[0]); + +int +main(int argc, char **argv) +{ + unsigned char *buf = NULL; + size_t buflen = 0; + size_t bufsz = 0; + int goptind = 0; + int ret; + + setprogname("rkbase64"); + if (getarg(args, num_args, argc, argv, &goptind) || help_flag) { + arg_printusage(args, num_args, NULL, "FILE | -"); + return help_flag ? 0 : 1; + } + + argc -= goptind; + argv += goptind; + + if (help_flag) + return arg_printusage(args, num_args, NULL, "FILE | -- -"), 0; + if (argc != 1) + return arg_printusage(args, num_args, NULL, "FILE | -- -"), 1; + + if (strcmp(argv[0], "-") == 0) { + unsigned char *tmp; + unsigned char d[4096]; + size_t bytes; + + while (!feof(stdin) && !ferror(stdin)) { + bytes = fread(d, 1, sizeof(d), stdin); + if (bytes == 0) + continue; + if (buflen + bytes > bufsz) { + if ((tmp = realloc(buf, bufsz + (bufsz >> 2) + sizeof(d))) == NULL) + err(1, "Could not read stdin"); + buf = tmp; + bufsz = bufsz + (bufsz >> 2) + sizeof(d); + } + memcpy(buf + buflen, d, bytes); + buflen += bytes; + } + if (ferror(stdin)) + err(1, "Could not read stdin"); + } else { + void *d; + if ((errno = rk_undumpdata(argv[0], &d, &bufsz))) + err(1, "Could not read %s", argv[0]); + buflen = bufsz; + buf = d; + } + + if (decode_flag) { + unsigned char *d; + + if (buflen == bufsz) { + unsigned char *tmp; + + if ((tmp = realloc(buf, bufsz + 1)) == NULL) + err(1, "Could not decode data"); + buf = tmp; + bufsz++; + } + buf[buflen] = '\0'; + + if ((d = malloc(buflen * 3 / 4 + 4)) == NULL) + err(1, "Could not decode data"); + + if ((ret = rk_base64_decode((const char *)buf, d)) < 0) + err(1, "Could not decode data"); + if (fwrite(d, ret, 1, stdout) != 1) + err(1, "Could not write decoded data"); + free(d); + } else if (buf) { /* buf can be NULL if we read from an empty file */ + char *e; + + if ((ret = rk_base64_encode(buf, buflen, &e)) < 0) + err(1, "Could not encode data"); + if (fwrite(e, ret, 1, stdout) != 1) + err(1, "Could not write decoded data"); + free(e); + if (fwrite("\n", 1, 1, stdout) != 1) + err(1, "Could not write decoded data"); + } + free(buf); + return 0; +} +#endif diff --git a/third_party/heimdal/lib/roken/base64.h b/third_party/heimdal/lib/roken/base64.h new file mode 100644 index 0000000..734a6b5 --- /dev/null +++ b/third_party/heimdal/lib/roken/base64.h @@ -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. + */ + +/* $Id$ */ + +#ifndef _BASE64_H_ +#define _BASE64_H_ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base64_encode(const void *, int, char **); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_base64_decode(const char *, void *); + +#endif diff --git a/third_party/heimdal/lib/roken/bswap.c b/third_party/heimdal/lib/roken/bswap.c new file mode 100644 index 0000000..b0c4248 --- /dev/null +++ b/third_party/heimdal/lib/roken/bswap.c @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_BSWAP64 + +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL +bswap64 (uint64_t val) +{ + return + (val & 0xffULL) << 56 | + (val & 0xff00ULL) << 40 | + (val & 0xff0000ULL) << 24 | + (val & 0xff000000ULL) << 8 | + (val & 0xff00000000ULL) >> 8 | + (val & 0xff0000000000ULL) >> 24 | + (val & 0xff000000000000ULL) >> 40 | + (val & 0xff00000000000000ULL) >> 56 ; +} +#endif + +#ifndef HAVE_BSWAP32 + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +bswap32 (unsigned int val) +{ + return (val & 0xff) << 24 | + (val & 0xff00) << 8 | + (val & 0xff0000) >> 8 | + (val & 0xff000000) >> 24; +} +#endif + +#ifndef HAVE_BSWAP16 + +ROKEN_LIB_FUNCTION unsigned short ROKEN_LIB_CALL +bswap16 (unsigned short val) +{ + return (val & 0xff) << 8 | + (val & 0xff00) >> 8; +} +#endif diff --git a/third_party/heimdal/lib/roken/chown.c b/third_party/heimdal/lib/roken/chown.c new file mode 100644 index 0000000..90a82d9 --- /dev/null +++ b/third_party/heimdal/lib/roken/chown.c @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +chown(const char *path, uid_t owner, gid_t group) +{ + return 0; +} diff --git a/third_party/heimdal/lib/roken/cloexec.c b/third_party/heimdal/lib/roken/cloexec.c new file mode 100644 index 0000000..59ffa50 --- /dev/null +++ b/third_party/heimdal/lib/roken/cloexec.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008 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. + */ + +#include <config.h> + +#include "roken.h" + +void ROKEN_LIB_FUNCTION +rk_cloexec(int fd) +{ +#ifdef HAVE_FCNTL + int ret; + + ret = fcntl(fd, F_GETFD); + if (ret == -1) + return; + if (fcntl(fd, F_SETFD, ret | FD_CLOEXEC) == -1) + return; +#endif +} + +void ROKEN_LIB_FUNCTION +rk_cloexec_file(FILE *f) +{ +#ifdef HAVE_FCNTL + rk_cloexec(fileno(f)); +#endif +} + +void ROKEN_LIB_FUNCTION +rk_cloexec_dir(DIR * d) +{ +#ifndef _WIN32 + rk_cloexec(dirfd(d)); +#endif +} + +void ROKEN_LIB_FUNCTION +rk_cloexec_socket(rk_socket_t s) +{ +#ifndef _WIN32 + rk_cloexec((int)s); +#endif +} + diff --git a/third_party/heimdal/lib/roken/closefrom.c b/third_party/heimdal/lib/roken/closefrom.c new file mode 100644 index 0000000..770eb2c --- /dev/null +++ b/third_party/heimdal/lib/roken/closefrom.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. + */ + +#include <config.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +closefrom(int fd) +{ + int num = getdtablesize(); + + if (num < 0) + num = 1024; /* XXX */ + + for (; fd <= num; fd++) + close(fd); + + return 0; +} diff --git a/third_party/heimdal/lib/roken/clz.c b/third_party/heimdal/lib/roken/clz.c new file mode 100644 index 0000000..1a36234 --- /dev/null +++ b/third_party/heimdal/lib/roken/clz.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <config.h> +#include <assert.h> + +#include "roken.h" + +#if defined(_MSC_VER) +#include <intrin.h> +#if defined(_WIN64) +#pragma intrinsic(_BitScanReverse64) +#else +#pragma intrinsic(_BitScanReverse) +#endif +#endif + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_clzll(uint64_t x) +{ +#if defined(_MSC_VER) + unsigned long r = 0; +#elif !(defined(__GNUC__) && __GNUC__ >= 4) + int r = 0; +#endif + + assert(x != 0); + +#if defined(_MSC_VER) +# if defined(_WIN64) + _BitScanReverse64(&r, x); +# else + if (_BitScanReverse(&r, (uint32_t)(x >> 32))) + return 63 - (r + 32); + _BitScanReverse(&r, (uint32_t)(x & 0xFFFFFFFF)); +# endif + + return 63 - r; +#elif (defined(__GNUC__) && __GNUC__ >= 4) + return __builtin_clzll(x); +#else + while (!(x & ((uint64_t)1 << 63))) { + x <<= 1; + ++r; + } + + return r; +#endif /* _MSC_VER || __GNUC__ */ +} diff --git a/third_party/heimdal/lib/roken/concat.c b/third_party/heimdal/lib/roken/concat.c new file mode 100644 index 0000000..0b4ac46 --- /dev/null +++ b/third_party/heimdal/lib/roken/concat.c @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +roken_mconcat (char **s, size_t max_len, ...) +{ + size_t ret; + va_list args; + + va_start(args, max_len); + ret = roken_vmconcat (s, max_len, args); + va_end(args); + return ret; +} diff --git a/third_party/heimdal/lib/roken/copyhostent.c b/third_party/heimdal/lib/roken/copyhostent.c new file mode 100644 index 0000000..9b9dba2 --- /dev/null +++ b/third_party/heimdal/lib/roken/copyhostent.c @@ -0,0 +1,98 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * return a malloced copy of `h' + */ + +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/ct.c b/third_party/heimdal/lib/roken/ct.c new file mode 100644 index 0000000..79f312d --- /dev/null +++ b/third_party/heimdal/lib/roken/ct.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 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. + */ + +#include <config.h> +#include "roken.h" + +/** + * Constant time compare to memory regions. The reason for making it + * constant time is to make sure that timeing information leak from + * where in the function the diffrence is. + * + * ct_memcmp() can't be used to order memory regions like memcmp(), + * for example, use ct_memcmp() with qsort(). + * + * We use volatile to avoid optimizations where the compiler and/or + * linker turn this ct_memcmp() into a plain memcmp(). The pointers + * themselves are also marked volatile (not just the memory pointed at) + * because in some GCC versions there is a bug which can be worked + * around by doing this. + * + * @param p1 memory region 1 to compare + * @param p2 memory region 2 to compare + * @param len length of memory + * + * @return 0 when the memory regions are equal, non zero if not + * + * @ingroup roken + */ + +int +ct_memcmp(const volatile void * volatile p1, + const volatile void * volatile p2, + size_t len) +{ + /* + * There's no need for s1 and s2 to be volatile; only p1 and p2 have + * to be in order to work around GCC bugs. + * + * However, s1 and s2 do have to point to volatile, as we don't know + * if the object was originally defined as volatile, and if it was + * then we'd get undefined behavior here if s1/s2 were declared to + * point to non-volatile memory. + */ + const volatile unsigned char *s1 = p1; + const volatile unsigned char *s2 = p2; + size_t i; + int r = 0; + + for (i = 0; i < len; i++) + r |= (s1[i] ^ s2[i]); + return !!r; +} diff --git a/third_party/heimdal/lib/roken/daemon.c b/third_party/heimdal/lib/roken/daemon.c new file mode 100644 index 0000000..6128beb --- /dev/null +++ b/third_party/heimdal/lib/roken/daemon.c @@ -0,0 +1,80 @@ +/*- + * 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 */ + +#include <config.h> + +#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" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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) + (void) close(fd); + } + return (0); +} + +#endif /* HAVE_DAEMON */ diff --git a/third_party/heimdal/lib/roken/detach.c b/third_party/heimdal/lib/roken/detach.c new file mode 100644 index 0000000..4a00682 --- /dev/null +++ b/third_party/heimdal/lib/roken/detach.c @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 2015 + * Cryptonector LLC. 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. Cryptonector LLC may not 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. + */ + +#include <config.h> +#include <errno.h> +#include <fcntl.h> +#ifdef WIN32 +#include <io.h> +#include <stdlib.h> +#else +#include <unistd.h> +#endif +#include "roken.h" + +#ifdef WIN32 +#define dup2 _dup2 +#endif + +static int pipefds[2] = {-1, -1}; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_detach_prep(int argc, char **argv, char *special_arg) +{ + ssize_t bytes; + size_t i; + pid_t child; + char **new_argv; + char buf[1]; + char fildes[21]; + int status; + + pipefds[0] = -1; + pipefds[1] = -1; + +#ifdef WIN32 + if (_pipe(pipefds, 4, _O_NOINHERIT | O_BINARY) == -1) + err(1, "failed to setup to detach daemon (_pipe failed)"); +#else + if (pipe(pipefds) == -1) + err(1, "failed to setup to detach daemon (pipe failed)"); +#endif + + new_argv = calloc(argc + 3, sizeof(*new_argv)); + if (new_argv == NULL) + err(1, "Out of memory"); + +#ifdef WIN32 + pipefds[1] = _dup(pipefds[1]); /* The new fd will be inherited */ + if (pipefds[1] == -1) + err(1, "Out of memory"); +#else + (void) fcntl(pipefds[1], F_SETFD, + fcntl(pipefds[1], F_GETFD & ~(O_CLOEXEC))); +#endif + + if (snprintf(fildes, sizeof(fildes), "%d", pipefds[1]) >= sizeof(fildes)) + err(1, "failed to setup to detach daemon (fd number %d too large)", + pipefds[1]); + + new_argv[0] = argv[0]; + new_argv[1] = special_arg; + new_argv[2] = fildes; + for (i = 1; argv[i] != NULL; i++) + new_argv[i + 2] = argv[i]; + new_argv[argc + 2] = NULL; + +#ifndef WIN32 + fflush(stdout); + child = fork(); +#else + { + intptr_t child_handle; + + _flushall(); + child_handle = spawnvp(_P_NOWAIT, argv[0], new_argv); + if (child_handle == -1) + child = (pid_t)-1; + else + child = GetProcessId((HANDLE)child_handle); + } +#endif + if (child == (pid_t)-1) + err(1, "failed to setup to fork daemon (fork failed)"); + +#ifndef WIN32 + if (child == 0) { + int fd; + + (void) close(pipefds[0]); + pipefds[0] = -1; + /* + * Keep stdout/stderr for now so output and errors prior to + * detach_finish() can be seen by the user. + */ + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd == -1) + err(1, "failed to open /dev/null"); + (void) dup2(fd, STDIN_FILENO); + if (fd > STDERR_FILENO) + (void) close(fd); + if (getenv("ROKEN_DETACH_USE_EXEC")) { + (void) execvp(argv[0], new_argv); + err(1, "failed to self-re-exec"); + } + free(new_argv); + return pipefds[1]; + } +#endif + + /* Parent */ + free(new_argv); + (void) close(pipefds[1]); + pipefds[1] = -1; + do { + bytes = read(pipefds[0], buf, sizeof(buf)); + } while (bytes == -1 && errno == EINTR); + (void) close(pipefds[0]); + pipefds[0] = -1; + if (bytes == -1) { + /* + * No need to wait for the process. We've killed it. If it + * doesn't want to exit, we'd have to wait potentially forever, + * but we want to indicate failure to the user as soon as + * possible. A wait with timeout would end the same way + * (attempting to kill the process). + */ + err(1, "failed to setup daemon child (read from child pipe)"); + } + if (bytes == 0) { + warnx("daemon child preparation failed, waiting for child"); + status = wait_for_process(child); + if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0) + errx(SE_PROCSTATUS(status), + "daemon child preparation failed (child exited)"); + } + _exit(0); + /* NOTREACHED */ + return -1; +} + +#ifdef WIN32 +#ifdef dup2 +#undef dup2 +#endif +#define dup2 _dup2 +#endif + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +roken_detach_finish(const char *dir, int daemon_child_fd) +{ + char buf[1] = ""; + ssize_t bytes; + int fd; + + rk_pidfile(NULL); + if (pipefds[1] == -1 && daemon_child_fd != -1) + pipefds[1] = daemon_child_fd; + if (pipefds[0] != -1) + (void) close(pipefds[0]); + if (pipefds[1] == -1) + return; + +#ifdef HAVE_SETSID + if (setsid() == -1) + err(1, "failed to detach from tty"); +#endif + +#ifndef WIN32 + /* + * Hopefully we've written any pidfiles by now, if they had to be in + * the current directory... + * + * The daemons do re-open logs and so on, therefore this chdir() + * call needs to be optional for testing. + */ + if (dir != NULL && chdir(dir) == -1) + err(1, "failed to chdir to /"); +#endif + + do { + bytes = write(pipefds[1], buf, sizeof(buf)); + } while (bytes == -1 && errno == EINTR); + if (bytes == -1) + err(1, "failed to signal parent while detaching"); + (void) close(pipefds[1]); + if (bytes != sizeof(buf)) + errx(1, "failed to signal parent while detaching"); + + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd == -1) + err(1, "failed to open /dev/null"); + /* + * Maybe we should check that our output got written, if redirected + * to a file. File utils normally do this. + */ + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + if (fd > 2) + (void) close(fd); +} diff --git a/third_party/heimdal/lib/roken/dirent-test.c b/third_party/heimdal/lib/roken/dirent-test.c new file mode 100644 index 0000000..dc4518a --- /dev/null +++ b/third_party/heimdal/lib/roken/dirent-test.c @@ -0,0 +1,278 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <direct.h> +#include <errno.h> +#include <io.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <string.h> +#include "dirent.h" + +/* Note that we create a known directory structure in a subdirectory + of the current directory to run our tests. */ + +#define TESTDIR "dirent-test-dir" + +const char * dir_entries[] = { + "A", + "B", + "C", + "CAA", + "CAAA", + "CABBBB", + "CAABBB.txt", + "A filename with spaces" +}; + +const char * entries_begin_with_C[] = { + "C", + "CAA", + "CAAA", + "CABBBB", + "CAABBB.txt" +}; + +const char * entries_end_with_A[] = { + "A", + "CAA", + "CAAA" +}; + +const int n_dir_entries = sizeof(dir_entries)/sizeof(dir_entries[0]); + +int teardown_test(void); + +void fail_test(const char * reason, ...) +{ + va_list args; + + va_start(args, reason); + vfprintf(stderr, reason, args); + va_end(args); + + fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno)); + teardown_test(); + abort(); +} + +void fail_test_nf(const char * format, ...) +{ + va_list args; + + fprintf(stderr, "FAIL:"); + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno)); +} + +int touch(const char * filename) +{ + int fd; + + fd = _open(filename, _O_CREAT, _S_IREAD| _S_IWRITE); + + if (fd == -1) + return -1; + + return _close(fd); +} + +int setup_test(void) +{ + int i; + + fprintf(stderr, "Creating test directory %s ...\n", TESTDIR); + + if (_mkdir(TESTDIR)) + fail_test("Can't create test directory \"" TESTDIR "\""); + + if (_chdir(TESTDIR)) + fail_test("Can't change to test directory"); + + for (i=0; i < n_dir_entries; i++) { + if (touch(dir_entries[i])) + fail_test("Can't create test file '%s'", dir_entries[i]); + } + + fprintf(stderr, "Done with test setup.\n"); + + return 0; +} + +int teardown_test(void) +{ + char dirname[_MAX_PATH]; + size_t len; + int i; + + printf ("Begin cleanup...\n"); + + if (_getcwd(dirname, sizeof(dirname)/sizeof(char)) != NULL && + + (len = strlen(dirname)) > sizeof(TESTDIR)/sizeof(char) && + + strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR) == 0) { + + fallthrough; + + } else { + /* did we create the directory? */ + + if (!_rmdir( TESTDIR )) { + fprintf(stderr, "Removed test directory\n"); + return 0; + } else { + if (errno == ENOTEMPTY) { + if (_chdir(TESTDIR)) { + fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n"); + return -1; + } else { + fallthrough; + } + } else { + return -1; + } + } + } + + fprintf(stderr, "Cleaning up test directory %s ...\n", TESTDIR); + + for (i=0; i < n_dir_entries; i++) { + if (_unlink(dir_entries[i])) { + /* if the test setup failed, we expect this to happen for + at least some files */ + } + } + + if (_chdir("..")) { + fprintf(stderr, "Can't escape test directory. Giving in.\n"); + return -1; + } + + if (_rmdir( TESTDIR )) { + fprintf(stderr, "Can't remove test directory.\n"); + return -1; + } + + printf("Cleaned up test directory\n"); + return 0; +} + +int check_list(const char * filespec, const char ** list, int n, int expect_dot_and_dotdot) +{ + DIR * d; + struct dirent * e; + int n_found = 0; + int i; + int rv = 0; + int retry = 1; + + d = opendir(filespec); + if (d == NULL) { + fail_test_nf("opendir failed for [%s]", filespec); + return -1; + } + + printf("Checking filespec [%s]... ", filespec); + + retry: + while ((e = readdir(d)) != NULL) { + n_found ++; + + if (expect_dot_and_dotdot && + (strcmp(e->d_name, ".") == 0 || + strcmp(e->d_name, "..") == 0)) + continue; + + for (i=0; i < n; i++) { + if (strcmp(list[i], e->d_name) == 0) + break; + } + + if (i == n) { + fail_test_nf("Found unexpected entry [%s]", e->d_name); + rv = -1; + } + } + + if (n_found != n) { + fail_test_nf("Unexpected number of entries [%d]. Expected %d", n_found, n); + rv = -1; + } + + if (retry) { + retry = 0; + n_found = 0; + + rewinddir(d); + goto retry; + } + + if (closedir(d)) { + fail_test_nf("closedir() failed"); + } + + printf("done\n"); + + return rv; +} + +int run_tests() +{ + /* assumes that the test directory has been set up and we have + changed into the test directory. */ + + check_list("*", dir_entries, n_dir_entries + 2, 1); + check_list("*.*", dir_entries, n_dir_entries + 2, 1); + check_list("C*", entries_begin_with_C, sizeof(entries_begin_with_C)/sizeof(entries_begin_with_C[0]), 0); + check_list("*A", entries_end_with_A, sizeof(entries_end_with_A)/sizeof(entries_end_with_A[0]), 0); + + return 0; +} + +int main(int argc, char ** argv) +{ + if (setup_test()) + return 1; + + run_tests(); + + teardown_test(); + + return 0; +} diff --git a/third_party/heimdal/lib/roken/dirent.c b/third_party/heimdal/lib/roken/dirent.c new file mode 100644 index 0000000..36f1bc9 --- /dev/null +++ b/third_party/heimdal/lib/roken/dirent.c @@ -0,0 +1,235 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <stdlib.h> +#include <io.h> +#include <string.h> +#include <errno.h> +#include "dirent.h" + +#ifndef _WIN32 +#error Only implemented for Win32 +#endif + +struct _dirent_dirinfo { + int magic; + long n_entries; + long nc_entries; + long cursor; + struct dirent **entries; +}; +#define DIRINFO_MAGIC 0xf8c0639d +#define IS_DP(p) ((p) && ((DIR *)(p))->magic == DIRINFO_MAGIC) + +#define INITIAL_ENTRIES 16 + +/** + * Create a filespec for use with _findfirst() using a path spec + * + * If the last component of the path spec contains wildcards, we let + * it be. If the last component doesn't end with a slash, we add one. + */ +static const char * +filespec_from_dir_path(const char * path, char * buffer, size_t cch_buffer) +{ + char *comp, *t; + size_t pos; + int found_sep = 0; + + if (strcpy_s(buffer, cch_buffer, path) != 0) + return NULL; + + comp = strrchr(buffer, '\\'); + if (comp == NULL) + comp = buffer; + else + found_sep = 1; + + t = strrchr(comp, '/'); + if (t != NULL) { + comp = t; + found_sep = 1; + } + + if (found_sep) + comp++; + + pos = strcspn(comp, "*?"); + if (comp[pos] != '\0') + return buffer; + + /* We don't append a slash if pos == 0 because that changes the + * meaning: + * + * "*.*" is all files in the current directory. + * "\*.*" is all files in the root directory of the current drive. + */ + if (pos > 0 && comp[pos - 1] != '\\' && + comp[pos - 1] != '/') { + strcat_s(comp, cch_buffer - (comp - buffer), "\\"); + } + + strcat_s(comp, cch_buffer - (comp - buffer), "*.*"); + + return buffer; +} + +ROKEN_LIB_FUNCTION DIR * ROKEN_LIB_CALL +opendir(const char * path) +{ + DIR * dp; + struct _finddata_t fd; + intptr_t fd_handle; + const char *filespec; + char path_buffer[1024]=""; + + memset(&fd, 0, sizeof(fd)); + + filespec = filespec_from_dir_path(path, path_buffer, sizeof(path_buffer)/sizeof(char)); + if (filespec == NULL) + return NULL; + + fd_handle = _findfirst(filespec, &fd); + + if (fd_handle == -1) + return NULL; + + dp = malloc(sizeof(*dp)); + if (dp == NULL) + goto done; + + memset(dp, 0, sizeof(*dp)); + dp->magic = DIRINFO_MAGIC; + dp->cursor = 0; + dp->n_entries = 0; + dp->nc_entries = INITIAL_ENTRIES; + dp->entries = calloc(dp->nc_entries, sizeof(dp->entries[0])); + + if (dp->entries == NULL) { + closedir(dp); + dp = NULL; + goto done; + } + + do { + size_t len = strlen(fd.name); + struct dirent * e; + + if (dp->n_entries == dp->nc_entries) { + struct dirent ** ne; + + dp->nc_entries *= 2; + ne = realloc(dp->entries, sizeof(dp->entries[0]) * dp->nc_entries); + + if (ne == NULL) { + closedir(dp); + dp = NULL; + goto done; + } + + dp->entries = ne; + } + + e = malloc(sizeof(*e) + len * sizeof(char)); + if (e == NULL) { + closedir(dp); + dp = NULL; + goto done; + } + + e->d_ino = 0; /* no inodes :( */ + strcpy_s(e->d_name, len + 1, fd.name); + + dp->entries[dp->n_entries++] = e; + + } while (_findnext(fd_handle, &fd) == 0); + + done: + if (fd_handle != -1) + _findclose(fd_handle); + + return dp; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +closedir(DIR * dp) +{ + if (!IS_DP(dp)) + return EINVAL; + + if (dp->entries) { + long i; + + for (i=0; i < dp->n_entries; i++) { + free(dp->entries[i]); + } + + free(dp->entries); + } + + free(dp); + + return 0; +} + +ROKEN_LIB_FUNCTION struct dirent * ROKEN_LIB_CALL +readdir(DIR * dp) +{ + if (!IS_DP(dp) || + dp->cursor < 0 || + dp->cursor >= dp->n_entries) + + return NULL; + + return dp->entries[dp->cursor++]; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rewinddir(DIR * dp) +{ + if (IS_DP(dp)) + dp->cursor = 0; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +seekdir(DIR * dp, long offset) +{ + if (IS_DP(dp) && offset >= 0 && offset < dp->n_entries) + dp->cursor = offset; +} + +ROKEN_LIB_FUNCTION long ROKEN_LIB_CALL +telldir(DIR * dp) +{ + return dp->cursor; +} diff --git a/third_party/heimdal/lib/roken/dirent.hin b/third_party/heimdal/lib/roken/dirent.hin new file mode 100644 index 0000000..c9a86c6 --- /dev/null +++ b/third_party/heimdal/lib/roken/dirent.hin @@ -0,0 +1,66 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 __DIRENT_H__ +#define __DIRENT_H__ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#include<sys/types.h> + +struct dirent { + ino_t d_ino; + char d_name[1]; +}; + +typedef struct _dirent_dirinfo DIR; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL closedir(DIR *); + +ROKEN_LIB_FUNCTION DIR * ROKEN_LIB_CALL opendir(const char *); + +ROKEN_LIB_FUNCTION struct dirent * ROKEN_LIB_CALL readdir(DIR *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rewinddir(DIR *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL seekdir(DIR *, long); + +ROKEN_LIB_FUNCTION long ROKEN_LIB_CALL telldir(DIR *); + +#endif diff --git a/third_party/heimdal/lib/roken/dlfcn.hin b/third_party/heimdal/lib/roken/dlfcn.hin new file mode 100644 index 0000000..4f2341b --- /dev/null +++ b/third_party/heimdal/lib/roken/dlfcn.hin @@ -0,0 +1,109 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 __dlfcn_h__ +#define __dlfcn_h__ + +#include <windows.h> + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#ifdef _WIN32 +typedef int (__stdcall *DLSYM_RET_TYPE)(); +#else +#define DLSYM_RET_TYPE void * +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Relocations are performed when the object is loaded. */ +#define RTLD_NOW 0 + +/* Relocations are performed at an implementation-defined time. + * Windows API does not support lazy symbol resolving (when first reference + * to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW. + */ +#define RTLD_LAZY RTLD_NOW + +/* All symbols are available for relocation processing of other modules. */ +#define RTLD_GLOBAL (1 << 1) + +/* All symbols are not made available for relocation processing by other modules. */ +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +/* The symbol lookup happens in the normal global scope. */ +#define RTLD_DEFAULT ((void *)0LL) + +/* Specifies the next object after this one that defines name. */ +#define RTLD_NEXT ((void *)-1LL) + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +dlclose(void *); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +dlerror(void); + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +dlopen(const char *, int); + +ROKEN_LIB_FUNCTION DLSYM_RET_TYPE ROKEN_LIB_CALL +dlsym(void *, const char *); + +typedef struct Dl_info +{ + const char *dli_fname; /* Filename of defining object (thread unsafe and reused on every call to dladdr) */ + void *dli_fbase; /* Load address of that object */ + const char *dli_sname; /* Name of nearest lower symbol */ + void *dli_saddr; /* Exact value of nearest symbol */ +} Dl_info, Dl_info_t; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +dladdr(void *addr, Dl_info *dli); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __dlfcn_h__ */ diff --git a/third_party/heimdal/lib/roken/dlfcn_w32.c b/third_party/heimdal/lib/roken/dlfcn_w32.c new file mode 100644 index 0000000..9da3f6f --- /dev/null +++ b/third_party/heimdal/lib/roken/dlfcn_w32.c @@ -0,0 +1,700 @@ +/*
+ * dlfcn-win32
+ * Copyright (c) 2007 Ramiro Polla
+ * Copyright (c) 2015 Tiancheng "Timothy" Gu
+ * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
+ * Copyright (c) 2020 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * Copied from https://github.com/dlfcn-win32/dlfcn-win32 and modified only to
+ * fit Heimdal's lib/roken.
+ */
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#ifdef _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */
+#pragma intrinsic(_ReturnAddress)
+#else
+/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */
+#ifndef _ReturnAddress
+#define _ReturnAddress() (__builtin_extract_return_addr(__builtin_return_address(0)))
+#endif
+#endif
+
+#ifdef DLFCN_WIN32_SHARED
+#define DLFCN_WIN32_EXPORTS
+#endif
+#include "dlfcn.h"
+
+/* Note:
+ * MSDN says these functions are not thread-safe. We make no efforts to have
+ * any kind of thread safety.
+ */
+
+typedef struct local_object {
+ HMODULE hModule;
+ struct local_object *previous;
+ struct local_object *next;
+} local_object;
+
+static local_object first_object;
+
+/* These functions implement a double linked list for the local objects. */
+static local_object *local_search( HMODULE hModule )
+{
+ local_object *pobject;
+
+ if( hModule == NULL )
+ return NULL;
+
+ for( pobject = &first_object; pobject; pobject = pobject->next )
+ if( pobject->hModule == hModule )
+ return pobject;
+
+ return NULL;
+}
+
+static BOOL local_add( HMODULE hModule )
+{
+ local_object *pobject;
+ local_object *nobject;
+
+ if( hModule == NULL )
+ return TRUE;
+
+ pobject = local_search( hModule );
+
+ /* Do not add object again if it's already on the list */
+ if( pobject )
+ return TRUE;
+
+ for( pobject = &first_object; pobject->next; pobject = pobject->next );
+
+ nobject = (local_object*) malloc( sizeof( local_object ) );
+
+ if( !nobject )
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ return FALSE;
+ }
+
+ pobject->next = nobject;
+ nobject->next = NULL;
+ nobject->previous = pobject;
+ nobject->hModule = hModule;
+
+ return TRUE;
+}
+
+static void local_rem( HMODULE hModule )
+{
+ local_object *pobject;
+
+ if( hModule == NULL )
+ return;
+
+ pobject = local_search( hModule );
+
+ if( !pobject )
+ return;
+
+ if( pobject->next )
+ pobject->next->previous = pobject->previous;
+ if( pobject->previous )
+ pobject->previous->next = pobject->next;
+
+ free( pobject );
+}
+
+/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
+ * static buffer.
+ * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
+ * the limit.
+ */
+static char error_buffer[65535];
+static BOOL error_occurred;
+
+static void save_err_str( const char *str )
+{
+ DWORD dwMessageId;
+ DWORD ret;
+ size_t pos, len;
+
+ dwMessageId = GetLastError( );
+
+ if( dwMessageId == 0 )
+ return;
+
+ len = strlen( str );
+ if( len > sizeof( error_buffer ) - 5 )
+ len = sizeof( error_buffer ) - 5;
+
+ /* Format error message to:
+ * "<argument to function that failed>": <Windows localized error message>
+ */
+ pos = 0;
+ error_buffer[pos++] = '"';
+ memcpy( error_buffer+pos, str, len );
+ pos += len;
+ error_buffer[pos++] = '"';
+ error_buffer[pos++] = ':';
+ error_buffer[pos++] = ' ';
+
+ ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId,
+ MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
+ error_buffer+pos, (DWORD) (sizeof(error_buffer)-pos), NULL );
+ pos += ret;
+
+ /* When FormatMessageA() fails it returns zero and does not touch buffer
+ * so add trailing null byte */
+ if( ret == 0 )
+ error_buffer[pos] = '\0';
+
+ if( pos > 1 )
+ {
+ /* POSIX says the string must not have trailing <newline> */
+ if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
+ error_buffer[pos-2] = '\0';
+ }
+
+ error_occurred = TRUE;
+}
+
+static void save_err_ptr_str( const void *ptr )
+{
+ char ptr_buf[2 + 2 * sizeof( ptr ) + 1];
+ char num;
+ size_t i;
+
+ ptr_buf[0] = '0';
+ ptr_buf[1] = 'x';
+
+ for( i = 0; i < 2 * sizeof( ptr ); i++ )
+ {
+ num = ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF;
+ ptr_buf[2+i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) );
+ }
+
+ ptr_buf[2 + 2 * sizeof( ptr )] = 0;
+
+ save_err_str( ptr_buf );
+}
+
+/* Load Psapi.dll at runtime, this avoids linking caveat */
+static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded )
+{
+ static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD);
+ HMODULE psapi;
+
+ if( !EnumProcessModulesPtr )
+ {
+ psapi = LoadLibraryA( "Psapi.dll" );
+ if( psapi )
+ EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "EnumProcessModules" );
+ if( !EnumProcessModulesPtr )
+ return 0;
+ }
+
+ return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded );
+}
+
+ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
+dlopen( const char *file, int mode )
+{
+ HMODULE hModule;
+ UINT uMode;
+
+ error_occurred = FALSE;
+
+ /* Do not let Windows display the critical-error-handler message box */
+ uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
+
+ if( file == 0 )
+ {
+ /* POSIX says that if the value of file is 0, a handle on a global
+ * symbol object must be provided. That object must be able to access
+ * all symbols from the original program file, and any objects loaded
+ * with the RTLD_GLOBAL flag.
+ * The return value from GetModuleHandle( ) allows us to retrieve
+ * symbols only from the original program file. EnumProcessModules() is
+ * used to access symbols from other libraries. For objects loaded
+ * with the RTLD_LOCAL flag, we create our own list later on. They are
+ * excluded from EnumProcessModules() iteration.
+ */
+ hModule = GetModuleHandle( NULL );
+
+ if( !hModule )
+ save_err_str( "(null)" );
+ }
+ else
+ {
+ HANDLE hCurrentProc;
+ DWORD dwProcModsBefore, dwProcModsAfter;
+ char lpFileName[MAX_PATH];
+ size_t i, len;
+
+ len = strlen( file );
+
+ if( len >= sizeof( lpFileName ) )
+ {
+ SetLastError( ERROR_FILENAME_EXCED_RANGE );
+ save_err_str( file );
+ hModule = NULL;
+ }
+ else
+ {
+ /* MSDN says backslashes *must* be used instead of forward slashes. */
+ for( i = 0; i < len; i++ )
+ {
+ if( file[i] == '/' )
+ lpFileName[i] = '\\';
+ else
+ lpFileName[i] = file[i];
+ }
+ lpFileName[len] = '\0';
+
+ hCurrentProc = GetCurrentProcess( );
+
+ if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 )
+ dwProcModsBefore = 0;
+
+ /* POSIX says the search path is implementation-defined.
+ * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
+ * to UNIX's search paths (start with system folders instead of current
+ * folder).
+ */
+ hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
+
+ if( !hModule )
+ {
+ save_err_str( lpFileName );
+ }
+ else
+ {
+ if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 )
+ dwProcModsAfter = 0;
+
+ /* If the object was loaded with RTLD_LOCAL, add it to list of local
+ * objects, so that its symbols cannot be retrieved even if the handle for
+ * the original program file is passed. POSIX says that if the same
+ * file is specified in multiple invocations, and any of them are
+ * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
+ * symbols will remain global. If number of loaded modules was not
+ * changed after calling LoadLibraryEx(), it means that library was
+ * already loaded.
+ */
+ if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter )
+ {
+ if( !local_add( hModule ) )
+ {
+ save_err_str( lpFileName );
+ FreeLibrary( hModule );
+ hModule = NULL;
+ }
+ }
+ else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter )
+ {
+ local_rem( hModule );
+ }
+ }
+ }
+ }
+
+ /* Return to previous state of the error-mode bit flags. */
+ SetErrorMode( uMode );
+
+ return (void *) hModule;
+}
+
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+dlclose( void *handle )
+{
+ HMODULE hModule = (HMODULE) handle;
+ BOOL ret;
+
+ error_occurred = FALSE;
+
+ ret = FreeLibrary( hModule );
+
+ /* If the object was loaded with RTLD_LOCAL, remove it from list of local
+ * objects.
+ */
+ if( ret )
+ local_rem( hModule );
+ else
+ save_err_ptr_str( handle );
+
+ /* dlclose's return value in inverted in relation to FreeLibrary's. */
+ ret = !ret;
+
+ return (int) ret;
+}
+
+__declspec(noinline) /* Needed for _ReturnAddress() */
+ROKEN_LIB_FUNCTION DLSYM_RET_TYPE ROKEN_LIB_CALL
+dlsym( void *handle, const char *name )
+{
+ FARPROC symbol;
+ HMODULE hCaller;
+ HMODULE hModule;
+ HANDLE hCurrentProc;
+
+ error_occurred = FALSE;
+
+ symbol = NULL;
+ hCaller = NULL;
+ hModule = GetModuleHandle( NULL );
+ hCurrentProc = GetCurrentProcess( );
+
+ if( handle == RTLD_DEFAULT )
+ {
+ /* The symbol lookup happens in the normal global scope; that is,
+ * a search for a symbol using this handle would find the same
+ * definition as a direct use of this symbol in the program code.
+ * So use same lookup procedure as when filename is NULL.
+ */
+ handle = hModule;
+ }
+ else if( handle == RTLD_NEXT )
+ {
+ /* Specifies the next object after this one that defines name.
+ * This one refers to the object containing the invocation of dlsym().
+ * The next object is the one found upon the application of a load
+ * order symbol resolution algorithm. To get caller function of dlsym()
+ * use _ReturnAddress() intrinsic. To get HMODULE of caller function
+ * use standard GetModuleHandleExA() function.
+ */
+ if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) _ReturnAddress( ), &hCaller ) )
+ goto end;
+ }
+
+ if( handle != RTLD_NEXT )
+ {
+ symbol = GetProcAddress( (HMODULE) handle, name );
+
+ if( symbol != NULL )
+ goto end;
+ }
+
+ /* If the handle for the original program file is passed, also search
+ * in all globally loaded objects.
+ */
+
+ if( hModule == handle || handle == RTLD_NEXT )
+ {
+ HMODULE *modules;
+ DWORD cbNeeded;
+ DWORD dwSize;
+ size_t i;
+
+ /* GetModuleHandle( NULL ) only returns the current program file. So
+ * if we want to get ALL loaded module including those in linked DLLs,
+ * we have to use EnumProcessModules( ).
+ */
+ if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 )
+ {
+ modules = malloc( dwSize );
+ if( modules )
+ {
+ if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded )
+ {
+ for( i = 0; i < dwSize / sizeof( HMODULE ); i++ )
+ {
+ if( handle == RTLD_NEXT && hCaller )
+ {
+ /* Next modules can be used for RTLD_NEXT */
+ if( hCaller == modules[i] )
+ hCaller = NULL;
+ continue;
+ }
+ if( local_search( modules[i] ) )
+ continue;
+ symbol = GetProcAddress( modules[i], name );
+ if( symbol != NULL )
+ {
+ free( modules );
+ goto end;
+ }
+ }
+
+ }
+ free( modules );
+ }
+ else
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ goto end;
+ }
+ }
+ }
+
+end:
+ if( symbol == NULL )
+ {
+ if( GetLastError() == 0 )
+ SetLastError( ERROR_PROC_NOT_FOUND );
+ save_err_str( name );
+ }
+
+ return *(void **) (&symbol);
+}
+
+ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
+dlerror( void )
+{
+ /* If this is the second consecutive call to dlerror, return NULL */
+ if( !error_occurred )
+ return NULL;
+
+ /* POSIX says that invoking dlerror( ) a second time, immediately following
+ * a prior invocation, shall result in NULL being returned.
+ */
+ error_occurred = FALSE;
+
+ return error_buffer;
+}
+
+/* See https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2
+ * for details */
+
+/* Get specific image section */
+static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *size )
+{
+ IMAGE_DOS_HEADER *dosHeader;
+ IMAGE_OPTIONAL_HEADER *optionalHeader;
+
+ dosHeader = (IMAGE_DOS_HEADER *) module;
+
+ if( dosHeader->e_magic != 0x5A4D )
+ return FALSE;
+
+ optionalHeader = (IMAGE_OPTIONAL_HEADER *) ( (BYTE *) module + dosHeader->e_lfanew + 24 );
+
+ if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
+ return FALSE;
+
+ if( index < 0 || index > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR )
+ return FALSE;
+
+ if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 )
+ return FALSE;
+
+ if( size != NULL )
+ *size = optionalHeader->DataDirectory[index].Size;
+
+ *ptr = (void *)( (BYTE *) module + optionalHeader->DataDirectory[index].VirtualAddress );
+
+ return TRUE;
+}
+
+/* Return symbol name for a given address */
+static const char *get_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid, void *addr, void **func_address )
+{
+ int i;
+ void *candidateAddr = NULL;
+ const char *candidateName = NULL;
+ BYTE *base = (BYTE *) module; /* Required to have correct calculations */
+
+ for( i = 0; iid[i].Characteristics != 0 && iid[i].FirstThunk != 0; i++ )
+ {
+ IMAGE_THUNK_DATA *thunkILT = (IMAGE_THUNK_DATA *)( base + iid[i].Characteristics );
+ IMAGE_THUNK_DATA *thunkIAT = (IMAGE_THUNK_DATA *)( base + iid[i].FirstThunk );
+
+ for( ; thunkILT->u1.AddressOfData != 0; thunkILT++, thunkIAT++ )
+ {
+ IMAGE_IMPORT_BY_NAME *nameData;
+
+ if( IMAGE_SNAP_BY_ORDINAL( thunkILT->u1.Ordinal ) )
+ continue;
+
+ if( (void *) thunkIAT->u1.Function > addr || candidateAddr >= (void *) thunkIAT->u1.Function )
+ continue;
+
+ candidateAddr = (void *) thunkIAT->u1.Function;
+ nameData = (IMAGE_IMPORT_BY_NAME *)( base + (ULONG_PTR) thunkILT->u1.AddressOfData );
+ candidateName = (const char *) nameData->Name;
+ }
+ }
+
+ *func_address = candidateAddr;
+ return candidateName;
+}
+
+static BOOL is_valid_address( void *addr )
+{
+ MEMORY_BASIC_INFORMATION info;
+ SIZE_T result;
+
+ if( addr == NULL )
+ return FALSE;
+
+ /* check valid pointer */
+ result = VirtualQuery( addr, &info, sizeof( info ) );
+
+ if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS )
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return state if address points to an import thunk
+ *
+ * An import thunk is setup with a 'jmp' instruction followed by an
+ * absolute address (32bit) or relative offset (64bit) pointing into
+ * the import address table (iat), which is partially maintained by
+ * the runtime linker.
+ */
+static BOOL is_import_thunk( void *addr )
+{
+ return *(short *) addr == 0x25ff ? TRUE : FALSE;
+}
+
+/* Return adress from the import address table (iat),
+ * if the original address points to a thunk table entry.
+ */
+static void *get_address_from_import_address_table( void *iat, DWORD iat_size, void *addr )
+{
+ BYTE *thkp = (BYTE *) addr;
+ /* Get offset from thunk table (after instruction 0xff 0x25)
+ * 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00
+ */
+ ULONG offset = *(ULONG *)( thkp + 2 );
+#ifdef _WIN64
+ /* On 64 bit the offset is relative
+ * 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery>
+ * And can be also negative (MSVC in WDK)
+ * 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060
+ * So cast to signed LONG type
+ */
+ BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset );
+#else
+ /* On 32 bit the offset is absolute
+ * 4019b4: ff 25 90 71 40 00 jmp *0x40719
+ */
+ BYTE *ptr = (BYTE *) offset;
+#endif
+
+ if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size )
+ return NULL;
+
+ return *(void **) ptr;
+}
+
+/* Holds module filename */
+static char module_filename[2*MAX_PATH];
+
+static BOOL fill_module_info( void *addr, Dl_info *info )
+{
+ HMODULE hModule;
+ DWORD dwSize;
+
+ if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL )
+ return FALSE;
+
+ dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) );
+
+ if( dwSize == 0 || dwSize == sizeof( module_filename ) )
+ return FALSE;
+
+ info->dli_fbase = (void *) hModule;
+ info->dli_fname = module_filename;
+
+ return TRUE;
+}
+
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+dladdr( void *addr, Dl_info *info )
+{
+ void *realAddr, *funcAddress = NULL;
+ HMODULE hModule;
+ IMAGE_IMPORT_DESCRIPTOR *iid;
+ DWORD iidSize = 0;
+
+ if( addr == NULL || info == NULL )
+ return 0;
+
+ hModule = GetModuleHandleA( NULL );
+ if( hModule == NULL )
+ return 0;
+
+ if( !is_valid_address( addr ) )
+ return 0;
+
+ realAddr = addr;
+
+ if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) )
+ return 0;
+
+ if( is_import_thunk( addr ) )
+ {
+ void *iat;
+ void *iatAddr = NULL;
+ DWORD iatSize = 0;
+
+ if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) )
+ {
+ /* Fallback for cases where the iat is not defined,
+ * for example i586-mingw32msvc-gcc */
+ if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 )
+ return 0;
+
+ iat = (void *)( (BYTE *) hModule + iid->FirstThunk );
+ /* We assume that in this case iid and iat's are in linear order */
+ iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid );
+ }
+
+ iatAddr = get_address_from_import_address_table( iat, iatSize, addr );
+ if( iatAddr == NULL )
+ return 0;
+
+ realAddr = iatAddr;
+ }
+
+ if( !fill_module_info( realAddr, info ) )
+ return 0;
+
+ info->dli_sname = get_symbol_name( hModule, iid, realAddr, &funcAddress );
+
+ info->dli_saddr = !info->dli_sname ? NULL : funcAddress ? funcAddress : realAddr;
+ return 1;
+}
+
+#ifdef DLFCN_WIN32_SHARED
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ (void) hinstDLL;
+ (void) fdwReason;
+ (void) lpvReserved;
+ return TRUE;
+}
+#endif
diff --git a/third_party/heimdal/lib/roken/doxygen.c b/third_party/heimdal/lib/roken/doxygen.c new file mode 100644 index 0000000..0d30a47 --- /dev/null +++ b/third_party/heimdal/lib/roken/doxygen.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009 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. + */ + +/*! @mainpage Heimdal Roken support library + * + * @section intro Introduction + * + * Heimdal's roken implememnts missing functions and make it easier to + * work with almost unixies like cygwin and AIX. + * + * The project web page: http://www.h5l.org/ + */ + +/** @defgroup roken Heimdal roken library */ diff --git a/third_party/heimdal/lib/roken/dumpdata.c b/third_party/heimdal/lib/roken/dumpdata.c new file mode 100644 index 0000000..252744e --- /dev/null +++ b/third_party/heimdal/lib/roken/dumpdata.c @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Write datablob to a filename, don't care about errors. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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); +} + +/* + * Read all data from a filename, care about errors. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_undumpdata(const char *filename, void **buf, size_t *size) +{ + struct stat sb; + int fd, ret; + ssize_t sret; + + *buf = NULL; + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) + return errno; + if (fstat(fd, &sb) != 0){ + ret = errno; + goto out; + } + *buf = malloc(sb.st_size); + if (*buf == NULL) { + ret = ENOMEM; + goto out; + } + *size = sb.st_size; + + sret = net_read(fd, *buf, *size); + if (sret < 0) + ret = errno; + else if (sret != (ssize_t)*size) + ret = EINVAL; + else + ret = 0; + + out: + if (ret) { + free(*buf); + *buf = NULL; + } + close(fd); + return ret; +} diff --git a/third_party/heimdal/lib/roken/ecalloc.3 b/third_party/heimdal/lib/roken/ecalloc.3 new file mode 100644 index 0000000..a2863df --- /dev/null +++ b/third_party/heimdal/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$ +.\" +.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/third_party/heimdal/lib/roken/ecalloc.c b/third_party/heimdal/lib/roken/ecalloc.c new file mode 100644 index 0000000..04b3733 --- /dev/null +++ b/third_party/heimdal/lib/roken/ecalloc.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> +#include <err.h> + +#include "roken.h" + +/* + * Like calloc but never fails. + */ + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/emalloc.c b/third_party/heimdal/lib/roken/emalloc.c new file mode 100644 index 0000000..2520230 --- /dev/null +++ b/third_party/heimdal/lib/roken/emalloc.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> +#include <err.h> + +#include "roken.h" + +/* + * Like malloc but never fails. + */ + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/environment.c b/third_party/heimdal/lib/roken/environment.c new file mode 100644 index 0000000..a14f27b --- /dev/null +++ b/third_party/heimdal/lib/roken/environment.c @@ -0,0 +1,162 @@ +/* + * 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. + */ + + +#include <config.h> + +#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 +read_env_file(FILE *F, char ***env, int *assigned) +{ + size_t alloced = 0; + size_t idx = 0; + int i; + char **l; + char buf[BUFSIZ], *p, *r; + char **tmp; + int ret = 0; + + *assigned = 0; + + l = *env; + for (idx = 0; l != NULL && l[idx] != NULL; idx++) + ; + if (l) + alloced = idx + 1; + + /* 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; + + if ((size_t)i >= alloced) + continue; /* Doesn't happen (fix scan-build noise) */ + 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; + alloced = idx + 1; + (*assigned)++; + } + if(ferror(F)) + ret = errno; + *env = l; + return ret; +} + +/* + * return count of environment assignments from file and + * list of malloced strings in `env' + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +read_environment(const char *file, char ***env) +{ + int assigned; + FILE *F; + + if ((F = fopen(file, "r")) == NULL) + return 0; + + read_env_file(F, env, &assigned); + fclose(F); + return assigned; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +free_environment(char **env) +{ + int i; + if (env == NULL) + return; + for (i = 0; env[i]; i++) + free(env[i]); + free(env); +} diff --git a/third_party/heimdal/lib/roken/eread.c b/third_party/heimdal/lib/roken/eread.c new file mode 100644 index 0000000..ba30f02 --- /dev/null +++ b/third_party/heimdal/lib/roken/eread.c @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Like read but never fails (and never returns partial data). + */ + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/erealloc.c b/third_party/heimdal/lib/roken/erealloc.c new file mode 100644 index 0000000..1c30ecc --- /dev/null +++ b/third_party/heimdal/lib/roken/erealloc.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> +#include <err.h> + +#include "roken.h" + +/* + * Like realloc but never fails. + */ + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/err.c b/third_party/heimdal/lib/roken/err.c new file mode 100644 index 0000000..592ed69 --- /dev/null +++ b/third_party/heimdal/lib/roken/err.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include "err.h" + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +err(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verr(eval, fmt, ap); + va_end(ap); +} diff --git a/third_party/heimdal/lib/roken/err.hin b/third_party/heimdal/lib/roken/err.hin new file mode 100644 index 0000000..905b1eb --- /dev/null +++ b/third_party/heimdal/lib/roken/err.hin @@ -0,0 +1,99 @@ +/* + * 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$ */ + +#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 + #define ROKEN_LIB_FUNCTION +#endif +#ifndef ROKEN_LIB_NORETURN_FUNCTION + #ifdef _WIN32 + #define ROKEN_LIB_NORETURN_FUNCTION __declspec(noreturn) + #else + #define ROKEN_LIB_NORETURN_FUNCTION + #endif +#endif +#ifndef ROKEN_LIB_CALL + #ifdef _WIN32 + #define ROKEN_LIB_CALL __cdecl + #else + #define ROKEN_LIB_CALL + #endif +#endif + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +verr(int eval, const char *fmt, va_list ap) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +err(int eval, const char *fmt, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +verrx(int eval, const char *fmt, va_list ap) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +errx(int eval, const char *fmt, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vwarn(const char *fmt, va_list ap) + __attribute__ ((__format__ (__printf__, 1, 0))); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +warn(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vwarnx(const char *fmt, va_list ap) + __attribute__ ((__format__ (__printf__, 1, 0))); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +warnx(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +#endif /* __ERR_H__ */ diff --git a/third_party/heimdal/lib/roken/errx.c b/third_party/heimdal/lib/roken/errx.c new file mode 100644 index 0000000..121c707 --- /dev/null +++ b/third_party/heimdal/lib/roken/errx.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. + */ + +#include <config.h> + +#include "err.h" + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} diff --git a/third_party/heimdal/lib/roken/esetenv.c b/third_party/heimdal/lib/roken/esetenv.c new file mode 100644 index 0000000..3cbf5ed --- /dev/null +++ b/third_party/heimdal/lib/roken/esetenv.c @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#include <err.h> + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/estrdup.c b/third_party/heimdal/lib/roken/estrdup.c new file mode 100644 index 0000000..d275a28 --- /dev/null +++ b/third_party/heimdal/lib/roken/estrdup.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> +#include <err.h> + +#include "roken.h" + +/* + * Like strdup but never fails. + */ + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +estrdup (const char *str) +{ + char *tmp = strdup (str); + + if (tmp == NULL) + errx (1, "strdup failed"); + return tmp; +} diff --git a/third_party/heimdal/lib/roken/ewrite.c b/third_party/heimdal/lib/roken/ewrite.c new file mode 100644 index 0000000..fce5705 --- /dev/null +++ b/third_party/heimdal/lib/roken/ewrite.c @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Like write but never fails (and never returns partial data). + */ + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/fchown.c b/third_party/heimdal/lib/roken/fchown.c new file mode 100644 index 0000000..050c2dd --- /dev/null +++ b/third_party/heimdal/lib/roken/fchown.c @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +fchown(int fd, uid_t owner, gid_t group) +{ + return 0; +} diff --git a/third_party/heimdal/lib/roken/flock.c b/third_party/heimdal/lib/roken/flock.c new file mode 100644 index 0000000..068d099 --- /dev/null +++ b/third_party/heimdal/lib/roken/flock.c @@ -0,0 +1,154 @@ +/* + * 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. + */ + +#include <config.h> + +#ifndef HAVE_FLOCK + +#include "roken.h" + +#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN) + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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; + +#elif defined(_WIN32) + /* Windows */ + +#define FLOCK_OFFSET_LOW 0 +#define FLOCK_OFFSET_HIGH 0 +#define FLOCK_LENGTH_LOW 0x00000000 +#define FLOCK_LENGTH_HIGH 0x80000000 + + HANDLE hFile; + OVERLAPPED ov; + BOOL rv = FALSE; + DWORD f = 0; + + hFile = (HANDLE) _get_osfhandle(fd); + if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) { + _set_errno(EBADF); + return -1; + } + + ZeroMemory(&ov, sizeof(ov)); + ov.hEvent = NULL; + ov.Offset = FLOCK_OFFSET_LOW; + ov.OffsetHigh = FLOCK_OFFSET_HIGH; + + if (operation & LOCK_NB) + f = LOCKFILE_FAIL_IMMEDIATELY; + + switch (operation & OP_MASK) { + case LOCK_UN: /* Unlock */ + rv = UnlockFileEx(hFile, 0, + FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov); + break; + + case LOCK_SH: /* Shared lock */ + rv = LockFileEx(hFile, f, 0, + FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, &ov); + break; + + case LOCK_EX: /* Exclusive lock */ + rv = LockFileEx(hFile, f|LOCKFILE_EXCLUSIVE_LOCK, 0, + FLOCK_LENGTH_LOW, FLOCK_LENGTH_HIGH, + &ov); + break; + + default: + _set_errno(EINVAL); + return -1; + } + + if (!rv) { + switch (GetLastError()) { + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + case ERROR_IO_PENDING: + _set_errno(EWOULDBLOCK); + break; + + case ERROR_ACCESS_DENIED: + _set_errno(EACCES); + break; + + default: + _set_errno(ENOLCK); + } + return -1; + } + + return 0; + +#else + return -1; +#endif +} + +#endif + diff --git a/third_party/heimdal/lib/roken/fnmatch.c b/third_party/heimdal/lib/roken/fnmatch.c new file mode 100644 index 0000000..74f3528 --- /dev/null +++ b/third_party/heimdal/lib/roken/fnmatch.c @@ -0,0 +1,175 @@ +/* $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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <roken.h> + +#include <fnmatch.h> +#include <string.h> + +#define EOS '\0' + +static const char *rangematch (const char *, int, int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/fnmatch.hin b/third_party/heimdal/lib/roken/fnmatch.hin new file mode 100644 index 0000000..fd96656 --- /dev/null +++ b/third_party/heimdal/lib/roken/fnmatch.hin @@ -0,0 +1,66 @@ +/* $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 +#define ROKEN_LIB_CALL __stdcall +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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/third_party/heimdal/lib/roken/freeaddrinfo.c b/third_party/heimdal/lib/roken/freeaddrinfo.c new file mode 100644 index 0000000..80a7487 --- /dev/null +++ b/third_party/heimdal/lib/roken/freeaddrinfo.c @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * free the list of `struct addrinfo' starting at `ai' + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/freehostent.c b/third_party/heimdal/lib/roken/freehostent.c new file mode 100644 index 0000000..05dd0fe --- /dev/null +++ b/third_party/heimdal/lib/roken/freehostent.c @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * free a malloced hostent + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/fseeko.c b/third_party/heimdal/lib/roken/fseeko.c new file mode 100644 index 0000000..b6ffaa2 --- /dev/null +++ b/third_party/heimdal/lib/roken/fseeko.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE_FSEEKO +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +fseeko(FILE *f, off_t o, int w) +{ +#ifdef HAVE__FSEEKI64 + return _fseeki64(f, o, w); +#else + return fseek(f, o, w); +#endif +} +#endif diff --git a/third_party/heimdal/lib/roken/ftello.c b/third_party/heimdal/lib/roken/ftello.c new file mode 100644 index 0000000..cd3b84b --- /dev/null +++ b/third_party/heimdal/lib/roken/ftello.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE_FTELLO +ROKEN_LIB_FUNCTION off_t ROKEN_LIB_CALL +ftello(FILE *f) +{ +#ifdef HAVE__FTELLI64 + return _ftelli64(f); +#else + return ftell(f); +#endif +} +#endif diff --git a/third_party/heimdal/lib/roken/gai_strerror.c b/third_party/heimdal/lib/roken/gai_strerror.c new file mode 100644 index 0000000..1e326be --- /dev/null +++ b/third_party/heimdal/lib/roken/gai_strerror.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. + */ + +#include <config.h> + +#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}, +}; + +/* + * + */ + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/get_window_size.c b/third_party/heimdal/lib/roken/get_window_size.c new file mode 100644 index 0000000..5a4a175 --- /dev/null +++ b/third_party/heimdal/lib/roken/get_window_size.c @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#include <config.h> + +#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" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +get_window_size(int fd, int *lines, int *columns) +{ + char *s; + +#if defined(TIOCGWINSZ) + { + struct winsize ws; + int ret; + ret = ioctl(fd, TIOCGWINSZ, &ws); + if (ret != -1) { + if (lines) + *lines = ws.ws_row; + if (columns) + *columns = ws.ws_col; + return 0; + } + } +#elif defined(TIOCGSIZE) + { + struct ttysize ts; + int ret; + ret = ioctl(fd, TIOCGSIZE, &ts); + if (ret != -1) { + if (lines) + *lines = ts.ws_lines; + if (columns) + *columns = ts.ts_cols; + return 0; + } + } +#elif defined(HAVE__SCRSIZE) + { + int dst[2]; + + _scrsize(dst); + if (lines) + *lines = dst[1]; + if (columns) + *columns = dst[0]; + return 0; + } +#elif defined(_WIN32) + { + intptr_t fh = 0; + CONSOLE_SCREEN_BUFFER_INFO sb_info; + + fh = _get_osfhandle(fd); + if (fh != (intptr_t) INVALID_HANDLE_VALUE && + GetConsoleScreenBufferInfo((HANDLE) fh, &sb_info)) { + if (lines) + *lines = 1 + sb_info.srWindow.Bottom - sb_info.srWindow.Top; + if (columns) + *columns = 1 + sb_info.srWindow.Right - sb_info.srWindow.Left; + + return 0; + } + } +#endif + if (columns) { + if ((s = getenv("COLUMNS"))) + *columns = atoi(s); + else + return -1; + } + if (lines) { + if ((s = getenv("LINES"))) + *lines = atoi(s); + else + return -1; + } + return 0; +} diff --git a/third_party/heimdal/lib/roken/getaddrinfo-test.c b/third_party/heimdal/lib/roken/getaddrinfo-test.c new file mode 100644 index 0000000..6bdc603 --- /dev/null +++ b/third_party/heimdal/lib/roken/getaddrinfo-test.c @@ -0,0 +1,151 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include "getarg.h" + +static int flags; +static int family; +static int socktype; + +static int verbose_counter; +static int version_flag; +static int help_flag; + +static struct getargs args[] = { + {"verbose", 0, arg_counter, &verbose_counter,"verbose", NULL}, + {"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; + + if (verbose_counter) + 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) + errx(1, "error: %s\n", gai_strerror(ret)); + + if (verbose_counter) + 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) { + if (verbose_counter) + printf ("\tbad address?\n"); + continue; + } + if (verbose_counter) { + 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; + } + + if (rk_SOCK_INIT()) + errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO)); + + 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]); + } + rk_SOCK_EXIT(); + return 0; +} diff --git a/third_party/heimdal/lib/roken/getaddrinfo.c b/third_party/heimdal/lib/roken/getaddrinfo.c new file mode 100644 index 0000000..12a26a7 --- /dev/null +++ b/third_party/heimdal/lib/roken/getaddrinfo.c @@ -0,0 +1,414 @@ +/* + * 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. + */ + +#include <config.h> + +#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, + ¤t, const_v6, &v6_addr, NULL); + } +#endif + if (family == PF_INET || family == PF_UNSPEC) { + ret = add_one (port, protocol, socktype, + ¤t, 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, + ¤t, 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, + ¤t, 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, + ¤t, 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, + ¤t, 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; + * ... + * }; + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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) + rk_freeaddrinfo(*res); + return ret; +} diff --git a/third_party/heimdal/lib/roken/getaddrinfo_hostspec.c b/third_party/heimdal/lib/roken/getaddrinfo_hostspec.c new file mode 100644 index 0000000..4541219 --- /dev/null +++ b/third_party/heimdal/lib/roken/getaddrinfo_hostspec.c @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* getaddrinfo via string specifying host and port */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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, 0 }, + { "udp/", SOCK_DGRAM, IPPROTO_UDP, 0 }, + { NULL, 0, 0, 0 } + }; + + 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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_getaddrinfo_hostspec(const char *hostspec, + int port, + struct addrinfo **ai) +{ + return roken_getaddrinfo_hostspec2(hostspec, 0, port, ai); +} diff --git a/third_party/heimdal/lib/roken/getarg.3 b/third_party/heimdal/lib/roken/getarg.3 new file mode 100644 index 0000000..0d01d8f --- /dev/null +++ b/third_party/heimdal/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$ +.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 Fl foo= Ns Ar bar . +Long option flags can either be specified as they are +.Pf ( Fl Fl help ) , +or with an (boolean parsable) option +.Pf ( Fl Fl help= Ns Ar yes , +.Fl Fl help= Ns Ar true , +or similar), or they can also be negated +.Pf ( Fl Fl no-help +is the same as +.Fl Fl help= Ns no ) , +and if you're really confused you can do it multiple times +.Pf ( Fl Fl no-no-help= Ns Ar false , +or even +.Fl 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 integrated 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/third_party/heimdal/lib/roken/getarg.c b/third_party/heimdal/lib/roken/getarg.c new file mode 100644 index 0000000..76f3c80 --- /dev/null +++ b/third_party/heimdal/lib/roken/getarg.c @@ -0,0 +1,607 @@ +/* + * 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. + */ + +#include <config.h> + +#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, + char *(i18n)(const char *)) +{ + 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 = (*i18n)(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, + char *(i18n)(const char *)) +{ + size_t 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 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, i18n); + 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, i18n); + printf("Fl 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, i18n); + printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf); + print_arg(buf, sizeof(buf), 1, 1, args + i, i18n); + printf(".Fl 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, i18n); + printf("%s", buf); + if(args[i].long_name) + printf(" ,"); + printf("\n"); + } + if(args[i].long_name){ + printf(".Fl Fl %s%s", + args[i].type == arg_negative_flag ? "no-" : "", + args[i].long_name); + print_arg(buf, sizeof(buf), 1, 1, args + i, i18n); + 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; +} + +static char * +builtin_i18n(const char *str) +{ + return rk_UNCONST(str); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +arg_printusage (struct getargs *args, + size_t num_args, + const char *progname, + const char *extra_string) +{ + arg_printusage_i18n(args, num_args, "Usage", + progname, extra_string, builtin_i18n); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +arg_printusage_i18n (struct getargs *args, + size_t num_args, + const char *usage, + const char *progname, + const char *extra_string, + char *(*i18n)(const char *)) +{ + size_t i, max_len = 0; + char buf[128]; + int col = 0, columns; + + if (progname == NULL) + progname = getprogname(); + + if (i18n == NULL) + i18n = builtin_i18n; + + if(getenv("GETARGMANDOC")){ + mandoc_template(args, num_args, progname, extra_string, i18n); + return; + } + if(get_window_size(2, NULL, &columns) == -1) + columns = 80; + col = 0; + col += fprintf (stderr, "%s: %s", usage, 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], i18n); + 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], i18n); + 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) { + 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], i18n); + 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], i18n); + count += fprintf(stderr, "%s", buf); + } + while(count++ <= max_len) + putc (' ', stderr); + fprintf (stderr, "%s\n", (*i18n)(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) +{ + size_t 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) { + *flag = rk_random() & 1; + } 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 (); + UNREACHABLE(return 0); + } +} + +static int +arg_match_short (struct getargs *args, size_t num_args, + char *argv, int argc, char **rargv, int *goptind) +{ + size_t 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; + int a = (int)j; + + if((*c->func)(TRUE, argc, rargv, goptind, &a, c->data)) + return ARG_ERR_BAD_ARG; + j = a; + 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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getarg(struct getargs *args, size_t num_args, + int argc, char **argv, int *goptind) +{ + int i; + int ret = 0; + + rk_random_init(); + (*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; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/getarg.h b/third_party/heimdal/lib/roken/getarg.h new file mode 100644 index 0000000..1065c7c --- /dev/null +++ b/third_party/heimdal/lib/roken/getarg.h @@ -0,0 +1,112 @@ +/* + * 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$ */ + +#ifndef __GETARG_H__ +#define __GETARG_H__ + +#include <stddef.h> + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getarg(struct getargs *args, size_t num_args, + int argc, char **argv, int *goptind); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +arg_printusage (struct getargs *args, + size_t num_args, + const char *progname, + const char *extra_string); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +arg_printusage_i18n (struct getargs *args, + size_t num_args, + const char *usage, + const char *progname, + const char *extra_string, + char *(*i18n)(const char *)); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +free_getarg_strings (getarg_strings *); + +#endif /* __GETARG_H__ */ diff --git a/third_party/heimdal/lib/roken/getauxval.c b/third_party/heimdal/lib/roken/getauxval.c new file mode 100644 index 0000000..f12bc93 --- /dev/null +++ b/third_party/heimdal/lib/roken/getauxval.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2016 - 2017 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. + */ + +#include <config.h> + +#ifdef HAVE_SYS_AUXV_H +#include <sys/auxv.h> +#endif + +#if defined(ENABLE_PTHREAD_SUPPORT) && defined(HAVE_PTHREAD_H) +#include <pthread.h> +#endif + +#include <errno.h> + +#include "roken.h" +#include "getauxval.h" + +int rk_injected_auxv = 0; /* shared with issuid() for testing */ +static int has_proc_auxv = 1; +static int proc_auxv_ret = 0; + +#if defined(ENABLE_PTHREAD_SUPPORT) && defined(HAVE_PTHREAD_H) +pthread_once_t readprocauxv_once = PTHREAD_ONCE_INIT; +#endif + +/* + * There's no standard maximum. + * + * At the time of this writing we observe some 20 or so auxv entries. + * If eventually that grows much larger then rk_getprocaux*() will see a + * truncated auxv. + */ +#define MAX_AUXV_COUNT 128 +static auxv_t auxv[MAX_AUXV_COUNT]; + +static void +do_readprocauxv(void) +{ + char *p = (void *)auxv; + ssize_t bytes = 0; + size_t sz = sizeof(auxv) - sizeof(auxv[0]); /* leave terminator */ + int save_errno = errno; + int fd; + + errno = 0; + memset(auxv, 0, sizeof(auxv)); /* terminates our copy */ + if ((fd = open("/proc/self/auxv", O_RDONLY)) == -1) { + if (errno == ENOENT) + has_proc_auxv = 0; + goto out; + } + + do { + if ((bytes = read(fd, p, sz)) > 0) { + sz -= bytes; + p += bytes; + } + } while (sz && ((bytes == -1 && errno == EINTR) || bytes > 0)); + +out: + proc_auxv_ret = errno; + if (fd != -1) + (void) close(fd); + if (sz == 0 && bytes > 0) + warnx("/proc/self/auxv has more entries than expected"); + errno = save_errno; + return; +} + +static int +readprocauxv(void) +{ +#if defined(ENABLE_PTHREAD_SUPPORT) && defined(HAVE_PTHREAD_H) + pthread_once(&readprocauxv_once, do_readprocauxv); +#else + do_readprocauxv(); +#endif + return proc_auxv_ret; +} + +/** + * Looks up an auxv entry in /proc/self/auxv. Preserves errno. + * + * @return a pointer to an auxv_t if found, else NULL. + */ +ROKEN_LIB_FUNCTION const auxv_t * ROKEN_LIB_CALL +rk_getauxv(unsigned long type) +{ + auxv_t *a; + + if (!has_proc_auxv || type > INT_MAX) + return NULL; + + if (readprocauxv() != 0) + return NULL; + + for (a = auxv; a - auxv < MAX_AUXV_COUNT; a++) { + if ((int)a->a_type == (int)type) + return a; + if (a->a_type == 0 && a->a_un.a_val == 0) + break; + } + return NULL; +} + +#ifdef HAVE_GETAUXVAL +static unsigned long +rk_getprocauxval(unsigned long type) +{ + const auxv_t *a = rk_getauxv(type); + + if (a == NULL) { + errno = ENOENT; + return 0; + } + return a->a_un.a_val; +} +#endif + +/** + * Like the nearly-standard getauxval(). If the auxval is not found + * returns zero and always sets errno to ENOENT. Otherwise if auxval is + * found it leaves errno as it was, even if the value is zero. + * + * @return The value of the ELF auxiliary value for the given type, or + * zero and sets errno to ENOENT. + */ +ROKEN_LIB_FUNCTION unsigned long ROKEN_LIB_CALL +rk_getauxval(unsigned long type) +{ + const auxv_t *a; +#ifdef HAVE_GETAUXVAL +#ifdef GETAUXVAL_SETS_ERRNO + if (rk_injected_auxv) + return rk_getprocauxval(type); + return getauxval(type); +#else + unsigned long ret; + unsigned long ret2; + static int getauxval_sets_errno = -1; + int save_errno = errno; + + if (rk_injected_auxv) + return rk_getprocauxval(type); + + errno = 0; + ret = getauxval(type); + if (ret != 0 || errno == ENOENT || getauxval_sets_errno == 1) { + if (ret != 0) + errno = save_errno; + else if (getauxval_sets_errno > 0 && errno == 0) + errno = save_errno; + return ret; + } + + if (getauxval_sets_errno == 0) { + errno = save_errno; + a = rk_getauxv(type); + if (a == NULL) { + errno = ENOENT; + return 0; + } + return a->a_un.a_val; + } + + /* + * We've called getauxval() and it returned 0, but we don't know if + * getauxval() sets errno = ENOENT when entries are not found. + * + * Attempt to detect whether getauxval() sets errno = ENOENT by + * calling it with what should be a bogus type. + */ + + errno = 0; + ret2 = getauxval(~type); + if (ret2 == 0 && errno == ENOENT) { + getauxval_sets_errno = 1; + errno = save_errno; + return ret; + } + + getauxval_sets_errno = 0; + errno = save_errno; +#endif +#endif + if ((a = rk_getauxv(type)) == NULL) { + errno = ENOENT; + return 0; + } + return a->a_un.a_val; +} + +/** + * *Internal* function for testing by injecting or overwriting an ELF + * auxiliary vector entry. + * + * @return zero on success or ENOSPC if there are too many ELF auxiliary + * entries. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_injectauxv(auxv_t *e) +{ + size_t i; + int ret; + + /* + * This function is racy, but as an internal function never meant to + * be called in a threaded program, we don't care. + */ + + if ((ret = readprocauxv()) != 0) + return ret; + + rk_injected_auxv = 1; + for (i = 0; i < MAX_AUXV_COUNT - 1 && auxv[i].a_type != 0; i++) { + /* e->a_type == 0 -> truncate auxv, delete all entries */ + if (auxv[i].a_type == e->a_type || e->a_type == 0) + break; + } + if (i == MAX_AUXV_COUNT - 1) + return ENOSPC; + auxv[i] = e[0]; + return 0; +} diff --git a/third_party/heimdal/lib/roken/getauxval.h b/third_party/heimdal/lib/roken/getauxval.h new file mode 100644 index 0000000..3088f0c --- /dev/null +++ b/third_party/heimdal/lib/roken/getauxval.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2016 - 2017 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. + */ + +#ifndef RK_GETAUXVAL_H +#define RK_GETAUXVAL_H + +#include <config.h> + +#ifdef HAVE_SYS_AUXV_H +#include <sys/auxv.h> +#endif + +#ifdef HAVE_SYS_EXEC_ELF_H +#include <sys/exec_elf.h> +#endif + +#ifndef HAVE_AUXV_T +/* + * Illumos defines auxv_t per the ABI standards, but all other OSes seem + * to use { long; long; } instead, depends on sizeof(long) == + * sizeof(void *), and they do not define an auxv_t. + * + * sizeof(long) != sizeof(void *) on WIN64, but Windows doesn't have + * /proc/self/auxv anyways. Just in case we use uintptr_t. + */ +typedef struct rk_auxv { + uintptr_t a_type; + union { + uintptr_t a_val; + uintptr_t a_ptr; /* This would be void * */ + uintptr_t a_fnc; /* This would be void (*)(void) */ + } a_un; +} auxv_t; +#endif + +#ifdef __linux__ +/* + * Older glibcs have no <sys/auxv.h>, but do nonetheless have an ELF + * auxiliary vector, and with the values for these types that appear in + * <sys/auxv.h> in later versions. + * + * Note that Travis-CI still uses Ubuntu 14 for its Linux build + * environment, which has such an older glibc version. + */ +#ifndef AT_UID +#define AT_UID 11 +#endif +#ifndef AT_EUID +#define AT_EUID 12 +#endif +#ifndef AT_GID +#define AT_GID 13 +#endif +#ifndef AT_EGID +#define AT_EGID 14 +#endif +#ifndef AT_SECURE +#define AT_SECURE 23 +#endif +#endif + +#if __sun +#if !defined(AT_UID) && defined(AT_SUN_RUID) +#define AT_UID AT_SUN_RUID +#endif +#if !defined(AT_EUID) && defined(AT_SUN_UID) +#define AT_EUID AT_SUN_UID +#endif +#if !defined(AT_GID) && defined(AT_SUN_RGID) +#define AT_GID AT_SUN_RGID +#endif +#if !defined(AT_EGID) && defined(AT_SUN_GID) +#define AT_EGID AT_SUN_GID +#endif +#endif /* __sun */ + +/* NetBSD calls AT_UID AT_RUID. Everyone else calls it AT_UID. */ +#if defined(AT_EUID) && defined(AT_RUID) && !defined(AT_UID) +#define AT_UID AT_RUID +#endif +#if defined(AT_EGID) && defined(AT_RGID) && !defined(AT_GID) +#define AT_GID AT_RGID +#endif + +#if defined(AT_EUID) && defined(AT_UID) && !defined(AT_RUID) +#define AT_RUID AT_UID +#endif +#if defined(AT_EGID) && defined(AT_GID) && !defined(AT_RGID) +#define AT_RGID AT_GID +#endif + + +/* + * There are three different names for the type whose value is the path + * to the executable being run by the process. + */ +#if defined(AT_EXECFN) && !defined(AT_EXECPATH) +#define AT_EXECPATH AT_EXECFN +#endif +#if defined(AT_EXECFN) && !defined(AT_SUN_EXECNAME) +#define AT_SUN_EXECNAME AT_EXECFN +#endif +#if defined(AT_EXECPATH) && !defined(AT_EXECFN) +#define AT_EXECFN AT_EXECPATH +#endif +#if defined(AT_EXECPATH) && !defined(AT_SUN_EXECNAME) +#define AT_SUN_EXECNAME AT_EXECPATH +#endif +#if defined(AT_SUN_EXECNAME) && !defined(AT_EXECFN) +#define AT_EXECFN AT_SUN_EXECNAME +#endif +#if defined(AT_SUN_EXECNAME) && !defined(AT_EXECPATH) +#define AT_EXECPATH AT_SUN_EXECNAME +#endif + +/* We need this for part of the getauxval() brokenness detection below */ +#ifdef __GLIBC__ +#ifdef __GLIBC_PREREQ +#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) __GLIBC_PREREQ(maj, min) +#else +#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) \ + ((__GLIBC << 16) + GLIBC_MINOR >= ((maj) << 16) + (min)) +#endif + +/* + * Detect whether getauxval() is broken. + * + * Do change this check in order to manually test rk_getauxval() for + * older glibcs. + */ +#if HAVE_GLIBC_API_VERSION_SUPPORT(2, 19) +#define GETAUXVAL_SETS_ERRNO +/* #else it's broken */ +#endif +#endif + +ROKEN_LIB_FUNCTION const auxv_t * ROKEN_LIB_CALL + rk_getauxv(unsigned long type); + +ROKEN_LIB_FUNCTION unsigned long ROKEN_LIB_CALL + rk_getauxval(unsigned long); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_injectauxv(auxv_t *e); + +#endif /* RK_GETAUXVAL_H */ diff --git a/third_party/heimdal/lib/roken/getcwd.c b/third_party/heimdal/lib/roken/getcwd.c new file mode 100644 index 0000000..f8917b2 --- /dev/null +++ b/third_party/heimdal/lib/roken/getcwd.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. + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#include "roken.h" + +ROKEN_LIB_FUNCTION char* ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/getdtablesize.c b/third_party/heimdal/lib/roken/getdtablesize.c new file mode 100644 index 0000000..08c0661 --- /dev/null +++ b/third_party/heimdal/lib/roken/getdtablesize.c @@ -0,0 +1,99 @@ +/* + * 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. + */ + +#include <config.h> + +#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 + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/getegid.c b/third_party/heimdal/lib/roken/getegid.c new file mode 100644 index 0000000..663fb1d --- /dev/null +++ b/third_party/heimdal/lib/roken/getegid.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE_GETEGID + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getegid(void) +{ + return getgid(); +} + +#endif diff --git a/third_party/heimdal/lib/roken/geteuid.c b/third_party/heimdal/lib/roken/geteuid.c new file mode 100644 index 0000000..598a739 --- /dev/null +++ b/third_party/heimdal/lib/roken/geteuid.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE_GETEUID + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +geteuid(void) +{ + return getuid(); +} + +#endif diff --git a/third_party/heimdal/lib/roken/getgid.c b/third_party/heimdal/lib/roken/getgid.c new file mode 100644 index 0000000..b24ceeb --- /dev/null +++ b/third_party/heimdal/lib/roken/getgid.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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_GETGID + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getgid(void) +{ + return 17; +} + +#endif diff --git a/third_party/heimdal/lib/roken/gethostname.c b/third_party/heimdal/lib/roken/gethostname.c new file mode 100644 index 0000000..8389091 --- /dev/null +++ b/third_party/heimdal/lib/roken/gethostname.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. + */ + +#include <config.h> +#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).) + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/getifaddrs-test.c b/third_party/heimdal/lib/roken/getifaddrs-test.c new file mode 100644 index 0000000..252763d --- /dev/null +++ b/third_party/heimdal/lib/roken/getifaddrs-test.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009, Secure Endpoints Inc. 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. + */ + +#include <config.h> +#include <err.h> +#include "getarg.h" + +#include "roken.h" + +#include <ifaddrs.h> + +static int verbose_counter; +static int version_flag; +static int help_flag; + +static struct getargs args[] = { + {"verbose", 0, arg_counter, &verbose_counter,"verbose", 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, ""); + exit (ret); +} + + +static 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"); +} + +static void +print_ifaddrs(struct ifaddrs *x) +{ + struct ifaddrs *p; + + for(p = x; p; p = p->ifa_next) { + if (verbose_counter) { + 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(int argc, char **argv) +{ + struct ifaddrs *addrs = NULL; + int ret, 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) { + fprintf (stderr, "%s from %s-%s\n", getprogname(), PACKAGE, VERSION); + return 0; + } + + if (rk_SOCK_INIT()) + errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO)); + + ret = getifaddrs(&addrs); + if (ret != 0) + err(1, "getifaddrs"); + + if (addrs == NULL) + errx(1, "address == NULL"); + + print_ifaddrs(addrs); + + /* Check that freeifaddrs doesn't crash */ + freeifaddrs(addrs); + + rk_SOCK_EXIT(); + + return 0; +} diff --git a/third_party/heimdal/lib/roken/getifaddrs.c b/third_party/heimdal/lib/roken/getifaddrs.c new file mode 100644 index 0000000..72eb5aa --- /dev/null +++ b/third_party/heimdal/lib/roken/getifaddrs.c @@ -0,0 +1,1309 @@ +/* + * 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. + */ + +#include <config.h> +#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; +} + +/* ====================================================================== */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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) != 0)) { + /* 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; +} + +void ROKEN_LIB_FUNCTION +rk_freeifaddrs(struct ifaddrs *ifp) +{ + /* AF_NETLINK method uses a single allocation for all interfaces */ + free(ifp); +} + +#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; + 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) */ + +/** + * Join two struct ifaddrs lists by appending supp to base. + * Either may be NULL. The new list head (usually base) will be + * returned. + */ +static struct ifaddrs * +append_ifaddrs(struct ifaddrs *base, struct ifaddrs *supp) { + if (!base) + return supp; + + if (!supp) + return base; + + while (base->ifa_next) + base = base->ifa_next; + + base->ifa_next = supp; + + return base; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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) + /* Do IPv6 and IPv4 queries separately then join the result. + * + * HP-UX only returns IPv6 addresses using SIOCGLIFCONF, + * SIOCGIFCONF has to be used for IPv4 addresses. The result is then + * merged. + * + * Solaris needs particular care, because a SIOCGLIFCONF lookup using + * AF_UNSPEC can fail in a Zone requiring an AF_INET lookup, so we just + * do them separately the same as for HP-UX. See + * http://repo.or.cz/w/heimdal.git/commitdiff/76afc31e9ba2f37e64c70adc006ade9e37e9ef73 + */ + if (ret) { + int v6err, v4err; + struct ifaddrs *v6addrs, *v4addrs; + + v6err = getlifaddrs2 (&v6addrs, AF_INET6, SIOCGLIFCONF, SIOCGLIFFLAGS, + sizeof(struct lifreq)); + v4err = getifaddrs2 (&v4addrs, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, + sizeof(struct ifreq)); + if (v6err) + v6addrs = NULL; + if (v4err) + v4addrs = NULL; + + if (v6addrs) { + if (v4addrs) + *ifap = append_ifaddrs(v6addrs, v4addrs); + else + *ifap = v6addrs; + } else if (v4addrs) { + *ifap = v4addrs; + } else { + *ifap = NULL; + } + + ret = (v6err || v4err) ? -1 : 0; + } +#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; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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); + } +} + +#endif /* !AF_NETLINK */ + +#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/third_party/heimdal/lib/roken/getifaddrs_w32.c b/third_party/heimdal/lib/roken/getifaddrs_w32.c new file mode 100644 index 0000000..beb29b3 --- /dev/null +++ b/third_party/heimdal/lib/roken/getifaddrs_w32.c @@ -0,0 +1,161 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <roken.h> + +#include <ifaddrs.h> + +#ifndef _WIN32 +#error This is a Windows specific implementation. +#endif + +static struct sockaddr * +dupaddr(const sockaddr_gen * src) +{ + sockaddr_gen * d = malloc(sizeof(*d)); + + if (d) { + memcpy(d, src, sizeof(*d)); + } + + return (struct sockaddr *) d; +} + +int ROKEN_LIB_FUNCTION +rk_getifaddrs(struct ifaddrs **ifpp) +{ + SOCKET s = INVALID_SOCKET; + size_t il_len = 8192; + int ret = -1; + INTERFACE_INFO *il = NULL; + + *ifpp = NULL; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == INVALID_SOCKET) + return -1; + + for (;;) { + DWORD cbret = 0; + + il = malloc(il_len); + if (!il) + break; + + ZeroMemory(il, il_len); + + if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, + (LPVOID) il, (DWORD) il_len, &cbret, + NULL, NULL) == 0) { + il_len = cbret; + break; + } + + free (il); + il = NULL; + + if (WSAGetLastError() == WSAEFAULT && cbret > il_len) { + il_len = cbret; + } else { + break; + } + } + + if (!il) + goto _exit; + + /* il is an array of INTERFACE_INFO structures. il_len has the + actual size of the buffer. The number of elements is + il_len/sizeof(INTERFACE_INFO) */ + + { + size_t n = il_len / sizeof(INTERFACE_INFO); + size_t i; + + for (i = 0; i < n; i++ ) { + struct ifaddrs *ifp; + + ifp = malloc(sizeof(*ifp)); + if (ifp == NULL) + break; + + ZeroMemory(ifp, sizeof(*ifp)); + + ifp->ifa_next = NULL; + ifp->ifa_name = NULL; + ifp->ifa_flags = il[i].iiFlags; + ifp->ifa_addr = dupaddr(&il[i].iiAddress); + ifp->ifa_netmask = dupaddr(&il[i].iiNetmask); + ifp->ifa_broadaddr = dupaddr(&il[i].iiBroadcastAddress); + ifp->ifa_data = NULL; + + *ifpp = ifp; + ifpp = &ifp->ifa_next; + } + + if (i == n) + ret = 0; + } + + _exit: + + if (s != INVALID_SOCKET) + closesocket(s); + + if (il) + free (il); + + return ret; +} + +void ROKEN_LIB_FUNCTION +rk_freeifaddrs(struct ifaddrs *ifp) +{ + struct ifaddrs *p, *q; + + for(p = ifp; p; ) { + if (p->ifa_name) + 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); + } +} diff --git a/third_party/heimdal/lib/roken/getipnodebyaddr.c b/third_party/heimdal/lib/roken/getipnodebyaddr.c new file mode 100644 index 0000000..afebe91 --- /dev/null +++ b/third_party/heimdal/lib/roken/getipnodebyaddr.c @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * lookup `src, len' (address family `af') in DNS and return a pointer + * to a malloced struct hostent or NULL. + */ + +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/getipnodebyname.c b/third_party/heimdal/lib/roken/getipnodebyname.c new file mode 100644 index 0000000..ee430c7 --- /dev/null +++ b/third_party/heimdal/lib/roken/getipnodebyname.c @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#include <config.h> + +#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. + */ + +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/getnameinfo.c b/third_party/heimdal/lib/roken/getnameinfo.c new file mode 100644 index 0000000..9d11860 --- /dev/null +++ b/third_party/heimdal/lib/roken/getnameinfo.c @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#include <config.h> + +#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; +} + +/* + * + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/getnameinfo_verified.c b/third_party/heimdal/lib/roken/getnameinfo_verified.c new file mode 100644 index 0000000..6175291 --- /dev/null +++ b/third_party/heimdal/lib/roken/getnameinfo_verified.c @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#include <config.h> + +#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. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; + void *saaddr; + size_t sasize; + + 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; + + saaddr = socket_get_address(sa); + sasize = socket_addr_size(sa); + for (a = ai; a != NULL; a = a->ai_next) { + if (sasize == socket_addr_size(a->ai_addr) && + memcmp(saaddr, socket_get_address(a->ai_addr), sasize) == 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/third_party/heimdal/lib/roken/getopt.c b/third_party/heimdal/lib/roken/getopt.c new file mode 100644 index 0000000..f035f74 --- /dev/null +++ b/third_party/heimdal/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 <config.h> +#include "roken.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * get option letter from argument vector + */ +ROKEN_LIB_VARIABLE int opterr = 1; /* if error message should be printed */ +ROKEN_LIB_VARIABLE int optind = 1; /* index into parent argv vector */ +ROKEN_LIB_VARIABLE int optopt; /* character checked for validity */ +int optreset; /* reset getopt */ +ROKEN_LIB_VARIABLE char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getopt(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/third_party/heimdal/lib/roken/getprogname.c b/third_party/heimdal/lib/roken/getprogname.c new file mode 100644 index 0000000..a310208 --- /dev/null +++ b/third_party/heimdal/lib/roken/getprogname.c @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE___PROGNAME +const char *__progname; +#endif + +#ifndef HAVE_GETPROGNAME +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +getprogname(void) +{ + return __progname; +} +#endif /* HAVE_GETPROGNAME */ diff --git a/third_party/heimdal/lib/roken/gettimeofday.c b/third_party/heimdal/lib/roken/gettimeofday.c new file mode 100644 index 0000000..918b6f6 --- /dev/null +++ b/third_party/heimdal/lib/roken/gettimeofday.c @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#include <config.h> +#include "roken.h" +#ifndef HAVE_GETTIMEOFDAY + +#ifdef _WIN32 + +typedef BOOL (WINAPI *LPFN_GETSYSTEMTIME) (LPFILETIME); + +static LPFN_GETSYSTEMTIME lpGetSystemTime = NULL; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +gettimeofday (struct timeval *tp, void *ignore) +{ + FILETIME ft; + ULARGE_INTEGER li; + ULONGLONG ull; + + if (lpGetSystemTime == NULL) { + HANDLE h1; + LPFN_GETSYSTEMTIME fn; + + h1 = GetModuleHandle(TEXT("kernel32.dll")); /* no refcount increase */ + fn = (LPFN_GETSYSTEMTIME)GetProcAddress(h1, + "GetSystemTimePreciseAsFileTime"); + if (fn == NULL) + fn = (LPFN_GETSYSTEMTIME)GetProcAddress(h1, + "GetSystemTimeAsFileTime"); + lpGetSystemTime = fn; + } + + lpGetSystemTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + ull = li.QuadPart; + + ull -= 116444736000000000i64; + ull /= 10i64; /* ull is now in microseconds */ + + tp->tv_usec = (ull % 1000000i64); + tp->tv_sec = (ull / 1000000i64); + + return 0; +} +#else + +/* + * Simple gettimeofday that only returns seconds. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +gettimeofday (struct timeval *tp, void *ignore) +{ + time_t t; + + t = time(NULL); + tp->tv_sec = (long) t; + tp->tv_usec = 0; + return 0; +} + +#endif /* !_WIN32 */ +#endif diff --git a/third_party/heimdal/lib/roken/getuid.c b/third_party/heimdal/lib/roken/getuid.c new file mode 100644 index 0000000..63fdec1 --- /dev/null +++ b/third_party/heimdal/lib/roken/getuid.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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_GETUID + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getuid(void) +{ + return 17; +} + +#endif diff --git a/third_party/heimdal/lib/roken/getuserinfo.c b/third_party/heimdal/lib/roken/getuserinfo.c new file mode 100644 index 0000000..7fd2ca9 --- /dev/null +++ b/third_party/heimdal/lib/roken/getuserinfo.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2017 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. + */ + +#include <config.h> +#include "roken.h" + +#ifdef WIN32 +#include <Shlobj.h> // need to include definitions of constants +#define SECURITY_WIN32 +#include <security.h> +#else +#include <sys/types.h> +#include <pwd.h> +#include <unistd.h> +#endif + +/** + * Returns the user's SHELL. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_shell(char *shell, size_t shellsz) +{ + char *p; + +#ifndef WIN32 +#ifdef HAVE_GETPWNAM_R + size_t buflen = 2048; + + if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); +#endif + + if (issuid()) + return "/bin/sh"; + + p = secure_getenv("SHELL"); + if (p != NULL && p[0] != '\0') { + if (strlcpy(shell, p, shellsz) < shellsz) + return shell; + errno = ERANGE; + return NULL; + } + +#ifdef HAVE_GETPWNAM_R + { + struct passwd pwd; + struct passwd *pwdp; + char buf[buflen]; + char user[128]; + const char *username = roken_get_username(user, sizeof(user)); + + if (username && + getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && + pwdp != NULL && pwdp->pw_shell != NULL) { + if (strlcpy(shell, pwdp->pw_shell, shellsz) < shellsz) + return shell; + errno = ERANGE; + return NULL; + } + } +#endif + errno = 0; + return "/bin/sh"; +#else + /* Windows */ + p = getenv("SHELL"); + if (p != NULL && p[0] != '\0') { + if (strlcpy(shell, p, shellsz) < shellsz) + return shell; + errno = ERANGE; + return NULL; + } + errno = 0; + return NULL; +#endif +} + +/** + * Returns the home directory. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_homedir(char *home, size_t homesz) +{ + char *p; + +#ifdef WIN32 + if (homesz < MAX_PATH) { + errno = ERANGE; + return NULL; + } + + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, + SHGFP_TYPE_CURRENT, home))) + return home; + + if ((p = getenv("HOMEDRIVE")) != NULL && p[0] != '\0') { + if (strlcpy(home, p, homesz) >= homesz) { + errno = ERANGE; + return NULL; + } + if ((p = getenv("HOMEPATH")) != NULL) { + if (strlcat(home, p, homesz) < homesz) + return home; + errno = ERANGE; + return NULL; + } + return home; + } + fallthrough; +#else +#ifdef HAVE_GETPWNAM_R + size_t buflen = 2048; + + if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); +#endif + + if (issuid()) { + errno = 0; + return NULL; + } + + p = secure_getenv("HOME"); + if (p != NULL && p[0] != '\0') { + if (strlcpy(home, p, homesz) < homesz) + return home; + errno = ERANGE; + return NULL; + } + +#ifdef HAVE_GETPWNAM_R + { + char user[128]; + const char *username = roken_get_username(user, sizeof(user)); + struct passwd pwd; + struct passwd *pwdp; + char buf[buflen]; + + if (username && + getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 && + pwdp != NULL && pwdp->pw_dir != NULL) { + if (strlcpy(home, pwdp->pw_dir, homesz) < homesz) + return home; + errno = ERANGE; + return NULL; + } + } +#endif +#endif + errno = 0; + return NULL; +} + +/** + * Returns the home directory on Unix, or the AppData directory on + * Windows. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_appdatadir(char *appdata, size_t appdatasz) +{ +#ifdef WIN32 + char *p; +#endif + +#ifndef WIN32 + return roken_get_homedir(appdata, appdatasz); +#else + if (appdatasz < MAX_PATH) { + errno = ERANGE; + return NULL; + } + + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, + SHGFP_TYPE_CURRENT, appdata))) + return appdata; + + if ((p = getenv("APPDATA")) != NULL && p[0] != '\0') { + if (strlcpy(appdata, p, appdatasz) < appdatasz) + return appdata; + errno = ERANGE; + return NULL; + } + + errno = 0; + return NULL; +#endif +} + +/** + * Return a bare username. This is used for, e.g., constructing default + * principal names. + * + * On POSIX systems, if the caller is not set-uid-like, then this will return + * the value of the USER or LOGNAME environment variables (in that order of + * preference), else the username found by looking up the effective UID. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_username(char *user, size_t usersz) +{ + char *p; + +#ifdef WIN32 + ULONG sz = usersz; + + if (GetUserNameEx(NameSamCompatible, user, &sz)) { + /* + * There's no EXTENDED_NAME_FORMAT for "bare username". We we + * have to parse one. + */ + p = strchr(user, '\\'); + if (p != NULL) { + p++; + memmove(user, p, strlen(p) + 1); + } + return user; + } else { + DWORD err = GetLastError(); + if (err == ERROR_MORE_DATA) { + errno = ERANGE; + return NULL; + } + /* %USERNAME% is generally bare */ + p = getenv("USERNAME"); + if (p != NULL && p[0] != '\0') { + if (strchr(p, '\\') != NULL) + p = strchr(p, '\\') + 1; + if (strlcpy(user, p, usersz) < usersz) + return user; + errno = ERANGE; + return NULL; + } + } +#else +#ifdef HAVE_GETPWUID_R + size_t buflen = 2048; + + if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0) + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); +#endif + + p = secure_getenv("USER"); + if (p == NULL || p[0] == '\0') + p = secure_getenv("LOGNAME"); + if (p != NULL && p[0] != '\0') { + if (strlcpy(user, p, usersz) < usersz) + return user; + errno = ERANGE; + return NULL; + } + +#ifdef HAVE_GETPWUID_R + { + struct passwd pwd; + struct passwd *pwdp; + char buf[buflen]; + + if (getpwuid_r(getuid(), &pwd, buf, buflen, &pwdp) == 0 && + pwdp != NULL && pwdp->pw_name != NULL) { + if (strlcpy(user, pwdp->pw_name, usersz) < usersz) + return user; + errno = ERANGE; + return NULL; + } + } +#endif +#endif + errno = 0; + return NULL; +} + +/** + * Return a bare username. This is used for, e.g., constructing default + * principal names. + * + * On POSIX systems this returns the name recorded in the system as currently + * logged in on the current terminal. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_loginname(char *user, size_t usersz) +{ +#ifdef WIN32 + return roken_get_username(user, usersz); +#else +#ifdef HAVE_GETLOGIN_R + if ((errno = getlogin_r(user, usersz)) == 0) + return user; + if (errno != ENOENT) + return NULL; +#else +#ifdef HAVE_GETLOGIN + if ((p = getlogin()) != NULL && p[0] != '\0') { + if (strlcpy(user, p, usersz) < usersz) + return user; + errno = ERANGE; + return NULL; + } + if (errno != ENOENT) + return NULL; +#endif +#endif + errno = 0; + return NULL; +#endif +} diff --git a/third_party/heimdal/lib/roken/getusershell.c b/third_party/heimdal/lib/roken/getusershell.c new file mode 100644 index 0000000..6f7145d --- /dev/null +++ b/third_party/heimdal/lib/roken/getusershell.c @@ -0,0 +1,185 @@ +/* + * 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. + */ + +#include <config.h> + +#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. + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +getusershell() +{ + char *ret; + + if (curshell == NULL) + curshell = initshells(); + ret = *curshell; + if (ret != NULL) + curshell++; + return (ret); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +endusershell() +{ + if (shells != NULL) + free(shells); + shells = NULL; + if (strings != NULL) + free(strings); + strings = NULL; + curshell = NULL; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/h_errno.c b/third_party/heimdal/lib/roken/h_errno.c new file mode 100644 index 0000000..7e49f80 --- /dev/null +++ b/third_party/heimdal/lib/roken/h_errno.c @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include <config.h> + +#ifndef HAVE_H_ERRNO +int h_errno = -17; /* Some magic number */ +#endif diff --git a/third_party/heimdal/lib/roken/hex-test.c b/third_party/heimdal/lib/roken/hex-test.c new file mode 100644 index 0000000..01f21c8 --- /dev/null +++ b/third_party/heimdal/lib/roken/hex-test.c @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <hex.h> + +int +main(int argc, char **argv) +{ + int numerr = 0; + int numtest = 1; + struct test { + void *data; + ssize_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" }, + /* Embedded NUL, non-ASCII / binary */ + { "\0\x01\x1a\xad\xf1\xff", 6, "00011AADF1FF" }, + /* Invalid encodings */ + { "", -1, "00.11AADF1FF" }, + { "", -1, "000x1AADF1FF" }, + { "", -1, "00011?ADF1FF" }, + { NULL, 0, NULL } + }; + for(t = tests; t->data; t++) { + ssize_t len; + char *str; + + if (t->len > -1) { + (void) 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 != %ld\n", numtest, + (long)len, (long)t->len); + numerr++; + } else if (t->len > -1 && 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/third_party/heimdal/lib/roken/hex.c b/third_party/heimdal/lib/roken/hex.c new file mode 100644 index 0000000..cc47fa4 --- /dev/null +++ b/third_party/heimdal/lib/roken/hex.c @@ -0,0 +1,114 @@ +/* + * 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. + */ + + +#include <config.h> +#include "roken.h" +#include <ctype.h> +#include "hex.h" + +static const char hexchar[16] = "0123456789ABCDEF"; + +static inline int +pos(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'A' && c <= 'F') + return 10 + c - 'A'; + if (c >= 'a' && c <= 'f') + return 10 + c - 'a'; + return -1; +} + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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) { + *str = NULL; + return -1; + } + + p = malloc(size * 2 + 1); + if (p == NULL) { + *str = 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; +} + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +hex_decode(const char *str, void *data, size_t len) +{ + size_t l; + unsigned char *p = data; + size_t i; + int d; + + l = strlen(str); + + /* check for overflow, same as (l+1)/2 but overflow safe */ + if ((l/2) + (l&1) > len) + return -1; + + if (l & 1) { + if ((d = pos(str[0])) == -1) + return -1; + p[0] = d; + str++; + p++; + } + for (i = 0; i < l / 2; i++) { + if ((d = pos(str[i * 2])) == -1) + return -1; + p[i] = d << 4; + if ((d = pos(str[(i * 2) + 1])) == -1) + return -1; + p[i] |= d; + } + return i + (l & 1); +} diff --git a/third_party/heimdal/lib/roken/hex.h b/third_party/heimdal/lib/roken/hex.h new file mode 100644 index 0000000..c266268 --- /dev/null +++ b/third_party/heimdal/lib/roken/hex.h @@ -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. + */ + +/* $Id$ */ + +#ifndef _rk_HEX_H_ +#define _rk_HEX_H_ 1 + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#define hex_encode rk_hex_encode +#define hex_decode rk_hex_decode + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL + hex_encode(const void *, size_t, char **); +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL + hex_decode(const char *, void *, size_t); + +#endif /* _rk_HEX_H_ */ diff --git a/third_party/heimdal/lib/roken/hostent_find_fqdn.c b/third_party/heimdal/lib/roken/hostent_find_fqdn.c new file mode 100644 index 0000000..dc3c17f --- /dev/null +++ b/third_party/heimdal/lib/roken/hostent_find_fqdn.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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Try to find a fqdn (with `.') in he if possible, else return h_name + */ + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/hstrerror.c b/third_party/heimdal/lib/roken/hstrerror.c new file mode 100644 index 0000000..70b6301 --- /dev/null +++ b/third_party/heimdal/lib/roken/hstrerror.c @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#include <config.h> + +#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 + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/ifaddrs.hin b/third_party/heimdal/lib/roken/ifaddrs.hin new file mode 100644 index 0000000..ef00b63 --- /dev/null +++ b/third_party/heimdal/lib/roken/ifaddrs.hin @@ -0,0 +1,79 @@ +/* + * 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$ */ + +#ifndef __ifaddrs_h__ +#define __ifaddrs_h__ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL _stdcall +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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/third_party/heimdal/lib/roken/inet_aton.c b/third_party/heimdal/lib/roken/inet_aton.c new file mode 100644 index 0000000..31644a0 --- /dev/null +++ b/third_party/heimdal/lib/roken/inet_aton.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* Minimal implementation of inet_aton. + * Cannot distinguish between failure and a local broadcast address. */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/inet_ntop.c b/third_party/heimdal/lib/roken/inet_ntop.c new file mode 100644 index 0000000..b3c327c --- /dev/null +++ b/third_party/heimdal/lib/roken/inet_ntop.c @@ -0,0 +1,151 @@ +/* + * 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. + */ + +#include <config.h> + +#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; + int compressed = 0; + + if (size < INET6_ADDRSTRLEN) { + errno = ENOSPC; + return NULL; + } + for (i = 0; i < 8; ++i) { + int non_zerop = 0; + + if (compressed == 0 && + ptr[0] == 0 && ptr[1] == 0 && + i <= 5 && + ptr[2] == 0 && ptr[3] == 0 && + ptr[4] == 0 && ptr[5] == 0) { + + compressed = 1; + + if (i == 0) + *dst++ = ':'; + *dst++ = ':'; + + for (ptr += 6, i += 3; + i < 8 && ptr[0] == 0 && ptr[1] == 0; + ++i, ptr += 2); + + if (i >= 8) + break; + } + + 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 */ + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/inet_pton.c b/third_party/heimdal/lib/roken/inet_pton.c new file mode 100644 index 0000000..e44fb19 --- /dev/null +++ b/third_party/heimdal/lib/roken/inet_pton.c @@ -0,0 +1,116 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifdef HAVE_WINSOCK + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +inet_pton(int af, const char *csrc, void *dst) +{ + char * src; + + if (csrc == NULL || (src = strdup(csrc)) == NULL) { + _set_errno( ENOMEM ); + return 0; + } + + switch (af) { + case AF_INET: + { + struct sockaddr_in si4; + INT r; + INT s = sizeof(si4); + + si4.sin_family = AF_INET; + r = WSAStringToAddress(src, AF_INET, NULL, (LPSOCKADDR) &si4, &s); + free(src); + src = NULL; + + if (r == 0) { + memcpy(dst, &si4.sin_addr, sizeof(si4.sin_addr)); + return 1; + } + } + break; + + case AF_INET6: + { + struct sockaddr_in6 si6; + INT r; + INT s = sizeof(si6); + + si6.sin6_family = AF_INET6; + r = WSAStringToAddress(src, AF_INET6, NULL, (LPSOCKADDR) &si6, &s); + free(src); + src = NULL; + + if (r == 0) { + memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr)); + return 1; + } + } + break; + + default: + _set_errno( EAFNOSUPPORT ); + return -1; + } + + /* the call failed */ + { + int le = WSAGetLastError(); + + if (le == WSAEINVAL) + return 0; + + _set_errno(le); + return -1; + } +} + +#else /* !HAVE_WINSOCK */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +inet_pton(int af, const char *src, void *dst) +{ + if (af != AF_INET) { + errno = EAFNOSUPPORT; + return -1; + } + return inet_aton (src, dst); +} + +#endif diff --git a/third_party/heimdal/lib/roken/initgroups.c b/third_party/heimdal/lib/roken/initgroups.c new file mode 100644 index 0000000..2ba944c --- /dev/null +++ b/third_party/heimdal/lib/roken/initgroups.c @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +initgroups(const char *name, gid_t basegid) +{ + return 0; +} diff --git a/third_party/heimdal/lib/roken/innetgr.c b/third_party/heimdal/lib/roken/innetgr.c new file mode 100644 index 0000000..e1783bb --- /dev/null +++ b/third_party/heimdal/lib/roken/innetgr.c @@ -0,0 +1,45 @@ +/* + * 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. */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_INNETGR + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +innetgr(const char *netgroup, const char *machine, + const char *user, const char *domain) +{ + return 0; +} +#endif + diff --git a/third_party/heimdal/lib/roken/install-sh b/third_party/heimdal/lib/roken/install-sh new file mode 100644 index 0000000..e9de238 --- /dev/null +++ b/third_party/heimdal/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/third_party/heimdal/lib/roken/issuid.c b/third_party/heimdal/lib/roken/issuid.c new file mode 100644 index 0000000..0c503a0 --- /dev/null +++ b/third_party/heimdal/lib/roken/issuid.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 1998 - 2017 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. + */ + +#include <config.h> + +#ifdef HAVE_SYS_AUXV_H +#include <sys/auxv.h> +#endif + +#include <errno.h> + +#include "roken.h" +#include "getauxval.h" + +extern int rk_injected_auxv; + +/** + * Returns non-zero if the caller's process started as set-uid or + * set-gid (and therefore the environment cannot be trusted). + * + * As much as possible this implements the same functionality and + * semantics as OpenBSD's issetugid() (as opposed to FreeBSD's). + * + * Preserves errno. + * + * @return Non-zero if the environment is not trusted. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +issuid(void) +{ +#ifdef WIN32 + return 0; /* No set-id programs or anything like it on Windows */ +#else + /* + * We want to use issetugid(), but issetugid() is not the same on + * all OSes. + * + * On OpenBSD (where issetugid() originated), Illumos derivatives, + * and Solaris, issetugid() returns true IFF the program exec()ed + * was set-uid or set-gid. + * + * FreeBSD departed from OpenBSD's issetugid() semantics, and other + * BSDs (NetBSD, DragonFly) and OS X adopted FreeBSD's. + * + * FreeBSDs' issetugid() returns true if the program exec()ed was + * set-uid or set-gid, or if the process has switched UIDs/GIDs or + * otherwise changed privileges or is a descendant of such a process + * and has not exec()ed since. + * + * The FreeBSD/NetBSD issetugid() does us no good because we _want_ + * to trust the environment when the process started life as + * non-set-uid root (or otherwise privileged). There's nothing + * about _dropping_ privileges (without having gained them first) + * that taints the environment. It's not like calling system(), + * say, might change the environment of the caller. + * + * We want OpenBSD's issetugid() semantics. + * + * Linux, meanwhile, has no issetugid() (at least glibc doesn't + * anyways) but has an equivalent: getauxval(AT_SECURE). + * + * To be really specific: we want getauxval(AT_SECURE) semantics + * because there may be ways in which a process might gain privilege + * at exec time other than by exec'ing a set-id program. + * + * Where we use getauxval(), we really use our getauxval(), the one + * that isn't broken the way glibc's used to be. Our getauxval() + * also works on more systems than actually provide one. + * + * In order to avoid FreeBSD issetugid() semantics, where available, + * we use the ELF auxilliary vector to implement OpenBSD semantics + * before finally falling back on issetugid(). + * + * All of this is as of April 2017, and might become stale in the + * future. + */ + static int we_are_suid = -1; /* Memoize; -1 == dunno */ + int save_errno = errno; +#if defined(AT_EUID) && defined(AT_UID) && defined(AT_EGID) && defined(AT_GID) + int seen = 0; +#endif + + if (we_are_suid >= 0 && !rk_injected_auxv) + return we_are_suid; + +#ifdef AT_SECURE + errno = 0; + if (rk_getauxval(AT_SECURE) != 0) { + errno = save_errno; + return we_are_suid = 1; + } else if (errno == 0) { + errno = save_errno; + return we_are_suid = 0; + } + /* errno == ENOENT; AT_SECURE not found; fall through */ +#endif + +#if defined(AT_EUID) && defined(AT_UID) && defined(AT_EGID) && defined(AT_GID) + { + unsigned long euid; + unsigned long uid; + + errno = 0; + euid = rk_getauxval(AT_EUID); + if (errno == 0) + seen |= 1; + errno = 0; + uid = rk_getauxval(AT_UID); + if (errno == 0) + seen |= 2; + if (euid != uid) { + errno = save_errno; + return we_are_suid = 1; + } + } + /* Check GIDs */ + { + unsigned long egid; + unsigned long gid; + + errno = 0; + egid = rk_getauxval(AT_EGID); + if (errno == 0) + seen |= 4; + errno = 0; + gid = rk_getauxval(AT_GID); + if (errno == 0) + seen |= 8; + if (egid != gid) { + errno = save_errno; + return we_are_suid = 1; + } + } + errno = save_errno; + if (seen == 15) + return we_are_suid = 0; +#endif + +#if defined(HAVE_ISSETUGID) + /* If issetugid() == 0 then we're definitely OK then */ + if (issetugid() == 0) + return we_are_suid = 0; + /* issetugid() == 1 might have been a false positive; fall through */ +#endif /* USE_RK_GETAUXVAL */ + +#ifdef AT_EXECFN + /* + * There's an auxval by which to find the path of the program this + * process exec'ed. + * + * We can stat() it. If the program did a chroot() and the chroot + * has a program with the same path but not set-uid/set-gid, of + * course, we lose here. But a) that's a bit of a stretch, b) + * there's not much more we can do here. + * + * Also, this is technically a TOCTOU race, though for set-id + * programs this is exceedingly unlikely to be an actual TOCTOU + * race. + */ + { + unsigned long p = rk_getauxval(AT_EXECPATH); + struct stat st; + + if (p != 0 && *(const char *)p == '/' && + stat((const char *)p, &st) == 0) { + if ((st.st_mode & S_ISUID) || (st.st_mode & S_ISGID)) { + errno = save_errno; + return we_are_suid = 1; + } + errno = save_errno; + return we_are_suid = 0; + } + } + /* Fall through */ +#endif + +#if defined(HAVE_ISSETUGID) + errno = save_errno; + return we_are_suid = 1; +#else + /* + * Paranoia: for extra safety we ought to default to returning 1. + * + * But who knows what that might break where users link statically + * (so no auxv), say. + * + * We'll check the actual real and effective IDs (as opposed to the + * ones at main() start time. + * + * For now we stick to returning zero by default. We've been rather + * heroic above trying to find out if we're suid, and we're running + * on a rather old or uncool OS if we've gotten here. + */ + +#if defined(HAVE_GETRESUID) + /* + * If r/e/suid are all the same then chances are very good we did + * not start as set-uid. Though this could be a login program that + * started out as privileged and is calling Heimdal "as the user". + * + * Again, such a program would have to be statically linked to get + * here. + */ + { + uid_t r, e, s; + if (getresuid(&r, &e, &s) == 0) { + if (r != e || r != s) { + errno = save_errno; + return we_are_suid = 1; + } + } + } +#endif +#if defined(HAVE_GETRESGID) + { + gid_t r, e, s; + if (getresgid(&r, &e, &s) == 0) { + if (r != e || r != s) { + errno = save_errno; + return we_are_suid = 1; + } + } + } +#endif +#if defined(HAVE_GETRESUID) && defined(HAVE_GETRESGID) + errno = save_errno; + return we_are_suid = 0; + +#else /* avoid compiler warnings about dead code */ + +#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) + if (getuid() != geteuid()) + return we_are_suid = 1; +#endif +#if defined(HAVE_GETGID) && defined(HAVE_GETEGID) + if (getgid() != getegid()) + return we_are_suid = 1; +#endif + +#endif /* !defined(HAVE_GETRESUID) || !defined(HAVE_GETRESGID) */ + + errno = save_errno; + return we_are_suid = 0; +#endif /* !defined(HAVE_ISSETUGID) */ +#endif /* WIN32 */ +} diff --git a/third_party/heimdal/lib/roken/localtime_r.c b/third_party/heimdal/lib/roken/localtime_r.c new file mode 100644 index 0000000..fa3d126 --- /dev/null +++ b/third_party/heimdal/lib/roken/localtime_r.c @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <time.h> +#include "roken.h" + +#ifndef HAVE_LOCALTIME_R + +ROKEN_LIB_FUNCTION struct tm * ROKEN_LIB_CALL +localtime_r(const time_t *timer, struct tm *result) +{ +#ifdef _MSC_VER + + return (localtime_s(result, timer) == 0)? result : NULL; + +#else + struct tm *tm; + + tm = localtime((time_t *)timer); + if (tm == NULL) + return NULL; + *result = *tm; + return result; +#endif +} + +#endif diff --git a/third_party/heimdal/lib/roken/lstat.c b/third_party/heimdal/lib/roken/lstat.c new file mode 100644 index 0000000..4692588 --- /dev/null +++ b/third_party/heimdal/lib/roken/lstat.c @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +lstat(const char *path, struct stat *buf) +{ + return stat(path, buf); +} diff --git a/third_party/heimdal/lib/roken/memmem.c b/third_party/heimdal/lib/roken/memmem.c new file mode 100644 index 0000000..3f9c6bc --- /dev/null +++ b/third_party/heimdal/lib/roken/memmem.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. + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> + +#ifndef HAVE_MEMMEM +#include "roken.h" +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +memmem(const void *haystack, + size_t haystacklen, + const void *needle, + size_t needlelen) +{ + const unsigned char *hs = haystack; + const unsigned char *n = needle; + size_t hsi, ni; + + if (haystacklen < needlelen || haystacklen == 0) + return NULL; + /* + * Imagine a haystack of length 5 and needle of length 2, then the largest + * index in the haystack at which we can bother looking for the needle is: + * + * 0 1 2 3 4 + * +---------+ + * |?|?|?|?|?| + * +---------+ + * ^ + * \ + * here, at index 3, which is 5 - 2, and less than (5 - 2 + 1). + */ + for (hsi = 0, ni = 0; hsi < (haystacklen - needlelen + 1); hsi++, ni = 0) { + while (ni < needlelen && n[ni] == hs[hsi + ni]) + ni++; + if (ni == needlelen) + return rk_UNCONST(&hs[hsi]); + } + return NULL; +} +#endif diff --git a/third_party/heimdal/lib/roken/memmove.c b/third_party/heimdal/lib/roken/memmove.c new file mode 100644 index 0000000..1825d7e --- /dev/null +++ b/third_party/heimdal/lib/roken/memmove.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. + */ + +#include <config.h> + +/* + * memmove for systems that doesn't have it + */ + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +ROKEN_LIB_FUNCTION void* ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/memset_s.c b/third_party/heimdal/lib/roken/memset_s.c new file mode 100644 index 0000000..207fe19 --- /dev/null +++ b/third_party/heimdal/lib/roken/memset_s.c @@ -0,0 +1,51 @@ +/*********************************************************************** + * Copyright (c) 2015, Your File System Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 "roken.h" + +int ROKEN_LIB_FUNCTION +memset_s(void *s, size_t smax, int c, size_t n) +{ + volatile unsigned char *p = s; + +#ifdef _WIN32 + if (c == 0) { + SecureZeroMemory(s, n); + return 0; + } +#endif + + while (n--) + *p++ = c; + + return 0; +} diff --git a/third_party/heimdal/lib/roken/mergesort.c b/third_party/heimdal/lib/roken/mergesort.c new file mode 100644 index 0000000..ba51889 --- /dev/null +++ b/third_party/heimdal/lib/roken/mergesort.c @@ -0,0 +1,50 @@ +/*********************************************************************** + * Copyright (c) 2020, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 "roken.h" + +static int +mergesort_compar_thunk(const void *a, const void *b, void *thunk) +{ + int (*compar)(const void *, const void *) = thunk; + + return compar(a, b); +} + +int ROKEN_LIB_FUNCTION +mergesort(void *base, size_t nel, size_t width, + int (*compar)(const void *, const void *)) +{ + return rk_mergesort_r(base, nel, width, + mergesort_compar_thunk, compar); +} + diff --git a/third_party/heimdal/lib/roken/mergesort_r.c b/third_party/heimdal/lib/roken/mergesort_r.c new file mode 100644 index 0000000..39b0301 --- /dev/null +++ b/third_party/heimdal/lib/roken/mergesort_r.c @@ -0,0 +1,339 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Peter McIlroy. + * + * 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. + */ + +#include <config.h> +#include "roken.h" + +/* + * Hybrid exponential search/linear search merge sort with hybrid + * natural/pairwise first pass. Requires about .3% more comparisons + * for random data than LSMS with pairwise first pass alone. + * It works for objects as small as two bytes. + */ + +#define NATURAL +#define THRESHOLD 16 /* Best choice for natural merge cut-off. */ + +/* #define NATURAL to get hybrid natural merge. + * (The default is pairwise merging.) + */ + +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +typedef int (*cmp_t)(const void *, const void *, void *); + +static void setup(u_char *, u_char *, size_t, size_t, cmp_t, void *); +static void insertionsort(u_char *, size_t, size_t, cmp_t, void *); + +#define ISIZE sizeof(int) +#define PSIZE sizeof(u_char *) +#define ICOPY_LIST(src, dst, last) \ + do \ + *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \ + while(src < last) +#define ICOPY_ELT(src, dst, i) \ + do \ + *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \ + while (i -= ISIZE) + +#define CCOPY_LIST(src, dst, last) \ + do \ + *dst++ = *src++; \ + while (src < last) +#define CCOPY_ELT(src, dst, i) \ + do \ + *dst++ = *src++; \ + while (i -= 1) + +/* + * Find the next possible pointer head. (Trickery for forcing an array + * to do double duty as a linked list when objects do not align with word + * boundaries. + */ +/* Assumption: PSIZE is a power of 2. */ +#define EVAL(p) (u_char **) \ + ((((uintptr_t)p + PSIZE - 1) & ~(PSIZE - 1))) + +/* + * Arguments are as for qsort_r, except thunk is moved to the last + * parameter for glibc compatibility. See: + * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214248 + */ +int +mergesort_r(void *base, size_t nmemb, size_t size, cmp_t cmp, void *thunk) +{ + size_t i; + int sense; + int big, iflag; + u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2; + u_char *list2, *list1, *p2, *p, *last, **p1; + + if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */ + errno = EINVAL; + return (-1); + } + + if (nmemb == 0) + return (0); + + /* + * XXX + * Stupid subtraction for the Cray. + */ + iflag = 0; + if (!(size % ISIZE) && !(((uintptr_t)base) % ISIZE)) + iflag = 1; + + if ((list2 = malloc(nmemb * size + PSIZE)) == NULL) + return (-1); + + list1 = base; + setup(list1, list2, nmemb, size, cmp, thunk); + last = list2 + nmemb * size; + i = big = 0; + while (*EVAL(list2) != last) { + l2 = list1; + p1 = EVAL(list1); + for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) { + p2 = *EVAL(p2); + f1 = l2; + f2 = l1 = list1 + (p2 - list2); + if (p2 != last) + p2 = *EVAL(p2); + l2 = list1 + (p2 - list2); + while (f1 < l1 && f2 < l2) { + if (cmp(f1, f2, thunk) <= 0) { + q = f2; + b = f1, t = l1; + sense = -1; + } else { + q = f1; + b = f2, t = l2; + sense = 0; + } + if (!big) { /* here i = 0 */ + while ((b += size) < t && cmp(q, b, thunk) >sense) + if (++i == 6) { + big = 1; + goto EXPONENTIAL; + } + } else { +EXPONENTIAL: for (i = size; ; i <<= 1) + if ((p = (b + i)) >= t) { + if ((p = t - size) > b && + cmp(q, p, thunk) <= sense) + t = p; + else + b = p; + break; + } else if (cmp(q, p, thunk) <= sense) { + t = p; + if (i == size) + big = 0; + goto FASTCASE; + } else + b = p; + while (t > b+size) { + i = (((t - b) / size) >> 1) * size; + if (cmp(q, p = b + i, thunk) <= sense) + t = p; + else + b = p; + } + goto COPY; +FASTCASE: while (i > size) + if (cmp(q, + p = b + (i >>= 1), thunk) <= sense) + t = p; + else + b = p; +COPY: b = t; + } + i = size; + if (q == f1) { + if (iflag) { + ICOPY_LIST(f2, tp2, b); + ICOPY_ELT(f1, tp2, i); + } else { + CCOPY_LIST(f2, tp2, b); + CCOPY_ELT(f1, tp2, i); + } + } else { + if (iflag) { + ICOPY_LIST(f1, tp2, b); + ICOPY_ELT(f2, tp2, i); + } else { + CCOPY_LIST(f1, tp2, b); + CCOPY_ELT(f2, tp2, i); + } + } + } + if (f2 < l2) { + if (iflag) + ICOPY_LIST(f2, tp2, l2); + else + CCOPY_LIST(f2, tp2, l2); + } else if (f1 < l1) { + if (iflag) + ICOPY_LIST(f1, tp2, l1); + else + CCOPY_LIST(f1, tp2, l1); + } + *p1 = l2; + } + tp2 = list1; /* swap list1, list2 */ + list1 = list2; + list2 = tp2; + last = list2 + nmemb*size; + } + if (base == list2) { + memmove(list2, list1, nmemb*size); + list2 = list1; + } + free(list2); + return (0); +} + +#define swap(a, b) { \ + s = b; \ + i = size; \ + do { \ + tmp = *a; *a++ = *s; *s++ = tmp; \ + } while (--i); \ + a -= size; \ + } +#define reverse(bot, top) { \ + s = top; \ + do { \ + i = size; \ + do { \ + tmp = *bot; *bot++ = *s; *s++ = tmp; \ + } while (--i); \ + s -= size2; \ + } while(bot < s); \ +} + +/* + * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of + * increasing order, list2 in a corresponding linked list. Checks for runs + * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL + * is defined. Otherwise simple pairwise merging is used.) + */ +void +setup(u_char *list1, u_char *list2, size_t n, size_t size, cmp_t cmp, void *thunk) +{ + int i, length, size2, tmp, sense; + u_char *f1, *f2, *s, *l2, *last, *p2; + + size2 = size*2; + if (n <= 5) { + insertionsort(list1, n, size, cmp, thunk); + *EVAL(list2) = (u_char*) list2 + n*size; + return; + } + /* + * Avoid running pointers out of bounds; limit n to evens + * for simplicity. + */ + i = 4 + (n & 1); + insertionsort(list1 + (n - i) * size, i, size, cmp, thunk); + last = list1 + size * (n - i); + *EVAL(list2 + (last - list1)) = list2 + n * size; + +#ifdef NATURAL + p2 = list2; + f1 = list1; + sense = (cmp(f1, f1 + size, thunk) > 0); + for (; f1 < last; sense = !sense) { + length = 2; + /* Find pairs with same sense. */ + for (f2 = f1 + size2; f2 < last; f2 += size2) { + if ((cmp(f2, f2+ size, thunk) > 0) != sense) + break; + length += 2; + } + if (length < THRESHOLD) { /* Pairwise merge */ + do { + p2 = *EVAL(p2) = f1 + size2 - list1 + list2; + if (sense > 0) + swap (f1, f1 + size); + } while ((f1 += size2) < f2); + } else { /* Natural merge */ + l2 = f2; + for (f2 = f1 + size2; f2 < l2; f2 += size2) { + if ((cmp(f2-size, f2, thunk) > 0) != sense) { + p2 = *EVAL(p2) = f2 - list1 + list2; + if (sense > 0) + reverse(f1, f2-size); + f1 = f2; + } + } + if (sense > 0) + reverse (f1, f2-size); + f1 = f2; + if (f2 < last || cmp(f2 - size, f2, thunk) > 0) + p2 = *EVAL(p2) = f2 - list1 + list2; + else + p2 = *EVAL(p2) = list2 + n*size; + } + } +#else /* pairwise merge only. */ + for (f1 = list1, p2 = list2; f1 < last; f1 += size2) { + p2 = *EVAL(p2) = p2 + size2; + if (cmp (f1, f1 + size) > 0) + swap(f1, f1 + size); + } +#endif /* NATURAL */ +} + +/* + * This is to avoid out-of-bounds addresses in sorting the + * last 4 elements. + */ +static void +insertionsort(u_char *a, size_t n, size_t size, cmp_t cmp, void *thunk) +{ + u_char *ai, *s, *t, *u, tmp; + int i; + + for (ai = a+size; --n >= 1; ai += size) + for (t = ai; t > a; t -= size) { + u = t - size; + if (cmp(u, t, thunk) <= 0) + break; + swap(u, t); + } +} diff --git a/third_party/heimdal/lib/roken/mini_inetd.c b/third_party/heimdal/lib/roken/mini_inetd.c new file mode 100644 index 0000000..a9398f4 --- /dev/null +++ b/third_party/heimdal/lib/roken/mini_inetd.c @@ -0,0 +1,197 @@ +/* + * 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. + */ + +#include <config.h> + +#include <err.h> +#include "roken.h" + +/* + * accept a connection on `s' and pretend it's served by inetd. + */ + +static void +accept_it (rk_socket_t s, rk_socket_t *ret_socket) +{ + rk_socket_t as; + + as = accept(s, NULL, NULL); + if(rk_IS_BAD_SOCKET(as)) + err (1, "accept"); + + if (ret_socket) { + + *ret_socket = as; + + } else { + int fd = socket_to_fd(as, 0); + + /* We would use _O_RDONLY for the socket_to_fd() call for + STDIN, but there are instances where we assume that STDIN + is a r/w socket. */ + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + + rk_closesocket(as); + } +} + +/** + * Listen on a specified addresses + * + * Listens on the specified addresses for incoming connections. If + * the \a ret_socket parameter is \a NULL, on return STDIN and STDOUT + * will be connected to an accepted socket. If the \a ret_socket + * parameter is non-NULL, the accepted socket will be returned in + * *ret_socket. In the latter case, STDIN and STDOUT will be left + * unmodified. + * + * This function does not return if there is an error or if no + * connection is established. + * + * @param[in] ai Addresses to listen on + * @param[out] ret_socket If non-NULL receives the accepted socket. + * + * @see mini_inetd() + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +mini_inetd_addrinfo (struct addrinfo *ai, rk_socket_t *ret_socket) +{ + int ret; + struct addrinfo *a; + int n, nalloc, i; + rk_socket_t *fds; + fd_set orig_read_set, read_set; + rk_socket_t max_fd = (rk_socket_t)-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"); + UNREACHABLE(return); + } + + 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 (rk_IS_BAD_SOCKET(fds[i])) + continue; + socket_set_reuseaddr (fds[i], 1); + socket_set_ipv6only(fds[i], 1); + if (rk_IS_SOCKET_ERROR(bind (fds[i], a->ai_addr, a->ai_addrlen))) { + warn ("bind af = %d", a->ai_family); + rk_closesocket(fds[i]); + fds[i] = rk_INVALID_SOCKET; + continue; + } + if (rk_IS_SOCKET_ERROR(listen (fds[i], SOMAXCONN))) { + warn ("listen af = %d", a->ai_family); + rk_closesocket(fds[i]); + fds[i] = rk_INVALID_SOCKET; + continue; + } +#ifndef NO_LIMIT_FD_SETSIZE + if (fds[i] >= FD_SETSIZE) + errx (1, "fd too large"); +#endif + 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 (rk_IS_SOCKET_ERROR(ret) && rk_SOCK_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], ret_socket); + for (i = 0; i < n; ++i) + rk_closesocket(fds[i]); + free(fds); + return; + } + abort (); +} + +/** + * Listen on a specified port + * + * Listens on the specified port for incoming connections. If the \a + * ret_socket parameter is \a NULL, on return STDIN and STDOUT will be + * connected to an accepted socket. If the \a ret_socket parameter is + * non-NULL, the accepted socket will be returned in *ret_socket. In + * the latter case, STDIN and STDOUT will be left unmodified. + * + * This function does not return if there is an error or if no + * connection is established. + * + * @param[in] port Port to listen on + * @param[out] ret_socket If non-NULL receives the accepted socket. + * + * @see mini_inetd_addrinfo() + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +mini_inetd(int port, rk_socket_t * ret_socket) +{ + 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, ret_socket); + + freeaddrinfo(ai); +} + diff --git a/third_party/heimdal/lib/roken/missing b/third_party/heimdal/lib/roken/missing new file mode 100644 index 0000000..7789652 --- /dev/null +++ b/third_party/heimdal/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/third_party/heimdal/lib/roken/mkdir.c b/third_party/heimdal/lib/roken/mkdir.c new file mode 100644 index 0000000..5ed4c0d --- /dev/null +++ b/third_party/heimdal/lib/roken/mkdir.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 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. + */ + +#include <config.h> + +#ifdef WIN32 +#include <direct.h> +#endif + +#include "roken.h" +#ifndef WIN32 + #undef rk_mkdir +#endif + +int ROKEN_LIB_FUNCTION +rk_mkdir(const char *pathname, mode_t mode) +{ +#ifdef WIN32 + return _mkdir(pathname); +#else + return mkdir(pathname, mode); +#endif +} diff --git a/third_party/heimdal/lib/roken/mkdtemp.c b/third_party/heimdal/lib/roken/mkdtemp.c new file mode 100644 index 0000000..b106add --- /dev/null +++ b/third_party/heimdal/lib/roken/mkdtemp.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020 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. + */ + +#include <config.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> + +#include <roken.h> + +#ifndef O_APPEND +#define O_APPEND 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifndef O_SYNC +#define O_SYNC 0 +#endif + +#ifndef HAVE_MKDTEMP +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +mkdtemp(char *template) +{ + size_t len = strlen(template) - 1; + size_t start, i; + pid_t val = getpid(); + + for (i = 0; i < len && i < 7 && template[len - i] == 'X'; i++) { + template[len] = '0' + val % 10; + val /= 10; + len--; + if (!val) + val = getpid(); + } + + if (i < 6) { + errno = EINVAL; + return NULL; + } + + start = len - i; + do { + if (mkdir(template, 0700) == 0) + return template; + for (i = start + 1; i < len; i++) { + if (++(template[i]) == '9' + 1) + template[i] = 'a'; + if (template[i] <= 'z') + break; + template[i] = 'a'; + } + } while(1); +} +#endif diff --git a/third_party/heimdal/lib/roken/mkinstalldirs b/third_party/heimdal/lib/roken/mkinstalldirs new file mode 100644 index 0000000..6b3b5fc --- /dev/null +++ b/third_party/heimdal/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/third_party/heimdal/lib/roken/mkostemp.c b/third_party/heimdal/lib/roken/mkostemp.c new file mode 100644 index 0000000..8d739d8 --- /dev/null +++ b/third_party/heimdal/lib/roken/mkostemp.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 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. + */ + +#include <config.h> + +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <errno.h> + +#include <roken.h> + +#ifndef O_APPEND +#define O_APPEND 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifndef O_SYNC +#define O_SYNC 0 +#endif + +#ifndef HAVE_MKOSTEMP +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +mkostemp(char *template, int flags) +{ + int fd = mkstemp(template); + + if (flags == 0) + return fd; + + if ((flags & O_CLOEXEC)) + rk_cloexec(fd); + + /* fcntl F_SETFL O_APPEND and O_SYNC. */ +#ifdef HAVE_FCNTL + if ((flags & (O_APPEND | O_SYNC))) { + int fl; + + if ((fl = fcntl(fd, F_GETFL)) == -1 || + fcntl(fd, F_SETFD, fl | (flags & (O_APPEND | O_SYNC))) == -1) { + int save_errno = errno; + + (void) unlink(template); + (void) close(fd); + errno = save_errno; + return -1; + } + } +#endif + return fd; +} +#endif diff --git a/third_party/heimdal/lib/roken/mkstemp.c b/third_party/heimdal/lib/roken/mkstemp.c new file mode 100644 index 0000000..a3ca6c7 --- /dev/null +++ b/third_party/heimdal/lib/roken/mkstemp.c @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#include <config.h> + +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <errno.h> + +#include <roken.h> + +#ifndef HAVE_MKSTEMP + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/ndbm_wrap.c b/third_party/heimdal/lib/roken/ndbm_wrap.c new file mode 100644 index 0000000..f8403da --- /dev/null +++ b/third_party/heimdal/lib/roken/ndbm_wrap.c @@ -0,0 +1,227 @@ +/* + * 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. + */ + +#include <config.h> + +#include "ndbm_wrap.h" +#if defined(HAVE_DBHEADER) +#include <db.h> +#elif defined(HAVE_DB6_DB_H) +#include <db6/db.h> +#elif defined(HAVE_DB5_DB_H) +#include <db5/db.h> +#elif 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)) + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +dbm_close (DBM *db) +{ +#ifdef HAVE_DB3 + D(db)->close(D(db), 0); + cursor = NULL; +#else + D(db)->close(D(db)); +#endif +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 d; +#ifdef HAVE_DB3 + if(cursor == NULL) + db->cursor(db, NULL, &cursor, 0); + if(cursor->c_get(cursor, &key, &value, flags) != 0) { + d.dptr = NULL; + d.dsize = 0; + } else + DBT2DATUM(&value, &d); +#else + db->seq(db, &key, &value, flags); + DBT2DATUM(&value, &d); +#endif + return d; +} + +#ifndef DB_FIRST +#define DB_FIRST R_FIRST +#define DB_NEXT R_NEXT +#define DB_NOOVERWRITE R_NOOVERWRITE +#define DB_KEYEXIST 1 +#endif + +ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL +dbm_firstkey (DBM *db) +{ + return dbm_get(D(db), DB_FIRST); +} + +ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL +dbm_nextkey (DBM *db) +{ + return dbm_get(D(db), DB_NEXT); +} + +ROKEN_LIB_FUNCTION DBM* ROKEN_LIB_CALL +dbm_open (const char *file, int flags, mode_t mode) +{ +#ifdef HAVE_DB3 + int myflags = 0; +#endif + DB *db; + 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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +dbm_error (DBM *db) +{ + return 0; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +dbm_clearerr (DBM *db) +{ + return 0; +} + diff --git a/third_party/heimdal/lib/roken/ndbm_wrap.h b/third_party/heimdal/lib/roken/ndbm_wrap.h new file mode 100644 index 0000000..a2ec4f2 --- /dev/null +++ b/third_party/heimdal/lib/roken/ndbm_wrap.h @@ -0,0 +1,93 @@ +/* + * 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$ */ + +#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 +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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 + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL dbm_clearerr (DBM*); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL dbm_close (DBM*); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL dbm_delete (DBM*, datum); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL dbm_error (DBM*); +ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL dbm_fetch (DBM*, datum); +ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL dbm_firstkey (DBM*); +ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL dbm_nextkey (DBM*); +ROKEN_LIB_FUNCTION DBM* ROKEN_LIB_CALL dbm_open (const char*, int, mode_t); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL dbm_store (DBM*, datum, datum, int); + +#endif /* __ndbm_wrap_h__ */ diff --git a/third_party/heimdal/lib/roken/net_read.c b/third_party/heimdal/lib/roken/net_read.c new file mode 100644 index 0000000..df1ac53 --- /dev/null +++ b/third_party/heimdal/lib/roken/net_read.c @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Like read but never return partial data. + */ + +#ifndef _WIN32 + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +net_read (rk_socket_t fd, void *buf, size_t nbytes) +{ + char *cbuf = (char *)buf; + ssize_t count; + size_t rem = nbytes; + + while (rem > 0) { + count = read (fd, cbuf, rem); + if (count < 0) { + if (errno == EINTR) + continue; + else + return count; + } else if (count == 0) { + return count; + } + cbuf += count; + rem -= count; + } + return nbytes; +} + +#else + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +net_read(rk_socket_t sock, void *buf, size_t nbytes) +{ + char *cbuf = (char *)buf; + ssize_t count; + size_t rem = nbytes; + +#ifdef SOCKET_IS_NOT_AN_FD + int use_read = 0; +#endif + + while (rem > 0) { +#ifdef SOCKET_IS_NOT_AN_FD + if (use_read) + count = _read (sock, cbuf, rem); + else + count = recv (sock, cbuf, rem, 0); + + if (use_read == 0 && + rk_IS_SOCKET_ERROR(count) && + (rk_SOCK_ERRNO == WSANOTINITIALISED || + rk_SOCK_ERRNO == WSAENOTSOCK)) { + use_read = 1; + + count = _read (sock, cbuf, rem); + } +#else + count = recv (sock, cbuf, rem, 0); +#endif + if (count < 0) { + + /* With WinSock, the error EINTR (WSAEINTR), is used to + indicate that a blocking call was cancelled using + WSACancelBlockingCall(). */ + +#ifndef HAVE_WINSOCK + if (rk_SOCK_ERRNO == EINTR) + continue; +#endif + return count; + } else if (count == 0) { + return count; + } + cbuf += count; + rem -= count; + } + return nbytes; +} + +#endif diff --git a/third_party/heimdal/lib/roken/net_write.c b/third_party/heimdal/lib/roken/net_write.c new file mode 100644 index 0000000..e66f56b --- /dev/null +++ b/third_party/heimdal/lib/roken/net_write.c @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +/* + * Like write but blocking sockets never return partial data, i.e. we retry on + * EINTR. With non-blocking sockets (EWOULDBLOCK or EAGAIN) we return the + * number of bytes written. + */ + +#ifndef _WIN32 + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +net_write (rk_socket_t fd, const void *buf, size_t nbytes) +{ + const char *cbuf = (const char *)buf; + ssize_t count; + size_t rem = nbytes; + + while (rem > 0) { + count = write (fd, cbuf, rem); + if (count < 0) { + switch (errno) { + case EINTR: + continue; +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + case EAGAIN: +#endif + case EWOULDBLOCK: + return nbytes - rem; + default: + return count; + } + } + cbuf += count; + rem -= count; + } + return nbytes; +} + +#else /* defined(_WIN32) */ + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +net_write(rk_socket_t sock, const void *buf, size_t nbytes) +{ + const char *cbuf = (const char *)buf; + ssize_t count; + size_t rem = nbytes; +#ifdef SOCKET_IS_NOT_AN_FD + int use_write = 0; +#endif + + while (rem > 0) { +#ifdef SOCKET_IS_NOT_AN_FD + if (use_write) + count = _write (sock, cbuf, rem); + else + count = send (sock, cbuf, rem, 0); + + if (use_write == 0 && + rk_IS_SOCKET_ERROR(count) && + (rk_SOCK_ERRNO == WSANOTINITIALISED || + rk_SOCK_ERRNO == WSAENOTSOCK)) { + use_write = 1; + + count = _write (sock, cbuf, rem); + } +#else + count = send (sock, cbuf, rem, 0); +#endif + if (count < 0) { +#ifdef SOCKET_IS_NOT_AN_FD + if (!use_write) { + switch (rk_SOCK_ERRNO) { + case WSAEINTR: + continue; + case WSAEWOULDBLOCK: + return nbytes - rem; + default: + return count; + } + } else +#endif + { + switch (errno) { + case EINTR: + continue; + case EWOULDBLOCK: + return nbytes - rem; + default: + return count; + } + } + } + cbuf += count; + rem -= count; + } + return nbytes; +} + +#endif diff --git a/third_party/heimdal/lib/roken/parse_bytes-test.c b/third_party/heimdal/lib/roken/parse_bytes-test.c new file mode 100644 index 0000000..f7697e6 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_bytes-test.c @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include "parse_bytes.h" + +static struct testcase { + int canonicalp; + ssize_t 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"}, + {1, 1024UL * 1024 * 1024 * 1024, NULL, "1 terabyte"}, +}; + +int +main(int argc, char **argv) +{ + int i; + int ret = 0; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) { + char buf[256]; + ssize_t val = parse_bytes (tests[i].str, tests[i].def_unit); + + if (val != tests[i].val) { + printf ("parse_bytes (%s, %s) = %lld != %lld\n", + tests[i].str, + tests[i].def_unit ? tests[i].def_unit : "none", + (long long)val, (long long)tests[i].val); + ++ret; + } + if (tests[i].canonicalp) { + (void) unparse_bytes (tests[i].val, buf, sizeof(buf)); + if (strcmp (tests[i].str, buf) != 0) { + printf ("unparse_bytes (%lld) = \"%s\" != \"%s\"\n", + (long long)tests[i].val, buf, tests[i].str); + ++ret; + } + } + } + if (ret) { + printf ("%d errors\n", ret); + return 1; + } else + return 0; +} diff --git a/third_party/heimdal/lib/roken/parse_bytes.c b/third_party/heimdal/lib/roken/parse_bytes.c new file mode 100644 index 0000000..006a352 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_bytes.c @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#include <config.h> + +#include <parse_units.h> +#include "parse_bytes.h" + +static struct units bytes_units[] = { + { "petabyte", 1024UL * 1024 * 1024 * 1024 * 1024 }, + { "PB", 1024UL * 1024 * 1024 * 1024 * 1024 }, + { "terabyte", 1024UL * 1024 * 1024 * 1024 }, + { "TB", 1024UL * 1024 * 1024 * 1024 }, + { "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[] = { + { "PB", 1024UL * 1024 * 1024 * 1024 * 1024 }, + { "TB", 1024UL * 1024 * 1024 * 1024 }, + { "GB", 1024 * 1024 * 1024 }, + { "MB", 1024 * 1024 }, + { "KB", 1024 }, + { NULL, 0 } +}; + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +parse_bytes(const char *s, const char *def_unit) +{ + return parse_units (s, bytes_units, def_unit); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_bytes(ssize_t t, char *s, size_t len) +{ + return unparse_units (t, bytes_units, s, len); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_bytes_short (ssize_t t, char *s, size_t len) +{ + return unparse_units_approx (t, bytes_short_units, s, len); +} diff --git a/third_party/heimdal/lib/roken/parse_bytes.h b/third_party/heimdal/lib/roken/parse_bytes.h new file mode 100644 index 0000000..b7eea2b --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_bytes.h @@ -0,0 +1,50 @@ +/* + * 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$ */ + +#ifndef __PARSE_BYTES_H__ +#define __PARSE_BYTES_H__ + +#include <roken.h> + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +parse_bytes(const char *s, const char *def_unit); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_bytes(ssize_t t, char *s, size_t len); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_bytes_short(ssize_t t, char *s, size_t len); + +#endif /* __PARSE_BYTES_H__ */ diff --git a/third_party/heimdal/lib/roken/parse_reply-test.c b/third_party/heimdal/lib/roken/parse_reply-test.c new file mode 100644 index 0000000..5e40b81 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_reply-test.c @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#include <config.h> + +#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/third_party/heimdal/lib/roken/parse_time-test.c b/third_party/heimdal/lib/roken/parse_time-test.c new file mode 100644 index 0000000..a2dfb22 --- /dev/null +++ b/third_party/heimdal/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. + */ + +#include <config.h> + +#include "roken.h" +#include "parse_time.h" +#include "test-mem.h" +#include "err.h" + +static struct testcase { + size_t size; + int 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" }, + { 9, 300, "5 minutes" }, +}; + +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, min(buf_sz, tests[i].size)); + 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, min(buf_sz, tests[i].size) - 1) != 0) + errx(1, "test %i wrong result %s vs %s", i, buf, tests[i].str); + if (buf_sz > 0 && buf[min(buf_sz, tests[i].size) - 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/third_party/heimdal/lib/roken/parse_time.3 b/third_party/heimdal/lib/roken/parse_time.3 new file mode 100644 index 0000000..7881eab --- /dev/null +++ b/third_party/heimdal/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,v 1.3 2013/06/17 18:57:45 robert Exp $ +.\" +.Dd November 17, 2013 +.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 the period of time specified +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. Numbers without explicit units are taken as being +.Fa def_unit . +.Pp +The +.Fn unparse_time +and +.Fn unparse_time_approx +do the opposite of +.Fn parse_time , +that is they take a number of seconds and express that as human +readable strings. +.Fa unparse_time +produces an exact time, while +.Fa unparse_time_approx +restricts the result to include only one unit. +.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/third_party/heimdal/lib/roken/parse_time.c b/third_party/heimdal/lib/roken/parse_time.c new file mode 100644 index 0000000..f5a99e3 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_time.c @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#include <config.h> + +#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}, +}; + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_time (const char *s, const char *def_unit) +{ + return parse_units (s, time_units, def_unit); +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time(int64_t t, char *s, size_t len) +{ + return unparse_units (t, time_units, s, len); +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time_approx(int64_t t, char *s, size_t len) +{ + return unparse_units_approx (t, time_units, s, len); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_time_table (FILE *f) +{ + print_units_table (time_units, f); +} + +#undef parse_time +#undef unparse_time +#undef unparse_time_approx +#undef print_time_table + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_time(const char *s, const char *def_unit) +{ + return rk_parse_units(s, time_units, def_unit); +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time(int64_t t, char *s, size_t len) +{ + return rk_unparse_units(t, time_units, s, len); +} + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time_approx(int64_t t, char *s, size_t len) +{ + return rk_unparse_units_approx(t, time_units, s, len); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_time_table(FILE *f) +{ + rk_print_units_table(time_units, f); +} diff --git a/third_party/heimdal/lib/roken/parse_time.h b/third_party/heimdal/lib/roken/parse_time.h new file mode 100644 index 0000000..c0f08f9 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_time.h @@ -0,0 +1,72 @@ +/* + * 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$ */ + +#ifndef __PARSE_TIME_H__ +#define __PARSE_TIME_H__ + +#include <roken.h> + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_time (const char *s, const char *def_unit); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time(int64_t t, char *s, size_t len); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time_approx(int64_t t, char *s, size_t len); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_time_table (FILE *f); + +/* And again, but renamed */ + +#define parse_time rk_parse_time +#define unparse_time rk_unparse_time +#define unparse_time_approx rk_unparse_time_approx +#define print_time_table rk_print_time_table + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_time (const char *s, const char *def_unit); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time(int64_t t, char *s, size_t len); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +unparse_time_approx(int64_t t, char *s, size_t len); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_time_table (FILE *f); + +#endif /* __PARSE_TIME_H__ */ diff --git a/third_party/heimdal/lib/roken/parse_units.c b/third_party/heimdal/lib/roken/parse_units.c new file mode 100644 index 0000000..d76578a --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_units.c @@ -0,0 +1,525 @@ +/* + * 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. + */ + +#include <config.h> + +#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 int64_t +parse_something_signed(const char *s, const struct units *units, + const char *def_unit, + int64_t (*func)(int64_t res, int64_t val, uint64_t mult), + int64_t init, + int accept_no_val_p) +{ + const char *p; + int64_t 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) { + int64_t 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 = strtoll(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; + while (isspace((unsigned char)*p)) + ++p; + } + return res; +} + +static uint64_t +parse_something_unsigned(const char *s, const struct units *units, + const char *def_unit, + uint64_t (*func)(uint64_t res, int64_t val, uint64_t mult), + uint64_t init, + int accept_no_val_p) +{ + const char *p; + int64_t 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) { + int64_t 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 = strtoll(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; + while (isspace((unsigned char)*p)) + ++p; + } + return res; +} + +/* + * The string consists of a sequence of `n unit' + */ + +static int64_t +acc_units(int64_t res, int64_t val, uint64_t mult) +{ + return res + val * mult; +} + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_units (const char *s, const struct units *units, + const char *def_unit) +{ + return parse_something_signed(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 uint64_t +acc_flags(uint64_t res, int64_t val, uint64_t mult) +{ + if(val == 1) + return res | mult; + else if(val == -1) + return res & ~mult; + else if (val == 0) + return mult; + else + return -1; +} + +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL +parse_flags (const char *s, const struct units *units, + int orig) +{ + return parse_something_unsigned (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_signed(int64_t num, const struct units *units, char *s, + size_t len, + int64_t (*get_divisor)(int64_t, uint64_t), + int (*print)(char *, size_t, int64_t, const char *, int64_t), + int64_t (*update)(int64_t, uint64_t), + const char *zero_string) +{ + const struct units *u; + int ret = 0, tmp; + + if (num == 0) + return snprintf (s, len, "%s", zero_string); + if (len) + s[0] = '\0'; + if (num < 0) + return -1; + + for (u = units; num > 0 && u->name; ++u) { + long long divisor = get_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 ((size_t)tmp > len) { + len = 0; + s = NULL; + } else { + len -= tmp; + s += tmp; + } + ret += tmp; + } + } + return ret; +} + +static int +unparse_something_unsigned(uint64_t num, const struct units *units, char *s, + size_t len, + uint64_t (*get_divisor)(uint64_t, uint64_t), + int (*print)(char *, size_t, uint64_t, const char *, uint64_t), + uint64_t (*update)(uint64_t, uint64_t), + const char *zero_string) +{ + const struct units *u; + int64_t tmp; + int ret = 0; + + if (num == 0) + return snprintf (s, len, "%s", zero_string); + if (len) + s[0] = '\0'; + + for (u = units; num > 0 && u->name; ++u) { + long long divisor = get_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 ((size_t)tmp > len) { + len = 0; + s = NULL; + } else { + len -= tmp; + s += tmp; + } + ret += tmp; + } + } + return ret; +} + +static int +print_unit(char *s, size_t len, int64_t divisor, const char *name, int64_t rem) +{ + return snprintf(s, len, "%lld %s%s%s", (long long)divisor, name, + divisor == 1 ? "" : "s", rem > 0 ? " " : ""); +} + +static int64_t +get_divisor_unit(int64_t in, uint64_t mult) +{ + return in / mult; +} + +static int64_t +update_unit(int64_t in, uint64_t mult) +{ + return in % mult; +} + +static int64_t +update_unit_approx(int64_t in, uint64_t mult) +{ + if (in / mult > 0) + return 0; + else + return update_unit (in, mult); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units(int64_t num, const struct units *units, char *s, size_t len) +{ + return unparse_something_signed(num, units, s, len, + get_divisor_unit, print_unit, update_unit, + "0"); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units_approx(int64_t num, const struct units *units, char *s, size_t len) +{ + return unparse_something_signed(num, units, s, len, get_divisor_unit, + print_unit, update_unit_approx, "0"); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_units_table (const struct units *units, FILE *f) +{ + const struct units *u, *u2; + size_t 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", (int)max_sz, u->name, buf); + } else { + fprintf (f, "1 %s\n", u->name); + } + u = next; + } +} + +static uint64_t +get_divisor_flag(uint64_t in, uint64_t mult) +{ + return in & mult; +} + +static int +print_flag(char *s, size_t len, uint64_t divisor, const char *name, uint64_t rem) +{ + return snprintf (s, len, "%s%s", name, rem > 0 ? ", " : ""); +} + +static uint64_t +update_flag(uint64_t in, uint64_t mult) +{ + return in & ~mult; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_flags (uint64_t num, const struct units *units, char *s, size_t len) +{ + return unparse_something_unsigned(num, units, s, len, get_divisor_flag, + print_flag, update_flag, ""); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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"); +} + +#undef parse_units +#undef unparse_units +#undef unparse_units_approx +#undef print_units_table +#undef parse_flags +#undef unparse_flags +#undef print_flags_table + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_units(const char *s, const struct units *units, + const char *def_unit) +{ + return rk_parse_units(s, units, def_unit); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units(int64_t num, const struct units *units, char *s, size_t len) +{ + return rk_unparse_units(num, units, s, len); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units_approx(int64_t num, const struct units *units, char *s, size_t len) +{ + return rk_unparse_units_approx(num, units, s, len); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_units_table(const struct units *units, FILE *f) +{ + rk_print_units_table(units, f); +} + +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL +parse_flags(const char *s, const struct units *units, int orig) +{ + return rk_parse_flags(s, units, orig); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_flags(uint64_t num, const struct units *units, char *s, size_t len) +{ + return rk_unparse_flags(num, units, s, len); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_flags_table (const struct units *units, FILE *f) +{ + rk_print_flags_table(units, f); +} diff --git a/third_party/heimdal/lib/roken/parse_units.h b/third_party/heimdal/lib/roken/parse_units.h new file mode 100644 index 0000000..c5b6f20 --- /dev/null +++ b/third_party/heimdal/lib/roken/parse_units.h @@ -0,0 +1,116 @@ +/* + * 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$ */ + +#ifndef __PARSE_UNITS_H__ +#define __PARSE_UNITS_H__ + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +struct units { + const char *name; + uint64_t mult; +}; + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_units (const char *s, const struct units *units, + const char *def_unit); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_units_table (const struct units *units, FILE *f); + +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL +parse_flags (const char *s, const struct units *units, + int orig); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units(int64_t num, const struct units *units, char *s, size_t len); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units_approx(int64_t num, const struct units *units, char *s, + size_t len); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_flags(uint64_t num, const struct units *units, char *s, size_t len); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_flags_table (const struct units *units, FILE *f); + +/* And again, but renamed */ + +#define parse_units rk_parse_units +#define unparse_units rk_unparse_units +#define unparse_units_approx rk_unparse_units_approx +#define print_units_table rk_print_units_table +#define parse_flags rk_parse_flags +#define unparse_flags rk_unparse_flags +#define print_flags_table rk_print_flags_table + +ROKEN_LIB_FUNCTION int64_t ROKEN_LIB_CALL +parse_units (const char *s, const struct units *units, + const char *def_unit); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_units_table (const struct units *units, FILE *f); + +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL +parse_flags (const char *s, const struct units *units, + int orig); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units(int64_t num, const struct units *units, char *s, size_t len); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_units_approx(int64_t num, const struct units *units, char *s, + size_t len); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unparse_flags(uint64_t num, const struct units *units, char *s, size_t len); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_flags_table (const struct units *units, FILE *f); + +#endif /* __PARSE_UNITS_H__ */ diff --git a/third_party/heimdal/lib/roken/putenv.c b/third_party/heimdal/lib/roken/putenv.c new file mode 100644 index 0000000..647eb7a --- /dev/null +++ b/third_party/heimdal/lib/roken/putenv.c @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> + +#if !HAVE_DECL_ENVIRON +extern char **environ; +#endif + +/* + * 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. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/qsort.c b/third_party/heimdal/lib/roken/qsort.c new file mode 100644 index 0000000..7689813 --- /dev/null +++ b/third_party/heimdal/lib/roken/qsort.c @@ -0,0 +1,203 @@ +/*- + * 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. + * 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 0 +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#endif + +#include <config.h> + +#ifdef NEED_QSORT + +#include "roken.h" + +#include <stdlib.h> + +#ifdef I_AM_QSORT_R +typedef int cmp_t(void *, const void *, const void *); +#else +typedef int cmp_t(const void *, const void *); +#endif +static inline char *med3(char *, char *, char *, cmp_t *, void *); +static inline void swapfunc(char *, char *, int, int); + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc(a, b, n, swaptype) + char *a, *b; + int n, swaptype; +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +#ifdef I_AM_QSORT_R +#define CMP(t, x, y) (cmp((t), (x), (y))) +#else +#define CMP(t, x, y) (cmp((x), (y))) +#endif + +static inline char * +med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk +#ifndef I_AM_QSORT_R +/* __unused */ +#endif +) +{ + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) + :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); +} + +#ifdef I_AM_QSORT_R +void +rk_qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#else +#define thunk NULL +void +rk_qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#endif +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + size_t d, r; + int cmp_result; + int swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); + } + pm = med3(pl, pm, pn, cmp, thunk); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) +#ifdef I_AM_QSORT_R + rk_qsort_r(a, r / es, es, thunk, cmp); +#else + rk_qsort(a, r / es, es, cmp); +#endif + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* rk_qsort(pn - r, r / es, es, cmp);*/ +} + +#endif /* NEED_QSORT */ diff --git a/third_party/heimdal/lib/roken/rand.c b/third_party/heimdal/lib/roken/rand.c new file mode 100644 index 0000000..59ff47a --- /dev/null +++ b/third_party/heimdal/lib/roken/rand.c @@ -0,0 +1,74 @@ +/* + * 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. + */ +#include <config.h> + +#include "roken.h" + +#ifdef HAVE_WIN32_RAND_S +static int hasRand_s = 1; +#include "versionsupport.h" +#endif + +void ROKEN_LIB_FUNCTION +rk_random_init(void) +{ +#if defined(HAVE_ARC4RANDOM) + /* nothing to do */; +#elif defined(HAVE_SRANDOMDEV) + srandomdev(); +#elif defined(HAVE_RANDOM) + srandom(time(NULL)); +#else +# ifdef HAVE_WIN32_RAND_S + hasRand_s = IsWindowsXPOrGreater(); +# endif + srand (time(NULL)); +#endif +} + +#ifdef HAVE_WIN32_RAND_S +unsigned int ROKEN_LIB_FUNCTION +rk_random(void) +{ + if (hasRand_s) { + unsigned int n; + int code; + + code = rand_s(&n); + if (code == 0) + return n; + } + + return rand(); +} +#endif diff --git a/third_party/heimdal/lib/roken/rcmd.c b/third_party/heimdal/lib/roken/rcmd.c new file mode 100644 index 0000000..7fa85a3 --- /dev/null +++ b/third_party/heimdal/lib/roken/rcmd.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. + */ + +#include <config.h> + +#include "roken.h" +#include <stdio.h> + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/readv.c b/third_party/heimdal/lib/roken/readv.c new file mode 100644 index 0000000..a156015 --- /dev/null +++ b/third_party/heimdal/lib/roken/readv.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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/realloc.c b/third_party/heimdal/lib/roken/realloc.c new file mode 100644 index 0000000..fefa90d --- /dev/null +++ b/third_party/heimdal/lib/roken/realloc.c @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#include <config.h> +#undef realloc + +#include <stdlib.h> +#include "roken.h" +#undef realloc + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + return malloc(size); + return realloc(ptr, size); +} diff --git a/third_party/heimdal/lib/roken/recvmsg.c b/third_party/heimdal/lib/roken/recvmsg.c new file mode 100644 index 0000000..aba298b --- /dev/null +++ b/third_party/heimdal/lib/roken/recvmsg.c @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/rename.c b/third_party/heimdal/lib/roken/rename.c new file mode 100644 index 0000000..d7348d3 --- /dev/null +++ b/third_party/heimdal/lib/roken/rename.c @@ -0,0 +1,49 @@ +/*********************************************************************** + * Copyright (c) 2010, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 "roken.h" + +/* rename() for platforms where the native implementation doesn't + * unlink newname. */ +int rk_rename(const char * oldname, const char * newname) +{ + int ret; + + ret = rename(oldname, newname); + if (ret != 0 && (errno == EEXIST || errno == EACCES)) { + ret = unlink(newname); + if (ret == 0) + ret = rename(oldname, newname); + } + + return ret; +} diff --git a/third_party/heimdal/lib/roken/resolve-test.c b/third_party/heimdal/lib/roken/resolve-test.c new file mode 100644 index 0000000..581600a --- /dev/null +++ b/third_party/heimdal/lib/roken/resolve-test.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 1995 - 2016 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. + */ + + +#include <config.h> + +#include "roken.h" +#include "getarg.h" +#include <assert.h> +#ifdef HAVE_ARPA_NAMESER_H +#include <arpa/nameser.h> +#endif +#ifdef HAVE_RESOLV_H +#include <resolv.h> +#endif +#include "resolve.h" + +static int srv_rr_order = 1; +static int loop_integer = 1; +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"srv-rr-order", 0, + arg_negative_flag, &srv_rr_order, + "do not test SRV RR ordering", NULL }, + {"loop", 0, arg_integer, &loop_integer, + "loop resolving", 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), + NULL, + "dns-record resource-record-type"); + exit (ret); +} + +#define NUMRRS 16 + +static +int +test_rk_dns_srv_order(size_t run) +{ + struct rk_dns_reply reply; + struct rk_resource_record rrs[NUMRRS]; + struct rk_resource_record *rr; + struct rk_srv_record srvs[NUMRRS]; + size_t i, prio0; + int fail = 0; + + (void) memset(&reply, 0, sizeof(reply)); + (void) memset(srvs, 0, sizeof(srvs)); + (void) memset(rrs, 0, sizeof(rrs)); + + /* Test with two equal weight zero SRV records */ + rrs[0].type = rk_ns_t_srv; + rrs[0].u.srv = &srvs[0]; + rrs[0].next = &rrs[1]; + srvs[0].priority = 10; + srvs[0].weight = 0; + + rrs[1].type = rk_ns_t_srv; + rrs[1].u.srv = &srvs[1]; + rrs[1].next = NULL; + srvs[1].priority = 10; + srvs[1].weight = 0; + reply.head = &rrs[0]; + + rk_dns_srv_order(&reply); + assert(reply.head != NULL); + printf("%p %p\n", &rrs[0], rrs[0].next); + + /* + * Test four priority groups with priority 1--5 and weigths 0--3 in the + * first two groups, and 1--4 in the last two groups. Test multiple zero + * weights, by further coercing the weight to zero if <= run/2. + */ + for (i = 0; i < NUMRRS; i++) { + rrs[i].type = rk_ns_t_srv; + rrs[i].u.srv = &srvs[i]; + srvs[i].priority = 1 + i / 4; + srvs[i].weight = i % 4 + i / 8; + if (srvs[i].weight <= run/2) + srvs[i].weight = 0; + } + /* Shuffle the RRs */ + for (i = 0; i < NUMRRS - 1; i++) { + struct rk_resource_record tmp; + size_t j = rk_random() % (NUMRRS - i); + + if (j > 0) { + tmp = rrs[i+j]; + rrs[i+j] = rrs[i]; + rrs[i] = tmp; + } + } + for (i = 0; i < NUMRRS; i++) + rrs[i].next = &rrs[i + 1]; + rrs[i - 1].next = NULL; + reply.head = &rrs[0]; + + for (i = 0, rr = reply.head; i < NUMRRS; i++) { + if (rr == NULL) + break; + printf("SRV RR order run %lu input: prio %lu weight %lu\n", + (unsigned long)run, (unsigned long)rr->u.srv->priority, + (unsigned long)rr->u.srv->weight); + rr = rr->next; + } + + rk_dns_srv_order(&reply); + assert(reply.head != NULL); + + /* + * After sorting, ensure monotone priority ordering with jumps by 1 at + * group boundaries. + */ + prio0 = 0; + for (i = 0, rr = reply.head; i < NUMRRS; i++) { + if (rr == NULL) + break; + if (rr->u.srv->priority < prio0 || + (rr->u.srv->priority != prio0 && + (i % 4 != 0 || rr->u.srv->priority > prio0 + 1))) { + printf("SRV RR order run %zu failed\n", run); + fail = 1; + } + prio0 = rr->u.srv->priority; + printf("SRV RR order run %lu output: prio %lu weight %lu\n", + (unsigned long)run, (unsigned long)rr->u.srv->priority, + (unsigned long)rr->u.srv->weight); + rr = rr->next; + } + assert(i == NUMRRS); + + return fail; +} + +int +main(int argc, char **argv) +{ + struct rk_dns_reply *r; + struct rk_resource_record *rr; + int optidx = 0, i, exit_code = 0; + + setprogname (argv[0]); + rk_random_init(); + + 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 && argc != 0 && !srv_rr_order) + usage(1); + + if (srv_rr_order) { + exit_code += test_rk_dns_srv_order(0); + exit_code += test_rk_dns_srv_order(1); + exit_code += test_rk_dns_srv_order(2); + exit_code += test_rk_dns_srv_order(3); + exit_code += test_rk_dns_srv_order(4); + exit_code += test_rk_dns_srv_order(5); + } + + if (srv_rr_order && argc == 0) + exit(exit_code ? 1 : 0); + + if (argc != 2) + usage(1); + + for (i = 0; i < loop_integer; i++) { + + r = rk_dns_lookup(argv[0], argv[1]); + if (r == NULL) { + printf("No reply.\n"); + exit_code = 1; + break; + } + if (r->q.type == rk_ns_t_srv) + rk_dns_srv_order(r); + + for (rr = r->head; rr;rr=rr->next) { + printf("%-30s %-5s %-6d ", rr->domain, rk_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 rk_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 rk_sig_record *sig = rr->u.sig; + const char *type_string = rk_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 rk_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 rk_sshfp_record *sshfp = rr->u.sshfp; + size_t j; + + printf ("alg %u type %u length %lu data ", sshfp->algorithm, + sshfp->type, (unsigned long)sshfp->sshfp_len); + for (j = 0; j < sshfp->sshfp_len; j++) + printf("%02X", sshfp->sshfp_data[j]); + printf("\n"); + + break; + } + case rk_ns_t_ds: { + struct rk_ds_record *ds = rr->u.ds; + size_t j; + + printf("key tag %u alg %u type %u length %lu data ", + ds->key_tag, ds->algorithm, ds->digest_type, + (unsigned long)ds->digest_len); + for (j = 0; j < ds->digest_len; j++) + printf("%02X", ds->digest_data[j]); + printf("\n"); + + break; + } + default: + printf("\n"); + break; + } + } + rk_dns_free_data(r); + } + + return exit_code ? 1 : 0; +} diff --git a/third_party/heimdal/lib/roken/resolve.c b/third_party/heimdal/lib/roken/resolve.c new file mode 100644 index 0000000..31da413 --- /dev/null +++ b/third_party/heimdal/lib/roken/resolve.c @@ -0,0 +1,956 @@ +/* + * 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. + */ + + +#include <config.h> + +#include "roken.h" +#ifdef HAVE_ARPA_NAMESER_H +#include <arpa/nameser.h> +#endif +#ifdef HAVE_RESOLV_H +#include <resolv.h> +#endif +#ifdef HAVE_DNS_H +#include <dns.h> +#endif +#include "resolve.h" + +#include <assert.h> + +#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; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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; +} + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +rk_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)) || defined(HAVE_WINDNS) + +static void +dns_free_rr(struct rk_resource_record *rr) +{ + if(rr->domain) + free(rr->domain); + if(rr->u.data) + free(rr->u.data); + free(rr); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_dns_free_data(struct rk_dns_reply *r) +{ + struct rk_resource_record *rr; + if(r->q.domain) + free(r->q.domain); + for(rr = r->head; rr;){ + struct rk_resource_record *tmp = rr; + rr = rr->next; + dns_free_rr(tmp); + } + free (r); +} + +#ifndef HAVE_WINDNS + +static int +parse_record(const unsigned char *data, const unsigned char *end_data, + const unsigned char **pp, struct rk_resource_record **ret_rr) +{ + struct rk_resource_record *rr; + int type, class, ttl; + unsigned 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 ((size_t)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 ((size_t)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 < (unsigned)(*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 ((size_t)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 rk_dns_reply* +parse_reply(const unsigned char *data, size_t len) +{ + const unsigned char *p; + int status; + size_t i; + char host[MAXDNAME]; + const unsigned char *end_data = data + len; + struct rk_dns_reply *r; + struct rk_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){ + rk_dns_free_data(r); + return NULL; + } + r->q.domain = strdup(host); + if(r->q.domain == NULL) { + rk_dns_free_data(r); + return NULL; + } + if (p + status + 4 > end_data) { + rk_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) { + rk_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) { + rk_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) { + rk_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 + +#if defined(HAVE_DNS_SEARCH) +#define resolve_search(h,n,c,t,r,l) \ + ((int)dns_search(h,n,c,t,r,l,(struct sockaddr *)&from,&fromsize)) +#define resolve_free_handle(h) dns_free(h) +#elif defined(HAVE_RES_NSEARCH) +#define resolve_search(h,n,c,t,r,l) res_nsearch(h,n,c,t,r,l) +#define resolve_free_handle(h) rk_res_free(h); +#else +#define resolve_search(h,n,c,t,r,l) res_search(n,c,t,r,l) +#define handle 0 +#define resolve_free_handle(h) +#endif + + +static struct rk_dns_reply * +dns_lookup_int(const char *domain, int rr_class, int rr_type) +{ + struct rk_dns_reply *r; + void *reply = NULL; + int size, len; +#if defined(HAVE_DNS_SEARCH) + struct sockaddr_storage from; + uint32_t fromsize = sizeof(from); + dns_handle_t handle; + + handle = dns_open(NULL); + if (handle == NULL) + return NULL; +#elif defined(HAVE_RES_NSEARCH) + struct __res_state state; + struct __res_state *handle = &state; + + memset(&state, 0, sizeof(state)); + if(res_ninit(handle)) + return NULL; /* is this the best we can do? */ +#endif + + len = 1500; + while(1) { + if (reply) { + free(reply); + reply = NULL; + } + if (_resolve_debug) { +#if defined(HAVE_DNS_SEARCH) + dns_set_debug(handle, 1); +#elif defined(HAVE_RES_NSEARCH) + state.options |= RES_DEBUG; +#endif + fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain, + rr_class, rk_dns_type_to_string(rr_type), len); + } + reply = malloc(len); + if (reply == NULL) { + resolve_free_handle(handle); + return NULL; + } + + size = resolve_search(handle, domain, rr_class, rr_type, reply, len); + + if (_resolve_debug) { + fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n", + domain, rr_class, rk_dns_type_to_string(rr_type), size); + } + if (size > len) { + /* resolver thinks it know better, go for it */ + len = size; + } else if (size > 0) { + /* got a good reply */ + break; + } else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) { + len *= 2; + if (len > rk_DNS_MAX_PACKET_SIZE) + len = rk_DNS_MAX_PACKET_SIZE; + } else { + /* the end, leave */ + resolve_free_handle(handle); + free(reply); + return NULL; + } + } + + len = min(len, size); + r = parse_reply(reply, len); + free(reply); + + resolve_free_handle(handle); + + return r; +} + +ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL +rk_dns_lookup(const char *domain, const char *type_name) +{ + int type; + + type = rk_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, rk_ns_c_in, type); +} + +#endif /* !HAVE_WINDNS */ + +static int +compare_srv(const void *a, const void *b) +{ + const struct rk_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); +} + +/* try to rearrange the srv-records by the algorithm in RFC2782 */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_dns_srv_order(struct rk_dns_reply *r) +{ + struct rk_resource_record **srvs, **ss, **headp; + struct rk_resource_record *rr; + int num_srv = 0; + unsigned int srv_found = FALSE; + + rk_random_init(); + + for(rr = r->head; rr; rr = rr->next) + if(rr->type == rk_ns_t_srv) { + num_srv++; + srv_found = TRUE; + } + + if(srv_found == FALSE) + 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); + + headp = &r->head; + + for (ss = srvs; ss < srvs + num_srv; ) { + int sum, zeros, rnd, count; /* zeros -> weight scaling */ + struct rk_resource_record **ee, **tt; + + /* + * find the last record with the same priority and count the sum of all + * weights + */ + for (sum = 0, zeros = 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; + if ((*tt)->u.srv->weight == 0) + zeros++; + } + /* make sure scale (`zeros') is > 0 then scale out */ + sum += zeros ? 1 : zeros++; + sum *= zeros; + ee = tt; + + /* + * ss is now the first record of this priority and ee is the first of + * the next or the first past the end of srvs + */ + while (ss < ee) { + rnd = rk_random() % sum + 1; + for (count = 0, tt = ss; tt < ee; tt++) { + if (*tt == NULL) + continue; /* this one's already been picked */ + if ((*tt)->u.srv->weight == 0) + count++; + else + count += (*tt)->u.srv->weight * zeros; + if (count >= rnd) + break; + } + assert(tt < ee); + + /* push the selected record */ + (*tt)->next = *headp; + *headp = *tt; + headp = &(*tt)->next; + /* + * reduce the sum so the next iteration is sure to reach the random + * total after examining all the remaining records. + */ + if ((*tt)->u.srv->weight == 0) + sum--; + else + sum -= (*tt)->u.srv->weight * zeros; + *tt = NULL; + while (ss < ee && *ss == NULL) + ss++; + } + } + + free(srvs); + return; +} + +#ifdef HAVE_WINDNS + +#include <WinDNS.h> + +static struct rk_resource_record * +parse_dns_record(PDNS_RECORD pRec) +{ + struct rk_resource_record * rr; + + if (pRec == NULL) + return NULL; + + rr = calloc(1, sizeof(*rr)); + + rr->domain = strdup(pRec->pName); + rr->type = pRec->wType; + rr->class = 0; + rr->ttl = pRec->dwTtl; + rr->size = 0; + + switch (rr->type) { + case rk_ns_t_ns: + case rk_ns_t_cname: + case rk_ns_t_ptr: + rr->u.txt = strdup(pRec->Data.NS.pNameHost); + if(rr->u.txt == NULL) { + dns_free_rr(rr); + return NULL; + } + break; + + case rk_ns_t_mx: + case rk_ns_t_afsdb:{ + size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH); + + rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) + + hostlen); + if (rr->u.mx == NULL) { + dns_free_rr(rr); + return NULL; + } + + strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange); + rr->u.mx->preference = pRec->Data.MX.wPreference; + break; + } + + case rk_ns_t_srv:{ + size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH); + + rr->u.srv = + (struct srv_record*)malloc(sizeof(struct srv_record) + + hostlen); + if(rr->u.srv == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.srv->priority = pRec->Data.SRV.wPriority; + rr->u.srv->weight = pRec->Data.SRV.wWeight; + rr->u.srv->port = pRec->Data.SRV.wPort; + strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget); + + break; + } + + case rk_ns_t_txt:{ + size_t len; + + if (pRec->Data.TXT.dwStringCount == 0) { + rr->u.txt = strdup(""); + break; + } + + len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH); + + rr->u.txt = (char *)malloc(len + 1); + strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]); + + break; + } + + case rk_ns_t_key : { + size_t key_len; + + if (pRec->wDataLength < 4) { + dns_free_rr(rr); + return NULL; + } + + key_len = pRec->wDataLength - 4; + rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1); + if (rr->u.key == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.key->flags = pRec->Data.KEY.wFlags; + rr->u.key->protocol = pRec->Data.KEY.chProtocol; + rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm; + rr->u.key->key_len = key_len; + memcpy_s (rr->u.key->key_data, key_len, + pRec->Data.KEY.Key, key_len); + break; + } + + case rk_ns_t_sig : { + size_t sig_len, hostlen; + + if(pRec->wDataLength <= 18) { + dns_free_rr(rr); + return NULL; + } + + sig_len = pRec->wDataLength; + + hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH); + + rr->u.sig = malloc(sizeof(*rr->u.sig) + + hostlen + sig_len); + if (rr->u.sig == NULL) { + dns_free_rr(rr); + return NULL; + } + rr->u.sig->type = pRec->Data.SIG.wTypeCovered; + rr->u.sig->algorithm = pRec->Data.SIG.chAlgorithm; + rr->u.sig->labels = pRec->Data.SIG.chLabelCount; + rr->u.sig->orig_ttl = pRec->Data.SIG.dwOriginalTtl; + rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration; + rr->u.sig->sig_inception = pRec->Data.SIG.dwTimeSigned; + rr->u.sig->key_tag = pRec->Data.SIG.wKeyTag; + rr->u.sig->sig_len = sig_len; + memcpy_s (rr->u.sig->sig_data, sig_len, + pRec->Data.SIG.Signature, sig_len); + rr->u.sig->signer = &rr->u.sig->sig_data[sig_len]; + strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner); + break; + } + +#ifdef DNS_TYPE_DS + case rk_ns_t_ds: { + rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1); + if (rr->u.ds == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.ds->key_tag = pRec->Data.DS.wKeyTag; + rr->u.ds->algorithm = pRec->Data.DS.chAlgorithm; + rr->u.ds->digest_type = pRec->Data.DS.chDigestType; + rr->u.ds->digest_len = pRec->Data.DS.wDigestLength; + memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength, + pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength); + break; + } +#endif + + default: + dns_free_rr(rr); + return NULL; + } + + rr->next = parse_dns_record(pRec->pNext); + return rr; +} + +ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL +rk_dns_lookup(const char *domain, const char *type_name) +{ + DNS_STATUS status; + int type; + PDNS_RECORD pRec = NULL; + struct rk_dns_reply * r = NULL; + + __try { + + type = rk_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; + } + + status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL, + &pRec, NULL); + if (status != ERROR_SUCCESS) + return NULL; + + r = calloc(1, sizeof(*r)); + r->q.domain = strdup(domain); + r->q.type = type; + r->q.class = 0; + + r->head = parse_dns_record(pRec); + + if (r->head == NULL) { + rk_dns_free_data(r); + return NULL; + } else { + return r; + } + + } __finally { + + if (pRec) + DnsRecordListFree(pRec, DnsFreeRecordList); + + } +} +#endif /* HAVE_WINDNS */ + +#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */ + +ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL +rk_dns_lookup(const char *domain, const char *type_name) +{ + return NULL; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_dns_free_data(struct rk_dns_reply *r) +{ +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_dns_srv_order(struct rk_dns_reply *r) +{ +} + +#endif diff --git a/third_party/heimdal/lib/roken/resolve.h b/third_party/heimdal/lib/roken/resolve.h new file mode 100644 index 0000000..fc1e97f --- /dev/null +++ b/third_party/heimdal/lib/roken/resolve.h @@ -0,0 +1,251 @@ +/* + * 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$ */ + +#ifndef __RESOLVE_H__ +#define __RESOLVE_H__ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +enum { + rk_ns_c_in = 1 +}; + +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 +}; + +#ifndef MAXDNAME +#define MAXDNAME 1025 +#endif + +#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 + +struct rk_dns_query{ + char *domain; + unsigned type; + unsigned class; +}; + +struct rk_mx_record{ + unsigned preference; + char domain[1]; +}; + +struct rk_srv_record{ + unsigned priority; + unsigned weight; + unsigned port; + char target[1]; +}; + +struct rk_key_record { + unsigned flags; + unsigned protocol; + unsigned algorithm; + size_t key_len; + u_char key_data[1]; +}; + +struct rk_sig_record { + unsigned type; + unsigned algorithm; + unsigned labels; + unsigned orig_ttl; + unsigned sig_expiration; + unsigned sig_inception; + unsigned key_tag; + char *signer; + size_t sig_len; + char sig_data[1]; /* also includes signer */ +}; + +struct rk_cert_record { + unsigned type; + unsigned tag; + unsigned algorithm; + size_t cert_len; + u_char cert_data[1]; +}; + +struct rk_sshfp_record { + unsigned algorithm; + unsigned type; + size_t sshfp_len; + u_char sshfp_data[1]; +}; + +struct rk_ds_record { + unsigned key_tag; + unsigned algorithm; + unsigned digest_type; + size_t digest_len; + u_char digest_data[1]; +}; + +struct rk_resource_record{ + char *domain; + unsigned type; + unsigned class; + unsigned ttl; + unsigned size; + union { + void *data; + struct rk_mx_record *mx; + struct rk_mx_record *afsdb; /* mx and afsdb are identical */ + struct rk_srv_record *srv; + struct in_addr *a; + char *txt; + struct rk_key_record *key; + struct rk_cert_record *cert; + struct rk_sig_record *sig; + struct rk_sshfp_record *sshfp; + struct rk_ds_record *ds; + }u; + struct rk_resource_record *next; +}; + +#define rk_DNS_MAX_PACKET_SIZE 0xffff + +struct rk_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 rk_dns_reply{ + struct rk_dns_header h; + struct rk_dns_query q; + struct rk_resource_record *head; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +ROKEN_LIB_FUNCTION struct rk_dns_reply* ROKEN_LIB_CALL + rk_dns_lookup(const char *, const char *); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL + rk_dns_free_data(struct rk_dns_reply *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_dns_string_to_type(const char *name); +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL + rk_dns_type_to_string(int type); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL + rk_dns_srv_order(struct rk_dns_reply*); + +#ifdef __cplusplus +} +#endif + +#endif /* __RESOLVE_H__ */ diff --git a/third_party/heimdal/lib/roken/rkpty.c b/third_party/heimdal/lib/roken/rkpty.c new file mode 100644 index 0000000..f7bfaca --- /dev/null +++ b/third_party/heimdal/lib/roken/rkpty.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2008 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. + */ + +#include "config.h" + +#ifndef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_PTY_H +#include <pty.h> +#endif +#ifdef HAVE_UTIL_H +#include <util.h> +#endif +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif + +#ifdef STREAMSPTY +#include <stropts.h> +#endif /* STREAMPTY */ + +#include "roken.h" +#include <getarg.h> + +struct command { + enum { CMD_EXPECT = 0, CMD_SEND, CMD_PASSWORD } type; + unsigned int lineno; + char *str; + struct command *next; +}; + +/* + * + */ + +static struct command *commands, **next = &commands; + +static sig_atomic_t alarmset = 0; + +static int timeout = 10; +static int verbose; +static int help_flag; +static int version_flag; + +static int master; +static int slave; +static char line[256] = { 0 }; + +static void +caught_signal(int signo) +{ + alarmset = signo; +} + + +static void +open_pty(void) +{ +#ifdef _AIX + printf("implement open_pty\n"); + exit(77); +#endif +#if defined(HAVE_OPENPTY) || defined(__osf__) /* XXX */ + if(openpty(&master, &slave, line, 0, 0) == 0) + return; +#endif /* HAVE_OPENPTY .... */ +#ifdef STREAMSPTY + { + char *clone[] = { + "/dev/ptc", + "/dev/ptmx", + "/dev/ptm", + "/dev/ptym/clone", + NULL + }; + char **q; + + for(q = clone; *q; q++){ + master = open(*q, O_RDWR); + if(master >= 0){ +#ifdef HAVE_GRANTPT + grantpt(master); +#endif +#ifdef HAVE_UNLOCKPT + unlockpt(master); +#endif +#ifdef HAVE_PTSNAME_R + if (ptsname_r(master, line, sizeof(line)) == -1) + err("Failed to open the pty master %s", *q); +#else + { + char *s = ptsname(master); + + if (s == NULL) + err("Failed to open the pty master %s", *q); + strlcpy(line, s, sizeof(line)); + } +#endif + slave = open(line, O_RDWR); + if (slave < 0) + errx(1, "failed to open slave when using %s", *q); + ioctl(slave, I_PUSH, "ptem"); + ioctl(slave, I_PUSH, "ldterm"); + + return; + } + } + } +#endif /* STREAMSPTY */ + + /* more cases, like open /dev/ptmx, etc */ + + exit(77); +} + +/* + * + */ + +static char * +iscmd(const char *buf, const char *s) +{ + size_t len = strlen(s); + if (strncmp(buf, s, len) != 0) + return NULL; + return estrdup(buf + len); +} + +static void +parse_configuration(const char *fn) +{ + struct command *c; + char s[1024]; + char *str; + unsigned int lineno = 0; + FILE *cmd; + + cmd = fopen(fn, "r"); + if (cmd == NULL) + err(1, "open: %s", fn); + + while (fgets(s, sizeof(s), cmd) != NULL) { + + s[strcspn(s, "#\n")] = '\0'; + lineno++; + + c = calloc(1, sizeof(*c)); + if (c == NULL) + errx(1, "malloc"); + + c->lineno = lineno; + (*next) = c; + next = &(c->next); + + if ((str = iscmd(s, "expect ")) != NULL) { + c->type = CMD_EXPECT; + c->str = str; + } else if ((str = iscmd(s, "send ")) != NULL) { + c->type = CMD_SEND; + c->str = str; + } else if ((str = iscmd(s, "password ")) != NULL) { + c->type = CMD_PASSWORD; + c->str = str; + } else + errx(1, "Invalid command on line %d: %s", lineno, s); + } + + fclose(cmd); +} + + +/* + * + */ + +static int +eval_parent(pid_t pid) +{ + struct command *c; + char in; + size_t len = 0; + ssize_t sret; + + for (c = commands; c != NULL; c = c->next) { + switch(c->type) { + case CMD_EXPECT: + if (verbose) + printf("[expecting %s]", c->str); + len = 0; + alarm(timeout); + while((sret = read(master, &in, sizeof(in))) > 0) { + alarm(timeout); + printf("%c", in); + if (c->str[len] != in) { + len = 0; + continue; + } + len++; + if (c->str[len] == '\0') + break; + } + alarm(0); + if (alarmset == SIGALRM) + errx(1, "timeout waiting for %s (line %u)", + c->str, c->lineno); + else if (alarmset) + errx(1, "got a signal %d waiting for %s (line %u)", + (int)alarmset, c->str, c->lineno); + if (sret <= 0) + errx(1, "end command while waiting for %s (line %u)", + c->str, c->lineno); + break; + case CMD_SEND: + case CMD_PASSWORD: { + size_t i = 0; + const char *msg = (c->type == CMD_PASSWORD) ? "****" : c->str; + + if (verbose) + printf("[send %s]", msg); + + len = strlen(c->str); + + while (i < len) { + if (c->str[i] == '\\' && i < len - 1) { + char ctrl; + i++; + switch(c->str[i]) { + case 'n': ctrl = '\n'; break; + case 'r': ctrl = '\r'; break; + case 't': ctrl = '\t'; break; + default: + errx(1, "unknown control char %c (line %u)", + c->str[i], c->lineno); + } + if (net_write(master, &ctrl, 1) != 1) + errx(1, "command refused input (line %u)", c->lineno); + } else { + if (net_write(master, &c->str[i], 1) != 1) + errx(1, "command refused input (line %u)", c->lineno); + } + i++; + } + break; + } + default: + abort(); + } + } + while(read(master, &in, sizeof(in)) > 0) + printf("%c", in); + + if (verbose) + printf("[end of program]\n"); + + /* + * Fetch status from child + */ + { + int ret, status; + + ret = waitpid(pid, &status, 0); + if (ret == -1) + err(1, "waitpid"); + if (WIFEXITED(status) && WEXITSTATUS(status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) { + printf("killed by signal: %d\n", WTERMSIG(status)); + return 1; + } + } + return 0; +} + +/* + * + */ + +static struct getargs args[] = { + { "timeout", 't', arg_integer, &timeout, "timout", "seconds" }, + { "verbose", 'v', arg_counter, &verbose, "verbose debugging", 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), NULL, "infile command.."); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx = 0; + pid_t pid; + + 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; + } + + argv += optidx; + argc -= optidx; + + if (argc < 2) + usage(1); + + parse_configuration(argv[0]); + + argv += 1; + + open_pty(); + + pid = fork(); + switch (pid) { + case -1: + err(1, "Failed to fork"); + case 0: + + if(setsid()<0) + err(1, "setsid"); + + dup2(slave, STDIN_FILENO); + dup2(slave, STDOUT_FILENO); + dup2(slave, STDERR_FILENO); + closefrom(STDERR_FILENO + 1); + + execvp(argv[0], argv); /* add NULL to end of array ? */ + err(1, "Failed to exec: %s", argv[0]); + default: + close(slave); + { + struct sigaction sa; + + sa.sa_handler = caught_signal; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction(SIGALRM, &sa, NULL); + } + + return eval_parent(pid); + } +} diff --git a/third_party/heimdal/lib/roken/roken-common.h b/third_party/heimdal/lib/roken/roken-common.h new file mode 100644 index 0000000..035b99b --- /dev/null +++ b/third_party/heimdal/lib/roken/roken-common.h @@ -0,0 +1,566 @@ +/* + * 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$ */ + +#ifndef __ROKEN_COMMON_H__ +#define __ROKEN_COMMON_H__ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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 O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#ifdef _WIN32 + +#define _PATH_DEVNULL "\\\\.\\NUL" + +#else + +#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 + +#endif /* !_WIN32 */ + +#ifndef PATH_MAX +#ifdef MAX_PATH +#define PATH_MAX MAX_PATH +#else +#define PATH_MAX 4096 +#endif +#endif + +#ifndef MAX_PATH +#define MAX_PATH PATH_MAX +#endif + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#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 + +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0x08 +#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 + +/* + * for dlopen(3) + */ +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + +#ifndef RTLD_NOW +#define RTLD_NOW 0 +#endif + +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +#ifndef RTLD_GROUP +#define RTLD_GROUP 0 +#endif + +#ifndef RTLD_NODELETE +#define RTLD_NODELETE 0 +#endif + +ROKEN_CPP_START + +#ifndef IRIX4 /* fix for compiler bug */ +#ifndef _WIN32 +#ifdef RETSIGTYPE +typedef RETSIGTYPE (*SigAction)(int); +SigAction signal(int iSig, SigAction pAction); /* BSD compatible */ +#endif +#endif +#endif + +#define SE_E_UNSPECIFIED (-1) +#define SE_E_FORKFAILED (-2) +#define SE_E_WAITPIDFAILED (-3) +#define SE_E_EXECTIMEOUT (-4) +#define SE_E_NOEXEC 126 +#define SE_E_NOTFOUND 127 + +#define SE_PROCSTATUS(st) (((st) >= 0 && (st) < 126)? st: -1) +#define SE_PROCSIGNAL(st) (((st) >= 128)? (st) - 128: -1) +#define SE_IS_ERROR(st) ((st) < 0 || (st) >= 126) + + +#define simple_execve rk_simple_execve +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execve(const char*, char*const[], char*const[]); + +#define simple_execve_timed rk_simple_execve_timed +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execve_timed(const char *, char *const[], + char *const [], time_t (*)(void *), + void *, time_t); + +#define simple_execvp rk_simple_execvp +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execvp(const char*, char *const[]); + +#define simple_execvp_timed rk_simple_execvp_timed +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execvp_timed(const char *, char *const[], + time_t (*)(void *), void *, time_t); + +#define simple_execlp rk_simple_execlp +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execlp(const char*, ...); + +#define simple_execle rk_simple_execle +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execle(const char*, ...); + +#define wait_for_process rk_wait_for_process +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +wait_for_process(pid_t); + +#define wait_for_process_timed rk_wait_for_process_timed +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +wait_for_process_timed(pid_t, time_t (*)(void *), + void *, time_t); + +#define pipe_execv rk_pipe_execv +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +pipe_execv(FILE**, FILE**, FILE**, const char*, ...); + +#define print_version rk_print_version +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +print_version(const char *); + +#define eread rk_eread +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +eread (int fd, void *buf, size_t nbytes); + +#define ewrite rk_ewrite +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +ewrite (int fd, const void *buf, size_t nbytes); + +struct hostent; + +#define hostent_find_fqdn rk_hostent_find_fqdn +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +hostent_find_fqdn (const struct hostent *); + +#define esetenv rk_esetenv +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +esetenv(const char *, const char *, int); + +#define socket_set_address_and_port rk_socket_set_address_and_port +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_address_and_port (struct sockaddr *, const void *, int); + +#define socket_addr_size rk_socket_addr_size +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +socket_addr_size (const struct sockaddr *); + +#define socket_set_any rk_socket_set_any +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_any (struct sockaddr *, int); + +#define socket_sockaddr_size rk_socket_sockaddr_size +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +socket_sockaddr_size (const struct sockaddr *); + +#define socket_get_address rk_socket_get_address +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +socket_get_address (const struct sockaddr *); + +#define socket_get_port rk_socket_get_port +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +socket_get_port (const struct sockaddr *); + +#define socket_set_port rk_socket_set_port +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_port (struct sockaddr *, int); + +#define socket_set_portrange rk_socket_set_portrange +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_portrange (rk_socket_t, int, int); + +#define socket_set_debug rk_socket_set_debug +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_debug (rk_socket_t); + +#define socket_set_tos rk_socket_set_tos +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_tos (rk_socket_t, int); + +#define socket_set_nonblocking rk_socket_set_nonblocking +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_nonblocking(rk_socket_t, int); + +#define socket_set_reuseaddr rk_socket_set_reuseaddr +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_reuseaddr (rk_socket_t, int); + +#define socket_set_ipv6only rk_socket_set_ipv6only +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_ipv6only (rk_socket_t, int); + +#define socket_set_keepalive rk_socket_set_keepalive +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_keepalive (rk_socket_t, int); + +#define socket_to_fd rk_socket_to_fd +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +socket_to_fd(rk_socket_t, int); + +#define vstrcollect rk_vstrcollect +ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL +vstrcollect(va_list *ap); + +#define strcollect rk_strcollect +ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL +strcollect(char *first, ...); + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +rk_time_add(time_t, time_t); + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +rk_time_sub(time_t, time_t); + +#define timevalfix rk_timevalfix +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevalfix(struct timeval *t1); + +#define timevaladd rk_timevaladd +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevaladd(struct timeval *t1, const struct timeval *t2); + +#define timevalsub rk_timevalsub +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevalsub(struct timeval *t1, const struct timeval *t2); + +#define pid_file_write rk_pid_file_write +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +pid_file_write (const char *progname); + +#define pid_file_delete rk_pid_file_delete +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +pid_file_delete (char **); + +#define read_environment rk_read_environment +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +read_environment(const char *file, char ***env); + +#define free_environment rk_free_environment +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +free_environment(char **); + +#define warnerr rk_warnerr +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_warnerr(int doerrno, const char *fmt, va_list ap) + __attribute__ ((__format__ (__printf__, 2, 0))); + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_realloc(void *, size_t); + +struct rk_strpool; + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_strpoolcollect(struct rk_strpool *); + +ROKEN_LIB_FUNCTION struct rk_strpool * ROKEN_LIB_CALL +rk_strpoolprintf(struct rk_strpool *, const char *, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_strpoolfree(struct rk_strpool *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_dumpdata (const char *, const void *, size_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_undumpdata (const char *, void **, size_t *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_xfree (void *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_cloexec(int); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_cloexec_file(FILE *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_cloexec_dir(DIR *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_cloexec_socket(rk_socket_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +ct_memcmp(const volatile void * volatile, + const volatile void * volatile, + size_t); + +void ROKEN_LIB_FUNCTION +rk_random_init(void); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_mkdir(const char *, mode_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_clzll(uint64_t); + +ROKEN_CPP_END + +#endif /* __ROKEN_COMMON_H__ */ diff --git a/third_party/heimdal/lib/roken/roken.awk b/third_party/heimdal/lib/roken/roken.awk new file mode 100644 index 0000000..47313c8 --- /dev/null +++ b/third_party/heimdal/lib/roken/roken.awk @@ -0,0 +1,46 @@ +# $Id$ + +BEGIN { + print "#include <config.h>" + print "#include <stdio.h>" + print "#ifdef HAVE_SYS_TYPES_H" + print "#include <sys/types.h>" + print "#endif" + print "#ifdef HAVE_SYS_SOCKET_H" + print "#include <sys/socket.h>" + print "#endif" + print "#ifdef HAVE_ERRNO_H" + print "#include <errno.h>" + print "#endif" + 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(\"\");" + print "puts(\"#endif /* __ROKEN_H__ */\");" + print "return 0;" + print "}" +} diff --git a/third_party/heimdal/lib/roken/roken.h.in b/third_party/heimdal/lib/roken/roken.h.in new file mode 100644 index 0000000..e1902f5 --- /dev/null +++ b/third_party/heimdal/lib/roken/roken.h.in @@ -0,0 +1,1330 @@ +/* -*- C -*- */ +/* + * Copyright (c) 1995-2017 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. + */ + +# if defined(_WIN32) && _MSC_VER >= 1400 +/* _CRT_RAND_S must be defined before including stdlib.h */ +# define _CRT_RAND_S +# define HAVE_WIN32_RAND_S 1 +# endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <string.h> +#include <limits.h> +#include <signal.h> + +#ifdef HAVE_UTIL_H +#include <util.h> +#endif + +# ifndef ROKEN_LIB_FUNCTION +# ifdef _WIN32 +# ifdef ROKEN_LIB_DYNAMIC +# define ROKEN_LIB_FUNCTION __declspec(dllimport) +# else +# define ROKEN_LIB_FUNCTION +# endif +# else +# define ROKEN_LIB_FUNCTION +# endif +# endif + +# ifndef ROKEN_LIB_NORETURN_FUNCTION +# ifdef _WIN32 +# ifdef ROKEN_LIB_DYNAMIC +# define ROKEN_LIB_NORETURN_FUNCTION __declspec(dllimport noreturn) +# else +# define ROKEN_LIB_NORETURN_FUNCTION __declspec(noreturn) +# endif +# else +# define ROKEN_LIB_NORETURN_FUNCTION +# endif +# endif + +# ifndef ROKEN_LIB_CALL +# ifdef _WIN32 +# define ROKEN_LIB_CALL __cdecl +# else +# define ROKEN_LIB_CALL +# endif +# endif + +# ifndef ROKEN_LIB_VARIABLE +# ifdef _WIN32 +# ifdef ROKEN_LIB_DYNAMIC +# define ROKEN_LIB_VARIABLE __declspec(dllimport) +# else +# define ROKEN_LIB_VARIABLE +# endif +# else +# define ROKEN_LIB_VARIABLE +# endif +# endif + +#ifdef HAVE_WINSOCK +/* Declarations for Microsoft Windows */ + +#include <winsock2.h> +#include <ws2tcpip.h> + +/* + * error codes for inet_ntop/inet_pton + */ +typedef SOCKET rk_socket_t; + +#define rk_closesocket(x) closesocket(x) +#define rk_INVALID_SOCKET INVALID_SOCKET +#define rk_IS_BAD_SOCKET(s) ((s) == INVALID_SOCKET) +#define rk_IS_SOCKET_ERROR(rv) ((rv) == SOCKET_ERROR) +#define rk_SOCK_ERRNO WSAGetLastError() + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp); + +#define rk_SOCK_INIT() rk_WSAStartup() +#define rk_SOCK_EXIT() rk_WSACleanup() + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_WSAStartup(void); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_WSACleanup(void); + +#else /* not WinSock */ + +typedef int rk_socket_t; + +#define rk_closesocket(x) close(x) +#define rk_SOCK_IOCTL(s,c,a) ioctl((s),(c),(a)) +#define rk_IS_BAD_SOCKET(s) ((s) < 0) +#define rk_IS_SOCKET_ERROR(rv) ((rv) < 0) +#define rk_SOCK_ERRNO errno +#define rk_INVALID_SOCKET (-1) + +static inline ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_SOCK_INIT(void) { + return 0; +} + +#define rk_SOCK_EXIT() do { } while(0) + +#endif /* WinSock */ + +#ifndef IN_LOOPBACKNET +#define IN_LOOPBACKNET 127 +#endif + +#ifdef _MSC_VER +#ifndef HAVE_STDINT_H +#include <intsafe.h> +#endif + +/* Declarations for Microsoft Visual C runtime on Windows */ + +#include<process.h> + +#include<io.h> + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ + +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; + +#endif /* __BIT_TYPES_DEFINED__ */ + +#define UNREACHABLE(x) x +#define UNUSED_ARGUMENT(x) ((void) x) + +#define RETSIGTYPE void + +#define VOID_RETSIGTYPE 1 + +#ifdef VOID_RETSIGTYPE +#define SIGRETURN(x) return +#else +#define SIGRETURN(x) return (RETSIGTYPE)(x) +#endif + +#ifndef CPP_ONLY + +typedef int pid_t; + +typedef unsigned int gid_t; + +typedef unsigned int uid_t; + +typedef unsigned short mode_t; + +#endif + +#ifndef __cplusplus +#define inline __inline +#endif + +#else + +#define UNREACHABLE(x) +#define UNUSED_ARGUMENT(x) + +#endif + +#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_ERRNO_H +#include <sys/errno.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 +#ifdef HAVE_SYS_IOCTL_H +#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_PATHS_H +#include <paths.h> +#endif + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif + +#ifdef WIN32 +#include <direct.h> +#endif + +#ifdef BACKSLASH_PATH_DELIM +#define rk_PATH_DELIM '\\' +#endif + +#ifndef HAVE_SSIZE_T +#ifndef SSIZE_T_DEFINED +#ifdef ssize_t +#undef ssize_t +#endif +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef int ssize_t; +#endif +#define SSIZE_T_DEFINED +#endif /* SSIZE_T_DEFINED */ +#endif /* HAVE_SSIZE_T */ + +#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 + +#ifdef _MSC_VER +/* Additional macros for Visual C/C++ runtime */ + +#define close _close + +#define getpid _getpid + +#define open _open + +#define chdir _chdir + +#define fsync _commit + +#define _PIPE_BUFFER_SZ 8192 +#define pipe(fds) _pipe((fds), _PIPE_BUFFER_SZ, O_BINARY); + +#define ftruncate(fd, sz) _chsize((fd), (sz)) + +#if !defined(HAVE_UCRT) +#define snprintf rk_snprintf +#define vsnprintf rk_vsnprintf +#define vasnprintf rk_vasnprintf +#define vasprintf rk_vasprintf +#define asnprintf rk_asnprintf +#define asprintf rk_asprintf + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_snprintf (char *str, size_t sz, const char *format, ...); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_asprintf (char **ret, const char *format, ...); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_asnprintf (char **ret, size_t max_sz, const char *format, ...); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_vasprintf (char **ret, const char *format, va_list args); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_vsnprintf (char *str, size_t sz, const char *format, va_list args); +#endif /* !defined(HAVE_UCRT) */ + +/* missing stat.h predicates */ + +#define S_ISREG(m) (((m) & _S_IFREG) == _S_IFREG) + +#define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) + +#define S_ISCHR(m) (((m) & _S_IFCHR) == _S_IFCHR) + +#define S_ISFIFO(m) (((m) & _S_IFIFO) == _S_IFIFO) + +/* The following are not implemented: + + S_ISLNK(m) + S_ISSOCK(m) + S_ISBLK(m) +*/ + +/* The following symbolic constants are provided for rk_mkdir mode */ + +#define S_IRWXU 00700 /* user (file owner) has read, write and execute permission */ +#define S_IRUSR 00400 /* user has read permission */ +#define S_IWUSR 00200 /* user has write permission */ +#define S_IXUSR 00100 /* user has execute permission */ +#define S_IRWXG 00070 /* group has read, write and execute permission */ +#define S_IRGRP 00040 /* group has read permission */ +#define S_IWGRP 00020 /* group has write permission */ +#define S_IXGRP 00010 /* group has execute permission */ +#define S_IRWXO 00007 /* others have read, write and execute permission */ +#define S_IROTH 00004 /* others have read permission */ +#define S_IWOTH 00002 /* others have write permission */ +#define S_IXOTH 00001 /* others have execute permission */ + +#if !defined(ROKEN_NO_DEFINE_ALLOCATORS) +/* Ensure that a common memory allocator is used by all */ +#define calloc rk_calloc +#define free rk_free +#define malloc rk_malloc +#define realloc rk_realloc +#define strdup rk_strdup +#define wcsdup rk_wcsdup +#endif + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_calloc(size_t, size_t); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_free(void *); + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_malloc(size_t); + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_realloc(void *, size_t); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_strdup(const char *); + +ROKEN_LIB_FUNCTION unsigned short * ROKEN_LIB_CALL +rk_wcsdup(const unsigned short *); + +#endif /* _MSC_VER */ + +#ifndef HAVE_MEMMEM +#define memmem rk_smemmem +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL memmem(const void *, size_t, const void *, size_t); +#endif + +#ifdef HAVE_WINSOCK + +/* While we are at it, define WinSock specific scatter gather socket + I/O. */ + +#define iovec _WSABUF +#define iov_base buf +#define iov_len len + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + size_t msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +#define sendmsg sendmsg_w32 + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags); + +#endif /* HAVE_WINSOCK */ + +#ifndef HAVE_PUTENV +#define putenv rk_putenv +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL putenv(const char *); +#endif + +#if !defined(HAVE_SETENV) || defined(NEED_SETENV_PROTO) +#ifndef HAVE_SETENV +#define setenv rk_setenv +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL setenv(const char *, const char *, int); +#endif + +#if !defined(HAVE_UNSETENV) || defined(NEED_UNSETENV_PROTO) +#ifndef HAVE_UNSETENV +#define unsetenv rk_unsetenv +#endif +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL unsetenv(const char *); +#endif + +#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO) +#ifndef HAVE_GETUSERSHELL +#define getusershell rk_getusershell +#define endusershell rk_endusershell +#endif +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL getusershell(void); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL endusershell(void); +#endif + +#if !defined(HAVE_SNPRINTF) || defined(NEED_SNPRINTF_PROTO) +#ifndef HAVE_SNPRINTF +#define snprintf rk_snprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_snprintf (char *, size_t, const char *, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +#endif + +#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO) +#ifndef HAVE_VSNPRINTF +#define vsnprintf rk_vsnprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_vsnprintf (char *, size_t, const char *, va_list) + __attribute__ ((__format__ (__printf__, 3, 0))); +#endif + +#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO) +#ifndef HAVE_ASPRINTF +#define asprintf rk_asprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_asprintf (char **, const char *, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +#endif + +#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO) +#ifndef HAVE_VASPRINTF +#define vasprintf rk_vasprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_vasprintf (char **, const char *, va_list) + __attribute__ ((__format__ (__printf__, 2, 0))); +#endif + +#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO) +#ifndef HAVE_ASNPRINTF +#define asnprintf rk_asnprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_asnprintf (char **, size_t, const char *, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +#endif + +#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO) +#ifndef HAVE_VASNPRINTF +#define vasnprintf rk_vasnprintf +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + vasnprintf (char **, size_t, const char *, va_list) + __attribute__ ((__format__ (__printf__, 3, 0))); +#endif + +#ifndef HAVE_STRDUP +#define strdup rk_strdup +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strdup(const char *); +#endif + +#if !defined(HAVE_STRNDUP) || defined(NEED_STRNDUP_PROTO) +#ifndef HAVE_STRNDUP +#define strndup rk_strndup +#endif +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strndup(const char *, size_t); +#endif + +#ifndef HAVE_STRLWR +#define strlwr rk_strlwr +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strlwr(char *); +#endif + +#ifndef HAVE_STRNLEN +#define strnlen rk_strnlen +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL strnlen(const char*, size_t); +#endif + +#if !defined(HAVE_STRSEP) || defined(NEED_STRSEP_PROTO) +#ifndef HAVE_STRSEP +#define strsep rk_strsep +#endif +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strsep(char**, const char*); +#endif + +#if !defined(HAVE_STRSEP_COPY) || defined(NEED_STRSEP_COPY_PROTO) +#ifndef HAVE_STRSEP_COPY +#define strsep_copy rk_strsep_copy +#endif +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL strsep_copy(const char**, const char*, char*, size_t); +#endif + +#ifndef HAVE_STRCASECMP +#define strcasecmp rk_strcasecmp +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL strcasecmp(const char *, const char *); +#endif + +#ifdef NEED_FCLOSE_PROTO +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL fclose(FILE *); +#endif + +#ifdef NEED_STRTOK_R_PROTO +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strtok_r(char *, const char *, char **); +#endif + +#ifndef HAVE_STRUPR +#define strupr rk_strupr +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strupr(char *); +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy rk_strlcpy +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL strlcpy (char *, const char *, size_t); +#endif + +#ifndef HAVE_STRLCAT +#define strlcat rk_strlcat +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL strlcat (char *, const char *, size_t); +#endif + +#ifndef HAVE_GETDTABLESIZE +#define getdtablesize rk_getdtablesize +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL getdtablesize(void); +#endif + +#if !defined(HAVE_STRERROR) && !defined(strerror) +#define strerror rk_strerror +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strerror(int); +#endif + +#if (!defined(HAVE_STRERROR_R) && !defined(strerror_r)) || (!defined(STRERROR_R_PROTO_COMPATIBLE) && defined(HAVE_STRERROR_R)) +int ROKEN_LIB_FUNCTION rk_strerror_r(int, char *, size_t); +#else +#define rk_strerror_r strerror_r +#endif + +#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO) +#ifndef HAVE_HSTRERROR +#define hstrerror rk_hstrerror +#endif +/* This causes a fatal error under Psoriasis */ +#ifndef SunOS +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL hstrerror(int); +#endif +#endif + +#if !HAVE_DECL_H_ERRNO +extern int h_errno; +#endif + +#if !defined(HAVE_INET_ATON) || defined(NEED_INET_ATON_PROTO) +#ifndef HAVE_INET_ATON +#define inet_aton rk_inet_aton +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL inet_aton(const char *, struct in_addr *); +#endif + +#ifndef HAVE_INET_NTOP +#define inet_ntop rk_inet_ntop +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + +#ifndef HAVE_INET_PTON +#define inet_pton rk_inet_pton +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +inet_pton(int, const char *, void *); +#endif + +#ifndef HAVE_GETCWD +#define getcwd rk_getcwd +ROKEN_LIB_FUNCTION char* ROKEN_LIB_CALL getcwd(char *, size_t); +#endif + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifndef HAVE_SETEUID +#define seteuid rk_seteuid +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL seteuid(uid_t); +#endif + +#ifndef HAVE_SETEGID +#define setegid rk_setegid +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL setegid(gid_t); +#endif + +#ifndef HAVE_LSTAT +#define lstat rk_lstat +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL lstat(const char *, struct stat *); +#endif + +#if !defined(HAVE_MKSTEMP) || defined(NEED_MKSTEMP_PROTO) +#ifndef HAVE_MKSTEMP +#define mkstemp rk_mkstemp +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL mkstemp(char *); +#endif + +#ifndef HAVE_MKOSTEMP +#define mkostemp rk_mkostemp +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL mkostemp(char *, int); +#endif + +#ifndef HAVE_MKDTEMP +#define mkdtemp rk_mkdtemp +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL mkdtemp(char *); +#endif + +#ifndef HAVE_INITGROUPS +#define initgroups rk_initgroups +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL initgroups(const char *, gid_t); +#endif + +#ifndef HAVE_FCHOWN +#define fchown rk_fchown +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL fchown(int, uid_t, gid_t); +#endif + +#ifdef RENAME_DOES_NOT_UNLINK +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_rename(const char *, const char *); +#else +#define rk_rename(__rk_rn_from,__rk_rn_to) rename(__rk_rn_from,__rk_rn_to) +#endif + +#ifdef WIN32 +#define mkdir rk_mkdir +#else +#define rk_mkdir(__rk_rn_name, __rk_rn_mode) mkdir(__rk_rn_name,__rk_rn_mode) +#endif + + +#if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO) +#ifndef HAVE_DAEMON +#define daemon rk_daemon +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL daemon(int, int); +#endif + +#ifndef HAVE_CHOWN +#define chown rk_chown +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL chown(const char *, uid_t, gid_t); +#endif + +#ifndef HAVE_RCMD +#define rcmd rk_rcmd +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rcmd(char **, unsigned short, const char *, + const char *, const char *, int *); +#endif + +#if !defined(HAVE_INNETGR) || defined(NEED_INNETGR_PROTO) +#ifndef HAVE_INNETGR +#define innetgr rk_innetgr +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL innetgr(const char*, const char*, + const char*, const char*); +#endif + +#if !defined(HAVE_GETHOSTNAME) || defined(NEED_GETHOSTNAME_PROTO) +#ifndef HAVE_GETHOSTNAME +#define gethostname rk_gethostname +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL gethostname(char *, int); +#endif + +#ifndef HAVE_WRITEV +#define writev rk_writev +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +writev(int, const struct iovec *, int); +#endif + +#ifndef HAVE_READV +#define readv rk_readv +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +readv(int, const struct iovec *, int); +#endif + +#ifdef NO_PIDFILES +#define rk_pidfile(x) ((void) 0) +#else +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rk_pidfile (const char*); +#endif + +#ifndef HAVE_BSWAP64 +#define bswap64 rk_bswap64 +ROKEN_LIB_FUNCTION uint64_t ROKEN_LIB_CALL bswap64(uint64_t); +#endif + +#ifndef HAVE_BSWAP32 +#define bswap32 rk_bswap32 +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL bswap32(unsigned int); +#endif + +#ifndef HAVE_BSWAP16 +#define bswap16 rk_bswap16 +ROKEN_LIB_FUNCTION unsigned short ROKEN_LIB_CALL 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 + +#define flock(_x,_y) rk_flock(_x,_y) +int rk_flock(int fd, int operation); +#endif /* HAVE_FLOCK */ + +#ifndef HAVE_DIRFD +#ifdef HAVE_DIR_DD_FD +#define dirfd(x) ((x)->dd_fd) +#elif defined(HAVE_DIR_D_FD) +#define dirfd(x) ((x)->d_fd) +#else +#ifndef _WIN32 /* Windows code never calls dirfd */ +#error Missing dirfd() and ->dd_fd and ->d_fd +#endif +#endif +#endif + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL tm2time (struct tm, int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_concat (char *, size_t, ...); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL roken_mconcat (char **, size_t, ...); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_vconcat (char *, size_t, va_list); + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL + roken_vmconcat (char **, size_t, va_list); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_detach_prep(int, char **, char *); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_finish(const char *, int); + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL + net_write (rk_socket_t, const void *, size_t); + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL + net_read (rk_socket_t, void *, size_t); + +ROKEN_LIB_FUNCTION unsigned long ROKEN_LIB_CALL + rk_getauxval(unsigned long); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + issuid(void); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_secure_getenv(const char *); + +#ifndef HAVE_SECURE_GETENV +#undef secure_getenv +#define secure_getenv(e) rk_secure_getenv(e) +#endif + +#ifndef HAVE_STRUCT_WINSIZE +struct winsize { + unsigned short ws_row, ws_col; + unsigned short ws_xpixel, ws_ypixel; +}; +#endif + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL get_window_size(int fd, int *, int *); + +#ifndef HAVE_VSYSLOG +#define vsyslog rk_vsyslog +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL vsyslog(int, const char *, va_list); +#endif + +#ifndef HAVE_GETOPT +#define getopt rk_getopt +#define optarg rk_optarg +#define optind rk_optind +#define opterr rk_opterr +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getopt(int nargc, char * const *nargv, const char *ostr); +#endif + +#if !HAVE_DECL_OPTARG +ROKEN_LIB_VARIABLE extern char *optarg; +#endif +#if !HAVE_DECL_OPTIND +ROKEN_LIB_VARIABLE extern int optind; +#endif +#if !HAVE_DECL_OPTERR +ROKEN_LIB_VARIABLE extern int opterr; +#endif + +#ifndef HAVE_GETIPNODEBYNAME +#define getipnodebyname rk_getipnodebyname +#endif +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_getipnodebyname(const char *, int, int, int *); + +#ifndef HAVE_GETIPNODEBYADDR +#define getipnodebyaddr rk_getipnodebyaddr +#endif +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_getipnodebyaddr(const void *, size_t, int, int *); + +#ifndef HAVE_FREEHOSTENT +#define freehostent rk_freehostent +#endif +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_freehostent(struct hostent *); + +#ifndef HAVE_COPYHOSTENT +#define copyhostent rk_copyhostent +#endif +ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL +rk_copyhostent(const struct hostent *); + +#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 +#define getaddrinfo rk_getaddrinfo +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_getaddrinfo(const char *, + const char *, + const struct addrinfo *, + struct addrinfo **); + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo rk_getnameinfo +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_getnameinfo(const struct sockaddr *, socklen_t, + char *, size_t, + char *, size_t, + int); + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo rk_freeaddrinfo +#endif +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_freeaddrinfo(struct addrinfo *); + +#ifndef HAVE_GAI_STRERROR +#define gai_strerror rk_gai_strerror +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +gai_strerror(int); +#endif + +#ifdef NO_SLEEP + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +sleep(unsigned int seconds); + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +usleep(unsigned int useconds); + +#endif + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getnameinfo_verified(const struct sockaddr *, socklen_t, + char *, size_t, + char *, size_t, + int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_getaddrinfo_hostspec(const char *, int, struct addrinfo **); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_homedir(char *, size_t); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_appdatadir(char *, size_t); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_username(char *, size_t); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_loginname(char *, size_t); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +roken_get_shell(char *, size_t); + +#ifndef HAVE_STRFTIME +#define strftime rk_strftime +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strftime (char *, size_t, const char *, const struct tm *); +#endif + +#ifndef HAVE_STRPTIME +#define strptime rk_strptime +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +strptime (const char *, const char *, struct tm *); +#endif + +#ifndef HAVE_GETTIMEOFDAY +#define gettimeofday rk_gettimeofday +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +gettimeofday (struct timeval *, void *); +#endif + +#ifndef HAVE_EMALLOC +#define emalloc rk_emalloc +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL emalloc (size_t); +#endif +#ifndef HAVE_ECALLOC +#define ecalloc rk_ecalloc +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL ecalloc(size_t, size_t); +#endif +#ifndef HAVE_EREALLOC +#define erealloc rk_erealloc +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL erealloc (void *, size_t); +#endif +#ifndef HAVE_ESTRDUP +#define estrdup rk_estrdup +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL estrdup (const char *); +#endif + +/* + * kludges and such + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_gethostby_setup(const char*, const char*); +ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL +roken_gethostbyname(const char*); +ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL +roken_gethostbyaddr(const void*, size_t, int); + +#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 +#define setprogname rk_setprogname +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL setprogname(const char *); +#endif + +#ifndef HAVE_GETPROGNAME +#define getprogname rk_getprogname +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL getprogname(void); +#endif + +#if !defined(HAVE_SETPROGNAME) && !defined(HAVE_GETPROGNAME) && !HAVE_DECL___PROGNAME +extern const char *__progname; +#endif + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +mini_inetd_addrinfo (struct addrinfo*, rk_socket_t *); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +mini_inetd (int, rk_socket_t *); + +#ifndef HAVE_LOCALTIME_R +#define localtime_r rk_localtime_r +ROKEN_LIB_FUNCTION struct tm * ROKEN_LIB_CALL +localtime_r(const time_t *, struct tm *); +#endif + +#if !defined(HAVE_STRTOLL) || defined(NEED_STRTOLL_PROTO) +#ifndef HAVE_STRTOLL +#define strtoll rk_strtoll +#endif +ROKEN_LIB_FUNCTION long long ROKEN_LIB_CALL +strtoll(const char * nptr, char ** endptr, int base); +#endif + +#if !defined(HAVE_STRTOULL) || defined(NEED_STRTOULL_PROTO) +#ifndef HAVE_STRTOULL +#define strtoull rk_strtoull +#endif +ROKEN_LIB_FUNCTION unsigned long long ROKEN_LIB_CALL +strtoull(const char * nptr, char ** endptr, int base); +#endif + +#if !defined(HAVE_STRSVIS) || defined(NEED_STRSVIS_PROTO) +#ifndef HAVE_STRSVIS +#define strsvis rk_strsvis +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +strsvis(char *, const char *, int, const char *); +#endif + +#if !defined(HAVE_STRSVISX) || defined(NEED_STRSVISX_PROTO) +#ifndef HAVE_STRSVISX +#define strsvisx rk_strsvisx +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +strsvisx(char *, const char *, size_t, int, const char *); +#endif + +#if !defined(HAVE_STRUNVIS) || defined(NEED_STRUNVIS_PROTO) +#ifndef HAVE_STRUNVIS +#define strunvis rk_strunvis +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +strunvis(char *, const char *); +#endif + +#if !defined(HAVE_STRVIS) || defined(NEED_STRVIS_PROTO) +#ifndef HAVE_STRVIS +#define strvis rk_strvis +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +strvis(char *, const char *, int); +#endif + +#if !defined(HAVE_STRVISX) || defined(NEED_STRVISX_PROTO) +#ifndef HAVE_STRVISX +#define strvisx rk_strvisx +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +strvisx(char *, const char *, size_t, int); +#endif + +#if !defined(HAVE_SVIS) || defined(NEED_SVIS_PROTO) +#ifndef HAVE_SVIS +#define svis rk_svis +#endif +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +svis(char *, int, int, int, const char *); +#endif + +#if !defined(HAVE_UNVIS) || defined(NEED_UNVIS_PROTO) +#ifndef HAVE_UNVIS +#define unvis rk_unvis +#endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +unvis(char *, int, int *, int); +#endif + +#if !defined(HAVE_VIS) || defined(NEED_VIS_PROTO) +#ifndef HAVE_VIS +#define vis rk_vis +#endif +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +vis(char *, int, int, int); +#endif + +#if !defined(HAVE_CLOSEFROM) +#define closefrom rk_closefrom +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +closefrom(int); +#endif + +#if !defined(HAVE_TIMEGM) +#define timegm rk_timegm +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +rk_timegm(struct tm *tm); +#endif + +#ifdef NEED_QSORT +#define qsort rk_qsort +void +rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +#endif + +#if !defined(HAVE_MERGESORT) +#define mergesort rk_mergesort +int +mergesort(void *base, size_t nel, size_t width, + int (*compar)(const void *, const void *)); +#endif + +#if !defined(HAVE_MERGESORT_R) +#define mergesort_r rk_mergesort_r +int +mergesort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *, const void *, void *), void *thunk); +#endif + +#ifndef HAVE_MEMSET_S +#define memset_s rk_memset_s +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL memset_s(void *s, size_t smax, + int c, size_t n); +#endif + +#if defined(HAVE_ARC4RANDOM) +# define rk_random() arc4random() +#elif defined(HAVE_RANDOM) +# define rk_random() random() +#else +# ifdef HAVE_WIN32_RAND_S +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +rk_random(void); +# else +# define rk_random() rand() +# endif +#endif + +#ifndef HAVE_TDELETE +#define tdelete(a,b,c) rk_tdelete(a,b,c) +#endif +#ifndef HAVE_TFIND +#define tfind(a,b,c) rk_tfind(a,b,c) +#endif +#ifndef HAVE_TSEARCH +#define tsearch(a,b,c) rk_tsearch(a,b,c) +#endif +#ifndef HAVE_TWALK +#define twalk(a,b) rk_twalk(a,b) +#endif + +#if defined(__linux__) && defined(SOCK_CLOEXEC) && !defined(SOCKET_WRAPPER_REPLACE) && !defined(__SOCKET_WRAPPER_H__) +#undef socket +#define socket(_fam,_type,_prot) rk_socket(_fam,_type,_prot) +int ROKEN_LIB_FUNCTION rk_socket(int, int, int); +#endif + +/* Microsoft VC 2010 POSIX definitions */ +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT 102 +#endif +#ifndef EINPROGRESS +#define EINPROGRESS 112 +#endif +#ifndef ELOOP +#define ELOOP 114 +#endif +#ifndef ENOTSOCK +#define ENOTSOCK 128 +#endif +#ifndef ENOTSUP +#define ENOTSUP 129 +#endif +#ifndef EOVERFLOW +#define EOVERFLOW 132 +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT 138 +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK 140 +#endif + +#ifdef WIN32 +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +win32_getLibraryVersion(const char *libname, char **outname, char **outversion); +#endif + +#ifdef SOCKET_WRAPPER_REPLACE +#include <socket_wrapper.h> +#endif + +ROKEN_CPP_END diff --git a/third_party/heimdal/lib/roken/roken_gethostby.c b/third_party/heimdal/lib/roken/roken_gethostby.c new file mode 100644 index 0000000..a2febd0 --- /dev/null +++ b/third_party/heimdal/lib/roken/roken_gethostby.c @@ -0,0 +1,292 @@ +/* + * 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. + */ + +#include <config.h> + +#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); + dns_req = NULL; + if(proxy_host) { + if(make_address(proxy_host, &dns_addr.sin_addr) != 0) + return -1; + dns_addr.sin_port = htons(proxy_port); + if (asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path) < 0) + return -1; + } else { + if(make_address(dns_host, &dns_addr.sin_addr) != 0) + return -1; + dns_addr.sin_port = htons(dns_port); + if (asprintf(&dns_req, "%s", dns_path) < 0) + return -1; + } + dns_addr.sin_family = AF_INET; + return 0; +} + +static int +split_spec(const char *spec, char **host, int *port, char **path, int def_port) +{ + char *p; + *host = strdup(spec); + if (*host == NULL) + return -1; + 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); + if (*path == NULL) { + free(*host); + *host = NULL; + return -1; + } + } + *p = '\0'; + }else + if(path) + *path = NULL; + return 0; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_gethostby_setup(const char *proxy_spec, const char *dns_spec) +{ + char *proxy_host = NULL; + int proxy_port = 0; + char *dns_host = NULL, *dns_path = NULL; + int dns_port; + int ret; + + ret = split_spec(dns_spec, &dns_host, &dns_port, &dns_path, 80); + if(ret) + goto out; + if(proxy_spec) { + ret = split_spec(proxy_spec, &proxy_host, &proxy_port, NULL, 80); + if (ret) + goto out; + } + ret = setup_int(proxy_host, proxy_port, dns_host, dns_port, dns_path); + if (ret) + goto out; + +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 = NULL; + char buf[1024]; + int offset = 0; + int n; + char *p, *foo; + size_t len; + + if(dns_addr.sin_family == 0) + return NULL; /* no configured host */ + addr = dns_addr; + if (asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname) < 0) + return NULL; + 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; + } + + len = strlen(request); + if(write(s, request, len) != (ssize_t)len) { + 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; + } +} + +ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL +roken_gethostbyname(const char *hostname) +{ + struct hostent *he; + he = gethostbyname(hostname); + if(he) + return he; + return roken_gethostby(hostname); +} + +ROKEN_LIB_FUNCTION struct hostent* ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/rtbl.3 b/third_party/heimdal/lib/roken/rtbl.3 new file mode 100644 index 0000000..0d70918 --- /dev/null +++ b/third_party/heimdal/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$ +.\" +.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 +widths 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/third_party/heimdal/lib/roken/rtbl.c b/third_party/heimdal/lib/roken/rtbl.c new file mode 100644 index 0000000..efcf55e --- /dev/null +++ b/third_party/heimdal/lib/roken/rtbl.c @@ -0,0 +1,558 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <ctype.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; +}; + +ROKEN_LIB_FUNCTION rtbl_t ROKEN_LIB_CALL +rtbl_create (void) +{ + return calloc (1, sizeof (struct rtbl_data)); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rtbl_set_flags (rtbl_t table, unsigned int flags) +{ + table->flags = flags; +} + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +rtbl_get_flags (rtbl_t table) +{ + return table->flags; +} + +static struct column_data * +rtbl_get_column_by_id (rtbl_t table, unsigned int id) +{ + size_t 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) +{ + size_t i; + for(i = 0; i < table->num_columns; i++) + if(strcmp(table->columns[i]->header, column) == 0) + return table->columns[i]; + return NULL; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rtbl_destroy (rtbl_t table) +{ + size_t 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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column (rtbl_t table, const char *header, unsigned int flags) +{ + return rtbl_add_column_by_id(table, 0, header, flags); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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[0])); + 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) +{ + size_t i; + + if(table->flags & RTBL_HEADER_STYLE_NONE) + column->width = 0; + else + column->width = (int)strlen (column->header); + for (i = 0; i < column->num_rows; i++) + column->width = max (column->width, (int) strlen (column->rows[i].data)); +} + +/* DEPRECATED */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_format (rtbl_t table, FILE * f) +{ + char *str = rtbl_format_str(table); + if (str == NULL) + return ENOMEM; + fprintf(f, "%s", str); + free(str); + return 0; +} + +static char * +rtbl_format_pretty(rtbl_t table) +{ + struct rk_strpool *p = NULL; + size_t 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) + p = rk_strpoolprintf(p, "%s", table->column_separator); + p = rk_strpoolprintf(p, "%s", get_column_prefix (table, c)); + if (c == NULL) { + /* do nothing if no column */ + } else if(i == table->num_columns - 1 && c->suffix == NULL) + /* last column, so no need to pad with spaces */ + p = rk_strpoolprintf(p, "%-*s", 0, c->header); + else + p = rk_strpoolprintf(p, "%-*s", (int)c->width, c->header); + p = rk_strpoolprintf(p, "%s", get_column_suffix (table, c)); + } + p = rk_strpoolprintf(p, "\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) + p = rk_strpoolprintf(p, "%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; + } + p = rk_strpoolprintf(p, "%s", get_column_prefix (table, c)); + if (c->num_rows <= j) + p = rk_strpoolprintf(p, "%*s", w, ""); + else + p = rk_strpoolprintf(p, "%*s", w, c->rows[j].data); + p = rk_strpoolprintf(p, "%s", get_column_suffix (table, c)); + } + p = rk_strpoolprintf(p, "\n"); + } + + return rk_strpoolcollect(p); +} + +static char * +rtbl_format_json(rtbl_t table) +{ + struct rk_strpool *p = NULL; + size_t i, j; + int comma; + + p = rk_strpoolprintf(p, "["); + 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; + + p = rk_strpoolprintf(p, "%s{", j > 0 ? "," : ""); + + comma = 0; + for (i = 0; i < table->num_columns; i++) { + struct column_data *c = table->columns[i]; + + if (c->num_rows > j) { + char *header = c->header; + while (isspace((int)header[0])) /* trim off prefixed whitespace */ + header++; + p = rk_strpoolprintf(p, "%s\"%s\" : \"%s\"", + comma ? "," : "", header, + c->rows[j].data); + comma = 1; + } + } + p = rk_strpoolprintf(p, "}"); + } + p = rk_strpoolprintf(p, "]"); + + return rk_strpoolcollect(p); +} + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rtbl_format_str (rtbl_t table) +{ + if (table->flags & RTBL_JSON) + return rtbl_format_json(table); + + return rtbl_format_pretty(table); +} + +#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/third_party/heimdal/lib/roken/rtbl.h b/third_party/heimdal/lib/roken/rtbl.h new file mode 100644 index 0000000..274f75c --- /dev/null +++ b/third_party/heimdal/lib/roken/rtbl.h @@ -0,0 +1,124 @@ +/* + * 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$ */ + +#ifndef __rtbl_h__ +#define __rtbl_h__ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#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 +#define RTBL_JSON 2 + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column (rtbl_t, const char*, unsigned int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column_by_id (rtbl_t, unsigned int, const char*, unsigned int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column_entryv_by_id (rtbl_t table, unsigned int id, + const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 0))); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column_entry (rtbl_t, const char*, const char*); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column_entryv (rtbl_t, const char*, const char*, ...) + __attribute__ ((__format__ (__printf__, 3, 0))); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_add_column_entry_by_id (rtbl_t, unsigned int, const char*); + +ROKEN_LIB_FUNCTION rtbl_t ROKEN_LIB_CALL +rtbl_create (void); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rtbl_destroy (rtbl_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_format (rtbl_t, FILE*); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rtbl_format_str (rtbl_t); + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +rtbl_get_flags (rtbl_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_new_row (rtbl_t); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_set_column_affix_by_id (rtbl_t, unsigned int, const char*, const char*); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_set_column_prefix (rtbl_t, const char*, const char*); + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rtbl_set_flags (rtbl_t, unsigned int); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_set_prefix (rtbl_t, const char*); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rtbl_set_separator (rtbl_t, const char*); + +#ifdef __cplusplus +} +#endif + +#endif /* __rtbl_h__ */ diff --git a/third_party/heimdal/lib/roken/search.hin b/third_party/heimdal/lib/roken/search.hin new file mode 100644 index 0000000..f8592c4 --- /dev/null +++ b/third_party/heimdal/lib/roken/search.hin @@ -0,0 +1,44 @@ +/*- + * Written by J.T. Conklin <jtc@netbsd.org> + * Public domain. + * + * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ + */ + +#ifndef _rk_SEARCH_H_ +#define _rk_SEARCH_H_ 1 + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#ifndef _WIN32 +#include <sys/cdefs.h> +#endif +#include <sys/types.h> + +typedef enum { + preorder, + postorder, + endorder, + leaf +} VISIT; + +ROKEN_CPP_START + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tdelete(const void *, void **, + int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tfind(const void *, void * const *, + int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tsearch(const void *, void **, int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rk_twalk(const void *, void (*)(const void *, VISIT, int)); + +ROKEN_CPP_END + +#endif /* !_rk_SEARCH_H_ */ diff --git a/third_party/heimdal/lib/roken/secure_getenv.c b/third_party/heimdal/lib/roken/secure_getenv.c new file mode 100644 index 0000000..d97d03d --- /dev/null +++ b/third_party/heimdal/lib/roken/secure_getenv.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 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. + */ + +#include <config.h> + +#include <errno.h> + +#include "roken.h" +#include "secure_getenv.h" + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_secure_getenv(const char *name) +{ + if (issuid()) + return NULL; + return getenv(name); +} diff --git a/third_party/heimdal/lib/roken/secure_getenv.h b/third_party/heimdal/lib/roken/secure_getenv.h new file mode 100644 index 0000000..a3f5363 --- /dev/null +++ b/third_party/heimdal/lib/roken/secure_getenv.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 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. + */ + +#include <config.h> + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_secure_getenv(const char *); + +#ifndef HAVE_SECURE_GETENV +#undef secure_getenv +#define secure_getenv(e) rk_secure_getenv(e) +#endif diff --git a/third_party/heimdal/lib/roken/sendmsg.c b/third_party/heimdal/lib/roken/sendmsg.c new file mode 100644 index 0000000..c685377 --- /dev/null +++ b/third_party/heimdal/lib/roken/sendmsg.c @@ -0,0 +1,148 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef _WIN32 + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +sendmsg(rk_socket_t 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; +} + +#else /* _WIN32 */ + +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of Secure Endpoints Inc. 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + * + **********************************************************************/ + +/** + * Implementation of sendmsg() for WIN32 + * + * We are using a contrived definition of msghdr which actually uses + * an array of ::_WSABUF structures instead of ::iovec . This allows + * us to call WSASend directly using the given ::msghdr instead of + * having to allocate another array of ::_WSABUF and copying data for + * each call. + * + * Limitations: + * + * - msg->msg_name is ignored. So is msg->control. + * - WSASend() only supports ::MSG_DONTROUTE, ::MSG_OOB and + * ::MSG_PARTIAL. + * + * @param[in] s The socket to use. + * @param[in] msg The message + * @param[in] flags Flags. A combination of ::MSG_DONTROUTE, + * ::MSG_OOB and ::MSG_PARTIAL + * + * @return The number of bytes sent, on success. Or -1 on error. + */ +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags) +{ + int srv; + DWORD num_bytes_sent = 0; + + /* TODO: For _WIN32_WINNT >= 0x0600 we can use WSASendMsg using + WSAMSG which is a much more direct analogue to sendmsg(). */ + + srv = WSASend(s, msg->msg_iov, msg->msg_iovlen, + &num_bytes_sent, flags, NULL, NULL); + + if (srv == 0) + return (int) num_bytes_sent; + + /* srv == SOCKET_ERROR and WSAGetLastError() == WSA_IO_PENDING + indicates that a non-blocking transfer has been scheduled. + We'll have to check for that if we ever support non-blocking + I/O. */ + + return -1; +} + +#endif /* !_WIN32 */ diff --git a/third_party/heimdal/lib/roken/setegid.c b/third_party/heimdal/lib/roken/setegid.c new file mode 100644 index 0000000..d9aef12 --- /dev/null +++ b/third_party/heimdal/lib/roken/setegid.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. + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/setenv.c b/third_party/heimdal/lib/roken/setenv.c new file mode 100644 index 0000000..b4dbefe --- /dev/null +++ b/third_party/heimdal/lib/roken/setenv.c @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#include <config.h> + +#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. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +setenv(const char *var, const char *val, int rewrite) +{ +#ifndef _WIN32 + char *t = NULL; + + if (!rewrite && getenv(var) != 0) + return 0; + + if (asprintf (&t, "%s=%s", var, val) < 0 || t == NULL) + return -1; + + if (putenv(t) == 0) + return 0; + else + return -1; +#else /* Win32 */ + char dummy[8]; + + if (!rewrite && GetEnvironmentVariable(var, dummy, sizeof(dummy)/sizeof(char)) != 0) + return 0; + + if (SetEnvironmentVariable(var, val) == 0) + return -1; + else + return 0; +#endif +} diff --git a/third_party/heimdal/lib/roken/seteuid.c b/third_party/heimdal/lib/roken/seteuid.c new file mode 100644 index 0000000..2d8c148 --- /dev/null +++ b/third_party/heimdal/lib/roken/seteuid.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. + */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "roken.h" + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/setprogname.c b/third_party/heimdal/lib/roken/setprogname.c new file mode 100644 index 0000000..d24106a --- /dev/null +++ b/third_party/heimdal/lib/roken/setprogname.c @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifndef HAVE___PROGNAME +extern const char *__progname; +#endif + +#ifndef HAVE_SETPROGNAME + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +setprogname(const char *argv0) +{ + +#ifndef HAVE___PROGNAME + + const char *p; + if(argv0 == NULL) + return; + p = strrchr(argv0, '/'); + +#ifdef BACKSLASH_PATH_DELIM + { + const char * pb; + + pb = strrchr((p != NULL)? p : argv0, '\\'); + if (pb != NULL) + p = pb; + } +#endif + + if(p == NULL) + p = argv0; + else + p++; + +#ifdef _WIN32 + { + char * fn = strdup(p); + char * ext; + + strlwr(fn); + ext = strrchr(fn, '.'); + if (ext != NULL && strcmp(ext, ".exe") == 0) + *ext = '\0'; + + __progname = fn; + } +#else + + __progname = p; + +#endif + +#endif /* HAVE___PROGNAME */ +} + +#endif /* HAVE_SETPROGNAME */ diff --git a/third_party/heimdal/lib/roken/signal.c b/third_party/heimdal/lib/roken/signal.c new file mode 100644 index 0000000..284f1e7 --- /dev/null +++ b/third_party/heimdal/lib/roken/signal.c @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#include <config.h> + +#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? + */ + +ROKEN_LIB_FUNCTION SigAction ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/simple_exec.c b/third_party/heimdal/lib/roken/simple_exec.c new file mode 100644 index 0000000..552e121 --- /dev/null +++ b/third_party/heimdal/lib/roken/simple_exec.c @@ -0,0 +1,325 @@ +/* + * 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. + */ + +#include <config.h> + +#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: + SE_E_UNSPECIFIED on `unspecified' system errors + SE_E_FORKFAILED on fork failures + SE_E_WAITPIDFAILED on waitpid errors + SE_E_EXECTIMEOUT exec timeout + 0- is return value from subprocess + SE_E_NOEXEC if the program couldn't be executed + SE_E_NOTFOUND 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); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 = SE_E_WAITPIDFAILED; + 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 = SE_E_EXECTIMEOUT; + 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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +wait_for_process(pid_t pid) +{ + return wait_for_process_timed(pid, NULL, NULL, 0); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd, + const char *file, ...) +{ + int in_fd[2] = {-1, -1}; + int out_fd[2] = {-1, -1}; + int err_fd[2] = {-1, -1}; + pid_t pid; + va_list ap; + char **argv; + int ret = 0; + + if(stdin_fd != NULL) + ret = pipe(in_fd); + if(ret != -1 && stdout_fd != NULL) + ret = pipe(out_fd); + if(ret != -1 && stderr_fd != NULL) + ret = pipe(err_fd); + + if (ret == -1) { + close(in_fd[0]); + close(in_fd[1]); + close(out_fd[0]); + close(out_fd[1]); + close(err_fd[0]); + close(err_fd[1]); + return SE_E_UNSPECIFIED; + } + + 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 SE_E_FORKFAILED; + 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; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_FORKFAILED; + case 0: + execvp(file, args); + exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); + default: + return wait_for_process_timed(pid, func, ptr, timeout); + } +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execvp(const char *file, char *const args[]) +{ + return simple_execvp_timed(file, args, NULL, NULL, 0); +} + +/* gee, I'd like a execvpe */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_FORKFAILED; + case 0: + execve(file, args, envp); + exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); + default: + return wait_for_process_timed(pid, func, ptr, timeout); + } +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execve(const char *file, char *const args[], char *const envp[]) +{ + return simple_execve_timed(file, args, envp, NULL, NULL, 0); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_UNSPECIFIED; + ret = simple_execvp(file, argv); + free(argv); + return ret; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_UNSPECIFIED; + ret = simple_execve(file, argv, envp); + free(argv); + return ret; +} diff --git a/third_party/heimdal/lib/roken/simple_exec_w32.c b/third_party/heimdal/lib/roken/simple_exec_w32.c new file mode 100644 index 0000000..264cdb2 --- /dev/null +++ b/third_party/heimdal/lib/roken/simple_exec_w32.c @@ -0,0 +1,431 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <roken.h> +#include <strsafe.h> + +#ifndef _WIN32 +#error This implementation is Windows specific. +#endif + +/** + * wait_for_process_timed waits for a process to terminate or until a + * specified timeout occurs. + * + * @param[in] pid Process id for the monitored process + + * @param[in] func Timeout callback function. When the wait times out, + * the callback function is called. The possible return values + * from the callback function are: + * + * - ((time_t) -2) Exit loop without killing child and return SE_E_EXECTIMEOUT. + * - ((time_t) -1) Kill child with SIGTERM and wait for child to exit. + * - 0 Don't timeout again + * - n Seconds to next timeout + * + * @param[in] ptr Optional parameter for func() + * + * @param[in] timeout Seconds to first timeout. + * + * @retval SE_E_UNSPECIFIED Unspecified system error + * @retval SE_E_FORKFAILED Fork failure (not applicable for _WIN32 targets) + * @retval SE_E_WAITPIDFAILED waitpid errors + * @retval SE_E_EXECTIMEOUT exec timeout + * @retval 0 <= Return value from subprocess + * @retval SE_E_NOTFOUND The program coudln't be found + * @retval 128- The signal that killed the subprocess +128. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +wait_for_process_timed(pid_t pid, time_t (*func)(void *), + void *ptr, time_t timeout) +{ + HANDLE hProcess; + DWORD wrv = 0; + DWORD dtimeout; + int rv = 0; + + hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); + + if (hProcess == NULL) { + return SE_E_WAITPIDFAILED; + } + + dtimeout = (DWORD) ((timeout == 0)? INFINITE: timeout * 1000); + + do { + wrv = WaitForSingleObject(hProcess, dtimeout); + + if (wrv == WAIT_OBJECT_0) { + + DWORD prv = 0; + + GetExitCodeProcess(hProcess, &prv); + rv = (int) prv; + break; + + } else if (wrv == WAIT_TIMEOUT) { + + if (func == NULL) + continue; + + timeout = (*func)(ptr); + + if (timeout == (time_t)-1) { + + if (TerminateProcess(hProcess, 128 + 9)) { + dtimeout = INFINITE; + continue; + } + rv = SE_E_UNSPECIFIED; + break; + + } else if (timeout == (time_t) -2) { + + rv = SE_E_EXECTIMEOUT; + break; + + } else { + + dtimeout = (DWORD) ((timeout == 0)? INFINITE: timeout * 1000); + continue; + + } + + } else { + + rv = SE_E_UNSPECIFIED; + break; + + } + + } while(TRUE); + + CloseHandle(hProcess); + + return rv; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +wait_for_process(pid_t pid) +{ + return wait_for_process_timed(pid, NULL, NULL, 0); +} + +static char * +collect_commandline(const char * fn, va_list * ap) +{ + size_t len = 0; + size_t alloc_len = 0; + const char * s; + char * cmd = NULL; + + for (s = fn; s; s = (char *) va_arg(*ap, char *)) { + size_t cmp_len; + int need_quote = FALSE; + + if (FAILED(StringCchLength(s, MAX_PATH, &cmp_len))) { + if (cmd) + free(cmd); + return NULL; + } + + if (cmp_len == 0) + continue; + + if (strchr(s, ' ') && /* need to quote any component that + has embedded spaces, but not if + they are already quoted. */ + s[0] != '"' && + s[cmp_len - 1] != '"') { + need_quote = TRUE; + cmp_len += 2 * sizeof(char); + } + + if (s != fn) + cmp_len += 1 * sizeof(char); + + if (alloc_len < len + cmp_len + 1) { + char * nc; + + alloc_len += ((len + cmp_len - alloc_len) / MAX_PATH + 1) * MAX_PATH; + nc = (char *) realloc(cmd, alloc_len * sizeof(char)); + if (nc == NULL) { + if (cmd) + free(cmd); + return NULL; + } + cmd = nc; + } + + if (cmd == NULL) + return NULL; + + if (s != fn) + cmd[len++] = ' '; + + if (need_quote) { + StringCchPrintf(cmd + len, alloc_len - len, "\"%s\"", s); + } else { + StringCchCopy(cmd + len, alloc_len - len, s); + } + + len += cmp_len; + } + + return cmd; +} + +ROKEN_LIB_FUNCTION pid_t ROKEN_LIB_CALL +pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd, + const char *file, ...) +{ + HANDLE hOut_r = NULL; + HANDLE hOut_w = NULL; + HANDLE hIn_r = NULL; + HANDLE hIn_w = NULL; + HANDLE hErr_r = NULL; + HANDLE hErr_w = NULL; + + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + char * commandline = NULL; + + pid_t rv = (pid_t) -1; + + { + va_list ap; + + va_start(ap, file); + commandline = collect_commandline(file, &ap); + + if (commandline == NULL) + return rv; + } + + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&sa, sizeof(sa)); + + pi.hProcess = NULL; + pi.hThread = NULL; + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + if ((stdout_fd && !CreatePipe(&hOut_r, &hOut_w, &sa, 0 /* Use default */)) || + + (stdin_fd && !CreatePipe(&hIn_r, &hIn_w, &sa, 0)) || + + (stderr_fd && !CreatePipe(&hErr_r, &hErr_w, &sa, 0)) || + + (!stdout_fd && (hOut_w = CreateFile("CON", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) || + + (!stdin_fd && (hIn_r = CreateFile("CON",GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) || + + (!stderr_fd && (hErr_w = CreateFile("CON", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)) + + goto _exit; + + /* We don't want the child processes inheriting these */ + if (hOut_r) + SetHandleInformation(hOut_r, HANDLE_FLAG_INHERIT, FALSE); + + if (hIn_w) + SetHandleInformation(hIn_w, HANDLE_FLAG_INHERIT, FALSE); + + if (hErr_r) + SetHandleInformation(hErr_r, HANDLE_FLAG_INHERIT, FALSE); + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = hIn_r; + si.hStdOutput = hOut_w; + si.hStdError = hErr_w; + + if (!CreateProcess(file, commandline, NULL, NULL, + TRUE, /* bInheritHandles */ + CREATE_NO_WINDOW, /* dwCreationFlags */ + NULL, /* lpEnvironment */ + NULL, /* lpCurrentDirectory */ + &si, + &pi)) { + + rv = (pid_t) (GetLastError() == ERROR_FILE_NOT_FOUND)? 127 : -1; + goto _exit; + } + + if (stdin_fd) { + *stdin_fd = _fdopen(_open_osfhandle((intptr_t) hIn_w, 0), "wb"); + if (*stdin_fd) + hIn_w = NULL; + } + + if (stdout_fd) { + *stdout_fd = _fdopen(_open_osfhandle((intptr_t) hOut_r, _O_RDONLY), "rb"); + if (*stdout_fd) + hOut_r = NULL; + } + + if (stderr_fd) { + *stderr_fd = _fdopen(_open_osfhandle((intptr_t) hErr_r, _O_RDONLY), "rb"); + if (*stderr_fd) + hErr_r = NULL; + } + + rv = (pid_t) pi.dwProcessId; + + _exit: + + if (pi.hProcess) CloseHandle(pi.hProcess); + + if (pi.hThread) CloseHandle(pi.hThread); + + if (hIn_r) CloseHandle(hIn_r); + + if (hIn_w) CloseHandle(hIn_w); + + if (hOut_r) CloseHandle(hOut_r); + + if (hOut_w) CloseHandle(hOut_w); + + if (hErr_r) CloseHandle(hErr_r); + + if (hErr_w) CloseHandle(hErr_w); + + return rv; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execvp_timed(const char *file, char *const args[], + time_t (*func)(void *), void *ptr, time_t timeout) +{ + intptr_t hp; + int rv; + + hp = spawnvp(_P_NOWAIT, file, args); + + if (hp == -1) + return (errno == ENOENT)? 127: 126; + else if (hp == 0) + return 0; + + rv = wait_for_process_timed(GetProcessId((HANDLE) hp), func, ptr, timeout); + + CloseHandle((HANDLE) hp); + + return rv; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execvp(const char *file, char *const args[]) +{ + return simple_execvp_timed(file, args, NULL, NULL, 0); +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execve_timed(const char *file, char *const args[], char *const envp[], + time_t (*func)(void *), void *ptr, time_t timeout) +{ + intptr_t hp; + int rv; + + hp = spawnve(_P_NOWAIT, file, args, envp); + + if (hp == -1) + return (errno == ENOENT)? 127: 126; + else if (hp == 0) + return 0; + + rv = wait_for_process_timed(GetProcessId((HANDLE) hp), func, ptr, timeout); + + CloseHandle((HANDLE) hp); + + return rv; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +simple_execve(const char *file, char *const args[], char *const envp[]) +{ + return simple_execve_timed(file, args, envp, NULL, NULL, 0); +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_UNSPECIFIED; + ret = simple_execvp(file, argv); + free(argv); + return ret; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 SE_E_UNSPECIFIED; + ret = simple_execve(file, argv, envp); + free(argv); + return ret; +} diff --git a/third_party/heimdal/lib/roken/sleep.c b/third_party/heimdal/lib/roken/sleep.c new file mode 100644 index 0000000..53f416e --- /dev/null +++ b/third_party/heimdal/lib/roken/sleep.c @@ -0,0 +1,55 @@ +/*********************************************************************** + * Copyright (c) 2009, 2014, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <roken.h> + +#ifndef _WIN32 +#error Only implemented on Windows +#endif + +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +sleep(unsigned int seconds) +{ + if (SleepEx(1000 * (DWORD) seconds, FALSE) != 0) + return 1; /* XXX Should get time before and after */ + return 0; +} + +/* We can only sleep in millisecond increments */ +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +usleep(unsigned int useconds) +{ + if (SleepEx((DWORD)(useconds / 1000), FALSE) != 0) + return 1000; /* XXX Should get time before and after */ + return 0; +} diff --git a/third_party/heimdal/lib/roken/snprintf-test.c b/third_party/heimdal/lib/roken/snprintf-test.c new file mode 100644 index 0000000..e51402d --- /dev/null +++ b/third_party/heimdal/lib/roken/snprintf-test.c @@ -0,0 +1,268 @@ +/* + * 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. */ + +#include <config.h> +#include "roken.h" +#include <limits.h> + +extern int rk_snprintf(char *, size_t, const char *, ...); +extern int rk_vsnprintf(char *, size_t, const char *, va_list); + +static int +try (const char *format, ...) +{ + int ret; + va_list ap; + char buf1[256], buf2[256]; + + va_start (ap, format); + ret = rk_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) - (sizeof(long long) > sizeof(long)), + LONG_MIN, -17, -1, 0, 1, 17, 4711, 65535, LONG_MAX, + ((long long)LONG_MAX) + (sizeof(long long) > sizeof(long)) + }; + 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 rk_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]; + rk_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/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c new file mode 100644 index 0000000..3da4896 --- /dev/null +++ b/third_party/heimdal/lib/roken/snprintf.c @@ -0,0 +1,700 @@ +/* + * 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. + */ + +#include <config.h> +#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 + +#ifndef HAVE_UINTPTR_T +typedef u_longest uintptr_t; +#endif + + + +static size_t +pad(struct snprintf_state *state, int width, char c) +{ + size_t 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 size_t +append_string (struct snprintf_state *state, + const unsigned char *arg, + int width, + int prec, + int flags) +{ + size_t 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 (prec-- && *arg) { + (*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 size_t +xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap) +{ + const unsigned char *format = (const unsigned char *)char_format; + unsigned char c; + size_t 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' : { + uintptr_t arg = (uintptr_t)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) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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) != 0) + abort (); + free (tmp); + } +#endif + + return ret; +} +#endif + +#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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) != 0) + abort (); + free (tmp); + } +#endif + + return val; +} +#endif + +#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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) != 0) + abort (); + free (tmp); + } +#endif + + va_end(args); + return val; +} +#endif + +#if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_vasprintf (char **ret, const char *format, va_list args) +{ + return vasnprintf (ret, 0, format, args); +} +#endif + + +#if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) +{ + size_t 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) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/socket.c b/third_party/heimdal/lib/roken/socket.c new file mode 100644 index 0000000..a790e08 --- /dev/null +++ b/third_party/heimdal/lib/roken/socket.c @@ -0,0 +1,371 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <err.h> + +/* + * Set `sa' to the unitialized address of address family `af' + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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') + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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' + */ + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +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 : + return 0; + } +} + +/* + * Return the size of a `struct sockaddr' in `sa'. + */ + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +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: + return 0; + } +} + +/* + * Return the binary address of `sa'. + */ + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +socket_get_address (const struct sockaddr *sa) +{ + switch (sa->sa_family) { + case AF_INET : { + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + return rk_UNCONST(&sin4->sin_addr); + } +#ifdef HAVE_IPV6 + case AF_INET6 : { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + return rk_UNCONST(&sin6->sin6_addr); + } +#endif + default: + return NULL; + } +} + +/* + * Return the port number from `sa'. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 : + return 0; + } +} + +/* + * Set the port in `sa' to `port'. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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. + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_portrange (rk_socket_t sock, int restr, int af) +{ +#if defined(IP_PORTRANGE) + if (af == AF_INET) { + int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; + (void) setsockopt(sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on)); + } +#endif +#if defined(IPV6_PORTRANGE) + if (af == AF_INET6) { + int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT; + (void) setsockopt(sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on)); + } +#endif +} + +/* + * Enable debug on `sock'. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_debug (rk_socket_t sock) +{ +#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) + int on = 1; + (void) setsockopt(sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)); +#endif +} + +/* + * Set the type-of-service of `sock' to `tos'. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_tos (rk_socket_t sock, int tos) +{ +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + (void) setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int)); +#endif +} + +/* + * Set the non-blocking-ness of the socket. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_nonblocking(rk_socket_t sock, int nonblock) +{ +#if defined(O_NONBLOCK) + int flags = fcntl(sock, F_GETFL, 0); + if (flags == -1) + return; + if (nonblock) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + fcntl(sock, F_SETFL, flags); +#elif defined(FIOBIO) + int flags = !!nonblock; + return ioctl(sock, FIOBIO, &flags); +#endif +} + +/* + * set the reuse of addresses on `sock' to `val'. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_reuseaddr (rk_socket_t sock, int val) +{ +#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, + sizeof(val)); +#endif +} + +/* + * Set the that the `sock' should bind to only IPv6 addresses. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_ipv6only (rk_socket_t sock, int val) +{ +#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT) + (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, + sizeof(val)); +#endif +} + +/* + * Set the that the `sock' keepalive setting. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +socket_set_keepalive(rk_socket_t sock, int val) +{ + (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, + sizeof(val)); +} + +/** + * Create a file descriptor from a socket + * + * While the socket handle in \a sock can be used with WinSock + * functions after calling socket_to_fd(), it should not be closed + * with rk_closesocket(). The socket will be closed when the associated + * file descriptor is closed. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +socket_to_fd(rk_socket_t sock, int flags) +{ +#ifndef _WIN32 + return sock; +#else + return _open_osfhandle((intptr_t) sock, flags); +#endif +} + +#ifdef HAVE_WINSOCK +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) { + u_long ul = (argp)? *argp : 0; + int rv; + + rv = ioctlsocket(s, cmd, &ul); + if (argp) + *argp = (int) ul; + return rv; +} +#endif + +#ifndef HEIMDAL_SMALLER +#undef socket + +int rk_socket(int, int, int); + +int +rk_socket(int domain, int type, int protocol) +{ + int s; + s = socket (domain, type, protocol); +#ifdef SOCK_CLOEXEC + if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) { + type &= ~SOCK_CLOEXEC; + s = socket (domain, type, protocol); + } +#endif + return s; +} + +#endif /* HEIMDAL_SMALLER */ diff --git a/third_party/heimdal/lib/roken/socket_wrapper.c b/third_party/heimdal/lib/roken/socket_wrapper.c new file mode 100644 index 0000000..9438949 --- /dev/null +++ b/third_party/heimdal/lib/roken/socket_wrapper.c @@ -0,0 +1,1911 @@ +/* + * 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_ */ + +#include <config.h> +#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/third_party/heimdal/lib/roken/socket_wrapper.h b/third_party/heimdal/lib/roken/socket_wrapper.h new file mode 100644 index 0000000..06fd633 --- /dev/null +++ b/third_party/heimdal/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/third_party/heimdal/lib/roken/sockstartup_w32.c b/third_party/heimdal/lib/roken/sockstartup_w32.c new file mode 100644 index 0000000..35eb3ae --- /dev/null +++ b/third_party/heimdal/lib/roken/sockstartup_w32.c @@ -0,0 +1,75 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <roken.h> + +#ifndef _WIN32 +#error Only implemented for Windows +#endif + +volatile LONG _startup_count = 0; + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_WSAStartup(void) +{ + WSADATA wsad; + + if (!WSAStartup( MAKEWORD(2, 2), &wsad )) { + if (wsad.wVersion != MAKEWORD(2, 2)) { + /* huh? We can't use 2.2? */ + WSACleanup(); + return -1; + } + + InterlockedIncrement(&_startup_count); + return 0; + } + + return -1; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_WSACleanup(void) +{ + LONG l; + + if ((l = InterlockedDecrement(&_startup_count)) < 0) { + l = InterlockedIncrement(&_startup_count) - 1; + } + + if (l >= 0) { + return WSACleanup(); + } + return -1; +} diff --git a/third_party/heimdal/lib/roken/stdbool.hin b/third_party/heimdal/lib/roken/stdbool.hin new file mode 100644 index 0000000..cdaee5b --- /dev/null +++ b/third_party/heimdal/lib/roken/stdbool.hin @@ -0,0 +1,13 @@ +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#ifndef __GNUC__ +typedef int _Bool; +#endif + +#define bool _Bool +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H */ diff --git a/third_party/heimdal/lib/roken/stdint.hin b/third_party/heimdal/lib/roken/stdint.hin new file mode 100644 index 0000000..e552d9d --- /dev/null +++ b/third_party/heimdal/lib/roken/stdint.hin @@ -0,0 +1,43 @@ +#ifndef _STDINT_H +#define _STDINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int int16_t; +typedef unsigned short int uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +#ifdef _MSC_VER +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#ifdef _MSC_VER +#include <intsafe.h> +#else +#define INT8_MAX 0x7F +#define INT8_MIN (-INT8_MAX - 1) +#define UINT8_MAX 0xFF +#define INT16_MAX 0x7FFF +#define INT16_MIN (-INT16_MAX - 1) +#define UINT16_MAX 0xFFFF +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN (-INT32_MIN - 1) +#define UINT32_MAX 0xFFFFFFFF +#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL +#define INT64_MIN (-INT64_MAX - 1) +#define UINT64_MAX 0xFFFFFFFFFFFFFFFFLL +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _STDINT_H */ diff --git a/third_party/heimdal/lib/roken/strcasecmp.c b/third_party/heimdal/lib/roken/strcasecmp.c new file mode 100644 index 0000000..00a0a8e --- /dev/null +++ b/third_party/heimdal/lib/roken/strcasecmp.c @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include <config.h> + +#include <string.h> +#include <ctype.h> +#include <stddef.h> +#include "roken.h" + +#ifndef HAVE_STRCASECMP + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strcollect.c b/third_party/heimdal/lib/roken/strcollect.c new file mode 100644 index 0000000..0afc3f0 --- /dev/null +++ b/third_party/heimdal/lib/roken/strcollect.c @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#include <config.h> + +#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. + */ + +ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL +vstrcollect(va_list *ap) +{ + return sub (NULL, 0, 0, ap); +} + +/* + * + */ + +ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strdup.c b/third_party/heimdal/lib/roken/strdup.c new file mode 100644 index 0000000..ce00456 --- /dev/null +++ b/third_party/heimdal/lib/roken/strdup.c @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> + +#ifndef HAVE_STRDUP +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +strdup(const char *old) +{ + char *t = malloc(strlen(old)+1); + if (t != 0) + strcpy(t, old); + return t; +} +#endif diff --git a/third_party/heimdal/lib/roken/strerror.c b/third_party/heimdal/lib/roken/strerror.c new file mode 100644 index 0000000..b5ec691 --- /dev/null +++ b/third_party/heimdal/lib/roken/strerror.c @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +extern int sys_nerr; +extern char *sys_errlist[]; + +ROKEN_LIB_FUNCTION char* ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strerror_r.c b/third_party/heimdal/lib/roken/strerror_r.c new file mode 100644 index 0000000..85271ec --- /dev/null +++ b/third_party/heimdal/lib/roken/strerror_r.c @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#include <config.h> + +#if (!defined(HAVE_STRERROR_R) && !defined(strerror_r)) || (!defined(STRERROR_R_PROTO_COMPATIBLE) && defined(HAVE_STRERROR_R)) + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "roken.h" + +#ifdef _MSC_VER + +int ROKEN_LIB_FUNCTION +rk_strerror_r(int eno, char * strerrbuf, size_t buflen) +{ + errno_t err; + + err = strerror_s(strerrbuf, buflen, eno); + if (err != 0) { + int code; + code = sprintf_s(strerrbuf, buflen, "Error % occurred.", eno); + err = ((code != 0)? errno : 0); + } + + return err; +} + +#else /* _MSC_VER */ + +int ROKEN_LIB_FUNCTION +rk_strerror_r(int eno, char *strerrbuf, size_t buflen) +{ + /* Assume is the linux broken strerror_r (returns the a buffer (char *) if the input buffer wasn't use */ +#ifdef HAVE_STRERROR_R + const char *str; + str = strerror_r(eno, strerrbuf, buflen); + if (str != strerrbuf) + if (strlcpy(strerrbuf, str, buflen) >= buflen) + return ERANGE; + return 0; +#else + int ret; + ret = strlcpy(strerrbuf, strerror(eno), buflen); + if (ret > buflen) + return ERANGE; + return 0; +#endif +} + +#endif /* !_MSC_VER */ + +#endif diff --git a/third_party/heimdal/lib/roken/strftime.c b/third_party/heimdal/lib/roken/strftime.c new file mode 100644 index 0000000..9a951dd --- /dev/null +++ b/third_party/heimdal/lib/roken/strftime.c @@ -0,0 +1,402 @@ +/* + * 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. */ + +#include <config.h> +#include "roken.h" +#ifdef TEST_STRPFTIME +#include "strpftime-test.h" +#endif + +#if defined(_WIN32) +# define timezone _timezone +# define tzname _tzname +#endif + +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; +} + +/* + * + */ + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +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); + break; + 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 >= (int)(maxsize - n)) + return 0; + n += ret; + buf += ret; + ++format; + } else { + *buf++ = *format++; + ++n; + } + } + *buf = '\0'; + return n; +} diff --git a/third_party/heimdal/lib/roken/strlcat.c b/third_party/heimdal/lib/roken/strlcat.c new file mode 100644 index 0000000..e8fe1b7 --- /dev/null +++ b/third_party/heimdal/lib/roken/strlcat.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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_STRLCAT + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strlcat (char *dst, const char *src, size_t dst_sz) +{ + size_t len; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + len = strnlen_s(dst, dst_sz); +#elif defined(HAVE_STRNLEN) + len = strnlen(dst, dst_sz); +#else + len = strlen(dst); +#endif + + 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/third_party/heimdal/lib/roken/strlcpy.c b/third_party/heimdal/lib/roken/strlcpy.c new file mode 100644 index 0000000..0fe2b97 --- /dev/null +++ b/third_party/heimdal/lib/roken/strlcpy.c @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_STRLCPY + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strlcpy (char *dst, const char *src, size_t dst_cch) +{ + errno_t e; + + if (dst_cch > 0) + e = strncpy_s(dst, dst_cch, src, _TRUNCATE); + + return strlen (src); +} + +#else + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +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 + +#endif diff --git a/third_party/heimdal/lib/roken/strlwr.c b/third_party/heimdal/lib/roken/strlwr.c new file mode 100644 index 0000000..68bd4ed --- /dev/null +++ b/third_party/heimdal/lib/roken/strlwr.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. + */ + +#include <config.h> +#include <string.h> +#include <ctype.h> + +#include "roken.h" + +#ifndef HAVE_STRLWR +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +strlwr(char *str) +{ + char *s; + + for(s = str; *s; s++) + *s = tolower((unsigned char)*s); + return str; +} +#endif diff --git a/third_party/heimdal/lib/roken/strncasecmp.c b/third_party/heimdal/lib/roken/strncasecmp.c new file mode 100644 index 0000000..f244fb5 --- /dev/null +++ b/third_party/heimdal/lib/roken/strncasecmp.c @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#include <config.h> + +#include <string.h> +#include <ctype.h> +#include <stddef.h> + +#ifndef HAVE_STRNCASECMP + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strndup.c b/third_party/heimdal/lib/roken/strndup.c new file mode 100644 index 0000000..e67c998 --- /dev/null +++ b/third_party/heimdal/lib/roken/strndup.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRNDUP +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strnlen.c b/third_party/heimdal/lib/roken/strnlen.c new file mode 100644 index 0000000..f26cd84 --- /dev/null +++ b/third_party/heimdal/lib/roken/strnlen.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strnlen(const char *s, size_t len) +{ + size_t i; + + for(i = 0; i < len && s[i]; i++) + ; + return i; +} diff --git a/third_party/heimdal/lib/roken/strpftime-test.c b/third_party/heimdal/lib/roken/strpftime-test.c new file mode 100644 index 0000000..8524ff5 --- /dev/null +++ b/third_party/heimdal/lib/roken/strpftime-test.c @@ -0,0 +1,295 @@ +/* + * 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. */ + +#include <config.h> +#include <roken.h> +#ifdef TEST_STRPFTIME +#include "strpftime-test.h" +#endif + +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/third_party/heimdal/lib/roken/strpftime-test.h b/third_party/heimdal/lib/roken/strpftime-test.h new file mode 100644 index 0000000..157c776 --- /dev/null +++ b/third_party/heimdal/lib/roken/strpftime-test.h @@ -0,0 +1,61 @@ +/* + * 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 + */ + +#ifdef strftime +#undef strftime +#endif +#define strftime test_strftime +#ifdef strptime +#undef strptime +#endif +#define strptime test_strptime + +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strftime (char *buf, size_t maxsize, const char *format, + const struct tm *tm); + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +strptime (const char *buf, const char *format, struct tm *timeptr); + +#endif /* __STRFTIME_TEST_H__ */ diff --git a/third_party/heimdal/lib/roken/strpool.c b/third_party/heimdal/lib/roken/strpool.c new file mode 100644 index 0000000..032bae1 --- /dev/null +++ b/third_party/heimdal/lib/roken/strpool.c @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdarg.h> +#include <stdlib.h> +#include "roken.h" + +struct rk_strpool { + char *str; + size_t len; /* strlen() of str */ + size_t sz; /* Allocated size */ +}; + +/* + * + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_strpoolfree(struct rk_strpool *p) +{ + if (p && p->str) { + free(p->str); + p->str = NULL; + } + free(p); +} + +/* + * + */ + +ROKEN_LIB_FUNCTION struct rk_strpool * ROKEN_LIB_CALL +rk_strpoolprintf(struct rk_strpool *p, const char *fmt, ...) +{ + va_list ap; + char *str; + int len; + + va_start(ap, fmt); + len = vasprintf(&str, fmt, ap); + va_end(ap); + if (str == NULL) + return rk_strpoolfree(p), NULL; + + if (p == NULL) { + if ((p = malloc(sizeof(*p))) == NULL) + return free(str), NULL; + p->str = str; + p->len = p->sz = len; + return p; + } /* else grow the buffer and append `str', but don't grow too fast */ + + if (len + p->len + 1 > p->sz) { + size_t sz = p->len + len + 9 + (p->sz >> 2); + char *str2; + + if ((str2 = realloc(p->str, sz)) == NULL) + return rk_strpoolfree(p), NULL; + p->str = str2; + p->sz = sz; + } + memcpy(p->str + p->len, str, len + 1); + p->len += len; + free(str); + return p; +} + +/* + * + */ + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_strpoolcollect(struct rk_strpool *p) +{ + char *str; + if (p == NULL) + return strdup(""); + str = p->str; + p->str = NULL; + free(p); + return str; +} diff --git a/third_party/heimdal/lib/roken/strptime.c b/third_party/heimdal/lib/roken/strptime.c new file mode 100644 index 0000000..86216d2 --- /dev/null +++ b/third_party/heimdal/lib/roken/strptime.c @@ -0,0 +1,449 @@ +/* + * 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. */ + +#include <config.h> +#include "roken.h" +#ifdef TEST_STRPFTIME +#include "strpftime-test.h" +#endif +#include <ctype.h> + +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 + (is_leap_year (year) ? 366 : 365)) % 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; + } +} + +/* + * + */ + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strsep.c b/third_party/heimdal/lib/roken/strsep.c new file mode 100644 index 0000000..76b447c --- /dev/null +++ b/third_party/heimdal/lib/roken/strsep.c @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include <config.h> + +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRSEP + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strsep_copy.c b/third_party/heimdal/lib/roken/strsep_copy.c new file mode 100644 index 0000000..1228f1a --- /dev/null +++ b/third_party/heimdal/lib/roken/strsep_copy.c @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <config.h> + +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRSEP_COPY + +/* strsep, but with const stringp, so return string in buf */ + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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, (size_t)(*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/third_party/heimdal/lib/roken/strtok_r.c b/third_party/heimdal/lib/roken/strtok_r.c new file mode 100644 index 0000000..16a9daf --- /dev/null +++ b/third_party/heimdal/lib/roken/strtok_r.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. + */ + +#include <config.h> + +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRTOK_R + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/strtoll.c b/third_party/heimdal/lib/roken/strtoll.c new file mode 100644 index 0000000..96c1b25 --- /dev/null +++ b/third_party/heimdal/lib/roken/strtoll.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * 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. + */ + +#include <config.h> + +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRTOLL + +/* #include <sys/cdefs.h> */ + +#include <limits.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdint.h> + +/* + * Convert a string to a long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +ROKEN_LIB_FUNCTION long long ROKEN_LIB_CALL +strtoll(const char * nptr, char ** endptr, int base) +{ + const char *s; + unsigned long long acc; + long long ret = 0; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX + : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + ret = neg ? LLONG_MIN : LLONG_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) { + ret = -(long long)acc; + } else { + ret = acc; + } + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return ret; +} +#endif /* !HAVE_STRTOLL */ diff --git a/third_party/heimdal/lib/roken/strtoull.c b/third_party/heimdal/lib/roken/strtoull.c new file mode 100644 index 0000000..0516e18 --- /dev/null +++ b/third_party/heimdal/lib/roken/strtoull.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * 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. + */ + +#include <config.h> + +#include <string.h> + +#include "roken.h" + +#ifndef HAVE_STRTOULL + +/* #include <sys/cdefs.h> */ + +#include <limits.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdint.h> + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +ROKEN_LIB_FUNCTION unsigned long long ROKEN_LIB_CALL +strtoull(const char * nptr, char ** endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = -(long long)acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} +#endif /* !HAVE_STRTOULL */ diff --git a/third_party/heimdal/lib/roken/strupr.c b/third_party/heimdal/lib/roken/strupr.c new file mode 100644 index 0000000..fdff7f4 --- /dev/null +++ b/third_party/heimdal/lib/roken/strupr.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. + */ + +#include <config.h> +#include <string.h> +#include <ctype.h> + +#include "roken.h" + +#ifndef HAVE_STRUPR +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +strupr(char *str) +{ + char *s; + + for(s = str; *s; s++) + *s = toupper((unsigned char)*s); + return str; +} +#endif diff --git a/third_party/heimdal/lib/roken/swab.c b/third_party/heimdal/lib/roken/swab.c new file mode 100644 index 0000000..9b8d1d1 --- /dev/null +++ b/third_party/heimdal/lib/roken/swab.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. + */ + +#include <config.h> +#include "roken.h" + +#ifndef HAVE_SWAB + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/syslog.hin b/third_party/heimdal/lib/roken/syslog.hin new file mode 100644 index 0000000..f68dd11 --- /dev/null +++ b/third_party/heimdal/lib/roken/syslog.hin @@ -0,0 +1,248 @@ +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 _SYS_SYSLOG_H +#define _SYS_SYSLOG_H 1 + +#include <stdarg.h> + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) + +#ifdef SYSLOG_NAMES +#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ + /* mark "facility" */ +#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) +typedef struct _code { + char *c_name; + int c_val; +} CODE; + +CODE prioritynames[] = + { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "error", LOG_ERR }, /* DEPRECATED */ + { "info", LOG_INFO }, + { "none", INTERNAL_NOPRI }, /* INTERNAL */ + { "notice", LOG_NOTICE }, + { "panic", LOG_EMERG }, /* DEPRECATED */ + { "warn", LOG_WARNING }, /* DEPRECATED */ + { "warning", LOG_WARNING }, + { NULL, -1 } + }; +#endif + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#ifdef SYSLOG_NAMES +CODE facilitynames[] = + { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "mark", INTERNAL_MARK }, /* INTERNAL */ + { "news", LOG_NEWS }, + { "security", LOG_AUTH }, /* DEPRECATED */ + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 } + }; +#endif + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + * + * LOG_ODELAY no longer does anything. + * LOG_NDELAY is the inverse of what it used to be. + */ +#define LOG_PID 0x01 /* log the pid with each message */ +#define LOG_CONS 0x02 /* log on the console if errors in sending */ +#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ +#define LOG_NDELAY 0x08 /* don't delay open */ +#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ +#define LOG_PERROR 0x20 /* log to stderr as well */ + +#define SYSLOG_PORT 514 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Close desriptor used to write to system logger. */ +extern void closelog (void); + +/* Open connection to system logger. */ +extern void openlog (char *__ident, int __option, int __facility); + +/* Set the log mask level. */ +extern int setlogmask (int __mask); + +/* Generate a log message using FMT string and option arguments. */ +extern void syslog (int __pri, char *__fmt, ...); + +/* Generate a log message using FMT and using arguments pointed to by AP. */ +extern void vsyslog (int __pri, char *__fmt, va_list __ap); + +#ifdef _WIN32 + /* Windows specific. + + init_syslog() *must* be called before calling any of the above + functions. exit_syslog() will be scheduled using atexit(). + However, it is not an error and encouraged to call + exit_syslog() before the application exits. + + During operation, the application is free to call exit_syslog() + followed by init_syslog() to re-initialize the library. i.e. if + a different syslog host is to be used. + + */ + + /* Initializes the syslog library and sets the syslog host. The + hostname parameter is of the form "<hostname>[:<port>]". The + <port> may be a numeric port or it may be a name of a service. + If the <port> is specified using a service name, it will be + looked up using getservbyname(). + + On failure, the hostname and port will be set to "localhost" + and SYSLOG_PORT respectively. + */ + extern void init_syslog(const char * hostname); + + extern void exit_syslog(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* syslog.h */ diff --git a/third_party/heimdal/lib/roken/syslogc.c b/third_party/heimdal/lib/roken/syslogc.c new file mode 100644 index 0000000..f4fb539 --- /dev/null +++ b/third_party/heimdal/lib/roken/syslogc.c @@ -0,0 +1,339 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + * + **********************************************************************/ + +/* + * Based on code by Alexander Yaworsky + */ + +#include <config.h> + +#include <roken.h> + +#define SYSLOG_DGRAM_SIZE 1024 + +static BOOL syslog_opened = FALSE; + +static int syslog_mask = 0xFF; +static char syslog_ident[ 128 ] = ""; +static int syslog_facility = LOG_USER; +static char syslog_procid_str[ 20 ]; + +static SOCKADDR_IN syslog_hostaddr; +static SOCKET syslog_socket = INVALID_SOCKET; +static char local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ]; + +static char syslog_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ] = "localhost"; +static unsigned short syslog_port = SYSLOG_PORT; + +static int datagramm_size; + +volatile BOOL initialized = FALSE; +BOOL wsa_initialized = FALSE; +CRITICAL_SECTION cs_syslog; + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +init_syslog(const char * hostname) +{ + WSADATA wsd; + char * service; + + if ( initialized ) + return; + + if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) ) { + fprintf(stderr, "Can't initialize WinSock\n"); + /* we let the rest of the initialization code go through, + although none of the syslog calls would succeed. */ + } else { + wsa_initialized = TRUE; + } + + if (hostname) + strcpy_s(syslog_hostname, sizeof(syslog_hostname), hostname); + else + strcpy_s(syslog_hostname, sizeof(syslog_hostname), ""); + + service = strchr(syslog_hostname, ':'); + + if (service) { + int tp; + + *service++ = '\0'; + + if ((tp = atoi(service)) <= 0) { + struct servent * se; + + se = getservbyname(service, "udp"); + + syslog_port = (se == NULL)? SYSLOG_PORT: se->s_port; + } else { + syslog_port = (unsigned short) tp; + } + } else { + syslog_port = SYSLOG_PORT; + } + + InitializeCriticalSection(&cs_syslog); + initialized = TRUE; + + atexit(exit_syslog); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +exit_syslog(void) +{ + if ( !initialized ) + return; + + closelog(); + + if ( wsa_initialized ) + WSACleanup(); + + DeleteCriticalSection(&cs_syslog); + initialized = FALSE; +} + +static void init_logger_addr() +{ + struct hostent * phe = NULL; + + memset( &syslog_hostaddr, 0, sizeof(SOCKADDR_IN) ); + syslog_hostaddr.sin_family = AF_INET; + + if (syslog_hostname[0] == '\0') + goto use_default; + + phe = gethostbyname( syslog_hostname ); + if( !phe ) + goto use_default; + + memcpy( &syslog_hostaddr.sin_addr.s_addr, phe->h_addr, phe->h_length ); + + syslog_hostaddr.sin_port = htons( syslog_port ); + return; + +use_default: + syslog_hostaddr.sin_addr.S_un.S_addr = htonl( 0x7F000001 ); + syslog_hostaddr.sin_port = htons( SYSLOG_PORT ); +} + +/****************************************************************************** + * closelog + * + * Close desriptor used to write to system logger. + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +closelog() +{ + if ( !initialized ) + return; + + EnterCriticalSection(&cs_syslog); + if( syslog_opened ) { + closesocket( syslog_socket ); + syslog_socket = INVALID_SOCKET; + syslog_opened = FALSE; + } + LeaveCriticalSection(&cs_syslog); +} + +/****************************************************************************** + * openlog + * + * Open connection to system logger. + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +openlog( char* ident, int option, int facility ) +{ + BOOL failed = FALSE; + SOCKADDR_IN sa_local; + DWORD n; + int size; + + if ( !initialized ) + return; + + EnterCriticalSection(&cs_syslog); + + if( syslog_opened ) + goto done; + + failed = TRUE; + + syslog_facility = facility? facility : LOG_USER; + + if( option & LOG_PID ) + sprintf_s( syslog_procid_str, sizeof(syslog_procid_str), "[%lu]", GetCurrentProcessId() ); + else + syslog_procid_str[0] = '\0'; + + /* FIXME: handle other options */ + + n = sizeof(local_hostname); + if( !GetComputerName( local_hostname, &n ) ) + goto done; + + syslog_socket = INVALID_SOCKET; + + init_logger_addr(); + + for( n = 0;; n++ ) + { + syslog_socket = socket( AF_INET, SOCK_DGRAM, 0 ); + if( INVALID_SOCKET == syslog_socket ) + goto done; + + memset( &sa_local, 0, sizeof(SOCKADDR_IN) ); + sa_local.sin_family = AF_INET; + if( bind( syslog_socket, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 ) + break; + rk_closesocket( syslog_socket ); + syslog_socket = INVALID_SOCKET; + if( n == 100 ) + goto done; + Sleep(0); + } + + /* get size of datagramm */ + size = sizeof(datagramm_size); + if( getsockopt( syslog_socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) ) + goto done; + if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 ) + goto done; + if( datagramm_size > SYSLOG_DGRAM_SIZE ) + datagramm_size = SYSLOG_DGRAM_SIZE; + + if (ident) + strcpy_s(syslog_ident, sizeof(syslog_ident), ident); + + syslog_facility = (facility ? facility : LOG_USER); + failed = FALSE; + + done: + if( failed ) { + if( syslog_socket != INVALID_SOCKET ) + rk_closesocket( syslog_socket ); + } + syslog_opened = !failed; + + LeaveCriticalSection(&cs_syslog); +} + +/****************************************************************************** + * setlogmask + * + * Set the log mask level. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +setlogmask( int mask ) +{ + int ret; + + if ( !initialized ) + return 0; + + EnterCriticalSection(&cs_syslog); + + ret = syslog_mask; + if( mask ) + syslog_mask = mask; + + LeaveCriticalSection(&cs_syslog); + + return ret; +} + +/****************************************************************************** + * syslog + * + * Generate a log message using FMT string and option arguments. + */ +ROKEN_LIB_FUNCTION void +syslog( int pri, char* fmt, ... ) +{ + va_list ap; + + va_start( ap, fmt ); + vsyslog( pri, fmt, ap ); + va_end( ap ); +} + +/****************************************************************************** + * vsyslog + * + * Generate a log message using FMT and using arguments pointed to by AP. + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vsyslog( int pri, char* fmt, va_list ap ) +{ + static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + char datagramm[ SYSLOG_DGRAM_SIZE ]; + SYSTEMTIME stm; + int len; + char *p; + + if ( !initialized ) + return; + + EnterCriticalSection(&cs_syslog); + + if( !(LOG_MASK( LOG_PRI( pri )) & syslog_mask) ) + goto done; + + openlog( NULL, 0, pri & LOG_FACMASK ); + if( !syslog_opened ) + goto done; + + if( !(pri & LOG_FACMASK) ) + pri |= syslog_facility; + + GetLocalTime( &stm ); + len = sprintf_s( datagramm, sizeof(datagramm), + "<%d>%s %2d %02d:%02d:%02d %s %s%s: ", + pri, + month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond, + local_hostname, syslog_ident, syslog_procid_str ); + vsprintf_s( datagramm + len, datagramm_size - len, fmt, ap ); + p = strchr( datagramm, '\n' ); + if( p ) + *p = 0; + p = strchr( datagramm, '\r' ); + if( p ) + *p = 0; + + sendto( syslog_socket, datagramm, strlen(datagramm), 0, (SOCKADDR*) &syslog_hostaddr, sizeof(SOCKADDR_IN) ); + + done: + LeaveCriticalSection(&cs_syslog); +} + diff --git a/third_party/heimdal/lib/roken/test-auxval.c b/third_party/heimdal/lib/roken/test-auxval.c new file mode 100644 index 0000000..69ab359 --- /dev/null +++ b/third_party/heimdal/lib/roken/test-auxval.c @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "roken.h" +#include "getauxval.h" + +static void +check_secure_getenv(char **env) +{ + size_t i; + char *v; + + for (i = 0; env[i] != NULL; i++) { + if (strchr(env[i], '=') == NULL) + continue; + if ((v = strdup(env[i])) == NULL) + err(1, "could not allocate copy of %s", env[i]); + *strchr(v, '=') = '\0'; + if (issuid() && rk_secure_getenv(v) != NULL) + err(1, "rk_secure_getenv() returned non-NULL when issuid()!"); + if (!issuid() && rk_secure_getenv(v) == NULL) + err(1, "rk_secure_getenv() returned NULL when !issuid()"); + free(v); + return; + } +} + +static void +inject_suid(int suid) +{ +#if defined(AT_SECURE) || (defined(AT_EUID) && defined(AT_RUID) && defined(AT_EGID) && defined(AT_RGID)) + auxv_t e; +#ifdef AT_SECURE + unsigned long secure = suid ? 1 : 0; +#endif +#if defined(AT_EUID) && defined(AT_RUID) && defined(AT_EGID) && defined(AT_RGID) + unsigned long eid = suid ? 0 : 1000; + + /* Inject real UID and GID */ + e.a_un.a_val = 1000; + e.a_type = AT_UID; + if ((errno = rk_injectauxv(&e)) != 0) + err(1, "rk_injectauxv(AT_RUID) failed"); + e.a_type = AT_GID; + if ((errno = rk_injectauxv(&e)) != 0) + err(1, "rk_injectauxv(AT_RGID) failed"); + + /* Inject effective UID and GID */ + e.a_un.a_val = eid; + e.a_type = AT_EUID; + if ((errno = rk_injectauxv(&e)) != 0) + err(1, "rk_injectauxv(AT_EUID) failed"); + e.a_type = AT_EGID; + if ((errno = rk_injectauxv(&e)) != 0) + err(1, "rk_injectauxv(AT_RGID) failed"); +#endif + +#ifdef AT_SECURE + e.a_un.a_val = secure; + e.a_type = AT_SECURE; + if ((errno = rk_injectauxv(&e)) != 0) + err(1, "rk_injectauxv(AT_SECURE) failed"); +#endif + + return; +#else + warnx("No ELF auxv types to inject"); +#endif +} + +static +unsigned long +getprocauxval(unsigned long type) +{ + const auxv_t *e; + + if ((e = rk_getauxv(type)) == NULL) { + errno = ENOENT; + return 0; + } + return e->a_un.a_val; +} + +/* returns 1 if auxval type is handled specially by libc */ +static int +is_special_auxv_p(long type) +{ +#ifdef AT_HWCAP + if (type == AT_HWCAP) + return 1; +#endif +#ifdef AT_HWCAP2 + if (type == AT_HWCAP2) + return 1; +#endif + + return 0; +} + +int +main(int argc, char **argv, char **env) +{ + unsigned long max_t = 0; + unsigned long a[2]; + unsigned long v; + ssize_t bytes; + int am_suid = issuid(); + int fd; + + (void) argc; + (void) argv; + + if (getuid() == geteuid() && getgid() == getegid()) { + if (issuid()) + errx(1, "issuid() false positive? Check AT_SECURE?"); + } else { + if (!issuid()) + errx(1, "issuid() did not detect set-uid-ness!"); + } + + if ((fd = open("/proc/self/auxv", O_RDONLY)) == -1) + return 0; + + /* + * Check that for every ELF auxv entry in /proc/self/auxv we + * find the correct answer from the rk_get*auxval() functions. + */ + do { + bytes = read(fd, a, sizeof(a)); + if (bytes != sizeof(a)) { + if (bytes == -1) + err(1, "Error reading from /proc/self/auxv"); + if (bytes == 0) + warnx("Did not see terminator in /proc/self/auxv"); + else + warnx("Partial entry in /proc/self/auxv or test interrupted"); + (void) close(fd); + return 1; + } + if (a[0] > max_t) + max_t = a[0]; + if (a[0] == 0) { + if (a[1] != 0) + warnx("AT_NULL with non-zero value %lu?!", a[1]); + continue; + } else if (is_special_auxv_p(a[0])) + continue; + + errno = EACCES; + + if ((v = rk_getauxval(a[0])) != a[1]) + errx(1, "rk_getauxval(%lu) should have been %lu, was %lu", + a[0], a[1], v); + if (errno != EACCES) + errx(1, "rk_getauxval(%lu) did not preserve errno", a[0]); + + if ((v = getprocauxval(a[0])) != a[1]) + errx(1, "rk_getauxval(%lu) should have been %lu, was %lu", + a[0], a[1], v); + if (errno != EACCES) + errx(1, "rk_getauxv(%lu) did not preserve errno", a[0]); + + printf("auxv type %lu -> %lu\n", a[0], a[1]); + } while (a[0] != 0 || a[1] != 0); + + (void) close(fd); + if (max_t == 0) { + warnx("No entries in /proc/self/auxv or it is not available on this " + "system or this program is linked statically; cannot test " + "rk_getauxval()"); + return 0; + } + + errno = EACCES; + if ((v = rk_getauxval(max_t + 1)) != 0) + errx(1, "rk_getauxval((max_type_seen = %lu) + 1) should have been " + "0, was %lu", max_t, v); + if (errno != ENOENT) + errx(1, "rk_getauxval((max_type_seen = %lu) + 1) did not set " + "errno = ENOENT!", max_t); + + errno = EACCES; + if ((v = getprocauxval(max_t + 1)) != 0) + errx(1, "rk_getauxv((max_type_seen = %lu) + 1) should have been " + "0, was %lu", max_t, v); + if (errno != ENOENT) + errx(1, "rk_getauxv((max_type_seen = %lu) + 1) did not set " + "errno = ENOENT!", max_t); + + check_secure_getenv(env); + inject_suid(!am_suid); + if ((am_suid && issuid()) || (!am_suid && !issuid())) + errx(1, "rk_injectprocauxv() failed"); + check_secure_getenv(env); + + return 0; +} diff --git a/third_party/heimdal/lib/roken/test-detach.c b/third_party/heimdal/lib/roken/test-detach.c new file mode 100644 index 0000000..0f4636e --- /dev/null +++ b/third_party/heimdal/lib/roken/test-detach.c @@ -0,0 +1,100 @@ +/*********************************************************************** + * Copyright (c) 2015, Cryptonector LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <sys/types.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#ifdef WIN32 +#include <process.h> +#ifdef getpid +#undef getpid +#endif +#define getpid _getpid +#else +#include <unistd.h> +#endif +#include "roken.h" + +int main(int argc, char **argv) +{ +/* + * XXXrcd: let's see how much further the tests get when we disable this + * on Windows. + */ +#ifndef WIN32 + char *ends; + long n; + int fd = -1; + pid_t parent = getpid(); + pid_t child; + + if (argc == 2 && strcmp(argv[1], "--reexec") != 0) + errx(1, "Usage: test-detach [--reexec] [--daemon-child FD]"); + if (argc == 3 || argc == 4) { + parent = getppid(); + errno = 0; + n = strtol(argv[2], &ends, 10); + fd = n; + if (errno != 0) + err(1, "Usage: test-detach [--daemon-child fd]"); + if (n < 0 || ends == NULL || *ends != '\0' || n != fd) + errx(1, "Usage: test-detach [--daemon-child fd]"); + } else { + if (argc == 2) + /* Make sure we re-exec on the child-side of fork() (not WIN32) */ + putenv("ROKEN_DETACH_USE_EXEC=1"); + fd = roken_detach_prep(argc, argv, "--daemon-child"); + if (fd == -1) + errx(1, "bad"); + } + if (parent == getpid()) + errx(1, "detach prep failed"); + child = getpid(); + roken_detach_finish(NULL, fd); + if (child != getpid()) + errx(1, "detach finish failed"); + /* + * These printfs will not appear: stderr will have been replaced + * with /dev/null. + */ + fprintf(stderr, "Now should be the child: %ld, wrote to parent\n", (long)getpid()); + sleep(5); + fprintf(stderr, "Daemon child done\n"); + return 0; +#else + return 0; +#endif +} diff --git a/third_party/heimdal/lib/roken/test-getuserinfo.c b/third_party/heimdal/lib/roken/test-getuserinfo.c new file mode 100644 index 0000000..4feae17 --- /dev/null +++ b/third_party/heimdal/lib/roken/test-getuserinfo.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017 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. + */ + +#ifndef WIN32 +#include <err.h> +#endif +#include "roken.h" + +static void +print1(const char *name, const char *tabs, const char *s2) +{ + (void) printf("%s:%s%s\n", name, tabs, s2 ? s2 : "<NULL>"); +} + +int +main(void) +{ + char buf[MAX_PATH * 2]; +#ifndef WIN32 + char buf2[MAX_PATH * 2]; + int ret = 0; + if (!issuid() && getuid() != 0) { + const char *s = NULL; + const char *s2 = NULL; + + if (getenv("USER") != NULL && strlen(getenv("USER")) != 0 && + (s = roken_get_username(buf, sizeof(buf))) == NULL) { + warnx("roken_get_username() returned NULL but $USER is set"); + ret++; + } + if (getenv("USER") != NULL && strlen(getenv("USER")) != 0 && s && + strcmp(getenv("USER"), s) != 0) { + warnx("roken_get_username() != getenv(\"USER\")"); + ret++; + } + + if (getenv("HOME") != NULL && strlen(getenv("HOME")) != 0 && + (s = roken_get_homedir(buf, sizeof(buf))) == NULL) { + warnx("roken_get_homedir() returned NULL but $HOME is set"); + ret++; + } + if (getenv("HOME") != NULL && strlen(getenv("HOME")) != 0 && s && + strcmp(getenv("HOME"), s) != 0) { + warnx("roken_get_homedir() != getenv(\"HOME\")"); + ret++; + } + + if (getenv("HOME") != NULL && strlen(getenv("HOME")) != 0 && s && + (s2 = roken_get_appdatadir(buf, sizeof(buf))) == NULL) { + warnx("roken_get_appdatadir() returned NULL but $HOME is set " + "and roken_get_homedir() returned not-NULL"); + ret++; + } + if (getenv("HOME") != NULL && strlen(getenv("HOME")) != 0 && + s && s2 && strcmp(s, s2) != 0) { + warnx("roken_get_homedir() != roken_get_appdatadir()"); + ret++; + } + if (getenv("SHELL") != NULL && strlen(getenv("SHELL")) != 0 && + strcmp(getenv("SHELL"), roken_get_shell(buf, sizeof(buf))) != 0) { + warnx("roken_get_shell() != getenv(\"SHELL\")"); + ret++; + } + } +#endif + + print1("Username", "\t", roken_get_username(buf, sizeof(buf))); + print1("Loginname", "\t", roken_get_loginname(buf, sizeof(buf))); + print1("Home", "\t\t", roken_get_homedir(buf, sizeof(buf))); + print1("Appdatadir", "\t", roken_get_appdatadir(buf, sizeof(buf))); + print1("Shell", "\t\t", roken_get_shell(buf, sizeof(buf))); + +#ifndef WIN32 + if (!issuid() && getuid() != 0) { + const char *s, *s2; + + putenv("USER=h5lfoouser"); + putenv("HOME=/no/such/dir/h5lfoouser"); + putenv("SHELL=/no/such/shell"); + if ((s = roken_get_username(buf, sizeof(buf))) == NULL || + strcmp("h5lfoouser", s) != 0) { + warnx("roken_get_username() (%s) did not honor $USER", s); + ret++; + } + if ((s = roken_get_homedir(buf, sizeof(buf))) == NULL || + strcmp("/no/such/dir/h5lfoouser", s) != 0) { + warnx("roken_get_homedir() (%s) did not honor $HOME", s); + ret++; + } + s = roken_get_homedir(buf, sizeof(buf)); + s2 = roken_get_appdatadir(buf2, sizeof(buf2)); + if (strcmp(s, s2) != 0) { + warnx("roken_get_homedir() != roken_get_appdatadir() (%s)", + roken_get_appdatadir(buf, sizeof(buf))); + ret++; + } + if ((s = roken_get_shell(buf, sizeof(buf))) == NULL || + strcmp("/no/such/shell", s) != 0) { + warnx("roken_get_shell() (%s) did not honor $SHELL", s); + ret++; + } + } + return ret; +#endif + return 0; +} diff --git a/third_party/heimdal/lib/roken/test-mem.c b/third_party/heimdal/lib/roken/test-mem.c new file mode 100644 index 0000000..5ae1017 --- /dev/null +++ b/third_party/heimdal/lib/roken/test-mem.c @@ -0,0 +1,215 @@ +/* + * 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. + */ + +#include <config.h> + +#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" + +/* #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; + +#ifdef HAVE_SIGACTION + +struct sigaction sa, osa; + +#else + +void (* osigh)(int); + +#endif + +char *testname; + +static RETSIGTYPE +segv_handler(int sig) +{ + int fd; + ssize_t ret; + char msg[] = "SIGSEGV i current test: "; + + fd = open("/dev/stdout", O_WRONLY, 0600); + if (fd >= 0) { + ret = write(fd, msg, sizeof(msg) - 1); + if (ret != -1) + ret = write(fd, testname, strlen(testname)); + if (ret != -1) + ret = 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"); + + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +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-1] = 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 +#ifdef HAVE_SIGACTION + 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); +#else + osigh = signal(SIGSEGV, segv_handler); +#endif + + map.data_size = size; + if (buf) + memcpy(map.data_start, buf, size); + return map.data_start; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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-1] != 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; + +#ifdef HAVE_SIGACTION + sigaction (SIGSEGV, &osa, NULL); +#else + signal (SIGSEGV, osigh); +#endif +} diff --git a/third_party/heimdal/lib/roken/test-mem.h b/third_party/heimdal/lib/roken/test-mem.h new file mode 100644 index 0000000..4d900b4 --- /dev/null +++ b/third_party/heimdal/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 }; + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL + rk_test_mem_alloc(enum rk_test_mem_type, const char *, void *, size_t); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL + rk_test_mem_free(const char *); diff --git a/third_party/heimdal/lib/roken/test-mini_inetd.c b/third_party/heimdal/lib/roken/test-mini_inetd.c new file mode 100644 index 0000000..7ab996a --- /dev/null +++ b/third_party/heimdal/lib/roken/test-mini_inetd.c @@ -0,0 +1,371 @@ +/*********************************************************************** + * Copyright (c) 2009, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 <roken.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#define PORT 8013 +#define PORT_S "8013" + +char * prog = "Master"; +int is_client = 0; + +static int +get_address(int flags, struct addrinfo ** ret) +{ + struct addrinfo ai; + int rv; + + memset(&ai, 0, sizeof(ai)); + + ai.ai_flags = flags | AI_NUMERICHOST; + ai.ai_family = AF_INET; + ai.ai_socktype = SOCK_STREAM; + ai.ai_protocol = PF_UNSPEC; + + rv = getaddrinfo("127.0.0.1", PORT_S, &ai, ret); + if (rv) + warnx("getaddrinfo: %s", gai_strerror(rv)); + return rv; +} + +static int +get_connected_socket(rk_socket_t * s_ret) +{ + struct addrinfo * ai = NULL; + int rv = 0; + rk_socket_t s = rk_INVALID_SOCKET; + + rv = get_address(0, &ai); + if (rv) + return rv; + + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (rk_IS_BAD_SOCKET(s)) { + rv = 1; + goto done; + } + + rv = connect(s, ai->ai_addr, ai->ai_addrlen); + if (rk_IS_SOCKET_ERROR(rv)) + goto done; + + *s_ret = s; + s = rk_INVALID_SOCKET; + rv = 0; + + done: + if (!rk_IS_BAD_SOCKET(s)) + rk_closesocket(s); + + if (ai) + freeaddrinfo(ai); + + return (rv) ? rk_SOCK_ERRNO : 0; +} + +const char * test_strings[] = { + "Hello", + "01234566789012345689012345678901234567890123456789", + "Another test", + "exit" +}; + +static int +test_simple_echo_client(void) +{ + rk_socket_t s = rk_INVALID_SOCKET; + int rv; + char buf[81]; + int i; + + fprintf(stderr, "[%s] Getting connected socket...", getprogname()); + rv = get_connected_socket(&s); + if (rv) { + fprintf(stderr, "\n[%s] get_connected_socket() failed (%s)\n", + getprogname(), strerror(rk_SOCK_ERRNO)); + return 1; + } + + fprintf(stderr, "[%s] done\n", getprogname()); + + for (i=0; i < sizeof(test_strings)/sizeof(test_strings[0]); i++) { + rv = send(s, test_strings[i], strlen(test_strings[i]), 0); + if (rk_IS_SOCKET_ERROR(rv)) { + fprintf(stderr, "[%s] send() failure (%s)\n", + getprogname(), strerror(rk_SOCK_ERRNO)); + rk_closesocket(s); + return 1; + } + + rv = recv(s, buf, sizeof(buf), 0); + if (rk_IS_SOCKET_ERROR(rv)) { + fprintf (stderr, "[%s] recv() failure (%s)\n", + getprogname(), strerror(rk_SOCK_ERRNO)); + rk_closesocket(s); + return 1; + } + + if (rv == 0) { + fprintf (stderr, "[%s] No data received\n", prog); + rk_closesocket(s); + return 1; + } + + if (rv != strlen(test_strings[i])) { + fprintf (stderr, "[%s] Data length mismatch %d != %zu\n", prog, rv, strlen(test_strings[i])); + rk_closesocket(s); + return 1; + } + } + + fprintf (stderr, "[%s] Done\n", prog); + rk_closesocket(s); + return 0; +} + +static int +test_simple_echo_socket(void) +{ + fprintf (stderr, "[%s] Process ID %d\n", prog, GetCurrentProcessId()); + fprintf (stderr, "[%s] Starting echo test with sockets\n", prog); + + if (is_client) { + return test_simple_echo_client(); + } else { + + rk_socket_t s = rk_INVALID_SOCKET; + + fprintf (stderr, "[%s] Listening for connections...\n", prog); + mini_inetd(htons(PORT), &s); + if (rk_IS_BAD_SOCKET(s)) { + fprintf (stderr, "[%s] Connect failed (%s)\n", + getprogname(), strerror(rk_SOCK_ERRNO)); + } else { + fprintf (stderr, "[%s] Connected\n", prog); + } + + { + char buf[81]; + int rv, srv; + + while ((rv = recv(s, buf, sizeof(buf), 0)) != 0 && !rk_IS_SOCKET_ERROR(rv)) { + buf[rv] = 0; + fprintf(stderr, "[%s] Received [%s]\n", prog, buf); + + /* simple echo */ + srv = send(s, buf, rv, 0); + if (srv != rv) { + if (rk_IS_SOCKET_ERROR(srv)) + fprintf(stderr, "[%s] send() error [%s]\n", + getprogname(), strerror(rk_SOCK_ERRNO)); + else + fprintf(stderr, "[%s] send() size mismatch %d != %d", + getprogname(), srv, rv); + } + + if (strcmp(buf, "exit") == 0) { + fprintf(stderr, "[%s] Exiting...\n", prog); + shutdown(s, SD_SEND); + rk_closesocket(s); + return 0; + } + } + + fprintf(stderr, "[%s] recv() failed (%s)\n", + getprogname(), + strerror(rk_SOCK_ERRNO)); + } + + rk_closesocket(s); + } + + return 1; +} + +static int +test_simple_echo(void) +{ + fprintf (stderr, "[%s] Starting echo test\n", prog); + + if (is_client) { + + return test_simple_echo_client(); + + } else { + + fprintf (stderr, "[%s] Listening for connections...\n", prog); + mini_inetd(htons(PORT), NULL); + fprintf (stderr, "[%s] Connected\n", prog); + + { + char buf[81]; + while (gets(buf)) { + fprintf(stderr, "[%s] Received [%s]\n", prog, buf); + + if (strcmp(buf, "exit") == 0) + return 0; + + /* simple echo */ + puts(buf); + } + + fprintf(stderr, "[%s] gets() failed (%s)\n", prog, _strerror("gets")); + } + } + + return 1; +} + +static int +do_client(void) +{ + int rv = 0; + + if (rk_SOCK_INIT()) + errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO)); + + prog = "Client"; + is_client = 1; + + fprintf(stderr, "Starting client...\n"); + + rv = test_simple_echo_socket(); + + rk_SOCK_EXIT(); + + return rv; +} + +static int +do_server(void) +{ + int rv = 0; + + if (rk_SOCK_INIT()) + errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO)); + + prog = "Server"; + + fprintf(stderr, "Starting server...\n"); + + rv = test_simple_echo_socket(); + + rk_SOCK_EXIT(); + + return rv; +} + +static time_t +wait_callback(void *p) +{ + return (time_t)-1; +} + +static int +do_test(char * path) +{ + intptr_t p_server; + intptr_t p_client; + int client_rv; + int server_rv; + + p_server = _spawnl(_P_NOWAIT, path, path, "--server", NULL); + if (p_server <= 0) { + fprintf(stderr, "%s: %s", path, _strerror("Can't start server process")); + return 1; + } +#ifdef _WIN32 + /* On Windows, the _spawn*() functions return a process handle on + success. We need a process ID for use with + wait_for_process_timed(). */ + + p_server = GetProcessId((HANDLE) p_server); +#endif + fprintf(stderr, "Created server process ID %d\n", p_server); + + p_client = _spawnl(_P_NOWAIT, path, path, "--client", NULL); + if (p_client <= 0) { + fprintf(stderr, "%s: %s", path, _strerror("Can't start client process")); + fprintf(stderr, "Waiting for server process to terminate ..."); + wait_for_process_timed(p_server, wait_callback, NULL, 5); + fprintf(stderr, "DONE\n"); + return 1; + } +#ifdef _WIN32 + p_client = GetProcessId((HANDLE) p_client); +#endif + fprintf(stderr, "Created client process ID %d\n", p_client); + + fprintf(stderr, "Waiting for client process to terminate ..."); + client_rv = wait_for_process_timed(p_client, wait_callback, NULL, 5); + if (SE_IS_ERROR(client_rv)) { + fprintf(stderr, "\nwait_for_process_timed() failed for client. rv=%d\n", client_rv); + } else { + fprintf(stderr, "DONE\n"); + } + + fprintf(stderr, "Waiting for server process to terminate ..."); + server_rv = wait_for_process_timed(p_server, wait_callback, NULL, 5); + if (SE_IS_ERROR(server_rv)) { + fprintf(stderr, "\nwait_for_process_timed() failed for server. rv=%d\n", server_rv); + } else { + fprintf(stderr, "DONE\n"); + } + + if (client_rv == 0 && server_rv == 0) { + fprintf(stderr, "PASS\n"); + return 0; + } else { + fprintf(stderr, "FAIL: Client rv=%d, Server rv=%d\n", client_rv, server_rv); + return 1; + } +} + +int main(int argc, char ** argv) +{ + setprogname(argv[0]); + + if (argc == 2 && strcmp(argv[1], "--client") == 0) + return do_client(); + else if (argc == 2 && strcmp(argv[1], "--server") == 0) + return do_server(); + else if (argc == 1) + return do_test(argv[0]); + else { + printf ("%s: Test mini_inetd() function. Run with no arguments to start test\n", + argv[0]); + return 1; + } +} diff --git a/third_party/heimdal/lib/roken/test-readenv.c b/third_party/heimdal/lib/roken/test-readenv.c new file mode 100644 index 0000000..24a6661 --- /dev/null +++ b/third_party/heimdal/lib/roken/test-readenv.c @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#include <config.h> + +#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/third_party/heimdal/lib/roken/timegm.c b/third_party/heimdal/lib/roken/timegm.c new file mode 100644 index 0000000..e6c8992 --- /dev/null +++ b/third_party/heimdal/lib/roken/timegm.c @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#include <config.h> + +#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/third_party/heimdal/lib/roken/timeval.c b/third_party/heimdal/lib/roken/timeval.c new file mode 100644 index 0000000..3012513 --- /dev/null +++ b/third_party/heimdal/lib/roken/timeval.c @@ -0,0 +1,286 @@ +/* + * 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 + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +rk_time_add(time_t t, time_t delta) +{ + if (delta == 0) + return t; + +#ifdef TIME_T_SIGNED + /* Signed overflow is UB in C */ +#if SIZEOF_TIME_T == 4 + if (t >= 0 && delta > 0 && INT32_MAX - t < delta) + /* Time left to hit INT32_MAX is less than what we want to add */ + return INT32_MAX; + else if (t == INT32_MIN && delta < 0) + /* Avoid computing -t when t == INT32_MIN! */ + return INT32_MIN; + else if (t < 0 && delta < 0 && INT32_MIN + (-t) > delta) + /* Time left to hit INT32_MIN is less than what we want to subtract */ + return INT32_MIN; + else + return t + delta; +#elif SIZEOF_TIME_T == 8 + if (t >= 0 && delta > 0 && INT64_MAX - t < delta) + return INT64_MAX; + else if (t == INT64_MIN && delta < 0) + /* Avoid computing -t when t == INT64_MIN! */ + return INT64_MIN; + else if (t < 0 && delta < 0 && INT64_MIN + (-t) > delta) + return INT64_MIN; + else + return t + delta; +#else +#error "Unexpected sizeof(time_t)" +#endif +#else + + /* Unsigned overflow is defined in C */ +#if SIZEOF_TIME_T == 4 + if (t + delta < t) + return UINT32_MAX; +#elif SIZEOF_TIME_T == 8 + if (t + delta < t) + return UINT64_MAX; +#else +#error "Unexpected sizeof(time_t)" +#endif +#endif + return t + delta; +} + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +rk_time_sub(time_t t, time_t delta) +{ + if (delta == 0) + return t; +#ifdef TIME_T_SIGNED + if (delta > 0) + return rk_time_add(t, -delta); +#if SIZEOF_TIME_T == 4 + if (delta == INT32_MIN) { + if (t < 0) { + t = t + INT32_MAX; + return t + 1; + } + return INT32_MAX; + } + /* Safe to compute -delta, so use rk_time_add() to add -delta */ + return rk_time_add(t, -delta); +#elif SIZEOF_TIME_T == 8 + if (delta == INT64_MIN) { + if (t < 0) { + t = t + INT64_MAX; + return t + 1; + } + return INT64_MAX; + } + return rk_time_add(t, -delta); +#else +#error "Unexpected sizeof(time_t)" +#endif +#else + /* Both t and delta are non-negative. */ + if (delta > t) + return 0; +#endif + return t - delta; +} + +/* + * Make `t1' consistent. + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevalfix(struct timeval *t1) +{ + if (t1->tv_usec < 0) { + t1->tv_sec = rk_time_sub(t1->tv_sec, 1); + t1->tv_usec = 1000000; + } + if (t1->tv_usec >= 1000000) { + t1->tv_sec = rk_time_add(t1->tv_sec, 1); + t1->tv_usec -= 1000000; + } +} + +/* + * t1 += t2 + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevaladd(struct timeval *t1, const struct timeval *t2) +{ + t1->tv_sec = rk_time_add(t1->tv_sec, t2->tv_sec); + t1->tv_usec += t2->tv_usec; + timevalfix(t1); +} + +/* + * t1 -= t2 + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +timevalsub(struct timeval *t1, const struct timeval *t2) +{ + t1->tv_sec = rk_time_sub(t1->tv_sec, t2->tv_sec); + t1->tv_usec -= t2->tv_usec; + timevalfix(t1); +} + +#ifdef TEST +int +main(int argc, char **argv) +{ + time_t t, delta, r; + int e = 0; + + if (argc == 0) + return 0; /* Apparently POSIX and Linux allow this case */ + + argc--; + argv++; + + while (argc > 0) { + int64_t n; + time_t a; + char *ends; + + if (argc < 3) + errx(1, "Usage: [TIME +|- DELTA [== TIME]]"); + + errno = 0; + n = strtoll(argv[0], &ends, 0); + if (errno) + err(1, "Time value is invalid"); + if (*ends != '\0') + errx(1, "Time value is invalid"); + t = n; + + n = strtoll(argv[2], &ends, 0); + if (errno) + err(1, "Delta value is invalid"); + if (*ends != '\0') + errx(1, "Delta value is invalid"); + delta = n; + + if (argv[1][0] == '+' && argv[1][1] == '\0') + r = rk_time_add(t, delta); + else if (argv[1][0] == '-' && argv[1][1] == '\0') + r = rk_time_sub(t, delta); + else + errx(1, "Operator must be a + or a - arithmetic operator"); + + if (delta == 0 && r != t) { + warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[0]); + e = 1; + } + if (t == 0 && r != delta) { + warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[2]); + e = 1; + } + + if (argc > 4 && strcmp(argv[3], "==") == 0) { + n = strtoll(argv[4], &ends, 0); + if (errno) + err(1, "Time value is invalid"); + if (*ends != '\0') + errx(1, "Time value is invalid"); + a = n; + if (a != r) { + warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[4]); + e = 1; + } + argc -= 5; + argv += 5; + } else { +#ifdef TIME_T_SIGNED + printf("%s %s %s == %lld\n", argv[0], argv[1], argv[2], + (long long)r); +#else + printf("%s %s %s == %llu\n", argv[0], argv[1], argv[2], + (unsigned long long)r); +#endif + argc -= 3; + argv += 3; + } + } + +#define CHECK(e) do { if (!(e)) errx(1, "Expression not true: " #e "!"); } while (0) +#ifdef TIME_T_SIGNED +#if SIZEOF_TIME_T == 4 + CHECK(rk_time_add(INT32_MIN, -1) == INT32_MIN); + CHECK(rk_time_sub(INT32_MIN, 1) == INT32_MIN); + CHECK(rk_time_sub(-1, INT32_MAX) == INT32_MIN); + CHECK(rk_time_add(INT32_MAX, 0) == INT32_MAX); + CHECK(rk_time_add(INT32_MAX, 1) == INT32_MAX); + CHECK(rk_time_add(1, INT32_MAX) == INT32_MAX); + CHECK(rk_time_add(0, INT32_MAX) == INT32_MAX); +#elif SIZEOF_TIME_T == 8 + CHECK(rk_time_add(INT64_MIN, -1) == INT64_MIN); + CHECK(rk_time_sub(INT64_MIN, 1) == INT64_MIN); + CHECK(rk_time_sub(-1, INT64_MAX) == INT64_MIN); + CHECK(rk_time_add(INT64_MAX, 0) == INT64_MAX); + CHECK(rk_time_add(INT64_MAX, 1) == INT64_MAX); + CHECK(rk_time_add(1, INT64_MAX) == INT64_MAX); + CHECK(rk_time_add(0, INT64_MAX) == INT64_MAX); +#endif + CHECK(rk_time_add(0, -1) == -1); + CHECK(rk_time_sub(0, 1) == -1); +#else +#if SIZEOF_TIME_T == 4 + CHECK(rk_time_add(UINT32_MAX, 0) == UINT32_MAX); + CHECK(rk_time_add(UINT32_MAX, 1) == UINT32_MAX); + CHECK(rk_time_add(1, UINT32_MAX) == UINT32_MAX); + CHECK(rk_time_add(0, UINT32_MAX) == UINT32_MAX); +#elif SIZEOF_TIME_T == 8 + CHECK(rk_time_add(UINT64_MAX, 0) == UINT64_MAX); + CHECK(rk_time_add(UINT64_MAX, 1) == UINT64_MAX); + CHECK(rk_time_add(1, UINT64_MAX) == UINT64_MAX); + CHECK(rk_time_add(0, UINT64_MAX) == UINT64_MAX); +#endif +#endif + CHECK(rk_time_add(0, 1) == 1); + CHECK(rk_time_add(1, 0) == 1); + return e; +} +#endif diff --git a/third_party/heimdal/lib/roken/tm2time.c b/third_party/heimdal/lib/roken/tm2time.c new file mode 100644 index 0000000..ba69a04 --- /dev/null +++ b/third_party/heimdal/lib/roken/tm2time.c @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include <config.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 "roken.h" + +ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/tsearch-test.c b/third_party/heimdal/lib/roken/tsearch-test.c new file mode 100644 index 0000000..b9d9963 --- /dev/null +++ b/third_party/heimdal/lib/roken/tsearch-test.c @@ -0,0 +1,125 @@ +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ + +#include <config.h> + +#include "roken.h" +#include "search.h" + +struct node { + char *string; + int order; +}; + +extern void *rk_tdelete(const void *, void **, + int (*)(const void *, const void *)); +extern void *rk_tfind(const void *, void * const *, + int (*)(const void *, const void *)); +extern void *rk_tsearch(const void *, void **, int (*)(const void *, const void *)); +extern void rk_twalk(const void *, void (*)(const void *, VISIT, int)); + +void *rootnode = NULL; +int numerr = 0; + +/* + * This routine compares two nodes, based on an + * alphabetical ordering of the string field. + */ +int +node_compare(const void *node1, const void *node2) +{ + return strcmp(((const struct node *) node1)->string, + ((const struct node *) node2)->string); +} + +static int walkorder = -1; + +void +list_node(const void *ptr, VISIT order, int level) +{ + const struct node *p = *(const struct node **) ptr; + + if (order == postorder || order == leaf) { + walkorder++; + if (p->order != walkorder) { + warnx("sort failed: expected %d next, got %d\n", walkorder, + p->order); + numerr++; + } + } +} + +int +main(int argc, char **argv) +{ + int numtest = 1; + struct node *t, *p, tests[] = { + { "", 0 }, + { "ab", 3 }, + { "abc", 4 }, + { "abcdefg", 8 }, + { "abcd", 5 }, + { "a", 2 }, + { "abcdef", 7 }, + { "abcde", 6 }, + { "=", 1 }, + { NULL } + }; + + for(t = tests; t->string; t++) { + /* Better not be there */ + p = (struct node *)rk_tfind((void *)t, (void **)&rootnode, + node_compare); + + if (p) { + warnx("erroneous list: found %d\n", p->order); + numerr++; + } + + /* Put node into the tree. */ + p = (struct node *) rk_tsearch((void *)t, (void **)&rootnode, + node_compare); + + if (!p) { + warnx("erroneous list: missing %d\n", t->order); + numerr++; + } + } + + rk_twalk(rootnode, list_node); + + for(t = tests; t->string; t++) { + /* Better be there */ + p = (struct node *) rk_tfind((void *)t, (void **)&rootnode, + node_compare); + + if (!p) { + warnx("erroneous list: missing %d\n", t->order); + numerr++; + } + + /* pull out node */ + (void) rk_tdelete((void *)t, (void **)&rootnode, + node_compare); + + /* Better not be there */ + p = (struct node *) rk_tfind((void *)t, (void **)&rootnode, + node_compare); + + if (p) { + warnx("erroneous list: found %d\n", p->order); + numerr++; + } + + } + + return numerr; +} diff --git a/third_party/heimdal/lib/roken/tsearch.c b/third_party/heimdal/lib/roken/tsearch.c new file mode 100644 index 0000000..e5df846 --- /dev/null +++ b/third_party/heimdal/lib/roken/tsearch.c @@ -0,0 +1,175 @@ +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + * + * $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ + * $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $ + * $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ + * $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ + */ + +#include <config.h> +#include "roken.h" +#include "search.h" +#include <stdlib.h> + +typedef struct node { + char *key; + struct node *llink, *rlink; +} node_t; + +/* + * find or insert datum into search tree + * + * Parameters: + * vkey: key to be located + * vrootp: address of tree root + */ + +ROKEN_LIB_FUNCTION void * +rk_tsearch(const void *vkey, void **vrootp, + int (*compar)(const void *, const void *)) +{ + node_t *q; + node_t **rootp = (node_t **)vrootp; + + if (rootp == NULL) + return NULL; + + while (*rootp != NULL) { /* Knuth's T1: */ + int r; + + if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ + return *rootp; /* we found it! */ + + rootp = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + } + + q = malloc(sizeof(node_t)); /* T5: key not found */ + if (q != 0) { /* make new node */ + *rootp = q; /* link new node to old */ + /* LINTED const castaway ok */ + q->key = rk_UNCONST(vkey); /* initialize new node */ + q->llink = q->rlink = NULL; + } + return q; +} + +/* + * Walk the nodes of a tree + * + * Parameters: + * root: Root of the tree to be walked + */ +static void +trecurse(const node_t *root, void (*action)(const void *, VISIT, int), + int level) +{ + + if (root->llink == NULL && root->rlink == NULL) + (*action)(root, leaf, level); + else { + (*action)(root, preorder, level); + if (root->llink != NULL) + trecurse(root->llink, action, level + 1); + (*action)(root, postorder, level); + if (root->rlink != NULL) + trecurse(root->rlink, action, level + 1); + (*action)(root, endorder, level); + } +} + +/* + * Walk the nodes of a tree + * + * Parameters: + * vroot: Root of the tree to be walked + */ +ROKEN_LIB_FUNCTION void +rk_twalk(const void *vroot, + void (*action)(const void *, VISIT, int)) +{ + if (vroot != NULL && action != NULL) + trecurse(vroot, action, 0); +} + +/* + * delete node with given key + * + * vkey: key to be deleted + * vrootp: address of the root of the tree + * compar: function to carry out node comparisons + */ +ROKEN_LIB_FUNCTION void * +rk_tdelete(const void * vkey, void ** vrootp, + int (*compar)(const void *, const void *)) +{ + node_t **rootp = (node_t **)vrootp; + node_t *q, *r; + int cmp; + + if (rootp == NULL || *rootp == NULL) + return NULL; + + while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) { + rootp = (cmp < 0) ? + &(*rootp)->llink : /* follow llink branch */ + &(*rootp)->rlink; /* follow rlink branch */ + if (*rootp == NULL) + return NULL; /* key not found */ + } + r = (*rootp)->rlink; /* D1: */ + if ((q = (*rootp)->llink) == NULL) /* Left NULL? */ + q = r; + else if (r != NULL) { /* Right link is NULL? */ + if (r->llink == NULL) { /* D2: Find successor */ + r->llink = q; + q = r; + } else { /* D3: Find NULL link */ + for (q = r->llink; q->llink != NULL; q = r->llink) + r = q; + r->llink = q->rlink; + q->llink = (*rootp)->llink; + q->rlink = (*rootp)->rlink; + } + } + free(*rootp); /* D4: Free node */ + *rootp = q; /* link parent to new node */ + return *rootp; +} + +/* + * find a node, or return 0 + * + * Parameters: + * vkey: key to be found + * vrootp: address of the tree root + */ +ROKEN_LIB_FUNCTION void * +rk_tfind(const void *vkey, void * const *vrootp, + int (*compar)(const void *, const void *)) +{ + node_t **rootp = (node_t **)vrootp; + + if (rootp == NULL) + return NULL; + + while (*rootp != NULL) { /* T1: */ + int r; + + if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ + return *rootp; /* key found */ + rootp = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + } + return NULL; +} diff --git a/third_party/heimdal/lib/roken/unsetenv.c b/third_party/heimdal/lib/roken/unsetenv.c new file mode 100644 index 0000000..55ba5e3 --- /dev/null +++ b/third_party/heimdal/lib/roken/unsetenv.c @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> + +#include "roken.h" + +#if !HAVE_DECL_ENVIRON +extern char **environ; +#endif + +/* + * unsetenv -- + */ +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/unvis.c b/third_party/heimdal/lib/roken/unvis.c new file mode 100644 index 0000000..6ceda4a --- /dev/null +++ b/third_party/heimdal/lib/roken/unvis.c @@ -0,0 +1,283 @@ +/* $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 +#include <config.h> +#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') + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strunvis (char *, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_unvis (char *, int, int *, int); + +/* + * unvis - decode characters previously encoded by vis + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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 = (u_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. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/verr.c b/third_party/heimdal/lib/roken/verr.c new file mode 100644 index 0000000..9201e6d --- /dev/null +++ b/third_party/heimdal/lib/roken/verr.c @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <err.h> + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +verr(int eval, const char *fmt, va_list ap) +{ + rk_warnerr(1, fmt, ap); + exit(eval); +} diff --git a/third_party/heimdal/lib/roken/verrx.c b/third_party/heimdal/lib/roken/verrx.c new file mode 100644 index 0000000..7b148a4 --- /dev/null +++ b/third_party/heimdal/lib/roken/verrx.c @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <err.h> + +ROKEN_LIB_NORETURN_FUNCTION void ROKEN_LIB_CALL +verrx(int eval, const char *fmt, va_list ap) +{ + rk_warnerr(0, fmt, ap); + exit(eval); +} diff --git a/third_party/heimdal/lib/roken/version-script.map b/third_party/heimdal/lib/roken/version-script.map new file mode 100644 index 0000000..be1713e --- /dev/null +++ b/third_party/heimdal/lib/roken/version-script.map @@ -0,0 +1,238 @@ +HEIMDAL_ROKEN_2.0 { + global: + arg_printusage; + arg_printusage_i18n; + cgetclose; + cgetmatch; + cgetnum; + cgetset; + cgetustr; + ct_memcmp; + err; + errx; + free_getarg_strings; + fseeko; + ftello; + get_window_size; + getarg; + getnameinfo_verified; + hex_decode; + hex_encode; + issuid; + mini_inetd; + mini_inetd_addrinfo; + net_read; + net_write; + parse_bytes; + parse_flags; + parse_time; + parse_units; + print_flags_table; + print_time_table; + print_units_table; + rk_asnprintf; + rk_asprintf; + rk_base32_decode; + rk_base32_encode; + rk_base64_decode; + rk_base64_encode; + rk_bswap16; + rk_bswap32; + rk_bswap64; + rk_cloexec; + rk_cloexec_dir; + rk_cloexec_file; + rk_cloexec_socket; + rk_closefrom; + rk_clzll; + rk_copyhostent; + rk_dns_free_data; + rk_dns_lookup; + rk_dns_srv_order; + rk_dns_string_to_type; + rk_dns_type_to_string; + rk_dumpdata; + rk_ecalloc; + rk_emalloc; + rk_eread; + rk_erealloc; + rk_esetenv; + rk_estrdup; + rk_ewrite; + rk_flock; + rk_fnmatch; + rk_free_environment; + rk_freeaddrinfo; + rk_freehostent; + rk_freeifaddrs; + rk_gai_strerror; + rk_getaddrinfo; + rk_getauxv; + rk_getauxval; + rk_getifaddrs; + rk_getipnodebyaddr; + rk_getipnodebyname; + rk_getnameinfo; + rk_getprogname; + rk_glob; + rk_globfree; + rk_hex_decode; + rk_hex_encode; + rk_hostent_find_fqdn; + rk_inet_ntop; + rk_inet_pton; + rk_injectauxv; + rk_localtime_r; + rk_memmem; + rk_memset_s; + rk_mergesort; + rk_mergesort_r; + rk_mkdir; + rk_mkdtemp; + rk_mkostemp; + rk_mkstemp; + rk_parse_flags; + rk_parse_time; + rk_parse_units; + rk_pid_file_delete; + rk_pid_file_write; + rk_pidfile; + rk_pipe_execv; + rk_print_flags_table; + rk_print_time_table; + rk_print_units_table; + rk_random_init; + rk_read_environment; + rk_readv; + rk_realloc; + rk_secure_getenv; + rk_setprogname; + rk_simple_execle; + rk_simple_execlp; + rk_simple_execve; + rk_simple_execve_timed; + rk_simple_execvp; + rk_simple_execvp_timed; + rk_socket; + rk_socket_addr_size; + rk_socket_get_address; + rk_socket_get_port; + rk_socket_set_address_and_port; + rk_socket_set_any; + rk_socket_set_debug; + rk_socket_set_ipv6only; + rk_socket_set_keepalive; + rk_socket_set_nonblocking; + rk_socket_set_port; + rk_socket_set_portrange; + rk_socket_set_reuseaddr; + rk_socket_set_tos; + rk_socket_sockaddr_size; + rk_strasvis; + rk_strasvisx; + rk_stravis; + rk_stravisx; + rk_strcollect; + rk_strerror; + rk_strerror_r; + rk_strftime; + rk_strlcat; + rk_strlcpy; + rk_strlwr; + rk_strndup; + rk_strnlen; + rk_strpoolcollect; + rk_strpoolfree; + rk_strpoolprintf; + rk_strptime; + rk_strrasvis; + rk_strrasvisx; + rk_strsep_copy; + rk_strsvis; + rk_strsvisx; + rk_strtoll; + rk_strtoull; + rk_strunvis; + rk_strunvisx; + rk_strupr; + rk_strvis; + rk_strvisx; + rk_svis; + rk_tdelete; + rk_tfind; + rk_timegm; + rk_time_add; + rk_time_sub; + rk_timevaladd; + rk_timevalfix; + rk_timevalsub; + rk_tsearch; + rk_twalk; + rk_undumpdata; + rk_unparse_flags; + rk_unparse_time; + rk_unparse_time_approx; + rk_unparse_units; + rk_unparse_units_approx; + rk_unvis; + rk_vasnprintf; + rk_vasprintf; + rk_vis; + rk_vsnprintf; + rk_vstrcollect; + rk_wait_for_process; + rk_wait_for_process_timed; + rk_warnerr; + rk_xfree; + roken_concat; + roken_detach_finish; + roken_detach_prep; + roken_getaddrinfo_hostspec2; + roken_getaddrinfo_hostspec; + roken_gethostby_setup; + roken_gethostbyaddr; + roken_gethostbyname; + roken_get_appdatadir; + roken_get_homedir; + roken_get_shell; + roken_get_username; + roken_get_loginname; + roken_mconcat; + roken_vconcat; + roken_vmconcat; + rtbl_add_column; + rtbl_add_column_by_id; + rtbl_add_column_entry; + rtbl_add_column_entry_by_id; + rtbl_add_column_entryv; + rtbl_add_column_entryv_by_id; + rtbl_create; + rtbl_destroy; + rtbl_format; + rtbl_get_flags; + rtbl_new_row; + rtbl_set_column_affix_by_id; + rtbl_set_column_prefix; + rtbl_set_flags; + rtbl_set_prefix; + rtbl_set_separator; + signal; + simple_execl; + tm2time; + unparse_bytes; + unparse_bytes_short; + unparse_flags; + unparse_time; + unparse_time_approx; + unparse_units; + unparse_units_approx; + verr; + verrx; + vwarn; + vwarnx; + warn; + warnx; + writev; + local: + *; +}; diff --git a/third_party/heimdal/lib/roken/versionsupport.h b/third_party/heimdal/lib/roken/versionsupport.h new file mode 100644 index 0000000..09adce3 --- /dev/null +++ b/third_party/heimdal/lib/roken/versionsupport.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018-2019, AuriStor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 _VERSIONSUPPORT_H_ +#define _VERSIONSUPPORT_H_ 1 + +/* + * IsWindowsVersionOrGreater() is provided by Windows SDK 8.1 or greater. + * As AuriStorFS supports building with SDK 7.0 and greater we must + * provide our own. VerifyVersionInfoW() is present on Windows XP and + * later. + */ + +#ifndef _WIN32_WINNT_WIN7 +#define _WIN32_WINNT_WIN7 0x0601 +#endif + +#ifndef _WIN32_WINNT_WIN8 +#define _WIN32_WINNT_WIN8 0x0602 +#endif + +#ifndef _WIN32_WINNT_WINBLUE +#define _WIN32_WINNT_WINBLUE 0x0603 +#endif + +/* Based upon VersionHelpers.h */ +FORCEINLINE BOOL +IsWindowsVersionOrGreater(WORD wMajorVersion, + WORD wMinorVersion, + WORD wServicePackMajor) +{ + OSVERSIONINFOEXW osvi; + DWORDLONG dwlConditionMask = 0; + + dwlConditionMask = VerSetConditionMask(dwlConditionMask, + VER_MAJORVERSION, + VER_GREATER_EQUAL); + dwlConditionMask = VerSetConditionMask(dwlConditionMask, + VER_MINORVERSION, + VER_GREATER_EQUAL); + dwlConditionMask = VerSetConditionMask(dwlConditionMask, + VER_SERVICEPACKMAJOR, + VER_GREATER_EQUAL); + + memset(&osvi, 0, sizeof(OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + osvi.dwMajorVersion = wMajorVersion; + osvi.dwMinorVersion = wMinorVersion; + osvi.wServicePackMajor = wServicePackMajor; + + return VerifyVersionInfoW(&osvi, + (VER_MAJORVERSION | + VER_MINORVERSION | + VER_SERVICEPACKMAJOR), + dwlConditionMask); +} + +FORCEINLINE BOOL +IsWindowsXPOrGreater(VOID) +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), + LOBYTE(_WIN32_WINNT_WINXP), + 0); +} + +FORCEINLINE BOOL +IsWindows7OrGreater(VOID) +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), + LOBYTE(_WIN32_WINNT_WIN7), + 0); +} + +FORCEINLINE BOOL +IsWindows8OrGreater(VOID) +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), + LOBYTE(_WIN32_WINNT_WIN8), + 0); +} + +FORCEINLINE BOOL +IsWindows8Point1OrGreater(VOID) +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), + LOBYTE(_WIN32_WINNT_WINBLUE), + 0); +} + +#define IS_WINDOWS_VERSION_OR_GREATER_CACHED(fn) \ + \ +FORCEINLINE BOOL \ +fn##Cached(VOID) \ +{ \ + static LONG lIsVersionOrGreater = -1; \ + \ + if (lIsVersionOrGreater == -1) { \ + LONG lResult = fn(); \ + InterlockedCompareExchangeRelease(&lIsVersionOrGreater, \ + lResult, -1); \ + } \ + \ + return lIsVersionOrGreater == 1; \ +} + +IS_WINDOWS_VERSION_OR_GREATER_CACHED(IsWindowsXPOrGreater) +IS_WINDOWS_VERSION_OR_GREATER_CACHED(IsWindows7OrGreater) +IS_WINDOWS_VERSION_OR_GREATER_CACHED(IsWindows8OrGreater) +IS_WINDOWS_VERSION_OR_GREATER_CACHED(IsWindows8Point1OrGreater) + +#endif /* _VERSIONSUPPORT_H_ */ diff --git a/third_party/heimdal/lib/roken/vis-extras.h b/third_party/heimdal/lib/roken/vis-extras.h new file mode 100644 index 0000000..693edf8 --- /dev/null +++ b/third_party/heimdal/lib/roken/vis-extras.h @@ -0,0 +1,27 @@ +#ifndef _VIS_EXTRAS_H_ +#define _VIS_EXTRAS_H_ + +#include <roken.h> + +ROKEN_CPP_START + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strasvis(char **, const char *, int, const char *); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strasvisx(char **, const char *, size_t, int, const char *); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strrasvis(char **, size_t *, const char *, int, const char *); + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strrasvisx(char **, size_t *, const char *, size_t, int, const char *); + +ROKEN_CPP_END + +#define strasvis(a, b, c, d) rk_strasvis(a, b, c, d) +#define strasvisx(a, b, c, d) rk_strasvisx(a, b, c, d) +#define strrasvis(a, b, c, d) rk_strrasvis(a, b, c, d) +#define strrasvisx(a, b, c, d) rk_strrasvisx(a, b, c, d) + +#endif /* !_VIS_EXTRAS_H_ */ diff --git a/third_party/heimdal/lib/roken/vis.c b/third_party/heimdal/lib/roken/vis.c new file mode 100644 index 0000000..0fe44ae --- /dev/null +++ b/third_party/heimdal/lib/roken/vis.c @@ -0,0 +1,649 @@ +/* $NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl 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, 2005 The NetBSD Foundation, Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#define _DEFAULT_SOURCE +#include <config.h> +#include "roken.h" +#ifdef TEST +#include "getarg.h" +#endif +#ifndef _DIAGASSERT +#define _DIAGASSERT(X) +#endif + +#include <sys/types.h> +#include <assert.h> +#include <ctype.h> +#ifdef TEST +#include <err.h> +#endif +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <vis.h> + +#if !HAVE_VIS || !HAVE_SVIS +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#endif + +#if !HAVE_VIS || !HAVE_SVIS || TEST +/* + * We use makextralist() in main(), so we need it even if we have all the VIS + * routines in the host's C libraries. + */ + +/* 5 is for VIS_SP, VIS_TAB, VIS_NL, VIS_DQ, and VIS_NOSLASH */ +#define MAXEXTRAS (sizeof(char_glob) - 1 + sizeof(char_shell) - 1 + 5) + +#ifndef VIS_SHELL +#define VIS_SHELL 0x2000 +#endif +#ifndef VIS_GLOB +#define VIS_GLOB 0x0100 +#endif + +#ifndef VIS_SP +#define VIS_SP 0x0004 /* also encode space */ +#endif +#ifndef VIS_TAB +#define VIS_TAB 0x0008 /* also encode tab */ +#endif +#ifndef VIS_NL +#define VIS_NL 0x0010 /* also encode newline */ +#endif +#ifndef VIS_WHITE +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#endif +#ifndef VIS_SAFE +#define VIS_SAFE 0x0020 /* only encode "unsafe" characters */ +#endif +#ifndef VIS_DQ +#define VIS_DQ 0x8000 /* also encode double quotes */ +#endif + + +/* + * Expand list of extra characters to not visually encode. + */ +static char * +makeextralist(int flags, const char *src) +{ + static const char char_glob[] = "*?[#"; + static const char char_shell[] = "'`\";&<>()|{}]\\$!^~"; + char *dst, *d; + size_t len; + + len = strlen(src); + if ((dst = d = calloc(1, len + MAXEXTRAS + 1)) == NULL) + return NULL; + + memcpy(dst, src, len); + d += len; + + if (flags & VIS_GLOB) { + memcpy(d, char_glob, sizeof(char_glob) - 1); + d += sizeof(char_glob) - 1; + } + if (flags & VIS_SHELL) { + memcpy(d, char_shell, sizeof(char_shell) - 1); + d += sizeof(char_shell) - 1; + } + + if (flags & VIS_SP) *d++ = ' '; + if (flags & VIS_TAB) *d++ = '\t'; + if (flags & VIS_NL) *d++ = '\n'; + if (flags & VIS_DQ) *d++ = '"'; + if ((flags & VIS_NOSLASH) == 0) *d++ = '\\'; + + return dst; +} +#endif + +#if !HAVE_VIS || !HAVE_SVIS +static char *do_svis(char *, int, int, int, const char *); + +#undef BELL +#if defined(__STDC__) +#define BELL '\a' +#else +#define BELL '\007' +#endif + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_vis (char *, int, int, int); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_svis (char *, int, int, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strvis (char *, const char *, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strsvis (char *, const char *, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strvisx (char *, const char *, size_t, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + 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 xtoa(c) "0123456789abcdef"[c] + +/* + * This is do_hvis, for HTTP style (RFC 1808) + */ +static char * +do_hvis(char *dst, int c, int flag, int nextc, const char *extra) +{ + if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL || + strchr(extra, c)) { + *dst++ = '%'; + *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); + *dst++ = xtoa((unsigned int)c & 0xf); + } else { + dst = do_svis(dst, c, flag, nextc, extra); + } + return dst; +} + +/* + * This is do_vis, the central code 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. + */ +static char * +do_svis(char *dst, int c, int flag, int nextc, const char *extra) +{ + int isextra; + isextra = strchr(extra, c) != NULL; + if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || + ((flag & VIS_SAFE) && issafe(c)))) { + *dst++ = c; + return dst; + } + if (flag & VIS_CSTYLE) { + switch (c) { + case '\n': + *dst++ = '\\'; *dst++ = 'n'; + return dst; + case '\r': + *dst++ = '\\'; *dst++ = 'r'; + return dst; + case '\b': + *dst++ = '\\'; *dst++ = 'b'; + return dst; + case BELL: + *dst++ = '\\'; *dst++ = 'a'; + return dst; + case '\v': + *dst++ = '\\'; *dst++ = 'v'; + return dst; + case '\t': + *dst++ = '\\'; *dst++ = 't'; + return dst; + case '\f': + *dst++ = '\\'; *dst++ = 'f'; + return dst; + case ' ': + *dst++ = '\\'; *dst++ = 's'; + return dst; + case '\0': + *dst++ = '\\'; *dst++ = '0'; + if (isoctal(nextc)) { + *dst++ = '0'; + *dst++ = '0'; + } + return dst; + default: + if (isgraph(c)) { + *dst++ = '\\'; *dst++ = c; + return dst; + } + } + } + if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { + *dst++ = '\\'; + *dst++ = (u_char)(((unsigned int)(u_char)c >> 6) & 03) + '0'; + *dst++ = (u_char)(((unsigned int)(u_char)c >> 3) & 07) + '0'; + *dst++ = (u_char)( c & 07) + '0'; + } else { + if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; + if (c & 0200) { + c &= 0177; *dst++ = 'M'; + } + if (iscntrl(c)) { + *dst++ = '^'; + if (c == 0177) + *dst++ = '?'; + else + *dst++ = c + '@'; + } else { + *dst++ = '-'; *dst++ = c; + } + } + return dst; +} + + +/* + * svis - visually encode characters, also encoding the characters + * pointed to by `extra' + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_svis(char *dst, int c, int flag, int nextc, const char *extra) +{ + char *nextra = NULL; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(extra != NULL); + nextra = makeextralist(flag, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return dst; + } + if (flag & VIS_HTTPSTYLE) + dst = do_hvis(dst, c, flag, nextc, nextra); + else + dst = do_svis(dst, c, flag, nextc, nextra); + free(nextra); + *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. + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strsvis(char *dst, const char *csrc, int flag, const char *extra) +{ + int c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + nextra = makeextralist(flag, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + if (flag & VIS_HTTPSTYLE) { + for (start = dst; (c = *src++) != '\0'; /* empty */) + dst = do_hvis(dst, c, flag, *src, nextra); + } else { + for (start = dst; (c = *src++) != '\0'; /* empty */) + dst = do_svis(dst, c, flag, *src, nextra); + } + free(nextra); + *dst = '\0'; + return (dst - start); +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) +{ + unsigned char c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + nextra = makeextralist(flag, extra); + if (! nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + + if (flag & VIS_HTTPSTYLE) { + for (start = dst; len > 0; len--) { + c = *src++; + dst = do_hvis(dst, c, flag, *src, nextra); + } + } else { + for (start = dst; len > 0; len--) { + c = *src++; + dst = do_svis(dst, c, flag, *src, nextra); + } + } + free(nextra); + *dst = '\0'; + return (dst - start); +} +#endif + +/* + * Heimdal innovations: functions that allocate or reallocate a destination + * buffer as needed. Based on OpenBSD's stravis(). + */ + +#include <vis-extras.h> + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strasvis(char **out, const char *csrc, int flag, const char *extra) +{ + return rk_strasvisx(out, csrc, strlen(csrc), flag, extra); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strrasvis(char **out, size_t *outsz, const char *csrc, int flag, const char *extra) +{ + return rk_strrasvisx(out, outsz, csrc, strlen(csrc), flag, extra); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strasvisx(char **out, const char *csrc, size_t len, int flag, const char *extra) +{ + size_t sz = 0; + + *out = NULL; + return rk_strrasvisx(out, &sz, csrc, strlen(csrc), flag, extra); +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strrasvisx(char **out, + size_t *outsz, + const char *csrc, + size_t len, + int flag, + const char *extra) +{ + size_t want = 4 * len + 4; + size_t have = *outsz; + char *s = *out; + int r; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + if (want < len || want > INT_MAX) { + errno = EOVERFLOW; + return -1; + } + if (have < want) { + if ((s = realloc(s, want)) == NULL) + return -1; + *outsz = want; + *out = s; + } + if (*out == NULL) { + errno = EINVAL; + return -1; + } + **out = '\0'; /* Makes source debugging nicer, that's all */ + r = strsvisx(*out, csrc, len, flag, extra); + return r; +} + +#if !HAVE_VIS +/* + * vis - visually encode characters + */ +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_vis(char *dst, int c, int flag, int nextc) +{ + char *extra = NULL; + unsigned char uc = (unsigned char)c; + + _DIAGASSERT(dst != NULL); + + extra = makeextralist(flag, ""); + if (! extra) { + *dst = '\0'; /* can't create extra, return "" */ + return dst; + } + if (flag & VIS_HTTPSTYLE) + dst = do_hvis(dst, uc, flag, nextc, extra); + else + dst = do_svis(dst, uc, flag, nextc, extra); + free(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. + */ +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strvis(char *dst, const char *src, int flag) +{ + char *extra = NULL; + int rv; + + extra = makeextralist(flag, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvis(dst, src, flag, extra); + free(extra); + return rv; +} + + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strvisx(char *dst, const char *src, size_t len, int flag) +{ + char *extra = NULL; + int rv; + + extra = makeextralist(flag, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvisx(dst, src, len, flag, extra); + free(extra); + return rv; +} +#endif + +#ifdef TEST +static const char *extra_arg = ""; +static int cstyle_flag; +static int glob_flag; +static int help_flag; +static int http_flag; +static int httponly_flag; +static int line_flag; +static int octal_flag; +static int safe_flag; +static int shell_flag; +static int stdin_flag; +static int tab_flag; +static int whitespace_flag; + +/* + * The short options are compatible with a subset of the FreeBSD contrib + * vis(1). Heimdal additions have long option names only. + */ +static struct getargs args[] = { + { "c", 'C', arg_flag, &cstyle_flag, "C style", "C style" }, + { "extra", 'e', arg_string, &extra_arg, "also encode extra", "also encode extra"}, + { "glob", 'g', arg_flag, &glob_flag, "escape glob specials", "escape glob specials" }, + { "help", 0, arg_flag, &help_flag, "help", "help"}, + { "line", 0, arg_flag, &line_flag, "read and escape stdin without escaping newlines", NULL }, + { "octal", 'o', arg_flag, &octal_flag, "octal escape", "octal escape" }, + { "safe", 's', arg_flag, &safe_flag, "only encode \"unsafe\" characters", "only encode \"unsafe\" characters" }, + { "shell", 'S', arg_flag, &shell_flag, "encode shell meta-characters", "encode shell meta-characters" }, + { "stdin", 0, arg_flag, &stdin_flag, "read and escape stdin", NULL }, + { "tab", 't', arg_flag, &tab_flag, "encode tabs", "encode tabs" }, + { "url", 'h', arg_flag, &http_flag, "url escape", "url escape" }, + { "url-only", 0, arg_flag, &httponly_flag, "url escape", "url escape" }, + { "whitespace", 'w', arg_flag, &whitespace_flag, "encode whitespace", "encode whitespace" }, + { 0, 0, 0, 0, 0, 0} +}; +static size_t num_args = sizeof(args)/sizeof(args[0]); + +int +main(int argc, char **argv) +{ + size_t sz = 0; + char *nextra = NULL; + char *s = NULL; + int goptind = 0; + int flags = 0; + + setprogname("vis"); + if (getarg(args, num_args, argc, argv, &goptind) || help_flag) { + arg_printusage(args, num_args, NULL, "strings..."); + return help_flag ? 0 : 1; + } + + argc -= goptind; + argv += goptind; + + if (argc == 0 && !stdin_flag && !line_flag) { + arg_printusage(args, num_args, NULL, "strings..."); + return 1; + } + + if (http_flag && cstyle_flag) + errx(1, "--http and --cstyle are mutually exclusive"); + + flags |= cstyle_flag ? VIS_CSTYLE : 0; + flags |= http_flag ? VIS_HTTPSTYLE : 0; + flags |= httponly_flag ? VIS_HTTPSTYLE | VIS_NOESCAPE : 0; + flags |= octal_flag ? VIS_OCTAL : 0; + flags |= safe_flag ? VIS_SAFE : 0; + flags |= tab_flag ? VIS_TAB : 0; + flags |= whitespace_flag ? VIS_WHITE : 0; + + if ((nextra = makeextralist(flags, extra_arg)) == NULL) + err(1, "Out of memory"); + + while (argc) { + if (rk_strrasvis(&s, &sz, argv[0], flags, nextra) < 0) + err(2, "Out of memory"); + printf("%s\n", s); + argc--; + } + if (line_flag) { + ssize_t nbytes; + size_t linesz = 0; + char *line = NULL; + + while (!feof(stdin) && + (nbytes = getline(&line, &linesz, stdin)) > 0) { + const char *nl = ""; + + if (line[nbytes - 1] == '\n') { + line[--nbytes] = '\0'; + nl = "\n"; + } + + if (rk_strrasvisx(&s, &sz, line, nbytes, flags, nextra) < 0) + err(2, "Out of memory"); + printf("%s%s", s, nl); + } + fflush(stdout); + if (ferror(stdin)) + errx(2, "I/O error"); + } else if (stdin_flag) { + size_t nbytes; + char buf[2048 + 1]; + char vbuf[4 * (sizeof(buf) - 1) + 1]; + + while (!feof(stdin) && + (nbytes = fread(buf, 1, sizeof(buf) - 1, stdin))) { + buf[nbytes] = '\0'; + strsvis(vbuf, buf, flags, nextra); + printf("%s", vbuf); + } + fflush(stdout); + if (ferror(stdin)) + errx(2, "I/O error"); + } + + free(nextra); + free(s); + return 0; +} +#endif diff --git a/third_party/heimdal/lib/roken/vis.hin b/third_party/heimdal/lib/roken/vis.hin new file mode 100644 index 0000000..f1027f5 --- /dev/null +++ b/third_party/heimdal/lib/roken/vis.hin @@ -0,0 +1,170 @@ +/* $NetBSD: vis.h,v 1.16 2005/09/13 01:44:32 christos Exp $ */ + +/*- + * 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 +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#include <sys/types.h> + +#include <roken.h> + +/* + * to select alternate encoding format + */ +#define VIS_OCTAL 0x0001 /* use octal \ddd format */ +#define VIS_CSTYLE 0x0002 /* 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 0x0004 /* also encode space */ +#define VIS_TAB 0x0008 /* also encode tab */ +#define VIS_NL 0x0010 /* also encode newline */ +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#define VIS_SAFE 0x0020 /* only encode "unsafe" characters */ +#define VIS_DQ 0x8000 /* also encode double quotes */ + +/* + * other + */ +#define VIS_NOSLASH 0x0040 /* inhibit printing '\' */ +#define VIS_HTTPSTYLE 0x0080 /* http-style escape % HEX HEX */ +#define VIS_HTTP1808 0x0080 /* http-style escape % hex hex */ +#define VIS_GLOB 0x0100 /* encode glob(3) magic characters */ +#if 0 +/* + * Not yet. FreeBSD calls 0x0400 VIS_HTTP1866, but if that means RFC1866, + * that's HTML 2.0, not HTTP. Argh. + */ +#define VIS_MIMESTYLE 0x0200 /* mime-style escape = HEX HEX */ +#define VIS_HTML1866 0x0400 /* HTML-style &#num; or &string; */ +#endif +#define VIS_NOESCAPE 0x0800 /* don't decode `\'; URL-encode only when given + * with VIS_HTTPSTYLE */ +#if 0 +#define _VIS_END 0x1000 /* for unvis */ +#endif +#define VIS_SHELL 0x2000 /* encode shell special characters [not glob] */ +#define VIS_META (VIS_WHITE | VIS_GLOB | VIS_SHELL) +#define VIS_NOLOCALE 0x4000 /* encode using the C locale */ + +/* + * 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 */ + +ROKEN_CPP_START + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_vis(char *, int, int, int); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL + rk_svis(char *, int, int, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strvis(char *, const char *, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strsvis(char *, const char *, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strvisx(char *, const char *, size_t, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strsvisx(char *, const char *, size_t, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strunvis(char *, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_strunvisx(char *, const char *, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL + rk_unvis(char *, int, int *, int); + +ROKEN_CPP_END + +#ifndef HAVE_VIS +#undef vis +#define vis(a,b,c,d) rk_vis(a,b,c,d) +#endif + +#ifndef HAVE_SVIS +#undef svis +#define svis(a,b,c,d,e) rk_svis(a,b,c,d,e) +#endif + +#ifndef HAVE_STRVIS +#undef strvis +#define strvis(a,b,c) rk_strvis(a,b,c) +#endif + +#ifndef HAVE_STRSVIS +#undef strsvis +#define strsvis(a,b,c,d) rk_strsvis(a,b,c,d) +#endif + +#ifndef HAVE_STRVISX +#undef strvisx +#define strvisx(a,b,c,d) rk_strvisx(a,b,c,d) +#endif + +#ifndef HAVE_STRSVISX +#undef strsvisx +#define strsvisx(a,b,c,d,e) rk_strsvisx(a,b,c,d,e) +#endif + +#ifndef HAVE_STRUNVIS +#undef strunvis +#define strunvis(a,b) rk_strunvis(a,b) +#endif + + +#ifndef HAVE_UNVIS +#undef unvis +#define unvis(a,b,c,d) rk_unvis(a,b,c,d) +#endif + +#endif /* !_VIS_H_ */ diff --git a/third_party/heimdal/lib/roken/vsyslog.c b/third_party/heimdal/lib/roken/vsyslog.c new file mode 100644 index 0000000..aea7086 --- /dev/null +++ b/third_party/heimdal/lib/roken/vsyslog.c @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#include <config.h> + +#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' + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vsyslog(int pri, const char *fmt, va_list ap) +{ + char *fmt2; + const char *p; + char *p2; + int ret; + 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'; + + ret = vasprintf (&buf, fmt2, ap); + free (fmt2); + if (ret < 0 || buf == NULL) { + simple_vsyslog (pri, fmt, ap); + return; + } + syslog (pri, "%s", buf); + free (buf); +} +#endif diff --git a/third_party/heimdal/lib/roken/vwarn.c b/third_party/heimdal/lib/roken/vwarn.c new file mode 100644 index 0000000..8f1706d --- /dev/null +++ b/third_party/heimdal/lib/roken/vwarn.c @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <err.h> + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vwarn(const char *fmt, va_list ap) +{ + rk_warnerr(1, fmt, ap); +} diff --git a/third_party/heimdal/lib/roken/vwarnx.c b/third_party/heimdal/lib/roken/vwarnx.c new file mode 100644 index 0000000..6fb1d8c --- /dev/null +++ b/third_party/heimdal/lib/roken/vwarnx.c @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include <err.h> + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +vwarnx(const char *fmt, va_list ap) +{ + rk_warnerr(0, fmt, ap); +} + diff --git a/third_party/heimdal/lib/roken/warn.c b/third_party/heimdal/lib/roken/warn.c new file mode 100644 index 0000000..e149c56 --- /dev/null +++ b/third_party/heimdal/lib/roken/warn.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include "err.h" + +void +warn(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} diff --git a/third_party/heimdal/lib/roken/warnerr.c b/third_party/heimdal/lib/roken/warnerr.c new file mode 100644 index 0000000..9e67023 --- /dev/null +++ b/third_party/heimdal/lib/roken/warnerr.c @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" +#include "err.h" + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_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/third_party/heimdal/lib/roken/warnx.c b/third_party/heimdal/lib/roken/warnx.c new file mode 100644 index 0000000..cf33939 --- /dev/null +++ b/third_party/heimdal/lib/roken/warnx.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. + */ + +#include <config.h> + +#include "err.h" + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} diff --git a/third_party/heimdal/lib/roken/win32_alloc.c b/third_party/heimdal/lib/roken/win32_alloc.c new file mode 100644 index 0000000..40fe0f4 --- /dev/null +++ b/third_party/heimdal/lib/roken/win32_alloc.c @@ -0,0 +1,76 @@ +/*********************************************************************** + * Copyright (c) 2012, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 "roken.h" +#undef calloc +#undef malloc +#undef free +#undef strdup +#undef wcsdup + +/* + * Windows executables and dlls suffer when memory is + * allocated with one allocator and deallocated with + * another because each allocator is backed by a separate + * heap. Reduce the exposure by ensuring that all + * binaries that are built using roken will build against + * same allocator. + */ + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_calloc(size_t elements, size_t size) +{ + return calloc( elements, size); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_free(void * ptr) +{ + free( ptr); +} + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL +rk_malloc(size_t size) +{ + return malloc( size); +} + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +rk_strdup(const char *str) +{ + return strdup( str); +} + +ROKEN_LIB_FUNCTION unsigned short * ROKEN_LIB_CALL +rk_wcsdup(const unsigned short *str) +{ + return wcsdup( str); +} diff --git a/third_party/heimdal/lib/roken/win32_version.c b/third_party/heimdal/lib/roken/win32_version.c new file mode 100644 index 0000000..faf05b8 --- /dev/null +++ b/third_party/heimdal/lib/roken/win32_version.c @@ -0,0 +1,128 @@ +#include <config.h> +#include "roken.h" +#include <psapi.h> + +static DWORD +GetVersionInfo(CHAR *filename, CHAR *szOutput, DWORD dwOutput) +{ + DWORD dwVersionHandle; + LPVOID pVersionInfo = 0; + DWORD retval = 0; + LPDWORD pLangInfo = 0; + LPTSTR szVersion = 0; + UINT len = 0; + TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion"); + DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle); + + if (!size) + return GetLastError(); + + pVersionInfo = malloc(size); + if (!pVersionInfo) + return ERROR_NOT_ENOUGH_MEMORY; + + GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo); + if (retval = GetLastError()) + goto cleanup; + + VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"), + (LPVOID*)&pLangInfo, &len); + if (retval = GetLastError()) + goto cleanup; + + wsprintf(szVerQ, + TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"), + LOWORD(*pLangInfo), HIWORD(*pLangInfo)); + + VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len); + if (retval = GetLastError()) { + /* try again with language 409 since the old binaries were tagged wrong */ + wsprintf(szVerQ, + TEXT("\\StringFileInfo\\0409%04x\\FileVersion"), + HIWORD(*pLangInfo)); + + VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len); + if (retval = GetLastError()) + goto cleanup; + } + snprintf(szOutput, dwOutput, TEXT("%s"), szVersion); + szOutput[dwOutput - 1] = 0; + + cleanup: + free(pVersionInfo); + + return retval; +} + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +win32_getLibraryVersion(const char *libname, char **outname, char **outversion) +{ + CHAR modVersion[128]; + HMODULE hMods[1024]; + HANDLE hProcess; + DWORD cbNeeded; + unsigned int i; + int success = -1; + HINSTANCE hPSAPI; + DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize); + BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded); + + if (outversion) + *outversion = NULL; + if (outname) + *outname = NULL; + + hPSAPI = LoadLibrary("psapi"); + if ( hPSAPI == NULL ) + return -1; + + if (((FARPROC) pGetModuleFileNameExA = + GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL || + ((FARPROC) pEnumProcessModules = + GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL) + { + goto out; + } + + // Get a list of all the modules in this process. + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, GetCurrentProcessId()); + + if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) + { + for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) + { + char szModName[2048]; + + // Get the full path to the module's file. + if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName))) + { + CHAR checkName[1024]; + lstrcpy(checkName, szModName); + strlwr(checkName); + + if (strstr(checkName, libname)) { + if (GetVersionInfo(szModName, modVersion, sizeof(modVersion)) == 0) { + success = 0; + if (outversion) { + *outversion = strdup(modVersion); + if (*outversion == NULL) + success = -1; + } + if (outname) { + *outname = strdup(szModName); + if (*outname == NULL) + success = -1; + } + } + break; + } + } + } + } + CloseHandle(hProcess); + + out: + FreeLibrary(hPSAPI); + return success; +} diff --git a/third_party/heimdal/lib/roken/write_pid.c b/third_party/heimdal/lib/roken/write_pid.c new file mode 100644 index 0000000..cf5299b --- /dev/null +++ b/third_party/heimdal/lib/roken/write_pid.c @@ -0,0 +1,117 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +#ifdef HAVE_UTIL_H +#include <util.h> +#endif + +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +pid_file_write(const char *progname) +{ + const char *pidfile_dir = NULL; + char *ret = NULL; + FILE *fp; + + /* + * Maybe we could have a version of this function (and pidfile()) + * where we get a directory from the caller. That would allow us to + * have command-line options for the daemons for this. + * + * For now we use an environment variable. + */ + pidfile_dir = secure_getenv("HEIM_PIDFILE_DIR"); + if (pidfile_dir == NULL) + pidfile_dir = _PATH_VARRUN; + + if (asprintf(&ret, "%s%s.pid", pidfile_dir, progname) < 0 || ret == NULL) + return NULL; + fp = fopen(ret, "w"); + if (fp == NULL) { + free(ret); + return NULL; + } + fprintf(fp, "%lu\n", (unsigned long)getpid()); + fclose(fp); + return ret; +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +pid_file_delete(char **filename) +{ + if (*filename != NULL) { + unlink(*filename); + free(*filename); + *filename = NULL; + } +} + +static char *pidfile_path; +static pid_t pidfile_pid; + +static void +pidfile_cleanup(void) +{ + if (pidfile_path != NULL && pidfile_pid == getpid()) + pid_file_delete(&pidfile_path); +} + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +rk_pidfile(const char *bname) +{ + /* + * If the OS has a pidfile(), call that, but still call + * pid_file_write(). Even if both want to write the same file, + * writing it twice will still work. + */ +#ifdef HAVE_PIDFILE + pidfile(bname); +#endif + + if (pidfile_path != NULL) + return; + if (bname == NULL) + bname = getprogname(); + pidfile_path = pid_file_write(bname); + pidfile_pid = getpid(); +#if defined(HAVE_ATEXIT) + if (pidfile_path != NULL) + atexit(pidfile_cleanup); +#elif defined(HAVE_ON_EXIT) + if (pidfile_path != NULL) + on_exit(pidfile_cleanup); +#endif +} diff --git a/third_party/heimdal/lib/roken/writev.c b/third_party/heimdal/lib/roken/writev.c new file mode 100644 index 0000000..80945e9 --- /dev/null +++ b/third_party/heimdal/lib/roken/writev.c @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#include <config.h> + +#include "roken.h" + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +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/third_party/heimdal/lib/roken/xdbm.h b/third_party/heimdal/lib/roken/xdbm.h new file mode 100644 index 0000000..c2c6c28 --- /dev/null +++ b/third_party/heimdal/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$ */ + +/* 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__ */ diff --git a/third_party/heimdal/lib/roken/xfree.c b/third_party/heimdal/lib/roken/xfree.c new file mode 100644 index 0000000..c7e30da --- /dev/null +++ b/third_party/heimdal/lib/roken/xfree.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008 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. + */ + +#include <config.h> + +#include "roken.h" + +void ROKEN_LIB_FUNCTION +rk_xfree (void *buf) +{ + free(buf); +} |