"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.19/mk/make-config.sh" (26 Apr 2020, 97570 Bytes) of package /linux/misc/s-nail-14.9.19.tar.xz:


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

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