From b42d8c0a313b25db9cd7e1147c5489aacfda7a50 Mon Sep 17 00:00:00 2001
From: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat, 24 Feb 2024 15:50:43 +0100
Subject: Add an option to test the configuration file

---
 man/nslcd.8.xml | 14 ++++++++++++++
 nslcd/nslcd.c   | 16 +++++++++++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/man/nslcd.8.xml b/man/nslcd.8.xml
index 00208dc..72cbd80 100644
--- a/man/nslcd.8.xml
+++ b/man/nslcd.8.xml
@@ -129,6 +129,20 @@
     </listitem>
    </varlistentry>
 
+   <varlistentry id="test">
+    <term>
+     <option>-t</option>, <option>--test</option>
+    </term>
+    <listitem>
+     <para>
+      Validate the configuration and exit. This performs syntax checking of the configuration,
+      checks for presence of files referred in the configuration and does some minimal other
+      sanity checking.
+      This causes <command>nslcd</command> to return 0 if the configuration appears valid and 1 if it is not.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry id="help">
     <term>
      <option>--help</option>
diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c
index 55da9ac..d54e2db 100644
--- a/nslcd/nslcd.c
+++ b/nslcd/nslcd.c
@@ -94,6 +94,9 @@ static int nslcd_checkonly = 0;
 /* name of the configuration file to load */
 static char *nslcd_conf_path = NSLCD_CONF_PATH;
 
+/* flag to indicate user requested the --test option */
+static int nslcd_testconfig = 0;
+
 /* the flag to indicate that a signal was received */
 static volatile int nslcd_receivedsignal = 0;
 
@@ -138,6 +141,7 @@ static void display_usage(FILE *fp, const char *program_name)
   fprintf(fp, "  -d, --debug        don't fork and print debugging to stderr\n");
   fprintf(fp, "  -n, --nofork       don't fork\n");
   fprintf(fp, "  -f, --config=FILE  alternative configuration file (default %s)\n", NSLCD_CONF_PATH);
+  fprintf(fp, "  -t, --test         test configuration for validity and exit\n");
   fprintf(fp, "      --help         display this help and exit\n");
   fprintf(fp, "      --version      output version information and exit\n");
   fprintf(fp, "\n" "Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
@@ -149,11 +153,12 @@ static struct option const nslcd_options[] = {
   {"debug",   no_argument,       NULL, 'd'},
   {"nofork",  no_argument,       NULL, 'n'},
   {"config",  required_argument, NULL, 'f'},
+  {"test",    no_argument,       NULL, 't'},
   {"help",    no_argument,       NULL, 'h'},
   {"version", no_argument,       NULL, 'V'},
   {NULL,      0,                 NULL, 0}
 };
-#define NSLCD_OPTIONSTRING "cndf:hV"
+#define NSLCD_OPTIONSTRING "cndf:thV"
 
 /* parse command line options and save settings in struct  */
 static void parse_cmdline(int argc, char *argv[])
@@ -181,6 +186,9 @@ static void parse_cmdline(int argc, char *argv[])
           exit(EXIT_FAILURE);
         }
         break;
+      case 't': /* -t, --test        test configuration for validity and exit */
+        nslcd_testconfig = 1;
+        break;
       case 'h': /*     --help         display this help and exit */
         display_usage(stdout, argv[0]);
         exit(EXIT_SUCCESS);
@@ -735,6 +743,12 @@ int main(int argc, char *argv[])
     exit(EXIT_FAILURE);
   /* read configuration file */
   cfg_init(nslcd_conf_path);
+  /* exit if we only wanted to check the configuration */
+  if (nslcd_testconfig)
+  {
+    log_log(LOG_INFO, "config (%s) OK", nslcd_conf_path);
+    exit(EXIT_SUCCESS);
+  }
   /* set default mode for pidfile and socket */
   (void)umask((mode_t)0022);
   /* see if someone already locked the pidfile
-- 
cgit v1.2.3