* [PATCH nft 0/4] Help and getopt improvements
@ 2020-03-05 14:48 Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 1/4] main: include '-d' in help Jeremy Sowden
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Jeremy Sowden @ 2020-03-05 14:48 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Devel
I spotted a couple more mistakes in the help. The first two patches fix
them. The last patch generates the getopt_long(3) optstring and
options, and the help from one data-structure in a bid to keep them all
in sync.
Jeremy Sowden (4):
main: include '-d' in help.
main: include '--reversedns' in help.
main: interpolate default include path into help format-string.
main: use one data-structure to initialize getopt_long(3) arguments
and help.
src/main.c | 251 +++++++++++++++++++++++++++++------------------------
1 file changed, 138 insertions(+), 113 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH nft 1/4] main: include '-d' in help.
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
@ 2020-03-05 14:48 ` Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 2/4] main: include '--reversedns' " Jeremy Sowden
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jeremy Sowden @ 2020-03-05 14:48 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Devel
The short option for '--debug' was omitted from the help.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
src/main.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/src/main.c b/src/main.c
index 81f30951c90f..3e37d600e38b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -140,28 +140,28 @@ static void show_help(const char *name)
"Usage: %s [ options ] [ cmds... ]\n"
"\n"
"Options:\n"
-" -h, --help Show this help\n"
-" -v, --version Show version information\n"
-" -V Show extended version information\n"
+" -h, --help Show this help\n"
+" -v, --version Show version information\n"
+" -V Show extended version information\n"
"\n"
-" -c, --check Check commands validity without actually applying the changes.\n"
-" -f, --file <filename> Read input from <filename>\n"
-" -i, --interactive Read input from interactive CLI\n"
+" -c, --check Check commands validity without actually applying the changes.\n"
+" -f, --file <filename> Read input from <filename>\n"
+" -i, --interactive Read input from interactive CLI\n"
"\n"
-" -j, --json Format output in JSON\n"
-" -n, --numeric Print fully numerical output.\n"
-" -s, --stateless Omit stateful information of ruleset.\n"
-" -t, --terse Omit contents of sets.\n"
-" -u, --guid Print UID/GID as defined in /etc/passwd and /etc/group.\n"
-" -N Translate IP addresses to names.\n"
-" -S, --service Translate ports to service names as described in /etc/services.\n"
-" -p, --numeric-protocol Print layer 4 protocols numerically.\n"
-" -y, --numeric-priority Print chain priority numerically.\n"
-" -T, --numeric-time Print time values numerically.\n"
-" -a, --handle Output rule handle.\n"
-" -e, --echo Echo what has been added, inserted or replaced.\n"
-" -I, --includepath <directory> Add <directory> to the paths searched for include files. Default is: %s\n"
-" --debug <level [,level...]> Specify debugging level (scanner, parser, eval, netlink, mnl, proto-ctx, segtree, all)\n"
+" -j, --json Format output in JSON\n"
+" -n, --numeric Print fully numerical output.\n"
+" -s, --stateless Omit stateful information of ruleset.\n"
+" -t, --terse Omit contents of sets.\n"
+" -u, --guid Print UID/GID as defined in /etc/passwd and /etc/group.\n"
+" -N Translate IP addresses to names.\n"
+" -S, --service Translate ports to service names as described in /etc/services.\n"
+" -p, --numeric-protocol Print layer 4 protocols numerically.\n"
+" -y, --numeric-priority Print chain priority numerically.\n"
+" -T, --numeric-time Print time values numerically.\n"
+" -a, --handle Output rule handle.\n"
+" -e, --echo Echo what has been added, inserted or replaced.\n"
+" -I, --includepath <directory> Add <directory> to the paths searched for include files. Default is: %s\n"
+" -d, --debug <level [,level...]> Specify debugging level (scanner, parser, eval, netlink, mnl, proto-ctx, segtree, all)\n"
"\n",
name, DEFAULT_INCLUDE_PATH);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 2/4] main: include '--reversedns' in help.
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 1/4] main: include '-d' in help Jeremy Sowden
@ 2020-03-05 14:48 ` Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 3/4] main: interpolate default include path into help format-string Jeremy Sowden
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Jeremy Sowden @ 2020-03-05 14:48 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Devel
The long option for '-N' was omitted from the help.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
src/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main.c b/src/main.c
index 3e37d600e38b..d00c7ec2b687 100644
--- a/src/main.c
+++ b/src/main.c
@@ -153,7 +153,7 @@ static void show_help(const char *name)
" -s, --stateless Omit stateful information of ruleset.\n"
" -t, --terse Omit contents of sets.\n"
" -u, --guid Print UID/GID as defined in /etc/passwd and /etc/group.\n"
-" -N Translate IP addresses to names.\n"
+" -N, --reversedns Translate IP addresses to names.\n"
" -S, --service Translate ports to service names as described in /etc/services.\n"
" -p, --numeric-protocol Print layer 4 protocols numerically.\n"
" -y, --numeric-priority Print chain priority numerically.\n"
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 3/4] main: interpolate default include path into help format-string.
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 1/4] main: include '-d' in help Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 2/4] main: include '--reversedns' " Jeremy Sowden
@ 2020-03-05 14:48 ` Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 4/4] main: use one data-structure to initialize getopt_long(3) arguments and help Jeremy Sowden
2020-03-10 13:45 ` [PATCH nft 0/4] Help and getopt improvements Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Jeremy Sowden @ 2020-03-05 14:48 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Devel
The default include path is a string literal defined as a preprocessor
macro by autoconf. We can just interpolate it.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
src/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main.c b/src/main.c
index d00c7ec2b687..4e9a2ed3bcec 100644
--- a/src/main.c
+++ b/src/main.c
@@ -160,10 +160,10 @@ static void show_help(const char *name)
" -T, --numeric-time Print time values numerically.\n"
" -a, --handle Output rule handle.\n"
" -e, --echo Echo what has been added, inserted or replaced.\n"
-" -I, --includepath <directory> Add <directory> to the paths searched for include files. Default is: %s\n"
+" -I, --includepath <directory> Add <directory> to the paths searched for include files. Default is: " DEFAULT_INCLUDE_PATH "\n"
" -d, --debug <level [,level...]> Specify debugging level (scanner, parser, eval, netlink, mnl, proto-ctx, segtree, all)\n"
"\n",
- name, DEFAULT_INCLUDE_PATH);
+ name);
}
static void show_version(void)
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 4/4] main: use one data-structure to initialize getopt_long(3) arguments and help.
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
` (2 preceding siblings ...)
2020-03-05 14:48 ` [PATCH nft 3/4] main: interpolate default include path into help format-string Jeremy Sowden
@ 2020-03-05 14:48 ` Jeremy Sowden
2020-03-10 13:45 ` [PATCH nft 0/4] Help and getopt improvements Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Jeremy Sowden @ 2020-03-05 14:48 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Devel
By generating the getopt_long(3) optstring and options, and the help
from one source, we reduce the chance that they may get out of sync.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
src/main.c | 251 +++++++++++++++++++++++++++++------------------------
1 file changed, 138 insertions(+), 113 deletions(-)
diff --git a/src/main.c b/src/main.c
index 4e9a2ed3bcec..1ee4d957a152 100644
--- a/src/main.c
+++ b/src/main.c
@@ -24,6 +24,19 @@
static struct nft_ctx *nft;
+/*
+ * These options are grouped separately in the help, so we give them named
+ * indices for use there.
+ */
+enum opt_indices {
+ IDX_HELP,
+ IDX_VERSION,
+ IDX_VERSION_LONG,
+ IDX_CHECK,
+ IDX_FILE,
+ IDX_INTERACTIVE,
+};
+
enum opt_vals {
OPT_HELP = 'h',
OPT_VERSION = 'v',
@@ -47,123 +60,133 @@ enum opt_vals {
OPT_TERSE = 't',
OPT_INVALID = '?',
};
-#define OPTSTRING "+hvVcf:iI:jnsNSd:aeuypTt"
-static const struct option options[] = {
- {
- .name = "help",
- .val = OPT_HELP,
- },
- {
- .name = "version",
- .val = OPT_VERSION,
- },
- {
- .name = "check",
- .val = OPT_CHECK,
- },
- {
- .name = "file",
- .val = OPT_FILE,
- .has_arg = 1,
- },
- {
- .name = "interactive",
- .val = OPT_INTERACTIVE,
- },
- {
- .name = "numeric",
- .val = OPT_NUMERIC,
- },
- {
- .name = "stateless",
- .val = OPT_STATELESS,
- },
- {
- .name = "reversedns",
- .val = OPT_IP2NAME,
- },
- {
- .name = "service",
- .val = OPT_SERVICE,
- },
- {
- .name = "includepath",
- .val = OPT_INCLUDEPATH,
- .has_arg = 1,
- },
- {
- .name = "debug",
- .val = OPT_DEBUG,
- .has_arg = 1,
- },
- {
- .name = "handle",
- .val = OPT_HANDLE_OUTPUT,
- },
- {
- .name = "echo",
- .val = OPT_ECHO,
- },
- {
- .name = "json",
- .val = OPT_JSON,
- },
- {
- .name = "guid",
- .val = OPT_GUID,
- },
- {
- .name = "numeric-priority",
- .val = OPT_NUMERIC_PRIO,
- },
- {
- .name = "numeric-protocol",
- .val = OPT_NUMERIC_PROTO,
- },
- {
- .name = "numeric-time",
- .val = OPT_NUMERIC_TIME,
- },
- {
- .name = "terse",
- .val = OPT_TERSE,
- },
- {
- .name = NULL
- }
+struct nft_opt {
+ const char *name;
+ enum opt_vals val;
+ const char *arg;
+ const char *help;
+};
+
+#define NFT_OPT(n, v, a, h) \
+ (struct nft_opt) { .name = n, .val = v, .arg = a, .help = h }
+
+static const struct nft_opt nft_options[] = {
+ NFT_OPT("help", OPT_HELP, NULL,
+ "Show this help"),
+ NFT_OPT("version", OPT_VERSION, NULL,
+ "Show version information"),
+ NFT_OPT(NULL, OPT_VERSION_LONG, NULL,
+ "Show extended version information"),
+ NFT_OPT("check", OPT_CHECK, NULL,
+ "Check commands validity without actually applying the changes."),
+ NFT_OPT("file", OPT_FILE, "<filename>",
+ "Read input from <filename>"),
+ NFT_OPT("interactive", OPT_INTERACTIVE, NULL,
+ "Read input from interactive CLI"),
+ NFT_OPT("numeric", OPT_NUMERIC, NULL,
+ "Print fully numerical output."),
+ NFT_OPT("stateless", OPT_STATELESS, NULL,
+ "Omit stateful information of ruleset."),
+ NFT_OPT("reversedns", OPT_IP2NAME, NULL,
+ "Translate IP addresses to names."),
+ NFT_OPT("service", OPT_SERVICE, NULL,
+ "Translate ports to service names as described in /etc/services."),
+ NFT_OPT("includepath", OPT_INCLUDEPATH, "<directory>",
+ "Add <directory> to the paths searched for include files. Default is: " DEFAULT_INCLUDE_PATH),
+ NFT_OPT("debug", OPT_DEBUG, "<level [,level...]>",
+ "Specify debugging level (scanner, parser, eval, netlink, mnl, proto-ctx, segtree, all)"),
+ NFT_OPT("handle", OPT_HANDLE_OUTPUT, NULL,
+ "Output rule handle."),
+ NFT_OPT("echo", OPT_ECHO, NULL,
+ "Echo what has been added, inserted or replaced."),
+ NFT_OPT("json", OPT_JSON, NULL,
+ "Format output in JSON"),
+ NFT_OPT("guid", OPT_GUID, NULL,
+ "Print UID/GID as defined in /etc/passwd and /etc/group."),
+ NFT_OPT("numeric-priority", OPT_NUMERIC_PRIO, NULL,
+ "Print chain priority numerically."),
+ NFT_OPT("numeric-protocol", OPT_NUMERIC_PROTO, NULL,
+ "Print layer 4 protocols numerically."),
+ NFT_OPT("numeric-time", OPT_NUMERIC_TIME, NULL,
+ "Print time values numerically."),
+ NFT_OPT("terse", OPT_TERSE, NULL,
+ "Omit contents of sets."),
};
+#define NR_NFT_OPTIONS (sizeof(nft_options) / sizeof(nft_options[0]))
+
+static const char *get_optstring(void)
+{
+ static char optstring[NR_NFT_OPTIONS + 2];
+
+ if (!optstring[0]) {
+ size_t i, j;
+
+ optstring[0] = '+';
+ for (i = 0, j = 1; i < NR_NFT_OPTIONS; i++)
+ j += sprintf(optstring + j, "%c%s",
+ nft_options[i].val,
+ nft_options[i].arg ? ":" : "");
+ }
+ return optstring;
+}
+
+static const struct option *get_options(void)
+{
+ static struct option options[NR_NFT_OPTIONS + 1];
+
+ if (!options[0].name) {
+ size_t i, j;
+
+ for (i = 0, j = 0; i < NR_NFT_OPTIONS; ++i) {
+ if (nft_options[i].name) {
+ options[j].name = nft_options[i].name;
+ options[j].val = nft_options[i].val;
+ options[j].has_arg = nft_options[i].arg != NULL;
+ j++;
+ }
+ }
+ }
+ return options;
+}
+
+static void print_option(const struct nft_opt *opt)
+{
+ char optbuf[33] = "";
+ int i;
+
+ i = snprintf(optbuf, sizeof(optbuf), " -%c", opt->val);
+ if (opt->name)
+ i += snprintf(optbuf + i, sizeof(optbuf) - i, ", %s", opt->name);
+ if (opt->arg)
+ i += snprintf(optbuf + i, sizeof(optbuf) - i, " %s", opt->arg);
+
+ printf("%-32s%s\n", optbuf, opt->help);
+}
+
static void show_help(const char *name)
{
- printf(
-"Usage: %s [ options ] [ cmds... ]\n"
-"\n"
-"Options:\n"
-" -h, --help Show this help\n"
-" -v, --version Show version information\n"
-" -V Show extended version information\n"
-"\n"
-" -c, --check Check commands validity without actually applying the changes.\n"
-" -f, --file <filename> Read input from <filename>\n"
-" -i, --interactive Read input from interactive CLI\n"
-"\n"
-" -j, --json Format output in JSON\n"
-" -n, --numeric Print fully numerical output.\n"
-" -s, --stateless Omit stateful information of ruleset.\n"
-" -t, --terse Omit contents of sets.\n"
-" -u, --guid Print UID/GID as defined in /etc/passwd and /etc/group.\n"
-" -N, --reversedns Translate IP addresses to names.\n"
-" -S, --service Translate ports to service names as described in /etc/services.\n"
-" -p, --numeric-protocol Print layer 4 protocols numerically.\n"
-" -y, --numeric-priority Print chain priority numerically.\n"
-" -T, --numeric-time Print time values numerically.\n"
-" -a, --handle Output rule handle.\n"
-" -e, --echo Echo what has been added, inserted or replaced.\n"
-" -I, --includepath <directory> Add <directory> to the paths searched for include files. Default is: " DEFAULT_INCLUDE_PATH "\n"
-" -d, --debug <level [,level...]> Specify debugging level (scanner, parser, eval, netlink, mnl, proto-ctx, segtree, all)\n"
-"\n",
- name);
+ printf("Usage: %s [ options ] [ cmds... ]\n"
+ "\n"
+ "Options:\n", name);
+
+ print_option(&nft_options[IDX_HELP]);
+ print_option(&nft_options[IDX_VERSION]);
+ print_option(&nft_options[IDX_VERSION_LONG]);
+
+ fputs("\n", stdout);
+
+ print_option(&nft_options[IDX_CHECK]);
+ print_option(&nft_options[IDX_FILE]);
+ print_option(&nft_options[IDX_INTERACTIVE]);
+
+ fputs("\n", stdout);
+
+ for (size_t i = IDX_INTERACTIVE + 1; i < NR_NFT_OPTIONS; ++i)
+ print_option(&nft_options[i]);
+
+ fputs("\n", stdout);
}
static void show_version(void)
@@ -288,6 +311,8 @@ static bool nft_options_check(int argc, char * const argv[])
int main(int argc, char * const *argv)
{
+ const struct option *options = get_options();
+ const char *optstring = get_optstring();
char *buf = NULL, *filename = NULL;
unsigned int output_flags = 0;
bool interactive = false;
@@ -301,7 +326,7 @@ int main(int argc, char * const *argv)
nft = nft_ctx_new(NFT_CTX_DEFAULT);
while (1) {
- val = getopt_long(argc, argv, OPTSTRING, options, NULL);
+ val = getopt_long(argc, argv, optstring, options, NULL);
if (val == -1)
break;
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH nft 0/4] Help and getopt improvements
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
` (3 preceding siblings ...)
2020-03-05 14:48 ` [PATCH nft 4/4] main: use one data-structure to initialize getopt_long(3) arguments and help Jeremy Sowden
@ 2020-03-10 13:45 ` Pablo Neira Ayuso
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2020-03-10 13:45 UTC (permalink / raw)
To: Jeremy Sowden; +Cc: Netfilter Devel
On Thu, Mar 05, 2020 at 02:48:01PM +0000, Jeremy Sowden wrote:
> I spotted a couple more mistakes in the help. The first two patches fix
> them. The last patch generates the getopt_long(3) optstring and
> options, and the help from one data-structure in a bid to keep them all
> in sync.
Series applied, thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-03-10 13:45 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-05 14:48 [PATCH nft 0/4] Help and getopt improvements Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 1/4] main: include '-d' in help Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 2/4] main: include '--reversedns' " Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 3/4] main: interpolate default include path into help format-string Jeremy Sowden
2020-03-05 14:48 ` [PATCH nft 4/4] main: use one data-structure to initialize getopt_long(3) arguments and help Jeremy Sowden
2020-03-10 13:45 ` [PATCH nft 0/4] Help and getopt improvements Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).