"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.22/mk/make-config.sh" (24 Feb 2021, 100084 Bytes) of package /linux/misc/s-nail-14.9.22.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 and code folding option. 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.21_vs_14.9.22.

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