"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/make-config.sh" (8 Aug 2018, 90335 Bytes) of package /linux/misc/s-nail-14.9.11.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "make-config.sh": 14.9.10_vs_14.9.11.

    1 #!/bin/sh -
    2 #@ Please see INSTALL and make.rc instead.
    3 
    4 LC_ALL=C
    5 export LC_ALL
    6 
    7 # For heaven's sake auto-redirect on SunOS/Solaris
    8 if [ "x${SHELL}" = x ] || [ "${SHELL}" = /bin/sh ] && \
    9       [ -f /usr/xpg4/bin/sh ] && [ -x /usr/xpg4/bin/sh ]; then
   10    SHELL=/usr/xpg4/bin/sh
   11    export SHELL
   12    exec /usr/xpg4/bin/sh "${0}" "${@}"
   13 fi
   14 [ -n "${SHELL}" ] || SHELL=/bin/sh
   15 export SHELL
   16 
   17 # The feature set, to be kept in sync with make.rc
   18 # If no documentation given, the option is used as such; if doc is a hyphen,
   19 # entry is suppressed when configuration overview is printed, and also in the
   20 # *features* string: most likely for obsolete features etc.
   21 XOPTIONS="\
   22    ICONV='Character set conversion using iconv(3)' \
   23    MAILDIR='Maildir E-mail directories' \
   24    SOCKETS='Network support' \
   25       TLS='Transport Layer Security (OpenSSL / LibreSSL)' \
   26          TLS_ALL_ALGORITHMS='Support of all digest and cipher algorithms' \
   27       SMTP='Simple Mail Transfer Protocol client' \
   28       POP3='Post Office Protocol Version 3 client' \
   29       IMAP='IMAP v4r1 client' \
   30       GSSAPI='Generic Security Service authentication' \
   31       NETRC='.netrc file support' \
   32       AGENT='-' \
   33       MD5='MD5 message digest (APOP, CRAM-MD5)' \
   34    IDNA='Internationalized Domain Names for Applications (encode only)' \
   35    IMAP_SEARCH='IMAP-style search expressions' \
   36    REGEX='Regular expressions' \
   37    MLE='Mailx Line Editor' \
   38       HISTORY='Line editor history management' \
   39       KEY_BINDINGS='Configurable key bindings' \
   40    TERMCAP='Terminal capability queries (termcap(5))' \
   41       TERMCAP_VIA_TERMINFO='Terminal capability queries use terminfo(5)' \
   42    ERRORS='Log message ring' \
   43    SPAM_SPAMC='Spam management via spamc(1) of spamassassin(1)' \
   44    SPAM_SPAMD='-' \
   45    SPAM_FILTER='Freely configurable *spam-filter-..*s' \
   46    DOCSTRINGS='Command documentation help strings' \
   47    UISTRINGS='User interface and error message strings' \
   48    QUOTE_FOLD='Extended *quote-fold*ing' \
   49    FILTER_HTML_TAGSOUP='Simple built-in HTML-to-text display filter' \
   50    COLOUR='Coloured message display' \
   51    DOTLOCK='Dotlock files and privilege-separated dotlock program' \
   52 "
   53 
   54 # Options which are automatically deduced from host environment, i.e., these
   55 # need special treatment all around here to warp from/to OPT_ stuff
   56 # setlocale, C90AMEND1, NL_LANGINFO, wcwidth
   57 XOPTIONS_DETECT="\
   58    LOCALES='Locale support - printable characters etc. depend on environment' \
   59    MULTIBYTE_CHARSETS='Multibyte character sets' \
   60    TERMINAL_CHARSET='Automatic detection of terminal character set' \
   61    WIDE_GLYPHS='Wide glyph support' \
   62 "
   63 
   64 # Rather special options, for custom building, or which always exist.
   65 # Mostly for generating the visual overview and the *features* string
   66 XOPTIONS_XTRA="\
   67    MIME='Multipurpose Internet Mail Extensions' \
   68    SMIME='S/MIME message signing, verification, en- and decryption' \
   69    CROSS_BUILD='Cross-compilation: trust any detected environment' \
   70    DEBUG='Debug enabled binary, not for end-users: THANKS!' \
   71    DEVEL='Computers do not blunder' \
   72 "
   73 
   74 # To avoid too many recompilations we use a two-stage "configuration changed"
   75 # detection, the first uses mk-config.lst, which only goes for actual user
   76 # config settings etc. the second uses mk-config.h, which thus includes the
   77 # things we have truly detected.  This does not work well for multiple choice
   78 # values of which only one will be really used, so those user wishes may not be
   79 # placed in the header, only the really detected one (but that has to!).
   80 # Used for grep(1), for portability assume fixed matching only.
   81 H_BLACKLIST='-e VAL_RANDOM -e VAL_IDNA'
   82 
   83 # The problem is that we don't have any tools we can use right now, so
   84 # encapsulate stuff in functions which get called in right order later on
   85 
   86 option_reset() {
   87    set -- ${OPTIONS}
   88    for i
   89    do
   90       eval OPT_${i}=0
   91    done
   92 }
   93 
   94 option_maximal() {
   95    set -- ${OPTIONS}
   96    for i
   97    do
   98       eval OPT_${i}=1
   99    done
  100    OPT_DOTLOCK=require OPT_ICONV=require OPT_REGEX=require
  101 }
  102 
  103 option_setup() {
  104    option_parse OPTIONS_DETECT "${XOPTIONS_DETECT}"
  105    option_parse OPTIONS "${XOPTIONS}"
  106    option_parse OPTIONS_XTRA "${XOPTIONS_XTRA}"
  107    OPT_MIME=1
  108 
  109    # Predefined CONFIG= urations take precedence over anything else
  110    if [ -n "${CONFIG}" ]; then
  111       option_reset
  112       case "${CONFIG}" in
  113       [nN][uU][lL][lL])
  114          ;;
  115       [nN][uU][lL][lL][iI])
  116          OPT_ICONV=require
  117          OPT_UISTRINGS=1
  118          ;;
  119       [mM][iI][nN][iI][mM][aA][lL])
  120          OPT_DOTLOCK=require OPT_ICONV=require OPT_REGEX=require
  121          OPT_COLOUR=1
  122          OPT_DOCSTRINGS=1
  123          OPT_UISTRINGS=1
  124          OPT_ERRORS=1
  125          OPT_IDNA=1
  126          OPT_MAILDIR=1
  127          OPT_MLE=1
  128             OPT_HISTORY=1 OPT_KEY_BINDINGS=1
  129          OPT_SPAM_FILTER=1
  130          ;;
  131       [nN][eE][tT][sS][eE][nN][dD])
  132          OPT_DOTLOCK=require OPT_ICONV=require OPT_REGEX=require
  133          OPT_SOCKETS=require
  134             OPT_TLS=require
  135             OPT_SMTP=require
  136             OPT_GSSAPI=1 OPT_NETRC=1
  137                OPT_AGENT=1
  138          OPT_COLOUR=1
  139          OPT_DOCSTRINGS=1
  140          OPT_UISTRINGS=1
  141          OPT_ERRORS=1
  142          OPT_IDNA=1
  143          OPT_MAILDIR=1
  144          OPT_MLE=1
  145             OPT_HISTORY=1 OPT_KEY_BINDINGS=1
  146          OPT_SPAM_FILTER=1
  147          ;;
  148       [mM][aA][xX][iI][mM][aA][lL])
  149          option_maximal
  150          ;;
  151       [dD][eE][vV][eE][lL])
  152          option_maximal
  153          OPT_DEVEL=1 OPT_DEBUG=1 OPT_NYD2=1
  154          ;;
  155       [oO][dD][eE][vV][eE][lL])
  156          option_maximal
  157          OPT_DEVEL=1
  158          ;;
  159       *)
  160          echo >&2 "Unknown CONFIG= setting: ${CONFIG}"
  161          echo >&2 '   NULL, NULLI, MINIMAL, NETSEND, MAXIMAL'
  162          exit 1
  163          ;;
  164       esac
  165       msg_nonl "CONFIG=${CONFIG} ... "
  166    fi
  167 }
  168 
  169 # Inter-relationships XXX sort this!
  170 option_update() {
  171    if feat_no TLS; then
  172       OPT_TLS_ALL_ALGORITHMS=0
  173    fi
  174 
  175    if feat_no SMTP && feat_no POP3 && feat_no IMAP; then
  176       OPT_SOCKETS=0
  177    fi
  178    if feat_no SOCKETS; then
  179       if feat_require SMTP; then
  180          msg 'ERROR: need SOCKETS for required feature SMTP'
  181          config_exit 13
  182       fi
  183       if feat_require POP3; then
  184          msg 'ERROR: need SOCKETS for required feature POP3'
  185          config_exit 13
  186       fi
  187       if feat_require IMAP; then
  188          msg 'ERROR: need SOCKETS for required feature IMAP'
  189          config_exit 13
  190       fi
  191       OPT_TLS=0 OPT_TLS_ALL_ALGORITHMS=0
  192       OPT_SMTP=0 OPT_POP3=0 OPT_IMAP=0
  193       OPT_GSSAPI=0 OPT_NETRC=0 OPT_AGENT=0
  194    fi
  195    if feat_no SMTP && feat_no IMAP; then
  196       OPT_GSSAPI=0
  197    fi
  198 
  199    if feat_no ICONV; then
  200       if feat_yes IMAP; then
  201          if feat_yes ALWAYS_UNICODE_LOCALE; then
  202             msg 'WARN: no ICONV, keeping IMAP due to ALWAYS_UNICODE_LOCALE!'
  203          elif feat_require IMAP; then
  204             msg 'ERROR: need ICONV for required feature IMAP'
  205             config_exit 13
  206          else
  207             msg 'ERROR: disabling IMAP due to missing ICONV'
  208             OPT_IMAP=0
  209          fi
  210       fi
  211 
  212       if feat_yes IDNA; then
  213          if feat_require IDNA; then
  214             msg 'ERROR: need ICONV for required feature IDNA'
  215             config_exit 13
  216          fi
  217          msg 'ERROR: disabling IDNA due to missing ICONV'
  218          OPT_IDNA=0
  219       fi
  220    fi
  221 
  222    if feat_no MLE; then
  223       OPT_HISTORY=0 OPT_KEY_BINDINGS=0
  224    fi
  225 
  226    # If we don't need MD5 leave it alone
  227    if feat_no SOCKETS; then
  228       OPT_MD5=0
  229    fi
  230 
  231    if feat_no TERMCAP; then
  232       OPT_TERMCAP_VIA_TERMINFO=0
  233    fi
  234 
  235    if feat_yes DEVEL; then
  236       OPT_DEBUG=1
  237    fi
  238 }
  239 
  240 rc=./make.rc
  241 lst=.obj/mk-config.lst
  242 ev=.obj/mk-config.ev
  243 h=.obj/mk-config.h h_name=mk-config.h
  244 mk=.obj/mk-config.mk
  245 
  246 newlst=.obj/mk-nconfig.lst
  247 newmk=.obj/mk-nconfig.mk
  248 oldmk=.obj/mk-oconfig.mk
  249 newev=.obj/mk-nconfig.ev
  250 newh=.obj/mk-nconfig.h
  251 oldh=.obj/mk-oconfig.h
  252 tmp0=.obj/___tmp
  253 tmp=${tmp0}1$$
  254 tmp2=${tmp0}2$$
  255 
  256 ##  --  >8  - << OPTIONS | OS/CC >> -  8<  --  ##
  257 
  258 # Note that potential duplicates in PATH, C_INCLUDE_PATH etc. will be cleaned
  259 # via path_check() later on once possible
  260 
  261 COMMLINE="${*}"
  262 
  263 # TODO cc_maxopt is brute simple, we should compile test program and dig real
  264 # compiler versions for known compilers, then be more specific
  265 [ -n "${cc_maxopt}" ] || cc_maxopt=100
  266 #cc_force_no_stackprot=
  267 #ld_need_R_flags=
  268 #ld_no_bind_now=
  269 #ld_rpath_not_runpath=
  270 
  271 _CFLAGS= _LDFLAGS=
  272 
  273 os_early_setup() {
  274    # We don't "have any utility" (see make.rc)
  275    [ -n "${OS}" ] && [ -n "${OSFULLSPEC}" ] ||
  276       thecmd_testandset_fail uname uname
  277 
  278    [ -n "${OS}" ] || OS=`${uname} -s`
  279    export OS
  280    msg 'Operating system is %s' "${OS}"
  281 
  282    if [ ${OS} = SunOS ]; then
  283       # According to standards(5), this is what we need to do
  284       if [ -d /usr/xpg4 ]; then :; else
  285          msg 'ERROR: On SunOS / Solaris we need /usr/xpg4 environment!  Sorry.'
  286          config_exit 1
  287       fi
  288       PATH="/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:${PATH}"
  289       [ -d /usr/xpg6 ] && PATH="/usr/xpg6/bin:${PATH}"
  290       export PATH
  291    fi
  292 }
  293 
  294 os_setup() {
  295    # OSFULLSPEC is used to recognize changes (i.e., machine type, updates
  296    # etc.), it is not baked into the binary
  297    [ -n "${OSFULLSPEC}" ] || OSFULLSPEC=`${uname} -a`
  298 
  299    if [ ${OS} = darwin ]; then
  300       msg ' . have special Darwin environmental addons...'
  301       LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${DYLD_LIBRARY_PATH}
  302    elif [ ${OS} = sunos ]; then
  303       msg ' . have special SunOS / Solaris "setup" rules ...'
  304       _os_setup_sunos
  305    elif [ ${OS} = unixware ]; then
  306       if feat_yes AUTOCC && acmd_set CC cc; then
  307          msg ' . have special UnixWare environmental rules ...'
  308          feat_yes DEBUG && _CFLAGS='-v -Xa -g' || _CFLAGS='-Xa -O'
  309 
  310          CFLAGS="${_CFLAGS} ${EXTRA_CFLAGS}"
  311          LDFLAGS="${_LDFLAGS} ${EXTRA_LDFLAGS}"
  312          export CC CFLAGS LDFLAGS
  313          OPT_AUTOCC=0 ld_need_R_flags=-R
  314       fi
  315    elif [ -n "${VERBOSE}" ]; then
  316       msg ' . no special treatment for this system necessary or known'
  317    fi
  318 
  319    # Sledgehammer: better set _GNU_SOURCE
  320    # And in general: oh, boy!
  321    OS_DEFINES="${OS_DEFINES}#define _GNU_SOURCE\n"
  322    #OS_DEFINES="${OS_DEFINES}#define _POSIX_C_SOURCE 200809L\n"
  323    #OS_DEFINES="${OS_DEFINES}#define _XOPEN_SOURCE 700\n"
  324    #[ ${OS} = darwin ] && OS_DEFINES="${OS_DEFINES}#define _DARWIN_C_SOURCE\n"
  325 
  326    # On pkgsrc(7) systems automatically add /usr/pkg/*
  327    if [ -d /usr/pkg ] && feat_yes USE_PKGSYS; then
  328       msg ' . found pkgsrc(7), merging C_INCLUDE_PATH and LD_LIBRARY_PATH'
  329       C_INCLUDE_PATH=/usr/pkg/include:${C_INCLUDE_PATH}
  330       LD_LIBRARY_PATH=/usr/pkg/lib:${LD_LIBRARY_PATH}
  331       ld_rpath_not_runpath=1
  332    fi
  333 }
  334 
  335 _os_setup_sunos() {
  336    C_INCLUDE_PATH=/usr/xpg4/include:${C_INCLUDE_PATH}
  337    LD_LIBRARY_PATH=/usr/xpg4/lib:${LD_LIBRARY_PATH}
  338 
  339    # Include packages
  340    if [ -d /opt/csw ] && feat_yes USE_PKGSYS; then
  341       msg ' . found OpenCSW PKGSYS, merging C_INCLUDE_PATH and LD_LIBRARY_PATH'
  342       C_INCLUDE_PATH=/opt/csw/include:${C_INCLUDE_PATH}
  343       LD_LIBRARY_PATH=/opt/csw/lib:${LD_LIBRARY_PATH}
  344       ld_no_bind_now=1 ld_rpath_not_runpath=1
  345    fi
  346    if [ -d /opt/schily ] && feat_yes USE_PKGSYS; then
  347       msg ' . found Schily PKGSYS, merging C_INCLUDE_PATH and LD_LIBRARY_PATH'
  348       C_INCLUDE_PATH=/opt/schily/include:${C_INCLUDE_PATH}
  349       LD_LIBRARY_PATH=/opt/schily/lib:${LD_LIBRARY_PATH}
  350       ld_no_bind_now=1 ld_rpath_not_runpath=1
  351    fi
  352 
  353    OS_DEFINES="${OS_DEFINES}#define __EXTENSIONS__\n"
  354    #OS_DEFINES="${OS_DEFINES}#define _POSIX_C_SOURCE 200112L\n"
  355 
  356    if feat_yes AUTOCC; then
  357       if acmd_set CC cc; then
  358          feat_yes DEBUG && _CFLAGS="-v -Xa -g" || _CFLAGS="-Xa -O"
  359 
  360          CFLAGS="${_CFLAGS} ${EXTRA_CFLAGS}"
  361          LDFLAGS="${_LDFLAGS} ${EXTRA_LDFLAGS}"
  362          export CC CFLAGS LDFLAGS
  363          OPT_AUTOCC=0 ld_need_R_flags=-R
  364       else
  365          cc_maxopt=2 cc_force_no_stackprot=1
  366       fi
  367    fi
  368 }
  369 
  370 # Check out compiler ($CC) and -flags ($CFLAGS)
  371 cc_setup() {
  372    # Even though it belongs into cc_flags we will try to compile and link
  373    # something, so ensure we have a clean state regarding CFLAGS/LDFLAGS or
  374    # EXTRA_CFLAGS/EXTRA_LDFLAGS
  375    if feat_no AUTOCC; then
  376       _cc_default
  377       # Ensure those don't do any harm
  378       EXTRA_CFLAGS= EXTRA_LDFLAGS=
  379       export EXTRA_CFLAGS EXTRA_LDFLAGS
  380       return
  381    else
  382       CFLAGS= LDFLAGS=
  383       export CFLAGS LDFLAGS
  384    fi
  385 
  386    [ -n "${CC}" ] && { _cc_default; return; }
  387 
  388    msg_nonl 'Searching for a usable C compiler .. $CC='
  389    if acmd_set CC clang || acmd_set CC gcc ||
  390          acmd_set CC tcc || acmd_set CC pcc ||
  391          acmd_set CC c89 || acmd_set CC c99; then
  392       :
  393    else
  394       msg 'boing booom tschak'
  395       msg 'ERROR: I cannot find a compiler!'
  396       msg ' Neither of clang(1), gcc(1), tcc(1), pcc(1), c89(1) and c99(1).'
  397       msg ' Please set ${CC} environment variable, maybe ${CFLAGS}, rerun.'
  398       config_exit 1
  399    fi
  400    msg '%s' "${CC}"
  401    export CC
  402 }
  403 
  404 _cc_default() {
  405    if [ -z "${CC}" ]; then
  406       msg 'To go on like you have chosen, please set $CC, rerun.'
  407       config_exit 1
  408    fi
  409 
  410    if [ -z "${VERBOSE}" ] && [ -f ${lst} ] && feat_no DEBUG; then
  411       :
  412    else
  413       msg 'Using C compiler ${CC}=%s' "${CC}"
  414    fi
  415 }
  416 
  417 cc_flags() {
  418    if feat_yes AUTOCC; then
  419       if [ -f ${lst} ] && feat_no DEBUG && [ -z "${VERBOSE}" ]; then
  420          cc_check_silent=1
  421          msg 'Detecting ${CFLAGS}/${LDFLAGS} for ${CC}=%s, just a second..' \
  422             "${CC}"
  423       else
  424          cc_check_silent=
  425          msg 'Testing usable ${CFLAGS}/${LDFLAGS} for ${CC}=%s' "${CC}"
  426       fi
  427 
  428       i=`echo "${CC}" | ${awk} 'BEGIN{FS="/"}{print $NF}'`
  429       if { echo "${i}" | ${grep} tcc; } >/dev/null 2>&1; then
  430          msg ' . have special tcc(1) environmental rules ...'
  431          _cc_flags_tcc
  432       else
  433          # As of pcc CVS 2016-04-02, stack protection support is announced but
  434          # will break if used on Linux
  435          if { echo "${i}" | ${grep} pcc; } >/dev/null 2>&1; then
  436             cc_force_no_stackprot=1
  437          fi
  438          _cc_flags_generic
  439       fi
  440 
  441       feat_no DEBUG && _CFLAGS="-DNDEBUG ${_CFLAGS}"
  442       CFLAGS="${_CFLAGS} ${EXTRA_CFLAGS}"
  443       LDFLAGS="${_LDFLAGS} ${EXTRA_LDFLAGS}"
  444    else
  445       if feat_no DEBUG; then
  446          CFLAGS="-DNDEBUG ${CFLAGS}"
  447       fi
  448    fi
  449    export CFLAGS LDFLAGS
  450 }
  451 
  452 _cc_flags_tcc() {
  453    __cflags=${_CFLAGS} __ldflags=${_LDFLAGS}
  454    _CFLAGS= _LDFLAGS=
  455 
  456    cc_check -W
  457    cc_check -Wall
  458    cc_check -Wextra
  459    cc_check -pedantic
  460 
  461    if feat_yes DEBUG; then
  462       # May have problems to find libtcc cc_check -b
  463       cc_check -g
  464    fi
  465 
  466    if ld_check -Wl,-rpath =./ no; then
  467       ld_need_R_flags=-Wl,-rpath=
  468       if [ -z "${ld_rpath_not_runpath}" ]; then
  469          ld_check -Wl,--enable-new-dtags
  470       else
  471          msg ' ! $LD_LIBRARY_PATH adjusted, not trying --enable-new-dtags'
  472       fi
  473       ld_runtime_flags # update!
  474    fi
  475 
  476    _CFLAGS="${_CFLAGS} ${__cflags}" _LDFLAGS="${_LDFLAGS} ${__ldflags}"
  477    unset __cflags __ldflags
  478 }
  479 
  480 _cc_flags_generic() {
  481    __cflags=${_CFLAGS} __ldflags=${_LDFLAGS}
  482    _CFLAGS= _LDFLAGS=
  483    feat_yes DEVEL && cc_check -std=c89 || cc_check -std=c99
  484 
  485    # E.g., valgrind does not work well with high optimization
  486    if [ ${cc_maxopt} -gt 1 ] && feat_yes NOMEMDBG &&
  487          feat_no ASAN_ADDRESS && feat_no ASAN_MEMORY; then
  488       msg ' ! OPT_NOMEMDBG, setting cc_maxopt=1 (-O1)'
  489       cc_maxopt=1
  490    fi
  491    # Check -g first since some others may rely upon -g / optim. level
  492    if feat_yes DEBUG; then
  493       cc_check -O
  494       cc_check -g
  495    elif [ ${cc_maxopt} -gt 2 ] && cc_check -O3; then
  496       :
  497    elif [ ${cc_maxopt} -gt 1 ] && cc_check -O2; then
  498       :
  499    elif [ ${cc_maxopt} -gt 0 ] && cc_check -O1; then
  500       :
  501    else
  502       cc_check -O
  503    fi
  504 
  505    if feat_yes AMALGAMATION; then
  506       cc_check -pipe
  507    fi
  508 
  509    #if feat_yes DEVEL && cc_check -Weverything; then
  510    #   :
  511    #else
  512       cc_check -W
  513       cc_check -Wall
  514       cc_check -Wextra
  515       cc_check -Wbad-function-cast
  516       cc_check -Wcast-align
  517       cc_check -Wcast-qual
  518       cc_check -Winit-self
  519       cc_check -Wmissing-prototypes
  520       cc_check -Wshadow
  521       cc_check -Wunused
  522       cc_check -Wwrite-strings
  523       cc_check -Wno-long-long
  524    #fi
  525    cc_check -pedantic
  526 
  527    if feat_yes AMALGAMATION && feat_no DEVEL; then
  528       cc_check -Wno-unused-function
  529    fi
  530    feat_no DEVEL && cc_check -Wno-unused-result # XXX do right way (pragma too)
  531 
  532    cc_check -fno-unwind-tables
  533    cc_check -fno-asynchronous-unwind-tables
  534    cc_check -fstrict-aliasing
  535    if cc_check -fstrict-overflow && feat_yes DEVEL; then
  536       cc_check -Wstrict-overflow=5
  537    fi
  538 
  539    if feat_yes DEBUG || feat_yes FORCED_STACKPROT; then
  540       if [ -z "${cc_force_no_stackprot}" ]; then
  541          if cc_check -fstack-protector-strong ||
  542                cc_check -fstack-protector-all; then
  543             cc_check -D_FORTIFY_SOURCE=2
  544          fi
  545       else
  546          msg ' ! Not checking for -fstack-protector compiler option,'
  547          msg ' ! since that caused errors in a "similar" configuration.'
  548          msg ' ! You may turn off OPT_AUTOCC and use your own settings, rerun'
  549       fi
  550    fi
  551 
  552    # LD (+ dependend CC)
  553 
  554    if feat_yes ASAN_ADDRESS; then
  555       _ccfg=${_CFLAGS}
  556       if cc_check -fsanitize=address && ld_check -fsanitize=address; then
  557          :
  558       else
  559          feat_bail_required ASAN_ADDRESS
  560          _CFLAGS=${_ccfg}
  561       fi
  562    fi
  563 
  564    if feat_yes ASAN_MEMORY; then
  565       _ccfg=${_CFLAGS}
  566       if cc_check -fsanitize=memory && ld_check -fsanitize=memory &&
  567             cc_check -fsanitize-memory-track-origins=2 &&
  568             ld_check -fsanitize-memory-track-origins=2; then
  569          :
  570       else
  571          feat_bail_required ASAN_MEMORY
  572          _CFLAGS=${_ccfg}
  573       fi
  574    fi
  575 
  576    if feat_yes USAN; then
  577       _ccfg=${_CFLAGS}
  578       if cc_check -fsanitize=undefined && ld_check -fsanitize=undefined; then
  579          :
  580       else
  581          feat_bail_required USAN
  582          _CFLAGS=${_ccfg}
  583       fi
  584    fi
  585 
  586    ld_check -Wl,-z,relro
  587    if [ -z "${ld_no_bind_now}" ]; then
  588       ld_check -Wl,-z,now
  589    else
  590       msg ' ! $LD_LIBRARY_PATH adjusted, not trying -Wl,-z,now'
  591    fi
  592    ld_check -Wl,-z,noexecstack
  593    ld_check -Wl,--as-needed
  594    if ld_check -Wl,-rpath =./ no; then
  595       ld_need_R_flags=-Wl,-rpath=
  596       # Choose DT_RUNPATH (after $LD_LIBRARY_PATH) over DT_RPATH (before)
  597       if [ -z "${ld_rpath_not_runpath}" ]; then
  598          ld_check -Wl,--enable-new-dtags
  599       else
  600          msg ' ! $LD_LIBRARY_PATH adjusted, not trying --enable-new-dtags'
  601       fi
  602       ld_runtime_flags # update!
  603    elif ld_check -Wl,-R ./ no; then
  604       ld_need_R_flags=-Wl,-R
  605       if [ -z "${ld_rpath_not_runpath}" ]; then
  606          ld_check -Wl,--enable-new-dtags
  607       else
  608          msg ' ! $LD_LIBRARY_PATH adjusted, not trying --enable-new-dtags'
  609       fi
  610       ld_runtime_flags # update!
  611    fi
  612 
  613    # Address randomization
  614    _ccfg=${_CFLAGS}
  615    if cc_check -fPIE || cc_check -fpie; then
  616       ld_check -pie || _CFLAGS=${_ccfg}
  617    fi
  618    unset _ccfg
  619 
  620    _CFLAGS="${_CFLAGS} ${__cflags}" _LDFLAGS="${_LDFLAGS} ${__ldflags}"
  621    unset __cflags __ldflags
  622 }
  623 
  624 ##  --  >8  - <<OS/CC | SUPPORT FUNS>> -  8<  --  ##
  625 
  626 ## Notes:
  627 ## - Heirloom sh(1) (and same origin) have _sometimes_ problems with ': >'
  628 ##   redirection, so use "printf '' >" instead
  629 
  630 ## Very first: we undergo several states regarding I/O redirection etc.,
  631 ## but need to deal with option updates from within all.  Since all the
  632 ## option stuff should be above the scissor line, define utility functions
  633 ## and redefine them as necessary.
  634 ## And, since we have those functions, simply use them for whatever
  635 
  636 t1=ten10one1ten10one1
  637 if ( [ ${t1##*ten10} = one1 ] && [ ${t1#*ten10} = one1ten10one1 ] &&
  638       [ ${t1%%one1*} = ten10 ] && [ ${t1%one1*} = ten10one1ten10 ]
  639       ) > /dev/null 2>&1; then
  640    good_shell=1
  641 else
  642    unset good_shell
  643 fi
  644 unset t1
  645 
  646 ( set -o noglob ) >/dev/null 2>&1 && noglob_shell=1 || unset noglob_shell
  647 
  648 config_exit() {
  649    exit ${1}
  650 }
  651 
  652 # which(1) not standardized, command(1) -v may return non-executable: unroll!
  653 acmd_test() { __acmd "${1}" 1 0 0; }
  654 acmd_test_fail() { __acmd "${1}" 1 1 0; }
  655 acmd_set() { __acmd "${2}" 0 0 0 "${1}"; }
  656 acmd_set_fail() { __acmd "${2}" 0 1 0 "${1}"; }
  657 acmd_testandset() { __acmd "${2}" 1 0 0 "${1}"; }
  658 acmd_testandset_fail() { __acmd "${2}" 1 1 0 "${1}"; }
  659 thecmd_set() { __acmd "${2}" 0 0 1 "${1}"; }
  660 thecmd_set_fail() { __acmd "${2}" 0 1 1 "${1}"; }
  661 thecmd_testandset() { __acmd "${2}" 1 0 1 "${1}"; }
  662 thecmd_testandset_fail() { __acmd "${2}" 1 1 1 "${1}"; }
  663 __acmd() {
  664    pname=${1} dotest=${2} dofail=${3} verbok=${4} varname=${5}
  665 
  666    if [ "${dotest}" -ne 0 ]; then
  667       eval dotest=\$${varname}
  668       if [ -n "${dotest}" ]; then
  669          [ -n "${VERBOSE}" ] && [ ${verbok} -ne 0 ] &&
  670             msg ' . ${%s} ... %s' "${pname}" "${dotest}"
  671          return 0
  672       fi
  673    fi
  674 
  675    oifs=${IFS} IFS=:
  676    [ -n "${noglob_shell}" ] && set -o noglob
  677    set -- ${PATH}
  678    [ -n "${noglob_shell}" ] && set +o noglob
  679    IFS=${oifs}
  680    for path
  681    do
  682       if [ -z "${path}" ] || [ "${path}" = . ]; then
  683          if [ -d "${PWD}" ]; then
  684             path=${PWD}
  685          else
  686             path=.
  687          fi
  688       fi
  689       if [ -f "${path}/${pname}" ] && [ -x "${path}/${pname}" ]; then
  690          [ -n "${VERBOSE}" ] && [ ${verbok} -ne 0 ] &&
  691             msg ' . ${%s} ... %s' "${pname}" "${path}/${pname}"
  692          [ -n "${varname}" ] && eval ${varname}="${path}/${pname}"
  693          return 0
  694       fi
  695    done
  696 
  697    # We may have no builtin string functions, we yet have no programs we can
  698    # use, try to access once from the root, assuming it is an absolute path if
  699    # that finds the executable
  700    if ( cd && [ -f "${pname}" ] && [ -x "${pname}" ] ); then
  701      [ -n "${VERBOSE}" ] && [ ${verbok} -ne 0 ] &&
  702             msg ' . ${%s} ... %s' "${pname}" "${pname}"
  703       [ -n "${varname}" ] && eval ${varname}="${pname}"
  704       return 0
  705    fi
  706 
  707    [ ${dofail} -eq 0 ] && return 1
  708    msg 'ERROR: no trace of utility '"${pname}"
  709    exit 1
  710 }
  711 
  712 msg() {
  713    fmt=${1}
  714    shift
  715    printf >&2 -- "${fmt}\\n" "${@}"
  716 }
  717 
  718 msg_nonl() {
  719    fmt=${1}
  720    shift
  721    printf >&2 -- "${fmt}" "${@}"
  722 }
  723 
  724 # Our feature check environment
  725 feat_val_no() {
  726    [ "x${1}" = x0 ] || [ "x${1}" = xn ] ||
  727    [ "x${1}" = xfalse ] || [ "x${1}" = xno ] || [ "x${1}" = xoff ]
  728 }
  729 
  730 feat_val_yes() {
  731    [ "x${1}" = x1 ] || [ "x${1}" = xy ] ||
  732    [ "x${1}" = xtrue ] || [ "x${1}" = xyes ] || [ "x${1}" = xon ] ||
  733          [ "x${1}" = xrequire ]
  734 }
  735 
  736 feat_val_require() {
  737    [ "x${1}" = xrequire ]
  738 }
  739 
  740 _feat_check() {
  741    eval i=\$OPT_${1}
  742    i="`echo ${i} | ${tr} '[A-Z]' '[a-z]'`"
  743    if feat_val_no "${i}"; then
  744       return 1
  745    elif feat_val_yes "${i}"; then
  746       return 0
  747    else
  748       msg "ERROR: %s: 0/n/false/no/off or 1/y/true/yes/on/require, got: %s" \
  749          "${1}" "${i}"
  750       config_exit 11
  751    fi
  752 }
  753 
  754 feat_yes() {
  755    _feat_check ${1}
  756 }
  757 
  758 feat_no() {
  759    _feat_check ${1} && return 1
  760    return 0
  761 }
  762 
  763 feat_require() {
  764    eval i=\$OPT_${1}
  765    i="`echo ${i} | ${tr} '[A-Z]' '[a-z]'`"
  766    [ "x${i}" = xrequire ] || [ "x${i}" = xrequired ]
  767 }
  768 
  769 feat_bail_required() {
  770    if feat_require ${1}; then
  771       msg 'ERROR: feature OPT_%s is required but not available' "${1}"
  772       config_exit 13
  773    fi
  774    feat_is_unsupported "${1}"
  775 }
  776 
  777 feat_is_disabled() {
  778    [ ${#} -eq 1 ] && msg ' .  (disabled: OPT_%s)' "${1}"
  779    echo "/* OPT_${1} -> HAVE_${1} */" >> ${h}
  780 }
  781 
  782 feat_is_unsupported() {
  783    msg ' ! NOTICE: unsupported: OPT_%s' "${1}"
  784    echo "/* OPT_${1} -> HAVE_${1} */" >> ${h}
  785    eval OPT_${1}=0
  786    option_update # XXX this is rather useless here (dependency chain..)
  787 }
  788 
  789 feat_def() {
  790    if feat_yes ${1}; then
  791       msg ' . %s ... yes' "${1}"
  792       echo '#define HAVE_'${1}'' >> ${h}
  793       return 0
  794    else
  795       feat_is_disabled "${@}"
  796       return 1
  797    fi
  798 }
  799 
  800 option_parse() {
  801    # Parse one of our XOPTIONS* in $2 and assign the sh(1) compatible list of
  802    # options, without documentation, to $1
  803    j=\'
  804    i="`${awk} -v input=\"${2}\" '
  805       BEGIN{
  806          for(i = 0;;){
  807             voff = match(input, /[[:alnum:]_]+(='${j}'[^'${j}']+)?/)
  808             if(voff == 0)
  809                break
  810             v = substr(input, voff, RLENGTH)
  811             input = substr(input, voff + RLENGTH)
  812             doff = index(v, "=")
  813             if(doff > 0){
  814                d = substr(v, doff + 2, length(v) - doff - 1)
  815                v = substr(v, 1, doff - 1)
  816             }
  817             print v
  818          }
  819       }
  820       '`"
  821    eval ${1}=\"${i}\"
  822 }
  823 
  824 option_doc_of() {
  825    # Return the "documentation string" for option $1, itself if none such
  826    j=\'
  827    ${awk} -v want="${1}" \
  828       -v input="${XOPTIONS_DETECT}${XOPTIONS}${XOPTIONS_XTRA}" '
  829    BEGIN{
  830       for(;;){
  831          voff = match(input, /[[:alnum:]_]+(='${j}'[^'${j}']+)?/)
  832          if(voff == 0)
  833             break
  834          v = substr(input, voff, RLENGTH)
  835          input = substr(input, voff + RLENGTH)
  836          doff = index(v, "=")
  837          if(doff > 0){
  838             d = substr(v, doff + 2, length(v) - doff - 1)
  839             v = substr(v, 1, doff - 1)
  840          }else
  841             d = v
  842          if(v == want){
  843             if(d != "-")
  844                print d
  845             exit
  846          }
  847       }
  848    }
  849    '
  850 }
  851 
  852 option_join_rc() {
  853    # Join the values from make.rc into what currently is defined, not
  854    # overwriting yet existing settings
  855    ${rm} -f ${tmp}
  856    # We want read(1) to perform reverse solidus escaping in order to be able to
  857    # use multiline values in make.rc; the resulting sh(1)/sed(1) code was very
  858    # slow in VMs (see [fa2e248]), Aharon Robbins suggested the following
  859    < ${rc} ${awk} 'BEGIN{line = ""}{
  860       gsub(/^[[:space:]]+/, "", $0)
  861       gsub(/[[:space:]]+$/, "", $0)
  862       if(gsub(/\\$/, "", $0)){
  863          line = line $0
  864          next
  865       }else
  866          line = line $0
  867       if(index(line, "#") == 1){
  868          line = ""
  869       }else if(length(line)){
  870          print line
  871          line = ""
  872       }
  873    }' |
  874    while read line; do
  875       if [ -n "${good_shell}" ]; then
  876          i=${line%%=*}
  877       else
  878          i=`${awk} -v LINE="${line}" 'BEGIN{
  879             gsub(/=.*$/, "", LINE)
  880             print LINE
  881          }'`
  882       fi
  883       if [ "${i}" = "${line}" ]; then
  884          msg 'ERROR: invalid syntax in: %s' "${line}"
  885          continue
  886       fi
  887 
  888       eval j="\$${i}" jx="\${${i}+x}"
  889       if [ -n "${j}" ] || [ "${jx}" = x ]; then
  890          : # Yet present
  891       else
  892          j=`${awk} -v LINE="${line}" 'BEGIN{
  893             gsub(/^[^=]*=/, "", LINE)
  894             gsub(/^\"*/, "", LINE)
  895             gsub(/\"*$/, "", LINE)
  896             print LINE
  897          }'`
  898       fi
  899       [ "${i}" = "DESTDIR" ] && continue
  900       echo "${i}=\"${j}\""
  901    done > ${tmp}
  902    # Reread the mixed version right now
  903    . ./${tmp}
  904 }
  905 
  906 option_evaluate() {
  907    # Expand the option values, which may contain shell snippets
  908    ${rm} -f ${newlst} ${newmk} ${newh}
  909    exec 5<&0 6>&1 <${tmp} >${newlst}
  910    while read line; do
  911       z=
  912       if [ -n "${good_shell}" ]; then
  913          i=${line%%=*}
  914          [ "${i}" != "${i#OPT_}" ] && z=1
  915       else
  916          i=`${awk} -v LINE="${line}" 'BEGIN{
  917             gsub(/=.*$/, "", LINE);\
  918             print LINE
  919          }'`
  920          if echo "${i}" | ${grep} '^OPT_' >/dev/null 2>&1; then
  921             z=1
  922          fi
  923       fi
  924 
  925       eval j=\$${i}
  926       if [ -n "${z}" ]; then
  927          j="`echo ${j} | ${tr} '[A-Z]' '[a-z]'`"
  928          if [ -z "${j}" ] || feat_val_no "${j}"; then
  929             j=0
  930             printf "   /* #undef ${i} */\n" >> ${newh}
  931          elif feat_val_yes "${j}"; then
  932             if feat_val_require "${j}"; then
  933                j=require
  934             else
  935                j=1
  936             fi
  937             printf "   /* #define ${i} */\n" >> ${newh}
  938          else
  939             msg 'ERROR: cannot parse <%s>' "${line}"
  940             config_exit 1
  941          fi
  942       elif { echo ${i} | ${grep} ${H_BLACKLIST} >/dev/null 2>&1; }; then
  943          :
  944       else
  945          printf "#define ${i} \"${j}\"\n" >> ${newh}
  946       fi
  947       printf "${i} = ${j}\n" >> ${newmk}
  948       printf "${i}=${j}\n"
  949       eval "${i}=\"${j}\""
  950    done
  951    exec 0<&5 1>&6 5<&- 6<&-
  952 }
  953 
  954 val_allof() {
  955    eval __expo__=\$${1}
  956    ${awk} -v HEAP="${2}" -v USER="${__expo__}" '
  957       BEGIN{
  958          i = split(HEAP, ha, /[, ]/)
  959          if((j = split(USER, ua, /[, ]/)) == 0)
  960             exit
  961          for(; j != 0; --j){
  962             us = tolower(ua[j])
  963             if(us == "all" || us == "any")
  964                continue
  965             ok = 0
  966             for(ii = i; ii != 0; --ii)
  967                if(tolower(ha[ii]) == us){
  968                   ok = 1
  969                   break
  970                }
  971             if(!ok)
  972                exit 1
  973          }
  974       }
  975    '
  976    __rv__=${?}
  977    [ ${__rv__} -ne 0 ] && return ${__rv__}
  978 
  979     if ${awk} -v USER="${__expo__}" '
  980             BEGIN{
  981                if((j = split(USER, ua, /[, ]/)) == 0)
  982                   exit
  983                for(; j != 0; --j){
  984                   us = tolower(ua[j])
  985                   if(us == "all" || us == "any")
  986                      exit 0
  987                }
  988                exit 1
  989             }
  990          '; then
  991       eval "${1}"=\"${2}\"
  992    else
  993       # Enfore lowercase also in otherwise unchanged user value..
  994       eval "${1}"=\""`echo ${__expo__} | ${tr} '[A-Z]_' '[a-z]-'`"\"
  995    fi
  996    return 0
  997 }
  998 
  999 path_check() {
 1000    # "path_check VARNAME" or "path_check VARNAME FLAG VARNAME"
 1001    varname=${1} addflag=${2} flagvarname=${3}
 1002    j=${IFS}
 1003    IFS=:
 1004    [ -n "${noglob_shell}" ] && set -o noglob
 1005    eval "set -- \$${1}"
 1006    [ -n "${noglob_shell}" ] && set +o noglob
 1007    IFS=${j}
 1008    j= k= y= z=
 1009    for i
 1010    do
 1011       [ -z "${i}" ] && continue
 1012       [ -d "${i}" ] || continue
 1013       if [ -n "${j}" ]; then
 1014          if { z=${y}; echo "${z}"; } | ${grep} ":${i}:" >/dev/null 2>&1; then
 1015             :
 1016          else
 1017             y="${y} :${i}:"
 1018             j="${j}:${i}"
 1019             # But do not link any fakeroot path into our binaries!
 1020             if [ -n "${addflag}" ]; then
 1021                case "${i}" in *fakeroot*) continue;; esac
 1022                k="${k} ${addflag}${i}"
 1023             fi
 1024          fi
 1025       else
 1026          y=" :${i}:"
 1027          j="${i}"
 1028          # But do not link any fakeroot path into our binaries!
 1029          if [ -n "${addflag}" ]; then
 1030             case "${i}" in *fakeroot*) continue;; esac
 1031             k="${k} ${addflag}${i}"
 1032          fi
 1033       fi
 1034    done
 1035    eval "${varname}=\"${j}\""
 1036    [ -n "${addflag}" ] && eval "${flagvarname}=\"${k}\""
 1037    unset varname
 1038 }
 1039 
 1040 ld_runtime_flags() {
 1041    if [ -n "${ld_need_R_flags}" ]; then
 1042       i=${IFS}
 1043       IFS=:
 1044       set -- ${LD_LIBRARY_PATH}
 1045       IFS=${i}
 1046       for i
 1047       do
 1048          # But do not link any fakeroot path into our binaries!
 1049          case "${i}" in *fakeroot*) continue;; esac
 1050          LDFLAGS="${LDFLAGS} ${ld_need_R_flags}${i}"
 1051          _LDFLAGS="${_LDFLAGS} ${ld_need_R_flags}${i}"
 1052       done
 1053       export LDFLAGS
 1054    fi
 1055    # Disable it for a possible second run.
 1056    ld_need_R_flags=
 1057 }
 1058 
 1059 cc_check() {
 1060    [ -n "${cc_check_silent}" ] || msg_nonl ' . CC %s .. ' "${1}"
 1061    if ${CC} ${INCS} \
 1062          ${_CFLAGS} ${1} ${EXTRA_CFLAGS} ${_LDFLAGS} ${EXTRA_LDFLAGS} \
 1063          -o ${tmp2} ${tmp}.c ${LIBS} >/dev/null 2>&1; then
 1064       _CFLAGS="${_CFLAGS} ${1}"
 1065       [ -n "${cc_check_silent}" ] || msg 'yes'
 1066       return 0
 1067    fi
 1068    [ -n "${cc_check_silent}" ] || msg 'no'
 1069    return 1
 1070 }
 1071 
 1072 ld_check() {
 1073    # $1=option [$2=option argument] [$3=if set, shall NOT be added to _LDFLAGS]
 1074    [ -n "${cc_check_silent}" ] || msg_nonl ' . LD %s .. ' "${1}"
 1075    if ${CC} ${INCS} ${_CFLAGS} ${_LDFLAGS} ${1}${2} ${EXTRA_LDFLAGS} \
 1076          -o ${tmp2} ${tmp}.c ${LIBS} >/dev/null 2>&1; then
 1077       [ -n "${3}" ] || _LDFLAGS="${_LDFLAGS} ${1}"
 1078       [ -n "${cc_check_silent}" ] || msg 'yes'
 1079       return 0
 1080    fi
 1081    [ -n "${cc_check_silent}" ] || msg 'no'
 1082    return 1
 1083 }
 1084 
 1085 dump_test_program=1
 1086 _check_preface() {
 1087    variable=$1 topic=$2 define=$3
 1088 
 1089    echo '**********'
 1090    msg_nonl ' . %s ... ' "${topic}"
 1091    #echo "/* checked ${topic} */" >> ${h}
 1092    ${rm} -f ${tmp} ${tmp}.o
 1093    if [ "${dump_test_program}" = 1 ]; then
 1094       echo '*** test program is'
 1095       { echo '#include <'"${h_name}"'>'; cat; } | ${tee} ${tmp}.c
 1096    else
 1097       { echo '#include <'"${h_name}"'>'; cat; } > ${tmp}.c
 1098    fi
 1099    #echo '*** the preprocessor generates'
 1100    #${make} -f ${makefile} ${tmp}.x
 1101    #${cat} ${tmp}.x
 1102    echo '*** tests results'
 1103 }
 1104 
 1105 without_check() {
 1106    yesno=$1 variable=$2 topic=$3 define=$4 libs=$5 incs=$6
 1107 
 1108    echo '**********'
 1109    msg_nonl ' . %s ... ' "${topic}"
 1110 
 1111    echo '*** enforced unchecked results are'
 1112    if feat_val_yes ${yesno}; then
 1113       if [ -n "${incs}" ] || [ -n "${libs}" ]; then
 1114          echo "*** adding INCS<${incs}> LIBS<${libs}>"
 1115          LIBS="${LIBS} ${libs}"
 1116          echo "${libs}" >> ${lib}
 1117          INCS="${INCS} ${incs}"
 1118          echo "${incs}" >> ${inc}
 1119       fi
 1120       msg 'yes (deduced)'
 1121       echo "${define}" >> ${h}
 1122       eval have_${variable}=yes
 1123       return 0
 1124    else
 1125       #echo "/* ${define} */" >> ${h}
 1126       msg 'no (deduced)'
 1127       eval unset have_${variable}
 1128       return 1
 1129    fi
 1130 }
 1131 
 1132 compile_check() {
 1133    variable=$1 topic=$2 define=$3
 1134 
 1135    _check_preface "${variable}" "${topic}" "${define}"
 1136 
 1137    if ${make} -f ${makefile} XINCS="${INCS}" \
 1138             CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ${tmp}.o &&
 1139             [ -f ${tmp}.o ]; then
 1140       msg 'yes'
 1141       echo "${define}" >> ${h}
 1142       eval have_${variable}=yes
 1143       return 0
 1144    else
 1145       #echo "/* ${define} */" >> ${h}
 1146       msg 'no'
 1147       eval unset have_${variable}
 1148       return 1
 1149    fi
 1150 }
 1151 
 1152 _link_mayrun() {
 1153    run=$1 variable=$2 topic=$3 define=$4 libs=$5 incs=$6
 1154 
 1155    _check_preface "${variable}" "${topic}" "${define}"
 1156 
 1157    if feat_yes CROSS_BUILD; then
 1158       if [ ${run} = 1 ]; then
 1159          run=0
 1160       fi
 1161    fi
 1162 
 1163    if ${make} -f ${makefile} XINCS="${INCS} ${incs}" \
 1164             CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" \
 1165             XLIBS="${LIBS} ${libs}" ${tmp} &&
 1166          [ -f ${tmp} ] && { [ ${run} -eq 0 ] || ${tmp}; }; then
 1167       echo "*** adding INCS<${incs}> LIBS<${libs}>; executed: ${run}"
 1168       msg 'yes'
 1169       echo "${define}" >> ${h}
 1170       LIBS="${LIBS} ${libs}"
 1171       echo "${libs}" >> ${lib}
 1172       INCS="${INCS} ${incs}"
 1173       echo "${incs}" >> ${inc}
 1174       eval have_${variable}=yes
 1175       return 0
 1176    else
 1177       msg 'no'
 1178       #echo "/* ${define} */" >> ${h}
 1179       eval unset have_${variable}
 1180       return 1
 1181    fi
 1182 }
 1183 
 1184 link_check() {
 1185    _link_mayrun 0 "${1}" "${2}" "${3}" "${4}" "${5}"
 1186 }
 1187 
 1188 run_check() {
 1189    _link_mayrun 1 "${1}" "${2}" "${3}" "${4}" "${5}"
 1190 }
 1191 
 1192 xrun_check() {
 1193    _link_mayrun 2 "${1}" "${2}" "${3}" "${4}" "${5}"
 1194 }
 1195 
 1196 squeeze_em() {
 1197    < "${1}" > "${2}" ${awk} \
 1198    'BEGIN {ORS = " "} /^[^#]/ {print} {next} END {ORS = ""; print "\n"}'
 1199 }
 1200 
 1201 ##  --  >8  - <<SUPPORT FUNS | RUNNING>> -  8<  --  ##
 1202 
 1203 # First of all, create new configuration and check whether it changed
 1204 
 1205 if [ -d .obj ] || mkdir .obj; then :; else
 1206    msg 'ERROR: cannot create .obj build directory'
 1207    exit 1
 1208 fi
 1209 
 1210 # Very easy checks for the operating system in order to be able to adjust paths
 1211 # or similar very basic things which we need to be able to go at all
 1212 os_early_setup
 1213 
 1214 # Check those tools right now that we need before including $rc
 1215 msg 'Checking for basic utility set'
 1216 thecmd_testandset_fail awk awk
 1217 thecmd_testandset_fail rm rm
 1218 thecmd_testandset_fail tr tr
 1219 
 1220 # Lowercase this now in order to isolate all the remains from case matters
 1221 OS=`echo ${OS} | ${tr} '[A-Z]' '[a-z]'`
 1222 export OS
 1223 
 1224 # Initialize the option set
 1225 msg_nonl 'Setting up configuration options ... '
 1226 option_setup
 1227 msg 'done'
 1228 
 1229 # Include $rc, but only take from it what wasn't overwritten by the user from
 1230 # within the command line or from a chosen fixed CONFIG=
 1231 # Note we leave alone the values
 1232 trap "exit 1" HUP INT TERM
 1233 trap "${rm} -f ${tmp}" EXIT
 1234 
 1235 msg_nonl 'Joining in %s ... ' ${rc}
 1236 option_join_rc
 1237 msg 'done'
 1238 
 1239 # We need to know about that now, in order to provide utility overwrites etc.
 1240 os_setup
 1241 
 1242 msg 'Checking for remaining set of utilities'
 1243 thecmd_testandset_fail grep grep
 1244 
 1245 # Before we step ahead with the other utilities perform a path cleanup first.
 1246 path_check PATH
 1247 
 1248 # awk(1) above
 1249 thecmd_testandset_fail basename basename
 1250 thecmd_testandset_fail cat cat
 1251 thecmd_testandset_fail chmod chmod
 1252 thecmd_testandset_fail cp cp
 1253 thecmd_testandset_fail cmp cmp
 1254 # grep(1) above
 1255 thecmd_testandset_fail mkdir mkdir
 1256 thecmd_testandset_fail mv mv
 1257 # pwd(1) is needed - either for make-emerge.sh, or for ourselves
 1258 [ -n "${CWDDIR}" ] || thecmd_testandset_fail pwd pwd
 1259 # rm(1) above
 1260 thecmd_testandset_fail sed sed
 1261 thecmd_testandset_fail sort sort
 1262 thecmd_testandset_fail tee tee
 1263 __PATH=${PATH}
 1264 thecmd_testandset chown chown ||
 1265    PATH="/sbin:${PATH}" thecmd_set chown chown ||
 1266    PATH="/usr/sbin:${PATH}" thecmd_set_fail chown chown
 1267 PATH=${__PATH}
 1268 thecmd_testandset_fail MAKE make
 1269 make=${MAKE}
 1270 export MAKE
 1271 thecmd_testandset strip strip && HAVE_STRIP=1 || HAVE_STRIP=0
 1272 
 1273 # For ./cc-test.sh only
 1274 thecmd_testandset_fail cksum cksum
 1275 
 1276 # Now that we have pwd(1), set our build paths unless make-emerge.sh has been
 1277 # used; it would have created a makefile with the full paths, then
 1278 [ -n "${CWDDIR}" ] || CWDDIR=`${pwd}`/
 1279 [ -n "${SRCDIR}" ] || SRCDIR=${CWDDIR}
 1280 
 1281 # Update OPT_ options now, in order to get possible inter-dependencies right
 1282 option_update
 1283 
 1284 # (No functions since some shells loose non-exported variables in traps)
 1285 trap "trap \"\" HUP INT TERM; exit 1" HUP INT TERM
 1286 trap "trap \"\" HUP INT TERM EXIT;\
 1287    ${rm} -rf ${newlst} ${tmp0}.* ${tmp0}* \
 1288       ${newmk} ${oldmk} ${newev} ${newh} ${oldh}" EXIT
 1289 
 1290 # Our configuration options may at this point still contain shell snippets,
 1291 # we need to evaluate them in order to get them expanded, and we need those
 1292 # evaluated values not only in our new configuration file, but also at hand..
 1293 msg_nonl 'Evaluating all configuration items ... '
 1294 option_evaluate
 1295 msg 'done'
 1296 
 1297 #
 1298 printf "#define VAL_UAGENT \"${VAL_SID}${VAL_MAILX}\"\n" >> ${newh}
 1299 printf "VAL_UAGENT = ${VAL_SID}${VAL_MAILX}\n" >> ${newmk}
 1300 
 1301 # The problem now is that the test should be able to run in the users linker
 1302 # and path environment, so we need to place the test: rule first, before
 1303 # injecting the relevant make variables.  Set up necessary environment
 1304 if [ -z "${VERBOSE}" ]; then
 1305    printf -- "ECHO_CC = @echo '  'CC \$(@);\n" >> ${newmk}
 1306    printf -- "ECHO_LINK = @echo '  'LINK \$(@);\n" >> ${newmk}
 1307    printf -- "ECHO_GEN = @echo '  'GEN \$(@);\n" >> ${newmk}
 1308    printf -- "ECHO_TEST = @\n" >> ${newmk}
 1309    printf -- "ECHO_CMD = @echo '  CMD';\n" >> ${newmk}
 1310    printf -- "ECHO_BLOCK_BEGIN = @( \n" >> ${newmk}
 1311    printf -- "ECHO_BLOCK_END = ) >/dev/null\n" >> ${newmk}
 1312 fi
 1313 printf 'test: all\n\t$(ECHO_TEST)%s %scc-test.sh --check-only %s\n' \
 1314    "${SHELL}" "${SRCDIR}" "./${VAL_SID}${VAL_MAILX}" >> ${newmk}
 1315 printf 'citest: all\n\t$(ECHO_TEST)%s %scc-test.sh --ci-test %s\n' \
 1316    "${SHELL}" "${SRCDIR}" "./${VAL_SID}${VAL_MAILX}" >> ${newmk}
 1317 
 1318 # Add the known utility and some other variables
 1319 printf "#define VAL_PRIVSEP \"${VAL_SID}${VAL_MAILX}-privsep\"\n" >> ${newh}
 1320 printf "VAL_PRIVSEP = \$(VAL_UAGENT)-privsep\n" >> ${newmk}
 1321 if feat_yes DOTLOCK; then
 1322    printf "OPTIONAL_PRIVSEP = \$(VAL_PRIVSEP)\n" >> ${newmk}
 1323 else
 1324    printf "OPTIONAL_PRIVSEP =\n" >> ${newmk}
 1325 fi
 1326 
 1327 for i in \
 1328    CWDDIR SRCDIR \
 1329       awk basename cat chmod chown cp cmp grep mkdir mv rm sed sort tee tr \
 1330       MAKE MAKEFLAGS make SHELL strip \
 1331       cksum; do
 1332    eval j=\$${i}
 1333    printf -- "${i} = ${j}\n" >> ${newmk}
 1334    printf -- "${i}=${j}\n" >> ${newlst}
 1335    printf -- "${i}=\"${j}\";export ${i}; " >> ${newev}
 1336 done
 1337 # Note that makefile reads and eval'uates one line of this file, whereas other
 1338 # consumers source it via .(1)
 1339 printf "\n" >> ${newev}
 1340 
 1341 # Build a basic set of INCS and LIBS according to user environment.
 1342 C_INCLUDE_PATH="${CWDDIR}:${CWDDIR}.obj:${SRCDIR}:${C_INCLUDE_PATH}"
 1343 path_check C_INCLUDE_PATH -I _INCS
 1344 INCS="${INCS} ${_INCS}"
 1345 path_check LD_LIBRARY_PATH -L _LIBS
 1346 LIBS="${LIBS} ${_LIBS}"
 1347 unset _INCS _LIBS
 1348 export C_INCLUDE_PATH LD_LIBRARY_PATH
 1349 
 1350 # Some environments need runtime path flags to be able to go at all
 1351 ld_runtime_flags
 1352 
 1353 ## Detect CC, whether we can use it, and possibly which CFLAGS we can use
 1354 
 1355 cc_setup
 1356 
 1357 ${cat} > ${tmp}.c << \!
 1358 #include <stdio.h>
 1359 #include <string.h>
 1360 static void doit(char const *s);
 1361 int
 1362 main(int argc, char **argv){
 1363    (void)argc;
 1364    (void)argv;
 1365    doit("Hello world");
 1366    return 0;
 1367 }
 1368 static void
 1369 doit(char const *s){
 1370    char buf[12];
 1371    memcpy(buf, s, strlen(s) +1);
 1372    puts(s);
 1373 }
 1374 !
 1375 
 1376 if ${CC} ${INCS} ${CFLAGS} ${EXTRA_CFLAGS} ${LDFLAGS} ${EXTRA_LDFLAGS} \
 1377       -o ${tmp2} ${tmp}.c ${LIBS}; then
 1378    :
 1379 else
 1380    msg 'ERROR: i cannot compile a "Hello world" via'
 1381    msg '   %s' \
 1382    "${CC} ${INCS} ${CFLAGS} ${EXTRA_CFLAGS} ${LDFLAGS} ${EXTRA_LDFLAGS} ${LIBS}"
 1383    msg 'ERROR:   Please read INSTALL, rerun'
 1384    config_exit 1
 1385 fi
 1386 
 1387 # This may also update ld_runtime_flags() (again)
 1388 cc_flags
 1389 
 1390 for i in \
 1391       COMMLINE \
 1392       INCS LIBS \
 1393       ; do
 1394    eval j="\$${i}"
 1395    printf -- "${i}=${j}\n" >> ${newlst}
 1396 done
 1397 for i in \
 1398       CC \
 1399       CFLAGS \
 1400       LDFLAGS \
 1401       PATH C_INCLUDE_PATH LD_LIBRARY_PATH \
 1402       OSFULLSPEC \
 1403       ; do
 1404    eval j=\$${i}
 1405    if [ -n "${j}" ]; then
 1406       printf -- "${i} = ${j}\n" >> ${newmk}
 1407       printf -- "${i}=${j}\n" >> ${newlst}
 1408    fi
 1409 done
 1410 
 1411 # Now finally check whether we already have a configuration and if so, whether
 1412 # all those parameters are still the same.. or something has actually changed
 1413 config_updated=
 1414 if [ -f ${lst} ] && ${cmp} ${newlst} ${lst} >/dev/null 2>&1; then
 1415    echo 'Configuration is up-to-date'
 1416    exit 0
 1417 elif [ -f ${lst} ]; then
 1418    config_updated=1
 1419    echo 'Configuration has been updated..'
 1420 else
 1421    echo 'Shiny configuration..'
 1422 fi
 1423 
 1424 # Time to redefine helper 1
 1425 config_exit() {
 1426    ${rm} -f ${lst} ${h} ${mk}
 1427    exit ${1}
 1428 }
 1429 
 1430 ${mv} -f ${newlst} ${lst}
 1431 ${mv} -f ${newev} ${ev}
 1432 [ -f ${h} ] && ${mv} -f ${h} ${oldh}
 1433 ${mv} -f ${newh} ${h}
 1434 [ -f ${mk} ] && ${mv} -f ${mk} ${oldmk}
 1435 ${mv} -f ${newmk} ${mk}
 1436 
 1437 ## Compile and link checking
 1438 
 1439 tmp3=${tmp0}3$$
 1440 log=.obj/mk-config.log
 1441 lib=.obj/mk-config.lib
 1442 inc=.obj/mk-config.inc
 1443 makefile=${tmp0}.mk
 1444 
 1445 # (No function since some shells loose non-exported variables in traps)
 1446 trap "trap \"\" HUP INT TERM;\
 1447    ${rm} -f ${lst} ${oldh} ${h} ${oldmk} ${mk} ${lib} ${inc}; exit 1" \
 1448       HUP INT TERM
 1449 trap "trap \"\" HUP INT TERM EXIT;\
 1450    ${rm} -rf ${oldh} ${oldmk} ${tmp0}.* ${tmp0}*" EXIT
 1451 
 1452 # Time to redefine helper 2
 1453 msg() {
 1454    fmt=${1}
 1455    shift
 1456    printf "*** ${fmt}\\n" "${@}"
 1457    printf -- "${fmt}\\n" "${@}" >&5
 1458 }
 1459 msg_nonl() {
 1460    fmt=${1}
 1461    shift
 1462    printf "*** ${fmt}\\n" "${@}"
 1463    printf -- "${fmt}" "${@}" >&5
 1464 }
 1465 
 1466 # !!
 1467 exec 5>&2 > ${log} 2>&1
 1468 
 1469 echo "${LIBS}" > ${lib}
 1470 echo "${INCS}" > ${inc}
 1471 ${cat} > ${makefile} << \!
 1472 .SUFFIXES: .o .c .x .y
 1473 .c.o:
 1474     $(CC) -I./ $(XINCS) $(CFLAGS) -o $(@) -c $(<)
 1475 .c.x:
 1476     $(CC) -I./ $(XINCS) -E $(<) > $(@)
 1477 .c:
 1478     $(CC) -I./ $(XINCS) $(CFLAGS) $(LDFLAGS) -o $(@) $(<) $(XLIBS)
 1479 !
 1480 
 1481 ## Generics
 1482 
 1483 # May be multiline..
 1484 echo >> ${h}
 1485 [ -n "${OS_DEFINES}" ] && printf -- "${OS_DEFINES}" >> ${h}
 1486 echo '#define VAL_BUILD_OS "'"${OS}"'"' >> ${h}
 1487 
 1488 # Generate n_err_number OS mappings
 1489 dump_test_program=0
 1490 (
 1491    feat_yes DEVEL && NV= || NV=noverbose
 1492    SRCDIR="${SRCDIR}" TARGET="${h}" awk="${awk}" \
 1493       ${SHELL} "${SRCDIR}"make-errors.sh ${NV} config
 1494 ) | xrun_check oserrno 'OS error mapping table generated' || config_exit 1
 1495 dump_test_program=1
 1496 
 1497 feat_def ALWAYS_UNICODE_LOCALE
 1498 feat_def AMALGAMATION 0
 1499 feat_def CROSS_BUILD
 1500 feat_def DOCSTRINGS
 1501 feat_def MAILDIR
 1502 feat_def UISTRINGS
 1503 feat_def ERRORS
 1504 
 1505 feat_def ASAN_ADDRESS 0
 1506 feat_def ASAN_MEMORY 0
 1507 feat_def DEBUG 0
 1508 feat_def DEVEL 0
 1509 feat_def NYD2 0
 1510 feat_def NOMEMDBG 0
 1511 
 1512 if xrun_check inline 'inline functions' \
 1513    '#define HAVE_INLINE
 1514    #define n_INLINE static inline' << \!
 1515 static inline int ilf(int i){return ++i;}
 1516 int main(void){return ilf(-1);}
 1517 !
 1518 then
 1519    :
 1520 elif xrun_check inline 'inline functions (via __inline)' \
 1521    '#define HAVE_INLINE
 1522    #define n_INLINE static __inline' << \!
 1523 static __inline int ilf(int i){return ++i;}
 1524 int main(void){return ilf(-1);}
 1525 !
 1526 then
 1527    :
 1528 fi
 1529 
 1530 ## Test for "basic" system-calls / functionality that is used by all parts
 1531 ## of our program.  Once this is done fork away BASE_LIBS and other BASE_*
 1532 ## macros to be used by only the subprograms (potentially).
 1533 
 1534 if run_check clock_gettime 'clock_gettime(2)' \
 1535    '#define HAVE_CLOCK_GETTIME' << \!
 1536 #include <time.h>
 1537 # include <errno.h>
 1538 int main(void){
 1539    struct timespec ts;
 1540 
 1541    if(!clock_gettime(CLOCK_REALTIME, &ts) || errno != ENOSYS)
 1542       return 0;
 1543    return 1;
 1544 }
 1545 !
 1546 then
 1547    :
 1548 elif run_check clock_gettime 'clock_gettime(2) (via -lrt)' \
 1549    '#define HAVE_CLOCK_GETTIME' '-lrt' << \!
 1550 #include <time.h>
 1551 # include <errno.h>
 1552 int main(void){
 1553    struct timespec ts;
 1554 
 1555    if(!clock_gettime(CLOCK_REALTIME, &ts) || errno != ENOSYS)
 1556       return 0;
 1557    return 1;
 1558 }
 1559 !
 1560 then
 1561    :
 1562 elif run_check gettimeofday 'gettimeofday(2)' \
 1563    '#define HAVE_GETTIMEOFDAY' << \!
 1564 #include <stdio.h> /* For C89 NULL */
 1565 #include <sys/time.h>
 1566 # include <errno.h>
 1567 int main(void){
 1568    struct timeval tv;
 1569 
 1570    if(!gettimeofday(&tv, NULL) || errno != ENOSYS)
 1571       return 0;
 1572    return 1;
 1573 }
 1574 !
 1575 then
 1576    :
 1577 else
 1578    have_no_subsecond_time=1
 1579 fi
 1580 
 1581 if run_check nanosleep 'nanosleep(2)' \
 1582    '#define HAVE_NANOSLEEP' << \!
 1583 #include <time.h>
 1584 # include <errno.h>
 1585 int main(void){
 1586    struct timespec ts;
 1587 
 1588    ts.tv_sec = 1;
 1589    ts.tv_nsec = 100000;
 1590    if(!nanosleep(&ts, NULL) || errno != ENOSYS)
 1591       return 0;
 1592    return 1;
 1593 }
 1594 !
 1595 then
 1596    :
 1597 elif run_check nanosleep 'nanosleep(2) (via -lrt)' \
 1598    '#define HAVE_NANOSLEEP' '-lrt' << \!
 1599 #include <time.h>
 1600 # include <errno.h>
 1601 int main(void){
 1602    struct timespec ts;
 1603 
 1604    ts.tv_sec = 1;
 1605    ts.tv_nsec = 100000;
 1606    if(!nanosleep(&ts, NULL) || errno != ENOSYS)
 1607       return 0;
 1608    return 1;
 1609 }
 1610 !
 1611 then
 1612    :
 1613 # link_check is enough for this, that function is so old, trust the proto
 1614 elif link_check sleep 'sleep(3)' \
 1615    '#define HAVE_SLEEP' << \!
 1616 #include <unistd.h>
 1617 # include <errno.h>
 1618 int main(void){
 1619    if(!sleep(1) || errno != ENOSYS)
 1620       return 0;
 1621    return 1;
 1622 }
 1623 !
 1624 then
 1625    :
 1626 else
 1627    msg 'ERROR: we require one of nanosleep(2) and sleep(3).'
 1628    config_exit 1
 1629 fi
 1630 
 1631 if run_check userdb 'gete?[gu]id(2), getpwuid(3), getpwnam(3)' << \!
 1632 #include <pwd.h>
 1633 #include <unistd.h>
 1634 # include <errno.h>
 1635 int main(void){
 1636    struct passwd *pw;
 1637    gid_t gid;
 1638    uid_t uid;
 1639 
 1640    if((gid = getgid()) != 0)
 1641       gid = getegid();
 1642    if((uid = getuid()) != 0)
 1643       uid = geteuid();
 1644    if((pw = getpwuid(uid)) == NULL && errno == ENOSYS)
 1645       return 1;
 1646    if((pw = getpwnam("root")) == NULL && errno == ENOSYS)
 1647       return 1;
 1648    return 0;
 1649 }
 1650 !
 1651 then
 1652    :
 1653 else
 1654    msg 'ERROR: we require user and group info / database searches.'
 1655    msg 'That much Unix we indulge ourselfs.'
 1656    config_exit 1
 1657 fi
 1658 
 1659 if link_check ftruncate 'ftruncate(2)' \
 1660    '#define HAVE_FTRUNCATE' << \!
 1661 #include <unistd.h>
 1662 #include <sys/types.h>
 1663 int main(void){
 1664    return (ftruncate(0, 0) != 0);
 1665 }
 1666 !
 1667 then
 1668    :
 1669 else
 1670    # TODO support HAVE_FTRUNCATE *everywhere*, do not require this syscall!
 1671    msg 'ERROR: we require the ftruncate(2) system call.'
 1672    config_exit 1
 1673 fi
 1674 
 1675 if run_check sa_restart 'SA_RESTART (for sigaction(2))' << \!
 1676 #include <signal.h>
 1677 # include <errno.h>
 1678 int main(void){
 1679    struct sigaction nact, oact;
 1680 
 1681    nact.sa_handler = SIG_DFL;
 1682    sigemptyset(&nact.sa_mask);
 1683    nact.sa_flags = SA_RESTART;
 1684    return !(!sigaction(SIGCHLD, &nact, &oact) || errno != ENOSYS);
 1685 }
 1686 !
 1687 then
 1688    :
 1689 else
 1690    msg 'ERROR: we (yet) require the SA_RESTART flag for sigaction(2).'
 1691    config_exit 1
 1692 fi
 1693 
 1694 if link_check snprintf 'snprintf(3)' << \!
 1695 #include <stdio.h>
 1696 int main(void){
 1697    char b[20];
 1698 
 1699    snprintf(b, sizeof b, "%s", "string");
 1700    return 0;
 1701 }
 1702 !
 1703 then
 1704    :
 1705 else
 1706    msg 'ERROR: we require the snprintf(3) function.'
 1707    config_exit 1
 1708 fi
 1709 
 1710 if link_check environ 'environ(3)' << \!
 1711 #include <stdio.h> /* For C89 NULL */
 1712 int main(void){
 1713    extern char **environ;
 1714 
 1715    return environ[0] == NULL;
 1716 }
 1717 !
 1718 then
 1719    :
 1720 else
 1721    msg 'ERROR: we require the environ(3) array for subprocess control.'
 1722    config_exit 1
 1723 fi
 1724 
 1725 if link_check setenv '(un)?setenv(3)' '#define HAVE_SETENV' << \!
 1726 #include <stdlib.h>
 1727 int main(void){
 1728    setenv("s-mailx", "i want to see it cute!", 1);
 1729    unsetenv("s-mailx");
 1730    return 0;
 1731 }
 1732 !
 1733 then
 1734    :
 1735 elif link_check setenv 'putenv(3)' '#define HAVE_PUTENV' << \!
 1736 #include <stdlib.h>
 1737 int main(void){
 1738    putenv("s-mailx=i want to see it cute!");
 1739    return 0;
 1740 }
 1741 !
 1742 then
 1743    :
 1744 else
 1745    msg 'ERROR: we require either the setenv(3) or putenv(3) functions.'
 1746    config_exit 1
 1747 fi
 1748 
 1749 if link_check termios 'termios.h and tc*(3) family' << \!
 1750 #include <termios.h>
 1751 int main(void){
 1752    struct termios tios;
 1753 
 1754    tcgetattr(0, &tios);
 1755    tcsetattr(0, TCSANOW | TCSADRAIN | TCSAFLUSH, &tios);
 1756    return 0;
 1757 }
 1758 !
 1759 then
 1760    :
 1761 else
 1762    msg 'ERROR: we require termios.h and the tc[gs]etattr() family of functions.'
 1763    msg 'That much Unix we indulge ourselfs.'
 1764    config_exit 1
 1765 fi
 1766 
 1767 ## optional stuff
 1768 
 1769 if link_check vsnprintf 'vsnprintf(3)' << \!
 1770 #include <stdarg.h>
 1771 #include <stdio.h>
 1772 static void dome(char *buf, size_t blen, ...){
 1773    va_list ap;
 1774 
 1775    va_start(ap, blen);
 1776    vsnprintf(buf, blen, "%s", ap);
 1777    va_end(ap);
 1778 }
 1779 int main(void){
 1780    char b[20];
 1781 
 1782    dome(b, sizeof b, "string");
 1783    return 0;
 1784 }
 1785 !
 1786 then
 1787    :
 1788 else
 1789    feat_bail_required ERRORS
 1790 fi
 1791 
 1792 if [ "${have_vsnprintf}" = yes ]; then
 1793    __va_copy() {
 1794       link_check va_copy "va_copy(3) (as ${2})" \
 1795          "#define HAVE_N_VA_COPY
 1796 #define n_va_copy ${2}" <<_EOT
 1797 #include <stdarg.h>
 1798 #include <stdio.h>
 1799 #if ${1}
 1800 # if defined __va_copy && !defined va_copy
 1801 #  define va_copy __va_copy
 1802 # endif
 1803 #endif
 1804 static void dome2(char *buf, size_t blen, va_list src){
 1805    va_list ap;
 1806 
 1807    va_copy(ap, src);
 1808    vsnprintf(buf, blen, "%s", ap);
 1809    va_end(ap);
 1810 }
 1811 static void dome(char *buf, size_t blen, ...){
 1812    va_list ap;
 1813 
 1814    va_start(ap, blen);
 1815    dome2(buf, blen, ap);
 1816    va_end(ap);
 1817 }
 1818 int main(void){
 1819    char b[20];
 1820 
 1821    dome(b, sizeof b, "string");
 1822    return 0;
 1823 }
 1824 _EOT
 1825    }
 1826    __va_copy 0 va_copy || __va_copy 1 __va_copy
 1827 fi
 1828 
 1829 run_check pathconf 'f?pathconf(2)' '#define HAVE_PATHCONF' << \!
 1830 #include <unistd.h>
 1831 #include <errno.h>
 1832 int main(void){
 1833    int rv = 0;
 1834 
 1835    errno = 0;
 1836    rv |= !(pathconf(".", _PC_NAME_MAX) >= 0 || errno == 0 || errno != ENOSYS);
 1837    errno = 0;
 1838    rv |= !(pathconf(".", _PC_PATH_MAX) >= 0 || errno == 0 || errno != ENOSYS);
 1839 
 1840    /* Only link check */
 1841    fpathconf(0, _PC_NAME_MAX);
 1842 
 1843    return rv;
 1844 }
 1845 !
 1846 
 1847 run_check pipe2 'pipe2(2)' '#define HAVE_PIPE2' << \!
 1848 #include <fcntl.h>
 1849 #include <unistd.h>
 1850 # include <errno.h>
 1851 int main(void){
 1852    int fds[2];
 1853 
 1854    if(!pipe2(fds, O_CLOEXEC) || errno != ENOSYS)
 1855       return 0;
 1856    return 1;
 1857 }
 1858 !
 1859 
 1860 link_check tcgetwinsize 'tcgetwinsize(3)' '#define HAVE_TCGETWINSIZE' << \!
 1861 #include <termios.h>
 1862 int main(void){
 1863    struct winsize ws;
 1864 
 1865    tcgetwinsize(0, &ws);
 1866    return 0;
 1867 }
 1868 !
 1869 
 1870 # We use this only then for now (need NOW+1)
 1871 run_check utimensat 'utimensat(2)' '#define HAVE_UTIMENSAT' << \!
 1872 #include <fcntl.h> /* For AT_* */
 1873 #include <sys/stat.h>
 1874 # include <errno.h>
 1875 int main(void){
 1876    struct timespec ts[2];
 1877 
 1878    ts[0].tv_nsec = UTIME_NOW;
 1879    ts[1].tv_nsec = UTIME_OMIT;
 1880    if(!utimensat(AT_FDCWD, "", ts, 0) || errno != ENOSYS)
 1881       return 0;
 1882    return 1;
 1883 }
 1884 !
 1885 
 1886 ##
 1887 
 1888 # The random check has been moved to below TLS detection due to multiple choice
 1889 # selection for PRG sources
 1890 
 1891 link_check putc_unlocked 'putc_unlocked(3)' '#define HAVE_PUTC_UNLOCKED' <<\!
 1892 #include <stdio.h>
 1893 int main(void){
 1894    putc_unlocked('@', stdout);
 1895    return 0;
 1896 }
 1897 !
 1898 
 1899 link_check fchdir 'fchdir(3)' '#define HAVE_FCHDIR' << \!
 1900 #include <unistd.h>
 1901 int main(void){
 1902    fchdir(0);
 1903    return 0;
 1904 }
 1905 !
 1906 
 1907 if link_check realpath 'realpath(3)' '#define HAVE_REALPATH' << \!
 1908 #include <stdlib.h>
 1909 int main(void){
 1910    char x_buf[4096], *x = realpath(".", x_buf);
 1911 
 1912    return (x != NULL) ? 0 : 1;
 1913 }
 1914 !
 1915 then
 1916    if run_check realpath_malloc 'realpath(3) takes NULL' \
 1917          '#define HAVE_REALPATH_NULL' << \!
 1918 #include <stdlib.h>
 1919 int main(void){
 1920    char *x = realpath(".", NULL);
 1921 
 1922    if(x != NULL)
 1923       free(x);
 1924    return (x != NULL) ? 0 : 1;
 1925 }
 1926 !
 1927    then
 1928       :
 1929    fi
 1930 fi
 1931 
 1932 ##
 1933 ## optional and selectable
 1934 ##
 1935 
 1936 if feat_yes DOTLOCK; then
 1937    if run_check readlink 'readlink(2)' << \!
 1938 #include <unistd.h>
 1939 # include <errno.h>
 1940 int main(void){
 1941    char buf[128];
 1942 
 1943    if(!readlink("here", buf, sizeof buf) || errno != ENOSYS)
 1944       return 0;
 1945    return 1;
 1946 }
 1947 !
 1948    then
 1949       :
 1950    else
 1951       feat_bail_required DOTLOCK
 1952    fi
 1953 fi
 1954 
 1955 if feat_yes DOTLOCK; then
 1956    if run_check fchown 'fchown(2)' << \!
 1957 #include <unistd.h>
 1958 # include <errno.h>
 1959 int main(void){
 1960    if(!fchown(0, 0, 0) || errno != ENOSYS)
 1961       return 0;
 1962    return 1;
 1963 }
 1964 !
 1965    then
 1966       :
 1967    else
 1968       feat_bail_required DOTLOCK
 1969    fi
 1970 fi
 1971 
 1972 if feat_yes DOTLOCK; then
 1973    if run_check prctl_dumpable 'prctl(2) + PR_SET_DUMPABLE' \
 1974          '#define HAVE_PRCTL_DUMPABLE' << \!
 1975 #include <sys/prctl.h>
 1976 # include <errno.h>
 1977 int main(void){
 1978    if(!prctl(PR_SET_DUMPABLE, 0) || errno != ENOSYS)
 1979       return 0;
 1980    return 1;
 1981 }
 1982 !
 1983    then
 1984       :
 1985    elif run_check prtrace_deny 'ptrace(2) + PT_DENY_ATTACH' \
 1986          '#define HAVE_PTRACE_DENY' << \!
 1987 #include <sys/ptrace.h>
 1988 # include <errno.h>
 1989 int main(void){
 1990    if(ptrace(PT_DENY_ATTACH, 0, 0, 0) != -1 || errno != ENOSYS)
 1991       return 0;
 1992    return 1;
 1993 }
 1994 !
 1995    then
 1996       :
 1997    elif run_check setpflags_protect 'setpflags(2) + __PROC_PROTECT' \
 1998          '#define HAVE_SETPFLAGS_PROTECT' << \!
 1999 #include <priv.h>
 2000 # include <errno.h>
 2001 int main(void){
 2002    if(!setpflags(__PROC_PROTECT, 1) || errno != ENOSYS)
 2003       return 0;
 2004    return 1;
 2005 }
 2006 !
 2007    then
 2008       :
 2009    fi
 2010 fi
 2011 
 2012 ## Now it is the time to fork away the BASE_ series
 2013 
 2014 ${rm} -f ${tmp}
 2015 squeeze_em ${inc} ${tmp}
 2016 ${mv} ${tmp} ${inc}
 2017 squeeze_em ${lib} ${tmp}
 2018 ${mv} ${tmp} ${lib}
 2019 
 2020 echo "BASE_LIBS = `${cat} ${lib}`" >> ${mk}
 2021 echo "BASE_INCS = `${cat} ${inc}`" >> ${mk}
 2022 
 2023 ## The remains are expected to be used only by the main MUA binary!
 2024 
 2025 OPT_LOCALES=0
 2026 link_check setlocale 'setlocale(3)' '#define HAVE_SETLOCALE' << \!
 2027 #include <locale.h>
 2028 int main(void){
 2029    setlocale(LC_ALL, "");
 2030    return 0;
 2031 }
 2032 !
 2033 [ -n "${have_setlocale}" ] && OPT_LOCALES=1
 2034 
 2035 OPT_MULTIBYTE_CHARSETS=0
 2036 OPT_WIDE_GLYPHS=0
 2037 OPT_TERMINAL_CHARSET=0
 2038 if [ -n "${have_setlocale}" ]; then
 2039    link_check c90amend1 'ISO/IEC 9899:1990/Amendment 1:1995' \
 2040       '#define HAVE_C90AMEND1' << \!
 2041 #include <limits.h>
 2042 #include <stdlib.h>
 2043 #include <wchar.h>
 2044 #include <wctype.h>
 2045 int main(void){
 2046    char mbb[MB_LEN_MAX + 1];
 2047    wchar_t wc;
 2048 
 2049    iswprint(L'c');
 2050    towupper(L'c');
 2051    mbtowc(&wc, "x", 1);
 2052    mbrtowc(&wc, "x", 1, NULL);
 2053    wctomb(mbb, wc);
 2054    return (mblen("\0", 1) == 0);
 2055 }
 2056 !
 2057    [ -n "${have_c90amend1}" ] && OPT_MULTIBYTE_CHARSETS=1
 2058 
 2059    if [ -n "${have_c90amend1}" ]; then
 2060       link_check wcwidth 'wcwidth(3)' '#define HAVE_WCWIDTH' << \!
 2061 #include <wchar.h>
 2062 int main(void){
 2063    wcwidth(L'c');
 2064    return 0;
 2065 }
 2066 !
 2067       [ -n "${have_wcwidth}" ] && OPT_WIDE_GLYPHS=1
 2068    fi
 2069 
 2070    link_check nl_langinfo 'nl_langinfo(3)' '#define HAVE_NL_LANGINFO' << \!
 2071 #include <langinfo.h>
 2072 #include <stdlib.h>
 2073 int main(void){
 2074    nl_langinfo(DAY_1);
 2075    return (nl_langinfo(CODESET) == NULL);
 2076 }
 2077 !
 2078    [ -n "${have_nl_langinfo}" ] && OPT_TERMINAL_CHARSET=1
 2079 fi # have_setlocale
 2080 
 2081 link_check fnmatch 'fnmatch(3)' '#define HAVE_FNMATCH' << \!
 2082 #include <fnmatch.h>
 2083 int main(void){
 2084    return (fnmatch("*", ".", FNM_PATHNAME | FNM_PERIOD) == FNM_NOMATCH);
 2085 }
 2086 !
 2087 
 2088 link_check dirent_d_type 'struct dirent.d_type' '#define HAVE_DIRENT_TYPE' << \!
 2089 #include <dirent.h>
 2090 int main(void){
 2091    struct dirent de;
 2092    return !(de.d_type == DT_UNKNOWN ||
 2093       de.d_type == DT_DIR || de.d_type == DT_LNK);
 2094 }
 2095 !
 2096 
 2097 ## optional and selectable
 2098 
 2099 if feat_yes ICONV; then
 2100    # To be able to create tests we need to figure out which replacement
 2101    # sequence the iconv(3) implementation creates
 2102    ${cat} > ${tmp2}.c << \!
 2103 #include <stdio.h> /* For C89 NULL */
 2104 #include <string.h>
 2105 #include <iconv.h>
 2106 int main(void){
 2107    char inb[16], oub[16], *inbp, *oubp;
 2108    iconv_t id;
 2109    size_t inl, oul;
 2110 
 2111    memcpy(inbp = inb, "\342\200\223", sizeof("\342\200\223"));
 2112    inl = sizeof("\342\200\223") -1;
 2113    oul = sizeof oub;
 2114    oubp = oub;
 2115 
 2116    if((id = iconv_open("ascii", "utf-8")) == (iconv_t)-1)
 2117      return 1;
 2118    if(iconv(id, &inbp, &inl, &oubp, &oul) == (size_t)-1)
 2119       return 1;
 2120    iconv_close(id);
 2121 
 2122    *oubp = '\0';
 2123    oul = (size_t)(oubp - oub);
 2124    if(oul == 0)
 2125       return 1;
 2126    /* Character-wise replacement? */
 2127    if(oul == 1){
 2128       if(oub[0] == '?')
 2129          return 2;
 2130       if(oub[0] == '*')
 2131          return 3;
 2132       return 1;
 2133    }
 2134    /* Byte-wise replacement? */
 2135    if(oul == sizeof("\342\200\223") -1){
 2136       if(!memcmp(oub, "???????", sizeof("\342\200\223") -1))
 2137          return 12;
 2138       if(!memcmp(oub, "*******", sizeof("\342\200\223") -1))
 2139          return 13;
 2140       return 1;
 2141    }
 2142    return 0;
 2143 }
 2144 !
 2145    < ${tmp2}.c link_check iconv 'iconv(3) functionality' \
 2146          '#define HAVE_ICONV' ||
 2147       < ${tmp2}.c link_check iconv 'iconv(3) functionality (via -liconv)' \
 2148          '#define HAVE_ICONV' '-liconv' ||
 2149       feat_bail_required ICONV
 2150 
 2151    if feat_no CROSS_BUILD; then
 2152       { ${tmp}; } >/dev/null 2>&1
 2153       case ${?} in
 2154       2) echo 'MAILX_ICONV_MODE=2;export MAILX_ICONV_MODE;' >> ${ev};;
 2155       3) echo 'MAILX_ICONV_MODE=3;export MAILX_ICONV_MODE;' >> ${ev};;
 2156       12) echo 'MAILX_ICONV_MODE=12;export MAILX_ICONV_MODE;' >> ${ev};;
 2157       13) echo 'MAILX_ICONV_MODE=13;export MAILX_ICONV_MODE;' >> ${ev};;
 2158       *) msg 'WARN: will restrict iconv(3) tests due to unknown replacement';;
 2159       esac
 2160    fi
 2161 else
 2162    feat_is_disabled ICONV
 2163 fi # feat_yes ICONV
 2164 
 2165 if feat_yes SOCKETS || feat_yes SPAM_SPAMD; then
 2166    ${cat} > ${tmp2}.c << \!
 2167 #include <sys/types.h>
 2168 #include <sys/socket.h>
 2169 #include <sys/un.h>
 2170 # include <errno.h>
 2171 int main(void){
 2172    struct sockaddr_un soun;
 2173 
 2174    if(socket(AF_UNIX, SOCK_STREAM, 0) == -1 && errno == ENOSYS)
 2175       return 1;
 2176    if(connect(0, (struct sockaddr*)&soun, 0) == -1 && errno == ENOSYS)
 2177       return 1;
 2178    if(shutdown(0, SHUT_RD | SHUT_WR | SHUT_RDWR) == -1 && errno == ENOSYS)
 2179       return 1;
 2180    return 0;
 2181 }
 2182 !
 2183 
 2184    < ${tmp2}.c run_check af_unix 'AF_UNIX sockets' \
 2185          '#define HAVE_UNIX_SOCKETS' ||
 2186       < ${tmp2}.c run_check af_unix 'AF_UNIX sockets (via -lnsl)' \
 2187          '#define HAVE_UNIX_SOCKETS' '-lnsl' ||
 2188       < ${tmp2}.c run_check af_unix 'AF_UNIX sockets (via -lsocket -lnsl)' \
 2189          '#define HAVE_UNIX_SOCKETS' '-lsocket -lnsl'
 2190 fi
 2191 
 2192 if feat_yes SOCKETS; then
 2193    ${cat} > ${tmp2}.c << \!
 2194 #include <sys/types.h>
 2195 #include <sys/socket.h>
 2196 #include <netinet/in.h>
 2197 # include <errno.h>
 2198 int main(void){
 2199    struct sockaddr s;
 2200 
 2201    if(socket(AF_INET, SOCK_STREAM, 0) == -1 && errno == ENOSYS)
 2202       return 1;
 2203    if(connect(0, &s, 0) == -1 && errno == ENOSYS)
 2204       return 1;
 2205    return 0;
 2206 }
 2207 !
 2208 
 2209    < ${tmp2}.c run_check sockets 'sockets' \
 2210          '#define HAVE_SOCKETS' ||
 2211       < ${tmp2}.c run_check sockets 'sockets (via -lnsl)' \
 2212          '#define HAVE_SOCKETS' '-lnsl' ||
 2213       < ${tmp2}.c run_check sockets 'sockets (via -lsocket -lnsl)' \
 2214          '#define HAVE_SOCKETS' '-lsocket -lnsl' ||
 2215       feat_bail_required SOCKETS
 2216 else
 2217    feat_is_disabled SOCKETS
 2218 fi # feat_yes SOCKETS
 2219 
 2220 feat_yes SOCKETS &&
 2221    link_check sockopt '[gs]etsockopt(2)' '#define HAVE_SOCKOPT' << \!
 2222 #include <sys/socket.h>
 2223 #include <stdlib.h>
 2224 # include <errno.h>
 2225 int main(void){
 2226    socklen_t sol;
 2227    int sockfd = 3, soe;
 2228 
 2229    sol = sizeof soe;
 2230    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &soe, &sol) == -1 &&
 2231          errno == ENOSYS)
 2232       return 1;
 2233    if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == -1 &&
 2234          errno == ENOSYS)
 2235       return 1;
 2236    return 0;
 2237 }
 2238 !
 2239 
 2240 feat_yes SOCKETS &&
 2241    link_check nonblocksock 'non-blocking sockets' \
 2242       '#define HAVE_NONBLOCKSOCK' << \!
 2243 #include <sys/types.h>
 2244 #include <sys/select.h>
 2245 #include <sys/socket.h>
 2246 #include <sys/time.h>
 2247 #include <arpa/inet.h>
 2248 #include <netinet/in.h>
 2249 #include <fcntl.h>
 2250 #include <stdlib.h>
 2251 #include <unistd.h>
 2252 # include <errno.h>
 2253 int main(void){
 2254    fd_set fdset;
 2255    struct timeval tv;
 2256    struct sockaddr_in sin;
 2257    socklen_t sol;
 2258    int sofd, soe;
 2259 
 2260    if((sofd = socket(AF_INET, SOCK_STREAM, 0)) == -1 && errno == ENOSYS)
 2261       return 1;
 2262    if(fcntl(sofd, F_SETFL, O_NONBLOCK) != 0)
 2263       return 1;
 2264 
 2265    sin.sin_family = AF_INET;
 2266    sin.sin_addr.s_addr = inet_addr("127.0.0.1");
 2267    sin.sin_port = htons(80);
 2268    if(connect(sofd, &sin, sizeof sin) == -1 && errno == ENOSYS)
 2269       return 1;
 2270 
 2271    FD_ZERO(&fdset);
 2272    FD_SET(sofd, &fdset);
 2273    tv.tv_sec = 10;
 2274    tv.tv_usec = 0;
 2275    if((soe = select(sofd + 1, NULL, &fdset, NULL, &tv)) == 1){
 2276       sol = sizeof soe;
 2277       getsockopt(sofd, SOL_SOCKET, SO_ERROR, &soe, &sol);
 2278       if(soe == 0)
 2279          return 0;
 2280    }else if(soe == -1 && errno == ENOSYS)
 2281       return 1;
 2282 
 2283    close(sofd);
 2284    return 0;
 2285 }
 2286 !
 2287 
 2288 if feat_yes SOCKETS; then
 2289    link_check getaddrinfo 'getaddrinfo(3)' \
 2290       '#define HAVE_GETADDRINFO' << \!
 2291 #include <sys/types.h>
 2292 #include <sys/socket.h>
 2293 #include <stdio.h>
 2294 #include <netdb.h>
 2295 int main(void){
 2296    struct addrinfo a, *ap;
 2297    int lrv;
 2298 
 2299    switch((lrv = getaddrinfo("foo", "0", &a, &ap))){
 2300    case EAI_NONAME:
 2301    case EAI_SERVICE:
 2302    default:
 2303       fprintf(stderr, "%s\n", gai_strerror(lrv));
 2304    case 0:
 2305       break;
 2306    }
 2307    return 0;
 2308 }
 2309 !
 2310 fi
 2311 
 2312 if feat_yes SOCKETS && [ -z "${have_getaddrinfo}" ]; then
 2313    compile_check arpa_inet_h '<arpa/inet.h>' \
 2314       '#define HAVE_ARPA_INET_H' << \!
 2315 #include <sys/types.h>
 2316 #include <sys/socket.h>
 2317 #include <netdb.h>
 2318 #include <netinet/in.h>
 2319 #include <arpa/inet.h>
 2320 !
 2321 
 2322    ${cat} > ${tmp2}.c << \!
 2323 #include <sys/types.h>
 2324 #include <sys/socket.h>
 2325 #include <stdio.h>
 2326 #include <string.h>
 2327 #include <netdb.h>
 2328 #include <netinet/in.h>
 2329 #ifdef HAVE_ARPA_INET_H
 2330 #include <arpa/inet.h>
 2331 #endif
 2332 int main(void){
 2333    struct sockaddr_in servaddr;
 2334    unsigned short portno;
 2335    struct servent *ep;
 2336    struct hostent *hp;
 2337    struct in_addr **pptr;
 2338 
 2339    portno = 0;
 2340    if((ep = getservbyname("POPPY-PORT", "tcp")) != NULL)
 2341       portno = (unsigned short)ep->s_port;
 2342 
 2343    if((hp = gethostbyname("POPPY-HOST")) != NULL){
 2344       pptr = (struct in_addr**)hp->h_addr_list;
 2345       if(hp->h_addrtype != AF_INET)
 2346          fprintf(stderr, "au\n");
 2347    }else{
 2348       switch(h_errno){
 2349       case HOST_NOT_FOUND:
 2350       case TRY_AGAIN:
 2351       case NO_RECOVERY:
 2352       case NO_DATA:
 2353          break;
 2354       default:
 2355          fprintf(stderr, "au\n");
 2356          break;
 2357       }
 2358    }
 2359 
 2360    memset(&servaddr, 0, sizeof servaddr);
 2361    servaddr.sin_family = AF_INET;
 2362    servaddr.sin_port = htons(portno);
 2363    memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));
 2364    fprintf(stderr, "Would connect to %s:%d ...\n",
 2365       inet_ntoa(**pptr), (int)portno);
 2366    return 0;
 2367 }
 2368 !
 2369 
 2370    < ${tmp2}.c link_check gethostbyname 'get(serv|host)byname(3)' ||
 2371       < ${tmp2}.c link_check gethostbyname \
 2372          'get(serv|host)byname(3) (via -nsl)' '' '-lnsl' ||
 2373       < ${tmp2}.c link_check gethostbyname \
 2374          'get(serv|host)byname(3) (via -lsocket -nsl)' \
 2375          '' '-lsocket -lnsl' ||
 2376       feat_bail_required SOCKETS
 2377 fi
 2378 
 2379 feat_yes SOCKETS && [ -n "${have_sockopt}" ] &&
 2380    link_check so_xtimeo 'SO_{RCV,SND}TIMEO' '#define HAVE_SO_XTIMEO' << \!
 2381 #include <sys/socket.h>
 2382 #include <stdlib.h>
 2383 int main(void){
 2384    struct timeval tv;
 2385    int sockfd = 3;
 2386 
 2387    tv.tv_sec = 42;
 2388    tv.tv_usec = 21;
 2389    setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
 2390    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
 2391    return 0;
 2392 }
 2393 !
 2394 
 2395 feat_yes SOCKETS && [ -n "${have_sockopt}" ] &&
 2396    link_check so_linger 'SO_LINGER' '#define HAVE_SO_LINGER' << \!
 2397 #include <sys/socket.h>
 2398 #include <stdlib.h>
 2399 int main(void){
 2400    struct linger li;
 2401    int sockfd = 3;
 2402 
 2403    li.l_onoff = 1;
 2404    li.l_linger = 42;
 2405    setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &li, sizeof li);
 2406    return 0;
 2407 }
 2408 !
 2409 
 2410 VAL_TLS_FEATURES=
 2411 if feat_yes TLS; then # {{{
 2412    # {{{ LibreSSL decided to define OPENSSL_VERSION_NUMBER with a useless value
 2413    # instead of keeping it at the one that corresponds to the OpenSSL at fork
 2414    # time: we need to test it first in order to get things right
 2415    if compile_check _xtls 'TLS (LibreSSL)' \
 2416       '#define HAVE_TLS
 2417       #define HAVE_XTLS
 2418       #define HAVE_XTLS_RESSL
 2419       #define HAVE_XTLS_OPENSSL 0' << \!
 2420 #include <openssl/opensslv.h>
 2421 #ifdef LIBRESSL_VERSION_NUMBER
 2422 #else
 2423 # error nope
 2424 #endif
 2425 !
 2426    then
 2427       ossl_v1_1=
 2428       VAL_TLS_FEATURES=libressl
 2429    # TODO OPENSSL_IS_BORINGSSL, but never tried that one!
 2430    elif compile_check _xtls 'TLS (OpenSSL >= v1.1.0)' \
 2431       '#define HAVE_TLS
 2432       #define HAVE_XTLS
 2433       #define HAVE_XTLS_OPENSSL 0x10100' << \!
 2434 #include <openssl/opensslv.h>
 2435 #if OPENSSL_VERSION_NUMBER + 0 >= 0x10100000L
 2436 #else
 2437 # error nope
 2438 #endif
 2439 !
 2440    then
 2441       ossl_v1_1=1
 2442       VAL_TLS_FEATURES=libssl-0x10100
 2443    elif compile_check _xtls 'TLS (OpenSSL)' \
 2444       '#define HAVE_TLS
 2445       #define HAVE_XTLS
 2446       #define HAVE_XTLS_OPENSSL 0x10000' << \!
 2447 #include <openssl/opensslv.h>
 2448 #ifdef OPENSSL_VERSION_NUMBER
 2449 #else
 2450 # error nope
 2451 #endif
 2452 !
 2453    then
 2454       ossl_v1_1=
 2455       VAL_TLS_FEATURES=libssl-0x10000
 2456    else
 2457       feat_bail_required TLS
 2458    fi # }}}
 2459 
 2460    if feat_yes TLS; then # {{{
 2461       if [ -n "${ossl_v1_1}" ]; then
 2462          without_check yes xtls 'TLS new style TLS_client_method(3ssl)' \
 2463             '#define n_XTLS_CLIENT_METHOD TLS_client_method' \
 2464             '-lssl -lcrypto'
 2465       elif link_check xtls 'TLS new style TLS_client_method(3ssl)' \
 2466             '#define n_XTLS_CLIENT_METHOD TLS_client_method' \
 2467             '-lssl -lcrypto' << \!
 2468 #include <openssl/ssl.h>
 2469 #include <openssl/err.h>
 2470 #include <openssl/x509v3.h>
 2471 #include <openssl/x509.h>
 2472 #include <openssl/rand.h>
 2473 #ifdef OPENSSL_NO_TLS1 /* TODO only deduced from OPENSSL_NO_SSL[23]! */
 2474 # error We need TLSv1.
 2475 #endif
 2476 int main(void){
 2477    SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
 2478 
 2479    SSL_CTX_free(ctx);
 2480    PEM_read_PrivateKey(0, 0, 0, 0);
 2481    return 0;
 2482 }
 2483 !
 2484       then
 2485          :
 2486       elif link_check xtls 'TLS old style SSLv23_client_method(3ssl)' \
 2487             '#define n_XTLS_CLIENT_METHOD SSLv23_client_method' \
 2488             '-lssl -lcrypto' << \!
 2489 #include <openssl/ssl.h>
 2490 #include <openssl/err.h>
 2491 #include <openssl/x509v3.h>
 2492 #include <openssl/x509.h>
 2493 #include <openssl/rand.h>
 2494 #if defined OPENSSL_NO_SSL3 &&\
 2495       defined OPENSSL_NO_TLS1 /* TODO only deduced from OPENSSL_NO_SSL[23]! */
 2496 # error We need one of SSLv3 and TLSv1.
 2497 #endif
 2498 int main(void){
 2499    SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
 2500 
 2501    SSL_CTX_free(ctx);
 2502    PEM_read_PrivateKey(0, 0, 0, 0);
 2503    return 0;
 2504 }
 2505 !
 2506       then
 2507          :
 2508       else
 2509          feat_bail_required TLS
 2510       fi
 2511    fi # }}}
 2512 
 2513    if feat_yes TLS; then # {{{
 2514       if [ -n "${ossl_v1_1}" ]; then
 2515          without_check yes xtls_stack_of 'TLS STACK_OF()' \
 2516             '#define HAVE_XTLS_STACK_OF'
 2517       elif compile_check xtls_stack_of 'TLS STACK_OF()' \
 2518             '#define HAVE_XTLS_STACK_OF' << \!
 2519 #include <stdio.h> /* For C89 NULL */
 2520 #include <openssl/ssl.h>
 2521 #include <openssl/err.h>
 2522 #include <openssl/x509v3.h>
 2523 #include <openssl/x509.h>
 2524 #include <openssl/rand.h>
 2525 int main(void){
 2526    STACK_OF(GENERAL_NAME) *gens = NULL;
 2527 
 2528    printf("%p", gens); /* to use it */
 2529    return 0;
 2530 }
 2531 !
 2532       then
 2533          :
 2534       fi
 2535 
 2536       if [ -n "${ossl_v1_1}" ]; then
 2537          without_check yes xtls_conf 'TLS OpenSSL_modules_load_file(3ssl)' \
 2538             '#define HAVE_XTLS_CONFIG'
 2539          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+modules-load-file"
 2540       elif link_check xtls_conf \
 2541             'TLS OpenSSL_modules_load_file(3ssl) support' \
 2542             '#define HAVE_XTLS_CONFIG' << \!
 2543 #include <stdio.h> /* For C89 NULL */
 2544 #include <openssl/conf.h>
 2545 int main(void){
 2546    CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_IGNORE_MISSING_FILE);
 2547    CONF_modules_free();
 2548    return 0;
 2549 }
 2550 !
 2551       then
 2552          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+modules-load-file"
 2553       else
 2554          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},-modules-load-file"
 2555       fi
 2556 
 2557       if [ -n "${ossl_v1_1}" ]; then
 2558          without_check yes xtls_conf_ctx 'TLS SSL_CONF_CTX support' \
 2559             '#define HAVE_XTLS_CONF_CTX'
 2560          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+conf-ctx"
 2561       elif link_check xtls_conf_ctx 'TLS SSL_CONF_CTX support' \
 2562          '#define HAVE_XTLS_CONF_CTX' << \!
 2563 #include <openssl/ssl.h>
 2564 #include <openssl/err.h>
 2565 int main(void){
 2566    SSL_CTX *ctx = SSL_CTX_new(n_XSSL_CLIENT_METHOD());
 2567    SSL_CONF_CTX *cctx = SSL_CONF_CTX_new();
 2568 
 2569    SSL_CONF_CTX_set_flags(cctx,
 2570       SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_CLIENT |
 2571       SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_SHOW_ERRORS);
 2572    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
 2573    SSL_CONF_cmd(cctx, "Protocol", "ALL");
 2574    SSL_CONF_CTX_finish(cctx);
 2575    SSL_CONF_CTX_free(cctx);
 2576    SSL_CTX_free(ctx);
 2577    return 0;
 2578 }
 2579 !
 2580       then
 2581          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+conf-ctx"
 2582       else
 2583          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},-conf-ctx"
 2584       fi
 2585 
 2586       if [ -n "${ossl_v1_1}" ]; then
 2587          without_check yes xtls_ctx_config 'TLS SSL_CTX_config(3ssl)' \
 2588             '#define HAVE_XTLS_CTX_CONFIG'
 2589          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-config"
 2590       elif [ -n "${have_xtls_conf}" ] && [ -n "${have_xtls_conf_ctx}" ] &&
 2591             link_check xtls_ctx_config 'TLS SSL_CTX_config(3ssl)' \
 2592                '#define HAVE_XTLS_CTX_CONFIG' << \!
 2593 #include <stdio.h> /* For C89 NULL */
 2594 #include <openssl/ssl.h>
 2595 int main(void){
 2596    SSL_CTX_config(NULL, "SOMEVAL");
 2597    return 0;
 2598 }
 2599 !
 2600       then
 2601          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-config"
 2602       else
 2603          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},-ctx-config"
 2604       fi
 2605 
 2606       if [ -n "${ossl_v1_1}" ] && [ -n "${have_xtls_conf_ctx}" ]; then
 2607          without_check yes xtls_set_maxmin_proto \
 2608             'TLS SSL_CTX_set_min_proto_version(3ssl)' \
 2609             '#define HAVE_XTLS_SET_MIN_PROTO_VERSION'
 2610          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-set-maxmin-proto"
 2611       elif link_check xtls_set_maxmin_proto \
 2612          'TLS SSL_CTX_set_min_proto_version(3ssl)' \
 2613          '#define HAVE_XTLS_SET_MIN_PROTO_VERSION' << \!
 2614 #include <stdio.h> /* For C89 NULL */
 2615 #include <openssl/ssl.h>
 2616 int main(void){
 2617    SSL_CTX_set_min_proto_version(NULL, 0);
 2618    SSL_CTX_set_max_proto_version(NULL, 10);
 2619    return 0;
 2620 }
 2621 !
 2622       then
 2623          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-set-maxmin-proto"
 2624       else
 2625          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},-ctx-set-maxmin-proto"
 2626       fi
 2627 
 2628       if [ -n "${ossl_v1_1}" ] && [ -n "${have_xtls_conf_ctx}" ]; then
 2629          without_check yes xtls_set_ciphersuites \
 2630             'TLSv1.3 SSL_CTX_set_ciphersuites(3ssl)' \
 2631             '#define HAVE_XTLS_SET_CIPHERSUITES'
 2632          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-set-ciphersuites"
 2633       elif link_check xtls_set_ciphersuites \
 2634          'TLSv1.3 SSL_CTX_set_ciphersuites(3ssl)' \
 2635          '#define HAVE_XTLS_SET_CIPHERSUITES' << \!
 2636 #include <stdio.h> /* For C89 NULL */
 2637 #include <openssl/ssl.h>
 2638 int main(void){
 2639    SSL_CTX_set_ciphersuites(NULL, NULL);
 2640    return 0;
 2641 }
 2642 !
 2643       then
 2644          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},+ctx-set-ciphersuites"
 2645       else
 2646          VAL_TLS_FEATURES="${VAL_TLS_FEATURES},-ctx-set-ciphersuites"
 2647       fi
 2648    fi # feat_yes SSL }}}
 2649 
 2650    if feat_yes TLS; then # digest etc algorithms {{{
 2651       if feat_yes TLS_ALL_ALGORITHMS; then
 2652          if [ -n "${ossl_v1_1}" ]; then
 2653             without_check yes tls_all_algo 'TLS all-algorithms support' \
 2654                '#define HAVE_TLS_ALL_ALGORITHMS'
 2655          elif link_check tls_all_algo 'TLS all-algorithms support' \
 2656             '#define HAVE_TLS_ALL_ALGORITHMS' << \!
 2657 #include <openssl/evp.h>
 2658 int main(void){
 2659    OpenSSL_add_all_algorithms();
 2660    EVP_get_cipherbyname("two cents i never exist");
 2661    EVP_cleanup();
 2662    return 0;
 2663 }
 2664 !
 2665          then
 2666             :
 2667          else
 2668             feat_bail_required TLS_ALL_ALGORITHMS
 2669          fi
 2670       elif [ -n "${ossl_v1_1}" ]; then
 2671          without_check yes tls_all_algo \
 2672             'TLS all-algorithms (always available in v1.1.0+)' \
 2673             '#define HAVE_TLS_ALL_ALGORITHMS'
 2674       fi
 2675 
 2676       # Blake
 2677       link_check tls_blake2 'TLS: BLAKE2 digests' \
 2678             '#define HAVE_XTLS_BLAKE2' << \!
 2679 #include <openssl/evp.h>
 2680 int main(void){
 2681    EVP_blake2b512();
 2682    EVP_blake2s256();
 2683    return 0;
 2684 }
 2685 !
 2686 
 2687       # SHA-3
 2688       link_check tls_sha3 'TLS: SHA-3 digests' '#define HAVE_XTLS_SHA3' << \!
 2689 #include <openssl/evp.h>
 2690 int main(void){
 2691    EVP_sha3_512();
 2692    EVP_sha3_384();
 2693    EVP_sha3_256();
 2694    EVP_sha3_224();
 2695    return 0;
 2696 }
 2697 !
 2698 
 2699       if feat_yes MD5 && feat_no NOEXTMD5; then
 2700          run_check tls_md5 'TLS: MD5 digest' '#define HAVE_XTLS_MD5' << \!
 2701 #include <stdlib.h>
 2702 #include <string.h>
 2703 #include <openssl/md5.h>
 2704 int main(void){
 2705    char const dat[] = "abrakadabrafidibus";
 2706    char dig[16], hex[16 * 2];
 2707    MD5_CTX ctx;
 2708    size_t i, j;
 2709 
 2710    memset(dig, 0, sizeof(dig));
 2711    memset(hex, 0, sizeof(hex));
 2712    MD5_Init(&ctx);
 2713    MD5_Update(&ctx, dat, sizeof(dat) - 1);
 2714    MD5_Final(dig, &ctx);
 2715 
 2716 #define hexchar(n) ((n) > 9 ? (n) - 10 + 'a' : (n) + '0')
 2717    for(i = 0; i < sizeof(hex) / 2; i++){
 2718       j = i << 1;
 2719       hex[j] = hexchar((dig[i] & 0xf0) >> 4);
 2720       hex[++j] = hexchar(dig[i] & 0x0f);
 2721    }
 2722    return !!memcmp("6d7d0a3d949da2e96f2aa010f65d8326", hex, sizeof(hex));
 2723 }
 2724 !
 2725       fi
 2726    fi # }}}
 2727 
 2728    if feat_yes TLS; then
 2729       feat_def TLS_ALL_ALGORITHMS
 2730    else
 2731       feat_bail_required TLS_ALL_ALGORITHMS
 2732    fi
 2733 else
 2734    feat_is_disabled TLS
 2735    feat_is_disabled TLS_ALL_ALGORITHMS
 2736 fi # }}} feat_yes TLS
 2737 printf '#define VAL_TLS_FEATURES "#'"${VAL_TLS_FEATURES}"'"\n' >> ${h}
 2738 
 2739 if [ "${have_xtls}" = yes ]; then
 2740    OPT_SMIME=1
 2741 else
 2742    OPT_SMIME=0
 2743 fi
 2744 feat_def SMIME
 2745 
 2746 # VAL_RANDOM {{{
 2747 if val_allof VAL_RANDOM \
 2748       "arc4,tls,libgetrandom,sysgetrandom,urandom,builtin,error"; then
 2749    :
 2750 else
 2751    msg 'ERROR: VAL_RANDOM with invalid entries: %s' "${VAL_RANDOM}"
 2752    config_exit 1
 2753 fi
 2754 
 2755 val_random_arc4() {
 2756    link_check arc4random 'VAL_RANDOM: arc4random(3)' \
 2757       '#define HAVE_RANDOM n_RANDOM_IMPL_ARC4' << \!
 2758 #include <stdlib.h>
 2759 int main(void){
 2760    arc4random();
 2761    return 0;
 2762 }
 2763 !
 2764 }
 2765 
 2766 val_random_tls() {
 2767    if feat_yes TLS; then
 2768       msg ' . VAL_RANDOM: tls ... yes'
 2769       echo '#define HAVE_RANDOM n_RANDOM_IMPL_TLS' >> ${h}
 2770       return 0
 2771    else
 2772       msg ' . VAL_RANDOM: tls ... no'
 2773       return 1
 2774    fi
 2775 }
 2776 
 2777 val_random_libgetrandom() {
 2778    link_check getrandom 'VAL_RANDOM: getrandom(3) (in sys/random.h)' \
 2779       '#define HAVE_RANDOM n_RANDOM_IMPL_GETRANDOM
 2780       #define n_RANDOM_GETRANDOM_FUN(B,S) getrandom(B, S, 0)
 2781       #define n_RANDOM_GETRANDOM_H <sys/random.h>' <<\!
 2782 #include <sys/random.h>
 2783 int main(void){
 2784    char buf[256];
 2785    getrandom(buf, sizeof buf, 0);
 2786    return 0;
 2787 }
 2788 !
 2789 }
 2790 
 2791 val_random_sysgetrandom() {
 2792    link_check getrandom 'VAL_RANDOM: getrandom(2) (via syscall(2))' \
 2793       '#define HAVE_RANDOM n_RANDOM_IMPL_GETRANDOM
 2794       #define n_RANDOM_GETRANDOM_FUN(B,S) syscall(SYS_getrandom, B, S, 0)
 2795       #define n_RANDOM_GETRANDOM_H <sys/syscall.h>' <<\!
 2796 #include <sys/syscall.h>
 2797 int main(void){
 2798    char buf[256];
 2799    syscall(SYS_getrandom, buf, sizeof buf, 0);
 2800    return 0;
 2801 }
 2802 !
 2803 }
 2804 
 2805 val_random_urandom() {
 2806    msg_nonl ' . VAL_RANDOM: /dev/urandom ... '
 2807    if feat_yes CROSS_BUILD; then
 2808       msg 'yes (unchecked)'
 2809       echo '#define HAVE_RANDOM n_RANDOM_IMPL_URANDOM' >> ${h}
 2810    elif [ -f /dev/urandom ]; then
 2811       msg yes
 2812       echo '#define HAVE_RANDOM n_RANDOM_IMPL_URANDOM' >> ${h}
 2813    else
 2814       msg no
 2815       return 1
 2816    fi
 2817    return 0
 2818 }
 2819 
 2820 val_random_builtin() {
 2821    msg_nonl ' . VAL_RANDOM: builtin ... '
 2822    if [ -n "${have_no_subsecond_time}" ]; then
 2823       msg 'no\nERROR: %s %s' 'without a specialized PRG ' \
 2824          'one of clock_gettime(2) and gettimeofday(2) is required.'
 2825       config_exit 1
 2826    else
 2827       msg yes
 2828       echo '#define HAVE_RANDOM n_RANDOM_IMPL_BUILTIN' >> ${h}
 2829    fi
 2830 }
 2831 
 2832 val_random_error() {
 2833    msg 'ERROR: VAL_RANDOM search reached "error" entry'
 2834    config_exit 42
 2835 }
 2836 
 2837 oifs=${IFS}
 2838 IFS=", "
 2839 VAL_RANDOM="${VAL_RANDOM},error"
 2840 set -- ${VAL_RANDOM}
 2841 IFS=${oifs}
 2842 for randfun
 2843 do
 2844    eval val_random_$randfun && break
 2845 done
 2846 # }}} VAL_RANDOM
 2847 
 2848 feat_def SMTP
 2849 feat_def POP3
 2850 feat_def IMAP
 2851 
 2852 if feat_yes GSSAPI; then
 2853    ${cat} > ${tmp2}.c << \!
 2854 #include <gssapi/gssapi.h>
 2855 int main(void){
 2856    gss_import_name(0, 0, GSS_C_NT_HOSTBASED_SERVICE, 0);
 2857    gss_init_sec_context(0,0,0,0,0,0,0,0,0,0,0,0,0);
 2858    return 0;
 2859 }
 2860 !
 2861    ${sed} -e '1s/gssapi\///' < ${tmp2}.c > ${tmp3}.c
 2862 
 2863    if acmd_set i krb5-config; then
 2864       GSS_LIBS="`CFLAGS= ${i} --libs gssapi`"
 2865       GSS_INCS="`CFLAGS= ${i} --cflags`"
 2866       i='GSS-API via krb5-config(1)'
 2867    else
 2868       GSS_LIBS='-lgssapi'
 2869       GSS_INCS=
 2870       i='GSS-API in gssapi/gssapi.h, libgssapi'
 2871    fi
 2872    if < ${tmp2}.c link_check gss \
 2873          "${i}" '#define HAVE_GSSAPI' "${GSS_LIBS}" "${GSS_INCS}" ||\
 2874       < ${tmp3}.c link_check gss \
 2875          'GSS-API in gssapi.h, libgssapi' \
 2876          '#define HAVE_GSSAPI
 2877          #define GSSAPI_REG_INCLUDE' \
 2878          '-lgssapi' ||\
 2879       < ${tmp2}.c link_check gss 'GSS-API in libgssapi_krb5' \
 2880          '#define HAVE_GSSAPI' \
 2881          '-lgssapi_krb5' ||\
 2882       < ${tmp3}.c link_check gss \
 2883          'GSS-API in libgssapi, OpenBSD-style (pre 5.3)' \
 2884          '#define HAVE_GSSAPI
 2885          #define GSS_REG_INCLUDE' \
 2886          '-lgssapi -lkrb5 -lcrypto' \
 2887          '-I/usr/include/kerberosV' ||\
 2888       < ${tmp2}.c link_check gss 'GSS-API in libgss' \
 2889          '#define HAVE_GSSAPI' \
 2890          '-lgss' ||\
 2891       link_check gss 'GSS-API in libgssapi_krb5, old-style' \
 2892          '#define HAVE_GSSAPI
 2893          #define GSSAPI_OLD_STYLE' \
 2894          '-lgssapi_krb5' << \!
 2895 #include <gssapi/gssapi.h>
 2896 #include <gssapi/gssapi_generic.h>
 2897 int main(void){
 2898    gss_import_name(0, 0, gss_nt_service_name, 0);
 2899    gss_init_sec_context(0,0,0,0,0,0,0,0,0,0,0,0,0);
 2900    return 0;
 2901 }
 2902 !
 2903    then
 2904       :
 2905    else
 2906       feat_bail_required GSSAPI
 2907    fi
 2908 else
 2909    feat_is_disabled GSSAPI
 2910 fi # feat_yes GSSAPI
 2911 
 2912 feat_def NETRC
 2913 feat_def AGENT
 2914 
 2915 if feat_yes IDNA; then # {{{
 2916    if val_allof VAL_IDNA "idnkit,idn2,idn"; then
 2917       :
 2918    else
 2919       msg 'ERROR: VAL_IDNA with invalid entries: %s' "${VAL_IDNA}"
 2920       config_exit 1
 2921    fi
 2922 
 2923    val_idna_idn2() {
 2924       link_check idna 'OPT_IDNA: GNU Libidn2' \
 2925          '#define HAVE_IDNA n_IDNA_IMPL_LIBIDN2' '-lidn2' << \!
 2926 #include <idn2.h>
 2927 int main(void){
 2928    char *idna_utf8, *idna_lc;
 2929 
 2930    if(idn2_to_ascii_8z("does.this.work", &idna_utf8,
 2931          IDN2_NONTRANSITIONAL | IDN2_TRANSITIONAL) != IDN2_OK)
 2932       return 1;
 2933    if(idn2_to_unicode_8zlz(idna_utf8, &idna_lc, 0) != IDN2_OK)
 2934       return 1;
 2935    idn2_free(idna_lc);
 2936    idn2_free(idna_utf8);
 2937    return 0;
 2938 }
 2939 !
 2940    }
 2941 
 2942    val_idna_idn() {
 2943       link_check idna 'OPT_IDNA: GNU Libidn' \
 2944          '#define HAVE_IDNA n_IDNA_IMPL_LIBIDN' '-lidn' << \!
 2945 #include <idna.h>
 2946 #include <idn-free.h>
 2947 #include <stringprep.h> /* XXX we actually use our own iconv instead */
 2948 int main(void){
 2949    char *utf8, *idna_ascii, *idna_utf8;
 2950 
 2951    utf8 = stringprep_locale_to_utf8("does.this.work");
 2952    if (idna_to_ascii_8z(utf8, &idna_ascii, IDNA_USE_STD3_ASCII_RULES)
 2953          != IDNA_SUCCESS)
 2954       return 1;
 2955    idn_free(idna_ascii);
 2956    /* (Rather link check only here) */
 2957    idna_utf8 = stringprep_convert(idna_ascii, "UTF-8", "de_DE");
 2958    return 0;
 2959 }
 2960 !
 2961    }
 2962 
 2963    val_idna_idnkit() {
 2964       link_check idna 'OPT_IDNA: idnkit' \
 2965          '#define HAVE_IDNA n_IDNA_IMPL_IDNKIT' '-lidnkit' << \!
 2966 #include <stdio.h>
 2967 #include <idn/api.h>
 2968 #include <idn/result.h>
 2969 int main(void){
 2970    idn_result_t r;
 2971    char ace_name[256];
 2972    char local_name[256];
 2973 
 2974    r = idn_encodename(IDN_ENCODE_APP, "does.this.work", ace_name,
 2975          sizeof(ace_name));
 2976    if (r != idn_success) {
 2977       fprintf(stderr, "idn_encodename failed: %s\n", idn_result_tostring(r));
 2978       return 1;
 2979    }
 2980    r = idn_decodename(IDN_DECODE_APP, ace_name, local_name, sizeof(local_name));
 2981    if (r != idn_success) {
 2982       fprintf(stderr, "idn_decodename failed: %s\n", idn_result_tostring(r));
 2983       return 1;
 2984    }
 2985    return 0;
 2986 }
 2987 !
 2988    }
 2989 
 2990    val_idna_bye() {
 2991       feat_bail_required IDNA
 2992    }
 2993 
 2994    oifs=${IFS}
 2995    IFS=", "
 2996    VAL_IDNA="${VAL_IDNA},bye"
 2997    set -- ${VAL_IDNA}
 2998    IFS=${oifs}
 2999    for randfun
 3000    do
 3001       eval val_idna_$randfun && break
 3002    done
 3003 else
 3004    feat_is_disabled IDNA
 3005 fi # }}} IDNA
 3006 
 3007 feat_def IMAP_SEARCH
 3008 
 3009 if feat_yes REGEX; then
 3010    if link_check regex 'regular expressions' '#define HAVE_REGEX' << \!
 3011 #include <regex.h>
 3012 #include <stdlib.h>
 3013 int main(void){
 3014    size_t xret;
 3015    int status;
 3016    regex_t re;
 3017 
 3018    status = regcomp(&re, ".*bsd", REG_EXTENDED | REG_ICASE | REG_NOSUB);
 3019    xret = regerror(status, &re, NULL, 0);
 3020    status = regexec(&re, "plan9", 0,NULL, 0);
 3021    regfree(&re);
 3022    return !(status == REG_NOMATCH);
 3023 }
 3024 !
 3025    then
 3026       :
 3027    else
 3028       feat_bail_required REGEX
 3029    fi
 3030 else
 3031    feat_is_disabled REGEX
 3032 fi
 3033 
 3034 if feat_yes MLE; then
 3035    if [ -n "${have_c90amend1}" ]; then
 3036       have_mle=1
 3037       echo '#define HAVE_MLE' >> ${h}
 3038    else
 3039       feat_bail_required MLE
 3040    fi
 3041 else
 3042    feat_is_disabled MLE
 3043 fi
 3044 
 3045 # Generic have-a-line-editor switch for those who need it below
 3046 if [ -n "${have_mle}" ]; then
 3047    have_cle=1
 3048 fi
 3049 
 3050 if feat_yes HISTORY; then
 3051    if [ -n "${have_cle}" ]; then
 3052       echo '#define HAVE_HISTORY' >> ${h}
 3053    else
 3054       feat_is_unsupported HISTORY
 3055    fi
 3056 else
 3057    feat_is_disabled HISTORY
 3058 fi
 3059 
 3060 if feat_yes KEY_BINDINGS; then
 3061    if [ -n "${have_mle}" ]; then
 3062       echo '#define HAVE_KEY_BINDINGS' >> ${h}
 3063    else
 3064       feat_is_unsupported KEY_BINDINGS
 3065    fi
 3066 else
 3067    feat_is_disabled KEY_BINDINGS
 3068 fi
 3069 
 3070 if feat_yes TERMCAP; then # {{{
 3071    ADDINC=
 3072    __termcaplib() {
 3073       link_check termcap "termcap(5) (via ${4}${ADDINC})" \
 3074          "#define HAVE_TERMCAP${3}" "${1}" "${ADDINC}" << _EOT
 3075 #include <stdio.h>
 3076 #include <stdlib.h>
 3077 ${2}
 3078 #include <term.h>
 3079 #define UNCONST(P) ((void*)(unsigned long)(void const*)(P))
 3080 static int my_putc(int c){return putchar(c);}
 3081 int main(void){
 3082    char buf[1024+512], cmdbuf[2048], *cpb, *r1;
 3083    int r2 = OK, r3 = ERR;
 3084 
 3085    tgetent(buf, getenv("TERM"));
 3086    cpb = cmdbuf;
 3087    r1 = tgetstr(UNCONST("cm"), &cpb);
 3088    tgoto(r1, 1, 1);
 3089    r2 = tgetnum(UNCONST("Co"));
 3090    r3 = tgetflag(UNCONST("ut"));
 3091    tputs("cr", 1, &my_putc);
 3092    return (r1 == NULL || r2 == -1 || r3 == 0);
 3093 }
 3094 _EOT
 3095    }
 3096 
 3097    __terminfolib() {
 3098       link_check terminfo "terminfo(5) (via ${2}${ADDINC})" \
 3099          '#define HAVE_TERMCAP
 3100          #define HAVE_TERMCAP_CURSES
 3101          #define HAVE_TERMINFO' "${1}" "${ADDINC}" << _EOT
 3102 #include <stdio.h>
 3103 #include <curses.h>
 3104 #include <term.h>
 3105 #define UNCONST(P) ((void*)(unsigned long)(void const*)(P))
 3106 static int my_putc(int c){return putchar(c);}
 3107 int main(void){
 3108    int er, r0, r1, r2;
 3109    char *r3, *tp;
 3110 
 3111    er = OK;
 3112    r0 = setupterm(NULL, 1, &er);
 3113    r1 = tigetflag(UNCONST("bce"));
 3114    r2 = tigetnum(UNCONST("colors"));
 3115    r3 = tigetstr(UNCONST("cr"));
 3116    tp = tparm(r3, NULL, NULL, 0,0,0,0,0,0,0);
 3117    tputs(tp, 1, &my_putc);
 3118    return (r0 == ERR || r1 == -1 || r2 == -2 || r2 == -1 ||
 3119       r3 == (char*)-1 || r3 == NULL);
 3120 }
 3121 _EOT
 3122    }
 3123 
 3124    if feat_yes TERMCAP_VIA_TERMINFO; then
 3125       ADDINC=
 3126       do_me() {
 3127          xbail=
 3128          __terminfolib -ltinfo -ltinfo ||
 3129             __terminfolib -lcurses -lcurses ||
 3130             __terminfolib -lcursesw -lcursesw ||
 3131          xbail=y
 3132       }
 3133       do_me
 3134       if [ -n "${xbail}" ] && [ -d /usr/local/include/ncurses ]; then
 3135          ADDINC=' -I/usr/local/include/ncurses'
 3136          do_me
 3137       fi
 3138       if [ -n "${xbail}" ] && [ -d /usr/include/ncurses ]; then
 3139          ADDINC=' -I/usr/include/ncurses'
 3140          do_me
 3141       fi
 3142       [ -n "${xbail}" ] && feat_bail_required TERMCAP_VIA_TERMINFO
 3143    fi
 3144 
 3145    if [ -z "${have_terminfo}" ]; then
 3146       ADDINC=
 3147       do_me() {
 3148          xbail=
 3149          __termcaplib -ltermcap '' '' '-ltermcap' ||
 3150             __termcaplib -ltermcap '#include <curses.h>' '
 3151                #define HAVE_TERMCAP_CURSES' \
 3152                'curses.h / -ltermcap' ||
 3153             __termcaplib -lcurses '#include <curses.h>' '
 3154                #define HAVE_TERMCAP_CURSES' \
 3155                'curses.h / -lcurses' ||
 3156             __termcaplib -lcursesw '#include <curses.h>' '
 3157                #define HAVE_TERMCAP_CURSES' \
 3158                'curses.h / -lcursesw' ||
 3159             xbail=y
 3160       }
 3161       do_me
 3162       if [ -n "${xbail}" ] && [ -d /usr/local/include/ncurses ]; then
 3163          ADDINC=' -I/usr/local/include/ncurses'
 3164          do_me
 3165       fi
 3166       if [ -n "${xbail}" ] && [ -d /usr/include/ncurses ]; then
 3167          ADDINC=' -I/usr/include/ncurses'
 3168          do_me
 3169       fi
 3170       [ -n "${xbail}" ] && feat_bail_required TERMCAP
 3171 
 3172       if [ -n "${have_termcap}" ]; then
 3173          run_check tgetent_null \
 3174             "tgetent(3) of termcap(5) takes NULL buffer" \
 3175             "#define HAVE_TGETENT_NULL_BUF" << _EOT
 3176 #include <stdio.h> /* For C89 NULL */
 3177 #include <stdlib.h>
 3178 #ifdef HAVE_TERMCAP_CURSES
 3179 # include <curses.h>
 3180 #endif
 3181 #include <term.h>
 3182 int main(void){
 3183    tgetent(NULL, getenv("TERM"));
 3184    return 0;
 3185 }
 3186 _EOT
 3187       fi
 3188    fi
 3189    unset ADDINC
 3190 else # }}}
 3191    feat_is_disabled TERMCAP
 3192    feat_is_disabled TERMCAP_VIA_TERMINFO
 3193 fi
 3194 
 3195 if feat_def SPAM_SPAMC; then
 3196    if acmd_set i spamc; then
 3197       echo "#define SPAM_SPAMC_PATH \"${i}\"" >> ${h}
 3198    fi
 3199 fi
 3200 
 3201 if feat_yes SPAM_SPAMD; then
 3202    if [ -n "${have_af_unix}" ]; then
 3203       echo '#define HAVE_SPAM_SPAMD' >> ${h}
 3204    else
 3205       feat_bail_required SPAM_SPAMD
 3206    fi
 3207 else
 3208    feat_is_disabled SPAM_SPAMD
 3209 fi
 3210 
 3211 feat_def SPAM_FILTER
 3212 
 3213 if feat_yes SPAM_SPAMC || feat_yes SPAM_SPAMD || feat_yes SPAM_FILTER; then
 3214    echo '#define HAVE_SPAM' >> ${h}
 3215 else
 3216    echo '/* HAVE_SPAM */' >> ${h}
 3217 fi
 3218 
 3219 if feat_yes QUOTE_FOLD; then
 3220    if [ -n "${have_c90amend1}" ] && [ -n "${have_wcwidth}" ]; then
 3221       echo '#define HAVE_QUOTE_FOLD' >> ${h}
 3222    else
 3223       feat_bail_required QUOTE_FOLD
 3224    fi
 3225 else
 3226    feat_is_disabled QUOTE_FOLD
 3227 fi
 3228 
 3229 feat_def FILTER_HTML_TAGSOUP
 3230 feat_def COLOUR
 3231 feat_def DOTLOCK
 3232 feat_def MD5
 3233 
 3234 ## Summarizing
 3235 
 3236 ${rm} -f ${tmp}
 3237 squeeze_em ${inc} ${tmp}
 3238 ${mv} ${tmp} ${inc}
 3239 squeeze_em ${lib} ${tmp}
 3240 ${mv} ${tmp} ${lib}
 3241 
 3242 echo "LIBS = `${cat} ${lib}`" >> ${mk}
 3243 echo "INCS = `${cat} ${inc}`" >> ${mk}
 3244 echo >> ${mk}
 3245 
 3246 # mk-config.h
 3247 ${mv} ${h} ${tmp}
 3248 printf '#ifndef n_MK_CONFIG_H\n# define n_MK_CONFIG_H 1\n' > ${h}
 3249 ${cat} ${tmp} >> ${h}
 3250 printf '\n' >> ${h}
 3251 # Also need these for correct "second stage configuration changed" detection */
 3252 i=
 3253 if (${CC} --version) >/dev/null 2>&1; then
 3254    i=`${CC} --version 2>&1 | ${awk} '
 3255       BEGIN{l=""}
 3256       {if(length($0)) {if(l) l = l "\\\\n"; l = l "@" $0}}
 3257       END{gsub(/"/, "", l); print "\\\\n" l}
 3258    '`
 3259 elif (${CC} -v) >/dev/null 2>&1; then
 3260    i=`${CC} -v 2>&1 | ${awk} '
 3261       BEGIN{l=""}
 3262       {if(length($0)) {if(l) l = l "\\\\n"; l = l "@" $0}}
 3263       END{gsub(/"/, "", l); print "\\\\n" l}
 3264    '`
 3265 fi
 3266 printf '#define VAL_BUILD_CC "%s %s %s%s"\n' \
 3267    "${CC}" "${CFLAGS}" "" "${i}" >> ${h}
 3268 printf '#define VAL_BUILD_LD "%s %s %s"\n' \
 3269    "${CC}" "${LDFLAGS}" "`${cat} ${lib}`" >> ${h}
 3270 printf '#define VAL_BUILD_REST "%s"\n' "${COMMLINE}" >> ${h}
 3271 printf '\n' >> ${h}
 3272 
 3273 # Throw away all temporaries
 3274 ${rm} -rf ${tmp0}.* ${tmp0}*
 3275 
 3276 # Create the string that is used by *features* and `version'.
 3277 # Take this nice opportunity and generate a visual listing of included and
 3278 # non-included features for the person who runs the configuration
 3279 echo 'The following features are included (+) or not (-):' > ${tmp}
 3280 set -- ${OPTIONS_DETECT} ${OPTIONS} ${OPTIONS_XTRA}
 3281 printf '/* The "feature string" */\n' >> ${h}
 3282 # Because + is expanded by *folder* if first in "echo $features", put something
 3283 printf '#define VAL_FEATURES_CNT '${#}'\n#define VAL_FEATURES "#' >> ${h}
 3284 sep=
 3285 for opt
 3286 do
 3287    sdoc=`option_doc_of ${opt}`
 3288    [ -z "${sdoc}" ] && continue
 3289    sopt="`echo ${opt} | ${tr} '[A-Z]_' '[a-z]-'`"
 3290    feat_yes ${opt} && sign=+ || sign=-
 3291    printf -- "${sep}${sign}${sopt}" >> ${h}
 3292    sep=','
 3293    printf ' %s %s: %s\n' ${sign} ${sopt} "${sdoc}" >> ${tmp}
 3294 done
 3295 # TODO instead of using sh+tr+awk+printf, use awk, drop option_doc_of, inc here
 3296 #exec 5>&1 >>${h}
 3297 #${awk} -v opts="${OPTIONS_DETECT} ${OPTIONS} ${OPTIONS_XTRA}" \
 3298 #   -v xopts="${XOPTIONS_DETECT} ${XOPTIONS} ${XOPTIONS_XTRA}" \
 3299 printf '"\n' >> ${h}
 3300 
 3301 # Create the real mk-config.mk
 3302 # Note we cannout use explicit ./ filename prefix for source and object
 3303 # pathnames because of a bug in bmake(1)
 3304 srclist= objlist=
 3305 if feat_no AMALGAMATION; then
 3306    for i in `printf '%s\n' "${SRCDIR}"*.c | ${sort}`; do
 3307       i=`basename "${i}" .c`
 3308       if [ "${i}" = privsep ]; then
 3309          continue
 3310       fi
 3311       objlist="${objlist} ${i}.o"
 3312       srclist="${srclist} \$(SRCDIR)${i}.c"
 3313       printf '%s: %s\n\t$(ECHO_CC)$(CC) $(CFLAGS) $(INCS) -c %s\n' \
 3314          "${i}.o" "\$(SRCDIR)${i}.c" "\$(SRCDIR)${i}.c" >> ${mk}
 3315    done
 3316    printf '\nAMALGAM_TARGET =\nAMALGAM_DEP =\n' >> ${mk}
 3317 else
 3318    printf '%s:\n\t$(ECHO_CC)$(CC) $(CFLAGS) $(INCS) -c $(SRCDIR)%s\n' \
 3319       "main.o" "main.c" >> ${mk}
 3320    srclist=main.c objlist=main.o
 3321    printf '\nAMALGAM_TARGET = main.o\nAMALGAM_DEP = ' >> ${mk}
 3322 
 3323    printf '\n/* HAVE_AMALGAMATION: include sources */\n' >> ${h}
 3324    printf '#elif n_MK_CONFIG_H + 0 == 1\n' >> ${h}
 3325    printf '# undef n_MK_CONFIG_H\n' >> ${h}
 3326    printf '# define n_MK_CONFIG_H 2\n' >> ${h}
 3327    for i in `printf '%s\n' "${SRCDIR}"*.c | ${sort}`; do
 3328       i=`basename "${i}"`
 3329       if [ "${i}" = main.c ] ||
 3330             [ "${i}" = privsep.c ]; then
 3331          continue
 3332       fi
 3333       printf '$(SRCDIR)%s ' "${i}" >> ${mk}
 3334       printf '# include "%s%s"\n' "${SRCDIR}" "${i}" >> ${h}
 3335    done
 3336    echo >> ${mk}
 3337 fi
 3338 printf 'OBJ_SRC = %s\nOBJ = %s\n' "${srclist}" "${objlist}" >> "${mk}"
 3339 
 3340 printf '#endif /* n_MK_CONFIG_H */\n' >> ${h}
 3341 
 3342 echo >> ${mk}
 3343 ${cat} "${SRCDIR}"make-config.in >> ${mk}
 3344 
 3345 ## Finished!
 3346 
 3347 # We have completed the new configuration header.  Check whether *really*
 3348 # Do the "second stage configuration changed" detection, exit if nothing to do
 3349 if [ -f ${oldh} ]; then
 3350    if ${cmp} ${h} ${oldh} >/dev/null 2>&1; then
 3351       ${mv} -f ${oldh} ${h}
 3352       msg 'Effective configuration is up-to-date'
 3353       exit 0
 3354    fi
 3355    config_updated=1
 3356    ${rm} -f ${oldh}
 3357    msg 'Effective configuration has been updated..'
 3358 fi
 3359 
 3360 if [ -n "${config_updated}" ]; then
 3361    msg 'Wiping away old objects and such..'
 3362    ( cd .obj; oldmk=`${basename} ${oldmk}`; ${MAKE} -f ${oldmk} clean )
 3363 fi
 3364 
 3365 msg ''
 3366 while read l; do msg "${l}"; done < ${tmp}
 3367 
 3368 msg 'Setup:'
 3369 msg ' . System-wide resource file: %s/%s' "${VAL_SYSCONFDIR}" "${VAL_SYSCONFRC}"
 3370 msg ' . bindir: %s' "${VAL_BINDIR}"
 3371 if feat_yes DOTLOCK; then
 3372    msg ' . libexecdir: %s' "${VAL_LIBEXECDIR}"
 3373 fi
 3374 msg ' . mandir: %s' "${VAL_MANDIR}"
 3375 msg ' . M(ail)T(ransfer)A(gent): %s (argv0: %s)' "${VAL_MTA}" "${VAL_MTA_ARGV0}"
 3376 msg ' . $MAIL spool directory: %s' "${VAL_MAIL}"
 3377 
 3378 msg ''
 3379 if [ -n "${have_fnmatch}" ] && [ -n "${have_fchdir}" ]; then
 3380    exit 0
 3381 fi
 3382 msg 'Remarks:'
 3383 if [ -z "${have_fnmatch}" ]; then
 3384    msg ' . The function fnmatch(3) could not be found.'
 3385    msg '   Filename patterns like wildcard are not supported on your system'
 3386 fi
 3387 if [ -z "${have_fchdir}" ]; then
 3388    msg ' . The function fchdir(2) could not be found.'
 3389    msg '   We will use chdir(2) instead.'
 3390    msg '   This is a problem only if the current working directory is changed'
 3391    msg '   while this program is inside of it'
 3392 fi
 3393 msg ''
 3394 
 3395 # s-it-mode