diff --git a/configure.ac b/configure.ac index 5938caa1..f311764b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,527 +1,533 @@ # # Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+ # # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # AC_PREREQ([2.63]) AC_INIT([kronosnet], m4_esyscmd([build-aux/git-version-gen .tarball-version .gitarchivever]), [devel@lists.kronosnet.org]) # Don't let AC_PROC_CC (invoked by AC_USE_SYSTEM_EXTENSIONS) replace # undefined CFLAGS with -g -O2, overriding our special OPT_CFLAGS. : ${CFLAGS=""} AC_USE_SYSTEM_EXTENSIONS AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-xz color-tests -Wno-portability subdir-objects]) LT_PREREQ([2.2.6]) # --enable-new-dtags: Use RUNPATH instead of RPATH. # It is necessary to have this done before libtool does linker detection. # See also: https://github.com/kronosnet/kronosnet/issues/107 # --as-needed: Modern systems have builtin ceil() making -lm superfluous but # AC_SEARCH_LIBS can't detect this because it tests with a false prototype AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags], [AM_LDFLAGS=-Wl,--enable-new-dtags], [AC_MSG_ERROR(["Linker support for --enable-new-dtags is required"])]) AX_CHECK_LINK_FLAG([-Wl,--as-needed], [AM_LDFLAGS="$AM_LDFLAGS -Wl,--as-needed"]) AC_SUBST([AM_LDFLAGS]) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$AM_LDFLAGS $LDFLAGS" LT_INIT LDFLAGS="$saved_LDFLAGS" AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([kronosnetd/main.c]) AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST AC_LANG([C]) systemddir=${prefix}/lib/systemd/system if test "$prefix" = "NONE"; then prefix="/usr" if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi if test "$systemddir" = "NONE/lib/systemd/system"; then systemddir=/lib/systemd/system fi if test "$libdir" = "\${exec_prefix}/lib"; then if test -e /usr/lib64; then libdir="/usr/lib64" else libdir="/usr/lib" fi fi fi AC_PROG_AWK AC_PROG_GREP AC_PROG_SED AC_PROG_CPP AC_PROG_CC AC_PROG_CC_C99 if test "x$ac_cv_prog_cc_c99" = "xno"; then AC_MSG_ERROR(["C99 support is required"]) fi AC_PROG_LN_S AC_PROG_INSTALL AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG AC_CHECK_PROGS([VALGRIND_EXEC], [valgrind]) AM_CONDITIONAL([HAS_VALGRIND], [test x$VALGRIND_EXEC != "x"]) AC_CHECK_PROGS([COVBUILD_EXEC], [cov-build]) AM_CONDITIONAL([HAS_COVBUILD], [test x$COVBUILD_EXEC != "x"]) AC_CHECK_PROGS([COVANALYZE_EXEC], [cov-analyze]) AM_CONDITIONAL([HAS_COVANALYZE], [test x$COVANALYZE_EXEC != "x"]) AC_CHECK_PROGS([COVFORMATERRORS_EXEC], [cov-format-errors]) AM_CONDITIONAL([HAS_COVFORMATERRORS], [test x$COVFORMATERRORS_EXEC != "x"]) # KNET_OPTION_DEFINES(stem,type,detection code) # stem: enters name of option, Automake conditional and preprocessor define # type: compress or crypto, determines where the default comes from AC_DEFUN([KNET_OPTION_DEFINES],[ AC_ARG_ENABLE([$2-$1],[AS_HELP_STRING([--disable-$2-$1],[disable libknet $1 support])],, [enable_$2_$1="$enable_$2_all"]) AM_CONDITIONAL([BUILD_]m4_toupper([$2_$1]),[test "x$enable_$2_$1" = xyes]) if test "x$enable_$2_$1" = xyes; then $3 fi AC_DEFINE_UNQUOTED([WITH_]m4_toupper([$2_$1]), [`test "x$enable_$2_$1" != xyes; echo $?`], $1 $2 [built in]) ]) AC_ARG_ENABLE([man], [AS_HELP_STRING([--disable-man],[disable man page creation])],, [ enable_man="yes" ]) AM_CONDITIONAL([BUILD_MAN], [test x$enable_man = xyes]) AC_ARG_ENABLE([libknet-sctp], [AS_HELP_STRING([--disable-libknet-sctp],[disable libknet SCTP support])],, [ enable_libknet_sctp="yes" ]) AM_CONDITIONAL([BUILD_SCTP], [test x$enable_libknet_sctp = xyes]) AC_ARG_ENABLE([crypto-all], [AS_HELP_STRING([--disable-crypto-all],[disable libknet all crypto modules support])],, [ enable_crypto_all="yes" ]) KNET_OPTION_DEFINES([nss],[crypto],[PKG_CHECK_MODULES([nss], [nss])]) KNET_OPTION_DEFINES([openssl],[crypto],[PKG_CHECK_MODULES([openssl],[libcrypto])]) AC_ARG_ENABLE([compress-all], [AS_HELP_STRING([--disable-compress-all],[disable libknet all compress modules support])],, [ enable_compress_all="yes" ]) KNET_OPTION_DEFINES([zstd],[compress],[PKG_CHECK_MODULES([libzstd], [libzstd])]) KNET_OPTION_DEFINES([zlib],[compress],[PKG_CHECK_MODULES([zlib], [zlib])]) KNET_OPTION_DEFINES([lz4],[compress],[PKG_CHECK_MODULES([liblz4], [liblz4])]) KNET_OPTION_DEFINES([lzo2],[compress],[ PKG_CHECK_MODULES([lzo2], [lzo2], [# work around broken pkg-config file in v2.10 AC_SUBST([lzo2_CFLAGS],[`echo $lzo2_CFLAGS | sed 's,/lzo *, ,'`])], [AC_CHECK_HEADERS([lzo/lzo1x.h], [AC_CHECK_LIB([lzo2], [lzo1x_decompress_safe], [AC_SUBST([lzo2_LIBS], [-llzo2])])], [AC_MSG_ERROR(["missing required lzo/lzo1x.h header"])])]) ]) KNET_OPTION_DEFINES([lzma],[compress],[PKG_CHECK_MODULES([liblzma], [liblzma])]) KNET_OPTION_DEFINES([bzip2],[compress],[ PKG_CHECK_MODULES([bzip2], [bzip2],, [AC_CHECK_HEADERS([bzlib.h], [AC_CHECK_LIB([bz2], [BZ2_bzBuffToBuffCompress], [AC_SUBST([bzip2_LIBS], [-lbz2])])], [AC_MSG_ERROR(["missing required bzlib.h"])])]) ]) AC_ARG_ENABLE([install-tests], [AS_HELP_STRING([--enable-install-tests],[install tests])],, [ enable_install_tests="no" ]) AM_CONDITIONAL([INSTALL_TESTS], [test x$enable_install_tests = xyes]) AC_ARG_ENABLE([poc], [AS_HELP_STRING([--enable-poc],[enable building poc code])],, [ enable_poc="no" ]) AM_CONDITIONAL([BUILD_POC], [test x$enable_poc = xyes]) AC_ARG_ENABLE([kronosnetd], [AS_HELP_STRING([--enable-kronosnetd],[Kronosnetd support])],, [ enable_kronosnetd="no" ]) AM_CONDITIONAL([BUILD_KRONOSNETD], [test x$enable_kronosnetd = xyes]) AC_ARG_ENABLE([runautogen], [AS_HELP_STRING([--enable-runautogen],[run autogen.sh])],, [ enable_runautogen="no" ]) AM_CONDITIONAL([BUILD_RUNAUTOGEN], [test x$enable_runautogen = xyes]) override_rpm_debuginfo_option="yes" AC_ARG_ENABLE([rpm-debuginfo], [AS_HELP_STRING([--enable-rpm-debuginfo],[build debuginfo packages])],, [ enable_rpm_debuginfo="no", override_rpm_debuginfo_option="no" ]) AM_CONDITIONAL([BUILD_RPM_DEBUGINFO], [test x$enable_rpm_debuginfo = xyes]) AM_CONDITIONAL([OVERRIDE_RPM_DEBUGINFO], [test x$override_rpm_debuginfo_option = xyes]) AC_ARG_ENABLE([libnozzle], [AS_HELP_STRING([--enable-libnozzle],[libnozzle support])],, [ enable_libnozzle="yes" ]) if test "x$enable_kronosnetd" = xyes; then enable_libnozzle=yes fi AM_CONDITIONAL([BUILD_LIBNOZZLE], [test x$enable_libnozzle = xyes]) # Checks for libraries. AX_PTHREAD(,[AC_MSG_ERROR([POSIX threads support is required])]) saved_LIBS="$LIBS" LIBS= AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])]) AC_SUBST([m_LIBS], [$LIBS]) LIBS= AC_SEARCH_LIBS([clock_gettime], [rt], , [AC_MSG_ERROR([clock_gettime not found])]) AC_SUBST([rt_LIBS], [$LIBS]) LIBS= AC_SEARCH_LIBS([dlopen], [dl dld], , [AC_MSG_ERROR([dlopen not found])]) AC_SUBST([dl_LIBS], [$LIBS]) LIBS="$saved_LIBS" # Check RTLD_DI_ORIGIN (not decalred by musl. glibc has it as an enum so cannot use ifdef) AC_CHECK_DECL([RTLD_DI_ORIGIN], [AC_DEFINE([HAVE_RTLD_DI_ORIGIN], 1, [define when RTLD_DI_ORIGIN is declared])], ,[[#include ]]) # OS detection AC_MSG_CHECKING([for os in ${host_os}]) case "$host_os" in *linux*) AC_DEFINE_UNQUOTED([KNET_LINUX], [1], [Compiling for Linux platform]) AC_MSG_RESULT([Linux]) ;; *bsd*) AC_DEFINE_UNQUOTED([KNET_BSD], [1], [Compiling for BSD platform]) AC_MSG_RESULT([BSD]) ;; *) AC_MSG_ERROR([Unsupported OS? hmmmm]) ;; esac # Checks for header files. AC_CHECK_HEADERS([sys/epoll.h]) AC_CHECK_FUNCS([kevent]) # if neither sys/epoll.h nor kevent are present, we should fail. if test "x$ac_cv_header_sys_epoll_h" = xno && test "x$ac_cv_func_kevent" = xno; then AC_MSG_ERROR([Both epoll and kevent unavailable on this OS]) fi if test "x$ac_cv_header_sys_epoll_h" = xyes && test "x$ac_cv_func_kevent" = xyes; then AC_MSG_ERROR([Both epoll and kevent available on this OS, please contact the maintainers to fix the code]) fi if test "x$enable_libknet_sctp" = xyes; then AC_CHECK_HEADERS([netinet/sctp.h],, [AC_MSG_ERROR(["missing required SCTP headers"])]) fi # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT8_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_INT8_T AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T +PKG_CHECK_MODULES([libqb], [libqb]) + if test "x$enable_man" = "xyes"; then AC_ARG_VAR([DOXYGEN], [override doxygen executable]) AC_CHECK_PROGS([DOXYGEN], [doxygen], [no]) if test "x$DOXYGEN" = xno; then AC_MSG_ERROR(["Doxygen command not found"]) fi - # required by doxyxml to build man pages dynamically - # Don't let AC_PROC_CC (invoked by AX_PROG_CC_FOR_BUILD) replace - # undefined CFLAGS_FOR_BUILD with -g -O2, overriding our special OPT_CFLAGS. - : ${CFLAGS_FOR_BUILD=""} - AX_PROG_CC_FOR_BUILD + + AC_ARG_VAR([DOXYGEN2MAN], [override doxygen2man executable]) + + # required to detect doxygen2man when libqb is installed + # in non standard paths saved_PKG_CONFIG="$PKG_CONFIG" saved_ac_cv_path_PKG_CONFIG="$ac_cv_path_PKG_CONFIG" unset PKG_CONFIG ac_cv_path_PKG_CONFIG AC_PATH_PROG([PKG_CONFIG], [pkg-config]) PKG_CHECK_MODULES([libqb_BUILD], [libqb]) - PKG_CHECK_MODULES([libxml_BUILD], [libxml-2.0]) + PKG_CHECK_VAR([libqb_BUILD_PREFIX], [libqb], [prefix]) + AC_PATH_PROG([DOXYGEN2MAN], [doxygen2man], [no], [$libqb_BUILD_PREFIX/bin$PATH_SEPARATOR$PATH]) PKG_CONFIG="$saved_PKG_CONFIG" ac_cv_path_PKG_CONFIG="$saved_ac_cv_path_PKG_CONFIG" -fi -PKG_CHECK_MODULES([libqb], [libqb]) + if test "x$DOXYGEN2MAN" = "xno"; then + AC_MSG_ERROR(["doxygen2man command not found"]) + fi + AC_SUBST([DOXYGEN2MAN]) +fi # checks for libnozzle if test "x$enable_libnozzle" = xyes; then if `echo $host_os | grep -q linux`; then PKG_CHECK_MODULES([libnl], [libnl-3.0]) PKG_CHECK_MODULES([libnlroute], [libnl-route-3.0 >= 3.3], [], [PKG_CHECK_MODULES([libnlroute], [libnl-route-3.0 < 3.3], [AC_DEFINE_UNQUOTED([LIBNL3_WORKAROUND], [1], [Enable libnl < 3.3 build workaround])], [])]) fi fi # checks for kronosnetd if test "x$enable_kronosnetd" = xyes; then AC_CHECK_HEADERS([security/pam_appl.h], [AC_CHECK_LIB([pam], [pam_start], [AC_SUBST([pam_LIBS], [-lpam])], [AC_MSG_ERROR([Unable to find LinuxPAM devel files])])]) AC_CHECK_HEADERS([security/pam_misc.h], [AC_CHECK_LIB([pam_misc], [misc_conv], [AC_SUBST([pam_misc_LIBS], [-lpam_misc])], [AC_MSG_ERROR([Unable to find LinuxPAM MISC devel files])])]) AC_CHECK_LIB([qb], [qb_log_thread_priority_set], [have_qb_log_thread_priority_set="yes"], [have_qb_log_thread_priority_set="no"]) if test "x${have_qb_log_thread_priority_set}" = xyes; then AC_DEFINE_UNQUOTED([HAVE_QB_LOG_THREAD_PRIORITY_SET], [1], [have qb_log_thread_priority_set]) fi fi # local options AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug],[enable debug build])]) AC_ARG_WITH([sanitizers], [AS_HELP_STRING([--with-sanitizers=...,...], [enable SANitizer build, do *NOT* use for production. Only ASAN/UBSAN/TSAN are currently supported])], [ SANITIZERS="$withval" ], [ SANITIZERS="" ]) AC_ARG_WITH([testdir], [AS_HELP_STRING([--with-testdir=DIR],[path to /usr/lib../kronosnet/tests/ dir where to install the test suite])], [ TESTDIR="$withval" ], [ TESTDIR="$libdir/kronosnet/tests" ]) AC_ARG_WITH([initdefaultdir], [AS_HELP_STRING([--with-initdefaultdir=DIR],[path to /etc/sysconfig or /etc/default dir])], [ INITDEFAULTDIR="$withval" ], [ INITDEFAULTDIR="$sysconfdir/default" ]) AC_ARG_WITH([initddir], [AS_HELP_STRING([--with-initddir=DIR],[path to init script directory])], [ INITDDIR="$withval" ], [ INITDDIR="$sysconfdir/init.d" ]) AC_ARG_WITH([systemddir], [AS_HELP_STRING([--with-systemddir=DIR],[path to systemd unit files directory])], [ SYSTEMDDIR="$withval" ], [ SYSTEMDDIR="$systemddir" ]) AC_ARG_WITH([syslogfacility], [AS_HELP_STRING([--with-syslogfacility=FACILITY],[default syslog facility])], [ SYSLOGFACILITY="$withval" ], [ SYSLOGFACILITY="LOG_DAEMON" ]) AC_ARG_WITH([sysloglevel], [AS_HELP_STRING([--with-sysloglevel=LEVEL],[default syslog level])], [ SYSLOGLEVEL="$withval" ], [ SYSLOGLEVEL="LOG_INFO" ]) AC_ARG_WITH([defaultadmgroup], [AS_HELP_STRING([--with-defaultadmgroup=GROUP], [define PAM group. Users part of this group will be allowed to configure kronosnet. Others will only receive read-only rights.])], [ DEFAULTADMGROUP="$withval" ], [ DEFAULTADMGROUP="kronosnetadm" ]) ## random vars LOGDIR=${localstatedir}/log/ RUNDIR=${localstatedir}/run/ DEFAULT_CONFIG_DIR=${sysconfdir}/kronosnet ## do subst AC_SUBST([TESTDIR]) AC_SUBST([DEFAULT_CONFIG_DIR]) AC_SUBST([INITDEFAULTDIR]) AC_SUBST([INITDDIR]) AC_SUBST([SYSTEMDDIR]) AC_SUBST([LOGDIR]) AC_SUBST([DEFAULTADMGROUP]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_DIR], ["$(eval echo ${DEFAULT_CONFIG_DIR})"], [Default config directory]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_FILE], ["$(eval echo ${DEFAULT_CONFIG_DIR}/kronosnetd.conf)"], [Default config file]) AC_DEFINE_UNQUOTED([LOGDIR], ["$(eval echo ${LOGDIR})"], [Default logging directory]) AC_DEFINE_UNQUOTED([DEFAULT_LOG_FILE], ["$(eval echo ${LOGDIR}/kronosnetd.log)"], [Default log file]) AC_DEFINE_UNQUOTED([RUNDIR], ["$(eval echo ${RUNDIR})"], [Default run directory]) AC_DEFINE_UNQUOTED([SYSLOGFACILITY], [$(eval echo ${SYSLOGFACILITY})], [Default syslog facility]) AC_DEFINE_UNQUOTED([SYSLOGLEVEL], [$(eval echo ${SYSLOGLEVEL})], [Default syslog level]) AC_DEFINE_UNQUOTED([DEFAULTADMGROUP], ["$(eval echo ${DEFAULTADMGROUP})"], [Default admin group]) # debug build stuff if test "x${enable_debug}" = xyes; then AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code]) OPT_CFLAGS="-O0" else OPT_CFLAGS="-O3" fi # gdb flags if test "x${GCC}" = xyes; then GDB_FLAGS="-ggdb3" else GDB_FLAGS="-g" fi # --- ASAN/UBSAN/TSAN (see man gcc) --- # when using SANitizers, we need to pass the -fsanitize.. # to both CFLAGS and LDFLAGS. The CFLAGS/LDFLAGS must be # specified as first in the list or there will be runtime # issues (for example user has to LD_PRELOAD asan for it to work # properly). if test -n "${SANITIZERS}"; then SANITIZERS=$(echo $SANITIZERS | sed -e 's/,/ /g') for SANITIZER in $SANITIZERS; do case $SANITIZER in asan|ASAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=address" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=address -lasan" AC_CHECK_LIB([asan],[main],,AC_MSG_ERROR([Unable to find libasan])) ;; ubsan|UBSAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=undefined" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=undefined -lubsan" AC_CHECK_LIB([ubsan],[main],,AC_MSG_ERROR([Unable to find libubsan])) ;; tsan|TSAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=thread" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=thread -ltsan" AC_CHECK_LIB([tsan],[main],,AC_MSG_ERROR([Unable to find libtsan])) ;; esac done fi DEFAULT_CFLAGS="-Werror -Wall -Wextra" # manual overrides # generates too much noise for stub APIs UNWANTED_CFLAGS="-Wno-unused-parameter" AC_SUBST([AM_CFLAGS],["$SANITIZERS_CFLAGS $OPT_CFLAGS $GDB_FLAGS $DEFAULT_CFLAGS $UNWANTED_CFLAGS"]) LDFLAGS="$SANITIZERS_LDFLAGS $LDFLAGS" AX_PROG_DATE AS_IF([test "$ax_cv_prog_date_gnu_date:$ax_cv_prog_date_gnu_utc" = yes:yes], [UTC_DATE_AT="date -u -d@"], [AS_IF([test "x$ax_cv_prog_date_bsd_date" = xyes], [UTC_DATE_AT="date -u -r"], [AC_MSG_ERROR([date utility unable to convert epoch to UTC])])]) AC_SUBST([UTC_DATE_AT]) AC_ARG_VAR([SOURCE_EPOCH],[last modification date of the source]) AC_MSG_NOTICE([trying to determine source epoch]) AC_MSG_CHECKING([for source epoch in \$SOURCE_EPOCH]) AS_IF([test -n "$SOURCE_EPOCH"], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch in source_epoch file]) AS_IF([test -e "$srcdir/source_epoch"], [read SOURCE_EPOCH <"$srcdir/source_epoch" AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch baked in by gitattributes export-subst]) SOURCE_EPOCH='$Format:%at$' # template for rewriting by git-archive AS_CASE([$SOURCE_EPOCH], [?Format:*], # was not rewritten [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch in \$SOURCE_DATE_EPOCH]) AS_IF([test "x$SOURCE_DATE_EPOCH" != x], [SOURCE_EPOCH="$SOURCE_DATE_EPOCH" AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([whether git log can provide a source epoch]) SOURCE_EPOCH=f${SOURCE_EPOCH#\$F} # convert into git log --pretty format SOURCE_EPOCH=$(cd "$srcdir" && git log -1 --pretty=${SOURCE_EPOCH%$} 2>/dev/null) AS_IF([test -n "$SOURCE_EPOCH"], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no, using current time and breaking reproducibility]) SOURCE_EPOCH=$(date +%s)])])], [AC_MSG_RESULT([yes])] )]) ]) AC_MSG_NOTICE([using source epoch $($UTC_DATE_AT$SOURCE_EPOCH +'%F %T %Z')]) AC_CONFIG_FILES([ Makefile init/Makefile libnozzle/Makefile libnozzle/libnozzle.pc libnozzle/tests/Makefile kronosnetd/Makefile kronosnetd/kronosnetd.logrotate libknet/Makefile libknet/libknet.pc libknet/tests/Makefile man/Makefile man/Doxyfile-knet man/Doxyfile-nozzle poc-code/Makefile poc-code/iov-hash/Makefile ]) if test "x$VERSION" = "xUNKNOWN"; then AC_MSG_ERROR([m4_text_wrap([ configure was unable to determine the source tree's current version. This generally happens when using git archive (or the github download button) generated tarball/zip file. In order to workaround this issue, either use git clone https://github.com/kronosnet/kronosnet.git or use an official release tarball, available at https://kronosnet.org/releases/. Alternatively you can add a compatible version in a .tarball-version file at the top of the source tree, wipe your autom4te.cache dir and generated configure, and rerun autogen.sh. ], [ ], [ ], [76])]) fi AC_OUTPUT diff --git a/kronosnet.spec.in b/kronosnet.spec.in index 6c0b6c5d..14343eee 100644 --- a/kronosnet.spec.in +++ b/kronosnet.spec.in @@ -1,512 +1,512 @@ ############################################################################### ############################################################################### ## ## Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. ## ## This copyrighted material is made available to anyone wishing to use, ## modify, copy, or redistribute it subject to the terms and conditions ## of the GNU General Public License v.2 or higher ## ############################################################################### ############################################################################### # keep around ready for later user %global alphatag @alphatag@ %global numcomm @numcomm@ %global dirty @dirty@ # set defaults from ./configure invokation %@sctp@ sctp %@nss@ nss %@openssl@ openssl %@zlib@ zlib %@lz4@ lz4 %@lzo2@ lzo2 %@lzma@ lzma %@bzip2@ bzip2 %@zstd@ zstd %@kronosnetd@ kronosnetd %@libnozzle@ libnozzle %@runautogen@ runautogen %@rpmdebuginfo@ rpmdebuginfo %@overriderpmdebuginfo@ overriderpmdebuginfo %@buildman@ buildman %@installtests@ installtests %if %{with overriderpmdebuginfo} %undefine _enable_debug_packages %endif # main (empty) package # http://www.rpm.org/max-rpm/s1-rpm-subpack-spec-file-changes.html Name: kronosnet Summary: Multipoint-to-Multipoint VPN daemon Version: @version@ Release: 1%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist} License: GPLv2+ and LGPLv2+ URL: https://kronosnet.org Source0: https://kronosnet.org/releases/%{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.gz # Build dependencies BuildRequires: gcc libqb-devel # required to build man pages %if %{with buildman} -BuildRequires: libxml2-devel doxygen +BuildRequires: doxygen doxygen2man %endif %if %{with sctp} BuildRequires: lksctp-tools-devel %endif %if %{with nss} %if 0%{?suse_version} BuildRequires: mozilla-nss-devel %else BuildRequires: nss-devel %endif %endif %if %{with openssl} %if 0%{?suse_version} BuildRequires: libopenssl-devel %else BuildRequires: openssl-devel %endif %endif %if %{with zlib} BuildRequires: zlib-devel %endif %if %{with lz4} %if 0%{?suse_version} BuildRequires: liblz4-devel %else BuildRequires: lz4-devel %endif %endif %if %{with lzo2} BuildRequires: lzo-devel %endif %if %{with lzma} BuildRequires: xz-devel %endif %if %{with bzip2} %if 0%{?suse_version} BuildRequires: libbz2-devel %else BuildRequires: bzip2-devel %endif %endif %if %{with zstd} BuildRequires: libzstd-devel %endif %if %{with kronosnetd} BuildRequires: pam-devel %endif %if %{with libnozzle} BuildRequires: libnl3-devel %endif %if %{with runautogen} BuildRequires: autoconf automake libtool %endif %prep %setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} %build %if %{with runautogen} ./autogen.sh %endif %{configure} \ %if %{with installtests} --enable-install-tests \ %else --disable-install-tests \ %endif %if %{with buildman} --enable-man \ %else --disable-man \ %endif %if %{with sctp} --enable-libknet-sctp \ %else --disable-libknet-sctp \ %endif %if %{with nss} --enable-crypto-nss \ %else --disable-crypto-nss \ %endif %if %{with openssl} --enable-crypto-openssl \ %else --disable-crypto-openssl \ %endif %if %{with zlib} --enable-compress-zlib \ %else --disable-compress-zlib \ %endif %if %{with lz4} --enable-compress-lz4 \ %else --disable-compress-lz4 \ %endif %if %{with lzo2} --enable-compress-lzo2 \ %else --disable-compress-lzo2 \ %endif %if %{with lzma} --enable-compress-lzma \ %else --disable-compress-lzma \ %endif %if %{with bzip2} --enable-compress-bzip2 \ %else --disable-compress-bzip2 \ %endif %if %{with zstd} --enable-compress-zstd \ %else --disable-compress-zstd \ %endif %if %{with kronosnetd} --enable-kronosnetd \ %else --disable-kronosnetd \ %endif %if %{with libnozzle} --enable-libnozzle \ %else --disable-libnozzle \ %endif --with-initdefaultdir=%{_sysconfdir}/sysconfig/ \ --with-systemddir=%{_unitdir} make %{_smp_mflags} %install rm -rf %{buildroot} make install DESTDIR=%{buildroot} # tree cleanup # remove static libraries find %{buildroot} -name "*.a" -exec rm {} \; # remove libtools leftovers find %{buildroot} -name "*.la" -exec rm {} \; # remove init scripts rm -rf %{buildroot}/etc/init.d # remove docs rm -rf %{buildroot}/usr/share/doc/kronosnet # main empty package %description The kronosnet source %if %{with kronosnetd} ## Runtime and subpackages section %package -n kronosnetd Summary: Multipoint-to-Multipoint VPN daemon License: GPLv2+ Requires(post): systemd-sysv Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units Requires(post): shadow-utils Requires(preun): shadow-utils Requires: pam, /etc/pam.d/passwd %description -n kronosnetd The kronosnet daemon is a bridge between kronosnet switching engine and kernel network tap devices, to create and administer a distributed LAN over multipoint-to-multipoint VPNs. The daemon does a poor attempt to provide a configure UI similar to other known network devices/tools (Cisco, quagga). Beside looking horrific, it allows runtime changes and reconfiguration of the kronosnet(s) without daemon reload or service disruption. %post -n kronosnetd %systemd_post kronosnetd.service getent group @defaultadmgroup@ >/dev/null || groupadd --force --system @defaultadmgroup@ %preun -n kronosnetd %systemd_preun kronosnetd.service %files -n kronosnetd %license COPYING.* COPYRIGHT %dir %{_sysconfdir}/kronosnet %dir %{_sysconfdir}/kronosnet/* %config(noreplace) %{_sysconfdir}/sysconfig/kronosnetd %config(noreplace) %{_sysconfdir}/pam.d/kronosnetd %config(noreplace) %{_sysconfdir}/logrotate.d/kronosnetd %{_unitdir}/kronosnetd.service %{_sbindir}/* %{_mandir}/man8/* %endif %if %{with libnozzle} %package -n libnozzle1 Summary: Simple userland wrapper around kernel tap devices License: LGPLv2+ %description -n libnozzle1 This is an over-engineered commodity library to manage a pool of tap devices and provides the basic pre-up.d/up.d/down.d/post-down.d infrastructure. %files -n libnozzle1 %license COPYING.* COPYRIGHT %{_libdir}/libnozzle.so.* %if 0%{?ldconfig_scriptlets} %ldconfig_scriptlets -n libnozzle1 %else %post -n libnozzle1 -p /sbin/ldconfig %postun -n libnozzle1 -p /sbin/ldconfig %endif %package -n libnozzle1-devel Summary: Simple userland wrapper around kernel tap devices (developer files) License: LGPLv2+ Requires: libnozzle1%{_isa} = %{version}-%{release} Requires: pkgconfig %description -n libnozzle1-devel This is an over-engineered commodity library to manage a pool of tap devices and provides the basic pre-up.d/up.d/down.d/post-down.d infrastructure. %files -n libnozzle1-devel %license COPYING.* COPYRIGHT %{_libdir}/libnozzle.so %{_includedir}/libnozzle.h %{_libdir}/pkgconfig/libnozzle.pc %if %{with buildman} %{_mandir}/man3/nozzle*.3.gz %endif %endif %package -n libknet1 Summary: Kronosnet core switching implementation License: LGPLv2+ %description -n libknet1 The whole kronosnet core is implemented in this library. Please refer to the not-yet-existing documentation for further information. %files -n libknet1 %license COPYING.* COPYRIGHT %{_libdir}/libknet.so.* %dir %{_libdir}/kronosnet %if 0%{?ldconfig_scriptlets} %ldconfig_scriptlets -n libknet1 %else %post -n libknet1 -p /sbin/ldconfig %postun -n libknet1 -p /sbin/ldconfig %endif %package -n libknet1-devel Summary: Kronosnet core switching implementation (developer files) License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} Requires: pkgconfig %description -n libknet1-devel The whole kronosnet core is implemented in this library. Please refer to the not-yet-existing documentation for further information. %files -n libknet1-devel %license COPYING.* COPYRIGHT %{_libdir}/libknet.so %{_includedir}/libknet.h %{_libdir}/pkgconfig/libknet.pc %if %{with buildman} %{_mandir}/man3/knet*.3.gz %endif %if %{with nss} %package -n libknet1-crypto-nss-plugin Summary: Provides libknet1 nss support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-crypto-nss-plugin Provides NSS crypto support for libknet1. %files -n libknet1-crypto-nss-plugin %{_libdir}/kronosnet/crypto_nss.so %endif %if %{with openssl} %package -n libknet1-crypto-openssl-plugin Summary: Provides libknet1 openssl support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-crypto-openssl-plugin Provides OpenSSL crypto support for libknet1. %files -n libknet1-crypto-openssl-plugin %{_libdir}/kronosnet/crypto_openssl.so %endif %if %{with zlib} %package -n libknet1-compress-zlib-plugin Summary: Provides libknet1 zlib support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-zlib-plugin Provides zlib compression support for libknet1. %files -n libknet1-compress-zlib-plugin %{_libdir}/kronosnet/compress_zlib.so %endif %if %{with lz4} %package -n libknet1-compress-lz4-plugin Summary: Provides libknet1 lz4 and lz4hc support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lz4-plugin Provides lz4 and lz4hc compression support for libknet1. %files -n libknet1-compress-lz4-plugin %{_libdir}/kronosnet/compress_lz4.so %{_libdir}/kronosnet/compress_lz4hc.so %endif %if %{with lzo2} %package -n libknet1-compress-lzo2-plugin Summary: Provides libknet1 lzo2 support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lzo2-plugin Provides lzo2 compression support for libknet1. %files -n libknet1-compress-lzo2-plugin %{_libdir}/kronosnet/compress_lzo2.so %endif %if %{with lzma} %package -n libknet1-compress-lzma-plugin Summary: Provides libknet1 lzma support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lzma-plugin Provides lzma compression support for libknet1. %files -n libknet1-compress-lzma-plugin %{_libdir}/kronosnet/compress_lzma.so %endif %if %{with bzip2} %package -n libknet1-compress-bzip2-plugin Summary: Provides libknet1 bzip2 support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-bzip2-plugin Provides bzip2 compression support for libknet1. %files -n libknet1-compress-bzip2-plugin %{_libdir}/kronosnet/compress_bzip2.so %endif %if %{with zstd} %package -n libknet1-compress-zstd-plugin Summary: Provides libknet1 zstd support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-zstd-plugin Provides zstd compression support for libknet1. %files -n libknet1-compress-zstd-plugin %{_libdir}/kronosnet/compress_zstd.so %endif %package -n libknet1-crypto-plugins-all Summary: Provides libknet1 crypto plugins meta package License: LGPLv2+ %if %{with nss} Requires: libknet1-crypto-nss-plugin%{_isa} = %{version}-%{release} %endif %if %{with openssl} Requires: libknet1-crypto-openssl-plugin%{_isa} = %{version}-%{release} %endif %description -n libknet1-crypto-plugins-all Provides meta package to install all of libknet1 crypto plugins %files -n libknet1-crypto-plugins-all %package -n libknet1-compress-plugins-all Summary: Provides libknet1 compress plugins meta package License: LGPLv2+ %if %{with zlib} Requires: libknet1-compress-zlib-plugin%{_isa} = %{version}-%{release} %endif %if %{with lz4} Requires: libknet1-compress-lz4-plugin%{_isa} = %{version}-%{release} %endif %if %{with lzo2} Requires: libknet1-compress-lzo2-plugin%{_isa} = %{version}-%{release} %endif %if %{with lzma} Requires: libknet1-compress-lzma-plugin%{_isa} = %{version}-%{release} %endif %if %{with bzip2} Requires: libknet1-compress-bzip2-plugin%{_isa} = %{version}-%{release} %endif %if %{with zstd} Requires: libknet1-compress-zstd-plugin%{_isa} = %{version}-%{release} %endif %description -n libknet1-compress-plugins-all Meta package to install all of libknet1 compress plugins %files -n libknet1-compress-plugins-all %package -n libknet1-plugins-all Summary: Provides libknet1 plugins meta package License: LGPLv2+ Requires: libknet1-compress-plugins-all%{_isa} = %{version}-%{release} Requires: libknet1-crypto-plugins-all%{_isa} = %{version}-%{release} %description -n libknet1-plugins-all Meta package to install all of libknet1 plugins %files -n libknet1-plugins-all %if %{with installtests} %package -n kronosnet-tests Summary: Provides kronosnet test suite License: GPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n kronosnet-tests This package contains all the libknet and libnozzle test suite. %files -n kronosnet-tests %{_libdir}/kronosnet/tests/* %endif %if %{with rpmdebuginfo} %debug_package %endif %changelog * @date@ Autotools generated version - @version@-1-@numcomm@.@alphatag@.@dirty@ - These aren't the droids you're looking for. diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4 deleted file mode 100644 index 12cb005a..00000000 --- a/m4/ax_prog_cc_for_build.m4 +++ /dev/null @@ -1,125 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_CC_FOR_BUILD -# -# DESCRIPTION -# -# This macro searches for a C compiler that generates native executables, -# that is a C compiler that surely is not a cross-compiler. This can be -# useful if you have to generate source code at compile-time like for -# example GCC does. -# -# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything -# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). -# The value of these variables can be overridden by the user by specifying -# a compiler with an environment variable (like you do for standard CC). -# -# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object -# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if -# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are -# substituted in the Makefile. -# -# LICENSE -# -# Copyright (c) 2008 Paolo Bonzini -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 9 - -AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) -AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_CPP])dnl -AC_REQUIRE([AC_EXEEXT])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl - -dnl Use the standard macros, but make them use other variable names -dnl -pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl -pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl -pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl -pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl -pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl -pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl -pushdef([ac_cv_objext], ac_cv_build_objext)dnl -pushdef([ac_exeext], ac_build_exeext)dnl -pushdef([ac_objext], ac_build_objext)dnl -pushdef([CC], CC_FOR_BUILD)dnl -pushdef([CPP], CPP_FOR_BUILD)dnl -pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl -pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl -pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl -pushdef([host], build)dnl -pushdef([host_alias], build_alias)dnl -pushdef([host_cpu], build_cpu)dnl -pushdef([host_vendor], build_vendor)dnl -pushdef([host_os], build_os)dnl -pushdef([ac_cv_host], ac_cv_build)dnl -pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl -pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl -pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl -pushdef([ac_cv_host_os], ac_cv_build_os)dnl -pushdef([ac_cpp], ac_build_cpp)dnl -pushdef([ac_compile], ac_build_compile)dnl -pushdef([ac_link], ac_build_link)dnl - -save_cross_compiling=$cross_compiling -save_ac_tool_prefix=$ac_tool_prefix -cross_compiling=no -ac_tool_prefix= - -AC_PROG_CC -AC_PROG_CPP -AC_EXEEXT - -ac_tool_prefix=$save_ac_tool_prefix -cross_compiling=$save_cross_compiling - -dnl Restore the old definitions -dnl -popdef([ac_link])dnl -popdef([ac_compile])dnl -popdef([ac_cpp])dnl -popdef([ac_cv_host_os])dnl -popdef([ac_cv_host_vendor])dnl -popdef([ac_cv_host_cpu])dnl -popdef([ac_cv_host_alias])dnl -popdef([ac_cv_host])dnl -popdef([host_os])dnl -popdef([host_vendor])dnl -popdef([host_cpu])dnl -popdef([host_alias])dnl -popdef([host])dnl -popdef([LDFLAGS])dnl -popdef([CPPFLAGS])dnl -popdef([CFLAGS])dnl -popdef([CPP])dnl -popdef([CC])dnl -popdef([ac_objext])dnl -popdef([ac_exeext])dnl -popdef([ac_cv_objext])dnl -popdef([ac_cv_exeext])dnl -popdef([ac_cv_prog_cc_g])dnl -popdef([ac_cv_prog_cc_cross])dnl -popdef([ac_cv_prog_cc_works])dnl -popdef([ac_cv_prog_gcc])dnl -popdef([ac_cv_prog_CPP])dnl - -dnl Finally, set Makefile variables -dnl -BUILD_EXEEXT=$ac_build_exeext -BUILD_OBJEXT=$ac_build_objext -AC_SUBST(BUILD_EXEEXT)dnl -AC_SUBST(BUILD_OBJEXT)dnl -AC_SUBST([CFLAGS_FOR_BUILD])dnl -AC_SUBST([CPPFLAGS_FOR_BUILD])dnl -AC_SUBST([LDFLAGS_FOR_BUILD])dnl -]) diff --git a/m4/pkg_check_var.m4 b/m4/pkg_check_var.m4 new file mode 100644 index 00000000..ae1bf222 --- /dev/null +++ b/m4/pkg_check_var.m4 @@ -0,0 +1,14 @@ +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. + +m4_ifndef([PKG_CHECK_VAR], + [AC_DEFUN([PKG_CHECK_VAR], + [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl + AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + _PKG_CONFIG([$1], [variable="][$3]["], [$2]) + AS_VAR_COPY([$1], [pkg_cv_][$1]) + AS_VAR_IF([$1], [""], [$5], [$4])dnl + ])# PKG_CHECK_VAR +]) diff --git a/man/Makefile.am b/man/Makefile.am index 8c594ecf..eed38fe7 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,166 +1,151 @@ # # Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk EXTRA_DIST = \ kronosnetd.8 knet-keygen.8 \ api-to-man-page-coverage -# Avoid Automake warnings about overriding these user variables. -# Programs in this directory are used during the build only. -AUTOMAKE_OPTIONS = -Wno-gnu -EXEEXT=$(BUILD_EXEEXT) -CC=$(CC_FOR_BUILD) -CFLAGS=$(CFLAGS_FOR_BUILD) -CPPFLAGS=$(CPPFLAGS_FOR_BUILD) -LDFLAGS=$(LDFLAGS_FOR_BUILD) - if BUILD_MAN if BUILD_KRONOSNETD man8_MANS = kronosnetd.8 knet-keygen.8 endif -noinst_PROGRAMS = doxyxml - -doxyxml_SOURCES = doxyxml.c -doxyxml_CFLAGS = $(AM_CFLAGS) $(libqb_BUILD_CFLAGS) $(libxml_BUILD_CFLAGS) -doxyxml_LDADD = $(libqb_BUILD_LIBS) $(libxml_BUILD_LIBS) - knet_man3_MANS = \ knet_addrtostr.3 \ knet_handle_add_datafd.3 \ knet_handle_clear_stats.3 \ knet_handle_compress.3 \ knet_handle_crypto.3 \ knet_handle_enable_filter.3 \ knet_handle_enable_pmtud_notify.3 \ knet_handle_enable_sock_notify.3 \ knet_handle_free.3 \ knet_handle_get_channel.3 \ knet_get_compress_list.3 \ knet_get_crypto_list.3 \ knet_handle_get_datafd.3 \ knet_handle_get_stats.3 \ knet_get_transport_id_by_name.3 \ knet_get_transport_list.3 \ knet_get_transport_name_by_id.3 \ knet_handle_get_transport_reconnect_interval.3 \ knet_handle_new.3 \ knet_handle_pmtud_get.3 \ knet_handle_pmtud_set.3 \ knet_handle_pmtud_getfreq.3 \ knet_handle_pmtud_setfreq.3 \ knet_handle_remove_datafd.3 \ knet_handle_setfwd.3 \ knet_handle_set_transport_reconnect_interval.3 \ knet_host_add.3 \ knet_host_enable_status_change_notify.3 \ knet_host_get_host_list.3 \ knet_host_get_id_by_host_name.3 \ knet_host_get_name_by_host_id.3 \ knet_host_get_policy.3 \ knet_host_get_status.3 \ knet_host_remove.3 \ knet_host_set_name.3 \ knet_host_set_policy.3 \ knet_link_clear_config.3 \ knet_link_get_config.3 \ knet_link_get_enable.3 \ knet_link_get_link_list.3 \ knet_link_get_ping_timers.3 \ knet_link_get_pong_count.3 \ knet_link_get_priority.3 \ knet_link_get_status.3 \ knet_link_set_config.3 \ knet_link_set_enable.3 \ knet_link_set_ping_timers.3 \ knet_link_set_pong_count.3 \ knet_link_set_priority.3 \ knet_log_get_loglevel.3 \ knet_log_get_loglevel_id.3 \ knet_log_get_loglevel_name.3 \ knet_log_get_subsystem_id.3 \ knet_log_get_subsystem_name.3 \ knet_log_set_loglevel.3 \ knet_recv.3 \ knet_send.3 \ knet_send_sync.3 \ knet_strtoaddr.3 \ knet_handle_set_threads_timer_res.3 \ knet_handle_get_threads_timer_res.3 \ knet_link_enable_status_change_notify.3 \ knet_handle_enable_access_lists.3 \ knet_link_add_acl.3 \ knet_link_insert_acl.3 \ knet_link_rm_acl.3 \ knet_link_clear_acl.3 if BUILD_LIBNOZZLE nozzle_man3_MANS = \ nozzle_add_ip.3 \ nozzle_close.3 \ nozzle_del_ip.3 \ nozzle_get_fd.3 \ nozzle_get_handle_by_name.3 \ nozzle_get_ips.3 \ nozzle_get_mac.3 \ nozzle_get_mtu.3 \ nozzle_get_name_by_handle.3 \ nozzle_open.3 \ nozzle_reset_mac.3 \ nozzle_reset_mtu.3 \ nozzle_run_updown.3 \ nozzle_set_down.3 \ nozzle_set_mac.3 \ nozzle_set_mtu.3 \ nozzle_set_up.3 endif man3_MANS = $(knet_man3_MANS) $(nozzle_man3_MANS) $(MANS): doxyfile-knet.stamp doxyfile-nozzle.stamp # export LSAN_OPTIONS unconditionally for now. -# there is no urgency to fix doxyxml for leaks or bad memory access +# there is no urgency to fix doxygen2man for leaks or bad memory access # since it's a one-shot tool and doesn't affect runtime. -doxyfile-knet.stamp: $(noinst_PROGRAMS) Doxyfile-knet $(top_srcdir)/libknet/libknet.h +doxyfile-knet.stamp: Doxyfile-knet $(top_srcdir)/libknet/libknet.h $(DOXYGEN) Doxyfile-knet - LSAN_OPTIONS="exitcode=0" $(builddir)/doxyxml -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ + LSAN_OPTIONS="exitcode=0" $(DOXYGEN2MAN) -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ $$($(UTC_DATE_AT)$(SOURCE_EPOCH) +"-D %F -Y %Y") -d $(builddir)/xml-knet/ libknet_8h.xml touch doxyfile-knet.stamp -doxyfile-nozzle.stamp: $(noinst_PROGRAMS) Doxyfile-nozzle $(top_srcdir)/libnozzle/libnozzle.h +doxyfile-nozzle.stamp: Doxyfile-nozzle $(top_srcdir)/libnozzle/libnozzle.h if BUILD_LIBNOZZLE $(DOXYGEN) Doxyfile-nozzle - LSAN_OPTIONS="exitcode=0" $(builddir)/doxyxml -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ + LSAN_OPTIONS="exitcode=0" $(DOXYGEN2MAN) -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ $$($(UTC_DATE_AT)$(SOURCE_EPOCH) +"-D %F -Y %Y") -d $(builddir)/xml-nozzle/ libnozzle_8h.xml endif touch doxyfile-nozzle.stamp noinst_SCRIPTS = api-to-man-page-coverage check-local: check-api-to-man-page-coverage-libknet check-api-to-man-page-coverage-libnozzle check-api-to-man-page-coverage-libnozzle: if BUILD_LIBNOZZLE $(srcdir)/api-to-man-page-coverage $(top_srcdir) nozzle endif check-api-to-man-page-coverage-libknet: $(srcdir)/api-to-man-page-coverage $(top_srcdir) knet endif clean-local: rm -rf doxyfile*.stamp xml* *.3 diff --git a/man/doxyxml.c b/man/doxyxml.c deleted file mode 100644 index f8111fa7..00000000 --- a/man/doxyxml.c +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Copyright (C) 2018-2019 Red Hat, Inc. All rights reserved. - * - * Author: Christine Caulfield - * - * This software licensed under GPL-2.0+ - */ - - -/* - * NOTE: this code is very rough, it does the bare minimum to parse the - * XML out from doxygen and is probably very fragile to changes in that XML - * schema. It probably leaks memory all over the place too. - * - * In its favour, it *does* generate man pages and should only be run very ocasionally - */ - -#define _DEFAULT_SOURCE -#define _BSD_SOURCE -#define _XOPEN_SOURCE -#define _XOPEN_SOURCE_EXTENDED -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define XML_DIR "../man/xml-knet" -#define XML_FILE "libknet_8h.xml" - -/* - * This isn't a maximum size, it just defines how long a parameter - * type can get before we decide it's not worth lining everything up to. - * it's mainly to stop function pointer types (which can get VERY long because - * of all *their* parameters) making everything else 'line-up' over separate lines - */ -#define LINE_LENGTH 80 - -static int print_ascii = 1; -static int print_man = 0; -static int print_params = 0; -static int num_functions = 0; -static const char *man_section="3"; -static const char *package_name="Kronosnet"; -static const char *header="Kronosnet Programmer's Manual"; -static const char *output_dir="./"; -static const char *xml_dir = XML_DIR; -static const char *xml_file = XML_FILE; -static const char *manpage_date = NULL; -static long manpage_year = LONG_MIN; -static struct qb_list_head params_list; -static struct qb_list_head retval_list; -static qb_map_t *function_map; -static qb_map_t *structures_map; -static qb_map_t *used_structures_map; - -struct param_info { - char *paramname; - char *paramtype; - char *paramdesc; - struct param_info *next; - struct qb_list_head list; -}; - -struct struct_info { - enum {STRUCTINFO_STRUCT, STRUCTINFO_ENUM} kind; - char *structname; - struct qb_list_head params_list; /* our params */ - struct qb_list_head list; -}; - -static char *get_texttree(int *type, xmlNode *cur_node, char **returntext); -static void traverse_node(xmlNode *parentnode, const char *leafname, void (do_members(xmlNode*, void*)), void *arg); - -static void free_paraminfo(struct param_info *pi) -{ - free(pi->paramname); - free(pi->paramtype); - free(pi->paramdesc); - free(pi); -} - -static char *get_attr(xmlNode *node, const char *tag) -{ - xmlAttr *this_attr; - - for (this_attr = node->properties; this_attr; this_attr = this_attr->next) { - if (this_attr->type == XML_ATTRIBUTE_NODE && strcmp((char *)this_attr->name, tag) == 0) { - return strdup((char *)this_attr->children->content); - } - } - return NULL; -} - -static char *get_child(xmlNode *node, const char *tag) -{ - xmlNode *this_node; - xmlNode *child; - char buffer[1024] = {'\0'}; - char *refid = NULL; - char *declname = NULL; - - for (this_node = node->children; this_node; this_node = this_node->next) { - if ((strcmp( (char*)this_node->name, "declname") == 0)) { - declname = strdup((char*)this_node->children->content); - } - - if ((this_node->type == XML_ELEMENT_NODE && this_node->children) && ((strcmp((char *)this_node->name, tag) == 0))) { - refid = NULL; - for (child = this_node->children; child; child = child->next) { - if (child->content) { - strncat(buffer, (char *)child->content, sizeof(buffer)-1); - } - - if ((strcmp( (char*)child->name, "ref") == 0)) { - if (child->children->content) { - strncat(buffer, (char *)child->children->content, sizeof(buffer)-1); - } - refid = get_attr(child, "refid"); - } - } - } - if (declname && refid) { - qb_map_put(used_structures_map, refid, declname); - } - } - return strdup(buffer); -} - -static struct param_info *find_param_by_name(struct qb_list_head *list, const char *name) -{ - struct qb_list_head *iter; - struct param_info *pi; - - qb_list_for_each(iter, list) { - pi = qb_list_entry(iter, struct param_info, list); - if (strcmp(pi->paramname, name) == 0) { - return pi; - } - } - return NULL; -} - -static int not_all_whitespace(char *string) -{ - unsigned int i; - - for (i=0; ichildren; this_tag; this_tag = this_tag->next) { - for (sub_tag = this_tag->children; sub_tag; sub_tag = sub_tag->next) { - if (sub_tag->type == XML_ELEMENT_NODE && strcmp((char *)sub_tag->name, "parameternamelist") == 0) { - paramname = (char*)sub_tag->children->next->children->content; - } - if (paramname && sub_tag->type == XML_ELEMENT_NODE && strcmp((char *)sub_tag->name, "parameterdescription") == 0) { - paramdesc = (char*)sub_tag->children->next->children->content; - - /* Add text to the param_map */ - pi = find_param_by_name(list, paramname); - if (pi) { - pi->paramdesc = paramdesc; - } - else { - pi = malloc(sizeof(struct param_info)); - if (pi) { - pi->paramname = paramname; - pi->paramdesc = paramdesc; - pi->paramtype = NULL; /* retval */ - qb_list_add_tail(&pi->list, list); - } - } - } - } - } -} - -static char *get_text(xmlNode *cur_node, char **returntext) -{ - xmlNode *this_tag; - xmlNode *sub_tag; - char *kind; - char buffer[4096] = {'\0'}; - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - if (this_tag->type == XML_TEXT_NODE && strcmp((char *)this_tag->name, "text") == 0) { - if (not_all_whitespace((char*)this_tag->content)) { - strncat(buffer, (char*)this_tag->content, sizeof(buffer)-1); - strncat(buffer, "\n", sizeof(buffer)-1); - } - } - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "emphasis") == 0) { - if (print_man) { - strncat(buffer, "\\fB", sizeof(buffer)-1); - } - strncat(buffer, (char*)this_tag->children->content, sizeof(buffer)-1); - if (print_man) { - strncat(buffer, "\\fR", sizeof(buffer)-1); - } - } - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "itemizedlist") == 0) { - for (sub_tag = this_tag->children; sub_tag; sub_tag = sub_tag->next) { - if (sub_tag->type == XML_ELEMENT_NODE && strcmp((char *)sub_tag->name, "listitem") == 0) { - strncat(buffer, (char*)sub_tag->children->children->content, sizeof(buffer)-1); - strncat(buffer, "\n", sizeof(buffer)-1); - } - } - } - - /* Look for subsections - return value & params */ - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "simplesect") == 0) { - char *tmp; - - kind = get_attr(this_tag, "kind"); - tmp = get_text(this_tag->children, NULL); - - if (returntext && strcmp(kind, "return") == 0) { - *returntext = tmp; - } - free(kind); - } - - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "parameterlist") == 0) { - kind = get_attr(this_tag, "kind"); - if (strcmp(kind, "param") == 0) { - get_param_info(this_tag, ¶ms_list); - } - if (strcmp(kind, "retval") == 0) { - get_param_info(this_tag, &retval_list); - } - free(kind); - } - } - return strdup(buffer); -} - -static void read_structname(xmlNode *cur_node, void *arg) -{ - struct struct_info *si=arg; - xmlNode *this_tag; - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - if (strcmp((char*)this_tag->name, "compoundname") == 0) { - si->structname = strdup((char*)this_tag->children->content); - } - } -} - -/* Called from traverse_node() */ -static void read_struct(xmlNode *cur_node, void *arg) -{ - xmlNode *this_tag; - struct struct_info *si=arg; - struct param_info *pi; - char fullname[1024]; - char *type = NULL; - char *name = NULL; - const char *args=""; - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - if (strcmp((char*)this_tag->name, "type") == 0) { - type = (char*)this_tag->children->content ; - } - if (strcmp((char*)this_tag->name, "name") == 0) { - name = (char*)this_tag->children->content ; - } - if (this_tag->children && strcmp((char*)this_tag->name, "argsstring") == 0) { - args = (char*)this_tag->children->content; - } - } - - if (name) { - pi = malloc(sizeof(struct param_info)); - if (pi) { - snprintf(fullname, sizeof(fullname), "%s%s", name, args); - pi->paramtype = type?strdup(type):strdup(""); - pi->paramname = strdup(fullname); - pi->paramdesc = NULL; - qb_list_add_tail(&pi->list, &si->params_list); - } - } -} - -static int read_structure_from_xml(char *refid, char *name) -{ - char fname[PATH_MAX]; - xmlNode *rootdoc; - xmlDocPtr doc; - struct struct_info *si; - int ret = -1; - - snprintf(fname, sizeof(fname), "%s/%s.xml", xml_dir, refid); - - doc = xmlParseFile(fname); - if (doc == NULL) { - fprintf(stderr, "Error: unable to open xml file for %s\n", refid); - return -1; - } - - rootdoc = xmlDocGetRootElement(doc); - if (!rootdoc) { - fprintf(stderr, "Can't find \"document root\"\n"); - return -1; - } - - si = malloc(sizeof(struct struct_info)); - if (si) { - si->kind = STRUCTINFO_STRUCT; - qb_list_init(&si->params_list); - traverse_node(rootdoc, "memberdef", read_struct, si); - traverse_node(rootdoc, "compounddef", read_structname, si); - ret = 0; - qb_map_put(structures_map, refid, si); - } - xmlFreeDoc(doc); - - return ret; -} - - -static void print_param(FILE *manfile, struct param_info *pi, int field_width, int bold, const char *delimiter) -{ - char *asterisks = " "; - char *type = pi->paramtype; - int typelength = strlen(type); - - /* Reformat pointer params so they look nicer */ - if (typelength > 0 && pi->paramtype[typelength-1] == '*') { - asterisks=" *"; - type = strdup(pi->paramtype); - type[typelength-1] = '\0'; - - /* Cope with double pointers */ - if (typelength > 1 && pi->paramtype[typelength-2] == '*') { - asterisks="**"; - type[typelength-2] = '\0'; - } - } - - fprintf(manfile, " %s%-*s%s%s\\fI%s\\fP%s\n", - bold?"\\fB":"", field_width, type, - asterisks, bold?"\\fP":"", pi->paramname, delimiter); - - if (type != pi->paramtype) { - free(type); - } -} - -static void print_structure(FILE *manfile, char *refid, char *name) -{ - struct struct_info *si; - struct param_info *pi; - struct qb_list_head *iter; - unsigned int max_param_length=0; - - /* If it's not been read in - go and look for it */ - si = qb_map_get(structures_map, refid); - if (!si) { - if (!read_structure_from_xml(refid, name)) { - si = qb_map_get(structures_map, refid); - } - } - - if (si) { - qb_list_for_each(iter, &si->params_list) { - pi = qb_list_entry(iter, struct param_info, list); - if (strlen(pi->paramtype) > max_param_length) { - max_param_length = strlen(pi->paramtype); - } - } - - if (si->kind == STRUCTINFO_STRUCT) { - fprintf(manfile, "struct %s {\n", si->structname); - } else if (si->kind == STRUCTINFO_ENUM) { - fprintf(manfile, "enum %s {\n", si->structname); - } else { - fprintf(manfile, "%s {\n", si->structname); - } - - qb_list_for_each(iter, &si->params_list) { - pi = qb_list_entry(iter, struct param_info, list); - print_param(manfile, pi, max_param_length, 0,";"); - } - fprintf(manfile, "};\n"); - } -} - -char *get_texttree(int *type, xmlNode *cur_node, char **returntext) -{ - xmlNode *this_tag; - char *tmp = NULL; - char buffer[4096] = {'\0'}; - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "para") == 0) { - tmp = get_text(this_tag, returntext); - strncat(buffer, tmp, sizeof(buffer)-1); - strncat(buffer, "\n", sizeof(buffer)-1); - free(tmp); - } - } - - if (buffer[0]) { - return strdup(buffer); - } else { - return NULL; - } -} - -/* The text output is VERY basic and just a check that it's working really */ -static void print_text(char *name, char *def, char *brief, char *args, char *detailed, - struct qb_list_head *param_list, char *returntext) -{ - printf(" ------------------ %s --------------------\n", name); - printf("NAME\n"); - printf(" %s - %s\n", name, brief); - - printf("SYNOPSIS\n"); - printf(" %s %s\n\n", name, args); - - printf("DESCRIPTION\n"); - printf(" %s\n", detailed); - - if (returntext) { - printf("RETURN VALUE\n"); - printf(" %s\n", returntext); - } -} - -/* Print a long string with para marks in it. */ -static void man_print_long_string(FILE *manfile, char *text) -{ - char *next_nl; - char *current = text; - - next_nl = strchr(text, '\n'); - while (next_nl && *next_nl != '\0') { - *next_nl = '\0'; - if (strlen(current)) { - fprintf(manfile, ".PP\n%s\n", current); - } - - *next_nl = '\n'; - current = next_nl+1; - next_nl = strchr(current, '\n'); - } -} - -static void print_manpage(char *name, char *def, char *brief, char *args, char *detailed, - struct qb_list_head *param_map, char *returntext) -{ - char manfilename[PATH_MAX]; - char gendate[64]; - const char *dateptr = gendate; - FILE *manfile; - time_t t; - struct tm *tm; - qb_map_iter_t *map_iter; - struct qb_list_head *iter; - struct qb_list_head *tmp; - const char *p; - void *data; - unsigned int max_param_type_len; - unsigned int max_param_name_len; - unsigned int num_param_descs; - int param_count = 0; - int param_num = 0; - struct param_info *pi; - - t = time(NULL); - tm = localtime(&t); - if (!tm) { - perror("unable to get localtime"); - exit(1); - } - strftime(gendate, sizeof(gendate), "%Y-%m-%d", tm); - - if (manpage_date) { - dateptr = manpage_date; - } - if (manpage_year == LONG_MIN) { - manpage_year = tm->tm_year+1900; - } - - snprintf(manfilename, sizeof(manfilename), "%s/%s.%s", output_dir, name, man_section); - manfile = fopen(manfilename, "w+"); - if (!manfile) { - perror("unable to open output file"); - printf("%s", manfilename); - exit(1); - } - - /* Work out the length of the parameters, so we can line them up */ - max_param_type_len = 0; - max_param_name_len = 0; - num_param_descs = 0; - - qb_list_for_each(iter, ¶ms_list) { - pi = qb_list_entry(iter, struct param_info, list); - - if ((strlen(pi->paramtype) < LINE_LENGTH) && - (strlen(pi->paramtype) > max_param_type_len)) { - max_param_type_len = strlen(pi->paramtype); - } - if (strlen(pi->paramname) > max_param_name_len) { - max_param_name_len = strlen(pi->paramname); - } - if (pi->paramdesc) { - num_param_descs++; - } - param_count++; - } - - /* Off we go */ - - fprintf(manfile, ".\\\" Automatically generated man page, do not edit\n"); - fprintf(manfile, ".TH %s %s %s \"%s\" \"%s\"\n", name, man_section, dateptr, package_name, header); - - fprintf(manfile, ".SH NAME\n"); - fprintf(manfile, "%s \\- %s\n", name, brief); - - fprintf(manfile, ".SH SYNOPSIS\n"); - fprintf(manfile, ".nf\n"); - fprintf(manfile, ".B #include \n"); - fprintf(manfile, ".sp\n"); - fprintf(manfile, "\\fB%s\\fP(\n", def); - - - qb_list_for_each(iter, ¶ms_list) { - pi = qb_list_entry(iter, struct param_info, list); - - print_param(manfile, pi, max_param_type_len, 1, ++param_num < param_count?",":""); - } - - fprintf(manfile, ");\n"); - fprintf(manfile, ".fi\n"); - - if (print_params && num_param_descs) { - fprintf(manfile, ".SH PARAMS\n"); - - qb_list_for_each(iter, ¶ms_list) { - pi = qb_list_entry(iter, struct param_info, list); - fprintf(manfile, "\\fB%-*s \\fP\\fI%s\\fP\n", (int)max_param_name_len, pi->paramname, - pi->paramdesc); - fprintf(manfile, ".PP\n"); - } - } - - fprintf(manfile, ".SH DESCRIPTION\n"); - man_print_long_string(manfile, detailed); - - if (qb_map_count_get(used_structures_map)) { - fprintf(manfile, ".SH STRUCTURES\n"); - - map_iter = qb_map_iter_create(used_structures_map); - for (p = qb_map_iter_next(map_iter, &data); p; p = qb_map_iter_next(map_iter, &data)) { - fprintf(manfile, ".nf\n"); - fprintf(manfile, "\\fB\n"); - - print_structure(manfile, (char*)p, (char *)data); - - fprintf(manfile, "\\fP\n"); - fprintf(manfile, ".fi\n"); - } - qb_map_iter_free(map_iter); - - fprintf(manfile, ".RE\n"); - } - - if (returntext) { - fprintf(manfile, ".SH RETURN VALUE\n"); - man_print_long_string(manfile, returntext); - } - - qb_list_for_each(iter, &retval_list) { - pi = qb_list_entry(iter, struct param_info, list); - - fprintf(manfile, "\\fB%-*s \\fP\\fI%s\\fP\n", 10, pi->paramname, - pi->paramdesc); - fprintf(manfile, ".PP\n"); - } - - fprintf(manfile, ".SH SEE ALSO\n"); - fprintf(manfile, ".PP\n"); - fprintf(manfile, ".nh\n"); - fprintf(manfile, ".ad l\n"); - - param_num = 0; - map_iter = qb_map_iter_create(function_map); - for (p = qb_map_iter_next(map_iter, &data); p; p = qb_map_iter_next(map_iter, &data)) { - - /* Exclude us! */ - if (strcmp(data, name)) { - fprintf(manfile, "\\fI%s(%s)%s", (char *)data, man_section, - param_num < (num_functions - 1)?", ":""); - } - param_num++; - } - qb_map_iter_free(map_iter); - - fprintf(manfile, "\n"); - fprintf(manfile, ".ad\n"); - fprintf(manfile, ".hy\n"); - fprintf(manfile, ".SH \"COPYRIGHT\"\n"); - fprintf(manfile, ".PP\n"); - fprintf(manfile, "Copyright (C) 2010-%4ld Red Hat, Inc. All rights reserved.\n", manpage_year); - fclose(manfile); - - /* Free the params & retval info */ - qb_list_for_each_safe(iter, tmp, ¶ms_list) { - pi = qb_list_entry(iter, struct param_info, list); - qb_list_del(&pi->list); - free_paraminfo(pi); - } - - qb_list_for_each_safe(iter, tmp, &retval_list) { - pi = qb_list_entry(iter, struct param_info, list); - qb_list_del(&pi->list); - free_paraminfo(pi); - } - - /* Free used-structures map */ - map_iter = qb_map_iter_create(used_structures_map); - for (p = qb_map_iter_next(map_iter, &data); p; p = qb_map_iter_next(map_iter, &data)) { - qb_map_rm(used_structures_map, p); - free(data); - } -} - -/* Same as traverse_members, but to collect function names */ -static void collect_functions(xmlNode *cur_node, void *arg) -{ - xmlNode *this_tag; - char *kind; - char *name = NULL; - - if (cur_node->name && strcmp((char *)cur_node->name, "memberdef") == 0) { - - kind = get_attr(cur_node, "kind"); - if (kind && strcmp(kind, "function") == 0) { - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "name") == 0) { - name = strdup((char *)this_tag->children->content); - } - } - - if (name) { - qb_map_put(function_map, name, name); - num_functions++; - } - } - free(kind); - } -} - -/* Same as traverse_members, but to collect enums. The behave like structures for, - but, for some reason, are in the main XML file rather than their own */ -static void collect_enums(xmlNode *cur_node, void *arg) -{ - xmlNode *this_tag; - struct struct_info *si; - char *kind; - char *refid = NULL; - char *name = NULL; - - if (cur_node->name && strcmp((char *)cur_node->name, "memberdef") == 0) { - - kind = get_attr(cur_node, "kind"); - if (kind && strcmp(kind, "enum") == 0) { - refid = get_attr(cur_node, "id"); - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) { - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "name") == 0) { - name = strdup((char *)this_tag->children->content); - break; - } - } - - if (name) { - si = malloc(sizeof(struct struct_info)); - if (si) { - si->kind = STRUCTINFO_ENUM; - qb_list_init(&si->params_list); - si->structname = strdup(name); - traverse_node(cur_node, "enumvalue", read_struct, si); - qb_map_put(structures_map, refid, si); - } - free(name); - } - } - free(kind); - } -} - -static void traverse_members(xmlNode *cur_node, void *arg) -{ - xmlNode *this_tag; - - if (cur_node->name && strcmp((char *)cur_node->name, "memberdef") == 0) { - char *kind = NULL; - char *def = NULL; - char *args = NULL; - char *name = NULL; - char *brief = NULL; - char *detailed = NULL; - char *returntext = NULL; - int type; - - kind=def=args=name=NULL; - - kind = get_attr(cur_node, "kind"); - - for (this_tag = cur_node->children; this_tag; this_tag = this_tag->next) - { - if (!this_tag->children || !this_tag->children->content) - continue; - - if (!def && this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "definition") == 0) - def = strdup((char *)this_tag->children->content); - if (!args && this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "argsstring") == 0) - args = strdup((char *)this_tag->children->content); - if (!name && this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "name") == 0) - name = strdup((char *)this_tag->children->content); - - if (!brief && this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "briefdescription") == 0) { - brief = get_texttree(&type, this_tag, &returntext); - if (brief) { - /* - * apparently brief text contains extra trailing space and 2 \n. - * remove them. - */ - brief[strlen(brief) - 3] = '\0'; - } - } - if (!detailed && this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "detaileddescription") == 0) { - detailed = get_texttree(&type, this_tag, &returntext); - } - /* Get all the params */ - if (this_tag->type == XML_ELEMENT_NODE && strcmp((char *)this_tag->name, "param") == 0) { - char *param_type = get_child(this_tag, "type"); - char *param_name = get_child(this_tag, "declname"); - struct param_info *pi = malloc(sizeof(struct param_info)); - if (pi) { - pi->paramname = param_name; - pi->paramtype = param_type; - pi->paramdesc = NULL; - qb_list_add_tail(&pi->list, ¶ms_list); - } - } - } - - if (kind && strcmp(kind, "function") == 0) { - /* Make sure function has a doxygen description */ - if (!detailed) { - fprintf(stderr, "No doxygen description for function '%s' - please fix this\n", name); - exit(1); - } - - if (print_man) { - print_manpage(name, def, brief, args, detailed, ¶ms_list, returntext); - } - else { - print_text(name, def, brief, args, detailed, ¶ms_list, returntext); - } - - } - - free(kind); - free(def); - free(args); - free(detailed); - free(brief); - free(name); - } -} - - -static void traverse_node(xmlNode *parentnode, const char *leafname, void (do_members(xmlNode*, void*)), void *arg) -{ - xmlNode *cur_node; - - for (cur_node = parentnode->children; cur_node; cur_node = cur_node->next) { - - if (cur_node->type == XML_ELEMENT_NODE && cur_node->name - && strcmp((char*)cur_node->name, leafname)==0) { - do_members(cur_node, arg); - continue; - } - if (cur_node->type == XML_ELEMENT_NODE) { - traverse_node(cur_node, leafname, do_members, arg); - } - } -} - - -static void usage(char *name) -{ - printf("Usage:\n"); - printf(" %s [OPTIONS] []\n", name); - printf("\n"); - printf(" defaults to %s\n", XML_FILE); - printf("\n"); - printf(" -a Print ASCII dump of man pages to stdout\n"); - printf(" -m Write man page files to \n"); - printf(" -P Print PARAMS section\n"); - printf(" -s Write man pages into section Use name. default \n"); - printf(" -H
Set header (default \"Kronosnet Programmer's Manual\"\n"); - printf(" -D Date to print at top of man pages (format not checked, default: today)\n"); - printf(" -Y Year to print at end of copyright line (default: today's year)\n"); - printf(" -o Write all man pages to (default .)\n"); - printf(" -d Directory for XML files (default %s)\n", XML_DIR); - printf(" -h Print this usage text\n"); -} - -int main(int argc, char *argv[]) -{ - xmlNode *rootdoc; - xmlDocPtr doc; - int quiet=0; - int opt; - char xml_filename[PATH_MAX]; - - while ( (opt = getopt_long(argc, argv, "H:amPD:Y:s:d:o:p:f:h?", NULL, NULL)) != EOF) - { - switch(opt) - { - case 'a': - print_ascii = 1; - print_man = 0; - break; - case 'm': - print_man = 1; - print_ascii = 0; - break; - case 'P': - print_params = 1; - break; - case 's': - man_section = optarg; - break; - case 'd': - xml_dir = optarg; - break; - case 'D': - manpage_date = optarg; - break; - case 'Y': - manpage_year = strtol(optarg, NULL, 10); - /* - * Don't make too many assumptions about the year. I was on call at the - * 2000 rollover. #experience - */ - if (manpage_year == LONG_MIN || manpage_year == LONG_MAX || - manpage_year < 1900) { - fprintf(stderr, "Value passed to -Y is not a valid year number\n"); - return 1; - } - break; - case 'p': - package_name = optarg; - break; - case 'H': - header = optarg; - break; - case 'o': - output_dir = optarg; - break; - case '?': - case 'h': - usage(argv[0]); - return 0; - } - } - - if (argv[optind]) { - xml_file = argv[optind]; - } - if (!quiet) { - fprintf(stderr, "reading xml ... "); - } - - snprintf(xml_filename, sizeof(xml_filename), "%s/%s", xml_dir, xml_file); - doc = xmlParseFile(xml_filename); - if (doc == NULL) { - fprintf(stderr, "Error: unable to read xml file %s\n", xml_filename); - exit(1); - } - - rootdoc = xmlDocGetRootElement(doc); - if (!rootdoc) { - fprintf(stderr, "Can't find \"document root\"\n"); - exit(1); - } - if (!quiet) - fprintf(stderr, "done.\n"); - - qb_list_init(¶ms_list); - qb_list_init(&retval_list); - structures_map = qb_hashtable_create(10); - function_map = qb_hashtable_create(10); - used_structures_map = qb_hashtable_create(10); - - /* Collect functions */ - traverse_node(rootdoc, "memberdef", collect_functions, NULL); - - /* Collect enums */ - traverse_node(rootdoc, "memberdef", collect_enums, NULL); - - /* print pages */ - traverse_node(rootdoc, "memberdef", traverse_members, NULL); - - return 0; -}