From 8cf012327920d46bf32fff0b40a5bdea9eb8e7db Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Sat, 10 Apr 2021 20:27:09 +1100
Subject: [PATCH] allow options randomly placed in command line

---
 src/include/66/ssexec.h    | 19 +++++++++++++++++++
 src/lib66/ssexec_all.c     |  2 +-
 src/lib66/ssexec_dbctl.c   |  2 +-
 src/lib66/ssexec_disable.c |  2 +-
 src/lib66/ssexec_enable.c  |  2 +-
 src/lib66/ssexec_env.c     |  2 +-
 src/lib66/ssexec_main.c    | 33 ++++++++++++++++++++++++++++++++-
 src/lib66/ssexec_start.c   |  2 +-
 src/lib66/ssexec_stop.c    |  2 +-
 src/lib66/ssexec_svctl.c   |  2 +-
 10 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/src/include/66/ssexec.h b/src/include/66/ssexec.h
index dde180e9..ee862b12 100644
--- a/src/include/66/ssexec.h
+++ b/src/include/66/ssexec.h
@@ -98,6 +98,25 @@ extern char const *help_env ;
 extern char const *usage_all ;
 extern char const *help_all ;
 
+#define OPTS_INIT "cdb"
+#define OPTS_INIT_LEN (sizeof OPTS_INIT - 1)
+#define OPTS_ENABLE "cmCfFSiI"
+#define OPTS_ENABLE_LEN (sizeof OPTS_ENABLE - 1)
+#define OPTS_DISABLE "SFR"
+#define OPTS_DISABLE_LEN (sizeof OPTS_DISABLE - 1)
+#define OPTS_START "rR"
+#define OPTS_START_LEN (sizeof OPTS_START - 1)
+#define OPTS_STOP "uXK"
+#define OPTS_STOP_LEN (sizeof OPTS_STOP - 1)
+#define OPTS_SVCTL "n:urRdXK"
+#define OPTS_SVCTL_LEN (sizeof OPTS_SVCTL - 1)
+#define OPTS_DBCTL "udr"
+#define OPTS_DBCTL_LEN (sizeof OPTS_DBCTL - 1)
+#define OPTS_ENV "c:s:VLr:e:i:"
+#define OPTS_ENV_LEN (sizeof OPTS_ENV - 1)
+#define OPTS_ALL "f"
+#define OPTS_ALL_LEN (sizeof OPTS_ALL - 1)
+
 extern int ssexec_main(int argc, char const *const *argv, char const *const *envp,ssexec_func_t *func,ssexec_t *info) ;
 
 #endif
diff --git a/src/lib66/ssexec_all.c b/src/lib66/ssexec_all.c
index 557ccb39..ee4b2323 100644
--- a/src/lib66/ssexec_all.c
+++ b/src/lib66/ssexec_all.c
@@ -241,7 +241,7 @@ int ssexec_all(int argc, char const *const *argv,char const *const *envp,ssexec_
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">f", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_ALL, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
diff --git a/src/lib66/ssexec_dbctl.c b/src/lib66/ssexec_dbctl.c
index 5e371b14..de43916a 100644
--- a/src/lib66/ssexec_dbctl.c
+++ b/src/lib66/ssexec_dbctl.c
@@ -236,7 +236,7 @@ int ssexec_dbctl(int argc, char const *const *argv,char const *const *envp,ssexe
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, "udr", &l) ;
+            int opt = getopt_args(argc,argv, OPTS_DBCTL, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
diff --git a/src/lib66/ssexec_disable.c b/src/lib66/ssexec_disable.c
index 2e74e5b1..3e1d2382 100644
--- a/src/lib66/ssexec_disable.c
+++ b/src/lib66/ssexec_disable.c
@@ -200,7 +200,7 @@ int ssexec_disable(int argc, char const *const *argv,char const *const *envp,sse
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">SFR", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_DISABLE, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
diff --git a/src/lib66/ssexec_enable.c b/src/lib66/ssexec_enable.c
index 3907c1dd..ec44b626 100644
--- a/src/lib66/ssexec_enable.c
+++ b/src/lib66/ssexec_enable.c
@@ -264,7 +264,7 @@ int ssexec_enable(int argc, char const *const *argv,char const *const *envp,ssex
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">cmCfFSiI", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_ENABLE, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
diff --git a/src/lib66/ssexec_env.c b/src/lib66/ssexec_env.c
index c57b428f..dd569836 100644
--- a/src/lib66/ssexec_env.c
+++ b/src/lib66/ssexec_env.c
@@ -226,7 +226,7 @@ int ssexec_env(int argc, char const *const *argv,char const *const *envp,ssexec_
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">c:s:VLr:e:i:", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_ENV, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
diff --git a/src/lib66/ssexec_main.c b/src/lib66/ssexec_main.c
index 17f303fe..3bcca8cf 100644
--- a/src/lib66/ssexec_main.c
+++ b/src/lib66/ssexec_main.c
@@ -72,6 +72,28 @@ static inline void info_help (char const *help,char const *usage)
     log_info(usage,"\n",help) ;
 }
 
+static inline void append_opts(char *opts,size_t baselen, ssexec_func_t *func)
+{
+    if ((*func) == &ssexec_init)
+        auto_strings(opts + baselen,OPTS_INIT) ;
+    else if ((*func) == &ssexec_enable)
+        auto_strings(opts + baselen,OPTS_ENABLE) ;
+    else if ((*func) == &ssexec_disable)
+        auto_strings(opts + baselen,OPTS_DISABLE) ;
+    else if ((*func) == &ssexec_start)
+        auto_strings(opts + baselen,OPTS_START) ;
+    else if ((*func) == &ssexec_stop)
+        auto_strings(opts + baselen,OPTS_STOP) ;
+    else if ((*func) == &ssexec_svctl)
+        auto_strings(opts + baselen,OPTS_SVCTL) ;
+    else if ((*func) == &ssexec_dbctl)
+        auto_strings(opts + baselen,OPTS_DBCTL) ;
+    else if ((*func) == &ssexec_env)
+        auto_strings(opts + baselen,OPTS_ENV) ;
+    else if ((*func) == &ssexec_all)
+        auto_strings(opts + baselen,OPTS_ALL) ;
+}
+
 int ssexec_main(int argc, char const *const *argv,char const *const *envp,ssexec_func_t *func, ssexec_t *info)
 {
     log_flow() ;
@@ -82,13 +104,22 @@ int ssexec_main(int argc, char const *const *argv,char const *const *envp,ssexec
 
     log_color = &log_color_disable ;
 
+    /** 30 options should be large enough */
+    char opts[30] ;
+    char const *main = "hv:l:t:T:z" ;
+    size_t mainlen = strlen(main) ;
+
+    auto_strings(opts,main) ;
+
+    append_opts(opts,mainlen,func) ;
+
     nargv[n++] = "fake_name" ;
     {
         subgetopt_t l = SUBGETOPT_ZERO ;
         int f = 0 ;
         for (;;)
         {
-            int opt = subgetopt_r(argc,argv, "hv:l:t:T:z", &l) ;
+            int opt = subgetopt_r(argc,argv, opts, &l) ;
 
             if (opt == -1) break ;
             switch (opt)
diff --git a/src/lib66/ssexec_start.c b/src/lib66/ssexec_start.c
index 88237360..65bca887 100644
--- a/src/lib66/ssexec_start.c
+++ b/src/lib66/ssexec_start.c
@@ -228,7 +228,7 @@ int ssexec_start(int argc, char const *const *argv,char const *const *envp,ssexe
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">rR", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_START, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
 
diff --git a/src/lib66/ssexec_stop.c b/src/lib66/ssexec_stop.c
index fa0aedff..aeee76bb 100644
--- a/src/lib66/ssexec_stop.c
+++ b/src/lib66/ssexec_stop.c
@@ -137,7 +137,7 @@ int ssexec_stop(int argc, char const *const *argv,char const *const *envp,ssexec
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, ">uXK", &l) ;
+            int opt = getopt_args(argc,argv, ">" OPTS_STOP, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
 
diff --git a/src/lib66/ssexec_svctl.c b/src/lib66/ssexec_svctl.c
index 3bfa52b2..3aa71944 100644
--- a/src/lib66/ssexec_svctl.c
+++ b/src/lib66/ssexec_svctl.c
@@ -513,7 +513,7 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe
 
         for (;;)
         {
-            int opt = getopt_args(argc,argv, "n:urRdXK", &l) ;
+            int opt = getopt_args(argc,argv, OPTS_SVCTL, &l) ;
             if (opt == -1) break ;
             if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
             switch (opt)
-- 
GitLab