posts - 15, comments - 0, trackbacks - 0, articles - 5
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

1、源代码结构

Posted on 2018-10-21 19:37 eamon 阅读(330) 评论(0)  编辑 收藏 引用 所属分类: 读源码学编程-pure-ftpd
下载 pure-ftpd-1.0.47.tar.gz,解压后目录结构如下:

目录,每个目录中均包含一个Makefile.am

gui

 

m4

 

Man

 

Pam

 

Puredb

Puredb的项目,src里包含了源代码

src

ftp服务器代码

根目录

 

NEWS README AUTHORS ChangeLog automake 工具要求要有的文件。

 

autoscan -->> configure.scan -->> configure.ac 编辑configure.ac文件

aclocal ->>> aclocal.m4  ,编辑aclocal文件

autoheader --> config.h.in

automake --add-missing  -->> Makefile.am ->> Makefile.in

autoconf  -->  利用M4解析configure.ac,生成shell脚本configure

./configure  -->> Makefile config.h

 

调用autoheader,扫描configure.ac(configure.in)acconfig.h(如果存在),生成config.h.in宏定义文件,里面主要是根据configure.ac中某些特定宏(AC_DEFINE)生成的#define#undefine宏,configure在将根据实际的探测结果决定这些宏是否定义(具体见后面例子)。

compile  COPYING depcomp INSTALL install-sh missing 六个符号链接文件,为automake --add-missing时生成。

 

config.h.in  autoheader时生成

configure   autoconf时生成

 

pure-ftpd.conf.in 生成pure-ftpd.conf (configure.ac中定义的输出文件),并安装到etc目录下(Makefile.am中定义)

 

aclocal.m4aclocal命令生成的文件,文件末尾增加

 

m4_include([m4/ax_check_compile_flag.m4])

m4_include([m4/ax_check_link_flag.m4])

m4_include([m4/getloadavg.m4])

将三个m4文件加入,使得configure.ac可以使用这三个文件定义的宏。

 

.in文件如何变成实际安装的文件?在configure.ac中定义输出文件(AC_CONFIG_FILES),在调用configure命令式生成。

 

 

Makefile.am

打包时会包含的文件,主要是配置文件

EXTRA_DIST  =    THANKS \

      HISTORY \

      CONTACT \

      FAQ \

      Makefile.gui \

      README.LDAP \

      README.MySQL \

      README.PGSQL \

      README.Configuration-File \

      README.Virtual-Users \

      README.Authentication-Modules \

      README.Windows \

      README.TLS \

      README.MacOS-X \

      README.Donations \

      pureftpd.schema \

      pureftpd-ldap.conf \

      pureftpd-mysql.conf \

      pureftpd-pgsql.conf \

      pure-ftpd.png

 

项目包含6个子目录,每个子目录都会有Makefile.am

SUBDIRS=      puredb \

      src \

      man \

      pam \

      gui \

      m4

 

sbin_PROGRAMS, lib_LIBRARIES指生成库, sysconf_DATA指系统配置文件, man_MANS指手册等。相应的,在make install时会把他们拷贝到对应的目录。例如,指定man_MANS=hello.man.3则会把该文件安装到prefix/man目录下,指定sysconf_DATA=hello.conf就会把配置文件放到prefix/etc目录下。

目前只有pure-ftpd.conf.in文件,编译时会变成pure-ftpd.conf,安装时会安装到 /etc目录下。

sysconf_DATA= pure-ftpd.conf

 

GUI目录

只有build.sh 一个基于GUI编译的脚本。

Makefile.am:将脚本包含到打包文件中。

EXTRA_DIST = \

      build.sh

 

M4目录

3M4文件,和一个Makefile.am文件。

getloadavg.m4   提供宏定义: AC_FUNC_GETLOADAVG

ax_check_compile_flag.m4   提供宏定义:AX_CHECK_COMPILE_FLAG

ax_check_link_flag.m4    提供宏定义:AX_CHECK_LINK_FLAG

3个宏定义在configure.ac中用到。

 

Makefile.am: :将脚本getloadavg.m4包含到打包文件中。

EXTRA_DIST = \

      getloadavg.m4

 

Man目录

9.8的帮助文件,目前是.in文件,在configure时会生成去掉.in后缀的文件(在configure.ac 中定义)。和Makefile.am

安装到man目录的8目录下。

man_MANS = \

      pure-ftpd.8 \

      pure-ftpwho.8 \

      pure-mrtginfo.8 \

      pure-uploadscript.8 \

      pure-statsdecode.8 \

      pure-quotacheck.8 \

      pure-pw.8 \

      pure-pwconvert.8 \

      pure-authd.8

 

这个不知道什么意思

CLEANFILES = \

      pure-ftpd.8 \

      pure-ftpwho.8 \

      pure-mrtginfo.8 \

      pure-uploadscript.8 \

      pure-statsdecode.8 \

      pure-quotacheck.8 \

      pure-pw.8 \

      pure-pwconvert.8 \

      pure-authd.8

 

 

 

pam目录

README  

pure-ftpd   PAM配置文件,拷贝到/etc/pam.d目录下

ftpusers  不允许登陆ftp的用户列表,拷贝到/etc目录下

 

Makefile.am

将三个文件打包

EXTRA_DIST = \

      ftpusers \

      pure-ftpd \

      README

 

puredb目录

README.FIRST  README

Makefile.am

 

SUBDIRS = \

      src

 

EXTRA_DIST = \

      README.FIRST

 

 

src子目录

Makefile.am

 

noinst_LIBRARIES = libpuredb_read.a libpuredb_write.a

 

noinst_HEADERS = puredb_read.h puredb_write.h

 

noinst_PROGRAMS = example_read example_write regression

 

libpuredb_read_a_SOURCES = puredb_read.c puredb_read.h puredb_p.h

 

libpuredb_write_a_SOURCES = puredb_write.c puredb_write.h puredb_p.h

 

example_read_LDADD = libpuredb_read.a

 

example_write_LDADD = libpuredb_write.a

 

regression_LDADD = libpuredb_read.a libpuredb_write.a

 

example_read_SOURCES = example_read.c puredb_read.h

 

example_write_SOURCES = example_write.c puredb_write.h

 

regression_SOURCES = regression.c puredb_read.h puredb_write.h puredb_p.h

 

 

src目录

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

configure.ac

 

autoscan 生成的configure.scan:

 

#                                               -*- Autoconf -*-

# Process this file with autoconf to produce a configure script.

 

AC_PREREQ([2.69])

AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])

AC_CONFIG_SRCDIR([config.h.in])

AC_CONFIG_HEADERS([config.h])

 

# Checks for programs.

AC_PROG_CC

AC_PROG_INSTALL

AC_PROG_MAKE_SET

 

# Checks for libraries.

 

# Checks for header files.

AC_FUNC_ALLOCA

AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h locale.h memory.h netdb.h netinet/in.h nlist.h sgtty.h shadow.h stddef.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/socket.h sys/statvfs.h sys/time.h sys/vfs.h syslog.h termio.h termios.h unistd.h utime.h])

 

# Checks for typedefs, structures, and compiler characteristics.

AC_TYPE_UID_T

AC_C_INLINE

AC_TYPE_MODE_T

AC_TYPE_OFF_T

AC_TYPE_PID_T

AC_TYPE_SIZE_T

AC_TYPE_SSIZE_T

AC_TYPE_UINT32_T

 

# Checks for library functions.

AC_FUNC_CHOWN

AC_FUNC_ERROR_AT_LINE

AC_FUNC_FORK

AC_FUNC_GETGROUPS

AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK

AC_FUNC_MALLOC

AC_FUNC_MKTIME

AC_FUNC_MMAP

AC_FUNC_REALLOC

AC_FUNC_STRTOD

AC_FUNC_WAIT3

AC_CHECK_FUNCS([alarm dup2 endpwent ftruncate getcwd gethostbyaddr gethostbyname gethostname getpagesize getspnam gettimeofday getusershell inet_ntoa memmove memset mkdir mkfifo munmap putenv realpath rmdir select setlocale socket strcasecmp strchr strdup strerror strncasecmp strpbrk strrchr strspn strstr strtol strtoul strtoull tzset utime])

 

AC_CONFIG_FILES([Makefile

                 gui/Makefile

                 m4/Makefile

                 man/Makefile

                 pam/Makefile

                 puredb/Makefile

                 puredb/src/Makefile

                 src/Makefile])

AC_OUTPUT

 

 

修改如下:

 

AC_INIT([pure-ftpd], [1.0.47], [bugs at pureftpd dot org])

AC_CONFIG_SRCDIR([src/ftpd.c])

 

初始化automake

AM_INIT_AUTOMAKE([1.9 dist-bzip2 tar-ustar])

 

AC_CONFIG_LIBOBJ_DIR(src)  还不太清楚

 

 

AC_SUBST(VERSION)

 

ISODATE=`date +%Y-%m-%d`

AC_SUBST(ISODATE)

 

Makefiles中的替换

发布版本中每个包含了需要被编译或者被安装的文件的目录都应该含有一个文件`Makefile.in' configure将利用它在那个目录中创建一个`Makefile' 为了创建`Makefile'configure进行一个简单的变量替换:用configure`@variable@'选取的值,在`Makefile.in'中对它们进行替换。 按照这种方式被替换到输出文件中的变量被称为输出变量。在configure中,它们是普通 shell变量。为了让configure把特殊的变量替换到输出文件中,必须把那个变量的名字作为调用 AC_SUBST的参数。其他变量的任何`@variable@'都保持不变。关于 使用AC_SUBST创建输出变量的详情,请参见设定输出变量。

 

使用configure脚本的软件应该发布文件`Makefile.in',而不是`Makefile' 这样,用户就可以在编译它之前正确地为本地系统进行配置了。

 

关于应该把哪些东西放入`Makefile'的详情,请参见GNU编码标准中的`Makefile惯例'

 

Makefile.in

ISODATE = @ISODATE@

Makefile

ISODATE = 2018-10-20

 

AC_PROG_RANLIB 用于生成静态库

 

LX_CFLAGS=${CFLAGS-NONE}

AM_PROG_CC_C_O

AC_USE_SYSTEM_EXTENSIONS

AC_SEARCH_LIBS([strerror],[cposix])

 

检测编译和链接选项:

AX_CHECK_COMPILE_FLAG([-fPIC], [

  AX_CHECK_LINK_FLAG([-fPIC],

    [CFLAGS="$CFLAGS -fPIC"]

  )

])

 

AS_IF([test "$enable_pie" != "no"],[

  AX_CHECK_COMPILE_FLAG([-fPIE], [

    AX_CHECK_LINK_FLAG([-pie], [

      [CFLAGS="$CFLAGS -fPIE"

       LDFLAGS="$LDFLAGS -pie"]

    ])

  ])

])

 

AX_CHECK_COMPILE_FLAG([-fwrapv], [CFLAGS="$CFLAGS -fwrapv"])

AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing], [CFLAGS="$CFLAGS -fno-strict-aliasing"])

AX_CHECK_COMPILE_FLAG([-fno-strict-overflow], [CFLAGS="$CFLAGS -fno-strict-overflow"])

AS_IF([echo `(uname -s) 2>/dev/null` | $GREP "CYGWIN" > /dev/null], [

  AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [LDFLAGS="$LDFLAGS -Wl,--nxcompat"])

], [

  AS_IF([test `(uname -s) 2>/dev/null` = "DragonFly"],

    [

      AX_CHECK_COMPILE_FLAG([-fstack-protector], [

        AX_CHECK_LINK_FLAG([-fstack-protector],

          [CFLAGS="$CFLAGS -fstack-protector"]

        )

      ])

    ],

    [

      AX_CHECK_COMPILE_FLAG([-fstack-protector-all], [

        AX_CHECK_LINK_FLAG([-fstack-protector-all],

          [CFLAGS="$CFLAGS -fstack-protector-all"]

        )

      ])

    ]

  )

])

 

AX_CHECK_COMPILE_FLAG([-Winit-self], [CFLAGS="$CFLAGS -Winit-self"])

AX_CHECK_COMPILE_FLAG([-Wwrite-strings], [CFLAGS="$CFLAGS -Wwrite-strings"])

AX_CHECK_COMPILE_FLAG([-Wdiv-by-zero], [CFLAGS="$CFLAGS -Wdiv-by-zero"])

 

AC_ARG_VAR([CWFLAGS], [define to compilation flags for generating extra warnings])                  定义一个变量 CWFLAGS,输出到Makefile中。

 

AX_CHECK_COMPILE_FLAG([-Wall], [CWFLAGS="$CWFLAGS -Wall"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wextra], [CWFLAGS="$CWFLAGS -Wextra"])

 

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wbad-function-cast], [CWFLAGS="$CWFLAGS -Wbad-function-cast"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wcast-align], [CWFLAGS="$CWFLAGS -Wcast-align"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wcast-qual], [CWFLAGS="$CWFLAGS -Wcast-qual"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wchar-subscripts], [CWFLAGS="$CWFLAGS -Wchar-subscripts"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wcomment], [CWFLAGS="$CWFLAGS -Wcomment"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wfloat-equal], [CWFLAGS="$CWFLAGS -Wfloat-equal"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wformat=2], [CWFLAGS="$CWFLAGS -Wformat=2"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wimplicit], [CWFLAGS="$CWFLAGS -Wimplicit"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wmissing-declarations], [CWFLAGS="$CWFLAGS -Wmissing-declarations"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wmissing-prototypes], [CWFLAGS="$CWFLAGS -Wmissing-prototypes"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wnormalized=id], [CWFLAGS="$CWFLAGS -Wnormalized=id"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Woverride-init], [CWFLAGS="$CWFLAGS -Woverride-init"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wparentheses], [CWFLAGS="$CWFLAGS -Wparentheses"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wpointer-arith], [CWFLAGS="$CWFLAGS -Wpointer-arith"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wredundant-decls], [CWFLAGS="$CWFLAGS -Wredundant-decls"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wstrict-prototypes], [CWFLAGS="$CWFLAGS -Wstrict-prototypes"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wswitch-enum], [CWFLAGS="$CWFLAGS -Wswitch-enum"])

AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wvariable-decl], [CWFLAGS="$CWFLAGS -Wvariable-decl"])

 

AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"])

AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"])

AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"])

 

 

添加include目录和lib目录。

if test -d /usr/local/include; then

  CPPFLAGS="$CPPFLAGS -I/usr/local/include"

fi

 

if test -d /usr/kerberos/include; then

  CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include"

fi

 

if test -d /usr/local/lib; then

  LDFLAGS="$LDFLAGS -L/usr/local/lib"

fi

 

添加一个定义

CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2"

 

检查头文件:

AC_SYS_LARGEFILE   checking for special C compiler options needed for large files... no

checking for _FILE_OFFSET_BITS value needed for large files... no

 

 

AC_HEADER_STDC

AC_HEADER_STAT

AC_HEADER_TIME

AC_HEADER_DIRENT

AC_HEADER_SYS_WAIT

AC_CHECK_HEADERS(unistd.h string.h strings.h sys/param.h ioctl.h sys/ioctl.h)

AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/sendfile.h sys/uio.h)

AC_CHECK_HEADERS(sys/time.h sys/resource.h sys/capability.h)

AC_CHECK_HEADERS(shadow.h getopt.h stddef.h stdint.h)

AC_CHECK_HEADERS(netinet/in_systm.h netinet/in.h sys/pstat.h sys/file.h)

AC_CHECK_HEADERS(sys/mount.h, [], [],

[#ifdef HAVE_SYS_PARAM_H

# include <sys/param.h>

#endif])

AC_CHECK_HEADERS(fcntl.h sys/fcntl.h sys/loadavg.h sys/ptrace.h)

AC_CHECK_HEADERS(security/pam_appl.h security/pam_misc.h)

AC_CHECK_HEADERS(security/pam_modules.h security/pam_filter.h)

AC_CHECK_HEADERS(pam/pam_appl.h pam/pam_misc.h pam/pam_modules.h)

AC_CHECK_HEADERS(pam/pam_filter.h)

AC_CHECK_HEADERS(sgtty.h termio.h)

AC_CHECK_HEADERS(locale.h)

AC_CHECK_HEADERS(stdarg.h varargs.h)

AC_CHECK_HEADERS(windows.h io.h)

AC_CHECK_HEADERS(crypt.h)

AC_CHECK_HEADERS(utime.h)

AC_CHECK_HEADERS(openssl/ssl.h openssl/ec.h)

AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h)

AC_CHECK_HEADERS(iconv.h)

 

AC_SYS_POSIX_TERMIOS

 

如果checking POSIX termios... yes 则定义HAVE_POSIX_TERMIOS

if test "x$ac_cv_sys_posix_termios" = "xyes"; then

AC_DEFINE(HAVE_POSIX_TERMIOS,,[Define if you have POSIX termios(描述)])

fi

 

 

 

 

 

检查类型的大小

AC_CHECK_SIZEOF(short)

AC_CHECK_SIZEOF(int)

AC_CHECK_SIZEOF(long)

AC_CHECK_SIZEOF(long long)

AC_CHECK_SIZEOF(mode_t)

 

检查字节序

AC_C_BIGENDIAN

 

检查数据类型

 

AC_TYPE_SIGNAL

AC_TYPE_SIZE_T

AC_TYPE_SSIZE_T

AC_TYPE_UID_T

AC_TYPE_PID_T

AC_TYPE_OFF_T

AC_TYPE_MODE_T

AC_STRUCT_TM

AC_STRUCT_TIMEZONE

AC_CHECK_MEMBER(struct tm.tm_gmtoff, [AC_DEFINE(STRUCT_TM_TM_GMTOFF,,[Define if you have struct tm/tm_gmtoff])],,[

#include <sys/types.h>

#include <$ac_cv_struct_tm>

])

 

输出configuire脚本的提示

AC_MSG_CHECKING([whether timezone is scalar])

 

 

AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[

#include <sys/types.h>

#include <$ac_cv_struct_tm>   

    ]], [[timezone = 42L]])],[

         AC_MSG_RESULT(yes)

         AC_DEFINE(HAVE_SCALAR_TIMEZONE,,[Define if your timezone is a scalar number])

    ],[    AC_MSG_RESULT(no)    ])  

 

AC_CHECK_TYPE(nlink_t, , [AC_DEFINE(nlink_t, int, [nlink_t type])],

[

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#include <sys/types.h>

#include <sys/stat.h>

])

 

检查函数

dnl Socket things

 

AC_CHECK_FUNC(connect, , [AC_CHECK_LIB(socket, connect)])

 

AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(resolv, gethostbyname)])

 

AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname)])

 

if test "x$ac_cv_lib_nsl_gethostbyname" != "xyes" && test "x$ac_cv_func_gethostbyname" != "xyes" ; then

  AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(socket, gethostbyname)])

fi

 

if test "$ac_cv_lib_nsl_gethostbyname" = "$ac_cv_func_gethostbyname" ; then

  AC_MSG_CHECKING([if we can include libnsl + libsocket])

  LIBS="-lnsl -lsocket $LIBS"

  AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[(void) gethostbyname]])],[my_ac_link_result=yes],[my_ac_link_result=no ])

  if test "$my_ac_link_result" = "no" ; then

    AC_MSG_RESULT([failure])

    AC_MSG_ERROR([unable to use gethostbyname()])

  else

    AC_MSG_RESULT([success])

  fi

fi

 

dnl Compiler characteristics

 

AC_PROG_GCC_TRADITIONAL

AC_C_CONST

AC_C_INLINE

 

dnl Options

 

AM_WITH_DMALLOC

 

AC_ARG_ENABLE(pie,

[AS_HELP_STRING(--enable-pie,Produce position independent executables @<:@default=yes@:>@)],

 enable_pie=$enableval, enable_pie="maybe")

 

AC_ARG_ENABLE(ssp,

[AS_HELP_STRING(--disable-ssp,Don't compile with -fstack-protector)],

[AS_IF([test "x$enableval" = "xno"], [

    nxflags=""

    for flag in `echo $CFLAGS`; do

      case "$flag" in

       -fstack-protector*) ;;

        *) AS_VAR_APPEND([nxflags], [" $flag"]) ;;

      esac

    done

    CFLAGS="$nxflags"

  ])

])

 

AC_ARG_WITH

AC_ARG_WITH(common,"--with-common prefix for installed COMMON-LIBRARY",COMMON_LIBRARY_HOME=
$withval,COMMON_LIBRARY_HOME=)
AC_SUBST(COMMON_LIBRARY_HOME)
AS_IF([test "x$COMMON_LIBRARY_HOME" = "x"],[AC_MSG_ERROR([*** COMMON-LIBRARY could not be located. Please use the --with-common option ***.])])
经过上面的操作后,在Makefile.am中就可以引用common-library_home了,后面的AS_IF表示如果没有指定,则报错退出(执行configure时)。

 

最好将AC_ARG_WITH最好修改成:

1.   AC_ARG_WITH(common, AS_HELP_STRING([--with-common], [prefix for installed COMMON-LIBRARY]),COMMON_LIBRARY_HOME=$withval,COMMON_LIBRARY_HOME=)

 

 

 

AC_ARG_WITH(standalone,

[AS_HELP_STRING(--without-standalone,Don't compile the standalone server code)],

[ if test "x$withval" = "xno" ; then

    AC_DEFINE(NO_STANDALONE,,[without standalone])

    no_standalone=yes

  fi ])

 

if test "x$no_standalone" = "xyes" && test "x$no_inetd" = "xyes" ; then

  AC_MSG_ERROR(You can't disable both standalone and inetd mode.)

fi

 

AC_MSG_WARN(shadow.h was found, but getspnam() isn't available)

 

AC_ARG_WITH(pam,

[AS_HELP_STRING(--with-pam,Enable PAM support (default=disabled))],

[ if test "x$withval" = "xyes" ; then

    with_pam="yes"

  fi ])

 

 

AC_MSG_CHECKING([whether __ss_len is defined])

AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[

#include <stdio.h>

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#include <sys/types.h>

#include <sys/socket.h>

]], [[

do {

 struct sockaddr_storage a;

 (void) a.__ss_len;

} while(0)

]])],[

  AC_MSG_RESULT(yes)

  AC_DEFINE(HAVE___SS_LEN,,[define if you have __ss_len])

],[

  AC_MSG_RESULT(no)

]) 

 

AC_ARG_WITH(everything,

[AS_HELP_STRING(--with-everything,Build a big server with almost everything)],

[ if test "x$withval" = "xyes" ; then

    AC_DEFINE(WITH_ALTLOG)

    AC_DEFINE(COOKIE)

    AC_DEFINE(THROTTLING)

    AC_DEFINE(RATIOS)

    AC_DEFINE(QUOTAS)   

    AC_DEFINE(WITH_UPLOAD_SCRIPT)

    AC_DEFINE(WITH_VIRTUAL_HOSTS)

    AC_DEFINE(WITH_PUREDB)

    AC_DEFINE(WITH_EXTAUTH)

    AC_DEFINE(FTPWHO)

    AC_DEFINE(WITH_DIRALIASES)

    AC_DEFINE(PER_USER_LIMITS)

    with_bonjour='yes'

  fi ])

 

AC_CHECK_LIB(crypt, crypt, , )

 

AC_CHECK_LIB(sodium, crypto_pwhash_scryptsalsa208sha256_str)

 

# Checks for library functions.

AC_FUNC_ALLOCA

AC_FUNC_MMAP

AC_FUNC_MEMCMP

AC_FUNC_STRFTIME

AC_FUNC_STAT

AC_FUNC_VPRINTF

AC_FUNC_GETLOADAVG(src)

AC_FUNC_GETGROUPS

AC_FUNC_WAIT3

AC_FUNC_UTIME_NULL

AC_FUNC_STRTOD

AC_FUNC_SELECT_ARGTYPES

AC_FUNC_MKTIME

AC_FUNC_LSTAT

AC_FUNC_FORK

AC_FUNC_ERROR_AT_LINE

AC_FUNC_CLOSEDIR_VOID

AC_FUNC_CHOWN

AC_C_VOLATILE

 

 

AC_CHECK_FUNCS(initgroups setrlimit waitpid setproctitle getopt_long)

AC_CHECK_FUNCS(seteuid setreuid setresuid setegid setregid setresgid)

AC_CHECK_FUNCS(statvfs statfs putenv setenv unsetenv getpagesize realpath)

AC_CHECK_FUNCS(pread posix_fadvise ptrace)

AC_CHECK_FUNCS(strtoull strtoq)

AC_CHECK_FUNCS(strlcpy strlcat)

AC_CHECK_FUNCS(memset munmap strdup fileno mapviewoffile madvise)

AC_CHECK_FUNCS(getaddrinfo getnameinfo inet_ntop inet_pton)

AC_CHECK_FUNCS(setusershell setgroups snprintf vsnprintf vfprintf gethostname)

AC_CHECK_FUNCS(setlocale timegm)

AC_CHECK_FUNCS(tzset utime utimes mknod mkfifo)

AC_CHECK_FUNCS(random srandomdev arc4random arc4random_stir arc4random_addrandom)

AC_CHECK_FUNCS(closefrom explicit_bzero getpwnam_shadow)

 

AC_MSG_CHECKING([whether statvfs64() is defined])

AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[

#include <stdio.h>

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#include <sys/types.h>

#ifdef HAVE_SYS_STATVFS_H

# include <sys/statvfs.h>

#endif

]], [[

for (;;) {

 struct statvfs64 a;

 if (statvfs64(".", &a) == 0 || a.f_bsize != 0) {

   break;

 }

}

]])],[

  AC_MSG_RESULT(yes)

  AC_DEFINE(HAVE_STATVFS64,,[define if you have statvfs64])

],[

  AC_MSG_RESULT(no)

]) 

 

AC_MSG_CHECKING(whether snprintf is C99 conformant)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#ifdef STDC_HEADERS

# include <stdlib.h>

# include <stddef.h>

#else

# if HAVE_STDLIB_H

#  include <stdlib.h>

# endif

#endif

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

 

int main(void)

{

    char buf[4];

   

    (void) fprintf(fopen("conftestval", "w"), "%d\n",

        (int) snprintf(buf, sizeof buf, "12345678"));

    return 0;

}

]])],[CONF_SNPRINTF_TYPE=`cat conftestval`

],[],[CONF_SNPRINTF_TYPE=8])

AC_MSG_RESULT(done)

if test "x$CONF_SNPRINTF_TYPE" = "x" ; then

  AC_MSG_WARN(your operating system doesn't implement snprintf)

else

  AC_DEFINE_UNQUOTED(CONF_SNPRINTF_TYPE, $CONF_SNPRINTF_TYPE, [return value of an overflowed snprintf])

fi

 

 

AC_MSG_CHECKING(whether getgroups 0 is sane)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#ifdef STDC_HEADERS

# include <stdlib.h>

# include <stddef.h>

#else

# if HAVE_STDLIB_H

#  include <stdlib.h>

# endif

#endif

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

 

int main(void)

{

    return getgroups(0, NULL) <= 0;

}

]])],[

AC_MSG_RESULT(yes)

AC_DEFINE(SAFE_GETGROUPS_0,,[Define is getgroups(0, NULL) works on your system])

],[AC_MSG_RESULT(no)

],[AC_MSG_RESULT(suppose that it doesnt)])

 

AC_MSG_CHECKING(whether realpath likes unreadable directories)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#ifdef STDC_HEADERS

# include <stdlib.h>

# include <stddef.h>

#else

# if HAVE_STDLIB_H

#  include <stdlib.h>

# endif

#endif

#include <sys/types.h>

#include <sys/stat.h>

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#ifdef HAVE_LIMITS_H

# include <limits.h>

#endif

#ifdef HAVE_SYS_PARAM_H

# include <sys/param.h>

#endif

 

#ifndef PATH_MAX

# define PATH_MAX MAXPATHLEN

#endif

 

int main(void)

{

    char x[PATH_MAX];

   

    if (mkdir("x", 0300) != 0) {

        return 1;

    }

    if (mkdir("x/y", 0300) != 0) {

        rmdir("x");

        return 2;

    }   

    if (chdir("x") != 0) {

        rmdir("x/y");   

        rmdir("x");

        return 3;

    }

    if (realpath("y", x) == NULL) {

        rmdir("y");

        rmdir("../x");

        return 4;

    }

    rmdir("y");

    rmdir("../x");

   

    return 0;   

}

]])],[

AC_MSG_RESULT(yes)

AC_DEFINE(REALPATH_WORKS_WITH_UNREADABLE_DIRECTORIES,,

[Define if realpath() works on unreadable directories])

],[AC_MSG_RESULT(no)

AC_DEFINE(USE_BUILTIN_REALPATH)

],[AC_MSG_RESULT(no)

AC_DEFINE(USE_BUILTIN_REALPATH)])

 

AC_MSG_CHECKING(whether you already have a standard MD5 implementation)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <md5.h>

 

int main(void)

{

    MD5_CTX ctx;

    char b[33];

   

    MD5Init(&ctx);

    MD5Update(&ctx, (const unsigned char *) "test", 4U);

    MD5End(&ctx, b);

    b[32] = 0;

 

    return strcasecmp(b, "098f6bcd4621d373cade4e832627b4f6");

}

]])],[

AC_MSG_RESULT(yes)

AC_DEFINE(USE_SYSTEM_CRYPT_MD5,,[Define if you already have standard

MD5 functions])

],[AC_MSG_RESULT(no)

],[AC_MSG_RESULT(assuming no)])

 

AC_MSG_CHECKING(whether you already have a standard SHA1 implementation)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sha1.h>

 

int main(void)

{

    SHA1_CTX ctx;

    char b[41];

   

    SHA1Init(&ctx);

    SHA1Update(&ctx, (const unsigned char *) "test", 4U);

    SHA1End(&ctx, b);

    b[40] = 0;

   

    return strcasecmp(b, "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");

}

]])],[

AC_MSG_RESULT(yes)

AC_DEFINE(USE_SYSTEM_CRYPT_SHA1,,[Define if you already have standard

SHA1 functions])

],[AC_MSG_RESULT(no)

],[AC_MSG_RESULT(assuming no)])

 

AC_MSG_CHECKING([whether we are inside a Virtuozzo virtual host])

if test -d /proc/vz; then

  AC_MSG_RESULT(yes)

  AC_DEFINE(VIRTUOZZO,,[Define if you are inside a Virtuozzo virtual

host])

else

  AC_MSG_RESULT(no)

fi

 

AC_MSG_CHECKING(default TCP send buffer size)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#ifdef STDC_HEADERS

# include <stdlib.h>

# include <stddef.h>

#else

# if HAVE_STDLIB_H

#  include <stdlib.h>

# endif

#endif

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

int main(void)

{

    int fd,val=0,len=sizeof(int);

    if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) return 1;

        if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) return 1;

    if (val <= 0) return 1;

        fprintf (fopen("conftestval", "w"), "%d\n", val);

    return 0;

}

]])],[CONF_TCP_SO_SNDBUF=`cat conftestval`],[CONF_TCP_SO_SNDBUF=65536],[CONF_TCP_SO_SNDBUF=65536])

AC_MSG_RESULT($CONF_TCP_SO_SNDBUF)

 

AC_DEFINE_UNQUOTED(CONF_TCP_SO_SNDBUF, $CONF_TCP_SO_SNDBUF, [default TCP send buffer])

 

AC_MSG_CHECKING(default TCP receive buffer size)

AC_RUN_IFELSE([AC_LANG_SOURCE([[

#include <stdio.h>

#ifdef STDC_HEADERS

# include <stdlib.h>

# include <stddef.h>

#else

# if HAVE_STDLIB_H

#  include <stdlib.h>

# endif

#endif

#ifdef HAVE_UNISTD_H

# include <unistd.h>

#endif

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

int main(void)

{

    int fd,val=0,len=sizeof(int);

    if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) return 1;

        if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) return 1;

    if (val <= 0) return 1;

        fprintf (fopen("conftestval", "w"), "%d\n", val);

    return 0;

}

]])],[CONF_TCP_SO_RCVBUF=`cat conftestval`],[CONF_TCP_SO_RCVBUF=65536],[CONF_TCP_SO_RCVBUF=65536])

AC_MSG_RESULT($CONF_TCP_SO_RCVBUF)

 

AC_DEFINE_UNQUOTED(CONF_TCP_SO_RCVBUF, $CONF_TCP_SO_RCVBUF, [defaut TCP receive buffer])

 

 

AC_ARG_WITH(ldap,

[AS_HELP_STRING(--with-ldap,Users database is an LDAP directory (see doc))],

[ if test "x$withval" != "xno" ; then

    if test "x$withval" != "x" && test "x$withval" != "xyes" ; then

      LD_RUN_PATH="${withval}/lib${LD_RUN_PATH:+:}${LD_RUN_PATH}"

      LDFLAGS="$LDFLAGS -L${withval}/lib"

      CPPFLAGS="$CPPFLAGS -I${withval}/include"

    fi

    with_ldap="yes"

    AC_DEFINE(WITH_LDAP,,[with ldap])

    AC_CHECK_LIB(resolv, res_query)

    AC_CHECK_LIB(lber, ber_init, ,

    [AC_MSG_ERROR(liblber is needed for LDAP support)])

    AC_CHECK_LIB(ldap, ldap_init, ,

     [AC_MSG_WARN(Initial check for -lldap failed! May need -lssl -lcrypto)

      AC_CHECK_LIB(ldap, ldap_bind, [ldap_ssl_libs=true],

      [AC_MSG_ERROR(libldap is needed for LDAP support)], -lssl -lcrypto)

     ])

    if test "x$ldap_ssl_libs" = "xtrue" ; then

      LDAP_SSL_LIBS='-lssl -lcrypto'

    fi

  fi ])

 

AC_SUBST(LDAP_SSL_LIBS)

 

AC_ARG_WITH(mysql,

[AS_HELP_STRING(--with-mysql,Users database is a MySQL database (see doc))],

[ if test "x$withval" != "xno" ; then

    if test "x$withval" != "x" && test "x$withval" != "xyes" ; then

      LD_RUN_PATH="${withval}/lib${LD_RUN_PATH:+:}${LD_RUN_PATH}"   

      LDFLAGS="$LDFLAGS -L${withval}/lib -L${withval}/lib/mysql -L${withval}/mysql/lib"

      CPPFLAGS="$CPPFLAGS -I${withval}/include -I${withval}/include/mysql -I${withval}/mysql/include"

    else

      CFLAGS="$CFLAGS `mariadb_config --cflags 2> /dev/null || mysql_config --cflags`"

      LDFLAGS="$LDFLAGS `mariadb_config --libs 2> /dev/null || mysql_config --libs`"

    fi

    AC_CHECK_LIB(m, floor)

    AC_CHECK_LIB(z, gzclose)

    with_mysql="yes"

    AC_DEFINE(WITH_MYSQL,,[with mysql])

    AC_CHECK_FUNC(mysql_init, , [

      AC_CHECK_LIB(mariadb, mysql_init, , [

        AC_CHECK_LIB(mysqlclient, mysql_init, ,

          [AC_MSG_ERROR(libmysqlclient is needed for MySQL support)])

      ])

    ])

    AC_MSG_CHECKING(whether mysql clients can run)

    AC_RUN_IFELSE([AC_LANG_SOURCE([[

      #include <stdio.h>

      #include <mysql.h>   

      int main(void)

      {

          MYSQL *a = mysql_init(NULL);

          return 0;

      }

      ]])],[],[

        AC_MSG_RESULT(no)

        AC_MSG_ERROR(Your MySQL client libraries aren't properly installed)

    ],[])

    AC_MSG_RESULT(yes)

  fi ])

 

AC_ARG_WITH(pgsql,

[AS_HELP_STRING(--with-pgsql,Users database is a PostgreSQL database (see doc))],

[ if test "x$withval" != "xno" ; then

    if test "x$withval" != "x" && test "x$withval" != "xyes" ; then

      LD_RUN_PATH="${withval}/lib${LD_RUN_PATH:+:}${LD_RUN_PATH}"

      LDFLAGS="$LDFLAGS -L${withval}/lib -L${withval}/lib/pgsql -L${withval}/lib/postgresql -L${withval}/pgsql/lib -L${withval}/postgresql/lib"

      CPPFLAGS="$CPPFLAGS -I${withval}/include -I${withval}/include/pgsql -I${withval}/include/postgresql -I${withval}/pgsql/include -I${withval}/postgresql/include"

    else

      LD_RUN_PATH="`pg_config --libdir`${LD_RUN_PATH:+:}${LD_RUN_PATH}"

      CPPFLAGS="$CPPFLAGS -I`pg_config --includedir`"

      LDFLAGS="$LDFLAGS -L`pg_config --libdir`"

    fi

    AC_CHECK_LIB(m, floor)

    AC_CHECK_LIB(z, gzclose)

    with_pgsql="yes"

    AC_DEFINE(WITH_PGSQL,,[with pgsql])

    AC_CHECK_LIB(pq, PQconnectdb, ,

      [AC_MSG_ERROR(libpq is needed for PostgreSQL support)])       

    AC_MSG_CHECKING(whether postgresql clients can run)

    AC_RUN_IFELSE([AC_LANG_SOURCE([[

      #include <stdio.h>

      #include <libpq-fe.h>

      int main(void)

      {

          PGconn *a = PQconnectdb("");

          return 0;

      }

      ]])],[],[

        AC_MSG_RESULT(no)

        AC_MSG_ERROR(Your PostgreSQL client libraries aren't properly installed)     

    ],[])   

    AC_MSG_RESULT(yes)

  fi ])

 

AC_ARG_WITH(tls,

[AS_HELP_STRING(--with-tls,Enable TLS support)],

[ if test "x$withval" = "xyes" ; then

    with_tls="yes"

  fi ])

 

if test "x$with_tls" = "xyes" ; then

  if test "x$ac_cv_header_openssl_ssl_h" != "xyes" ; then

    AC_MSG_ERROR(OpenSSL headers not found.) 

  fi

  AC_CHECK_LIB(crypto, DH_new)

  AC_CHECK_LIB(ssl, SSL_accept)

  AC_CHECK_FUNCS(DH_get_2048_256)

  AC_DEFINE(WITH_TLS,,[Enable TLS])

fi

 

AC_ARG_WITH(certfile,

[AS_HELP_STRING(--with-certfile=,certificate file (default: /etc/ssl/private/pure-ftpd.pem))],

[ if test "x$withval" != "x" ; then

    certfile="$withval"

    AC_SUBST(certfile)

    CPPFLAGS="$CPPFLAGS -DTLS_CERTIFICATE_FILE='\"$certfile\"'"

    if test ! -e "$certfile"; then

      AC_MSG_WARN(No certificate is installed in $certfile yet)

    fi

  fi ])

 

AC_ARG_WITH(rfc2640,

[AS_HELP_STRING(--with-rfc2640,Enable RFC 2640 (UTF-8 encoding for file names) support (needs iconv))],

[ if test "x$withval" = "xyes" ; then

    with_rfc2640="yes"

  fi ])

 

if test "x$with_rfc2640" = "xyes" ; then

  if test "x$ac_cv_header_iconv_h" != "xyes" ; then

    AC_MSG_ERROR(iconv headers not found.) 

  fi

  AC_CHECK_LIB(iconv, iconv_open)

  AC_CHECK_LIB(iconv, libiconv_open)

  AC_DEFINE(WITH_RFC2640,,[Enable RFC2640 (UTF-8) support])

fi

 

AC_ARG_WITH(bonjour,

[AS_HELP_STRING(--with-bonjour,Enable Bonjour support on MacOS X)],

[ if test "x$withval" = "xyes" ; then

    with_bonjour="yes"

  fi ])

 

if test "x$with_bonjour" = "xyes" ; then

  if test "x$ac_cv_header_CoreFoundation_CoreFoundation_h" = "xyes" ; then

    AC_DEFINE(WITH_BONJOUR,,[Enable Bonjour on MacOS X])

    BONJOUR_LDADD='-framework CoreFoundation -framework CoreServices'

  fi

fi

 

AC_SUBST(BONJOUR_LDADD)

 

if test "x$sysconfdir" = 'xNONE' || test "x$sysconfdir" = 'x'; then

  CONFDIR='/etc'

else

  if test "x$sysconfdir" = 'x${prefix}/etc'; then

    if test "x$prefix" = 'xNONE' || test "x$prefix" = 'x/usr'; then

      CONFDIR='/etc'

    else

      CONFDIR="$sysconfdir"

    fi

  else

    CONFDIR="$sysconfdir"

  fi

fi 

 

if test "x$localstatedir" = 'xNONE' || test "x$localstatedir" = 'x'; then

  LOCALSTATEDIR='/var'

else

  if test "x$localstatedir" = 'x${prefix}/var'; then

    if test "x$prefix" = 'xNONE' || test "x$prefix" = 'x/usr' || test "x$localstatedir" = 'x${prefix}/var' ; then

      LOCALSTATEDIR='/var'

    else

      LOCALSTATEDIR="$localstatedir"

    fi

  else

    LOCALSTATEDIR="$localstatedir"

  fi

fi 

 

if test -r /dev/urandom; then

  AC_MSG_NOTICE([You have /dev/urandom - Great])

  AC_DEFINE(HAVE_DEV_URANDOM,,[Define if you have /dev/urandom])

fi

if test -r /dev/random; then

  AC_MSG_NOTICE([You have /dev/random - Great])

  AC_DEFINE(HAVE_DEV_RANDOM,,[Define if you have /dev/random])

fi

 

CONFDIR=`eval echo "$CONFDIR"`

LOCALSTATEDIR=`eval echo "$LOCALSTATEDIR"`

 

sysconfdir="$CONFDIR"

AC_SUBST(sysconfdir)

localstatedir="$LOCALSTATEDIR"

AC_SUBST(localstatedir)

 

CPPFLAGS="$CPPFLAGS -DCONFDIR=\\\"$sysconfdir\\\""

CPPFLAGS="$CPPFLAGS -DSTATEDIR=\\\"$localstatedir\\\""

 

AC_SUBST(CONFDIR)

AC_SUBST(LOCALSTATEDIR)

 

AH_VERBATIM([NDEBUG], [/* Never ever ignore assertions */

#ifdef NDEBUG

#/**/undef/**/ NDEBUG

#endif])

 

 

增加输出文件。

AC_CONFIG_FILES([Makefile

                 gui/Makefile

                 m4/Makefile

                 man/Makefile

                 pam/Makefile

                 puredb/Makefile

                 puredb/src/Makefile

                 src/Makefile

                 pure-ftpd.conf

                 man/pure-ftpd.8

                 man/pure-ftpwho.8

                 man/pure-mrtginfo.8

                 man/pure-uploadscript.8

                 man/pure-statsdecode.8

                 man/pure-quotacheck.8

                 man/pure-pw.8

                 man/pure-pwconvert.8

                 man/pure-authd.8

])

 

 

输出configure消息信息

AC_MSG_NOTICE([+--------------------------------------------------------+])

AC_MSG_NOTICE([| You can subscribe to the Pure-FTPd users mailing-list  |])

AC_MSG_NOTICE([| to ask for help and to stay informed of new releases.  |])

AC_MSG_NOTICE([| Go to http://www.pureftpd.org/ml/ now!                 |])

AC_MSG_NOTICE([+--------------------------------------------------------+])