dnl Process this file with autoconf to produce a configure script.
dnl $Id: configure.in,v 1.248 2003/09/02 04:39:17 rra Exp $
dnl
dnl Please try to follow GNU conventions and autoconf manual conventions as
dnl much as possible in this file so that any macros we develop can be easily
dnl contributed to the macro archive and possibly rolled into future versions
dnl of autoconf so that we can stop supporting them.  This means, for example,
dnl that code excerpts should probably follow the GNU coding standards rather
dnl than INN's.
dnl
dnl The macro archive is at <http://www.gnu.org/software/ac-archive/>.  Due to
dnl the submission format and significant changes to autoconf's internal
dnl architecture and building-block macros, I'm waiting until INN is switched
dnl to autoconf 2.52 or later and we can convert this file into a bunch of
dnl separate files before submitting macros to that archive.
dnl
dnl If a check is any way non-trivial, please package it up in a macro with
dnl AC_DEFUN.  This will allow us to easily break up this (far too long) file
dnl into a directory full of .m4 files for particular checks once we switch to
dnl autoconf 2.52 or later.  Please also put any long code blocks into a
dnl separate macro rather than in-line in the test macro; this will make
dnl quoting issues much easier.  See the existing tests for details on how to
dnl do this.
dnl
dnl Try to do as much with AC_DEFINE and as little with AC_SUBST as is
dnl reasonable; obviously, makefile things like library paths and so forth and
dnl paths to programs have to use AC_SUBST, but any compile-time parameters
dnl are easier to handle with AC_DEFINE.  (And AC_SUBST is slower.)
dnl
dnl And remember:  If you don't have any alternative available if your check
dnl for something fails, and there's no purpose served in aborting configure
dnl instead of the compile if what you're checking for is missing, don't
dnl bother checking for it.  Compile-time errors often produce a lot more
dnl useful information for someone debugging a problem than configure-time
dnl errors.

AC_REVISION($Revision: 1.248 $)dnl
AC_PREREQ(2.13)
AC_INIT(Makefile.global.in)
AC_CONFIG_AUX_DIR(support)
AC_PREFIX_DEFAULT(/usr/local/news)

dnl Make sure $prefix is set so that we can use it internally.
test x"$prefix" = xNONE && prefix="$ac_default_prefix"

dnl Linking against in-tree libraries need to know the current directory (the
dnl top of the build directory, not the source directory).
builddir=`pwd`
AC_SUBST(builddir)

dnl Earlier versions of INN used --with-largefiles, which was the wrong flag
dnl from the perspective of what --with and --enable are supposed to mean.
dnl Catch the old usage and error out.
if test x"$with_largefiles" != x ; then
    AC_MSG_ERROR([Use --enable-largefiles instead of --with-largefiles])
fi

dnl Used to check whether -o can be provided with -c with the chosen
dnl compiler.  We need this if we're not using libtool so that object files
dnl can be built in subdirectories.  This macro is stolen shamelessly from
dnl the libtool macros; there's a better version in Autoconf that we should
dnl eventually use that tests twice.
AC_DEFUN([INN_PROG_CC_C_O],
[AC_REQUIRE([AC_OBJEXT])
AC_MSG_CHECKING([if $CC supports -c -o file.$ac_objext])
AC_CACHE_VAL([inn_cv_compiler_c_o],
[rm -f -r conftest 2>/dev/null
mkdir conftest
cd conftest
echo "int some_variable = 0;" > conftest.$ac_ext
mkdir out
# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
# that will create temporary files in the current directory regardless of
# the output directory.  Thus, making CWD read-only will cause this test
# to fail, enabling locking or at least warning the user not to do parallel
# builds.
chmod -w .
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no
if { (eval $ac_compile) 2> out/conftest.err; } \
    && test -s out/conftest2.$ac_objext; then
  # The compiler can only warn and ignore the option if not recognized
  # So say no if there are warnings
  if test -s out/conftest.err; then
    inn_cv_compiler_c_o=no
  else
    inn_cv_compiler_c_o=yes
  fi
else
  # Append any errors to the config.log.
  cat out/conftest.err 1>&AC_FD_CC
  inn_cv_compiler_c_o=no
fi
CFLAGS="$save_CFLAGS"
chmod u+w .
rm -f conftest* out/*
rmdir out
cd ..
rmdir conftest
rm -f -r conftest 2>/dev/null])
compiler_c_o=$inn_cv_compiler_c_o
AC_MSG_RESULT([$compiler_c_o])])

dnl A few tests need to happen before any of the libtool tests in order to
dnl avoid error messages.  We therefore lift them up to the top of the file.
AC_PROG_CC
AC_AIX
AC_ISC_POSIX
INN_PROG_CC_C_O

dnl Check to see if the user wants to use libtool.  We only invoke the libtool
dnl setup macros if they do.  Keep this call together with the libtool setup
dnl so that the arguments to configure will be together in configure --help.
inn_use_libtool=no
AC_ARG_ENABLE(libtool,
    [  --enable-libtool        Use libtool for lib generation [default=no]],
    if test "$enableval" = yes ; then
        inn_use_libtool=yes
    fi)
if test x"$inn_use_libtool" = xyes ; then
    AC_PROG_LIBTOOL
    EXTLIB='la'
    EXTOBJ='lo'
    LIBTOOL='$(top)/libtool'
    LIBTOOLCC='$(top)/libtool --mode=compile'
    LIBTOOLLD='$(top)/libtool --mode=link'
    CCOUTPUT='-c -o $@ $<'
else
    AC_CANONICAL_HOST
    EXTLIB='a'
    EXTOBJ='o'
    LIBTOOL=''
    LIBTOOLCC=''
    LIBTOOLLD=''
    if test x"$compiler_c_o" = xyes ; then
        CCOUTPUT='-c -o $@ $<'
    else
        CCOUTPUT='-c $< && if test x"$(@F)" != x"$@" ; then mv $(@F) $@ ; fi'
    fi
    AC_SUBST(LIBTOOL)
fi
AC_SUBST(EXTLIB)
AC_SUBST(EXTOBJ)
AC_SUBST(LIBTOOLCC)
AC_SUBST(LIBTOOLLD)
AC_SUBST(CCOUTPUT)

dnl INN has quite a few more configurable paths than autoconf supports by
dnl default.  For right now, those additional paths are configured with
dnl --with-*-dir options.  This is the generic macro for those arguments; it
dnl takes the name of the directory, the path relative to $prefix if none
dnl given to configure, the variable to set, and the help string.
AC_DEFUN([INN_ARG_DIR],
[AC_ARG_WITH([$1-dir], [$4], [$3=$with_$1_dir], [$3=$prefix/$2])
AC_SUBST($3)])

dnl And here are all the paths.
dnl
dnl FIXME: We should honor bindir, libdir, includedir, and mandir at the
dnl least, and we should use libdir over --with-lib-dir.
INN_ARG_DIR(control, bin/control, CONTROLDIR,
    [  --with-control-dir=PATH Path for control programs [PREFIX/bin/control]])
INN_ARG_DIR(db, db, DBDIR,
    [  --with-db-dir=PATH      Path for news database files [PREFIX/db]])
INN_ARG_DIR(doc, doc, DOCDIR,
    [  --with-doc-dir=PATH     Path for news documentation [PREFIX/doc]])
INN_ARG_DIR(etc, etc, ETCDIR,
    [  --with-etc-dir=PATH     Path for news config files [PREFIX/etc]])
INN_ARG_DIR(filter, bin/filter, FILTERDIR,
    [  --with-filter-dir=PATH  Path for embedded filters [PREFIX/bin/filter]])
INN_ARG_DIR(lib, lib, LIBDIR,
    [  --with-lib-dir=PATH     Path for news library files [PREFIX/lib]])
INN_ARG_DIR(log, log, LOGDIR,
    [  --with-log-dir=PATH     Path for news logs [PREFIX/log]])
INN_ARG_DIR(run, run, RUNDIR,
    [  --with-run-dir=PATH     Path for news PID/runtime files [PREFIX/run]])
INN_ARG_DIR(spool, spool, SPOOLDIR,
    [  --with-spool-dir=PATH   Path for news storage [PREFIX/spool]])
INN_ARG_DIR(tmp, tmp, tmpdir,
    [  --with-tmp-dir=PATH     Path for temporary files [PREFIX/tmp]])

dnl This is actually given to AC_SUBST later on when we check whether the
dnl system has the LOG_NEWS facility.
AC_ARG_WITH(syslog-facility,
[  --with-syslog-facility=LOG_FAC  Syslog facility [LOG_NEWS or LOG_LOCAL1]],
    SYSLOG_FACILITY=$with_syslog_facility,
    SYSLOG_FACILITY=none)

dnl INN allows the user and group INN will run as to be specified, as well as
dnl the user to receive nightly reports and the like.  These are all fairly
dnl similar, so factor the commonality into this macro.  Takes the name of
dnl what we're looking for, the default, the variable to set, the help string,
dnl and the comment for config.h.
AC_DEFUN([INN_ARG_USER],
[AC_ARG_WITH([news-$1], [$4], [$3=$with_news_$1], [$3=$2])
AC_SUBST($3)
AC_DEFINE_UNQUOTED($3, "$[$3]", [$5])])

dnl And here they are.
INN_ARG_USER(user, news, NEWSUSER,
    [  --with-news-user=USER   News user name [news]],
    [The user that INN should run as.])
INN_ARG_USER(group, news, NEWSGRP,
    [  --with-news-group=GROUP News group name [news]],
    [The group that INN should run as.])
INN_ARG_USER(master, usenet, NEWSMASTER,
    [  --with-news-master=USER News master (address for reports) [usenet]],
    [The user who gets all INN-related e-mail.])

dnl INN defaults to a umask of 002 with the corresponding directory and file
dnl permissions, mostly for historical reasons.  If the user sets the umask to
dnl something else, change all of the permissions.
NEWSUMASK=02
FILEMODE=0664
DIRMODE=0775
RUNDIRMODE=0770
AC_ARG_WITH(news-umask,
    [  --with-news-umask=UMASK umask for news files [002]],
    with_news_umask=`echo "$with_news_umask" | sed 's/^0*//'`
    if test "x$with_news_umask" = x22 ; then
        NEWSUMASK=022
        FILEMODE=0644
        DIRMODE=0755
        RUNDIRMODE=0750
    else
        if test "x$with_news_umask" != x2 ; then
            AC_MSG_ERROR(Valid umasks are 02 or 022)
        fi
    fi)
AC_SUBST(NEWSUMASK)
AC_SUBST(FILEMODE)
AC_SUBST(DIRMODE)
AC_SUBST(RUNDIRMODE)
AC_DEFINE_UNQUOTED(ARTFILE_MODE, $FILEMODE,
    [Mode that incoming articles are created with.])
AC_DEFINE_UNQUOTED(BATCHFILE_MODE, $FILEMODE,
    [Mode that batch files are created with.])
AC_DEFINE_UNQUOTED(GROUPDIR_MODE, $DIRMODE,
    [Mode that directories are created with.])
AC_DEFINE_UNQUOTED(NEWSUMASK, $NEWSUMASK,
    [The umask used by all INN programs.])

dnl inews used to be installed setgid, but may not be secure.  Only do this if
dnl it's explicitly requested at configure time.
INEWSMODE=0550
AC_ARG_ENABLE(setgid-inews,
    [  --enable-setgid-inews   Install inews setgid],
    if test "x$enableval" = xyes ; then
        INEWSMODE=02555
    fi)
AC_SUBST(INEWSMODE)

dnl rnews used to be installed setuid root so that it could be run by the uucp
dnl user for incoming batches, but this isn't necessary unless you're using
dnl UUCP (which most people aren't).  Only do this if it's explicitly
dnl requested at configure time.
RNEWSGRP=$NEWSGRP
RNEWSMODE=0500
AC_ARG_ENABLE(uucp-rnews,
    [  --enable-uucp-rnews     Install rnews setuid, group uucp],
    if test "x$enableval" = xyes ; then
        RNEWSGRP=uucp
        RNEWSMODE=04550
    fi)
AC_SUBST(RNEWSGRP)
AC_SUBST(RNEWSMODE)

dnl Choose the log compression method; the argument should not be a full path,
dnl just the name of the compression type.
AC_ARG_WITH(log-compress,
    [  --with-log-compress=METHOD   Log compression method [gzip]],
    LOG_COMPRESS=$with_log_compress,
    LOG_COMPRESS=gzip)
case "$LOG_COMPRESS" in
bzip2) LOG_COMPRESSEXT=".bz2" ;;
gzip)  LOG_COMPRESSEXT=".gz"  ;;
*)     LOG_COMPRESSEXT=".Z"   ;;
esac
AC_SUBST(LOG_COMPRESS)
AC_SUBST(LOG_COMPRESSEXT)

dnl innbind by default only allows ports 119 and 433 below 1024; if the user
dnl wants to use some other port as well, they must use this option.
AC_ARG_WITH(innd-port,
    [  --with-innd-port=PORT   Additional low-numbered port for innbind],
    AC_DEFINE_UNQUOTED(INND_PORT, $with_innd_port,
                       [Additional valid low-numbered port for innbind.]))

dnl By default, we omit all IPv6 support.  This option enables it.
AC_ARG_ENABLE(ipv6,
    [  --enable-ipv6           Enable IPv6 support],
    if test "x$enableval" = xyes ; then
        inn_enable_ipv6_tests=yes
        AC_DEFINE(HAVE_INET6, 1, [Define to enable IPv6 support.])
    fi)

dnl Maximum number of sockets that can be listened on.
AC_ARG_WITH(max-sockets,
    [  --with-max-sockets=N    Maximum number of listening sockets in innd],,
    [with_max_sockets=15])
AC_DEFINE_UNQUOTED(MAX_SOCKETS, $with_max_sockets,
	       [Maximum number of sockets that innd can listen on.])

dnl This will eventually be a runtime option rather than a compile-time
dnl option.
AC_ARG_ENABLE(tagged-hash,
    [  --enable-tagged-hash    Use tagged hash table for history],
    if test "x$enableval" = xyes ; then
        DO_DBZ_TAGGED_HASH=DO
        AC_DEFINE(DO_TAGGED_HASH, 1,
                  [Define to use tagged hash for the history file.])
    else
        DO_DBZ_TAGGED_HASH=DONT
    fi)
AC_SUBST(DO_DBZ_TAGGED_HASH)

dnl Whether to enable the keyword generation code in innd.  Use of this code
dnl requires a regular expression library, which is checked for later on.
inn_enable_keywords=0
AC_ARG_ENABLE(keywords,
    [  --enable-keywords       Automatic keyword generation support],
    if test x"$enableval" = xyes ; then
        inn_enable_keywords=1
    fi)
AC_DEFINE_UNQUOTED(DO_KEYWORDS, $inn_enable_keywords,
    [Define to 1 to compile in support for keyword generation code.])

dnl Whether to use the OS flags to enable large file support.  Ideally this
dnl should just always be turned on if possible and the various parts of INN
dnl that read off_t's from disk should adjust somehow to the size, but INN
dnl isn't there yet.  Currently tagged hash doesn't work with large file
dnl support due to assumptions about the size of off_t.
AC_ARG_ENABLE(largefiles,
    [  --enable-largefiles     Support for files larger than 2GB [default=no]],
    [case "${enableval}" in
    yes) inn_enable_largefiles=yes
         if test x"$DO_DBZ_TAGGED_HASH" = xDO ; then
AC_MSG_ERROR([--enable-tagged-hash conflicts with --enable-largefiles.])
         fi ;;
    no)  inn_enable_largefiles=no ;;
    *)   AC_MSG_ERROR(invalid argument to --enable-largefiles) ;;
    esac])

dnl Override the automatically detected path to sendmail.  Used later on.
AC_ARG_WITH(sendmail,
    [  --with-sendmail=PATH    Path to sendmail],
    SENDMAIL=$with_sendmail)

dnl Check for whether the user wants to compile with BerkeleyDB, and if so
dnl what the path to the various components of it is.
AC_DEFUN([INN_LIB_BERKELEYDB],
[AC_ARG_WITH(berkeleydb,
    [  --with-berkeleydb[=PATH]  Enable BerkeleyDB (for ovdb overview method)],
    BERKELEY_DB_DIR=$with_berkeleydb,
    BERKELEY_DB_DIR=no)
AC_MSG_CHECKING(if BerkeleyDB is desired)
if test x"$BERKELEY_DB_DIR" = xno ; then
    AC_MSG_RESULT(no)
    BERKELEY_DB_LDFLAGS=
    BERKELEY_DB_CFLAGS=
    BERKELEY_DB_LIB=
else
    AC_MSG_RESULT(yes)
    AC_MSG_CHECKING(for BerkeleyDB location)
    if test x"$BERKELEY_DB_DIR" = xyes ; then
        for v in BerkeleyDB BerkeleyDB.3.0 BerkeleyDB.3.1 BerkeleyDB.3.2 \
                 BerkeleyDB.3.3 BerkeleyDB.4.0 BerkeleyDB.4.1 ; do
            for d in $prefix /usr/local /opt /usr ; do
                if test -d "$d/$v" ; then
                    BERKELEY_DB_DIR="$d/$v"
                    break
                fi
	    done
        done
    fi
    if test x"$BERKELEY_DB_DIR" = xyes ; then
        for v in db41 db4 db3 db2 ; do
            if test -d "/usr/local/include/$v" ; then
                BERKELEY_DB_LDFLAGS="-L/usr/local/lib"
                BERKELEY_DB_CFLAGS="-I/usr/local/include/$v"
                BERKELEY_DB_LIB="-l$v"
                AC_MSG_RESULT(FreeBSD locations)
                break
            fi
        done
        if test x"$BERKELEY_DB_LIB" = x ; then
            for v in db41 db4 db3 db2 ; do
                if test -d "/usr/include/$v" ; then
                    BERKELEY_DB_CFLAGS="-I/usr/include/$v"
                    BERKELEY_DB_LIB="-l$v"
                    AC_MSG_RESULT(Linux locations)
                    break
                fi
            done
            if test x"$BERKELEY_DB_LIB" = x ; then        
                BERKELEY_DB_LIB=-ldb
                AC_MSG_RESULT(trying -ldb)
            fi
        fi
    else
        BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib"
        BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include"
        BERKELEY_DB_LIB="-ldb"
        AC_MSG_RESULT($BERKELEY_DB_DIR)
    fi
    AC_DEFINE(USE_BERKELEY_DB, 1, [Define if BerkeleyDB is available.])
fi
AC_SUBST(BERKELEY_DB_LDFLAGS)
AC_SUBST(BERKELEY_DB_CFLAGS)
AC_SUBST(BERKELEY_DB_LIB)])
INN_LIB_BERKELEYDB

dnl Check for whether the user wants to compile with OpenSSL, and if so what
dnl the path to the various components of it is.
AC_DEFUN([INN_LIB_OPENSSL],
[AC_ARG_WITH(openssl,
    [  --with-openssl=PATH     Enable OpenSSL (for NNTP over SSL support)],
    OPENSSL_DIR=$with_openssl,
    OPENSSL_DIR=no)
AC_MSG_CHECKING(if OpenSSL is desired)
if test x"$OPENSSL_DIR" = xno ; then
    AC_MSG_RESULT(no)
    SSL_BIN=
    SSL_INC=
    SSL_LIB=
else
    AC_MSG_RESULT(yes)
    AC_MSG_CHECKING(for OpenSSL location)
    if test x"$OPENSSL_DIR" = xyes ; then
        for dir in $prefix /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg \
                   /usr/local /usr ; do
            if test -f "$dir/include/openssl/ssl.h" ; then
                OPENSSL_DIR=$dir
                break
            fi
        done
    fi
    if test x"$OPENSSL_DIR" = xyes ; then
        AC_MSG_ERROR(Can not find OpenSSL)
    else
        AC_MSG_RESULT($OPENSSL_DIR)
	SSL_BIN="${OPENSSL_DIR}/bin"
	SSL_INC="-I${OPENSSL_DIR}/include"

        # This is mildly tricky.  In order to satisfy most linkers, libraries
        # have to be listed in the right order, which means that libraries
        # with dependencies on other libraries need to be listed first.  But
        # the -L flag for the OpenSSL library directory needs to go first of
        # all.  So put the -L flag into LIBS and accumulate actual libraries
        # into SSL_LIB, and then at the end, restore LIBS and move -L to the
        # beginning of SSL_LIB.
        inn_save_LIBS=$LIBS
        LIBS="$LIBS -L${OPENSSL_DIR}/lib"
	SSL_LIB=''
	AC_CHECK_LIB(rsaref, RSAPublicEncrypt,
	    [AC_CHECK_LIB(RSAglue, RSAPublicEncrypt,
                          [SSL_LIB="-lRSAglue -lrsaref"], , -lrsaref)])
	AC_CHECK_LIB(crypto, BIO_new,
                     [AC_CHECK_LIB(dl, DSO_load,
		                   SSL_LIB="-lcrypto -ldl $SSL_LIB",
		                   SSL_LIB="-lcrypto $SSL_LIB",
                                   -lcrypto -ldl $SSL_LIB)],
                     [AC_MSG_ERROR(Can not find OpenSSL)],
                     $SSL_LIB)
	AC_CHECK_LIB(ssl, SSL_library_init,
                     [SSL_LIB="-lssl $SSL_LIB"],
                     [AC_MSG_ERROR(Can not find OpenSSL)],
                     $SSL_LIB)
        SSL_LIB="-L${OPENSSL_DIR}/lib $SSL_LIB"
        LIBS=$inn_save_LIBS
        AC_DEFINE(HAVE_SSL, 1, [Define if OpenSSL is available.])
    fi
fi
AC_SUBST(SSL_BIN)
AC_SUBST(SSL_INC)
AC_SUBST(SSL_LIB)])
INN_LIB_OPENSSL

dnl Check for whether the user wants to compile with SASL, and if so what
dnl the path to the various components of it is.
AC_DEFUN([INN_LIB_SASL],
[AC_ARG_WITH(sasl,
    [  --with-sasl=PATH        Enable SASL (for imapfeed authentication)],
    SASL_DIR=$with_sasl,
    SASL_DIR=no)
AC_MSG_CHECKING(if SASL is desired)
if test x"$SASL_DIR" = xno ; then
    AC_MSG_RESULT(no)
    SASL_INC=
    SASL_LIB=
else
    AC_MSG_RESULT(yes)
    AC_MSG_CHECKING(for SASL location)
    if test x"$SASL_DIR" = xyes ; then
        for dir in $prefix /usr/local/sasl /usr/sasl /usr/pkg /usr/local ; do
            if test -f "$dir/include/sasl/sasl.h" ; then
                SASL_DIR=$dir
                break
            fi
        done
    fi
    if test x"$SASL_DIR" = xyes ; then
        if test -f "/usr/include/sasl/sasl.h" ; then
            SASL_INC=-I/usr/include/sasl
            SASL_DIR=/usr
            AC_MSG_RESULT($SASL_DIR)
            inn_save_LIBS=$LIBS
            AC_CHECK_LIB(sasl2, sasl_getprop,
                 [SASL_LIB=-lsasl2], [AC_MSG_ERROR(Can not find SASL)])
            LIBS=$inn_save_LIBS
            AC_DEFINE(HAVE_SASL, 1, [Define if SASL is available.])
        else
            AC_MSG_ERROR(Can not find SASL)
        fi
    else
        AC_MSG_RESULT($SASL_DIR)
	SASL_INC="-I${SASL_DIR}/include"

        inn_save_LIBS=$LIBS
        LIBS="$LIBS -L${SASL_DIR}/lib"
	AC_CHECK_LIB(sasl2, sasl_getprop,
                     [SASL_LIB="-L${SASL_DIR}/lib -lsasl2"],
                     [AC_MSG_ERROR(Can not find SASL)],)
        LIBS=$inn_save_LIBS
        AC_DEFINE(HAVE_SASL, 1, [Define if SASL is available.])
    fi
fi
AC_SUBST(SASL_INC)
AC_SUBST(SASL_LIB)])
INN_LIB_SASL

dnl Specify the path to the Kerberos libraries if the user wants to build
dnl auth_krb5.  Note that we don't search far and wide for the libraries if
dnl the user doesn't specify the path.
AC_ARG_WITH(kerberos,
    [  --with-kerberos=PATH    Path to Kerberos v5 (for auth_krb5)],
    [if test x"$with_kerberos" != xno ; then
         KRB5_LIB="-L$with_kerberos/lib"
         KRB5_INC="-I$with_kerberos/include"
     fi])

dnl Checks for embedded interpretors.
dnl
dnl FIXME: These should ideally be combined with the later logic to
dnl determine the version, determine the compiler and linker flags, etc.
AC_ARG_WITH(perl,
    [  --with-perl             Embedded Perl script support [default=no]],
    [case "${withval}" in
    yes) DO_PERL=DO
         AC_DEFINE(DO_PERL, 1, [Define to compile in Perl script support.])
         ;;
    no)  DO_PERL=DONT ;;
    *)   AC_MSG_ERROR(invalid argument to --with-perl) ;;
    esac],
    DO_PERL=DONT)

AC_ARG_WITH(python,
    [  --with-python           Embedded Python module support [default=no]],
    [case "${withval}" in
    yes) DO_PYTHON=define
         AC_DEFINE(DO_PYTHON, 1,
                   [Define to compile in Python module support.])
         ;;
    no)  DO_PYTHON=DONT ;;
    *)   AC_MSG_ERROR(invalid argument to --with-python) ;;
    esac],
    DO_PYTHON=DONT)

dnl Tcl support.  For Tcl, the user can supply the path to the Tcl include
dnl files and libraries (for Perl and Python, this is determined
dnl automatically from little scripts run by the binary found in the user's
dnl path).
dnl
dnl FIXME: This should really use tclConfig.sh.
AC_DEFUN([INN_LIB_TCL],
[AC_ARG_WITH(tcl,
    [  --with-tcl=PATH         Embedded TCL script support [default=no]],
    TCL_DIR=$with_tcl,
    TCL_DIR=no)
if test x"$TCL_DIR" = xno ; then
    TCL_INC=
    TCL_LIB=
else
    if test x"$TCL_DIR" = xyes ; then
        TCL_INC="-I/usr/local/include"
        TCL_LIB="-L/usr/local/lib -ltcl -lm"
    else
        TCL_INC="-I${TCL_DIR}/include"
        TCL_LIB="-L${TCL_DIR}/lib -ltcl -lm"
    fi
    AC_DEFINE(DO_TCL, 1, [Define to compile in TCL script support.])
fi
AC_SUBST(TCL_LIB)
AC_SUBST(TCL_INC)])
INN_LIB_TCL

dnl Set some configuration file defaults from the machine hostname.
HOSTNAME=`hostname 2> /dev/null || uname -n`
AC_SUBST(HOSTNAME)

dnl Checks for programs.
AC_PROG_GCC_TRADITIONAL
AC_PROG_LEX
AC_PROG_MAKE_SET
AC_PROG_RANLIB
AC_PROG_YACC

dnl On MacOS X Server, -traditional-cpp is needed for gcc for compiling as
dnl well as preprocessing according to Miro Jurisic <meeroh@meeroh.org>.
case "$CPP" in
*-traditional-cpp*)
    CFLAGS="-traditional-cpp $CFLAGS"
    ;;
esac

case "$host" in

dnl HP-UX's native compiler needs a special flag to turn on ANSI, and needs
dnl -g on link as well as compile for debugging to work.
*hpux*)
    if test x"$GCC" != xyes ; then
        dnl Need flag to turn on ANSI.
        CFLAGS="$CFLAGS -Ae"

        dnl Need -g on link command for debug to work properly.
        case "$CFLAGS" in
        *-g*)
            LDFLAGS="$LDFLAGS -g"
            ;;
        esac
    fi
    ;;

dnl OSX needs '-multiply_defined suppress' 
*darwin*)
    LDFLAGS="$LDFLAGS -multiply_defined suppress"
    ;;

dnl From Boyd Gerber <gerberb@zenez.com>, needed in some cases to compile
dnl the bison-generated parser for innfeed.conf.
*UnixWare*|*unixware*|*-sco3*)
    if test x"$GCC" != xyes ; then
        CFLAGS="$CFLAGS -Kalloca"
    fi
esac
  
dnl Checks for pathnames.

dnl See if we have ctags; if so, set CTAGS to its full path plus the -t -w
dnl options.  Otherwise, set CTAGS to echo.
AC_PATH_PROG(CTAGS, ctags, echo)
if test x"$CTAGS" != xecho ; then
    CTAGS="$CTAGS -t -w"
fi

dnl Use INN_PATH_PROG if it's an error not to find a program.
AC_DEFUN([INN_ENSURE_PATH_PROG],
[AC_PATH_PROG($1, $2)
if test -z "${$1}" ; then
    AC_MSG_ERROR($2 was not found in path and is required)
fi])

INN_ENSURE_PATH_PROG(_PATH_AWK,awk)
INN_ENSURE_PATH_PROG(_PATH_EGREP,egrep)
INN_ENSURE_PATH_PROG(_PATH_PERL,perl)
INN_ENSURE_PATH_PROG(_PATH_SH,sh)
INN_ENSURE_PATH_PROG(_PATH_SED,sed)
INN_ENSURE_PATH_PROG(_PATH_SORT,sort)

dnl Check for a required version of Perl.  The separate shell variable and
dnl the changequotes are necessary for autoconf 2.13; autoconf 2.50 will
dnl provide a different interface that will allow this to work correctly.
changequote(<<,>>)dnl
inn_perl_command='print $]'
changequote([,])dnl
AC_DEFUN([INN_PERL_VERSION],
[AC_CACHE_CHECK(for Perl version, inn_cv_perl_version,
[if $_PATH_PERL -e 'require $1;' > /dev/null 2>&1 ; then
    inn_cv_perl_version=`$_PATH_PERL -e "$inn_perl_command"`
else
    AC_MSG_ERROR(Perl $1 or greater is required)
fi])])

dnl Embedded Perl requires 5.004.  controlchan requires 5.004_03.  Other
dnl things may work with 5.003, but make 5.004_03 the minimum level; anyone
dnl should really have at least that these days.
INN_PERL_VERSION(5.004_03)

dnl Look for PGP 5.0's pgpv, then pgp, then pgpgpg (not sure why anyone would
dnl have pgpgpg and not gpgv, but it doesn't hurt).  Separately look for
dnl GnuPG (which we prefer).
pgpverify=true
AC_PATH_PROGS(PATH_GPGV, gpgv)
AC_PATH_PROGS(_PATH_PGP, pgpv pgp pgpgpg)
if test -z "$_PATH_PGP" && test -z "$PATH_GPGV" ; then
    pgpverify=false
fi
AC_SUBST(pgpverify)

dnl Look for a program that takes an ftp URL as a command line argument and
dnl retrieves the file to the current directory.  Shame we can't also use
dnl lynx -source; it only writes to stdout.  ncftp as of version 3 doesn't
dnl support this any more (it comes with ncftpget instead), but if someone
dnl has ncftp and not ncftpget they have an earlier version.
AC_PATH_PROGS(GETFTP, wget ncftpget ncftp, $prefix/bin/simpleftp)

dnl Look for both compress and gzip, since the UUCP batching scripts require
dnl both.  If we're using a log compression method other than compress or
dnl gzip, check for it too and make sure whatever log compressor we're using
dnl exists.  If we don't find compress or gzip for the UUCP scripts, just
dnl use the bare program names in the hope that the path will be better at
dnl the time the script runs (or that the script will never run).
case "$LOG_COMPRESS" in
compress|gzip) ;;
*)             INN_ENSURE_PATH_PROG(LOG_COMPRESS, "$LOG_COMPRESS")
esac
AC_PATH_PROG(COMPRESS, compress, compress)
if test x"$LOG_COMPRESS" = xcompress ; then
    if test x"$COMPRESS" = xcompress ; then
        AC_MSG_ERROR(compress not found but specified for log compression)
    fi
    LOG_COMPRESS="$COMPRESS"
fi
AC_PATH_PROG(GZIP, gzip, gzip)
if test x"$LOG_COMPRESS" = xgzip ; then
    if test x"$GZIP" = xgzip ; then
        AC_MSG_ERROR(gzip not found but specified for log compression)
    fi
    LOG_COMPRESS="$GZIP"
fi

dnl Figure out what program to use to uncompress .Z files.  On systems that
dnl have gzip but don't have compress, we can use gzip for this purpose and
dnl should rather than hoping compres will be found at runtime.
if test x"$COMPRESS" = xcompress && test x"$GZIP" != xgzip ; then
    UNCOMPRESS="$GZIP -d"
else
    UNCOMPRESS="$COMPRESS -d"
fi
AC_SUBST(UNCOMPRESS)

dnl Search for sendmail, checking the path first and then some common
dnl locations.  If --with-sendmail was given, that path overrides.
if test "${with_sendmail+set}" = set ; then
    AC_MSG_CHECKING(for sendmail)
    AC_MSG_RESULT($SENDMAIL)
else
    AC_PATH_PROG(SENDMAIL, sendmail, , "$PATH:/usr/sbin:/usr/lib")
    if test -z "$SENDMAIL" ; then
        AC_MSG_ERROR(sendmail not found, re-run with --with-sendmail)
    fi
fi

dnl FIXME: innshellvars* wants to know if we have uustat, send-uucp expects
dnl it to be in the old subst DO/DONT format.  Should take a path.
AC_CHECK_PROG(HAVE_UUSTAT, uustat, DO, DONT)
AC_SUBST(HAVE_UUSTAT)

dnl If we're compiling with Python support, make sure Python is available.
if test x"$DO_PYTHON" = xdefine ; then
    INN_ENSURE_PATH_PROG(_PATH_PYTHON, python)
fi

dnl Search for a particular library, and if found, add that library to the
dnl specified variable (the third argument) and run the commands given in the
dnl fourth argument, if any.  This is for libraries we don't want to pollute
dnl LIBS with.
AC_DEFUN([INN_SEARCH_AUX_LIBS],
[inn_save_LIBS=$LIBS
LIBS=${$3}
AC_SEARCH_LIBS($1, $2,
               [$3=$LIBS
                $4], $5, $6)
LIBS=$inn_save_LIBS
AC_SUBST($3)])

dnl Checks for libraries.  Use AC_SEARCH_LIBS where possible to avoid
dnl adding libraries when the function is found in libc.  In several
dnl cases, we explicitly just add the library to LIBS on success rather
dnl than using default actions so as not to clutter config.h with defines
dnl we never use.

dnl Check for setproctitle in libc first, then libutil if not found there.
dnl We have a replacement function if we can't find it, and then we also need
dnl to check for pstat.
AC_SEARCH_LIBS(setproctitle, util,
    [AC_DEFINE(HAVE_SETPROCTITLE, 1,
        [Define if you have the setproctitle function.])],
    [LIBOBJS="$LIBOBJS setproctitle.o"
     AC_CHECK_FUNCS(pstat)])

dnl The rat's nest of networking libraries.  The common cases are not to
dnl need any extra libraries, or to need -lsocket -lnsl.  We need to avoid
dnl linking with libnsl unless we need it, though, since on some OSes where
dnl it isn't necessary it will totally break networking.  Unisys also
dnl includes gethostbyname in libsocket but needs libnsl for socket().
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(socket, socket, ,
    [AC_CHECK_LIB(nsl, socket, LIBS="$LIBS -lsocket -lnsl", , -lsocket)])

dnl Check for inet_aton.  We have our own, but on Solaris the version in
dnl libresolv is more lenient in ways that Solaris's internal DNS resolution
dnl code requires, so if we use our own *and* link with libresolv (which may
dnl be forced by Perl) DNS resolution fails.
AC_SEARCH_LIBS(inet_aton, resolv)

dnl Search for various additional libraries used by portions of INN.
INN_SEARCH_AUX_LIBS(crypt, crypt, CRYPT_LIB)
INN_SEARCH_AUX_LIBS(getspnam, shadow, SHADOW_LIB)
INN_SEARCH_AUX_LIBS(dbm_open, ndbm dbm, DBM_LIB,
    [AC_DEFINE(HAVE_DBM, 1, [Define if you have a dbm library.])])
INN_SEARCH_AUX_LIBS(pam_start, pam, PAM_LIB,
    [AC_DEFINE(HAVE_PAM, 1, [Define if you have PAM.])])

dnl If keyword generation support was requested, check for the appropriate
dnl libraries.
if test x"$inn_enable_keywords" = x1 ; then
    INN_SEARCH_AUX_LIBS(regexec, regex, REGEX_LIB, ,
        [AC_MSG_ERROR(no usable regular expression library found)])
fi

dnl Check for Kerberos libraries for auth_krb5, and if found define KRB5_AUTH
dnl to the relevant object file, which will enable compilation of it.
INN_SEARCH_AUX_LIBS(krb5_parse_name, krb5, KRB5_LIB,
    [KRB5_AUTH="auth_krb5"
     KRB5_LIB="$KRB5_LIB -lk5crypto -lcom_err"
     AC_SUBST(KRB5_AUTH)
     AC_SUBST(KRB5_INC)], , [$LIBS -lk5crypto -lcom_err])

dnl Check for necessity of krb5_init_ets
dnl OSX does not require this function
inn_save_LIBS=$LIBS
LIBS=$KRB5_LIB
AC_CHECK_FUNCS(krb5_init_ets)
LIBS=$inn_save_LIBS

dnl Libraries and flags for embedded Perl.  Some distributions of Linux have
dnl Perl linked with gdbm but don't normally have gdbm installed, so on that
dnl platform only strip -lgdbm out of the Perl libraries.  Leave it in on
dnl other platforms where it may be necessary (it isn't on Linux; Linux
dnl shared libraries can manage their own dependencies).  Strip -lc out, which
dnl is added on some platforms, is unnecessary, and breaks compiles with
dnl -pthread (which may be added by Python).
dnl
dnl If we aren't compiling with large-file support, strip out the large file
dnl flags from inn_perl_core_flags; otherwise, innd/cc.c and lib/qio.c
dnl disagree over the size of an off_t.  Since none of our calls into Perl
dnl use variables of type off_t, this should be harmless; in any event, it's
dnl going to be better than the innd/cc.c breakage.
if test x"$DO_PERL" = xDO ; then
    AC_MSG_CHECKING(for Perl linkage)
    inn_perl_core_path=`$_PATH_PERL -MConfig -e 'print $Config{archlibexp}'`
    inn_perl_core_flags=`$_PATH_PERL -MExtUtils::Embed -e ccopts`
    inn_perl_core_libs=`$_PATH_PERL -MExtUtils::Embed -e ldopts 2>&1 | tail -1`
    inn_perl_core_libs=" $inn_perl_core_libs "
    inn_perl_core_libs=`echo "$inn_perl_core_libs" | sed 's/ -lc / /'`
    for i in $LIBS ; do
        inn_perl_core_libs=`echo "$inn_perl_core_libs" | sed "s/ $i / /"`
    done
    case $host in
    *-linux*)
        inn_perl_core_libs=`echo "$inn_perl_core_libs" | sed 's/ -lgdbm / /'`
        ;;
    *-cygwin*)
        inn_perl_libname=`$_PATH_PERL -MConfig -e 'print $Config{libperl}'`
        inn_perl_libname=`echo "$inn_perl_libname" | sed 's/^lib//; s/\.a$//'`
        inn_perl_core_libs="${inn_perl_core_libs}-l$inn_perl_libname"
        ;;
    esac
    inn_perl_core_libs=`echo "$inn_perl_core_libs" | sed 's/^  *//'`
    inn_perl_core_libs=`echo "$inn_perl_core_libs" | sed 's/  *$//'`
    inn_perl_core_flags=" $inn_perl_core_flags "
    if test x"$inn_enable_largefiles" != xyes ; then
        for f in -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES ; do
            inn_perl_core_flags=`echo "$inn_perl_core_flags" | sed "s/ $f / /"`
        done
    fi
    inn_perl_core_flags=`echo "$inn_perl_core_flags" | sed 's/^  *//'`
    inn_perl_core_flags=`echo "$inn_perl_core_flags" | sed 's/  *$//'`
    PERL_INC="$inn_perl_core_flags"
    PERL_LIB="$inn_perl_core_libs"
    AC_MSG_RESULT($inn_perl_core_path)
else
    PERL_INC=''
    PERL_LIB=''
fi
AC_SUBST(PERL_INC)
AC_SUBST(PERL_LIB)

dnl Libraries and flags for embedded Python.
dnl
dnl FIXME: I wish there was a less icky way to get this.
if test x"$DO_PYTHON" = xdefine ; then
    AC_MSG_CHECKING(for Python linkage)
    py_prefix=`$_PATH_PYTHON -c 'import sys; print sys.prefix'`
    py_ver=`$_PATH_PYTHON -c 'import sys; print sys.version[[:3]]'`
    py_libdir="${py_prefix}/lib/python${py_ver}"
    PYTHON_INC="-I${py_prefix}/include/python${py_ver}"
    py_linkage=""
    for py_linkpart in LIBS LIBC LIBM LOCALMODLIBS BASEMODLIBS \
                       LINKFORSHARED LDFLAGS ; do
        py_linkage="$py_linkage "`grep "^${py_linkpart}=" \
                                       $py_libdir/config/Makefile \
                                  | sed -e 's/^.*=//'`
    done
    PYTHON_LIB="-L$py_libdir/config -lpython$py_ver $py_linkage"
    PYTHON_LIB=`echo $PYTHON_LIB | sed -e 's/[ \\t]*/ /g'`
    AC_MSG_RESULT($py_libdir)
else
    PYTHON_LIB=""
    PYTHON_INC=""
fi
AC_SUBST(PYTHON_LIB)
AC_SUBST(PYTHON_INC)

dnl If configuring with large file support, determine the right flags to
dnl use based on the platform.  This is the wrong approach; autoconf 2.50
dnl comes with a macro that takes the right approach.  But this works well
dnl enough until we switch to autoconf 2.50 or later.
if test x"$inn_enable_largefiles" = xyes ; then
    AC_MSG_CHECKING(for largefile linkage)
    case "$host" in
    *-aix4.[01]*)
        AC_MSG_RESULT(no)
        AC_MSG_ERROR([AIX before 4.2 does not support large files])
        ;;
    *-aix4*)
        AC_MSG_RESULT(ok)
        LFS_CFLAGS="-D_LARGE_FILES"
        LFS_LDFLAGS=""
        LFS_LIBS=""
        ;;
    *-hpux*)
        AC_MSG_RESULT(ok)
        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
        LFS_LDFLAGS=""
        LFS_LIBS=""
        ;;
    *-irix*)
        AC_MSG_RESULT(no)
        AC_MSG_ERROR([Large files not supported on this platform])
        ;;
    *-linux*)
        AC_MSG_RESULT(maybe)
        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
        LFS_LDFLAGS=""
        LFS_LIBS=""
        AC_DEFINE([_GNU_SOURCE], 1,
                  [Some versions of glibc need this defined for pread/pwrite.])
        ;;
    *-solaris*)
        AC_MSG_RESULT(ok)
        AC_PATH_PROG(GETCONF, getconf)
        if test -z "$GETCONF" ; then
            AC_MSG_ERROR([getconf required to configure large file support])
        fi
        LFS_CFLAGS=`$GETCONF LFS_CFLAGS`
        LFS_LDFLAGS=`$GETCONF LFS_LDFLAGS`
        LFS_LIBS=`$GETCONF LFS_LIBS`
        ;;
    *)
        AC_MSG_RESULT(maybe)
        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
        LFS_LDFLAGS=""
        LFS_LIBS=""
        ;;
    esac
    AC_SUBST(LFS_CFLAGS)
    AC_SUBST(LFS_LDFLAGS)
    AC_SUBST(LFS_LIBS)
fi

dnl Start by checking for standard C headers.  AC_HEADER_STDC will set
dnl STDC_HEADERS if stdlib.h, stdarg.h, string.h, and float.h all exist, if
dnl memchr (and probably the other mem functions) is in string.h, if free (and
dnl probably malloc and friends) are in stdlib.h, and if ctype.h will work on
dnl high-bit characters.
AC_HEADER_STDC

dnl Only if that wasn't set do we need to go hunting for other headers to
dnl include on non-ANSI systems and check for functions that all ANSI C
dnl systems should have.
if test x"$ac_cv_header_stdc" = xno ; then
    AC_CHECK_HEADERS(memory.h stdlib.h strings.h)
    AC_CHECK_FUNCS(memcpy strchr)
fi

dnl Special checks for header files.
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT

dnl Generic checks for header files.
AC_CHECK_HEADERS(crypt.h inttypes.h limits.h ndbm.h pam/pam_appl.h stdbool.h \
                 stddef.h stdint.h string.h sys/bitypes.h sys/filio.h \
                 sys/loadavg.h sys/param.h sys/select.h sys/sysinfo.h \
                 sys/time.h unistd.h)

dnl Some Linux systems have db1/ndbm.h instead of ndbm.h.  Others have
dnl gdbm-ndbm.h.
if test x"$ac_cv_header_ndbm_h" = xno ; then
    AC_CHECK_HEADERS(db1/ndbm.h gdbm-ndbm.h)
fi

dnl Check to see if herrno is declared.
AC_DEFUN([INN_NEED_HERRNO_DECLARATION],
[AC_CACHE_CHECK([whether h_errno must be declared], inn_cv_herrno_need_decl,
[AC_TRY_COMPILE([#include <netdb.h>], [h_errno = 0;],
               inn_cv_herrno_need_decl=no,
               inn_cv_herrno_need_decl=yes)])
if test "$inn_cv_herrno_need_decl" = yes ; then
    AC_DEFINE([NEED_HERRNO_DECLARATION], 1,
              [Define if <netdb.h> does not declare h_errno.])
fi])
INN_NEED_HERRNO_DECLARATION

dnl The set of standard includes, used for checking if functions need to be
dnl declared and for tests that need to use standard functions.
define([_INN_HEADER_SOURCE],
[#include <stdio.h>
#include <sys/types.h>
#if STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# if HAVE_STDLIB_H
#  include <stdlib.h>
# endif
# if !HAVE_STRCHR
#  define strchr index
#  define strrchr rindex
# endif
#endif
#if HAVE_STRING_H
# if !STDC_HEADERS && HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
#else
# if HAVE_STRINGS_H
#  include <strings.h>
# endif
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif])

dnl See if a given function needs a declaration by seeing if we can access a
dnl function pointer for that function.  This is done in a really ugly way
dnl with hacks so that autoheader will pick up the defines properly; it's a
dnl stop-gap solution until switching to autoconf 2.50.
AC_DEFUN([INN_NEED_DECLARATION],
[AC_MSG_CHECKING([whether $1 must be declared])
AC_CACHE_VAL([inn_cv_decl_needed_$1],
[AC_TRY_COMPILE(
_INN_HEADER_SOURCE()
[$3],
[char *(*pfn) = (char *(*)) $1],
[inn_cv_decl_needed_$1=no], [inn_cv_decl_needed_$1=yes])])
if test $inn_cv_decl_needed_$1 = yes ; then
    AC_MSG_RESULT(yes)
    AC_DEFINE($2, 1, [Define if $1 isn't declared in the system headers.])
else
    AC_MSG_RESULT(no)
fi])
INN_NEED_DECLARATION(inet_aton, [NEED_DECLARATION_INET_ATON],
[#include <netinet/in.h>
#include <arpa/inet.h>])
INN_NEED_DECLARATION(inet_ntoa, [NEED_DECLARATION_INET_NTOA],
[#include <netinet/in.h>
#include <arpa/inet.h>])
INN_NEED_DECLARATION(snprintf, [NEED_DECLARATION_SNPRINTF])
INN_NEED_DECLARATION(vsnprintf, [NEED_DECLARATION_VSNPRINTF])

dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
AC_C_CONST
AC_STRUCT_ST_BLKSIZE
AC_STRUCT_TM
AC_TYPE_SIZE_T
AC_TYPE_UID_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_CHECK_TYPE(ssize_t, int)

dnl Check for ISO C99 variadic macro support in the compiler.
AC_DEFUN([INN_C_C99_VAMACROS],
[AC_CACHE_CHECK(for C99 variadic macros, inn_cv_c_c99_vamacros,
[AC_TRY_COMPILE(
[#include <stdio.h>
#define error(...) fprintf(stderr, __VA_ARGS__)],
[error("foo"); error("foo %d", 0); return 0;],
[inn_cv_c_c99_vamacros=yes], [inn_cv_c_c99_vamacros=no])])
if test $inn_cv_c_c99_vamacros = yes ; then
    AC_DEFINE(HAVE_C99_VAMACROS, 1,
              [Define if the compiler supports C99 variadic macros.])
fi])
INN_C_C99_VAMACROS

dnl Check for GNU-style variadic macro support in the compiler.
AC_DEFUN([INN_C_GNU_VAMACROS],
[AC_CACHE_CHECK(for GNU-style variadic macros, inn_cv_c_gnu_vamacros,
[AC_TRY_COMPILE(
[#include <stdio.h>
#define error(args...) fprintf(stderr, args)],
[error("foo"); error("foo %d", 0); return 0;],
[inn_cv_c_gnu_vamacros=yes], [inn_cv_c_gnu_vamacros=no])])
if test $inn_cv_c_gnu_vamacros = yes ; then
    AC_DEFINE(HAVE_GNU_VAMACROS, 1,
              [Define if the compiler supports GNU-style variadic macros.])
fi])
INN_C_GNU_VAMACROS

dnl Check for long long int, and define HAVE_LONG_LONG if the compiler
dnl supports it.
AC_DEFUN([INN_C_LONG_LONG],
[AC_CACHE_CHECK(for long long int, inn_cv_c_long_long,
[AC_TRY_COMPILE(, [long long int i;],
                inn_cv_c_long_long=yes,
                inn_cv_c_long_long=no)])
if test $inn_cv_c_long_long = yes ; then
    AC_DEFINE(HAVE_LONG_LONG, 1,
              [Define if the compiler supports long long int.])
fi])
INN_C_LONG_LONG

dnl From Paul D. Smith <psmith@baynetworks.com> on the autoconf mailing list,
dnl this is a version of AC_CHECK_TYPE that allows specification of additional
dnl headers.  It's a modified version of the standard autoconf macro.
AC_DEFUN([INN_CHECK_TYPE],
[AC_REQUIRE([AC_HEADER_STDC])
AC_MSG_CHECKING(for $1)
AC_CACHE_VAL(ac_cv_type_$1,
[AC_EGREP_CPP(dnl
changequote(<<, >>)dnl
<<(^|[^a-zA-Z_0-9])$1[^a-zA-Z_0-9]>>dnl
changequote([, ]),
[#include <sys/types.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#endif
$3],
    ac_cv_type_$1=yes,
    ac_cv_type_$1=no
)])
AC_MSG_RESULT($ac_cv_type_$1)
if test x"$ac_cv_type_$1" = xno ; then
    AC_DEFINE_UNQUOTED($1, $2)
fi])

INN_CHECK_TYPE(sig_atomic_t, int, [#include <signal.h>])
INN_CHECK_TYPE(socklen_t, int, [#include <sys/socket.h>])

dnl Source used by INN_MACRO_IOV_MAX.
define([_INN_MACRO_IOV_MAX_SOURCE],
[[#include <sys/types.h>
#include <stdio.h>
#include <sys/uio.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif

int
main ()
{
  int fd, size;
  struct iovec array[1024];
  char data;

  FILE *f = fopen ("conftestval", "w");
  if (!f) return 1;
#ifdef IOV_MAX
  fprintf (f, "set in limits.h\n");
#else
# ifdef UIO_MAXIOV
  fprintf (f, "%d\n", UIO_MAXIOV);
# else
  fd = open ("/dev/null", O_WRONLY, 0666);
  if (fd < 0) return 1;
  for (size = 1; size <= 1024; size++)
    {
      array[size - 1].iov_base = &data;
      array[size - 1].iov_len = sizeof data;
      if (writev (fd, array, size) < 0)
        {
          if (errno != EINVAL) return 1;
          fprintf(f, "%d\n", size - 1);
          exit (0);
        }
    }
  fprintf (f, "1024\n");
# endif /* UIO_MAXIOV */
#endif /* IOV_MAX */
  return 0;
}]])

dnl Check for the number of elements in an iovec (IOV_MAX).  SVr4 systems
dnl appear to use that name for this limit (checked Solaris 2.6, IRIX 6.5, and
dnl HP-UX 11.00).  Linux doesn't have it, but instead has UIO_MAXIOV defined
dnl in <iovec.h> included from <sys/uio.h>.  The platforms that have IOV_MAX
dnl appear to also offer it via sysconf(3), but it should be a constant for a
dnl given implementation.  Set IOV_MAX if it's not defined in <sys/uio.h> or
dnl <limits.h>.
AC_DEFUN([INN_MACRO_IOV_MAX],
[AC_CACHE_CHECK([value of IOV_MAX], [inn_cv_macro_iov_max],
[AC_TRY_RUN(_INN_MACRO_IOV_MAX_SOURCE(),
            inn_cv_macro_iov_max=`cat conftestval`,
            inn_cv_macro_iov_max=error, 16)
if test x"$inn_cv_macro_iov_max" = xerror ; then
    AC_MSG_WARN([probe failure, assuming 16])
    inn_cv_macro_iov_max=16
fi])
if test x"$inn_cv_macro_iov_max" != x"set in limits.h" ; then
    AC_DEFINE_UNQUOTED(IOV_MAX, $inn_cv_macro_iov_max,
                       [Define to the max vectors in an iovec.])
fi])
INN_MACRO_IOV_MAX

dnl Check for SUN_LEN (size of a Unix domain socket struct, macro required
dnl POSIX.1g but not that widespread yet).
AC_DEFUN([INN_MACRO_SUN_LEN],
[AC_CACHE_CHECK(for SUN_LEN, inn_cv_macro_sun_len,
[AC_TRY_LINK(
[#include <sys/types.h>
#include <sys/un.h>],
[struct sockaddr_un sun;
int i;

i = SUN_LEN(&sun);],
    inn_cv_macro_sun_len=yes,
    inn_cv_macro_sun_len=no)])
if test x"$inn_cv_macro_sun_len" = xyes ; then
    AC_DEFINE(HAVE_SUN_LEN, 1,
              [Define if <sys/un.h> defines the SUN_LEN macro.])
fi])
INN_MACRO_SUN_LEN

dnl BSD hosts have a tm_gmtoff element in struct tm containing the offset from
dnl GMT/UTC for that time.  This is the strongly preferred way of getting time
dnl zone information.
AC_DEFUN([INN_STRUCT_TM_GMTOFF],
[AC_CACHE_CHECK(for tm_gmtoff in struct tm, inn_cv_struct_tm_gmtoff,
[AC_TRY_LINK([#include <time.h>],
             [struct tm t; t.tm_gmtoff = 3600],
             inn_cv_struct_tm_gmtoff=yes,
             inn_cv_struct_tm_gmtoff=no)])
if test x"$inn_cv_struct_tm_gmtoff" = xyes ; then
    AC_DEFINE([HAVE_TM_GMTOFF], 1,
              [Define if your struct tm has a tm_gmtoff member.])
fi])
INN_STRUCT_TM_GMTOFF

dnl BSD hosts have the name of the local time zone in struct tm, which is much
dnl nicer to use than the tzname variable (and also potentially handles
dnl renamings of the time zone in the past).
AC_DEFUN([INN_STRUCT_TM_ZONE],
[AC_CACHE_CHECK(for tm_zone in struct tm, inn_cv_struct_tm_zone,
[AC_TRY_LINK([#include <time.h>],
             [struct tm t; t.tm_zone = "UTC"],
             inn_cv_struct_tm_zone=yes,
             inn_cv_struct_tm_zone=no)])
if test x"$inn_cv_struct_tm_zone" = xyes ; then
    AC_DEFINE([HAVE_TM_ZONE], 1,
              [Define if your struct tm has a tm_zone member.])
fi])
INN_STRUCT_TM_ZONE

dnl Many System V hosts have an external variable timezone containing the
dnl offset of local time from GMT/UTC.  We can use this for the timezone
dnl offset for current time, although it's not usable for anything else.
dnl Unfortunately, some BSD varients have a function named timezone instead.
dnl HP-UX has timezone but doesn't have altzone, which isn't good enough.
AC_DEFUN([INN_VAR_TIMEZONE],
[AC_CACHE_CHECK(for timezone variable, inn_cv_var_timezone,
[AC_TRY_LINK([#include <time.h>], [timezone = 3600; altzone = 7200],
             inn_cv_var_timezone=yes,
             inn_cv_var_timezone=no)])
if test x"$inn_cv_var_timezone" = xyes ; then
    AC_DEFINE([HAVE_VAR_TIMEZONE], 1,
              [Define if timezone is an external variable in <time.h>.])
fi])
INN_VAR_TIMEZONE

dnl Many System V hosts and some BSD systems have an external variable tzname
dnl containing the abbreviations of the main and alternate time zone.  We can
dnl use these as a reasonable approximation of the correct time zone names,
dnl although they could be incorrect if the time zone name has changed in the
dnl past.
AC_DEFUN([INN_VAR_TZNAME],
[AC_CACHE_CHECK(for tzname variable, inn_cv_var_tzname,
[AC_TRY_LINK([#include <time.h>], [*tzname = "UTC"],
             inn_cv_var_tzname=yes,
             inn_cv_var_tzname=no)])
if test x"$inn_cv_var_tzname" = xyes ; then
    AC_DEFINE([HAVE_VAR_TZNAME], 1,
              [Define if tzname is an external variable in <time.h>.])
fi])
INN_VAR_TZNAME

dnl A modified version of AC_CHECK_SIZEOF that doesn't always AC_DEFINE, but
dnl instead lets you execute shell code based on success or failure.  This is
dnl to avoid config.h clutter.
AC_DEFUN(INN_IF_SIZEOF,
[changequote(<<, >>)dnl
dnl The name to #define.
define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
changequote([, ])dnl
AC_MSG_CHECKING(size of $1)
AC_CACHE_VAL(AC_CV_NAME,
[AC_TRY_RUN([#include <stdio.h>
main()
{
    FILE *f = fopen("conftestval", "w");
    if (!f) exit(1);
    fprintf(f, "%d\n", sizeof($1));
    exit(0);
}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0,
ifelse([$2], , , AC_CV_NAME=$2))
])dnl
AC_MSG_RESULT($AC_CV_NAME)
if test x"$AC_CV_NAME" = x"$3" ; then
    ifelse([$4], , :, [$4])
else
    ifelse([$5], , :, [$5])
fi
undefine([AC_TYPE_NAME])dnl
undefine([AC_CV_NAME])dnl
])

dnl Find a 32 bit type, by trying likely candidates.  First, check for the C9X
dnl int32_t, then look for something else with a size of four bytes.
INN_IF_SIZEOF(int, 4, 4, INN_INT32=int,
    [INN_IF_SIZEOF(long, 4, 4, INN_INT32=long,
        [INN_IF_SIZEOF(short, 2, 4, INN_INT32=short)])])
INN_CHECK_TYPE(int32_t, $INN_INT32,
[#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h>
#endif
])

dnl Figure out the unsigned version.
INN_CHECK_TYPE(uint32_t, unsigned $INN_INT32,
[#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h>
#endif
])

dnl Checks for library functions.
AC_FUNC_MEMCMP
AC_TYPE_SIGNAL

dnl Source used by INN_FUNC_INET_NTOA
define([_INN_FUNC_INET_NTOA_SOURCE],
[#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#if STDC_HEADERS || HAVE_STRING_H
# include <string.h>
#endif

int
main ()
{
  struct in_addr in;
  in.s_addr = htonl (0x7f000000L);
  return (!strcmp (inet_ntoa (in), "127.0.0.0") ? 0 : 1);
}])

dnl Check whether inet_ntoa is present and working.  Since calling inet_ntoa
dnl involves passing small structs on the stack, present and working versions
dnl may still not function with gcc on some platforms (such as IRIX).
AC_DEFUN([INN_FUNC_INET_NTOA],
[AC_CACHE_CHECK(for working inet_ntoa, inn_cv_func_inet_ntoa_works,
[AC_TRY_RUN(_INN_FUNC_INET_NTOA_SOURCE(),
            [inn_cv_func_inet_ntoa_works=yes],
            [inn_cv_func_inet_ntoa_works=no],
            [inn_cv_func_inet_ntoa_works=no])])
if test "$inn_cv_func_inet_ntoa_works" = yes ; then
    AC_DEFINE([HAVE_INET_NTOA], 1,
              [Define if your system has a working inet_ntoa function.])
else
    LIBOBJS="$LIBOBJS inet_ntoa.${ac_objext}"
fi])
INN_FUNC_INET_NTOA

dnl Check whether sockaddr structs have sa_len fields
AC_DEFUN([INN_SOCKADDR_SA_LEN],
[AC_CACHE_CHECK(whether struct sockaddr has sa_len,
		inn_cv_struct_sockaddr_sa_len,
		[AC_TRY_COMPILE(
			[#include <sys/types.h>
			#include <sys/socket.h>
			#include <netinet/in.h>],
			[struct sockaddr sa; int x = sa.sa_len;],
			[inn_cv_struct_sockaddr_sa_len=yes],
			[inn_cv_struct_sockaddr_sa_len=no])])
if test "$inn_cv_struct_sockaddr_sa_len" = yes ; then
    AC_DEFINE([HAVE_SOCKADDR_LEN],1,
	    [Define if your system has a sa_len field in struct sockaddr])
fi])
INN_SOCKADDR_SA_LEN

dnl Check whether we have an SA_LEN macro available to us
AC_DEFUN([INN_SA_LEN_MACRO],
[AC_CACHE_CHECK(for SA_LEN(s) macro, inn_cv_sa_len_macro,
		[AC_TRY_LINK(
			[#include <sys/types.h>
			#include <sys/socket.h>
			#include <netinet/in.h>],
			[struct sockaddr sa; int x = SA_LEN(&sa);],
			[inn_cv_sa_len_macro=yes],
			[inn_cv_sa_len_macro=no])])
if test "$inn_cv_sa_len_macro" = yes ; then
    AC_DEFINE([HAVE_SA_LEN_MACRO],1,
	    [Define if your system has a SA_LEN(s) macro])
fi])
INN_SA_LEN_MACRO

dnl Check to see how struct sockaddr_storage members are named.
dnl  *** Called from INN_SOCKADDR_STORAGE
AC_DEFUN([INN_2553_SS_FAMILY],
[AC_CACHE_CHECK(for RFC 2553 style sockaddr_storage member names,
		inn_cv_2553_ss_family,
		[AC_TRY_COMPILE(
			[#include <sys/types.h>
			#include <sys/socket.h>
			#include <netinet/in.h>],
			[struct sockaddr_storage ss; int x=ss.ss_family;],
			[inn_cv_2553_ss_family=no],
			[inn_cv_2553_ss_family=yes])])
if test "$inn_cv_2553_ss_family" = yes ; then
    AC_DEFINE([HAVE_2553_STYLE_SS_FAMILY],1,
	[Define if your system has sockaddr_storage.__ss_family])
fi])

dnl Check whether we have struct sockaddr_storage as defined by RFC 2553,
dnl or whether we should define it ourselves.
AC_DEFUN([INN_SOCKADDR_STORAGE],
[AC_CACHE_CHECK(for struct sockaddr_storage, inn_cv_struct_sockaddr_storage,
		[AC_TRY_COMPILE(
			[#include <sys/types.h>
			#include <sys/socket.h>
			#include <netinet/in.h>],
			[struct sockaddr_storage ss;],
			[inn_cv_struct_sockaddr_storage=yes],
			[inn_cv_struct_sockaddr_storage=no])])
if test "$inn_cv_struct_sockaddr_storage" = yes ; then
    AC_DEFINE([HAVE_SOCKADDR_STORAGE],1,
	[Define if your system has struct sockaddr_storage])
    INN_2553_SS_FAMILY
fi])
INN_SOCKADDR_STORAGE

dnl Source used by INN_IN6_EQ_BROKEN
dnl Test borrowed from a bug report by tmoestl@gmx.net for glibc
define([_INN_IN6_EQ_BROKEN_SOURCE],
[#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int
main ()
{
  struct in6_addr a;
  struct in6_addr b;

  inet_pton(AF_INET6,"fe80::1234:5678:abcd",&a);
  inet_pton(AF_INET6,"fe80::1234:5678:abcd",&b);
  return IN6_ARE_ADDR_EQUAL(&a,&b) ? 0 : 1;
}])

dnl Checks whether IN6_ARE_ADDR_EQUAL macro is broken (glibc 2.1.3 is)
dnl *** only run if we're building for IPv6 (--enable-ipv6)
AC_DEFUN([INN_IN6_EQ_BROKEN],
[AC_CACHE_CHECK(whether IN6_ARE_ADDR_EQUAL macro is broken,
		inn_cv_in6_are_addr_equal_broken,
		[AC_TRY_RUN(_INN_IN6_EQ_BROKEN_SOURCE,
			inn_cv_in6_are_addr_equal_broken=no,
			inn_cv_in6_are_addr_equal_broken=yes,
			inn_cv_in6_are_addr_equal_broken=no)])
if test "$inn_cv_in6_are_addr_equal_broken" = yes ; then
    AC_DEFINE([HAVE_BROKEN_IN6_ARE_ADDR_EQUAL],1,
	[Define if your IN6_ARE_ADDR_EQUAL macro is broken])
fi])
if test "$inn_enable_ipv6_tests" = yes ; then
    INN_IN6_EQ_BROKEN
fi

dnl Source used by INN_FUNC_SNPRINTF.
define([_INN_FUNC_SNPRINTF_SOURCE],
[[#include <stdio.h>
#include <stdarg.h>

char buf[2];

int
test (char *format, ...)
{
  va_list args;
  int count;

  va_start (args, format);
  count = vsnprintf (buf, sizeof buf, format, args);
  va_end (args);
  return count;
}

int
main ()
{
  return ((test ("%s", "abcd") == 4 && buf[0] == 'a' && buf[1] == '\0'
           && snprintf(NULL, 0, "%s", "abcd") == 4) ? 0 : 1);
}]])

dnl Check for a working snprintf.  Some systems have snprintf, but it doesn't
dnl null-terminate if the buffer isn't large enough or it returns -1 if the
dnl string doesn't fit instead of returning the number of characters that
dnl would have been formatted.
AC_DEFUN([INN_FUNC_SNPRINTF],
[AC_CACHE_CHECK(for working snprintf, inn_cv_func_snprintf_works,
[AC_TRY_RUN(_INN_FUNC_SNPRINTF_SOURCE(),
            [inn_cv_func_snprintf_works=yes],
            [inn_cv_func_snprintf_works=no],
            [inn_cv_func_snprintf_works=no])])
if test "$inn_cv_func_snprintf_works" = yes ; then
    AC_DEFINE([HAVE_SNPRINTF], 1,
        [Define if your system has a working snprintf function.])
else
    LIBOBJS="$LIBOBJS snprintf.${ac_objext}"
fi])
INN_FUNC_SNPRINTF

dnl Check for various other functions.
AC_CHECK_FUNCS(atexit getloadavg getrlimit getrusage getspnam setbuffer \
               sigaction setgroups setrlimit setsid socketpair statvfs \
               strncasecmp strtoul symlink sysconf)

dnl Find a way to get the file descriptor limit.
if test x"$ac_cv_func_getrlimit" = xno ; then
    AC_CHECK_FUNCS(getdtablesize ulimit, break)
fi

dnl If we don't have statvfs, gather some more information for inndf.
if test x"$ac_cv_func_statvfs" = xno ; then
    AC_CHECK_FUNCS(statfs)
    AC_CHECK_HEADERS(sys/vfs.h sys/mount.h)
fi

dnl If we can't find any of the following, we have replacements for them.
AC_REPLACE_FUNCS(fseeko ftello getaddrinfo getpagesize hstrerror inet_aton \
                 mkstemp pread pwrite seteuid strcasecmp strerror strlcat \
                 strlcpy strspn setenv)

dnl Source used by INN_TYPE_FPOS_T_LARGE.
define([_INN_TYPE_FPOS_T_LARGE_SOURCE],
[#include <stdio.h>
#include <sys/types.h>

int
main ()
{
  fpos_t fpos = 9223372036854775807ULL;
  off_t off;
  off = fpos;
  exit(off == (off_t) 9223372036854775807ULL ? 0 : 1);
}])

dnl Check whether fpos_t is 64 bits and can be assigned to an off_t.  If so,
dnl sets HAVE_LARGE_FPOS_T; this means that a missing fseeko or ftello can be
dnl emulated usint fgetpos and fsetpos.
AC_DEFUN([INN_TYPE_FPOS_T_LARGE],
[AC_CACHE_CHECK(for off_t-compatible fpos_t, inn_cv_type_fpos_t_large,
[AC_TRY_RUN(_INN_TYPE_FPOS_T_LARGE_SOURCE(),
            [inn_cv_type_fpos_t_large=yes],
            [inn_cv_type_fpos_t_large=no],
            [inn_cv_type_fpos_t_large=no])
if test "$inn_cv_type_fpos_t_large" = yes ; then
    AC_DEFINE([HAVE_LARGE_FPOS_T], 1,
        [Define if fpos_t is at least 64 bits and compatible with off_t.])
fi])])

dnl If replacing fseeko or ftello, see if we can use fsetpos/fgetpos.
if test "$ac_cv_func_fseeko" = no || test "$ac_cv_func_ftello" = no ; then
   INN_TYPE_FPOS_T_LARGE
fi

dnl Source used by INN_FUNC_MMAP.
define([_INN_FUNC_MMAP_SOURCE],
[_INN_HEADER_SOURCE()]
[[#include <fcntl.h>
#include <sys/mman.h>

int
main()
{
  int *data, *data2;
  int i, fd;

  /* First, make a file with some known garbage in it.  Use something
     larger than one page but still an odd page size. */
  data = malloc (20000);
  if (!data) return 1;
  for (i = 0; i < 20000 / sizeof (int); i++)
    data[i] = rand();
  umask (0);
  fd = creat ("conftestmmaps", 0600);
  if (fd < 0) return 1;
  if (write (fd, data, 20000) != 20000) return 1;
  close (fd);

  /* Next, try to mmap the file and make sure we see the same garbage. */
  fd = open ("conftestmmaps", O_RDWR);
  if (fd < 0) return 1;
  data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (data2 == (int *) -1) return 1;
  for (i = 0; i < 20000 / sizeof (int); i++)
    if (data[i] != data2[i])
      return 1;

  close (fd);
  unlink ("conftestmmaps");
  return 0;
}]])


dnl This portion is similar to what AC_FUNC_MMAP does, only it tests shared,
dnl non-fixed mmaps.
AC_DEFUN([INN_FUNC_MMAP],
[AC_CACHE_CHECK(for working mmap, inn_cv_func_mmap,
[AC_TRY_RUN(_INN_FUNC_MMAP_SOURCE(),
            inn_cv_func_mmap=yes,
            inn_cv_func_mmap=no,
            inn_cv_func_mmap=no)])
if test $inn_cv_func_mmap = yes ; then
    AC_DEFINE(HAVE_MMAP)
fi])

dnl Source used by INN_FUNC_MMAP_NEEDS_MSYNC.
define([_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE],
[_INN_HEADER_SOURCE()]
[[#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

int
main()
{
  int *data, *data2;
  int i, fd;

  /* First, make a file with some known garbage in it.  Use something
     larger than one page but still an odd page size. */
  data = malloc (20000);
  if (!data) return 1;
  for (i = 0; i < 20000 / sizeof (int); i++)
    data[i] = rand();
  umask (0);
  fd = creat ("conftestmmaps", 0600);
  if (fd < 0) return 1;
  if (write (fd, data, 20000) != 20000) return 1;
  close (fd);

  /* Next, try to mmap the file and make sure we see the same garbage. */
  fd = open ("conftestmmaps", O_RDWR);
  if (fd < 0) return 1;
  data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (data2 == (int *) -1) return 1;

  /* Finally, see if changes made to the mmaped region propagate back to
     the file as seen by read (meaning that msync isn't needed). */
  for (i = 0; i < 20000 / sizeof (int); i++)
    data2[i]++;
  if (read (fd, data, 20000) != 20000) return 1;
  for (i = 0; i < 20000 / sizeof (int); i++)
    if (data[i] != data2[i])
      return 1;

  close (fd);
  unlink ("conftestmmapm");
  return 0;
}]])

dnl Check whether the data read from an open file sees the changes made to an
dnl mmaped region, or if msync has to be called for other applications to see
dnl those changes.
AC_DEFUN([INN_FUNC_MMAP_NEEDS_MSYNC],
[AC_CACHE_CHECK(whether msync is needed, inn_cv_func_mmap_need_msync,
[AC_TRY_RUN(_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE(),
            inn_cv_func_mmap_need_msync=no,
            inn_cv_func_mmap_need_msync=yes,
            inn_cv_func_mmap_need_msync=yes)])
if test $inn_cv_func_mmap_need_msync = yes ; then
    AC_DEFINE(MMAP_NEEDS_MSYNC, 1,
       [Define if you need to call msync for calls to read to see changes.])
fi])

dnl Source used by INN_FUNC_MMAP_SEES_WRITES.
define([_INN_FUNC_MMAP_SEES_WRITES_SOURCE],
[[#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <sys/mman.h>

/* Fractional page is probably worst case. */
static char zbuff[1024];
static char fname[] = "conftestw";

int
main ()
{
  char *map;
  int i, fd;

  fd = open (fname, O_RDWR | O_CREAT, 0660);
  if (fd < 0) return 1;
  unlink (fname);
  write (fd, zbuff, sizeof (zbuff));
  lseek (fd, 0, SEEK_SET);
  map = mmap (0, sizeof (zbuff), PROT_READ, MAP_SHARED, fd, 0);
  if (map == (char *) -1) return 2;
  for (i = 0; fname[i]; i++)
    {
      if (write (fd, &fname[i], 1) != 1) return 3;
      if (map[i] != fname[i]) return 4;
    }
  return 0;
}]])

dnl Check if an mmaped region will see writes made to the underlying file
dnl without an intervening msync.
AC_DEFUN([INN_FUNC_MMAP_SEES_WRITES],
[AC_CACHE_CHECK(whether mmap sees writes, inn_cv_func_mmap_sees_writes,
[AC_TRY_RUN(_INN_FUNC_MMAP_SEES_WRITES_SOURCE(),
            inn_cv_func_mmap_sees_writes=yes,
            inn_cv_func_mmap_sees_writes=no,
            inn_cv_func_mmap_sees_writes=no)])
if test $inn_cv_func_mmap_sees_writes = no ; then
    AC_DEFINE(MMAP_MISSES_WRITES, 1,
              [Define if you need to call msync after writes.])
fi])

dnl Check whether msync takes three arguments.  (It takes three arguments on
dnl Solaris and Linux, two arguments on BSDI.)
AC_DEFUN([INN_FUNC_MSYNC_ARGS],
[AC_CACHE_CHECK(how many arguments msync takes, inn_cv_func_msync_args,
[AC_TRY_COMPILE(
[#include <sys/types.h>
#include <sys/mman.h>],
                [char *p; int psize; msync (p, psize, MS_ASYNC);],
                inn_cv_func_msync_args=3,
                inn_cv_func_msync_args=2)])
if test $inn_cv_func_msync_args = 3 ; then
    AC_DEFINE(HAVE_MSYNC_3_ARG, 1,
              [Define if your msync function takes three arguments.])
fi])

dnl Now that all the tests are set up, do the work of the mmap tests.
INN_FUNC_MMAP
if test x"$inn_cv_func_mmap" = xyes ; then
    AC_CHECK_FUNCS(madvise)
    INN_FUNC_MMAP_SEES_WRITES
    INN_FUNC_MMAP_NEEDS_MSYNC
    INN_FUNC_MSYNC_ARGS
fi

dnl If AF_UNIX is set in <sys/socket.h>, assume we have Unix domain sockets.
AC_DEFUN([INN_SYS_UNIX_SOCKETS],
[AC_CACHE_CHECK([for Unix domain sockets], inn_cv_sys_unix_sockets,
[AC_EGREP_CPP(yes,
[#include <sys/socket.h>
#ifdef AF_UNIX
yes
#endif],
              inn_cv_sys_unix_sockets=yes,
              inn_cv_sys_unix_sockets=no)])
if test $inn_cv_sys_unix_sockets = yes ; then
    AC_DEFINE(HAVE_UNIX_DOMAIN_SOCKETS, 1,
              [Define if you have unix domain sockets.])
fi])
INN_SYS_UNIX_SOCKETS

dnl Determine the facility for syslog messages.  Default to LOG_NEWS for
dnl syslog facility if it's available, but if it's not, fall back on
dnl LOG_LOCAL1.  --with-syslog-facility may have already set this.
AC_DEFUN([INN_LOG_FACILITY],
[AC_MSG_CHECKING(log facility for news)
AC_CACHE_VAL(inn_cv_log_facility,
[AC_EGREP_CPP(yes,
[#include <syslog.h>
#ifdef LOG_NEWS
yes
#endif],
              inn_cv_log_facility=LOG_NEWS,
              inn_cv_log_facility=LOG_LOCAL1)])
if test x"$SYSLOG_FACILITY" = xnone ; then
    SYSLOG_FACILITY=$inn_cv_log_facility
fi
AC_MSG_RESULT($SYSLOG_FACILITY)
AC_DEFINE_UNQUOTED(LOG_INN_SERVER, $SYSLOG_FACILITY,
                   [Syslog facility to use for innd logs.])
AC_DEFINE_UNQUOTED(LOG_INN_PROG, $SYSLOG_FACILITY,
                   [Syslog facility to use for INN program logs.])
AC_SUBST(SYSLOG_FACILITY)])
INN_LOG_FACILITY

dnl Clean up our LIBS, just for grins.
LIBS=`echo "$LIBS" | sed 's/^  *//' | sed 's/   */ /g' | sed 's/  *$//'`

AC_CONFIG_HEADER(include/config.h)
AC_OUTPUT(
        Makefile.global
        include/paths.h
        samples/inn.conf
        samples/innreport.conf
        samples/newsfeeds
        samples/sasl.conf
        scripts/inncheck
        scripts/innshellvars
        scripts/innshellvars.pl
        scripts/innshellvars.tcl
        scripts/news.daily
        support/fixscript
        ,
        chmod +x support/fixscript
)

dnl Print out some additional information on what to check.
cat <<EOM

Please check the following files before running make, to ensure that 
everything was set correctly.

	Makefile.global
	include/config.h
	include/paths.h
	innfeed/innfeed.h

EOM

dnl Finally, double-check the configured temporary directory.  Some people
dnl point this at the system temporary directories or at other world-writeable
dnl directories, which can be a local security hole.
if $_PATH_PERL -e "exit((stat('$tmpdir'))[[2]] & 2)" > /dev/null ; then
    :
else
    cat <<EOM

WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING

  The temporary directory you have configured is world-writeable.  It is
  currently set to $tmpdir.

  This directory is used by INN for temporary files and should only be
  writeable by the news user.  INN does not go to great lengths to prevent
  symlink attacks and the like because it assumes this directory is not
  world-writeable.  By configuring INN in this fashion, you may be
  introducing a locally exploitable security hole.

  It is STRONGLY recommended that you use a temporary directory reserved for
  INN's exclusive use, one which is not world-writeable.  You can do this
  either with --with-tmp-dir or by setting --prefix to something other than
  /usr or /.

EOM
fi
