#!/bin/sh # # Copyright (c) 2021, 2022, 2023 Omar Polo # Copyright (c) 2011, 2013-2022 Ingo Schwarze # Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons # # 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. set -e RELEASE=no VERSION=2.0.4-current usage() { echo "usage: $0 [--help] [--prefix=prefix] [OPTION=VALUE...]" >&2 exit 1 } if command -v yacc 2>/dev/null >&2; then YACC=yacc elif command -v bison 2>/dev/null >&2; then YACC=bison else # assume yacc by default. Make will fail building parse.y if # not from a release tarball, but at least it'll have a decent # error message. YACC=yacc fi pkgconfig= CC=${CC:-cc} if [ "$RELEASE" = no ]; then CFLAGS=${CFLAGS:--O0 -g3} else CFLAGS=${CFLAGS:--O2 -pipe} fi INSTALL=${INSTALL-install} PREFIX=${PREFIX-/usr/local} SYSCONFDIR=${SYSCONFDIR-/etc} CDIAGFLAGS= CDIAGFLAGS="${CDIAGFLAGS} -W -Wall -Wextra -Wpointer-arith -Wuninitialized" CDIAGFLAGS="${CDIAGFLAGS} -Wstrict-prototypes -Wmissing-prototypes -Wunused" CDIAGFLAGS="${CDIAGFLAGS} -Wsign-compare -Wno-unused-parameter" # -Wshadow CDIAGFLAGS="${CDIAGFLAGS} -Wno-missing-field-initializers" CDIAGFLAGS="${CDIAGFLAGS} -Wno-pointer-sign" # On all OSes except OpenBSD use the bundled one. It may crash at # runtime otherwise since we depend on the libtls internals for the # privsep crypto engine. # See . LIBTLS=bundled # or system if [ "$(uname || true)" = OpenBSD ]; then LIBTLS=system fi while [ $# -gt 0 ]; do key="${1%%=*}" val="${1#*=}" if [ "$key" = --help ]; then usage fi if [ "$key" = -Werror ]; then CDIAGFLAGS="$CDIAGFLAGS -Werror" shift continue fi if [ "$key" = --enable-sandbox ]; then key=DISABLE_SANDBOX val=0 fi if [ "$key" = --disable-sandbox ]; then key=DISABLE_SANDBOX val=1 fi if [ "$key" = "$1" ]; then # if no --xy=, look at the next arg if ! shift 2>/dev/null; then echo "$0: missing value for $key" >&2 exit 1 fi val="$1" fi case "$key" in --bindir) key=BINDIR ;; --mandir) key=MANDIR ;; --prefix) key=PREFIX ;; --sysconfdir) key=SYSCONFDIR ;; --with-libtls) key=LIBTLS ;; esac case "$key" in LIBTLS) case "$val" in bundled) LIBTLS=bundled ;; system) LIBTLS=system ;; *) usage ;; esac ;; BINDIR) BINDIR="$val" ;; CC) CC="$val" ;; CFLAGS) CFLAGS="$val" ;; CDIAGFLAGS) CDIAGFLAGS="$val" ;; DISABLE_SANDBOX) DISABLE_SANDBOX="$val" ;; INSTALL) INSTALL="$val" ;; LDFLAGS) LDFLAGS="$val" ;; MANDIR) MANDIR="$val" ;; PKG_CONFIG) PKG_CONFIG="$val" ;; PREFIX) PREFIX="$val" ;; SYSCONFDIR) SYSCONFDIR="$val" ;; YACC) YACC="$val" ;; *) usage esac shift done [ -w config.log ] && mv config.log config.log.old [ -w config.h ] && mv config.h config.h.old exec 3> config.log echo "file config.log: writing..." NEED_GNU_SOURCE=0 NEED_OPENBSD_SOURCE=0 COMPATS= COMP="${CC} ${CFLAGS} -Werror=implicit-function-declaration" # singletest name var extra-cflags extra-libs msg singletest() { msg="$5" if [ -z "$msg" ]; then if [ -n "$3" ]; then msg=" ($3)" elif [ -n "$4" ]; then msg=" ($4)" fi elif [ "$msg" = no ]; then msg="" fi cat >&3 <&3 2>&3; then rm -f test-${1} test-${1}.d echo "${1}: $CC$msg succeeded" >&3 echo "${1}$msg: yes" echo >&3 return 0 fi echo "${1}: $CC$msg failed $?" >&3 echo "${1}$msg: no" echo >&3 return 1 } # deptest name var deptest() { if singletest "$1" "$2" "${CFLAGS}" "${LIBS}" no; then eval HAVE_${2}=1 return 0 fi if [ -f compat/${1}.c ]; then COMPATS="compat/$1.c $COMPATS" fi eval HAVE_${2}=0 return 1 } # runtest name var extra-cflags extra-libs pkgconfig-name runtest() { if singletest "$1" "$2" "" ""; then eval HAVE_${2}=1 return 0 fi if [ -n "$3" -o -n "$4" ]; then echo "retrying with ${3+$3 }$4" >&3 if singletest "$1" "$2" "$3" "$4"; then eval HAVE_${2}=1 if [ "$3" = -D_GNU_SOURCE ]; then NEED_GNU_SOURCE=1 return 0 fi if [ "$4" = -D_OPENBSD_SOURCE ]; then NEED_OPENBSD_SOURCE=1 return 0 fi if [ -n "$3" ]; then CFLAGS="$CFLAGS $3" fi if [ -n "$4" ]; then LIBS="$LIBS $4" fi return 0 fi fi if [ -n "$5" -a -n "$pkgconfig" ]; then if $pkgconfig $5; then cflags="$($pkgconfig --cflags $5)" ldflags="$($pkgconfig --libs $5)" echo "retrying with pkg-config" >&3 if singletest "$1" "$2" "$cflags" "$ldflags"; then CFLAGS="$CFLAGS $cflags" LIBS="$LIBS $ldflags" eval HAVE_$2=1 return 0 fi fi fi if [ -f compat/$1.c ]; then COMPATS="compat/$1.c $COMPATS" fi eval HAVE_$2=0 return 1 } if [ "$PKG_CONFIG" = no ]; then echo "pkg-config: disabled" elif [ -n "$PKG_CONFIG" ]; then pkgconfig="$PKG_CONFIG" echo "pkg-config: (manual) $PKG_CONFIG" elif command -v pkg-config 2>/dev/null >&2; then pkgconfig="pkg-config" echo "pkg-config: (auto) pkg-config" else echo "pkg-config: not found" fi if singletest noop MMD -MMD; then CFLAGS="${CFLAGS} -MMD" fi if ! runtest wait_any WAIT_ANY; then CFLAGS="${CFLAGS} -DWAIT_ANY=-1" fi HAVE_ENDIAN_H=0 HAVE_SYS_ENDIAN_H=0 HAVE_MACHINE_ENDIAN=0 runtest endian_h ENDIAN_H || \ runtest sys_endian_h SYS_ENDIAN_H || \ runtest machine_endian MACHINE_ENDIAN || true if [ ${HAVE_ENDIAN_H} -eq 0 -a \ ${HAVE_SYS_ENDIAN_H} -eq 0 -a \ ${HAVE_MACHINE_ENDIAN} -eq 0 ]; then echo "FATAL: no endian header found" 1>&2 echo "FATAL: no endian header found" 1>&3 exit 1 fi runtest arc4random ARC4RANDOM || true runtest arc4random_buf ARC4RANDOM_BUF || true runtest err ERR || true runtest explicit_bzero EXPLICIT_BZERO || true runtest freezero FREEZERO || true runtest getdtablecount GETDTABLECOUNT || true runtest getdtablesize GETDTABLESIZE || true runtest getprogname GETPROGNAME || true runtest imsg IMSG "" -lutil libimsg || true runtest landlock LANDLOCK || true runtest libevent LIBEVENT "" -levent libevent_core|| true runtest memmem MEMMEM -D_GNU_SOURCE || true runtest openssl OPENSSL "" '-lcrypto -lssl' 'libcrypto libssl' || true runtest pr_set_name PR_SET_NAME || true runtest program_invocation_short_name PROGRAM_INVOCATION_SHORT_NAME -D_GNU_SOURCE || true runtest queue_h QUEUE_H || true runtest reallocarray REALLOCARRAY -D_OPENBSD_SOURCE || true runtest recallocarray RECALLOCARRAY || true runtest setproctitle SETPROCTITLE || true runtest setresgid SETRESGID -D_GNU_SOURCE || true runtest setresuid SETRESUID -D_GNU_SOURCE || true runtest strlcat STRLCAT || true runtest strlcpy STRLCPY || true runtest strtonum STRTONUM -D_OPENBSD_SOURCE || true runtest timingsafe_memcmp TIMINGSAFE_MEMCMP || true runtest tree_h TREE_H || true runtest vasprintf VASPRINTF -D_GNU_SOURCE || true # strnvis is a bit special since NetBSD, FreeBSD and MacOS have # the broken version with the wrong semantics and arguments. # Hence the -Wall -Werror check. if ! singletest strnvis STRNVIS "-Wall -Werror"; then CFLAGS="-I ${PWD}/compat/vis ${CFLAGS} ${CFLAGS}" COMPATS="compat/vis.c ${COMPATS}" fi if [ ${HAVE_ARC4RANDOM} -eq 1 -a ${HAVE_ARC4RANDOM_BUF} -eq 0 ]; then COMPATS="compat/arc4random.c ${COMPATS}" fi if [ ${HAVE_ARC4RANDOM} -eq 0 ]; then runtest getentropy GETENTROPY || true else # fake it HAVE_GETENTROPY=1 fi if [ ${HAVE_ARC4RANDOM} -eq 0 -a ${HAVE_GETENTROPY} -eq 1 ]; then COMPATS="compat/getentropy.c ${COMPATS}" fi if [ "${LIBTLS}" = system ]; then runtest libtls LIBTLS "" -ltls libtls || true # not actually needed HAVE_ASN1_TIME_TM_CMP=1 HAVE_ASN1_TIME_TM_CLAMP_NOTAFTER=1 HAVE_ASN1_TIME_PARSE=1 HAVE_SSL_CTX_UCCM=1 HAVE_SSL_CTX_LVM=1 HAVE_X509_LOOKUP_MEM=1 else # use bundled one HAVE_LIBTLS=1 for f in compat/libtls/*.c; do COMPATS="$f ${COMPATS}" done CFLAGS="-Icompat/libtls -I../compat/libtls ${CFLAGS}" deptest ASN1_time_tm_cmp ASN1_TIME_TM_CMP || true deptest ASN1_time_tm_clamp_notafter ASN1_TIME_TM_CLAMP_NOTAFTER || true deptest ASN1_time_parse ASN1_TIME_PARSE || true deptest SSL_CTX_use_certificate_chain_mem SSL_CTX_UCCM || true deptest SSL_CTX_load_verify_mem SSL_CTX_LVM || true deptest X509_LOOKUP_mem X509_LOOKUP_MEM || true fi deptest libevent2 LIBEVENT2 || true if [ ${HAVE_LIBTLS} -eq 0 ]; then echo "FATAL: openssl not found" 1>&2 echo "FATAL: openssl not found" 1>&3 exit 1 fi if [ ${HAVE_OPENSSL} -eq 0 ]; then echo "FATAL: openssl not found" 1>&2 echo "FATAL: openssl not found" 1>&3 exit 1 fi if [ ${HAVE_LIBEVENT} -eq 0 ]; then echo "FATAL: libevent not found" 1>&2 echo "FATAL: libevent not found" 1>&3 exit 1 fi if [ ${HAVE_IMSG} -eq 0 ]; then # compat/imsg.c is implicitly added COMPATS="$COMPATS compat/imsg-buffer.c" fi if [ ${HAVE_QUEUE_H} -eq 0 -o ${HAVE_IMSG} -eq 0 -o ${HAVE_TREE_H} -eq 0 ]; then CFLAGS="${CFLAGS} -I ${PWD}/compat" fi if [ $HAVE_LIBEVENT2 -eq 1 ]; then CFLAGS="$CFLAGS -DHAVE_LIBEVENT2=1" fi if [ $NEED_GNU_SOURCE = 1 ]; then CFLAGS="$CFLAGS -D_GNU_SOURCE" fi if [ $NEED_OPENBSD_SOURCE = 1 ]; then CFLAGS="$CFLAGS -D_OPENBSD_SOURCE" fi CFLAGS="-I. ${CFLAGS} ${CDIAGFLAGS}" exec > config.h echo "config.h: writing.." >&2 cat <<__HEREDOC__ #ifdef __cplusplus #error "Do not use C++." #endif __HEREDOC__ [ ${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 -o ${HAVE_IMSG} -eq 0 ] \ && echo "#include " [ ${HAVE_VASPRINTF} -eq 0 ] && echo "#include " if [ ${HAVE_QUEUE_H} -eq 1 ]; then echo "#include " else echo "#include " fi if [ ${HAVE_TREE_H} -eq 1 ]; then echo "#include " else echo "#include " fi echo "#include " echo "#include " echo "#include " echo "#include " echo "#include " cat <<__HEREDOC__ #define VERSION "${VERSION}" #define DISABLE_SANDBOX ${DISABLE_SANDBOX} #define HAVE_LANDLOCK ${HAVE_LANDLOCK} #ifndef SYSCONFDIR # define SYSCONFDIR "${SYSCONFDIR}" #endif __HEREDOC__ if [ ${HAVE_ENDIAN_H} -eq 1 ]; then echo "#include " elif [ ${HAVE_SYS_ENDIAN_H} -eq 1 ]; then echo "#include " elif [ ${HAVE_MACHINE_ENDIAN} -eq 1 ]; then cat <<__HEREDOC__ #include #include # define htobe16(x) OSSwapHostToBigInt16(x) # define htole16(x) OSSwapHostToLittleInt16(x) # define be16toh(x) OSSwapBigToHostInt16(x) # define le16toh(x) OSSwapLittleToHostInt16(x) # define htobe32(x) OSSwapHostToBigInt32(x) # define htole32(x) OSSwapHostToLittleInt32(x) # define be32toh(x) OSSwapBigToHostInt32(x) # define le32toh(x) OSSwapLittleToHostInt32(x) # define htobe64(x) OSSwapHostToBigInt64(x) # define htole64(x) OSSwapHostToLittleInt64(x) # define be64toh(x) OSSwapBigToHostInt64(x) # define le64toh(x) OSSwapLittleToHostInt64(x) __HEREDOC__ fi [ ${HAVE_ARC4RANDOM_BUF} -eq 0 -o \ ${HAVE_ASN1_TIME_PARSE} -eq 0 -o \ ${HAVE_EXPLICIT_BZERO} -eq 0 -o \ ${HAVE_FREEZERO} -eq 0 -o \ ${HAVE_GETENTROPY} -eq 0 -o \ ${HAVE_REALLOCARRAY} -eq 0 -o \ ${HAVE_RECALLOCARRAY} -eq 0 -o \ ${HAVE_STRLCAT} -eq 0 -o \ ${HAVE_STRLCPY} -eq 0 -o \ ${HAVE_STRTONUM} -eq 0 -o \ ${HAVE_TIMINGSAFE_MEMCMP} -eq 0 ] && echo "#include " [ ${HAVE_ARC4RANDOM} -eq 0 ] && echo "#include " [ ${HAVE_SETRESGID} -eq 0 -o \ ${HAVE_SETRESUID} -eq 0 ] && echo "#include " if [ ${HAVE_GETENTROPY} -eq 1 ]; then echo "#define HAVE_GETENTROPY 1" else echo "#define WITH_OPENSSL 1" echo "#define OPENSSL_PRNG_ONLY 1" fi if [ ${HAVE_ARC4RANDOM} -eq 0 ]; then echo "extern uint32_t arc4random(void);" else echo "#define HAVE_ARC4RANDOM 1" fi if [ ${HAVE_ARC4RANDOM_BUF} -eq 0 ]; then echo "extern void arc4random_buf(void *, size_t);" else echo "#define HAVE_ARC4RANDOM_BUF 1" fi if [ ${HAVE_ASN1_TIME_TM_CMP} -eq 0 ]; then echo "struct tm;" echo "extern int ASN1_time_tm_cmp(struct tm *, struct tm *);" else echo "#define HAVE_ASN1_TIME_TM_CMP 1" fi if [ ${HAVE_ASN1_TIME_TM_CLAMP_NOTAFTER} -eq 0 ]; then echo "struct tm;" echo "extern int ASN1_time_tm_clamp_notafter(struct tm *);" else echo "#define HAVE_ASN1_TIME_TM_CLAMP_NOTAFTER 1" fi if [ ${HAVE_ASN1_TIME_PARSE} -eq 0 ]; then echo "struct tm;" echo "extern int ASN1_time_parse(const char *, size_t, struct tm *, int);" else echo "#define HAVE_ASN1_TIME_PARSE 1" fi 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*, ...);" else echo "#include " fi if [ ${HAVE_EXPLICIT_BZERO} -eq 0 ]; then echo "extern void explicit_bzero(void*, size_t);" fi if [ ${HAVE_FREEZERO} -eq 0 ]; then echo "extern void freezero(void*, size_t);" fi if [ ${HAVE_GETDTABLECOUNT} -eq 0 ]; then echo "extern int getdtablecount(void);" fi if [ ${HAVE_GETDTABLESIZE} -eq 0 ]; then echo "extern int getdtablesize(void);" fi if [ ${HAVE_GETENTROPY} -eq 0 ]; then echo "extern int getentropy(void *, size_t);" fi if [ ${HAVE_GETPROGNAME} -eq 0 ]; then echo "extern const char *getprogname(void);" fi if [ ${HAVE_MEMMEM} -eq 0 ]; then echo "extern void *memmem(const void *, size_t, const void *, size_t);" 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_SETPROCTITLE} -eq 0 ]; then echo "extern void setproctitle(const char *fmt, ...);" fi if [ ${HAVE_SETRESGID} -eq 0 ]; then echo "extern int setresgid(gid_t, gid_t, gid_t);" fi if [ ${HAVE_SETRESUID} -eq 0 ]; then echo "extern int setresuid(uid_t, uid_t, uid_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_STRTONUM} -eq 0 ]; then echo "extern long long strtonum(const char*, long long, long long, const char**);" fi if [ ${HAVE_TIMINGSAFE_MEMCMP} -eq 0 ]; then echo "extern int timingsafe_memcmp(const void *, const void *, size_t);" fi if [ ${HAVE_VASPRINTF} -eq 0 ]; then echo "extern int vasprintf(char**, const char*, va_list);" fi if [ ${HAVE_ASN1_TIME_TM_CMP} -eq 0 ]; then echo "#include " echo "struct tm;" echo "int ASN1_time_tm_cmp(struct tm *, struct tm *);" else echo "#define HAVE_ASN1_TIME_TM_CMP 1" fi if [ ${HAVE_SSL_CTX_UCCM} -eq 0 -o ${HAVE_SSL_CTX_LVM} -eq 0 ]; then echo "#include " fi if [ ${HAVE_SSL_CTX_UCCM} -eq 0 ]; then echo "int SSL_CTX_use_certificate_chain_mem(SSL_CTX *, void *, int);" else echo "#define HAVE_SSL_CTX_USE_CERTIFICATE_CHAIN_MEM 1" fi if [ ${HAVE_SSL_CTX_LVM} -eq 0 ]; then echo "int SSL_CTX_load_verify_mem(SSL_CTX *, void *, int);" else echo "#define HAVE_SSL_CTX_LOAD_VERIFY_MEM 1" fi if [ ${HAVE_X509_LOOKUP_MEM} -eq 0 ]; then echo "#include " echo "X509_LOOKUP_METHOD *X509_LOOKUP_mem(void);" else echo "#define HAVE_X509_LOOKUP_MEM 1" fi cat <<__HEREDOC__ #ifndef __dead #define __dead __attribute__((noreturn)) #endif /* Linux and OpenBSD have LOGIN_NAME_MAX, FreeBSD MAXLOGNAME. */ #ifndef LOGIN_NAME_MAX # if defined(MAXLOGNAME) # define LOGIN_NAME_MAX MAXLOGNAME # elif defined(_POSIX_LOGIN_NAME_MAX) # define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX # else # define LOGIN_NAME_MAX 32 # endif #endif #ifndef HOST_NAME_MAX # if defined(_POSIX_HOST_NAME_MAX) # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX # else # define HOST_NAME_MAX 255 # endif #endif __HEREDOC__ echo "file config.h: written" 1>&2 echo "file config.h: written" 1>&3 exec > config.mk [ -z "${BINDIR}" ] && BINDIR="\${PREFIX}/bin" [ -z "${MANDIR}" ] && MANDIR="\${PREFIX}/man" cat << __HEREDOC__ CC = ${CC} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS} LIBS = ${LIBS} YACC = ${YACC} STATIC = ${STATIC} PREFIX = ${PREFIX} BINDIR = ${BINDIR} MANDIR = ${MANDIR} INSTALL = ${INSTALL} INSTALL_PROGRAM = \${INSTALL} -m 0555 INSTALL_LIB = \${INSTALL} -m 0444 INSTALL_MAN = \${INSTALL} -m 0444 INSTALL_DATA = \${INSTALL} -m 0444 COMPATS= ${COMPATS} VERSION = ${VERSION} __HEREDOC__ echo "file config.mk: written" 1>&2 echo "file config.mk: written" 1>&3 echo >&2 echo "Now run \`make' to compile." >&2 echo >&2 exit 0