Author: brane
Date: Mon Jun 23 10:09:30 2025
New Revision: 1926661

URL: http://svn.apache.org/viewvc?rev=1926661&view=rev
Log:
On the user-defined-authn branch: sync with trunk r1926660.

Added:
    serf/branches/user-defined-authn/.github/workflows/linux-old-scons.yml
      - copied unchanged from r1926660, 
serf/trunk/.github/workflows/linux-old-scons.yml
    serf/branches/user-defined-authn/src/init_once.c
      - copied unchanged from r1926660, serf/trunk/src/init_once.c
Modified:
    serf/branches/user-defined-authn/   (props changed)
    serf/branches/user-defined-authn/CMakeLists.txt
    serf/branches/user-defined-authn/auth/auth_spnego.c
    serf/branches/user-defined-authn/buckets/ssl_buckets.c
    serf/branches/user-defined-authn/serf_private.h
    serf/branches/user-defined-authn/test/certs/create_certs.py
    serf/branches/user-defined-authn/test/serf_httpd.c

Propchange: serf/branches/user-defined-authn/
------------------------------------------------------------------------------
  Merged /serf/trunk:r1926567-1926660

Modified: serf/branches/user-defined-authn/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/CMakeLists.txt?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/CMakeLists.txt (original)
+++ serf/branches/user-defined-authn/CMakeLists.txt Mon Jun 23 10:09:30 2025
@@ -131,6 +131,7 @@ list(APPEND SOURCES
     "src/context.c"
     "src/deprecated.c"
     "src/incoming.c"
+    "src/init_once.c"
     "src/logging.c"
     "src/outgoing.c"
     "src/outgoing_request.c"

Modified: serf/branches/user-defined-authn/auth/auth_spnego.c
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/auth/auth_spnego.c?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/auth/auth_spnego.c (original)
+++ serf/branches/user-defined-authn/auth/auth_spnego.c Mon Jun 23 10:09:30 2025
@@ -261,20 +261,11 @@ do_auth(const serf__authn_scheme_t *sche
         const char *auth_hdr,
         apr_pool_t *pool)
 {
-    serf_context_t *ctx = conn->ctx;
-    serf__authn_info_t *authn_info;
     const char *tmp = NULL;
     char *token = NULL;
     apr_size_t tmp_len = 0, token_len = 0;
     apr_status_t status;
 
-    if (peer == HOST) {
-        authn_info = serf__get_authn_info_for_server(conn);
-    } else {
-        authn_info = &ctx->proxy_authn_info;
-    }
-    /* FIXME: authn_info's value is never used. */
-
     /* Is this a response from a host/proxy? auth_hdr should always be set. */
     if (code && auth_hdr) {
         const char *space = NULL;

Modified: serf/branches/user-defined-authn/buckets/ssl_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/buckets/ssl_buckets.c?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/buckets/ssl_buckets.c (original)
+++ serf/branches/user-defined-authn/buckets/ssl_buckets.c Mon Jun 23 10:09:30 
2025
@@ -1467,90 +1467,66 @@ static apr_status_t cleanup_ssl(void *da
 
 #endif
 
-#if !APR_VERSION_AT_LEAST(1,0,0)
-#define apr_atomic_cas32(mem, with, cmp) apr_atomic_cas(mem, with, cmp)
-#endif
 
-enum ssl_init_e
+static apr_status_t do_init_libraries(void* baton)
 {
-   INIT_UNINITIALIZED = 0,
-   INIT_BUSY = 1,
-   INIT_DONE = 2
-};
-
-static volatile apr_uint32_t have_init_ssl = INIT_UNINITIALIZED;
-
-static void init_ssl_libraries(void)
-{
-    apr_uint32_t val;
-
-    val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED);
-
-    if (!val) {
 #if APR_HAS_THREADS && defined(SERF_HAVE_SSL_LOCKING_CALLBACKS)
-        int i, numlocks;
+    int i, numlocks;
 #endif
 
 #ifdef SERF_LOGGING_ENABLED
-        /* Warn when compile-time and run-time version of OpenSSL differ in
-           major/minor version number. */
+    /* Warn when compile-time and run-time version of OpenSSL differ in
+       major/minor version number. */
 #ifdef SERF_HAVE_OPENSSL_VERSION_NUM
-        unsigned long libver = OpenSSL_version_num();
+    unsigned long libver = OpenSSL_version_num();
 #else
-        long libver = SSLeay();
+    long libver = SSLeay();
 #endif
 
-        if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) {
-            serf__log(LOGLVL_WARNING, LOGCOMP_SSL, __FILE__, NULL,
-                      "Warning: OpenSSL library version mismatch, compile-"
-                      "time was %lx, runtime is %lx.\n",
-                      OPENSSL_VERSION_NUMBER, libver);
-        }
+    if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) {
+        serf__log(LOGLVL_WARNING, LOGCOMP_SSL, __FILE__, NULL,
+                  "Warning: OpenSSL library version mismatch, compile-"
+                  "time was %lx, runtime is %lx.\n",
+                  OPENSSL_VERSION_NUMBER, libver);
+    }
 #endif
 
 #ifdef SERF_HAVE_OPENSSL_SSL_LIBRARY_INIT
-        ERR_load_crypto_strings();
-        SSL_load_error_strings();
-        SSL_library_init();
-        OpenSSL_add_all_algorithms();
+    ERR_load_crypto_strings();
+    SSL_load_error_strings();
+    SSL_library_init();
+    OpenSSL_add_all_algorithms();
 #endif
 
 #if APR_HAS_THREADS && defined(SERF_HAVE_SSL_LOCKING_CALLBACKS)
-        numlocks = CRYPTO_num_locks();
-        apr_pool_create(&ssl_pool, NULL);
-        ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks);
-        for (i = 0; i < numlocks; i++) {
-            apr_status_t rv;
+    numlocks = CRYPTO_num_locks();
+    apr_pool_create(&ssl_pool, NULL);
+    ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks);
+    for (i = 0; i < numlocks; i++) {
+        apr_status_t status;
 
-            /* Intraprocess locks don't /need/ a filename... */
-            rv = apr_thread_mutex_create(&ssl_locks[i],
+        /* Intraprocess locks don't /need/ a filename... */
+        status = apr_thread_mutex_create(&ssl_locks[i],
                                          APR_THREAD_MUTEX_DEFAULT, ssl_pool);
-            if (rv != APR_SUCCESS) {
-                /* FIXME: error out here */
-            }
-        }
-        CRYPTO_set_locking_callback(ssl_lock);
-        CRYPTO_set_id_callback(ssl_id);
-        CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
-        CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
-        CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
+        if (status != APR_SUCCESS)
+            return status;
+    }
+    CRYPTO_set_locking_callback(ssl_lock);
+    CRYPTO_set_id_callback(ssl_id);
+    CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
+    CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
+    CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
 
-        apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
+    apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
 #endif
-        apr_atomic_cas32(&have_init_ssl, INIT_DONE, INIT_BUSY);
-    }
-  else
-    {
-        /* Make sure we don't continue before the initialization in another
-           thread has completed */
-        while (val != INIT_DONE) {
-            apr_sleep(APR_USEC_PER_SEC / 1000);
-
-            val = apr_atomic_cas32(&have_init_ssl,
-                                   INIT_UNINITIALIZED,
-                                   INIT_UNINITIALIZED);
-        }
-    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t init_ssl_libraries(void)
+{
+    SERF__DECLARE_STATIC_INIT_ONCE_CONTEXT(init_ctx);
+    return serf__init_once(&init_ctx, do_init_libraries, NULL);
 }
 
 static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
@@ -1774,7 +1750,8 @@ static serf_ssl_context_t *ssl_init_cont
 {
     serf_ssl_context_t *ssl_ctx;
 
-    init_ssl_libraries();
+    if (init_ssl_libraries())
+        return NULL;
 
     ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx));
 
@@ -2023,11 +2000,13 @@ apr_status_t serf_ssl_load_cert_file(
     status = apr_file_open(&cert_file, file_path, APR_READ, APR_OS_DEFAULT,
                            pool);
 
+    if (!status) {
+        status = init_ssl_libraries();
+    }
     if (status) {
         return status;
     }
 
-    init_ssl_libraries();
 
     biom = bio_meth_file_new();
     bio = BIO_new(biom);

Modified: serf/branches/user-defined-authn/serf_private.h
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/serf_private.h?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/serf_private.h (original)
+++ serf/branches/user-defined-authn/serf_private.h Mon Jun 23 10:09:30 2025
@@ -167,6 +167,32 @@ typedef int serf__bool_t; /* Not _Bool *
 #endif
 #endif
 
+/*** One-time initialization. ***/
+
+/* Init-once context. */
+struct serf__init_once_context
+{
+    volatile apr_uint32_t state;
+    apr_status_t status;
+};
+
+#define SERF__INIT_ONCE_NONE 0
+#define SERF__DECLARE_STATIC_INIT_ONCE_CONTEXT(name)  \
+    static struct serf__init_once_context name = {    \
+        SERF__INIT_ONCE_NONE, APR_SUCCESS             \
+    }
+
+/* The init-once callback function. */
+typedef apr_status_t (*serf__init_once_func_t)(void *baton);
+
+/* The function that performs on-time initialization.
+   If APR_HAS_THREADS, will use a spinlock to serialize the call to
+   the initialization function. */
+apr_status_t serf__init_once(struct serf__init_once_context *init_ctx,
+                             serf__init_once_func_t init_func,
+                             void *init_baton);
+
+
 typedef struct serf__authn_scheme_t serf__authn_scheme_t;
 
 typedef struct serf_io_baton_t {

Modified: serf/branches/user-defined-authn/test/certs/create_certs.py
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/certs/create_certs.py?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/certs/create_certs.py (original)
+++ serf/branches/user-defined-authn/test/certs/create_certs.py Mon Jun 23 
10:09:30 2025
@@ -9,9 +9,9 @@
 #   to you under the Apache License, Version 2.0 (the
 #   "License"); you may not use this file except in compliance
 #   with the License.  You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 #   Unless required by applicable law or agreed to in writing,
 #   software distributed under the License is distributed on an
 #   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,9 +21,9 @@
 # ===================================================================
 #
 
-# This script creates the private keys and certificates required for 
+# This script creates the private keys and certificates required for
 # running the serf test suite.
-# 
+#
 # It should be run from the test/certs folder without arguments.
 # Certificates will be created in the test/certs folder, private keys in the
 # test/certs/private folder.
@@ -47,12 +47,12 @@ def create_key(keyfile='', passphrase=No
     key = crypto.PKey()
     key.generate_key(KEY_ALGO, KEY_SIZE)
     if passphrase:
-        open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, 
-                                                         key, KEY_CIPHER, 
-                                                         passphrase))
+        open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM,
+                                                         key, KEY_CIPHER,
+                                                         
passphrase).decode('utf-8'))
     else:
-        open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, 
-                                                         key))
+        open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM,
+                                                         key).decode('utf-8'))
 
     return key
 
@@ -62,7 +62,7 @@ def create_pkcs12(clientkey, clientcert,
     pkcs12.set_certificate(clientcert)
     pkcs12.set_privatekey(clientkey)
     pkcs12.set_ca_certificates([issuer])
-    open(pkcs12file, "wt").write(pkcs12.export(passphrase=passphrase, 
+    open(pkcs12file, "wb").write(pkcs12.export(passphrase=passphrase,
                                                iter=2048, maciter=2048))
 
 def create_crl(revokedcert, cakey, cacert, crlfile, next_crl_days=VALID_DAYS):
@@ -73,9 +73,9 @@ def create_crl(revokedcert, cakey, cacer
     now = datetime.utcnow()
     now_str = now.strftime('%Y%m%d%H%M%SZ')
 
-    revoked.set_serial(serial_number)
-    revoked.set_reason('unspecified')
-    revoked.set_rev_date(now_str)   # revoked as of now
+    revoked.set_serial(serial_number.encode('ascii'))
+    revoked.set_reason(b'unspecified')
+    revoked.set_rev_date(now_str.encode('ascii'))   # revoked as of now
 
     crl.add_revoked(revoked)
     try:
@@ -84,16 +84,16 @@ def create_crl(revokedcert, cakey, cacer
         # Some very old versions of pyopenssl (such as the one on macOS)
         # do not support the 'digest' keyword argument.
         exported = crl.export(cacert, cakey, days=next_crl_days)
-    open(crlfile, "wt").write(exported)
+    open(crlfile, "wb").write(exported)
 
 # subjectAltName
-def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='', 
-                state='', city='', org='', ou='', cn='', email='', ca=False, 
+def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='',
+                state='', city='', org='', ou='', cn='', email='', ca=False,
                 valid_before=0, days_valid=VALID_DAYS, subjectAltName=None,
                 ocsp_responder_url=None, ocsp_signer=False):
     '''
     Create a X509 signed certificate.
-    
+
     subjectAltName
         Array of fully qualified subject alternative names (use OpenSSL 
syntax):
         For a DNS entry, use: ['DNS:localhost']. Other options are 'email', 
'URI', 'IP'.
@@ -103,15 +103,15 @@ def create_cert(subjectkey, certfile, is
     cert.set_version(3-1) # version 3, starts at 0
     cert.get_subject().C  = country
     cert.get_subject().ST = state
-    cert.get_subject().L  = city 
-    cert.get_subject().O  = org 
+    cert.get_subject().L  = city
+    cert.get_subject().O  = org
     cert.get_subject().OU = ou
     if cn:
         cert.get_subject().CN = cn
     cert.get_subject().emailAddress = email
     cert.set_serial_number(SERIAL_NUMBER)
     cert.set_pubkey(subjectkey)
-    
+
     cert.gmtime_adj_notBefore(valid_before * 24 * 3600)
     cert.gmtime_adj_notAfter(days_valid * 24 * 3600)
 
@@ -119,92 +119,92 @@ def create_cert(subjectkey, certfile, is
         issuer = cert # self signed
         issuerkey = subjectkey
     cert.set_issuer(issuer.get_subject())
-    
+
     if ca:
         cert.add_extensions([
-            crypto.X509Extension("basicConstraints", False,
-                                 "CA:TRUE"),
-            crypto.X509Extension("subjectKeyIdentifier", False, "hash",
+            crypto.X509Extension(b"basicConstraints", False,
+                                 b"CA:TRUE"),
+            crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash",
                                  subject=cert)
             ])
         cert.add_extensions([
-            crypto.X509Extension("authorityKeyIdentifier", False, 
-                                 "keyid:always", issuer=issuer)
+            crypto.X509Extension(b"authorityKeyIdentifier", False,
+                                 b"keyid:always", issuer=issuer)
             ])
 
     if subjectAltName:
         critical = True if not cn else False
         cert.add_extensions([
-            crypto.X509Extension('subjectAltName', critical, ", 
".join(subjectAltName))])
+            crypto.X509Extension(b'subjectAltName', critical, ", 
".join(subjectAltName).encode('ascii'))])
 
     if ocsp_responder_url:
         cert.add_extensions([
-            crypto.X509Extension('authorityInfoAccess', False,
-                                 'OCSP;URI:' + ocsp_responder_url)])
+            crypto.X509Extension(b'authorityInfoAccess', False,
+                                 ('OCSP;URI:' + 
ocsp_responder_url).encode('ascii'))])
 
     if ocsp_signer:
         cert.add_extensions([
-            crypto.X509Extension('extendedKeyUsage', True, 'OCSPSigning')
+            crypto.X509Extension(b'extendedKeyUsage', True, b'OCSPSigning')
         ])
 
     cert.sign(issuerkey, SIGN_ALGO)
 
-    open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, 
-                                                       cert))
+    open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM,
+                                                       cert).decode('utf-8'))
     return cert
 
 if __name__ == '__main__':
     # root CA key pair and certificate.
     # This key will be used to sign the intermediate CA certificate
-    rootcakey = create_key('private/serfrootcakey.pem', 'serftest')
+    rootcakey = create_key('private/serfrootcakey.pem', b'serftest')
 
-    rootcacert = create_cert(subjectkey=rootcakey, 
+    rootcacert = create_cert(subjectkey=rootcakey,
                              certfile='serfrootcacert.pem',
-                             country='BE', state='Antwerp', city='Mechelen', 
-                             org='In Serf we trust, Inc.', 
-                             ou='Test Suite Root CA', cn='Serf Root CA', 
+                             country='BE', state='Antwerp', city='Mechelen',
+                             org='In Serf we trust, Inc.',
+                             ou='Test Suite Root CA', cn='Serf Root CA',
                              email='serfroo...@example.com', ca=True)
 
     # intermediate CA key pair and certificate
     # This key will be used to sign all server certificates
-    cakey = create_key('private/serfcakey.pem', 'serftest')
+    cakey = create_key('private/serfcakey.pem', b'serftest')
 
     cacert = create_cert(subjectkey=cakey, certfile='serfcacert.pem',
                          issuer=rootcacert, issuerkey=rootcakey,
-                         country='BE', state='Antwerp', city='Mechelen', 
-                         org='In Serf we trust, Inc.', 
-                         ou='Test Suite CA', cn='Serf CA', 
+                         country='BE', state='Antwerp', city='Mechelen',
+                         org='In Serf we trust, Inc.',
+                         ou='Test Suite CA', cn='Serf CA',
                          email='ser...@example.com', ca=True)
 
     # server key pair
     # server certificate, no errors
-    serverkey = create_key('private/serfserverkey.pem', 'serftest')
+    serverkey = create_key('private/serfserverkey.pem', b'serftest')
 
-    servercert = create_cert(subjectkey=serverkey, 
+    servercert = create_cert(subjectkey=serverkey,
                              certfile='serfservercert.pem',
                              issuer=cacert, issuerkey=cakey,
-                             country='BE', state='Antwerp', city='Mechelen', 
-                             org='In Serf we trust, Inc.', 
-                             ou='Test Suite Server', cn='localhost', 
+                             country='BE', state='Antwerp', city='Mechelen',
+                             org='In Serf we trust, Inc.',
+                             ou='Test Suite Server', cn='localhost',
                              email='serfser...@example.com')
 
     # server certificate that expired a year ago
-    expiredcert = create_cert(subjectkey=serverkey, 
+    expiredcert = create_cert(subjectkey=serverkey,
                               certfile='serfserver_expired_cert.pem',
                               issuer=cacert, issuerkey=cakey,
-                              country='BE', state='Antwerp', city='Mechelen', 
-                              org='In Serf we trust, Inc.', 
-                              ou='Test Suite Server', cn='localhost', 
+                              country='BE', state='Antwerp', city='Mechelen',
+                              org='In Serf we trust, Inc.',
+                              ou='Test Suite Server', cn='localhost',
                               email='serfser...@example.com',
                               days_valid=-365)
 
     # server certificate that will be valid in 10 years
-    expiredcert = create_cert(subjectkey=serverkey, 
+    expiredcert = create_cert(subjectkey=serverkey,
                               certfile='serfserver_future_cert.pem',
                               issuer=cacert, issuerkey=cakey,
                               country='BE', state='Antwerp', city='Mechelen',
-                              org='In Serf we trust, Inc.', 
-                              ou='Test Suite Server', cn='localhost', 
+                              org='In Serf we trust, Inc.',
+                              ou='Test Suite Server', cn='localhost',
                               email='serfser...@example.com',
                               valid_before=10*365)
 
@@ -243,21 +243,21 @@ if __name__ == '__main__':
                               ocsp_signer=True)
 
     # client key pair and certificate
-    clientkey = create_key('private/serfclientkey.pem', 'serftest')
+    clientkey = create_key('private/serfclientkey.pem', b'serftest')
 
-    clientcert = create_cert(subjectkey=clientkey, 
+    clientcert = create_cert(subjectkey=clientkey,
                              certfile='serfclientcert.pem',
                              issuer=cacert, issuerkey=cakey,
-                             country='BE', state='Antwerp', city='Mechelen', 
-                             org='In Serf we trust, Inc.', 
-                             ou='Test Suite Client', cn='Serf Client', 
+                             country='BE', state='Antwerp', city='Mechelen',
+                             org='In Serf we trust, Inc.',
+                             ou='Test Suite Client', cn='Serf Client',
                              email='serfcli...@example.com')
 
-    clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert, 
-                                 'serfclientcert.p12', 'serftest')
+    clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert,
+                                 'serfclientcert.p12', b'serftest')
 
-    # Note that this creates a v1 CRL file without extensions set, and with 
+    # Note that this creates a v1 CRL file without extensions set, and with
     # MD5 hash. Not ideal, but pyOpenSSL doesn't support more than this.
-    # 
+    #
     # crl
     crl = create_crl(servercert, cakey, cacert, 'serfservercrl.pem')

Modified: serf/branches/user-defined-authn/test/serf_httpd.c
URL: 
http://svn.apache.org/viewvc/serf/branches/user-defined-authn/test/serf_httpd.c?rev=1926661&r1=1926660&r2=1926661&view=diff
==============================================================================
--- serf/branches/user-defined-authn/test/serf_httpd.c (original)
+++ serf/branches/user-defined-authn/test/serf_httpd.c Mon Jun 23 10:09:30 2025
@@ -383,6 +383,7 @@ int main(int argc, const char **argv)
     int verbose = 0;
     const char *opt_arg;
     const char *root_dir;
+    apr_finfo_t root_info;
 
     apr_initialize();
     atexit(apr_terminate);
@@ -448,8 +449,14 @@ int main(int argc, const char **argv)
         exit(-1);
     }
 
+    /* FIXME: root_dir is never used. */
     root_dir = argv[opt->ind];
-    /* FIXME: root_dir's value is never used. */
+    status = apr_stat(&root_info, root_dir, APR_FINFO_TYPE, scratch_pool);
+    printf("Ignoring root directory %s%s", root_dir,
+           (status == APR_SUCCESS
+            ? (root_info.filetype == APR_DIR ? "\n"
+               : " (which isn't a directory)\n")
+            : " (which doesn't even exist)\n"));
 
     /* Setup debug logging */
     if (verbose) {


Reply via email to