stagit

static git page generator
git clone git://git.sgregoratto.me/stagit
Log | Files | Refs | README | LICENSE

commit 021201a8580aa75c7301ec3e0c1a359d289a75b7
parent d6937c195f3459194d5ab056397981e1ade54871
Author: Stephen Gregoratto <dev@sgregoratto.me>
Date:   Sat, 20 Jul 2019 00:13:55 +1000

add oconfigure

General:
- Remove the existing copied functions/config.mk
- Change/Simplify Makefile to use oconfigure vars
- Use make builtin rules instead of defining own suffix rules
- Add gitignore

stagit:
- Replace compat.h with config.h, use config.h defines
- Move usage() to main function
- Use getopt for option handling

stagit-index:
- Replace compat.h with config.h, use config.h defines

Diffstat:
A.gitignore | 8++++++++
MMakefile | 70+++++++++++++++++++++-------------------------------------------------
Dcompat.h | 6------
Acompats.c | 1248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dconfig.mk | 30------------------------------
Aconfigure | 1214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dreallocarray.c | 39---------------------------------------
Mstagit-index.c | 8+++++---
Mstagit.c | 75++++++++++++++++++++++++++++++++++++++++-----------------------------------
Dstrlcat.c | 57---------------------------------------------------------
Dstrlcpy.c | 52----------------------------------------------------
Atests.c | 432+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 2968 insertions(+), 271 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.log +*.old +tags +Makefile.configure +config.h +stagit +stagit-index diff --git a/Makefile b/Makefile @@ -1,46 +1,19 @@ -include config.mk +include Makefile.configure NAME = stagit VERSION = 0.9.2 -SRC = \ - stagit.c\ - stagit-index.c -COMPATSRC = \ - reallocarray.c\ - strlcat.c\ - strlcpy.c -BIN = \ - stagit\ - stagit-index -MAN1 = \ - stagit.1\ - stagit-index.1 -DOC = \ - LICENSE\ - README -HDR = compat.h - -COMPATOBJ = \ - reallocarray.o\ - strlcat.o\ - strlcpy.o - -OBJ = ${SRC:.c=.o} ${COMPATOBJ} +BIN = stagit stagit-index +SRC = stagit.c stagit-index.c compats.c +DOC = stagit.1 stagit-index.1 LICENSE README all: ${BIN} -.o: - ${CC} ${LDFLAGS} -o $@ ${LIBS} - -.c.o: - ${CC} -c ${CFLAGS} ${CPPFLAGS} -o $@ -c $< - dist: rm -rf ${NAME}-${VERSION} mkdir -p ${NAME}-${VERSION} cp -f ${MAN1} ${HDR} ${SRC} ${COMPATSRC} ${DOC} \ - Makefile config.mk favicon.png logo.png style.css \ + Makefile favicon.png logo.png style.css \ example_create.sh example_post-receive.sh \ ${NAME}-${VERSION} # make tarball @@ -48,35 +21,33 @@ dist: gzip -c > ${NAME}-${VERSION}.tar.gz rm -rf ${NAME}-${VERSION} -${OBJ}: config.mk ${HDR} - -stagit: stagit.o ${COMPATOBJ} - ${CC} -o $@ stagit.o ${COMPATOBJ} ${LDFLAGS} +stagit: stagit.c compats.o + ${CC} ${CFLAGS} ${LDFLAGS} -o $@ stagit.c compats.o -stagit-index: stagit-index.o ${COMPATOBJ} - ${CC} -o $@ stagit-index.o ${COMPATOBJ} ${LDFLAGS} +stagit-index: stagit-index.c compats.o + ${CC} ${CFLAGS} ${LDFLAGS} -o $@ stagit-index.c compats.o clean: - rm -f ${BIN} ${OBJ} ${NAME}-${VERSION}.tar.gz + rm -f stagit stagit-index ${OBJS} ${NAME}-${VERSION}.tar.gz install: all # installing executable files. - mkdir -p ${DESTDIR}${PREFIX}/bin - cp -f ${BIN} ${DESTDIR}${PREFIX}/bin - for f in ${BIN}; do chmod 755 ${DESTDIR}${PREFIX}/bin/$$f; done + mkdir -p ${DESTDIR}${BINDIR} + ${INSTALL_BIN} stagit ${DESTDIR}${BINDIR} + ${INSTALL_BIN} stagit-index ${DESTDIR}${BINDIR} # installing example files. - mkdir -p ${DESTDIR}${DOCPREFIX} - cp -f style.css\ + mkdir -p ${DESTDIR}${SHAREDIR}/doc + cp -f style.css\ favicon.png\ logo.png\ example_create.sh\ example_post-receive.sh\ README\ - ${DESTDIR}${DOCPREFIX} + ${DESTDIR}${SHAREDIR}/doc # installing manual pages. - mkdir -p ${DESTDIR}${MANPREFIX}/man1 - cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1 - for m in ${MAN1}; do chmod 644 ${DESTDIR}${MANPREFIX}/man1/$$m; done + mkdir -p ${DESTDIR}${MANDIR}/man1 + ${INSTALL_MAN} stagit.1 ${DESTDIR}${MANDIR}/man1 + ${INSTALL_MAN} stagit-index.1 ${DESTDIR}${MANDIR}/man1 uninstall: # removing executable files. @@ -91,6 +62,7 @@ uninstall: ${DESTDIR}${DOCPREFIX}/README -rmdir ${DESTDIR}${DOCPREFIX} # removing manual pages. - for m in ${MAN1}; do rm -f ${DESTDIR}${MANPREFIX}/man1/$$m; done + rm -f ${DESTDIR}${MANDIR}/man1/stagit.1 + rm -f ${DESTDIR}${MANDIR}/man1/stagit-index.1 .PHONY: all clean dist install uninstall diff --git a/compat.h b/compat.h @@ -1,6 +0,0 @@ -#undef strlcat -size_t strlcat(char *, const char *, size_t); -#undef strlcpy -size_t strlcpy(char *, const char *, size_t); -#undef reallocarray -void *reallocarray(void *, size_t, size_t); diff --git a/compats.c b/compats.c @@ -0,0 +1,1248 @@ +#include "config.h" +#if !HAVE_ERR +/* + * Copyright (c) 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 <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +vwarnx(const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); +} + +void +vwarn(const char *fmt, va_list ap) +{ + int sverrno; + + sverrno = errno; + vwarnx(fmt, ap); + if (fmt != NULL) + fputs(": ", stderr); + fprintf(stderr, "%s\n", strerror(sverrno)); +} + +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); + fputc('\n', stderr); + exit(eval); +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} + +void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); + fputc('\n', stderr); +} +#endif /* !HAVE_ERR */ +#if !HAVE_B64_NTOP +/* $OpenBSD$ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> + +#include <stdlib.h> +#include <string.h> + +static const char b64_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char b64_Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = b64_Base64[output[0]]; + target[datalength++] = b64_Base64[output[1]]; + target[datalength++] = b64_Base64[output[2]]; + target[datalength++] = b64_Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = b64_Base64[output[0]]; + target[datalength++] = b64_Base64[output[1]]; + if (srclength == 1) + target[datalength++] = b64_Pad64; + else + target[datalength++] = b64_Base64[output[2]]; + target[datalength++] = b64_Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(char const *src, u_char *target, size_t targsize) +{ + int state, ch; + size_t tarindex; + u_char nextbyte; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = (unsigned char)*src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == b64_Pad64) + break; + + pos = strchr(b64_Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - b64_Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - b64_Base64) >> 4; + nextbyte = ((pos - b64_Base64) & 0x0f) << 4; + if (tarindex + 1 < targsize) + target[tarindex+1] = nextbyte; + else if (nextbyte) + return (-1); + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - b64_Base64) >> 2; + nextbyte = ((pos - b64_Base64) & 0x03) << 6; + if (tarindex + 1 < targsize) + target[tarindex+1] = nextbyte; + else if (nextbyte) + return (-1); + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - b64_Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == b64_Pad64) { /* We got a pad char. */ + ch = (unsigned char)*src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = (unsigned char)*src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != b64_Pad64) + return (-1); + ch = (unsigned char)*src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = (unsigned char)*src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && tarindex < targsize && + target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} +#endif /* !HAVE_B64_NTOP */ +#if !HAVE_EXPLICIT_BZERO +/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */ +/* + * Public domain. + * Written by Ted Unangst + */ + +#include <string.h> + +/* + * explicit_bzero - don't let the compiler optimize away bzero + */ + +#if HAVE_MEMSET_S + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + (void)memset_s(p, n, 0, n); +} + +#else /* HAVE_MEMSET_S */ + +/* + * Indirect bzero through a volatile pointer to hopefully avoid + * dead-store optimisation eliminating the call. + */ +static void (* volatile ssh_bzero)(void *, size_t) = bzero; + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + /* + * clang -fsanitize=memory needs to intercept memset-like functions + * to correctly detect memory initialisation. Make sure one is called + * directly since our indirection trick above sucessfully confuses it. + */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + memset(p, 0, n); +# endif +#endif + + ssh_bzero(p, n); +} + +#endif /* HAVE_MEMSET_S */ +#endif /* !HAVE_EXPLICIT_BZERO */ +#if !HAVE_GETPROGNAME +/* + * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com> + * Copyright (c) 2017 Kristaps Dzonsons <kristaps@bsd.lv> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <errno.h> + +#if HAVE_PROGRAM_INVOCATION_SHORT_NAME +const char * +getprogname(void) +{ + return (program_invocation_short_name); +} +#elif HAVE___PROGNAME +const char * +getprogname(void) +{ + extern char *__progname; + + return (__progname); +} +#else +static const char *progname; + +void +setprogname(const char *name) +{ + progname = name; +} + +const char * +getprogname(void) +{ + return progname; +} +#endif +#endif /* !HAVE_GETPROGNAME */ +#if !HAVE_MD5 +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value) >> 56; \ + (cp)[6] = (value) >> 48; \ + (cp)[5] = (value) >> 40; \ + (cp)[4] = (value) >> 32; \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +static u_int8_t PADDING[MD5_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(MD5_CTX *ctx) +{ + ctx->count = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) +{ + size_t have, need; + + /* Check how many bytes we already have and how many more we need. */ + have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); + need = MD5_BLOCK_LENGTH - have; + + /* Update bitcount */ + ctx->count += (u_int64_t)len << 3; + + if (len >= need) { + if (have != 0) { + memcpy(ctx->buffer + have, input, need); + MD5Transform(ctx->state, ctx->buffer); + input += need; + len -= need; + have = 0; + } + + /* Process data in MD5_BLOCK_LENGTH-byte chunks. */ + while (len >= MD5_BLOCK_LENGTH) { + MD5Transform(ctx->state, input); + input += MD5_BLOCK_LENGTH; + len -= MD5_BLOCK_LENGTH; + } + } + + /* Handle any remaining bytes of data. */ + if (len != 0) + memcpy(ctx->buffer + have, input, len); +} + +/* + * Pad pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Pad(MD5_CTX *ctx) +{ + u_int8_t count[8]; + size_t padlen; + + /* Convert count to 8 bytes in little endian order. */ + PUT_64BIT_LE(count, ctx->count); + + /* Pad out to 56 mod 64. */ + padlen = MD5_BLOCK_LENGTH - + ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += MD5_BLOCK_LENGTH; + MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + MD5Update(ctx, count, 8); +} + +/* + * Final wrapup--call MD5Pad, fill in digest and zero out ctx. + */ +void +MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) +{ + int i; + + MD5Pad(ctx); + for (i = 0; i < 4; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); + memset(ctx, 0, sizeof(*ctx)); +} + + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; + +#if BYTE_ORDER == LITTLE_ENDIAN + memcpy(in, block, sizeof(in)); +#else + for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { + in[a] = (u_int32_t)( + (u_int32_t)(block[a * 4 + 0]) | + (u_int32_t)(block[a * 4 + 1]) << 8 | + (u_int32_t)(block[a * 4 + 2]) << 16 | + (u_int32_t)(block[a * 4 + 3]) << 24); + } +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +char * +MD5End(MD5_CTX *ctx, char *buf) +{ + int i; + unsigned char digest[MD5_DIGEST_LENGTH]; + static const char hex[]="0123456789abcdef"; + + if (!buf) + buf = malloc(2*MD5_DIGEST_LENGTH + 1); + if (!buf) + return 0; + MD5Final(digest, ctx); + for (i = 0; i < MD5_DIGEST_LENGTH; i++) { + buf[i+i] = hex[digest[i] >> 4]; + buf[i+i+1] = hex[digest[i] & 0x0f]; + } + buf[i+i] = '\0'; + return buf; +} +#endif /* !HAVE_MD5 */ +#if !HAVE_MEMMEM +/*- + * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The name of the author may not 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. + */ +/* + * Find the first occurrence of the byte string s in byte string l. + */ +void * +memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ + const char *cur, *last; + const char *cl = l; + const char *cs = s; + + /* a zero length needle should just return the haystack */ + if (l_len == 0) + return (void *)cl; + + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; + + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, *cs, l_len); + + /* the last position where its possible to find "s" in "l" */ + last = cl + l_len - s_len; + + for (cur = cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return (void *)cur; + + return NULL; +} +#endif /* !HAVE_MEMMEM */ +#if !HAVE_MEMRCHR +/* + * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <string.h> + +/* + * Reverse memchr() + * Find the last occurrence of 'c' in the buffer 's' of size 'n'. + */ +void * +memrchr(const void *s, int c, size_t n) +{ + const unsigned char *cp; + + if (n != 0) { + cp = (unsigned char *)s + n; + do { + if (*(--cp) == (unsigned char)c) + return((void *)cp); + } while (--n != 0); + } + return(NULL); +} +#endif /* !HAVE_MEMRCHR */ +#if !HAVE_REALLOCARRAY +/* + * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} +#endif /* !HAVE_REALLOCARRAY */ +#if !HAVE_RECALLOCARRAY +/* + * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ + +#include <errno.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} +#endif /* !HAVE_RECALLOCARRAY */ +#if !HAVE_STRLCAT +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <string.h> + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} +#endif /* !HAVE_STRLCAT */ +#if !HAVE_STRLCPY +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <string.h> + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif /* !HAVE_STRLCPY */ +#if !HAVE_STRNDUP +/* $OpenBSD$ */ +/* + * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +char * +strndup(const char *str, size_t maxlen) +{ + char *copy; + size_t len; + + len = strnlen(str, maxlen); + copy = malloc(len + 1); + if (copy != NULL) { + (void)memcpy(copy, str, len); + copy[len] = '\0'; + } + + return copy; +} +#endif /* !HAVE_STRNDUP */ +#if !HAVE_STRNLEN +/* $OpenBSD$ */ + +/* + * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <string.h> + +size_t +strnlen(const char *str, size_t maxlen) +{ + const char *cp; + + for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--) + ; + + return (size_t)(cp - str); +} +#endif /* !HAVE_STRNLEN */ +#if !HAVE_STRTONUM +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} +#endif /* !HAVE_STRTONUM */ diff --git a/config.mk b/config.mk @@ -1,30 +0,0 @@ -# customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/man -DOCPREFIX = ${PREFIX}/share/doc/stagit - -# compiler and linker -#CC = cc - -GITINC = /usr/local/include -GITLIB = /usr/local/lib - -# includes and libs -INCS = -I${GITINC} -LIBS = -L${GITLIB} -lgit2 - -# debug -#CFLAGS = -fstack-protector-all -O0 -g -std=c99 -Wall -Wextra -pedantic ${INCS} -#LDFLAGS = ${LIBS} - -# optimized -CFLAGS = -O2 -std=c99 ${INCS} -LDFLAGS = -s ${LIBS} - -# optimized static -#CFLAGS = -static -O2 -std=c99 ${INCS} -#LDFLAGS = -static -s ${LIBS} - -CPPFLAGS = -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE -D_BSD_SOURCE ${INCS} diff --git a/configure b/configure @@ -0,0 +1,1214 @@ +#! /bin/sh +# +# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org> +# Copyright (c) 2017, 2018 Kristaps Dzonsons <kristaps@bsd.lv> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +OCONFIGURE_VERSION="0.1.8" + +# +# This script outputs two files: config.h and Makefile.configure. +# It tries to read from configure.local, which contains predefined +# values we won't autoconfigure. +# +# If you want to use configure with your project, have your GNUmakefile +# or BSDmakefile---whichever---try to import/include Makefile.configure +# at the beginning of the file. +# +# Like so (note no quotes, no period, etc.): +# +# include Makefile.configure +# +# If it exists, configure was run; otherwise, it wasn't. +# +# You'll probably want to change parts of this file. I've noted the +# parts that you'll probably change in the section documentation. +# +# See https://github.com/kristapsdz/oconfigure for more. + +set -e + +#---------------------------------------------------------------------- +# Prepare for running: move aside previous configure runs. +# Output file descriptor usage: +# 1 (stdout): config.h or Makefile.configure +# 2 (stderr): original stderr, usually to the console +# 3: config.log +# You DO NOT want to change this. +#---------------------------------------------------------------------- + +[ -w config.log ] && mv config.log config.log.old +[ -w config.h ] && mv config.h config.h.old + +exec 3> config.log +echo "config.log: writing..." + +#---------------------------------------------------------------------- +# Initialize all variables here such that nothing can leak in from the +# environment except for CC and CFLAGS, which we might have passed in. +#---------------------------------------------------------------------- + +CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -sf -` +CFLAGS=`printf "all:\\n\\t@echo \\\$(CFLAGS)\\n" | make -sf -` +CFLAGS="${CFLAGS} -g -O2 -std=c99" +LDADD= +CPPFLAGS="-D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE -D_BSD_SOURCE" +LDFLAGS="-s -lgit2" +DESTDIR= +PREFIX="/usr/local" +BINDIR= +SBINDIR= +INCLUDEDIR= +LIBDIR= +MANDIR= +SHAREDIR= +INSTALL="install" +INSTALL_PROGRAM= +INSTALL_LIB= +INSTALL_MAN= +INSTALL_DATA= + +#---------------------------------------------------------------------- +# Allow certain variables to be overriden on the command line. +#---------------------------------------------------------------------- + +for keyvals in "$@" +do + key=`echo $keyvals | cut -s -d '=' -f 1` + if [ -z "$key" ] + then + echo "$0: invalid key-value: $keyvals" 1>&2 + exit 1 + fi + val=`echo $keyvals | cut -d '=' -f 2-` + case "$key" in + LDADD) + LDADD="$val" ;; + LDFLAGS) + LDFLAGS="$val" ;; + CPPFLAGS) + CPPFLAGS="$val" ;; + DESTDIR) + DESTDIR="$val" ;; + PREFIX) + PREFIX="$val" ;; + MANDIR) + MANDIR="$val" ;; + LIBDIR) + LIBDIR="$val" ;; + BINDIR) + BINDIR="$val" ;; + SHAREDIR) + SHAREDIR="$val" ;; + SBINDIR) + SBINDIR="$val" ;; + INCLUDEDIR) + INCLUDEDIR="$val" ;; + *) + echo "$0: invalid key: $key" 1>&2 + exit 1 + esac +done + + +#---------------------------------------------------------------------- +# These are the values that will be pushed into config.h after we test +# for whether they're supported or not. +# Each of these must have a runtest(), below. +# Please sort by alpha, for clarity. +# You WANT to change this. +#---------------------------------------------------------------------- + +HAVE_ARC4RANDOM= +HAVE_B64_NTOP= +HAVE_CAPSICUM= +HAVE_ERR= +HAVE_EXPLICIT_BZERO= +HAVE_GETPROGNAME= +HAVE_INFTIM= +HAVE_MD5= +HAVE_MEMMEM= +HAVE_MEMRCHR= +HAVE_MEMSET_S= +HAVE_PATH_MAX= +HAVE_PLEDGE= +HAVE_PROGRAM_INVOCATION_SHORT_NAME= +HAVE_REALLOCARRAY= +HAVE_RECALLOCARRAY= +HAVE_SANDBOX_INIT= +HAVE_SECCOMP_FILTER= +HAVE_SOCK_NONBLOCK= +HAVE_STRLCAT= +HAVE_STRLCPY= +HAVE_STRNDUP= +HAVE_STRNLEN= +HAVE_STRTONUM= +HAVE_SYSTRACE= +HAVE_UNVEIL= +HAVE_ZLIB= +HAVE___PROGNAME= + +#---------------------------------------------------------------------- +# Allow configure.local to override all variables, default settings, +# command-line arguments, and tested features, above. +# You PROBABLY DO NOT want to change this. +#---------------------------------------------------------------------- + +if [ -r ./configure.local ]; then + echo "configure.local: reading..." 1>&2 + echo "configure.local: reading..." 1>&3 + cat ./configure.local 1>&3 + . ./configure.local +else + echo "configure.local: no (fully automatic configuration)" 1>&2 + echo "configure.local: no (fully automatic configuration)" 1>&3 +fi + +echo 1>&3 + +#---------------------------------------------------------------------- +# Infrastructure for running tests. +# These consists of a series of functions that will attempt to run the +# given test file and record its exit into a HAVE_xxx variable. +# You DO NOT want to change this. +#---------------------------------------------------------------------- + +COMP="${CC} ${CFLAGS} ${CPPFLAGS} -Wno-unused -Werror" + +# Check whether this HAVE_ setting is manually overridden. +# If yes, use the override, if no, do not decide anything yet. +# Arguments: lower-case test name, manual value + +ismanual() { + [ -z "${3}" ] && return 1 + echo "${1}: manual (HAVE_${2}=${3})" 1>&2 + echo "${1}: manual (HAVE_${2}=${3})" 1>&3 + echo 1>&3 + return 0 +} + +# Run a single autoconfiguration test. +# In case of success, enable the feature. +# In case of failure, do not decide anything yet. +# Arguments: lower-case test name, upper-case test name, additional +# CFLAGS, additional LIBS. + +singletest() { + extralib="" + cat 1>&3 << __HEREDOC__ +${1}: testing... +${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${4} +__HEREDOC__ + if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${4} 1>&3 2>&3; then + echo "${1}: ${CC} succeeded" 1>&3 + else + if [ -n "${5}" ] ; then + echo "${1}: ${CC} failed with $? (retrying)" 1>&3 + cat 1>&3 << __HEREDOC__ +${1}: testing... +${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${5} +__HEREDOC__ + if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${5} 1>&3 2>&3; then + echo "${1}: ${CC} succeeded" 1>&3 + extralib="(with ${5})" + else + echo "${1}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + else + echo "${1}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + fi + + echo "${1}: yes ${extralib}" 1>&2 + echo "${1}: yes ${extralib}" 1>&3 + echo 1>&3 + eval HAVE_${2}=1 + rm "test-${1}" + return 0 + + # Don't actually run the test: none of our tests check for + # run-time behaviour. + # if ./test-${1} 1>&3 2>&3; then + # echo "${1}: yes" 1>&2 + # echo "${1}: yes" 1>&3 + # echo 1>&3 + # eval HAVE_${2}=1 + # rm "test-${1}" + # return 0 + # else + # echo "${1}: execution failed with $?" 1>&3 + # echo 1>&3 + # rm "test-${1}" + # return 1 + # fi +} + +# Run a complete autoconfiguration test, including the check for +# a manual override and disabling the feature on failure. +# Arguments: lower case name, upper case name, additional CFLAGS, +# additional LDADD, alternative LDADD. + +runtest() { + eval _manual=\${HAVE_${2}} + ismanual "${1}" "${2}" "${_manual}" && return 0 + singletest "${1}" "${2}" "${3}" "${4}" "${5}" && return 0 + echo "${1}: no" 1>&2 + eval HAVE_${2}=0 + return 1 +} + +#---------------------------------------------------------------------- +# Begin running the tests themselves. +# All of your tests must be defined here. +# Please sort as the HAVE_xxxx values were defined. +# You WANT to change this. +# It consists of the following columns: +# runtest +# (1) test file +# (2) macro to set +# (3) argument to cc *before* -o +# (4) argument to cc *after* +# (5) alternative argument to cc *after* +#---------------------------------------------------------------------- + +runtest arc4random ARC4RANDOM || true +runtest b64_ntop B64_NTOP "" "" "-lresolv" || true +runtest capsicum CAPSICUM || true +runtest err ERR || true +runtest explicit_bzero EXPLICIT_BZERO || true +runtest getprogname GETPROGNAME || true +runtest INFTIM INFTIM || true +runtest md5 MD5 "" "" "-lmd" || true +runtest memmem MEMMEM || true +runtest memrchr MEMRCHR || true +runtest memset_s MEMSET_S || true +runtest PATH_MAX PATH_MAX || true +runtest pledge PLEDGE || true +runtest program_invocation_short_name PROGRAM_INVOCATION_SHORT_NAME || true +runtest reallocarray REALLOCARRAY || true +runtest recallocarray RECALLOCARRAY || true +runtest sandbox_init SANDBOX_INIT "-Wno-deprecated" || true +runtest seccomp-filter SECCOMP_FILTER || true +runtest SOCK_NONBLOCK SOCK_NONBLOCK || true +runtest strlcat STRLCAT || true +runtest strlcpy STRLCPY || true +runtest strndup STRNDUP || true +runtest strnlen STRNLEN || true +runtest strtonum STRTONUM || true +runtest sys_queue SYS_QUEUE || true +runtest systrace SYSTRACE || true +runtest unveil UNVEIL || true +runtest zlib ZLIB "" "-lz" || true +runtest __progname __PROGNAME || true + +#---------------------------------------------------------------------- +# Output writing: generate the config.h file. +# This file contains all of the HAVE_xxxx variables necessary for +# compiling your source. +# You must include "config.h" BEFORE any other variables. +# You WANT to change this. +#---------------------------------------------------------------------- + +exec > config.h + +# Start with prologue. + +cat << __HEREDOC__ +#ifdef __cplusplus +#error "Do not use C++: this is a C application." +#endif +#if !defined(__GNUC__) || (__GNUC__ < 4) +#define __attribute__(x) +#endif +#if defined(__linux__) || defined(__MINT__) +#define _GNU_SOURCE /* See test-*.c what needs this. */ +#endif +#if !defined(__BEGIN_DECLS) +# define __BEGIN_DECLS +#endif +#if !defined(__END_DECLS) +# define __END_DECLS +#endif +__HEREDOC__ + +# For the function declaration variables... + +[ ${HAVE_MD5} -eq 0 -o \ + ${HAVE_REALLOCARRAY} -eq 0 -o \ + ${HAVE_RECALLOCARRAY} -eq 0 -o \ + ${HAVE_STRLCAT} -eq 0 -o \ + ${HAVE_STRLCPY} -eq 0 -o \ + ${HAVE_STRNDUP} -eq 0 -o \ + ${HAVE_STRNLEN} -eq 0 ] \ + && echo "#include <sys/types.h>" + +[ ${HAVE_ERR} -eq 0 ] \ + && echo "#include <stdarg.h>" + +# Now we handle our HAVE_xxxx values. +# Most will just be defined as 0 or 1. + +[ ${HAVE_PATH_MAX} -eq 0 ] \ + && echo "#define PATH_MAX 4096" + +[ ${HAVE_INFTIM} -eq 0 ] \ + && echo "#define INFTIM (-1)" + +cat << __HEREDOC__ +#define HAVE_ARC4RANDOM ${HAVE_ARC4RANDOM} +#define HAVE_B64_NTOP ${HAVE_B64_NTOP} +#define HAVE_CAPSICUM ${HAVE_CAPSICUM} +#define HAVE_ERR ${HAVE_ERR} +#define HAVE_EXPLICIT_BZERO ${HAVE_EXPLICIT_BZERO} +#define HAVE_GETPROGNAME ${HAVE_GETPROGNAME} +#define HAVE_INFTIM ${HAVE_INFTIM} +#define HAVE_MD5 ${HAVE_MD5} +#define HAVE_MEMMEM ${HAVE_MEMMEM} +#define HAVE_MEMRCHR ${HAVE_MEMRCHR} +#define HAVE_MEMSET_S ${HAVE_MEMSET_S} +#define HAVE_PATH_MAX ${HAVE_PATH_MAX} +#define HAVE_PLEDGE ${HAVE_PLEDGE} +#define HAVE_PROGRAM_INVOCATION_SHORT_NAME ${HAVE_PROGRAM_INVOCATION_SHORT_NAME} +#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY} +#define HAVE_RECALLOCARRAY ${HAVE_RECALLOCARRAY} +#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT} +#define HAVE_SECCOMP_FILTER ${HAVE_SECCOMP_FILTER} +#define HAVE_SOCK_NONBLOCK ${HAVE_SOCK_NONBLOCK} +#define HAVE_STRLCAT ${HAVE_STRLCAT} +#define HAVE_STRLCPY ${HAVE_STRLCPY} +#define HAVE_STRNDUP ${HAVE_STRNDUP} +#define HAVE_STRNLEN ${HAVE_STRNLEN} +#define HAVE_STRTONUM ${HAVE_STRTONUM} +#define HAVE_SYS_QUEUE ${HAVE_SYS_QUEUE} +#define HAVE_SYSTRACE ${HAVE_SYSTRACE} +#define HAVE_UNVEIL ${HAVE_UNVEIL} +#define HAVE_ZLIB ${HAVE_ZLIB} +#define HAVE___PROGNAME ${HAVE___PROGNAME} +__HEREDOC__ + +# Now we do our function declarations for missing functions. + +if [ ${HAVE_ERR} -eq 0 ]; then + echo "extern void err(int, const char *, ...);" + echo "extern void errx(int, const char *, ...);" + echo "extern void warn(const char *, ...);" + echo "extern void warnx(const char *, ...);" + echo "extern void vwarn(const char *, va_list);" + echo "extern void vwarnx(const char *, va_list);" +fi + +if [ ${HAVE_MD5} -eq 0 ]; then + echo "#define MD5_BLOCK_LENGTH 64" + echo "#define MD5_DIGEST_LENGTH 16" + echo "#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)" + cat <<!! +typedef struct MD5Context { + u_int32_t state[4]; + u_int64_t count; + u_int8_t buffer[MD5_BLOCK_LENGTH]; +} MD5_CTX; +!! + echo "extern void MD5Init(MD5_CTX *);" + echo "extern void MD5Update(MD5_CTX *, const u_int8_t *, size_t);" + echo "extern void MD5Pad(MD5_CTX *);" + echo "extern void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]);" + echo "extern char *MD5End(MD5_CTX *, char *);" + echo "extern void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *);"; +fi + +if [ ${HAVE_SECCOMP_FILTER} -eq 1 ]; then + arch=`uname -m 2>/dev/null || echo unknown` + case "$arch" in + x86_64) + echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64" + ;; + i*86) + echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386" + ;; + arm*) + echo "#define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM" + ;; + esac +fi + +if [ ${HAVE_B64_NTOP} -eq 0 ]; then + echo "extern int b64_ntop(unsigned char const *, size_t, char *, size_t);"; + echo "extern int b64_pton(char const *, unsigned char *, size_t);" +fi + +if [ ${HAVE_EXPLICIT_BZERO} -eq 0 ]; then + echo "extern void explicit_bzero(void *, size_t);" +fi + +if [ ${HAVE_MEMMEM} -eq 0 ]; then + echo "void *memmem(const void *, size_t, const void *, size_t);" +fi + +if [ ${HAVE_MEMRCHR} -eq 0 ]; then + echo "void *memrchr(const void *b, int, size_t);" +fi + +if [ ${HAVE_GETPROGNAME} -eq 0 ]; then + echo "extern const char *getprogname(void);" + if [ ${HAVE_PROGRAM_INVOCATION_SHORT_NAME} -eq 0 -o \ + ${HAVE___PROGNAME} -eq 0 ]; then + echo "extern void setprogname(const char *);" + fi +fi + +if [ ${HAVE_REALLOCARRAY} -eq 0 ]; then + echo "extern void *reallocarray(void *, size_t, size_t);" +fi + +if [ ${HAVE_RECALLOCARRAY} -eq 0 ]; then + echo "extern void *recallocarray(void *, size_t, size_t, size_t);" +fi + +if [ ${HAVE_STRLCAT} -eq 0 ]; then + echo "extern size_t strlcat(char *, const char *, size_t);" +fi + +if [ ${HAVE_STRLCPY} -eq 0 ]; then + echo "extern size_t strlcpy(char *, const char *, size_t);" +fi + +if [ ${HAVE_STRNDUP} -eq 0 ]; then + echo "extern char *strndup(const char *, size_t);" +fi + +if [ ${HAVE_STRNLEN} -eq 0 ]; then + echo "extern size_t strnlen(const char *, size_t);" +fi + +if [ ${HAVE_STRTONUM} -eq 0 ]; then + echo "extern long long strtonum(const char *, long long, long long, const char **);" +fi + +if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then +cat <<!! + +/* $OpenBSD$ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +/* OPENBSD ORIGINAL: sys/sys/queue.h */ + +#ifndef _FAKE_QUEUE_H_ +#define _FAKE_QUEUE_H_ + +/* + * Require for OS/X and other platforms that have old/broken/incomplete + * <sys/queue.h>. + */ +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_ENTRY +#undef SLIST_FOREACH_PREVPTR +#undef SLIST_FOREACH_SAFE +#undef SLIST_FIRST +#undef SLIST_END +#undef SLIST_EMPTY +#undef SLIST_NEXT +#undef SLIST_FOREACH +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_REMOVE_HEAD +#undef SLIST_REMOVE_AFTER +#undef SLIST_REMOVE +#undef SLIST_REMOVE_NEXT +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_END +#undef LIST_EMPTY +#undef LIST_NEXT +#undef LIST_FOREACH +#undef LIST_FOREACH_SAFE +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_END +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_END +#undef TAILQ_NEXT +#undef TAILQ_LAST +#undef TAILQ_PREV +#undef TAILQ_EMPTY +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_FOREACH_SAFE +#undef TAILQ_FOREACH_REVERSE_SAFE +#undef TAILQ_INIT +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef CIRCLEQ_HEAD +#undef CIRCLEQ_HEAD_INITIALIZER +#undef CIRCLEQ_ENTRY +#undef CIRCLEQ_FIRST +#undef CIRCLEQ_LAST +#undef CIRCLEQ_END +#undef CIRCLEQ_NEXT +#undef CIRCLEQ_PREV +#undef CIRCLEQ_EMPTY +#undef CIRCLEQ_FOREACH +#undef CIRCLEQ_FOREACH_REVERSE +#undef CIRCLEQ_INIT +#undef CIRCLEQ_INSERT_AFTER +#undef CIRCLEQ_INSERT_BEFORE +#undef CIRCLEQ_INSERT_HEAD +#undef CIRCLEQ_INSERT_TAIL +#undef CIRCLEQ_REMOVE +#undef CIRCLEQ_REPLACE + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALIDATE(a) (a) = ((void *)-1) +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \\ +struct name { \\ + struct type *slh_first; /* first element */ \\ +} + +#define SLIST_HEAD_INITIALIZER(head) \\ + { NULL } + +#define SLIST_ENTRY(type) \\ +struct { \\ + struct type *sle_next; /* next element */ \\ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \\ + for((var) = SLIST_FIRST(head); \\ + (var) != SLIST_END(head); \\ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \\ + for ((var) = SLIST_FIRST(head); \\ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \\ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \\ + SLIST_FIRST(head) = SLIST_END(head); \\ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \\ + (elm)->field.sle_next = (slistelm)->field.sle_next; \\ + (slistelm)->field.sle_next = (elm); \\ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \\ + (elm)->field.sle_next = (head)->slh_first; \\ + (head)->slh_first = (elm); \\ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \\ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \\ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \\ + (head)->slh_first = (head)->slh_first->field.sle_next; \\ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \\ + if ((head)->slh_first == (elm)) { \\ + SLIST_REMOVE_HEAD((head), field); \\ + } else { \\ + struct type *curelm = (head)->slh_first; \\ + \\ + while (curelm->field.sle_next != (elm)) \\ + curelm = curelm->field.sle_next; \\ + curelm->field.sle_next = \\ + curelm->field.sle_next->field.sle_next; \\ + _Q_INVALIDATE((elm)->field.sle_next); \\ + } \\ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \\ +struct name { \\ + struct type *lh_first; /* first element */ \\ +} + +#define LIST_HEAD_INITIALIZER(head) \\ + { NULL } + +#define LIST_ENTRY(type) \\ +struct { \\ + struct type *le_next; /* next element */ \\ + struct type **le_prev; /* address of previous next element */ \\ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \\ + for((var) = LIST_FIRST(head); \\ + (var)!= LIST_END(head); \\ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \\ + for ((var) = LIST_FIRST(head); \\ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \\ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \\ + LIST_FIRST(head) = LIST_END(head); \\ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \\ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \\ + (listelm)->field.le_next->field.le_prev = \\ + &(elm)->field.le_next; \\ + (listelm)->field.le_next = (elm); \\ + (elm)->field.le_prev = &(listelm)->field.le_next; \\ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \\ + (elm)->field.le_prev = (listelm)->field.le_prev; \\ + (elm)->field.le_next = (listelm); \\ + *(listelm)->field.le_prev = (elm); \\ + (listelm)->field.le_prev = &(elm)->field.le_next; \\ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \\ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \\ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\\ + (head)->lh_first = (elm); \\ + (elm)->field.le_prev = &(head)->lh_first; \\ +} while (0) + +#define LIST_REMOVE(elm, field) do { \\ + if ((elm)->field.le_next != NULL) \\ + (elm)->field.le_next->field.le_prev = \\ + (elm)->field.le_prev; \\ + *(elm)->field.le_prev = (elm)->field.le_next; \\ + _Q_INVALIDATE((elm)->field.le_prev); \\ + _Q_INVALIDATE((elm)->field.le_next); \\ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \\ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \\ + (elm2)->field.le_next->field.le_prev = \\ + &(elm2)->field.le_next; \\ + (elm2)->field.le_prev = (elm)->field.le_prev; \\ + *(elm2)->field.le_prev = (elm2); \\ + _Q_INVALIDATE((elm)->field.le_prev); \\ + _Q_INVALIDATE((elm)->field.le_next); \\ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \\ +struct name { \\ + struct type *sqh_first; /* first element */ \\ + struct type **sqh_last; /* addr of last next element */ \\ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \\ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \\ +struct { \\ + struct type *sqe_next; /* next element */ \\ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \\ + for((var) = SIMPLEQ_FIRST(head); \\ + (var) != SIMPLEQ_END(head); \\ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \\ + for ((var) = SIMPLEQ_FIRST(head); \\ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \\ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \\ + (head)->sqh_first = NULL; \\ + (head)->sqh_last = &(head)->sqh_first; \\ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \\ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \\ + (head)->sqh_last = &(elm)->field.sqe_next; \\ + (head)->sqh_first = (elm); \\ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \\ + (elm)->field.sqe_next = NULL; \\ + *(head)->sqh_last = (elm); \\ + (head)->sqh_last = &(elm)->field.sqe_next; \\ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \\ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\\ + (head)->sqh_last = &(elm)->field.sqe_next; \\ + (listelm)->field.sqe_next = (elm); \\ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \\ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \\ + (head)->sqh_last = &(head)->sqh_first; \\ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \\ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \\ + == NULL) \\ + (head)->sqh_last = &(elm)->field.sqe_next; \\ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \\ +struct name { \\ + struct type *tqh_first; /* first element */ \\ + struct type **tqh_last; /* addr of last next element */ \\ +} + +#define TAILQ_HEAD_INITIALIZER(head) \\ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \\ +struct { \\ + struct type *tqe_next; /* next element */ \\ + struct type **tqe_prev; /* address of previous next element */ \\ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \\ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \\ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \\ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \\ + for((var) = TAILQ_FIRST(head); \\ + (var) != TAILQ_END(head); \\ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \\ + for ((var) = TAILQ_FIRST(head); \\ + (var) != TAILQ_END(head) && \\ + ((tvar) = TAILQ_NEXT(var, field), 1); \\ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \\ + for((var) = TAILQ_LAST(head, headname); \\ + (var) != TAILQ_END(head); \\ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \\ + for ((var) = TAILQ_LAST(head, headname); \\ + (var) != TAILQ_END(head) && \\ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \\ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \\ + (head)->tqh_first = NULL; \\ + (head)->tqh_last = &(head)->tqh_first; \\ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \\ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \\ + (head)->tqh_first->field.tqe_prev = \\ + &(elm)->field.tqe_next; \\ + else \\ + (head)->tqh_last = &(elm)->field.tqe_next; \\ + (head)->tqh_first = (elm); \\ + (elm)->field.tqe_prev = &(head)->tqh_first; \\ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \\ + (elm)->field.tqe_next = NULL; \\ + (elm)->field.tqe_prev = (head)->tqh_last; \\ + *(head)->tqh_last = (elm); \\ + (head)->tqh_last = &(elm)->field.tqe_next; \\ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \\ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\\ + (elm)->field.tqe_next->field.tqe_prev = \\ + &(elm)->field.tqe_next; \\ + else \\ + (head)->tqh_last = &(elm)->field.tqe_next; \\ + (listelm)->field.tqe_next = (elm); \\ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \\ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \\ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \\ + (elm)->field.tqe_next = (listelm); \\ + *(listelm)->field.tqe_prev = (elm); \\ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \\ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \\ + if (((elm)->field.tqe_next) != NULL) \\ + (elm)->field.tqe_next->field.tqe_prev = \\ + (elm)->field.tqe_prev; \\ + else \\ + (head)->tqh_last = (elm)->field.tqe_prev; \\ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \\ + _Q_INVALIDATE((elm)->field.tqe_prev); \\ + _Q_INVALIDATE((elm)->field.tqe_next); \\ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \\ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \\ + (elm2)->field.tqe_next->field.tqe_prev = \\ + &(elm2)->field.tqe_next; \\ + else \\ + (head)->tqh_last = &(elm2)->field.tqe_next; \\ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \\ + *(elm2)->field.tqe_prev = (elm2); \\ + _Q_INVALIDATE((elm)->field.tqe_prev); \\ + _Q_INVALIDATE((elm)->field.tqe_next); \\ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \\ +struct name { \\ + struct type *cqh_first; /* first element */ \\ + struct type *cqh_last; /* last element */ \\ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \\ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \\ +struct { \\ + struct type *cqe_next; /* next element */ \\ + struct type *cqe_prev; /* previous element */ \\ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \\ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \\ + for((var) = CIRCLEQ_FIRST(head); \\ + (var) != CIRCLEQ_END(head); \\ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \\ + for ((var) = CIRCLEQ_FIRST(head); \\ + (var) != CIRCLEQ_END(head) && \\ + ((tvar) = CIRCLEQ_NEXT(var, field), 1); \\ + (var) = (tvar)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \\ + for((var) = CIRCLEQ_LAST(head); \\ + (var) != CIRCLEQ_END(head); \\ + (var) = CIRCLEQ_PREV(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \\ + for ((var) = CIRCLEQ_LAST(head, headname); \\ + (var) != CIRCLEQ_END(head) && \\ + ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \\ + (var) = (tvar)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \\ + (head)->cqh_first = CIRCLEQ_END(head); \\ + (head)->cqh_last = CIRCLEQ_END(head); \\ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \\ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \\ + (elm)->field.cqe_prev = (listelm); \\ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \\ + (head)->cqh_last = (elm); \\ + else \\ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \\ + (listelm)->field.cqe_next = (elm); \\ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \\ + (elm)->field.cqe_next = (listelm); \\ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \\ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \\ + (head)->cqh_first = (elm); \\ + else \\ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \\ + (listelm)->field.cqe_prev = (elm); \\ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \\ + (elm)->field.cqe_next = (head)->cqh_first; \\ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \\ + if ((head)->cqh_last == CIRCLEQ_END(head)) \\ + (head)->cqh_last = (elm); \\ + else \\ + (head)->cqh_first->field.cqe_prev = (elm); \\ + (head)->cqh_first = (elm); \\ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \\ + (elm)->field.cqe_next = CIRCLEQ_END(head); \\ + (elm)->field.cqe_prev = (head)->cqh_last; \\ + if ((head)->cqh_first == CIRCLEQ_END(head)) \\ + (head)->cqh_first = (elm); \\ + else \\ + (head)->cqh_last->field.cqe_next = (elm); \\ + (head)->cqh_last = (elm); \\ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \\ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \\ + (head)->cqh_last = (elm)->field.cqe_prev; \\ + else \\ + (elm)->field.cqe_next->field.cqe_prev = \\ + (elm)->field.cqe_prev; \\ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \\ + (head)->cqh_first = (elm)->field.cqe_next; \\ + else \\ + (elm)->field.cqe_prev->field.cqe_next = \\ + (elm)->field.cqe_next; \\ + _Q_INVALIDATE((elm)->field.cqe_prev); \\ + _Q_INVALIDATE((elm)->field.cqe_next); \\ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \\ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \\ + CIRCLEQ_END(head)) \\ + (head).cqh_last = (elm2); \\ + else \\ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \\ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \\ + CIRCLEQ_END(head)) \\ + (head).cqh_first = (elm2); \\ + else \\ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \\ + _Q_INVALIDATE((elm)->field.cqe_prev); \\ + _Q_INVALIDATE((elm)->field.cqe_next); \\ +} while (0) +#endif /* !_FAKE_QUEUE_H_ */ + +!! +fi + +echo "config.h: written" 1>&2 +echo "config.h: written" 1>&3 + +#---------------------------------------------------------------------- +# Now we go to generate our Makefile.configure. +# This file is simply a bunch of Makefile variables. +# They'll work in both GNUmakefile and BSDmakefile. +# You MIGHT want to change this. +#---------------------------------------------------------------------- + +exec > Makefile.configure + +[ -z "${BINDIR}" ] && BINDIR="${PREFIX}/bin" +[ -z "${SBINDIR}" ] && SBINDIR="${PREFIX}/sbin" +[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include" +[ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib" +[ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man" +[ -z "${SHAREDIR}" ] && SHAREDIR="${PREFIX}/share" + +[ -z "${INSTALL_PROGRAM}" ] && INSTALL_PROGRAM="${INSTALL} -m 0555" +[ -z "${INSTALL_LIB}" ] && INSTALL_LIB="${INSTALL} -m 0444" +[ -z "${INSTALL_MAN}" ] && INSTALL_MAN="${INSTALL} -m 0444" +[ -z "${INSTALL_DATA}" ] && INSTALL_DATA="${INSTALL} -m 0444" + +cat << __HEREDOC__ +CC = ${CC} +CFLAGS = ${CFLAGS} +CPPFLAGS = ${CPPFLAGS} +LDADD = ${LDADD} +LDFLAGS = ${LDFLAGS} +STATIC = ${STATIC} +PREFIX = ${PREFIX} +BINDIR = ${BINDIR} +SHAREDIR = ${SHAREDIR} +SBINDIR = ${SBINDIR} +INCLUDEDIR = ${INCLUDEDIR} +LIBDIR = ${LIBDIR} +MANDIR = ${MANDIR} +INSTALL = ${INSTALL} +INSTALL_PROGRAM = ${INSTALL_PROGRAM} +INSTALL_LIB = ${INSTALL_LIB} +INSTALL_MAN = ${INSTALL_MAN} +INSTALL_DATA = ${INSTALL_DATA} +__HEREDOC__ + +echo "Makefile.configure: written" 1>&2 +echo "Makefile.configure: written" 1>&3 + +exit 0 diff --git a/reallocarray.c b/reallocarray.c @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> - -#include "compat.h" - -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) - -void * -reallocarray(void *optr, size_t nmemb, size_t size) -{ - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - return realloc(optr, size * nmemb); -} diff --git a/stagit-index.c b/stagit-index.c @@ -1,6 +1,10 @@ +#include "config.h" + #include <sys/stat.h> +#if HAVE_ERR #include <err.h> +#endif /* HAVE_ERR */ #include <errno.h> #include <inttypes.h> #include <limits.h> @@ -11,8 +15,6 @@ #include <git2.h> -#include "compat.h" - static git_repository *repo; static const char *relpath = ""; @@ -158,7 +160,7 @@ main(int argc, char *argv[]) git_libgit2_init(); -#ifdef __OpenBSD__ +#if HAVE_PLEDGE if (pledge("stdio rpath", NULL) == -1) err(1, "pledge"); #endif diff --git a/stagit.c b/stagit.c @@ -1,7 +1,11 @@ +#include "config.h" + #include <sys/stat.h> #include <sys/types.h> +#if HAVE_ERR #include <err.h> +#endif /* HAVE _ERR */ #include <errno.h> #include <inttypes.h> #include <libgen.h> @@ -13,8 +17,6 @@ #include <git2.h> -#include "compat.h" - struct deltainfo { git_patch *patch; @@ -1048,13 +1050,6 @@ err: return 0; } -void -usage(char *argv0) -{ - fprintf(stderr, "%s [-c cachefile | -l commits] repodir\n", argv0); - exit(1); -} - int main(int argc, char *argv[]) { @@ -1065,43 +1060,48 @@ main(int argc, char *argv[]) char path[PATH_MAX], repodirabs[PATH_MAX + 1], *p; char tmppath[64] = "cache.XXXXXXXXXXXX", buf[BUFSIZ]; size_t n; - int i, fd; - - for (i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - if (repodir) - usage(argv[0]); - repodir = argv[i]; - } else if (argv[i][1] == 'c') { - if (nlogcommits > 0 || i + 1 >= argc) - usage(argv[0]); - cachefile = argv[++i]; - } else if (argv[i][1] == 'l') { - if (cachefile || i + 1 >= argc) - usage(argv[0]); - errno = 0; - nlogcommits = strtoll(argv[++i], &p, 10); - if (argv[i][0] == '\0' || *p != '\0' || - nlogcommits <= 0 || errno) - usage(argv[0]); + int i, fd, ch; + const char *errstr; + + while ((ch = getopt(argc, argv, "c:l:")) != -1) { + switch (ch) { + case 'c': + cachefile = optarg; + break; + case 'l': + nlogcommits = strtonum(optarg, 1, LLONG_MAX, &errstr); + if (errstr != NULL) + errx(1, "number of commits is %s: %s", errstr, optarg); + default: + goto usage; } } - if (!repodir) - usage(argv[0]); + argc -= optind; + argv += optind; - if (!realpath(repodir, repodirabs)) + if (nlogcommits > 0 && cachefile != NULL) + goto usage; + + if (argc > 1) { + fprintf(stderr, "%s: Too many arguments\n", argv[1]); + goto usage; + } else if (argc == 1) + repodir = argv[0]; + else + goto usage; + + if (realpath(repodir, repodirabs) == NULL) err(1, "realpath"); git_libgit2_init(); -#ifdef __OpenBSD__ - if (cachefile) { +#if HAVE_PLEDGE + if (cachefile) if (pledge("stdio rpath wpath cpath fattr", NULL) == -1) err(1, "pledge"); - } else { + else if (pledge("stdio rpath wpath cpath", NULL) == -1) err(1, "pledge"); - } #endif if (git_repository_open_ext(&repo, repodir, @@ -1262,4 +1262,9 @@ main(int argc, char *argv[]) git_libgit2_shutdown(); return 0; + +usage: + fprintf(stderr, "%s [-c cachefile | -l commits] repodir\n", getprogname()); + return 1; + } diff --git a/strlcat.c b/strlcat.c @@ -1,57 +0,0 @@ -/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */ - -/* - * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <string.h> - -#include "compat.h" - -/* - * Appends src to string dst of size dsize (unlike strncat, dsize is the - * full size of dst, not space left). At most dsize-1 characters - * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). - * Returns strlen(src) + MIN(dsize, strlen(initial dst)). - * If retval >= dsize, truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t dsize) -{ - const char *odst = dst; - const char *osrc = src; - size_t n = dsize; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end. */ - while (n-- != 0 && *dst != '\0') - dst++; - dlen = dst - odst; - n = dsize - dlen; - - if (n-- == 0) - return(dlen + strlen(src)); - while (*src != '\0') { - if (n != 0) { - *dst++ = *src; - n--; - } - src++; - } - *dst = '\0'; - - return(dlen + (src - osrc)); /* count does not include NUL */ -} diff --git a/strlcpy.c b/strlcpy.c @@ -1,52 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */ - -/* - * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <string.h> - -#include "compat.h" - -/* - * Copy string src to buffer dst of size dsize. At most dsize-1 - * chars will be copied. Always NUL terminates (unless dsize == 0). - * Returns strlen(src); if retval >= dsize, truncation occurred. - */ -size_t -strlcpy(char *dst, const char *src, size_t dsize) -{ - const char *osrc = src; - size_t nleft = dsize; - - /* Copy as many bytes as will fit. */ - if (nleft != 0) { - while (--nleft != 0) { - if ((*dst++ = *src++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src. */ - if (nleft == 0) { - if (dsize != 0) - *dst = '\0'; /* NUL-terminate dst */ - while (*src++) - ; - } - - return(src - osrc - 1); /* count does not include NUL */ -} diff --git a/tests.c b/tests.c @@ -0,0 +1,432 @@ +#if TEST___PROGNAME +int +main(void) +{ + extern char *__progname; + + return !__progname; +} +#endif /* TEST___PROGNAME */ +#if TEST_ARC4RANDOM +#include <stdlib.h> + +int +main(void) +{ + return (arc4random() + 1) ? 0 : 1; +} +#endif /* TEST_ARC4RANDOM */ +#if TEST_B64_NTOP +#include <netinet/in.h> +#include <resolv.h> + +int +main(void) +{ + const char *src = "hello world"; + char output[1024]; + + return b64_ntop((const unsigned char *)src, 11, output, sizeof(output)) > 0 ? 0 : 1; +} +#endif /* TEST_B64_NTOP */ +#if TEST_CAPSICUM +#include <sys/capsicum.h> + +int +main(void) +{ + cap_enter(); + return(0); +} +#endif /* TEST_CAPSICUM */ +#if TEST_ERR +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <err.h> + +int +main(void) +{ + warnx("%d. warnx", 1); + warn("%d. warn", 2); + err(0, "%d. err", 3); + /* NOTREACHED */ + return 1; +} +#endif /* TEST_ERR */ +#if TEST_EXPLICIT_BZERO +#include <string.h> + +int +main(void) +{ + char foo[10]; + + explicit_bzero(foo, sizeof(foo)); + return(0); +} +#endif /* TEST_EXPLICIT_BZERO */ +#if TEST_GETPROGNAME +#include <stdlib.h> + +int +main(void) +{ + const char * progname; + + progname = getprogname(); + return progname == NULL; +} +#endif /* TEST_GETPROGNAME */ +#if TEST_INFTIM +/* + * Linux doesn't (always?) have this. + */ + +#include <poll.h> +#include <stdio.h> + +int +main(void) +{ + printf("INFTIM is defined to be %ld\n", (long)INFTIM); + return 0; +} +#endif /* TEST_INFTIM */ +#if TEST_MD5 +#include <sys/types.h> +#include <md5.h> + +int main(void) +{ + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, "abcd", 4); + + return 0; +} +#endif /* TEST_MD5 */ +#if TEST_MEMMEM +#define _GNU_SOURCE +#include <string.h> + +int +main(void) +{ + char *a = memmem("hello, world", strlen("hello, world"), "world", strlen("world")); + return(NULL == a); +} +#endif /* TEST_MEMMEM */ +#if TEST_MEMRCHR +#if defined(__linux__) || defined(__MINT__) +#define _GNU_SOURCE /* See test-*.c what needs this. */ +#endif +#include <string.h> + +int +main(void) +{ + const char *buf = "abcdef"; + void *res; + + res = memrchr(buf, 'a', strlen(buf)); + return(NULL == res ? 1 : 0); +} +#endif /* TEST_MEMRCHR */ +#if TEST_MEMSET_S +#include <string.h> + +int main(void) +{ + char buf[10]; + memset_s(buf, 0, 'c', sizeof(buf)); + return 0; +} +#endif /* TEST_MEMSET_S */ +#if TEST_PATH_MAX +/* + * POSIX allows PATH_MAX to not be defined, see + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html; + * the GNU Hurd is an example of a system not having it. + * + * Arguably, it would be better to test sysconf(_SC_PATH_MAX), + * but since the individual *.c files include "config.h" before + * <limits.h>, overriding an excessive value of PATH_MAX from + * "config.h" is impossible anyway, so for now, the simplest + * fix is to provide a value only on systems not having any. + * So far, we encountered no system defining PATH_MAX to an + * impractically large value, even though POSIX explicitly + * allows that. + * + * The real fix would be to replace all static buffers of size + * PATH_MAX by dynamically allocated buffers. But that is + * somewhat intrusive because it touches several files and + * because it requires changing struct mlink in mandocdb.c. + * So i'm postponing that for now. + */ + +#include <limits.h> +#include <stdio.h> + +int +main(void) +{ + printf("PATH_MAX is defined to be %ld\n", (long)PATH_MAX); + return 0; +} +#endif /* TEST_PATH_MAX */ +#if TEST_PLEDGE +#include <unistd.h> + +int +main(void) +{ + return !!pledge("stdio", NULL); +} +#endif /* TEST_PLEDGE */ +#if TEST_PROGRAM_INVOCATION_SHORT_NAME +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include <errno.h> + +int +main(void) +{ + + return !program_invocation_short_name; +} +#endif /* TEST_PROGRAM_INVOCATION_SHORT_NAME */ +#if TEST_REALLOCARRAY +#include <stdlib.h> + +int +main(void) +{ + return !reallocarray(NULL, 2, 2); +} +#endif /* TEST_REALLOCARRAY */ +#if TEST_RECALLOCARRAY +#include <stdlib.h> + +int +main(void) +{ + return !recallocarray(NULL, 0, 2, 2); +} +#endif /* TEST_RECALLOCARRAY */ +#if TEST_SANDBOX_INIT +#include <sandbox.h> + +int +main(void) +{ + char *ep; + int rc; + + rc = sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, &ep); + if (-1 == rc) + sandbox_free_error(ep); + return(-1 == rc); +} +#endif /* TEST_SANDBOX_INIT */ +#if TEST_SECCOMP_FILTER +#include <sys/prctl.h> +#include <linux/seccomp.h> +#include <errno.h> + +int +main(void) +{ + + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, 0); + return(EFAULT == errno ? 0 : 1); +} +#endif /* TEST_SECCOMP_FILTER */ +#if TEST_SOCK_NONBLOCK +/* + * Linux doesn't (always?) have this. + */ + +#include <sys/socket.h> + +int +main(void) +{ + int fd[2]; + socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0, fd); + return 0; +} +#endif /* TEST_SOCK_NONBLOCK */ +#if TEST_STRLCAT +#include <string.h> + +int +main(void) +{ + char buf[3] = "a"; + return ! (strlcat(buf, "b", sizeof(buf)) == 2 && + buf[0] == 'a' && buf[1] == 'b' && buf[2] == '\0'); +} +#endif /* TEST_STRLCAT */ +#if TEST_STRLCPY +#include <string.h> + +int +main(void) +{ + char buf[2] = ""; + return ! (strlcpy(buf, "a", sizeof(buf)) == 1 && + buf[0] == 'a' && buf[1] == '\0'); +} +#endif /* TEST_STRLCPY */ +#if TEST_STRNDUP +#include <string.h> + +int +main(void) +{ + const char *foo = "bar"; + char *baz; + + baz = strndup(foo, 1); + return(0 != strcmp(baz, "b")); +} +#endif /* TEST_STRNDUP */ +#if TEST_STRNLEN +#include <string.h> + +int +main(void) +{ + const char *foo = "bar"; + size_t sz; + + sz = strnlen(foo, 1); + return(1 != sz); +} +#endif /* TEST_STRNLEN */ +#if TEST_STRTONUM +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> + +int +main(void) +{ + const char *errstr; + + if (strtonum("1", 0, 2, &errstr) != 1) + return 1; + if (errstr != NULL) + return 2; + if (strtonum("1x", 0, 2, &errstr) != 0) + return 3; + if (errstr == NULL) + return 4; + if (strtonum("2", 0, 1, &errstr) != 0) + return 5; + if (errstr == NULL) + return 6; + if (strtonum("0", 1, 2, &errstr) != 0) + return 7; + if (errstr == NULL) + return 8; + return 0; +} +#endif /* TEST_STRTONUM */ +#if TEST_SYS_QUEUE +#include <sys/queue.h> +#include <stddef.h> + +struct foo { + int bar; + TAILQ_ENTRY(foo) entries; +}; + +TAILQ_HEAD(fooq, foo); + +int +main(void) +{ + struct fooq foo_q; + struct foo *p, *tmp; + int i = 0; + + TAILQ_INIT(&foo_q); + + /* + * Use TAILQ_FOREACH_SAFE because some systems (e.g., Linux) + * have TAILQ_FOREACH but not the safe variant. + */ + + TAILQ_FOREACH_SAFE(p, &foo_q, entries, tmp) + p->bar = i++; + return 0; +} +#endif /* TEST_SYS_QUEUE */ +#if TEST_SYSTRACE +#include <sys/param.h> +#include <dev/systrace.h> + +#include <stdlib.h> + +int +main(void) +{ + + return(0); +} +#endif /* TEST_SYSTRACE */ +#if TEST_UNVEIL +#include <unistd.h> + +int +main(void) +{ + return -1 != unveil(NULL, NULL); +} +#endif /* TEST_UNVEIL */ +#if TEST_ZLIB +#include <stddef.h> +#include <zlib.h> + +int +main(void) +{ + gzFile gz; + + if (NULL == (gz = gzopen("/dev/null", "w"))) + return(1); + gzputs(gz, "foo"); + gzclose(gz); + return(0); +} +#endif /* TEST_ZLIB */