Synopsis is `[-t table -T command [address ...]]', yet tables without commands are silently ignored:
$ pfctl -t t pfctl: /dev/pf: Permission denied # pfctl -t t ; echo $? 0 Commands without tables are catched, but only after opening pf(4): $ pfctl -T show pfctl: /dev/pf: Permission denied # pfctl -T show pfctl [-deghNnPqrvz] [-a anchor] [-D macro=value] [-F modifier] [-f file] [-i interface] [-K key] [-k key] [-L statefile] [-o level] [-p device] [-S statefile] [-s modifier [-R id]] [-t table -T command [address ...]] [-V rdomain] [-x level] 1 By moving the inter-dependence check right after option parsing is done, we can bail out much earlier and drop the internal wrapper pfctl_command_tables() as unneeded indirection with now duplicate checks. With this diff both examples will show usage without doing anything as expected. There's no other user of this wrapper. Feedback? OK? Index: sbin/pfctl//pfctl.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl.c,v retrieving revision 1.361 diff -u -p -r1.361 pfctl.c --- sbin/pfctl//pfctl.c 27 Dec 2018 16:33:44 -0000 1.361 +++ sbin/pfctl//pfctl.c 1 Jan 2019 19:01:23 -0000 @@ -2482,6 +2482,9 @@ main(int argc, char *argv[]) } } + if (tblcmdopt == NULL ^ tableopt == NULL) + usage(); + if (tblcmdopt != NULL) { argc -= optind; argv += optind; @@ -2661,7 +2664,7 @@ main(int argc, char *argv[]) pfctl_kill_src_nodes(dev, ifaceopt, opts); if (tblcmdopt != NULL) { - error = pfctl_command_tables(argc, argv, tableopt, + error = pfctl_table(argc, argv, tableopt, tblcmdopt, rulesopt, anchorname, opts); rulesopt = NULL; } Index: sbin/pfctl//pfctl.h =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl.h,v retrieving revision 1.57 diff -u -p -r1.57 pfctl.h --- sbin/pfctl//pfctl.h 6 Sep 2018 15:07:33 -0000 1.57 +++ sbin/pfctl//pfctl.h 1 Jan 2019 19:14:36 -0000 @@ -77,7 +77,7 @@ int pfi_clr_istats(const char *, int *, void pfctl_print_title(char *); void pfctl_clear_tables(const char *, int); void pfctl_show_tables(const char *, int); -int pfctl_command_tables(int, char *[], char *, const char *, char *, +int pfctl_table(int, char *[], char *, const char *, char *, const char *, int); void warn_namespace_collision(const char *); void pfctl_show_ifaces(const char *, int); Index: sbin/pfctl//pfctl_table.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_table.c,v retrieving revision 1.78 diff -u -p -r1.78 pfctl_table.c --- sbin/pfctl//pfctl_table.c 15 Oct 2018 21:15:35 -0000 1.78 +++ sbin/pfctl//pfctl_table.c 1 Jan 2019 18:59:55 -0000 @@ -54,8 +54,6 @@ #include "pfctl.h" extern void usage(void); -static int pfctl_table(int, char *[], char *, const char *, char *, - const char *, int); static void print_table(struct pfr_table *, int, int); static void print_tstats(struct pfr_tstats *, int); static int load_addr(struct pfr_buffer *, int, char *[], char *, int, int); @@ -114,15 +112,6 @@ pfctl_show_tables(const char *anchor, in { if (pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts) == -1) exit(1); -} - -int -pfctl_command_tables(int argc, char *argv[], char *tname, - const char *command, char *file, const char *anchor, int opts) -{ - if (tname == NULL || command == NULL) - usage(); - return pfctl_table(argc, argv, tname, command, file, anchor, opts); } int